From bf99a1aaadd2e93a15528cbaee6494e57f8e682a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 16 Jan 2024 01:39:32 +0600 Subject: [PATCH 0001/1190] Dark mode theme only for Windows --- src/qt/CMakeLists.txt | 3 +- src/qt/qdarkstyle/dark/darkstyle.qrc | 216 +++ src/qt/qdarkstyle/dark/darkstyle.qss | 2207 ++++++++++++++++++++++++++ src/qt/qt_main.cpp | 22 + src/qt/qt_styleoverride.cpp | 11 + src/qt/qt_winrawinputfilter.cpp | 53 + 6 files changed, 2511 insertions(+), 1 deletion(-) create mode 100644 src/qt/qdarkstyle/dark/darkstyle.qrc create mode 100644 src/qt/qdarkstyle/dark/darkstyle.qss diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index fb96de1ea..cc5bd6269 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -181,6 +181,7 @@ add_library(ui STATIC qt_mediahistorymanager.hpp ../qt_resources.qrc + ./qdarkstyle/dark/darkstyle.qrc ) if(RTMIDI) @@ -198,7 +199,7 @@ if(WIN32) target_sources(plat PRIVATE win_joystick_rawinput.c) endif() target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) - target_link_libraries(86Box hid d3d9) + target_link_libraries(86Box hid d3d9 dwmapi) # CMake 3.22 messed this up for clang/clang++ # See https://gitlab.kitware.com/cmake/cmake/-/issues/22611 diff --git a/src/qt/qdarkstyle/dark/darkstyle.qrc b/src/qt/qdarkstyle/dark/darkstyle.qrc new file mode 100644 index 000000000..ce0d85be6 --- /dev/null +++ b/src/qt/qdarkstyle/dark/darkstyle.qrc @@ -0,0 +1,216 @@ + + + + rc/arrow_down.png + rc/arrow_down@2x.png + rc/arrow_down_disabled.png + rc/arrow_down_disabled@2x.png + rc/arrow_down_focus.png + rc/arrow_down_focus@2x.png + rc/arrow_down_pressed.png + rc/arrow_down_pressed@2x.png + rc/arrow_left.png + rc/arrow_left@2x.png + rc/arrow_left_disabled.png + rc/arrow_left_disabled@2x.png + rc/arrow_left_focus.png + rc/arrow_left_focus@2x.png + rc/arrow_left_pressed.png + rc/arrow_left_pressed@2x.png + rc/arrow_right.png + rc/arrow_right@2x.png + rc/arrow_right_disabled.png + rc/arrow_right_disabled@2x.png + rc/arrow_right_focus.png + rc/arrow_right_focus@2x.png + rc/arrow_right_pressed.png + rc/arrow_right_pressed@2x.png + rc/arrow_up.png + rc/arrow_up@2x.png + rc/arrow_up_disabled.png + rc/arrow_up_disabled@2x.png + rc/arrow_up_focus.png + rc/arrow_up_focus@2x.png + rc/arrow_up_pressed.png + rc/arrow_up_pressed@2x.png + rc/base_icon.png + rc/base_icon@2x.png + rc/base_icon_disabled.png + rc/base_icon_disabled@2x.png + rc/base_icon_focus.png + rc/base_icon_focus@2x.png + rc/base_icon_pressed.png + rc/base_icon_pressed@2x.png + rc/branch_closed.png + rc/branch_closed@2x.png + rc/branch_closed_disabled.png + rc/branch_closed_disabled@2x.png + rc/branch_closed_focus.png + rc/branch_closed_focus@2x.png + rc/branch_closed_pressed.png + rc/branch_closed_pressed@2x.png + rc/branch_end.png + rc/branch_end@2x.png + rc/branch_end_disabled.png + rc/branch_end_disabled@2x.png + rc/branch_end_focus.png + rc/branch_end_focus@2x.png + rc/branch_end_pressed.png + rc/branch_end_pressed@2x.png + rc/branch_line.png + rc/branch_line@2x.png + rc/branch_line_disabled.png + rc/branch_line_disabled@2x.png + rc/branch_line_focus.png + rc/branch_line_focus@2x.png + rc/branch_line_pressed.png + rc/branch_line_pressed@2x.png + rc/branch_more.png + rc/branch_more@2x.png + rc/branch_more_disabled.png + rc/branch_more_disabled@2x.png + rc/branch_more_focus.png + rc/branch_more_focus@2x.png + rc/branch_more_pressed.png + rc/branch_more_pressed@2x.png + rc/branch_open.png + rc/branch_open@2x.png + rc/branch_open_disabled.png + rc/branch_open_disabled@2x.png + rc/branch_open_focus.png + rc/branch_open_focus@2x.png + rc/branch_open_pressed.png + rc/branch_open_pressed@2x.png + rc/checkbox_checked.png + rc/checkbox_checked@2x.png + rc/checkbox_checked_disabled.png + rc/checkbox_checked_disabled@2x.png + rc/checkbox_checked_focus.png + rc/checkbox_checked_focus@2x.png + rc/checkbox_checked_pressed.png + rc/checkbox_checked_pressed@2x.png + rc/checkbox_indeterminate.png + rc/checkbox_indeterminate@2x.png + rc/checkbox_indeterminate_disabled.png + rc/checkbox_indeterminate_disabled@2x.png + rc/checkbox_indeterminate_focus.png + rc/checkbox_indeterminate_focus@2x.png + rc/checkbox_indeterminate_pressed.png + rc/checkbox_indeterminate_pressed@2x.png + rc/checkbox_unchecked.png + rc/checkbox_unchecked@2x.png + rc/checkbox_unchecked_disabled.png + rc/checkbox_unchecked_disabled@2x.png + rc/checkbox_unchecked_focus.png + rc/checkbox_unchecked_focus@2x.png + rc/checkbox_unchecked_pressed.png + rc/checkbox_unchecked_pressed@2x.png + rc/line_horizontal.png + rc/line_horizontal@2x.png + rc/line_horizontal_disabled.png + rc/line_horizontal_disabled@2x.png + rc/line_horizontal_focus.png + rc/line_horizontal_focus@2x.png + rc/line_horizontal_pressed.png + rc/line_horizontal_pressed@2x.png + rc/line_vertical.png + rc/line_vertical@2x.png + rc/line_vertical_disabled.png + rc/line_vertical_disabled@2x.png + rc/line_vertical_focus.png + rc/line_vertical_focus@2x.png + rc/line_vertical_pressed.png + rc/line_vertical_pressed@2x.png + rc/radio_checked.png + rc/radio_checked@2x.png + rc/radio_checked_disabled.png + rc/radio_checked_disabled@2x.png + rc/radio_checked_focus.png + rc/radio_checked_focus@2x.png + rc/radio_checked_pressed.png + rc/radio_checked_pressed@2x.png + rc/radio_unchecked.png + rc/radio_unchecked@2x.png + rc/radio_unchecked_disabled.png + rc/radio_unchecked_disabled@2x.png + rc/radio_unchecked_focus.png + rc/radio_unchecked_focus@2x.png + rc/radio_unchecked_pressed.png + rc/radio_unchecked_pressed@2x.png + rc/toolbar_move_horizontal.png + rc/toolbar_move_horizontal@2x.png + rc/toolbar_move_horizontal_disabled.png + rc/toolbar_move_horizontal_disabled@2x.png + rc/toolbar_move_horizontal_focus.png + rc/toolbar_move_horizontal_focus@2x.png + rc/toolbar_move_horizontal_pressed.png + rc/toolbar_move_horizontal_pressed@2x.png + rc/toolbar_move_vertical.png + rc/toolbar_move_vertical@2x.png + rc/toolbar_move_vertical_disabled.png + rc/toolbar_move_vertical_disabled@2x.png + rc/toolbar_move_vertical_focus.png + rc/toolbar_move_vertical_focus@2x.png + rc/toolbar_move_vertical_pressed.png + rc/toolbar_move_vertical_pressed@2x.png + rc/toolbar_separator_horizontal.png + rc/toolbar_separator_horizontal@2x.png + rc/toolbar_separator_horizontal_disabled.png + rc/toolbar_separator_horizontal_disabled@2x.png + rc/toolbar_separator_horizontal_focus.png + rc/toolbar_separator_horizontal_focus@2x.png + rc/toolbar_separator_horizontal_pressed.png + rc/toolbar_separator_horizontal_pressed@2x.png + rc/toolbar_separator_vertical.png + rc/toolbar_separator_vertical@2x.png + rc/toolbar_separator_vertical_disabled.png + rc/toolbar_separator_vertical_disabled@2x.png + rc/toolbar_separator_vertical_focus.png + rc/toolbar_separator_vertical_focus@2x.png + rc/toolbar_separator_vertical_pressed.png + rc/toolbar_separator_vertical_pressed@2x.png + rc/transparent.png + rc/transparent@2x.png + rc/transparent_disabled.png + rc/transparent_disabled@2x.png + rc/transparent_focus.png + rc/transparent_focus@2x.png + rc/transparent_pressed.png + rc/transparent_pressed@2x.png + rc/window_close.png + rc/window_close@2x.png + rc/window_close_disabled.png + rc/window_close_disabled@2x.png + rc/window_close_focus.png + rc/window_close_focus@2x.png + rc/window_close_pressed.png + rc/window_close_pressed@2x.png + rc/window_grip.png + rc/window_grip@2x.png + rc/window_grip_disabled.png + rc/window_grip_disabled@2x.png + rc/window_grip_focus.png + rc/window_grip_focus@2x.png + rc/window_grip_pressed.png + rc/window_grip_pressed@2x.png + rc/window_minimize.png + rc/window_minimize@2x.png + rc/window_minimize_disabled.png + rc/window_minimize_disabled@2x.png + rc/window_minimize_focus.png + rc/window_minimize_focus@2x.png + rc/window_minimize_pressed.png + rc/window_minimize_pressed@2x.png + rc/window_undock.png + rc/window_undock@2x.png + rc/window_undock_disabled.png + rc/window_undock_disabled@2x.png + rc/window_undock_focus.png + rc/window_undock_focus@2x.png + rc/window_undock_pressed.png + rc/window_undock_pressed@2x.png + + + darkstyle.qss + + diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss new file mode 100644 index 000000000..d785d6078 --- /dev/null +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -0,0 +1,2207 @@ +/* --------------------------------------------------------------------------- + + WARNING! File created programmatically. All changes made in this file will be lost! + + Created by the qtsass compiler v0.4.0 + + The definitions are in the "qdarkstyle.qss._styles.scss" module + +--------------------------------------------------------------------------- */ +/* Light Style - QDarkStyleSheet ------------------------------------------ */ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; +} + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: #19232D; + border: 0px solid #455364; + padding: 0px; + color: #DFE1E2; + selection-background-color: #346792; + selection-color: #DFE1E2; +} + +QWidget:disabled { + background-color: #19232D; + color: #788D9C; + selection-background-color: #26486B; + selection-color: #788D9C; +} + +QWidget::item:selected { + background-color: #346792; +} + +QWidget::item:hover:!selected { + background-color: #1A72BB; +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow::separator { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 2px; +} + +QMainWindow::separator:hover { + background-color: #60798B; + border: 0px solid #1A72BB; +} + +QMainWindow::separator:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url(":/qss_icons/dark/rc/toolbar_separator_vertical.png"); +} + +QMainWindow::separator:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url(":/qss_icons/dark/rc/toolbar_separator_horizontal.png"); +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: #346792; + color: #DFE1E2; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: 1px solid #455364; + /* Fixes Spyder #9120, #9121 */ + background: #455364; + /* Fixes #205, white vertical borders separating items */ +} + +QStatusBar::item { + border: none; +} + +QStatusBar QToolTip { + background-color: #1A72BB; + border: 1px solid #19232D; + color: #19232D; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Reducing transparency to read better */ + opacity: 230; +} + +QStatusBar QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: #19232D; + color: #DFE1E2; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; +} + +QCheckBox:focus { + border: none; +} + +QCheckBox QWidget:disabled { + background-color: #19232D; + color: #788D9C; +} + +QCheckBox::indicator { + margin-left: 2px; + height: 14px; + width: 14px; +} + +QCheckBox::indicator:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QCheckBox::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QCheckBox::indicator:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QCheckBox::indicator:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +QCheckBox::indicator:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QCheckBox::indicator:indeterminate:disabled { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_disabled.png"); +} + +QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: 1px solid #455364; + border-radius: 4px; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; +} + +QGroupBox::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: #19232D; + color: #DFE1E2; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; +} + +QRadioButton:focus { + border: none; +} + +QRadioButton:disabled { + background-color: #19232D; + color: #788D9C; + border: none; + outline: none; +} + +QRadioButton QWidget { + background-color: #19232D; + color: #DFE1E2; + spacing: 0px; + padding: 0px; + outline: none; + border: none; +} + +QRadioButton::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; +} + +QRadioButton::indicator:unchecked { + image: url(":/qss_icons/dark/rc/radio_unchecked.png"); +} + +QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_unchecked_focus.png"); +} + +QRadioButton::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/radio_unchecked_disabled.png"); +} + +QRadioButton::indicator:checked { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked.png"); +} + +QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_focus.png"); +} + +QRadioButton::indicator:checked:disabled { + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_disabled.png"); +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: #19232D; + padding: 2px; + border: 1px solid #455364; + color: #DFE1E2; + selection-background-color: #1A72BB; +} + +QMenuBar:focus { + border: 1px solid #346792; +} + +QMenuBar::item { + background: transparent; + padding: 4px; +} + +QMenuBar::item:selected { + padding: 4px; + background: transparent; + border: 0px solid #455364; + background-color: #1A72BB; +} + +QMenuBar::item:pressed { + padding: 4px; + border: 0px solid #455364; + background-color: #1A72BB; + color: #DFE1E2; + margin-bottom: 0px; + padding-bottom: 0px; +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid #455364; + color: #DFE1E2; + margin: 0px; + background-color: #37414F; + selection-background-color: #1A72BB; +} + +QMenu::separator { + height: 1px; + background-color: #60798B; + color: #DFE1E2; +} + +QMenu::item { + background-color: #37414F; + padding: 4px 24px 4px 28px; + /* Reserve space for selection border */ + border: 1px transparent #455364; +} + +QMenu::item:selected { + color: #DFE1E2; + background-color: #1A72BB; +} + +QMenu::item:pressed { + background-color: #1A72BB; +} + +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +QMenu::indicator { + padding-left: 8px; + width: 12px; + height: 12px; + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ +} + +QMenu::indicator:non-exclusive:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QMenu::indicator:non-exclusive:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QMenu::indicator:non-exclusive:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QMenu::indicator:non-exclusive:checked:hover, QMenu::indicator:non-exclusive:checked:focus, QMenu::indicator:non-exclusive:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QMenu::indicator:non-exclusive:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:disabled { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:focus, QMenu::indicator:non-exclusive:indeterminate:hover, QMenu::indicator:non-exclusive:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +QMenu::indicator:exclusive:unchecked { + image: url(":/qss_icons/dark/rc/radio_unchecked.png"); +} + +QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked:focus, QMenu::indicator:exclusive:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_unchecked_focus.png"); +} + +QMenu::indicator:exclusive:unchecked:disabled { + image: url(":/qss_icons/dark/rc/radio_unchecked_disabled.png"); +} + +QMenu::indicator:exclusive:checked { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked.png"); +} + +QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_focus.png"); +} + +QMenu::indicator:exclusive:checked:disabled { + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_disabled.png"); +} + +QMenu::right-arrow { + margin: 5px; + padding-left: 12px; + image: url(":/qss_icons/dark/rc/arrow_right.png"); + height: 12px; + width: 12px; +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: #19232D; + color: #DFE1E2; + border: 1px solid #455364; + border-radius: 4px; +} + +QAbstractItemView QLineEdit { + padding: 2px; +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: #DFE1E2; +} + +QAbstractScrollArea:disabled { + color: #788D9C; +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: #19232D; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: 1px solid #455364; + border-radius: 4px; + background-color: #19232D; +} + +QScrollBar:vertical { + background-color: #19232D; + width: 16px; + margin: 16px 2px 16px 2px; + border: 1px solid #455364; + border-radius: 4px; +} + +QScrollBar::handle:horizontal { + background-color: #60798B; + border: 1px solid #455364; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::handle:vertical { + background-color: #60798B; + border: 1px solid #455364; + min-height: 8px; + border-radius: 4px; +} + +QScrollBar::handle:vertical:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-height: 8px; +} + +QScrollBar::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::add-line:horizontal { + margin: 0px 0px 0px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_right_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { + border-image: url(":/qss_icons/dark/rc/arrow_right.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { + border-image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + margin: 0px 3px 0px 3px; + border-image: url(":/qss_icons/dark/rc/arrow_left_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { + border-image: url(":/qss_icons/dark/rc/arrow_left.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_up_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { + border-image: url(":/qss_icons/dark/rc/arrow_up.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal { + background: none; +} + +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: #19232D; + color: #DFE1E2; + border-radius: 4px; + border: 1px solid #455364; +} + +QTextEdit:focus { + border: 1px solid #1A72BB; +} + +QTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: #19232D; + color: #DFE1E2; + border-radius: 4px; + border: 1px solid #455364; +} + +QPlainTextEdit:focus { + border: 1px solid #1A72BB; +} + +QPlainTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url(":/qss_icons/dark/rc/window_grip.png"); +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: #19232D; + border-bottom: 1px solid #19232D; + padding: 1px; + font-weight: bold; + spacing: 2px; +} + +QToolBar:disabled { + /* Fixes #272 */ + background-color: #19232D; +} + +QToolBar::handle:horizontal { + width: 16px; + image: url(":/qss_icons/dark/rc/toolbar_move_horizontal.png"); +} + +QToolBar::handle:vertical { + height: 16px; + image: url(":/qss_icons/dark/rc/toolbar_move_vertical.png"); +} + +QToolBar::separator:horizontal { + width: 16px; + image: url(":/qss_icons/dark/rc/toolbar_separator_horizontal.png"); +} + +QToolBar::separator:vertical { + height: 16px; + image: url(":/qss_icons/dark/rc/toolbar_separator_vertical.png"); +} + +QToolButton#qt_toolbar_ext_button { + background: #19232D; + border: 0px; + color: #DFE1E2; + image: url(":/qss_icons/dark/rc/arrow_right.png"); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: 4px; + /* min-width: 5px; removed to fix 109 */ +} + +QAbstractSpinBox:up-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: 1px solid #455364; + border-bottom: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; +} + +QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { + image: url(":/qss_icons/dark/rc/arrow_up_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::up-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_up.png"); +} + +QAbstractSpinBox:down-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: 1px solid #455364; + border-top: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; +} + +QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::down-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QAbstractSpinBox:hover { + border: 1px solid #346792; + color: #DFE1E2; +} + +QAbstractSpinBox:focus { + border: 1px solid #1A72BB; +} + +QAbstractSpinBox:selected { + background: #346792; + color: #455364; +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: #19232D; + border: 0px solid #455364; + padding: 2px; + margin: 0px; + color: #DFE1E2; +} + +QLabel:disabled { + background-color: #19232D; + border: 0px solid #455364; + color: #788D9C; +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; +} + +QTextBrowser:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #788D9C; + border-radius: 4px; +} + +QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { + border: 1px solid #455364; +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; +} + +QGraphicsView:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #788D9C; + border-radius: 4px; +} + +QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { + border: 1px solid #455364; +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: 1px solid #455364; + border-radius: 4px; +} + +QCalendarWidget:disabled { + background-color: #19232D; + color: #788D9C; +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: #19232D; + color: #DFE1E2; +} + +QLCDNumber:disabled { + background-color: #19232D; + color: #788D9C; +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; + text-align: center; +} + +QProgressBar:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #788D9C; + border-radius: 4px; + text-align: center; +} + +QProgressBar::chunk { + background-color: #346792; + color: #19232D; + border-radius: 4px; +} + +QProgressBar::chunk:disabled { + background-color: #26486B; + color: #788D9C; + border-radius: 4px; +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: #455364; + color: #DFE1E2; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; +} + +QPushButton:disabled { + background-color: #455364; + color: #788D9C; + border-radius: 4px; + padding: 2px; +} + +QPushButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:disabled { + background-color: #60798B; + color: #788D9C; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:selected { + background: #60798B; +} + +QPushButton:hover { + background-color: #54687A; + color: #DFE1E2; +} + +QPushButton:pressed { + background-color: #60798B; +} + +QPushButton:selected { + background: #60798B; + color: #DFE1E2; +} + +QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} + +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: #19232D; + color: #DFE1E2; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; + /* The subcontrols below are used only in the DelayedPopup mode */ + /* The subcontrols below are used only in the MenuButtonPopup mode */ + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ +} + +QToolButton:disabled { + background-color: #19232D; + color: #788D9C; + border-radius: 4px; + padding: 2px; +} + +QToolButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:disabled { + background-color: #60798B; + color: #788D9C; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:hover { + background-color: #54687A; + color: #DFE1E2; +} + +QToolButton:checked:pressed { + background-color: #60798B; +} + +QToolButton:checked:selected { + background: #60798B; + color: #DFE1E2; +} + +QToolButton:hover { + background-color: #54687A; + color: #DFE1E2; +} + +QToolButton:pressed { + background-color: #60798B; +} + +QToolButton:selected { + background: #60798B; + color: #DFE1E2; +} + +QToolButton[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; +} + +QToolButton[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; +} + +QToolButton[popupMode="1"]::menu-button { + border: none; +} + +QToolButton[popupMode="1"]::menu-button:hover { + border: none; + border-left: 1px solid #455364; + border-radius: 0; +} + +QToolButton[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; +} + +QToolButton::menu-button { + padding: 2px; + border-radius: 4px; + width: 12px; + border: none; + outline: none; +} + +QToolButton::menu-button:hover { + border: 1px solid #346792; +} + +QToolButton::menu-button:checked:hover { + border: 1px solid #346792; +} + +QToolButton::menu-indicator { + image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ +} + +QToolButton::menu-arrow { + image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 8px; + width: 8px; +} + +QToolButton::menu-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_down_focus.png"); +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; + padding: 0px; + margin: 0px; +} + +QCommandLinkButton:disabled { + background-color: transparent; + color: #788D9C; +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: 1px solid #455364; + border-radius: 4px; + selection-background-color: #346792; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + /* Fixes #103, #111 */ + min-height: 1.5em; + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + /* Needed to remove indicator - fix #132 */ +} + +QComboBox QAbstractItemView { + border: 1px solid #455364; + border-radius: 0; + background-color: #19232D; + selection-background-color: #346792; +} + +QComboBox QAbstractItemView:hover { + background-color: #19232D; + color: #DFE1E2; +} + +QComboBox QAbstractItemView:selected { + background: #346792; + color: #455364; +} + +QComboBox QAbstractItemView:alternate { + background: #19232D; +} + +QComboBox:disabled { + background-color: #19232D; + color: #788D9C; +} + +QComboBox:hover { + border: 1px solid #346792; +} + +QComboBox:focus { + border: 1px solid #1A72BB; +} + +QComboBox:on { + selection-background-color: #346792; +} + +QComboBox::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + /* Needed to remove indicator - fix #132 */ +} + +QComboBox::indicator:alternate { + background: #19232D; +} + +QComboBox::item { + /* Remove to fix #282, #285 and MR #288*/ + /*&:checked { + font-weight: bold; + } + + &:selected { + border: 0px solid transparent; + } + */ +} + +QComboBox::item:alternate { + background: #19232D; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QComboBox::down-arrow { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider:disabled { + background: #19232D; +} + +QSlider:focus { + border: none; +} + +QSlider::groove:horizontal { + background: #455364; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::groove:vertical { + background: #455364; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical { + background: #346792; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical :disabled { + background: #26486B; +} + +QSlider::sub-page:horizontal { + background: #346792; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::sub-page:horizontal:disabled { + background: #26486B; +} + +QSlider::handle:horizontal { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QSlider::handle:vertical { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: 4px; +} + +QSlider::handle:vertical:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: #19232D; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + color: #DFE1E2; +} + +QLineEdit:disabled { + background-color: #19232D; + color: #788D9C; +} + +QLineEdit:hover { + border: 1px solid #346792; + color: #DFE1E2; +} + +QLineEdit:focus { + border: 1px solid #1A72BB; +} + +QLineEdit:selected { + background-color: #346792; + color: #455364; +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: #455364; +} + +QTabWidget QWidget { + /* Fixes #189 */ + border-radius: 4px; +} + +QTabWidget::pane { + border: 1px solid #455364; + border-radius: 4px; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; +} + +QTabWidget::pane:selected { + background-color: #455364; + border: 1px solid #346792; +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar, QDockWidget QTabBar { + qproperty-drawBase: 0; + border-radius: 4px; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ +} + +QTabBar::close-button, QDockWidget QTabBar::close-button { + border: 0; + margin: 0; + padding: 4px; + image: url(":/qss_icons/dark/rc/window_close.png"); +} + +QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { + image: url(":/qss_icons/dark/rc/window_close_focus.png"); +} + +QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { + image: url(":/qss_icons/dark/rc/window_close_pressed.png"); +} + +QTabBar::tab, QDockWidget QTabBar::tab { + /* !selected and disabled ----------------------------------------- */ + /* selected ------------------------------------------------------- */ +} + +QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { + border-bottom: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { + border-top: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { + border-right: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { + border-left: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { + border-bottom: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { + border-top: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { + border-right: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { + border-left: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { + border-bottom: 2px solid #19232D; + margin-top: 2px; +} + +QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { + border-top: 2px solid #19232D; + margin-bottom: 2px; +} + +QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { + border-left: 2px solid #19232D; + margin-right: 2px; +} + +QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { + border-right: 2px solid #19232D; + margin-left: 2px; +} + +QTabBar::tab:top, QDockWidget QTabBar::tab:top { + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid #455364; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { + background-color: #54687A; + border-bottom: 3px solid #259AE9; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { + border: 1px solid #1A72BB; + border-bottom: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { + border-top: 3px solid #455364; + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + min-width: 5px; +} + +QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { + background-color: #54687A; + border-top: 3px solid #259AE9; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { + border: 1px solid #1A72BB; + border-top: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:left, QDockWidget QTabBar::tab:left { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { + background-color: #54687A; + border-right: 3px solid #259AE9; +} + +QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { + border: 1px solid #1A72BB; + border-right: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-right: 0px; + padding-right: -1px; +} + +QTabBar::tab:right, QDockWidget QTabBar::tab:right { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { + background-color: #54687A; + border-left: 3px solid #259AE9; +} + +QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { + border: 1px solid #1A72BB; + border-left: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-left: 0px; + padding-left: 0px; +} + +QTabBar QToolButton, QDockWidget QTabBar QToolButton { + /* Fixes #136 */ + background-color: #455364; + height: 12px; + width: 12px; +} + +QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { + background-color: #455364; +} + +QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { + border: 1px solid #346792; +} + +QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { + image: url(":/qss_icons/dark/rc/arrow_left.png"); +} + +QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { + image: url(":/qss_icons/dark/rc/arrow_left_disabled.png"); +} + +QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { + image: url(":/qss_icons/dark/rc/arrow_right.png"); +} + +QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { + image: url(":/qss_icons/dark/rc/arrow_right_disabled.png"); +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: 1px solid #455364; + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + titlebar-close-icon: url(":/qss_icons/dark/rc/transparent.png"); + titlebar-normal-icon: url(":/qss_icons/dark/rc/transparent.png"); +} + +QDockWidget::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: #455364; +} + +QDockWidget::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/dark/rc/window_close.png"); +} + +QDockWidget::close-button:hover { + image: url(":/qss_icons/dark/rc/window_close_focus.png"); +} + +QDockWidget::close-button:pressed { + image: url(":/qss_icons/dark/rc/window_close_pressed.png"); +} + +QDockWidget::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/dark/rc/window_undock.png"); +} + +QDockWidget::float-button:hover { + image: url(":/qss_icons/dark/rc/window_undock_focus.png"); +} + +QDockWidget::float-button:pressed { + image: url(":/qss_icons/dark/rc/window_undock_pressed.png"); +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/qss_icons/dark/rc/transparent.png"); +} + +QTreeView:branch:has-siblings:!adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_line.png") 0; +} + +QTreeView:branch:has-siblings:adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_more.png") 0; +} + +QTreeView:branch:!has-children:!has-siblings:adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_end.png") 0; +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/dark/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/dark/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/qss_icons/dark/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/qss_icons/dark/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked, +QListView::indicator:checked, +QTableView::indicator:checked, +QColumnView::indicator:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed, +QListView::indicator:checked:hover, +QListView::indicator:checked:focus, +QListView::indicator:checked:pressed, +QTableView::indicator:checked:hover, +QTableView::indicator:checked:focus, +QTableView::indicator:checked:pressed, +QColumnView::indicator:checked:hover, +QColumnView::indicator:checked:focus, +QColumnView::indicator:checked:pressed { + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked, +QListView::indicator:unchecked, +QTableView::indicator:unchecked, +QColumnView::indicator:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, +QListView::indicator:unchecked:hover, +QListView::indicator:unchecked:focus, +QListView::indicator:unchecked:pressed, +QTableView::indicator:unchecked:hover, +QTableView::indicator:unchecked:focus, +QTableView::indicator:unchecked:pressed, +QColumnView::indicator:unchecked:hover, +QColumnView::indicator:unchecked:focus, +QColumnView::indicator:unchecked:pressed { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QTreeView::indicator:indeterminate, +QListView::indicator:indeterminate, +QTableView::indicator:indeterminate, +QColumnView::indicator:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, +QListView::indicator:indeterminate:hover, +QListView::indicator:indeterminate:focus, +QListView::indicator:indeterminate:pressed, +QTableView::indicator:indeterminate:hover, +QTableView::indicator:indeterminate:focus, +QTableView::indicator:indeterminate:pressed, +QColumnView::indicator:indeterminate:hover, +QColumnView::indicator:indeterminate:focus, +QColumnView::indicator:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + gridline-color: #455364; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #19232D; + color: #788D9C; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #346792; + color: #455364; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #1A72BB; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #346792; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #346792; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #DFE1E2; + background-color: #37414F; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #DFE1E2; + background-color: #37414F; +} + +QTableCornerButton::section { + background-color: #19232D; + border: 1px transparent #455364; + border-radius: 0px; +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: #455364; + border: 0px transparent #455364; + padding: 0; + margin: 0; + border-radius: 0; +} + +QHeaderView:disabled { + background-color: #455364; + border: 1px transparent #455364; +} + +QHeaderView::section { + background-color: #455364; + color: #DFE1E2; + border-radius: 0; + text-align: left; + font-size: 13px; +} + +QHeaderView::section::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: 1px solid #19232D; +} + +QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { + border-left: 1px solid #455364; +} + +QHeaderView::section::horizontal:disabled { + color: #788D9C; +} + +QHeaderView::section::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: 1px solid #19232D; +} + +QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { + border-top: 1px solid #455364; +} + +QHeaderView::section::vertical:disabled { + color: #788D9C; +} + +QHeaderView::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QHeaderView::up-arrow { + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/dark/rc/arrow_up.png"); +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: 1px solid #455364; +} + +QToolBox:selected { + padding: 0px; + border: 2px solid #346792; +} + +QToolBox::tab { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QToolBox::tab:disabled { + color: #788D9C; +} + +QToolBox::tab:selected { + background-color: #60798B; + border-bottom: 2px solid #346792; +} + +QToolBox::tab:selected:disabled { + background-color: #455364; + border-bottom: 2px solid #26486B; +} + +QToolBox::tab:!selected { + background-color: #455364; + border-bottom: 2px solid #455364; +} + +QToolBox::tab:!selected:disabled { + background-color: #19232D; +} + +QToolBox::tab:hover { + border-color: #1A72BB; + border-bottom: 2px solid #1A72BB; +} + +QToolBox QScrollArea { + padding: 0px; + border: 0px; + background-color: #19232D; +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ +/* (dot) .QFrame fix #141, #126, #123 */ +.QFrame { + border-radius: 4px; + border: 1px solid #455364; + /* No frame */ + /* HLine */ + /* HLine */ +} + +.QFrame[frameShape="0"] { + border-radius: 4px; + border: 1px transparent #455364; +} + +.QFrame[frameShape="4"] { + max-height: 2px; + border: none; + background-color: #455364; +} + +.QFrame[frameShape="5"] { + max-width: 2px; + border: none; + background-color: #455364; +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: #455364; + spacing: 0px; + padding: 0px; + margin: 0px; +} + +QSplitter::handle { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 1px; + margin: 0px; +} + +QSplitter::handle:hover { + background-color: #9DA9B5; +} + +QSplitter::handle:horizontal { + width: 5px; + image: url(":/qss_icons/dark/rc/line_vertical.png"); +} + +QSplitter::handle:vertical { + height: 5px; + image: url(":/qss_icons/dark/rc/line_horizontal.png"); +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: #346792; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; +} + +QDateEdit:on, QDateTimeEdit:on { + selection-background-color: #346792; +} + +QDateEdit::drop-down, QDateTimeEdit::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QDateEdit::down-arrow, QDateTimeEdit::down-arrow { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { + background-color: #19232D; + border-radius: 4px; + border: 1px solid #455364; + selection-background-color: #346792; +} + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView:hover { + border: 1px solid #346792; + color: #DFE1E2; +} + +QAbstractView:selected { + background: #346792; + color: #455364; +} + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 4d02e2601..afe3a9469 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #ifdef QT_STATIC /* Static builds need plugin imports */ @@ -154,6 +156,10 @@ main_thread_fn() static std::thread *main_thread; +#ifdef Q_OS_WINDOWS +extern bool windows_is_light_theme(); +#endif + int main(int argc, char *argv[]) { @@ -168,6 +174,22 @@ main(int argc, char *argv[]) QApplication app(argc, argv); QLocale::setDefault(QLocale::C); +#ifdef Q_OS_WINDOWS + Q_INIT_RESOURCE(darkstyle); + + if (!windows_is_light_theme()) { + QFile f(":qdarkstyle/dark/darkstyle.qss"); + + if (!f.exists()) { + printf("Unable to set stylesheet, file not found\n"); + } else { + f.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&f); + qApp->setStyleSheet(ts.readAll()); + } + } +#endif + qt_set_sequence_auto_mnemonic(false); Q_INIT_RESOURCE(qt_resources); Q_INIT_RESOURCE(qt_translations); diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index 7ec5a341c..fab111172 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -19,6 +19,13 @@ #include #include +#ifdef Q_OS_WINDOWS +#include +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif +#endif + int StyleOverride::styleHint( StyleHint hint, @@ -48,6 +55,10 @@ StyleOverride::polish(QWidget *widget) widget->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, true); } widget->setWindowFlag(Qt::WindowContextHelpButtonHint, false); +#ifdef Q_OS_WINDOWS + BOOL DarkMode = TRUE; + DwmSetWindowAttribute((HWND)widget->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); +#endif } if (qobject_cast(widget)) { diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 3ca091ae6..57fd44126 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -34,10 +34,17 @@ #include "qt_winrawinputfilter.hpp" #include +#include +#include +#include #include #include +#include +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif #include <86box/keyboard.h> #include <86box/mouse.h> @@ -49,6 +56,34 @@ #include "qt_rendererstack.hpp" +bool windows_is_light_theme() { + // 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 + auto buffer = std::vector(4); + auto cbData = static_cast(buffer.size() * sizeof(char)); + auto res = RegGetValueW( + HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", + L"AppsUseLightTheme", + RRF_RT_REG_DWORD, // expected value type + nullptr, + buffer.data(), + &cbData); + + if (res != ERROR_SUCCESS) { + return 1; + } + + // convert bytes written to our buffer to an int, assuming little-endian + auto i = int(buffer[3] << 24 | + buffer[2] << 16 | + buffer[1] << 8 | + buffer[0]); + + return i == 1; +} + extern "C" void win_joystick_handle(PRAWINPUT); std::unique_ptr WindowsRawInputFilter::Register(MainWindow *window) @@ -124,6 +159,24 @@ WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *mess } return true; + } else if (msg && msg->message == WM_SETTINGCHANGE && msg->lParam != NULL && wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0) { + if (!windows_is_light_theme()) { + QFile f(":qdarkstyle/dark/darkstyle.qss"); + + if (!f.exists()) { + printf("Unable to set stylesheet, file not found\n"); + } else { + f.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&f); + qApp->setStyleSheet(ts.readAll()); + } + // From Dolphin emulator code: + // TODO: When switching from light to dark, the window decorations remain light. Qt seems very + // convinced that it needs to change these in response to this message, so even if we set them + // to dark here, Qt sets them back to light afterwards. + } else { + qApp->setStyleSheet(""); + } } /* Stop processing of Alt-F4 */ From 8389021508d1b758a29c3f95497c9a810e2929d9 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 16 Jan 2024 01:51:39 +0600 Subject: [PATCH 0002/1190] Forgot icon files --- src/qt/qdarkstyle/dark/rc/.keep | 1 + src/qt/qdarkstyle/dark/rc/arrow_down.png | Bin 0 -> 518 bytes src/qt/qdarkstyle/dark/rc/arrow_down@2x.png | Bin 0 -> 1023 bytes .../qdarkstyle/dark/rc/arrow_down_disabled.png | Bin 0 -> 546 bytes .../dark/rc/arrow_down_disabled@2x.png | Bin 0 -> 1068 bytes src/qt/qdarkstyle/dark/rc/arrow_down_focus.png | Bin 0 -> 523 bytes .../qdarkstyle/dark/rc/arrow_down_focus@2x.png | Bin 0 -> 992 bytes src/qt/qdarkstyle/dark/rc/arrow_down_pressed.png | Bin 0 -> 567 bytes .../qdarkstyle/dark/rc/arrow_down_pressed@2x.png | Bin 0 -> 1070 bytes src/qt/qdarkstyle/dark/rc/arrow_left.png | Bin 0 -> 555 bytes src/qt/qdarkstyle/dark/rc/arrow_left@2x.png | Bin 0 -> 1127 bytes .../qdarkstyle/dark/rc/arrow_left_disabled.png | Bin 0 -> 557 bytes .../dark/rc/arrow_left_disabled@2x.png | Bin 0 -> 1141 bytes src/qt/qdarkstyle/dark/rc/arrow_left_focus.png | Bin 0 -> 551 bytes .../qdarkstyle/dark/rc/arrow_left_focus@2x.png | Bin 0 -> 1119 bytes src/qt/qdarkstyle/dark/rc/arrow_left_pressed.png | Bin 0 -> 574 bytes .../qdarkstyle/dark/rc/arrow_left_pressed@2x.png | Bin 0 -> 1155 bytes src/qt/qdarkstyle/dark/rc/arrow_right.png | Bin 0 -> 532 bytes src/qt/qdarkstyle/dark/rc/arrow_right@2x.png | Bin 0 -> 1131 bytes .../qdarkstyle/dark/rc/arrow_right_disabled.png | Bin 0 -> 545 bytes .../dark/rc/arrow_right_disabled@2x.png | Bin 0 -> 1143 bytes src/qt/qdarkstyle/dark/rc/arrow_right_focus.png | Bin 0 -> 541 bytes .../qdarkstyle/dark/rc/arrow_right_focus@2x.png | Bin 0 -> 1112 bytes .../qdarkstyle/dark/rc/arrow_right_pressed.png | Bin 0 -> 574 bytes .../dark/rc/arrow_right_pressed@2x.png | Bin 0 -> 1162 bytes src/qt/qdarkstyle/dark/rc/arrow_up.png | Bin 0 -> 517 bytes src/qt/qdarkstyle/dark/rc/arrow_up@2x.png | Bin 0 -> 999 bytes src/qt/qdarkstyle/dark/rc/arrow_up_disabled.png | Bin 0 -> 549 bytes .../qdarkstyle/dark/rc/arrow_up_disabled@2x.png | Bin 0 -> 1074 bytes src/qt/qdarkstyle/dark/rc/arrow_up_focus.png | Bin 0 -> 532 bytes src/qt/qdarkstyle/dark/rc/arrow_up_focus@2x.png | Bin 0 -> 990 bytes src/qt/qdarkstyle/dark/rc/arrow_up_pressed.png | Bin 0 -> 554 bytes .../qdarkstyle/dark/rc/arrow_up_pressed@2x.png | Bin 0 -> 1053 bytes src/qt/qdarkstyle/dark/rc/base_icon.png | Bin 0 -> 1256 bytes src/qt/qdarkstyle/dark/rc/base_icon@2x.png | Bin 0 -> 3286 bytes src/qt/qdarkstyle/dark/rc/base_icon_disabled.png | Bin 0 -> 1256 bytes .../qdarkstyle/dark/rc/base_icon_disabled@2x.png | Bin 0 -> 3286 bytes src/qt/qdarkstyle/dark/rc/base_icon_focus.png | Bin 0 -> 1256 bytes src/qt/qdarkstyle/dark/rc/base_icon_focus@2x.png | Bin 0 -> 3286 bytes src/qt/qdarkstyle/dark/rc/base_icon_pressed.png | Bin 0 -> 1256 bytes .../qdarkstyle/dark/rc/base_icon_pressed@2x.png | Bin 0 -> 3286 bytes src/qt/qdarkstyle/dark/rc/branch_closed.png | Bin 0 -> 394 bytes src/qt/qdarkstyle/dark/rc/branch_closed@2x.png | Bin 0 -> 837 bytes .../dark/rc/branch_closed_disabled.png | Bin 0 -> 426 bytes .../dark/rc/branch_closed_disabled@2x.png | Bin 0 -> 862 bytes .../qdarkstyle/dark/rc/branch_closed_focus.png | Bin 0 -> 395 bytes .../dark/rc/branch_closed_focus@2x.png | Bin 0 -> 810 bytes .../qdarkstyle/dark/rc/branch_closed_pressed.png | Bin 0 -> 415 bytes .../dark/rc/branch_closed_pressed@2x.png | Bin 0 -> 867 bytes src/qt/qdarkstyle/dark/rc/branch_end.png | Bin 0 -> 147 bytes src/qt/qdarkstyle/dark/rc/branch_end@2x.png | Bin 0 -> 203 bytes .../qdarkstyle/dark/rc/branch_end_disabled.png | Bin 0 -> 152 bytes .../dark/rc/branch_end_disabled@2x.png | Bin 0 -> 205 bytes src/qt/qdarkstyle/dark/rc/branch_end_focus.png | Bin 0 -> 149 bytes .../qdarkstyle/dark/rc/branch_end_focus@2x.png | Bin 0 -> 203 bytes src/qt/qdarkstyle/dark/rc/branch_end_pressed.png | Bin 0 -> 152 bytes .../qdarkstyle/dark/rc/branch_end_pressed@2x.png | Bin 0 -> 204 bytes src/qt/qdarkstyle/dark/rc/branch_line.png | Bin 0 -> 132 bytes src/qt/qdarkstyle/dark/rc/branch_line@2x.png | Bin 0 -> 238 bytes .../qdarkstyle/dark/rc/branch_line_disabled.png | Bin 0 -> 135 bytes .../dark/rc/branch_line_disabled@2x.png | Bin 0 -> 240 bytes src/qt/qdarkstyle/dark/rc/branch_line_focus.png | Bin 0 -> 134 bytes .../qdarkstyle/dark/rc/branch_line_focus@2x.png | Bin 0 -> 238 bytes .../qdarkstyle/dark/rc/branch_line_pressed.png | Bin 0 -> 135 bytes .../dark/rc/branch_line_pressed@2x.png | Bin 0 -> 239 bytes src/qt/qdarkstyle/dark/rc/branch_more.png | Bin 0 -> 162 bytes src/qt/qdarkstyle/dark/rc/branch_more@2x.png | Bin 0 -> 260 bytes .../qdarkstyle/dark/rc/branch_more_disabled.png | Bin 0 -> 167 bytes .../dark/rc/branch_more_disabled@2x.png | Bin 0 -> 263 bytes src/qt/qdarkstyle/dark/rc/branch_more_focus.png | Bin 0 -> 164 bytes .../qdarkstyle/dark/rc/branch_more_focus@2x.png | Bin 0 -> 260 bytes .../qdarkstyle/dark/rc/branch_more_pressed.png | Bin 0 -> 161 bytes .../dark/rc/branch_more_pressed@2x.png | Bin 0 -> 262 bytes src/qt/qdarkstyle/dark/rc/branch_open.png | Bin 0 -> 407 bytes src/qt/qdarkstyle/dark/rc/branch_open@2x.png | Bin 0 -> 803 bytes .../qdarkstyle/dark/rc/branch_open_disabled.png | Bin 0 -> 422 bytes .../dark/rc/branch_open_disabled@2x.png | Bin 0 -> 872 bytes src/qt/qdarkstyle/dark/rc/branch_open_focus.png | Bin 0 -> 396 bytes .../qdarkstyle/dark/rc/branch_open_focus@2x.png | Bin 0 -> 791 bytes .../qdarkstyle/dark/rc/branch_open_pressed.png | Bin 0 -> 421 bytes .../dark/rc/branch_open_pressed@2x.png | Bin 0 -> 860 bytes src/qt/qdarkstyle/dark/rc/checkbox_checked.png | Bin 0 -> 650 bytes .../qdarkstyle/dark/rc/checkbox_checked@2x.png | Bin 0 -> 1238 bytes .../dark/rc/checkbox_checked_disabled.png | Bin 0 -> 731 bytes .../dark/rc/checkbox_checked_disabled@2x.png | Bin 0 -> 1334 bytes .../dark/rc/checkbox_checked_focus.png | Bin 0 -> 655 bytes .../dark/rc/checkbox_checked_focus@2x.png | Bin 0 -> 1269 bytes .../dark/rc/checkbox_checked_pressed.png | Bin 0 -> 704 bytes .../dark/rc/checkbox_checked_pressed@2x.png | Bin 0 -> 1319 bytes .../dark/rc/checkbox_indeterminate.png | Bin 0 -> 481 bytes .../dark/rc/checkbox_indeterminate@2x.png | Bin 0 -> 919 bytes .../dark/rc/checkbox_indeterminate_disabled.png | Bin 0 -> 545 bytes .../rc/checkbox_indeterminate_disabled@2x.png | Bin 0 -> 1003 bytes .../dark/rc/checkbox_indeterminate_focus.png | Bin 0 -> 466 bytes .../dark/rc/checkbox_indeterminate_focus@2x.png | Bin 0 -> 930 bytes .../dark/rc/checkbox_indeterminate_pressed.png | Bin 0 -> 518 bytes .../rc/checkbox_indeterminate_pressed@2x.png | Bin 0 -> 995 bytes src/qt/qdarkstyle/dark/rc/checkbox_unchecked.png | Bin 0 -> 385 bytes .../qdarkstyle/dark/rc/checkbox_unchecked@2x.png | Bin 0 -> 847 bytes .../dark/rc/checkbox_unchecked_disabled.png | Bin 0 -> 391 bytes .../dark/rc/checkbox_unchecked_disabled@2x.png | Bin 0 -> 868 bytes .../dark/rc/checkbox_unchecked_focus.png | Bin 0 -> 387 bytes .../dark/rc/checkbox_unchecked_focus@2x.png | Bin 0 -> 850 bytes .../dark/rc/checkbox_unchecked_pressed.png | Bin 0 -> 403 bytes .../dark/rc/checkbox_unchecked_pressed@2x.png | Bin 0 -> 862 bytes src/qt/qdarkstyle/dark/rc/line_horizontal.png | Bin 0 -> 120 bytes src/qt/qdarkstyle/dark/rc/line_horizontal@2x.png | Bin 0 -> 137 bytes .../dark/rc/line_horizontal_disabled.png | Bin 0 -> 121 bytes .../dark/rc/line_horizontal_disabled@2x.png | Bin 0 -> 139 bytes .../qdarkstyle/dark/rc/line_horizontal_focus.png | Bin 0 -> 119 bytes .../dark/rc/line_horizontal_focus@2x.png | Bin 0 -> 137 bytes .../dark/rc/line_horizontal_pressed.png | Bin 0 -> 120 bytes .../dark/rc/line_horizontal_pressed@2x.png | Bin 0 -> 138 bytes src/qt/qdarkstyle/dark/rc/line_vertical.png | Bin 0 -> 133 bytes src/qt/qdarkstyle/dark/rc/line_vertical@2x.png | Bin 0 -> 246 bytes .../dark/rc/line_vertical_disabled.png | Bin 0 -> 135 bytes .../dark/rc/line_vertical_disabled@2x.png | Bin 0 -> 249 bytes .../qdarkstyle/dark/rc/line_vertical_focus.png | Bin 0 -> 133 bytes .../dark/rc/line_vertical_focus@2x.png | Bin 0 -> 246 bytes .../qdarkstyle/dark/rc/line_vertical_pressed.png | Bin 0 -> 134 bytes .../dark/rc/line_vertical_pressed@2x.png | Bin 0 -> 248 bytes src/qt/qdarkstyle/dark/rc/radio_checked.png | Bin 0 -> 1260 bytes src/qt/qdarkstyle/dark/rc/radio_checked@2x.png | Bin 0 -> 2718 bytes .../dark/rc/radio_checked_disabled.png | Bin 0 -> 1336 bytes .../dark/rc/radio_checked_disabled@2x.png | Bin 0 -> 2871 bytes .../qdarkstyle/dark/rc/radio_checked_focus.png | Bin 0 -> 1232 bytes .../dark/rc/radio_checked_focus@2x.png | Bin 0 -> 2656 bytes .../qdarkstyle/dark/rc/radio_checked_pressed.png | Bin 0 -> 1288 bytes .../dark/rc/radio_checked_pressed@2x.png | Bin 0 -> 2804 bytes src/qt/qdarkstyle/dark/rc/radio_unchecked.png | Bin 0 -> 1007 bytes src/qt/qdarkstyle/dark/rc/radio_unchecked@2x.png | Bin 0 -> 2167 bytes .../dark/rc/radio_unchecked_disabled.png | Bin 0 -> 1045 bytes .../dark/rc/radio_unchecked_disabled@2x.png | Bin 0 -> 2277 bytes .../qdarkstyle/dark/rc/radio_unchecked_focus.png | Bin 0 -> 979 bytes .../dark/rc/radio_unchecked_focus@2x.png | Bin 0 -> 2127 bytes .../dark/rc/radio_unchecked_pressed.png | Bin 0 -> 1027 bytes .../dark/rc/radio_unchecked_pressed@2x.png | Bin 0 -> 2263 bytes .../dark/rc/toolbar_move_horizontal.png | Bin 0 -> 154 bytes .../dark/rc/toolbar_move_horizontal@2x.png | Bin 0 -> 307 bytes .../dark/rc/toolbar_move_horizontal_disabled.png | Bin 0 -> 155 bytes .../rc/toolbar_move_horizontal_disabled@2x.png | Bin 0 -> 309 bytes .../dark/rc/toolbar_move_horizontal_focus.png | Bin 0 -> 154 bytes .../dark/rc/toolbar_move_horizontal_focus@2x.png | Bin 0 -> 305 bytes .../dark/rc/toolbar_move_horizontal_pressed.png | Bin 0 -> 155 bytes .../rc/toolbar_move_horizontal_pressed@2x.png | Bin 0 -> 308 bytes .../qdarkstyle/dark/rc/toolbar_move_vertical.png | Bin 0 -> 140 bytes .../dark/rc/toolbar_move_vertical@2x.png | Bin 0 -> 212 bytes .../dark/rc/toolbar_move_vertical_disabled.png | Bin 0 -> 140 bytes .../rc/toolbar_move_vertical_disabled@2x.png | Bin 0 -> 214 bytes .../dark/rc/toolbar_move_vertical_focus.png | Bin 0 -> 139 bytes .../dark/rc/toolbar_move_vertical_focus@2x.png | Bin 0 -> 211 bytes .../dark/rc/toolbar_move_vertical_pressed.png | Bin 0 -> 143 bytes .../dark/rc/toolbar_move_vertical_pressed@2x.png | Bin 0 -> 209 bytes .../dark/rc/toolbar_separator_horizontal.png | Bin 0 -> 151 bytes .../dark/rc/toolbar_separator_horizontal@2x.png | Bin 0 -> 292 bytes .../rc/toolbar_separator_horizontal_disabled.png | Bin 0 -> 151 bytes .../toolbar_separator_horizontal_disabled@2x.png | Bin 0 -> 291 bytes .../rc/toolbar_separator_horizontal_focus.png | Bin 0 -> 149 bytes .../rc/toolbar_separator_horizontal_focus@2x.png | Bin 0 -> 288 bytes .../rc/toolbar_separator_horizontal_pressed.png | Bin 0 -> 151 bytes .../toolbar_separator_horizontal_pressed@2x.png | Bin 0 -> 294 bytes .../dark/rc/toolbar_separator_vertical.png | Bin 0 -> 137 bytes .../dark/rc/toolbar_separator_vertical@2x.png | Bin 0 -> 197 bytes .../rc/toolbar_separator_vertical_disabled.png | Bin 0 -> 136 bytes .../toolbar_separator_vertical_disabled@2x.png | Bin 0 -> 200 bytes .../dark/rc/toolbar_separator_vertical_focus.png | Bin 0 -> 135 bytes .../rc/toolbar_separator_vertical_focus@2x.png | Bin 0 -> 197 bytes .../rc/toolbar_separator_vertical_pressed.png | Bin 0 -> 138 bytes .../rc/toolbar_separator_vertical_pressed@2x.png | Bin 0 -> 196 bytes src/qt/qdarkstyle/dark/rc/transparent.png | Bin 0 -> 104 bytes src/qt/qdarkstyle/dark/rc/transparent@2x.png | Bin 0 -> 117 bytes .../qdarkstyle/dark/rc/transparent_disabled.png | Bin 0 -> 104 bytes .../dark/rc/transparent_disabled@2x.png | Bin 0 -> 117 bytes src/qt/qdarkstyle/dark/rc/transparent_focus.png | Bin 0 -> 104 bytes .../qdarkstyle/dark/rc/transparent_focus@2x.png | Bin 0 -> 117 bytes .../qdarkstyle/dark/rc/transparent_pressed.png | Bin 0 -> 104 bytes .../dark/rc/transparent_pressed@2x.png | Bin 0 -> 117 bytes src/qt/qdarkstyle/dark/rc/window_close.png | Bin 0 -> 733 bytes src/qt/qdarkstyle/dark/rc/window_close@2x.png | Bin 0 -> 1620 bytes .../qdarkstyle/dark/rc/window_close_disabled.png | Bin 0 -> 820 bytes .../dark/rc/window_close_disabled@2x.png | Bin 0 -> 1717 bytes src/qt/qdarkstyle/dark/rc/window_close_focus.png | Bin 0 -> 728 bytes .../qdarkstyle/dark/rc/window_close_focus@2x.png | Bin 0 -> 1659 bytes .../qdarkstyle/dark/rc/window_close_pressed.png | Bin 0 -> 744 bytes .../dark/rc/window_close_pressed@2x.png | Bin 0 -> 1777 bytes src/qt/qdarkstyle/dark/rc/window_grip.png | Bin 0 -> 412 bytes src/qt/qdarkstyle/dark/rc/window_grip@2x.png | Bin 0 -> 712 bytes .../qdarkstyle/dark/rc/window_grip_disabled.png | Bin 0 -> 434 bytes .../dark/rc/window_grip_disabled@2x.png | Bin 0 -> 764 bytes src/qt/qdarkstyle/dark/rc/window_grip_focus.png | Bin 0 -> 408 bytes .../qdarkstyle/dark/rc/window_grip_focus@2x.png | Bin 0 -> 730 bytes .../qdarkstyle/dark/rc/window_grip_pressed.png | Bin 0 -> 455 bytes .../dark/rc/window_grip_pressed@2x.png | Bin 0 -> 747 bytes src/qt/qdarkstyle/dark/rc/window_minimize.png | Bin 0 -> 203 bytes src/qt/qdarkstyle/dark/rc/window_minimize@2x.png | Bin 0 -> 333 bytes .../dark/rc/window_minimize_disabled.png | Bin 0 -> 207 bytes .../dark/rc/window_minimize_disabled@2x.png | Bin 0 -> 336 bytes .../qdarkstyle/dark/rc/window_minimize_focus.png | Bin 0 -> 206 bytes .../dark/rc/window_minimize_focus@2x.png | Bin 0 -> 333 bytes .../dark/rc/window_minimize_pressed.png | Bin 0 -> 210 bytes .../dark/rc/window_minimize_pressed@2x.png | Bin 0 -> 337 bytes src/qt/qdarkstyle/dark/rc/window_undock.png | Bin 0 -> 521 bytes src/qt/qdarkstyle/dark/rc/window_undock@2x.png | Bin 0 -> 880 bytes .../dark/rc/window_undock_disabled.png | Bin 0 -> 536 bytes .../dark/rc/window_undock_disabled@2x.png | Bin 0 -> 924 bytes .../qdarkstyle/dark/rc/window_undock_focus.png | Bin 0 -> 503 bytes .../dark/rc/window_undock_focus@2x.png | Bin 0 -> 866 bytes .../qdarkstyle/dark/rc/window_undock_pressed.png | Bin 0 -> 539 bytes .../dark/rc/window_undock_pressed@2x.png | Bin 0 -> 905 bytes 209 files changed, 1 insertion(+) create mode 100644 src/qt/qdarkstyle/dark/rc/.keep create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_down_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_left_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_right_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/arrow_up_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/base_icon_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_closed_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_end_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_line_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_more_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/branch_open_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/line_vertical_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_checked_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/transparent_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_close_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_grip_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_minimize_pressed@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock_disabled.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock_disabled@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock_focus.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock_focus@2x.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock_pressed.png create mode 100644 src/qt/qdarkstyle/dark/rc/window_undock_pressed@2x.png diff --git a/src/qt/qdarkstyle/dark/rc/.keep b/src/qt/qdarkstyle/dark/rc/.keep new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/src/qt/qdarkstyle/dark/rc/.keep @@ -0,0 +1 @@ + diff --git a/src/qt/qdarkstyle/dark/rc/arrow_down.png b/src/qt/qdarkstyle/dark/rc/arrow_down.png new file mode 100644 index 0000000000000000000000000000000000000000..412b76e6fe53b0228445c158b5d5f23bf6f06c88 GIT binary patch literal 518 zcmV+h0{Q)kP)__57AFwC7ZXWsX4&bfc&pqc7Z){^3#=| zcIo?l1OS7+zC>qUl03eE@(dfhQ6mVzi{SQS} zH>WheJ^DC2J#Ahl%wW5*mG-YAF4#uWGM$j^APLNkR?@sADgQa?mm5z~-b$JmC9X&+ z^Qv@0z}OsL9&62-mxp746`#ER}!xZUP=#936(+- zyy(e8)e4?Ot6~umdr1+`RV;WC1gZ9-VyUg?s@H0X*_oZ@qVW`=$ucuv582e6KS?&( zncYa==lFi_{eIuy@4e*x-Yj4+7z_r3!C){L35PW7ed^>=z0JAaoA@|6^Z<`nhE& z{0RU+5Zs;qV1OMcnh>0C+anKf>^73;YJaeL2(K-VYnsOId6C520s0 z&$~K;+)S9tSc;-2nCe>q59CaHX`M?RHTXLvo_V<0ys=k}c`CoVgCKZRw5|Yfa*+fL zU4*iozYV4HzVF|xM(KZnD#iExn@ZxN5N>4*+Gt+#om&C2xbwoTB({%MojeMGDr9kS z@ge)b)OP?L%NQhpR#Mt3NQKrGz_0Ptf#Z)HIr3K>I&1qR)^4}|jC<>I5Pr%SNI+@k z{cyLP&L>Y?k9+HLbtS(UyH+}#&OuoAmjF%p?#pvzT&FHzj4wDzRuD!Xfp~rUdHA^Hxo7&nNz~5RK8uq~eb0S^ z#M!N9>D`v+zB#Vsf$_fK@6rjw(*Q3F3`x+d)1LR~xV22?V-A2$7%l)j1t<~l+O+3= tH7P9ygTY`h7z_r3!C){L42FA&e*u4|FqhM}5ZC|!002ovPDHLkV1o3?-f;i` literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_down_disabled.png b/src/qt/qdarkstyle/dark/rc/arrow_down_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..972df9cd1661f7ff195c02b529491f8e71b92eb2 GIT binary patch literal 546 zcmV+-0^R+IP)3D(PSWl*NY3`@h)va==`1FV6 z&q|aqw6_Qnm=l26lY(pCT$-QXOfzzSFKM+}-Eyh;tYi7(h)axH1;ysX0*?y0cGdU& zpWA4IB)plq`-r=}*9gppbx+Je55i{c9$UH||907*qoM6N<$f(E<;yZ`_I literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_down_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_down_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b0fb4ad11d0e40af005fd1b70eb6909db0990b64 GIT binary patch literal 1068 zcmV+{1k?M8P)VOhRCr#|5Y?*M-fCszJmPm%;+Vk#sDQ@xLB80RUZn z1A8>jd4%o$FMx43Uu_gX4gQ#vd2#4YjzumN8&#CS;r(_v_`$xm}OF zaK>p|Xab%IQWZ9G_t&<0anr=zoX;A4R|101><))^@X8W6n5C#l%U zw<+VhW$)j)nWFgcs74#dR-e;=#UqMk5kWx!3yqb`+=)I zQ}7YyLkSH2sv5Ju+QCCe9ia>H=x^fIwJS_{49h9K*2&}e3!cJMoyk9&9vi+Eg4FO@ zV#)C@{@k*4u><7?zfA)tA@EL-*|K%9V`6ONuMi{xA@>9)Mn`XDAI^0n`rWyP#bU8o mEEbE!VzF2(7K_F5pz#l6b~h4l)L{bv00006V* ze~@1wsJ}pLQrcK3vWY!OX5~e@d=|ztn`tAm%f{js>Fn@-?0fgb@_L#1&RkXG11OV15+WOkkW#lJFNDhM` z^I#)GNF@CDTU*tB^IZV|)~B^I-U`=k&!*nN&L6@ci6FrC?07reSfAF;;JV)n+bTbc zcd>3Kf{MbK+F>N&baTG9S_^lOe);X5J1ft72K#Nb>1fLh z-$Z^0l!k@qGw&eXTCM5PUfP*^J2~em;iteslAAghqC2qLM%S8ky~v`QYq%yFJ|E=g zz+r=xhA;#rT3;MA)x4rtSv7M{_r$!<1bY!UhA`3HmVb`Y#Wyv*&7(Kc9Y4F^Q?cVE z;6(cBLn!IOa#ip1YK{DpIk({B?T$YJ?+%o7>2+0~M%5}PC@9!hegLHSu?BdH$G89h N002ovPDHLkV1g>L^e_Mb literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_down_focus@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_down_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..06b80be4bc306ff88da171474703a52f2c3362ea GIT binary patch literal 992 zcmV<610Vc}P)iJhz*Ird!VZ@3=%{@ z!`8=(llrJRo=HGyHmL(~uLSm(Mr|VMYc7cPO38j9lK@+1(Eoed=OS$DOtv_O(u_xt z=YR)NAp=Pl5p?008py)tQ&3+_q*CQRfIg>G^C^3nTH)_z+Dc{`%quQ7coatT?1;gBer-Pr)>z9{^`@`@|ae3s@>8kE{|!Y zFVeHX51S(bh*3*YBPZs=wN4uQS26N|j_9 z^j40*L|r;aHJ$4>A^U7~B6=68?S6MPVuKaGEqgkr*#ul@5{x9AJ-JHnES7b)({^_~ zWrt?`isdiKj7)J!*us2b>9xhOGRv_Y3R$zIiYKwZ1r9WqTehrS9hi(GWq&h&3%yXC z(Clv7h5~o)q4R#;@^^^)o6C(YI!;2~x&F^YI<-{Rn5OXG*3hhLtr%C-9qo;stsgR7fd2Vx@bE&y@psu6KQ@UNS z%nd=^X!I_n3x3e+o)Xo)Osyp|s>Nqf;jXGvy z0JMeqxq(%k=%#t-(FNw2AKkb9NAk7Ni!D{KzZrNadUat$^)5^6&7;P`i0aj!qnCw0 z-|1W9&uYI!r+Z-@dU%Bez}Da_?@9h7Uya_co#N9@E;XIf`*{ z+Mr2_gOdpA>R?S#ROSQTCJ0xe%V4J&G>~cRi z_>Oz;|NigZ_kEC%kdUy-Sg`0kUYf;d{V!F;=VznE4FFEainCBf#W?>0g=^GQ)yKAO4*CacKI+>F>dJ zHyk`OJ-*P|zWYvUZF(EV_Nu`@JjN?-EEbpDo}2x6mkcR-R!;Cr1i5 z8)-)#Y)5Xe%aK0@tN}#537Lb*fO+4X!{w{_2T^om?W}BX|6bwT2iDh_2!8ul-=V8K zTzni=GxizF_FUSD<318>0#w`W05j%$2PUtbdJ#vjsYBjzVrZ**-nhXQ0Kr?i?!NMs zlW*c`HGRwM$`5RI7xYf>(ofmJ=Yxg!&1xkiBqXdVzW}c|tb*cE5EB3Z002ovPDHLk FV1m2v3RnOD literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_down_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_down_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ef20f2cb07f9934ce792a502ce9ad103d4cde38f GIT binary patch literal 1070 zcmV+}1kwA6P)jSJ6 ze*#pGD{@!=_CYA3s2=yW`}P2U)~-`+B61#R@_eqKZX^oB!@?ieJRNcSibuUA<=+o<8#V4lNWe06RThH%Jl$z``H=FJjy6+2NjRcj{gC6vz(u zTvN^O0i05cilTP;6h?;tirT*5g{*3RPr2Y>jmKaveQdVj_RVJme((uU?Dfcjg17{Z zeW@XT^VwYb*z8*TRHS|H!ST)W4GU)leZ?tdLqE9i-w&96@q47ySs>;yE!PS)5megd1zyjNCC}C9JG@DX9~ycN zi*JAjR<`TXmR)5MB&fhy5cK8jSl^}Ue0oL*!%2~NVrUo2cfdoQVXC-91qMGSuKPmv zi~ejaI!i_g%TbY*BcDDYg-sU)eb{5FU^xT^|A%WA+NX!#{5b@f|Bn==vm#IRoPNaq z$GreNR$@?5P>HG?AZfag zr{nT?@_H0HBYP72X|($RKfqJCQ9}m9N)YUoBtYN zpVy|#d%`M@ujdRxc8k^@{jXHR! zu@YP>SEi=inHP6`yM6w?2NBs_=JQW-&2vYu3=aDDi3q6kRbD0Dm3j~1qhK-mes(PR zaW$8kYFU@}oOojBFv{qPCPg*jr2EqK)>4-x;AO^{%x!P&xF3<70t-N=lkWR!J+v4M o27|$1Fc=I5gTY`h816Ox1uyPFn?G+z{r~^~07*qoM6N<$g3NsPHvj+t literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_left.png b/src/qt/qdarkstyle/dark/rc/arrow_left.png new file mode 100644 index 0000000000000000000000000000000000000000..b7aeac5f8dc9d68f9704dfdb783eb36118ccc821 GIT binary patch literal 555 zcmV+`0@VG9P)&K=;-=vAe?3$})nI#zHFv zI~yT?fLMsV2!f@cl@>O^Lep7UO1MtE%icsd>^uq4!`o-EiGqzcKTyzD%?|s%-_O1` zGdu9Vhf)hV=Z?)P8yHxpXdnIE`^}W*fcf+&DtS+1FJ%j&XMfM5M% z00w1w6?6|kQjmEtz@RKwg&yra2Ac-~3`V1KLeGE(^^y-Z_XZdax6jB}2M*T8@>=mx z0PmeUO*VT8EY;?I+bs&fId?p(*Z?i3G>18l;%}90?~eslRMUTn`C4FX?hjJOTma36 zE&y8~EYbhN3n0()4^^fWu#ePth-46R3!TdIcT|n@z=XOKNg%vLI-L`5O{@Z65CV&a z@D}K{+pi6~49q|x@>&=41>K@pH|+XP4Fy94m#|wDPr%jy%&N=+D-qShPEp*KxGM=k z5JdDMD)Rg`#zO!>hWSB614y!yMSc@_T2J_CCfUo9W;>rJ*ML{PxyeqnUavPjbYS5U t;>}+H0BE&ZJ5A}L854s~DYgII_zp_imH@EpRyqIx002ovPDHLkV1kJO@a_Nr literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_left@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fef91a8c8bd419b03bc210c3a03b482e9d1a83bc GIT binary patch literal 1127 zcmV-t1ep7YP)T@-J^;!%ibG>E}J zpeGT7f*wQ#MbJZpC`J%Gh-koz2ZMSF3mRROAP9m7K@bVLvpqd+jJOa*FvQGEKMxzV zyLSY|>h4nK9p8hh?|c1KRabR2%rL_YGyDsXrrF-XFdHT5aGa*;Q?A-IR}IyP!Qh)6 zSpK2@h&PX;aLz^Bfs01!M1MG3#`2Xy@#o%FAezm`0-1E&Uh8**4>wP1{^)Qalu)qNAG}L-b8<1%>hZ0oI`Nx zkYKs2NMNZukwL0X)1=+Dqt|kZWnr`$~RH= zMYK`@{WQH!rh{Ah7r8ln%lj*6+<^5gyE?!Q0oy84jy0P+G;BbcrdL|7!@zkJDW~Bl z{~H=JV10c(%CS}8qLN_kB@Yc5u(q~#sm*oX2jnp@CJP-|t@-bhf<{VcQRl=j> zp#}pa*&xlH2ktHj=3nwqg8^xlJ%RB^iIhP8B@d1bNQT4vC7v#F0x)ZAbMtrM%zz}# z_9I@d@>cVK#y^F-3Xt|pVe`!+Eq~$8fGK-;uQNXbX9fs8#MYbx-#7Wp$((5eZIm0_>f zOD4t*zzn|fwxBD#Og%W9oHMDPN z-2gLFFX}!DyjJ8T%o>QVbpv2?^E3#%_W~o&W1_10Z8?0 zcop6l01(IVsqyHS-N0vMrJh@&;F$pcOG`^XO-848A--y&Kkp0xSX^BEUio+@aIEgW zyfgq{VPPQ+&`#jQ6xrF3@YVo;D2l#RV7q{yi@eKUX1q24V4>UnG)K2k*f;zyewiua tvMBlhv=5koO=LXNc1$zOFvEWXzXE`zP6rp5|5*S4002ovPDHLkV1m^E1nvL; literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_left_disabled.png b/src/qt/qdarkstyle/dark/rc/arrow_left_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..79b1f05651bfc923d3f6fb5ef7f6d91a230a95c9 GIT binary patch literal 557 zcmV+|0@D47P)_R>ey9?LH#tbOSpx-~4vw zG4Q{eVkcZovm@T?Envmy{`{Z5Z^ta2^!tbWj-CRYsxdBB@ia{j*v{M-I2jTb1t3k+ z)+gV22$qD##sJV~-?=R~j{)HK6=309b{$y504ERMF)CW4AzbKPT$gbb0Lfz(R2&*8 z(CuY?iJL!*6JESFK(d@IAw4L)dY#t>NP5{RLyv)$VOF>ES^(Yj(g~B>1m-X^p`eLx z1khc+d>n7jzz!Q&`QMvcC4kfE+A)|Fz)`>yxa+^ON^98id+&d7qZNmW3J6|9;0qHI zV9&MBfW1>dOjLm9`P~oDPJoYqEFwhZM8)Xd8=MwF+bR#4C=fwOihSdh%r61EfXtdh z1Sgn`2QP%J05b`J8l82uI+%eQind}CD zd7Nq}(Rhfqo(!%D?jSJ35vW9rRkDtoUNLxtfWXa&vdej%&*t596*LKrjrOADdHz)g vcYDCgzXAX-84kZVXJ?VNfoaU#|E_%lXh)R_h<{1o00000NkvXXu0mjf1=a9* literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_left_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_left_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..144fdb5f8f3b2a5644b2ddb836969618c1127d4f GIT binary patch literal 1141 zcmV-*1d98KP)RCt{2n@?z5RTRd5=gqWQj0m>6FsLh0)QwPtB1mi}i9rl@ z#?h77{FzV}q6J0p5982^6$BR|wn?VOMT(jx4WSx4Nn{F&ASejMg&^XhK?JQ7Z3~mR z$3+}@^Jc&l-@Wf*=39Or+;i@C&i(h8fet$8U^7FKPGF~vfM*+Oq_c&8y)kmhcUt#Dp8$3@AXb9 z-#{V;?8z1~f*x;)A7HR}VUqz`)^DMOF(y+7bLODH(a znq=i0u-XB;@&~qwF$=&w5lO-REpH>RWr6pO`R%l31V zs0>CVZz|t_4Flwhv#W0cPd2gIsC?qfz6r4#kjag{DCmI}LHud^Fk&^JH&@s%aHv%g zXOEjJMQjH2W=9T#z8mGm!?q72z77zHe$W6U(Ocd|5Sszg_6_g#+<_PkFvv5s&N%Te zPXC735?r30_y~BqRnb&jF>D~#3N6h}z5`lpW(B}o6Jl@CrP=a95#EmSih8*mY$T<- z?&^M4mFX}kh**mEpI{}SQmJIl?+Atv`8Xm8o^^t?WWF9BuU&On9z*r>W<^9j>IAEa zoH{jrv1aNIgM1t21;m#B(f7P&rX~c@_Wnn-t@100000NkvXX Hu0mjf&}sk~ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_left_focus.png b/src/qt/qdarkstyle/dark/rc/arrow_left_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..ef028499477b3c5008d9266018d9cb3dda17bee3 GIT binary patch literal 551 zcmV+?0@(eDP){=&9$P``tVD z&U^5`OSugv3ZIA#zqjz~Ryh8<^NpOz&#ikj_WTSuCYOr|xssnPeDHA3E5LY4To!<< zg-4DYh)cj^$-*-N*!tLr_pz>FBNP89KyxK77~KSe6cI^Hs0GmMcpm9CfUO8=$!h^L zJHC#5mqFI3#L8;{j6d}>@8pAYgHa0qOn zq=~Nu(0t-E!CnWBT9^#UO9M<4K1J{g;3UGSyZ$Scnt|BxCjet|wEbt5y@D-(vLBf2 z0AXJjfe%QfW3mFgYHORQN#HX^Rz8T*M%^oV7o{m+M@Gh3Ad*ZrTY3|%Y2dq17Kmhn z%~`!vP#fqEAXMwOu2KaXm$im<13-f=REDVB!tSh=k>-a!t_V@<4!bSg!(IeXMTpu% z)SU@;Y(D^yoeWWbl_a0;hg-;xkdV_hBg-y7Zma)wFU$eYQc9h3Oid5gY*CWsT-FW~hx4MG{FgWh36?s2!UeY(jd9@KN zfOTWOJdQjIT$IfO&a0gu0o*X=i)%H{0+$utR;}m;R;%mZ@%ewoeh+h18SMo%1BPCA z?^4UtnDt5DIZpYkf&nmez_rD--Ur;23WSy8qL)<|0Brrf5brgNWD{Im=OGXP{ZsMt zpnFrMFa?hMvML8KFzF{ik0(91@A|?!4;2F#nDqU|d$PV1waTiYG64NkZWzCsG7UB{ zE^N{7P$d8c#(gvPzHIvzu~gh6?@THkz~GeoEKdXHBz>DW&n@msRVsk~X{;N#bfTDwIu9kC1vX6jk{13DxHO$8rpy)Z3@UsEtQ+&%CHZ~e z%2Xh`>dr&KGhlGcYvP(`FxRC5VXRU%I{&1?X28$^*W#Mr0&YzDE@6Ma8WjUz)Y0NX z{2DNv@(VuM{Tt;Ez}CRE@e4-xWRs9aep$H#7?|QoqeoL_d#wwu^N=%uzDYl5yt^Zi zN;}-FR=EM_n{4e7ekJQWz-gaUjx!+hLWB1E`>M9MD^+d)1fA17=&rYw9{}lLGF_I4 zLjU}j8-TeHje#EOOq|O{%%YU*Q((TXmqDYQNw^Sl-v`W(u*>pGX;&bk5buWkcY>0e z$D&7!-%R;NxcaxySrt>zPQ|SsqwT=EnM5co2!$1M{xZ+RMHnjcKHx0S&5rl z^?|Ir$sV36fKb_^Xs)5RZS6>zT0TLRr%Ip2&4%{cda5IEd55RUHzUnD&k4VnGIjd! zRDvo8faJO3(PP4Ir2LY$%+&(`*r~Ypg6KYACX*C?cnSjmaB!oR*8HNo44xUj|6Yy=(Z3PJc;7~)~ z5NQ+eQ#Q-<+z>1PfcY)@GLkl9eoOkwvF@M&0304sQ`VNu52?=nzsw{xw^biu?V|np lt%dY#)irh1Raa++{sND%QC95D7mWY_002ovPDHLkV1mnw4eS->P)(rt(`+?>jJCj>q@@X?+yZ{OH*2U5zMu47Mk0PA-)Bk>d5f zzWyDL3{JS@1pz1)7km2i`yK#8uDJmKOz-ob?*L~pFf8pVK%q2u6I2GnWT}vK4PfBX zY}Mc@fJx5g9RUoKYh#FM0E1M9v$;1wp)@;!>3;h&6@KPk0EN=bNrOe8hnBIoxidiF z;`A{iw*>5L8#{IU?;`UgJYK3DPSF!!w}B~uIb^KBV0r3b)AY<>KNij$GFD*AqL06> zErm0OtUX|?gfw*q=*=~T4L-DCf?Z&l0ba~s{uE(Df-khjT`-8uLa*Y9x1`Nez?xbQ znII5OBFVkU*CHJOz7q(-Ss;n4&jq7E6A3uG9p#0A%I`(Qy+capjuCT@XsiwI+2J0YG+W^*{x9h(O3mGss!4*GHQh zUsuloPhE3^O|&=l8=IROKh6kV{uKa#m4z$oQKNAhSOa|vsr~Q9PZ2Vd3~y^7-T(jq M07*qoM6N<$f+%A3zyJUM literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_left_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_left_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f0bcb5229b1ceb85a30395d4255d258641f1dbdc GIT binary patch literal 1155 zcmV-}1bq96P)BteMrg{Ui0TnIzA5fNk*jRrCJ z09}brFw-59o_0VHe9$(Dn1J}`Hl}+F7#9Y06$Ugqx=28f%yi-daUqDf(5Qqcnh9oR zx_%dJpsE;y(Ry4=|I7bC-E+S>eeXS0)zDX8eVxs+tP}XBDvma5W_n6sNLxD-)o0?k zt{2Bel2&2#<(n{Sf;^DJ?CH3!?L2_hrDoC0CPBe!jV*7d0Tf1?SNUikusrAs{J6$& z7C>S2rOV7T1+0q33>4Qm`M53=r-nuv=bJGFT$=P)&Q-t->$k7SE#W=j$~4Av3c&C~ zub(qFuyij_4El<(L9#kSxYUFDgd>$c`U5uWjh=ux}#4$%7*R zilydujP*fJm_Uh69vlErC^a4j9*g>x!sH=i0N0iq8w|EB66&UvLuLSq<>tK-t*Eb* z?))ib0-(5|aSPI(MaK87xA3K=)BzOBjn#PU1(pPT89oW__kX8U0bEyVT#eWVEQ^GE zQ~HyK6afrvdgby3YzkNz^#AJYGMPN21mK$T&I`N+|3gEU1bu-YXJ_|slz2B-7;T?x zI{7|uMbKC8h@0u;A>j(Re*A@{W^*6L0hQuZ4H?MGfSrSKiDj@Pe1A3jE3w!B4>UMi6`;d?(tu}T<&(@n@Grd)sU@HxeGI|Zu-&d z+O3EmLIL3^V+g60;qQ|LEkV>8B{_hEAio0{(603`P_>8F%CpRrUdhJ1^~eR-6MbG23Q9i4*Hhh*60)ffP>Ak z-{x#!E%0?3<2eTa;EUGApSyW)jj->N9?MAp0H5yI{9PWc0ggpuah?{P1psicJ@ysG zT3|Nl+u8D$8Gue}Y#N`t6!?BH&W|ab2LRA{ZR{h^7O<{~F6KR(bxwWt)z|++e*%|w VK7(S3j)MRI002ovPDHLkV1jwU6pR1> literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_right.png b/src/qt/qdarkstyle/dark/rc/arrow_right.png new file mode 100644 index 0000000000000000000000000000000000000000..78d67f2dbc062ac17c8b16e76145bb2a21b033ee GIT binary patch literal 532 zcmV+v0_**WP)f7F zh2#^6h+jYytVJvYv0Fs3w6GSojM>bL$l53ogBslXSj;S@bLWMdLQi#zIrsU^nOod} zf4yv$helcc#lRwG{Wy+4cL{JaK6g}bhhpRy>e2(;4axU?vHbYi?vkaVIRGECF5;61PTKwiX%yAT#sj((Y|! z#nsS&3V{bO^yqz-t%e35F+CHJ!=7#A`T3v#fNBZ?4w@K@Mjy@w1ynUfEa3dh^`ck~ z4cLu17J0qS^Za;d00zD^usDGi!2v*(4~R3t0Ro2^z-DBe2n}$Q_lr*xXBUzr`4|!~ z4d2qltt`j!dY#6WrD^yN85jHglke(uw*?sGN1u3fxt}C&>Ta;FU3mEd!mgi6lR=YB znohtZRlQp4r}2}9`!t$>0nW@Yp5Eyqyaqs9lG*;qt@e7o?XJTA7r<|) W>z6i@J$8fu0000t5qc>i_CrudC|y2QXp6gb4ZH?pLimCo>Axw3|%=h|YfFRUaDdnT4`nQEK1Bgf!S~f7~Vz)bZ*p!A1 zj2QrcOByy(Ex*(m3<85XMlor?N(8k`E&MPTY;>SCHZBYRz>n0k{KBc{cNw-TW3?)7Xtv0UN;aPhp3&j zSv+}UKzZE&V0WXRezN?Yqe;9n02rA-nhE=QGJVfR1?imu0Kg1YToQ<|U#98nrnS5@ z002Og7t??lM|x7eY*NNw1BPhD6F|qhQa)`;z-t3mD4vKwM@?yXZ2$n2EqeqQ+ZMgK zIa$VN?AjzT=u=Y~UK^l*S}_5L@MLP$DGk~B^zzqT35yf%hDu}8KC>#8rP~xd5p1$fb5cih=mkxf33G;D0{k7|G zoEpFYfiz8K@N>;DTyPo7U7TG4D_3^>N;8U1xr(ERvkXv-n%>H9G^6NaS22{~!~h}) zDxC3{@qQx=D}PPKx&Z_TX6=akSsVoiY!o-+V%Y!^te@}CBw_H94}%Bn8X&YgdW0)b z`Ljz_{+V+{5 zncr+{{TECcQ1;;RI#}&!wKnw)>KMh!Co=#*z%51C*=RJrH>F_%Tc6A@f%mq;@EcS8 x+rnH15RL$p1IPh>D~h5oP4zut!h{L7_y>ZbNJS16nA!jU002ovPDHLkV1h!&_htY9 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_right_disabled.png b/src/qt/qdarkstyle/dark/rc/arrow_right_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..88da1f980bedb91fb51836fd7d897a1c3d1d6270 GIT binary patch literal 545 zcmV++0^a?JP)X2P&1zwGuyIi| zDJ*0^fk^NRh=PsTAnq1IHZI5_&c@Ed+TOxSuyKi?cp>MpmMTzsZ;=fjWY`s+uho7<3g!`JVFjR5UlMuX`U?`Kz0;1_%QaXT5|JL zseqgj0Ar4XKtH~8<7mkM0D?2j3HDZA&I9nr)95qv0ObArfnVWRsQ_oag!mLi#QhhY zkK@$sDQ3DONdgAZFx1km&iipoXWjwhh-~=xNL);}I`1Z_pAjGl2^dOB(#`gpNjuB} z5O`F7eP{FW_B2hV1!z<&Snc=P8&md~3Lu=Bg}-GN4v=}PgFousZue&q!(r?@paDXP j!cw}v{{IP)^@RCt{2n@@<_MHI)sZ<4K5*}38yclYd8lhVo zvZ7S5-DI^O9uz4kY7DlZ2o@^nx=CaYR#7+Ux`vv1UMjECL9Oh4e&WhsF3#uxWtq|AT;0?&8$L6O(sY z)Ub|C1K1cLZ0%~*Oz%Co-J*_FY#MMawsSnzNIdcMRspSnkuU%N?jE_U7stmZM}_p( zjWYw7Ik+Y6Z*Nlbnap!HxzfBIoEbnw8o|22*wwkE{c$2ujJwhu6xUlo!(0j3k+E~r zuy_gE2<~e@*h&EMsod0?&b8NpR1wt12=n1oHh)-1|C&e{003QMgy^kQE?*GL!9dc0 zwe4^rVrKvTEw1$=H=u`kTO{DVPW$GC#DN2wT`GHG002PuRzn|z2S+Z(K6TkV z`D6fyNVCyF()h^Oxk|BEbdsxA1^^7|oeaU6@YJ`b&%O-@9i(RlT*16DgI-AG3NP6f z^3?zUWHwKXqp4i}8Jj8|8^8ddjm^OHemYyo*;4V?006zB5Zn#~!n?Kvd^Z3TQudf( z?O62Q0Oqh9xoRuEH~*athhxE$kBFXa)GF`UQt)^Mn3D(LwZ>f8+T;O$4NxI>p5x8A z$`J=bK0yGpf;sz-9=Lbg^9cI^c7u3U1GEBNUH2LI^1_&!ER{+jx5JI&%?jY&vJX!F zn@ei+u^(qL9f0xQ5Dg%g3?Mn=r+=qWuSWh%#=QZd%?-~sYtU_dzWWt|8u2zJxCS7UzLt$7Ehe`S4eN& zNEmRIl}a^EPX8^SH83{s0bxH}o@b48t2Xn8MIEa+`DA95i<&9ZI$8O}qK0+seKdvs zS6|E^esrl`{=rs!S6KXNjE{oQ1-J{~jpkf+$yV$kLxv1-#s34LGQBCC9?}2+002ov JPDHLkV1jc`5&8fC literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_right_focus.png b/src/qt/qdarkstyle/dark/rc/arrow_right_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..92271a8ed9454067555798b44d143257b53b1b6c GIT binary patch literal 541 zcmV+&0^UjaBh z8oRc{y9+C>WCvg(!dU0uRpKq|k$Pxq010DkgQUy#)wrA$P?Uj~-gLFz@=|U9683L| zZ`519kQD$Ru+b24r}oIRSpf-Q8ylzyKd7zxR8~MjD3TD{6x}}2^6{*If)SmXb9bm6<=$3D{B*J}_G7HTA6Q8e^Y; zjU=ZHNSAu^YLBzdxF;Z`rbB3{JFk0Vu2UXhBN*=7*I%5~&2hs^1Dt*Z(p{Htcbnnb zB;ln2!XfpX?{{B@D@e`?NIPf!b3a^Ux%e5Gu*%+o&bJ*p_oksA(+DpE*hE(N8D?KM f^krJ%{|n$351ynzm+_qH00000NkvXXu0mjf9wG2> literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_right_focus@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_right_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d6c31bdda91b138d926aa03db2cd4695e6c6a3f8 GIT binary patch literal 1112 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 VQ(nMnXh8q~002ovPDHLkV1nj>+Qa|= literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_up_disabled.png b/src/qt/qdarkstyle/dark/rc/arrow_up_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..48054a8ae9e7f05f9353e37fd033916b6a5bf56c GIT binary patch literal 549 zcmV+=0^0qFP){bSc^n>JYJ;rBK8ql*Ym4 zPVfuCCe|+9oP(Qtw+zzF#i2?>tcwTfBG^$UKPJc0NjT4Ye}`ObLaI#O$ zm&(gP4KRwTi0sllRuGitpJjmgQ)ec(K7H7Hn^Zt@rOHF#QG9EqwdVeeio`y`?D)A0 z^6~wqzb}DmwQ2@NCRTt4ajDiE_l)dZW=@}-9KL<+$}8XZyJ~c8M4smjY}?E#a6Jy$ zck{OL0@_+Z2T@hiY@{y-1IMk`Yu~yA z=58z<{~m;O;9~s9(%YQx?SP2xe2I-P`cZtdwz>__*9r=P@UuXsEichFy&Kv&j;Vg9 n?+b9Oqer7~|5_yf4AkH&_E z!}m+Y!uOqwr;`GZmCU>k@aftkD7N>&$YZ7A>ZOha)rn0ak-1>#$+dY9rWzT~poQ{Z zPrtFU@^0Dh*nAftGCA23yc=2~@JWMP69LRnhRD9&=qtara_-!^pYi!Bz_E#m-5cwV zo+t28yPY>Tu2hfafV(Z=O78=G^5VsXyMD#!n*hhgr=BWT0yz*48{8Fx4KVklpM$D$ zJeOVk!^7~l@kM~>`0O5NohM+Q-OgYpkghkE!HPgsZNm*!uEg>e7H@eStLFkl%AaJP30eck^k3(M0A2Qn(6d^4vu706?SxW`}i< zp|8b~(?{A4)P`pQ#8NY(iuekE{%Q|1sEOpaA)&Kr_2U=wpRkERl(~x~`qJZ-Q1LJppWbMEqOi>;Pu--iG?vG-v3Ug>(_hgR2Z zRRD^mGVcL+$L)cJ$I06lhf8d-hK9qvrDEZ7%PTfRBr+Ea^{;&lV8-C~G5Ku>rryOk z`$XW*o7rr()+NhGQxy=Ioa_k&?kxeBaBS}LH*bJJjsr2W&OL|rJ^SK?n>T-KScHZv zU~Fvq@%y{fc`#g$AV1E01DGoTxZJy;tP@j%91P?E?5}b#TD;)+f`U7jVvu3wzB+rm-o&~BSjpM_44nrs zXty)K)Xdek6PVv0eh(;ZeVbjlQEOVwn_w(CeS}$Gg)@1^j&F2bfymT^_f#tCnl+v_ zy^;f{A;2q%>7#&J24TSAVj}1+pZR*YMIa1ljpb-69WhOCHIUIn`VB~VQ&n(SQGmm+yWkwf(bACHOO09Alq>dw@Xj}^%^bO%l^ z`ed+Q0~6SJ76E)UI{)sfJ`9s@s1DTHo(}dZFo7^ZDM2Y<;HdCwt?lW*VxZRYjG|Y7 zLl(wFoJ&J=wi;LTO0DUOBQ;Q8^iAP5Fb1|v+!-T?WHT9)ywqs<#z+h_TE2(<6sQ;* z)F-~hM$BTU7(Z(?eYdy)TlH2tYy2qxjQXv3ZUIH-ahB&A&GaGmu9toA#si0XHO_(V z02rb+roBg;y^R1M`|;b4;Xbqd1@sv>G4Fi`llTO5-C3q64JW>7!Uz#E5kK#J3%Ay8 zYkgM(r(XC#((?jvAse?MLsmWjfkQ6!s+Z{6+9mzyGjML%M}Bs_EOEwwOr&7tJK5d| zI$dez{S|!&NH&7jyZ$6GzUfNEe$#`{_CcTBZ+`|3!B-qG^tkpH{BpTzQRoZ)8%z)E(Z#%!< zo2hs|%lq#Ae$V&3@7#Cq0D(Xt5C{YUfj}S-2m}Iw{}&up;(SGAQeOfvkS;V9a;Hb3 zVce5{8D0lSEL8310N?L0 z@ry>;oC2v~$Qp_PrMjZE-|cyT$GcmhOHVy(-n})$jck<-!GO|bjj!$1S0Lt+&m>qj z6*xad0@d+9c=}|qx>}sotYRgc~vh)kyZd4NMsWQyW{Rg7|7A} zvo$~tpIo-@kk&nI_>QQBpABd?iuAIbgb?X+gK) zD;`}G-(lBQA-+afgsrmK40P&WbWYabWXEWTF+3pgh1qftE{>$Sdx zCP>AAVyt;1-2kwseO!TtB~6uTcJ7GwLVNayk* zz|#HgrUl`7X@WlczHC0~=l;;M0j0X4_229{ktbXsnHJy7A&~T%u=vu3dGFfM?G9Of zdNQDNS>tQZ=n8=OMD}L!?x!mgB#?mdsE?l;=ds!>|LQhY*9N?DT~BXpY8im@32I$x zhEjZ6PH!g=_$HTQx!e0gR|ZUet%+z;H3(Y|AripeS}s*cz}g(RwG0AxA4Z(L_a+~7 z4AE)A^s@FFs}%qT6OZ~k;ADaS{_rEjBaH?AveVKXKZ7qX>7cP%#cnPh*zVMLh(@bZ z*LA?RP6G^zoZaMJCj;@k0e!UK?RG|If^TjK42LPaw)sv}Xnc60Fn(7b9V zJ7EG+y;xPrx5VjyLPe)xbjIW4aJTsZal{jX<;RT$ezN1dVr(}A`2L>y&qHAI&b*1* z$2=#hCl_CB?jAs%ZSAU07J>zNcGNNgfj}S-2m}IwKp+qZ1OlVxA3TpxeLL5q^#A|> M07*qoM6N<$f~V8bJOBUy literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_up_pressed.png b/src/qt/qdarkstyle/dark/rc/arrow_up_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..22332010697f4eaa2390c2449306c349538772ef GIT binary patch literal 554 zcmV+_0@eMAP)1>OgLbV1%8?&cyvDXH}9aCQ%oL`=sdEZOEo;r{!lqbx^Y6im?1~glb3^?MUmMWAd z{)s>;Uzv8EMc{yeA$)t*yqOFba-PL>wtS(l0-4;yYtH;LU;r?&wRj83e9)BviRYPo z`RZ0>jeky-fm^hydhMq8R((uDE_kV|jC{RAskD9TItNZ%F76*Z zoSX-)0GRNy-imKZ2+20TvnOVW>-B1GV@H8>c5YB^?J33-1}5`r9kI~-)(Np-K5?mD z&HdOWaI*0DP{JB7FwO>ndoJFVKx&`3rN&xw`rZ89?*Q>%ixR%^0T^nVDb#Pe8y)+6 sE}n>g1P(&TyI}A1rLhqa5fT02Cur)Jpk8i6-T(jq07*qoM6N<$f}Rrq3;+NC literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/arrow_up_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/arrow_up_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9954cf51944f041d5982e32eb0cbbdf3b6a07630 GIT binary patch literal 1053 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 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed@2x.png b/src/qt/qdarkstyle/dark/rc/branch_closed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a641a550b67320b67fad7b9e5e6f8672f3b4bf9f GIT binary patch literal 837 zcmV-L1G@Z)P)3cN3eY1uJ6lP-iy@4eiBSu|oBr2!a&4n6-5Lv> z*@E*qzAx;1`*wyI5$(M*zUx8$7H~a|(-&*mt%HNT3$p#& zA$0`+K+Y7aRsjHHvbA|;mhRsU=>do+4C;$LaWlvBL)rfAQ1S(e#o~NuP%&;+cD+|B zGOUHNCD<>-M+1DQRVQG?@w{8AaoS81S>dd&}IQ|)xS(cH03dCW%-WY(h ztvVYtToB@o$}EW#006e@eFCuRK9C~xnWp(!RgT080M@=Eqz&p4Le%1B8%?6;@R!+{ zjyOGt_y;p9`8bKL005Y(RCaU(;cU#Pnzzhtvi%dki4FAi&4q;BF{2*a^&ZIfPrLvC z=r_&xARLPsos#XnDGC4pgyB>Ywwt1Wa=E+{Mrva9gkH<`PP~9hrP4*I^kV?|Mx6*Z z@|GBp?Vo4?%$%wR;W&UjjXHtvSVCM^ks;9n9B=wIfTK+!cULiz9WftWH*uFoEh$jJLS5#hL z!`N34;+^U|O1FUPx&?&%1Pw3GK)}F>Bwij+Sb*>Q+aq8Cgx;nAjEe=!dZsEzE3v=W zZZxG*DHBBe2%v#Rod`E`mU&l2hP9Bs0+`uIZ^_&Pu)k3!@O?{&YqI^@A-w?G^{@W< zZ*UpH%cXk#f~vFrZ%91_N~KaJ-I4hQptC{#V1P#~%lazQ`(Kf|0;<(&1n|;|!ZV1% zBb(*r0m%gn4Gk?38|Mg^19%Ei>To`vcVv2MG#ZUYqtR$I8jVJy(X`_iZyMa~dNuF$ P00000NkvXXu0mjfZa{t8 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed_disabled.png b/src/qt/qdarkstyle/dark/rc/branch_closed_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..165fae29baf0819689f3ba6a37233166b55f5881 GIT binary patch literal 426 zcmV;b0agBqP)H4%)umJ|6;q3iQweMCS;AC;JSeyt?1w$XXTrTLTfKtjv^!B*!+mWHC0syUgF|$)Ja{SqFvt5B=x5XYZUv-o&y+!;2yY{;qn-+6vV|h( z9pF=hjrMir#c77|E67;+U5!)$TSPXS_0p|Lj?q7m&gR!ZYCr(wu+=DCnB;)L5v*JL zakMmm5F#h7M(NbFxru<-Py-?wE|c-aBR9!`1tsI1Etqq U!Ivu(wg3PC07*qoM6N<$f+xAamjD0& literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/branch_closed_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..421e8e094f77dcf27757f6e67149f8e5399ca985 GIT binary patch literal 862 zcmV-k1EKthP)|l31(ks$;F;JnO{>x=IN{rARPkp0XsP7_>@fF}^x--j46NyM# zw0|MQt^fe5>5qA<001&YbTSYK2=_09@BqEC5!u>2&}cQg2v zFuucNw5m$eZ;AG|yZ``5c7_KzL7h=2z%kL@%c1}Ppqvg{;%kMe5zk?LJqPPD8TE_y zw!DDa+GZEEBLQIZoB_xAR4h~>+TYRw{C>Y}+QB+NuqR(9;H{~6C?F$)r3Fl|(n}mT zlCKeh2h-ylPXjPLBrP=-9)+9E0Q|~amAr6fbCojR6j}2yRNr(IgvSj2A9K{cw9bEcbx7Ll|Ao+9z~^gm%(yZW07~-YH^q*k zihCVbr9AH!Lg)(kvgtSDKsH~pCRsuf;zP3@~@uu3^IA;RGKDC3VSo@U2Ks og+ifFC=?2XLZMJ76pBLp0qPRnQ|A&%@&Et;07*qoM6N<$f-g&d8~^|S literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed_focus.png b/src/qt/qdarkstyle/dark/rc/branch_closed_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..ccc249a59a715084e9174ce3d7a7eadebea227ca GIT binary patch literal 395 zcmV;60d)R}P)sVqMg(S5G=x?lZ4d!Gf+)z_r1wo+-Ez;<)K7f1Q{$v7@6-HbgC<4zpSus_Ca^$v=tpIPB&0j6rL);ASUoaDC)zC5Ege`Qc zcJ7nowSlmuIYV^-VH>`~y#&HDO$AaD$eXm+soH_>@c06f1%VpC1g4Yg+h8-vaDaT= p27@QyZmbuqQ8SlRAR{9q;|oS`VxgOVQ)&PJ002ovPDHLkV1i)esn!4h literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed_focus@2x.png b/src/qt/qdarkstyle/dark/rc/branch_closed_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..88dd0a62b1d340cfb4443a5d9ae85b06fd7fb76e GIT binary patch literal 810 zcmV+_1J(SAP)_FGJAlPvu~;k?i^XEGSS*(R4eB=Va$z69Qvg8n+(d@Gx; zLYi+Cc{oC9_HyA3Q#r~p`VKzN@QIKYD-~W&<>a)003TO`5It*g&;hs+xwp= z0010?=~#T@FfGS>D4P`}Up^PXGu_^?7qE9&>JiE?h;1bT<=SM2)2!P+)&frSOTrDL z4?t6?BDei^r`tq^SPS^zs+$1P#WMjO)opYxfQ&pOtu^r-g$LylL~fOhU%Cmln7k>9 zrGTaZ$&fNo=KskFm@0Jgv&k&R3rG!#CrU;E)D?~Ap?JVQ&R3@MButw9z73WU0>xKk z0l>81!Gg&w%S2vS>R^ArG%82(0Lsq(?DDgGY$``NMs|VLywoaJh5+m=5k#*0S>7>` zVI}kz&@ImFqUr(AQYy$@KkHo8?q3D%1$eu0W%<9sBAzxTo%5#l`oE!d7ii5(?d+ob z0FW#izgbtq=CPwR@_WA;T35i=k5B-Xibo{d{*^BeXf9x?i%SI00+<0Xt;i!28NS!) oX|Y%=7K_DVu~;k?i^WonUqqD5zQp;Us{jB107*qoM6N<$g1$j(+5i9m literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed_pressed.png b/src/qt/qdarkstyle/dark/rc/branch_closed_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..2aae68a0a13741c25d9473669ce778e87f590491 GIT binary patch literal 415 zcmV;Q0bu@#P)VsLQUQG5 zv=WK_PN+C%(Fy>(Jbx+N+m?qEQ0W~St_h3*Pwk{L7PLdCkHlR{6+rSp%Q!l7xu3rY z+Qa%4OlFJoB2ov85oh+IymDgGCuviZ_KMSr)BqG&wjB-@JCI)78&~8QNTRxZUdfeh zhg%4!7{@e#LEx}C`nDcsI9ObPz=NQ-eV+ph_<0jnASNaz<_DfNVK)kGW#s?>002ov JPDHLkV1jb>vM>Mu literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_closed_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/branch_closed_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3849a7ff020677c35f8036ac33660edf3202a81e GIT binary patch literal 867 zcmV-p1DyPcP)F&d`ILRZl3rtsJ<*!lN_pz81Q8zrGOF8R;q}kE z&d>AK&j!~C0DzJoMHy2701<2696TQG`q|)aps(*pLd`+GQBV86A;DWe8$zzYE1!EV zsj6FzdYbNiCc?vV2phqXo2SMZXrDo=(xLmVi1Lw+DpG7BH1K(gvw8+VO=_J1yNaFF z;}gM0qayt*YKzC&=<6Y(;~5QxilE>9TBH|K0ssI__k9E?V;@LZS@D}2t_e{-ObY;5 zen+s{2M1_ zJRtB(aOcUkLL@EyAS~Ve8T4T1>Bpjcq$6Yk%3NMsJc|1Owx!k?aCzA8?h@f)IrvY2 z$D?r(gxig?sQ$`uAc?&0XQZ%UclmigDE_n&0+PT?)CqI>s_GC<+T+=F$*B~ zZ;{xCh^khOb~Fq5y`K%P6ObRVB>}|#yk@|ZMTys}mBRy^0|*857z646OamB0GO_=q t|Lhl@ni7dbB9TZW5{X12kw_%j_zhW`+6*7@B2NGS002ovPDHLkV1i=4iOm22 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_end.png b/src/qt/qdarkstyle/dark/rc/branch_end.png new file mode 100644 index 0000000000000000000000000000000000000000..f92994650dffcb32e82f36826d718291558880a0 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp|x z;usRq`u5yLUIqmoX2+%*(rHNxPfTu6>|r??pZ_}Ac*&NasB`Y+$IJyB7#LXu91eVL qco=`g=cTVh$Xl-Gj0_Al4;Ze`;kBH(bnZH!fefCmelF{r5}E+txh*#U literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_end@2x.png b/src/qt/qdarkstyle/dark/rc/branch_end@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..582832220aa0916159e14c3417bbf95f8ba5ad8b GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_Wk1 z#WAE}&fA*@c^ec&SRJ?gKb6yzpd4{*mciu%^*0NWdoIMhpZEIi)3)6<|Ja$XFlUj2 skF)PM_4w=c9}<7LD<1s@S_=XNP5d^c+;8>2NTz|fp00i_>zopr0Q~$!h5!Hn literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_end_disabled.png b/src/qt/qdarkstyle/dark/rc/branch_end_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..bb4344c7854ebb1c449d033cf37ff0096b7f2f23 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp(s z;usRq`u5yG-U9|4ERIbv(xL%OwKHY~EtspMCp3TV|GC$E1R`Z4*VgPX`p3-3BH+Nl v$kM~E^Yua8?TMzsA7tv!_7^cSFg&Z}*~aO=sqh*P&{PIbS3j3^P6V~5ODMQeEs&XYbp=fS?83{1OQ6bLOcKf literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_end_pressed.png b/src/qt/qdarkstyle/dark/rc/branch_end_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..2020162f231100cb45c703ad6bc75ed3753972f9 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp(s z;usRq`u3bBFM}Zu%fXllJg0QbM0`~L6gAA4`sd}Z^DDdsXB;=_Us+?4`iGr~L!p6z uiNk|m;?v=^^DCdQ+_@Z{8@&@~&`-Hf%A9voTKPb3VDNPHb6Mw<&;$U_buMTC literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_end_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/branch_end_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5c4fabf6dbdd4257b2d83b14c2885426f5e0db GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_WL^ z#WAE}&fA-gyayCSSRJE$D-QXmUKN?T(RYU7hj_C)63QmmH$Sf`+xbwh|9>OH*M?bS u;9DOV*L|w^Yij5ApXuHYJD|NFFy{gDt@Z4E3)YLWfViHnelF{r5}E+>Z%nHI literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line.png b/src/qt/qdarkstyle/dark/rc/branch_line.png new file mode 100644 index 0000000000000000000000000000000000000000..2e8c72ab63678bd9a5f3d29818a1f71d129a7e30 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}`&C z;usRq`u5yGUIqgWX2UBdZ;GT&=414~Z$ELhnD3>@U!FbAJtocwREh*@;+L~EPRopV P4-)fq^>bP0l+XkK(pe%G literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line@2x.png b/src/qt/qdarkstyle/dark/rc/branch_line@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f07af31dd1a465d042de5981b7d531b1f68780 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;h~# zi(^Q|oVOPoc^MQKm<^li`&oJ#dOq!tx{;dfkUf9*x1F03PkodxY2dqH<-ndHyMTEM w-v!1f_7@CmnM)e3FkaG&Yc~4}0Nu*q>FVdQ&MBb@08*4qlmGw# literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line_disabled.png b/src/qt/qdarkstyle/dark/rc/branch_line_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8c47b3d0135be4123a0ff0ed5c95f4853da7ad GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}`>F z;usRq`u3cmAcFx1i=*13fCiQp1zV*BcV7QbR~AeCn({Tr?p|7rAW$(9IKZB&%xoP| Ry`B>!=;`X`vd$@?2>{>~AaMWy literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/branch_line_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9b868f2a5cd7aa3a76b2559dd40bef003a0a3106 GIT binary patch literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;il_ zi(^Q|oVOPo1sN0=4jb_0YaC$ur`yo;A%kblcEbf*&&U3bxoPn92fvjAdxq=+<}G{| x7^B! RnBhr~n5V0s%Q~loCIDogB#8h3 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line_focus@2x.png b/src/qt/qdarkstyle/dark/rc/branch_line_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..512ee13a25ee7caa1f90e6ddd8b1cd9696f92fd4 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;h~# zi(^Q|oVOPo1sN0=4jb?V?{HI6P_~g`ex1vc@wWK7UAUQ#<-caW3ye|hFBsM`mo!{s vv~qaOAiJQnf$xHq1AB(-0_H6=ljdLloXvUqq{ux$w=#IT`njxgN@xNAM;}U1 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line_pressed.png b/src/qt/qdarkstyle/dark/rc/branch_line_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..3ca15c5d0b97a1acc143844169b21a2428a8bc62 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}`>F z;usRq`u3cmAcFx1i=)~sfmR-!2Np^T?!5k=t}K@7o9>%$cQ36*5U3al9ALM!XP#+k RttJl=^mO%eS?83{1OS*#9*Y0~ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_line_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/branch_line_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3685531020c5d683c3ca9d5b394d006431b5cc44 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;jBA zi(^Q|oVOPo1sN0=4jb_KRvhAQb9AdPVY_x);=--x>uT5K%qaT9F1vtv3*QCCDE1c& wYne+Lt}$9Uyk?MHP};zE!ODR>gJ#llY{e|sHD;Vm2RfF))78&qol`;+06G^Y}D z;usRq`u6HUP6h=Y=Rnc#0_KHV`ktv>@+@Ij7J2e~-lr2wH8~^SZM);UGjPhMZlE3z xc-Wv7f1_GM|7SC6(Y(E;yVthsLnIhlnE5`vmz4mCc)I$ztaD0e0syiXFWvwE literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_more@2x.png b/src/qt/qdarkstyle/dark/rc/branch_more@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9c1ab07d0456f6d92c406a4e953677a316498ea1 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;i^4 zi(^Q|oVPbG@-_$X9K9e?+NbnQp6j4eNl){aH>^pK-}Q|reBL$x^Dg<98%{pXU%(LM z5X_*vK(j&Yf`|im2G;^s6V?k%vzRg%eHphjEW;uFl)2_f;a{ownT(&WG8r2m|Cj6? kQ^!bzMl9y)$Uope(#m~k%FI3CKp!x8y85}Sb4q9e0IMlh7ytkO literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_more_disabled.png b/src/qt/qdarkstyle/dark/rc/branch_more_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..29d99a63e811101dbc2878b769cf378f40b6d9bd GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C>ZJK z;usRqnw+qJVMpr{6A%taViQ)KwUW_I*5Fk`AbXEh!WG8Fd=drh8v?Qp)U&a%d#!r1 zP@buWhljmv?aa##>;5tFHzL%P9$3N5c88IHbsnevw%j9oftE0My85}Sb4q9e0O6`I AxBvhE literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_more_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/branch_more_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aba830362c3072046a2dcba5304ffa389101a128 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;jTG zi(^Q|oVPavd7A?SST8O;D8;p*VNKKurX!6#m!F)KxN-8yzqdS3EY?4_SnqCC^W#y?xE8RQuwG!A#gxJ5%ebXs84l^E%sHQS)b*a<(r|O@fiq|R n{@$djx4(gaCLGe!_&+e|g>jV4O%nPD^aO*atDnm{r-UW|W;$9z literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_more_focus.png b/src/qt/qdarkstyle/dark/rc/branch_more_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..20a6f27b83b136afe1ffbbd519a833c8319be61f GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C>ZAH z;usRqnw+qJA!5zn+X)-L46o@Zn6fi8W_tNxSzWHDPOR} zOO8+RK*a+WgJR~LyVz}5z|w*2JysAM1?&tA2B*2%J2l+hfi^IBy85}Sb4q9e0McSF AaR2}S literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_more_focus@2x.png b/src/qt/qdarkstyle/dark/rc/branch_more_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6f42eea8460aa29720dc37926132b380a9b8a8f4 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;i^4 zi(^Q|oVPa}c@H}X9KDb!;`cCc!9&5I*@r5oUQ;ue_BG#_dFQ*Yao?+!9#-uC&&+y( zX%ZSN z;usRqnw+qJVMdBij={+pHyk=8eWqkAW0NR7u!7l5*5Fk`AbXEh!U5R>POQc<8Y?HY uyK=}_7%T5@j5*6J$F!IaSs~93W`>=UIp(_So;?LLp25@A&t;ucLK6VKR4xzz literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_more_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/branch_more_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5f18f83415213205e3c9069f9ae6a74662b26efa GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;iH* zi(^Q|oVPa*@-_zu9J#=|NTuqLo8g@onzj>-;+Eu_Z|9Z9i%Kc~O zTEJ?;dVy&cQwF0ibP0l+XkKe6UsL literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_open.png b/src/qt/qdarkstyle/dark/rc/branch_open.png new file mode 100644 index 0000000000000000000000000000000000000000..fdf0f8b43db3ae12a28d8ce17885235ba0c30c58 GIT binary patch literal 407 zcmV;I0cie-P)Iz;K9-=U9k^LUOrOg8M6%VVLCuf*=Tj|4xbm ziT5W$wsMi~lGaa?lp13qs!CtLVWjn@h;UR^6}FMHfGk&tdu#1lQQSG#f~q_SunNjt zQND0MRjIB(&H>C&)K%i#&Zw-lcH;wb3t$1@4Vbsb{eGeWjYi{bQP;Oca15X-kW=H* z1Cl?^XT0B|s0#o!0sF66){f)&rKrCYYyG})J~z(OSl=5A233;Exb(<4PvbnT_lLj7 zjWcoZTjE?tAZGw-0PX;0fUFaESHx}<>0X(>(gOhC+4~hmUIH@z^}>uITTQL6%XUpQ z006ADF-0W+Qs%1DY}OyA?V1`%DRb{22!h~G`UGzQhdxet(?tLP002ovPDHLkV1h^; Btc?Hw literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_open@2x.png b/src/qt/qdarkstyle/dark/rc/branch_open@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..703cd6af36efbc4ba0d03aa04eb075f376123556 GIT binary patch literal 803 zcmV+;1Kj+HP)F?IvO7DoY!IZE!b2JaMFb`l zUBj$HL>@Xs5OoL%ItWJKMTojohoA%_D!YUvY}lpKo-%j7nKcMgVKGeIbzg^+)=|Tp z*){O}j^F#{&HsBl!?1u5LI@#*5JCtcgb+dqA+`z%+Q4<)eG8z+1VowXUc!pqB_a+Z z+-kJWo?+r{03fC-wrvgs=@)naj_bV#aQII{dh%mBcd?`{`SpPiCI|pp>jV=G0JPUv`bJ!AwQc*;2K&}A zsaF6F_)1d>e9E${)P@3=2>b*9fNk4OM5$%~L%z~(CN-qBZvEGuuItvbQo~qz_)O7I zO<^1!2x$NSV4CJsVSes77*Bnr8YcD9@w|@p_R?A(ErL>D#FrHq9}Cr02a~bb=P)t@ zA-w{nm|1Brdk4VHl{e#VD;~c=M8&nP&$w=@?G3tZ5VCQXmlpbyrB z)rLA9i^V1ZAe~NE*VOK~58#5Y1p|CFVOc%p%2?I`0D#tdKa+Y5pw3qsF$gXBe15`+ zRP`}%%vYZ!rn9zf_LnnX*#`gsqoZHrDzfkfK>d356EML=buy8N4VO7ucwd3PNhYIS zv5-H+pm*!oK2lKBREfg_6&e5lB$LV9%yjMqfJbZZq7U;Cqj`^MeyLQhio61)7XQ?A z0@S%Y2=y5X?WSq|taPSLp*XCc+r`Wkdm8^6gUk`fakg!C4k3gPLI@#* h5JCtcgb-qj_yr{=^ZA1_Mxg)z002ovPDHLkV1ni0VWR*5 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_open_disabled.png b/src/qt/qdarkstyle/dark/rc/branch_open_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..8328e84d72d7c6572d7cbd8711be7c825b21fb4f GIT binary patch literal 422 zcmV;X0a^ZuP)HDgY?~RN+UBXy3n`n+F63+a0*@@Z3De*Z+=n>S}yXQst;d+38X+Y(^mL}B^27D{=Ugbhw4xMQpc%+^=$E;p{oOZHzwr-zeZ*M>wg8Q=^W3GEr-MQ7 z>bA0pQfmOBWaBiKUdM2GT>}8Z@x`d1_J9_F3k6kR5^xo=T*#+0we;0I03Z}!7y*3< zbOQ)fmGTqCT&7TKS6u@D!bzu3e9FM1_WkI|LFT63u0|*tIKr|l%lZ>O0C$CJFw~&s QX8-^I07*qoM6N<$f;FbQI{*Lx literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_open_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/branch_open_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d8d0faecb175e3864a519868e40fc9b41e209562 GIT binary patch literal 872 zcmV-u1DE`XP)j{Wth215j zsmN}Z5Mr^W+eS=07!z-%@kWA?aA`vSBm_-Vrhhmn=$0mwq=-h!tsa1y2q8ug!I02W z_IO$|C(_LNDa}D)E*HR5+X!GB$=KI83Ej6LD??@y%s#4i}XJGMwgua2H zH$aqKz@IaYp>M=v@zD*L*5||KCvxvU6<>7eFz{YrG$pvV!`yv{;1K{w=khN)$5DY5 zf$%>>y@nqKy2j>`yD8JYxG3&hf%?GcDynY|4fKxAx%3_39|54?_xu*~bS-eA^ti%v zPTYxPrnTY!W^T&1t#sl}&9e9j=VVP3iwB5B5dv_2{LIZ2FRc5@#c$UFt4l`JBC>sX zUH#>WU&nrVkgW99{00>Yz_T+a`cswXHWvDOFGSTlvJC(@ckbt6^R~vp3zu(H1Fx5i zM4(}LUH$y#ZH>btBO~{GO(vW2I}r{6PtF(!gHKGwwj4R!dp*j|k^BbCCY{N*tI)~a zn|x?`!R>dBA2=`>?2^j1egg98-D$e7#{1_Z-}j4A_bl560HmARHmj-+%nyu4ox8PV zc<|s~0J&VQ`kH%sKS)d9JO%l1sK0w(xjL400|1iQ)>j4j4p=;MqGyZ6*k&)z70? zB$LT3QU(JrDJ6>{@rt6%7G<%}9i;BPkAVTj>)uVyXFNSUJ*RUZ2!bH^@01nDZeDa~)Y&GtItDIL}zlE2GFS!G5|KxZ93i4*r`<#XHavV8{hP@y?1pE)2Z zYXaB=8in`c#FO7;<1G(h9|5hv;Y*~xpKkxF0jFbnPOmi%UIgle*K&#Hus=OtoOoLD zF3(q{Q7-WecQsGyunlBBmcGfu_=eR;uZ%dH_JY>25{d16tmXib$jBhz_dls%Zc~yz6$Ad<)ze q4V@QsU29kEY<>NVK@bGNpYsY0D{=*p^zVWI0000(RCt{2)=fxMQ5Xi`_q|?AvLJ$>2#i)iK~&N>8iYjzCMhP& zBFYk?pGAuZqJog1MPLPPf+&b;5%@D#q`yt{1Lim|ftwZ?1+Aj2upl+B_iZEOTr14E zGeLdN@_gsKeCN9yW&mT1F~%5Uj4{R-V~jDz{4bbmKt;D!AIxg5Pq@<1H;kcl4Q&xxl_gtJg z$nn|6IuW#%ogwa7;OhQbPYWZ+1^`q)lpFVgOQFjH5q!X$2QUF12JkMlym_wFTh*oI zx#m~5YyQY5bqhQ+bzQ(19q!KM>jM!?5CCF5T0vj;0IUp^-cqbhHS*bPa?884)TM3% zSRX2Vq*#|~WbbTpr;6eUAYI4Tj?XFpPeP?7f}X^>RQsoy8#=YR*ij18FaJtlWfYeO zA{qby^dXYjGj;qLWxLT2U{Zyr1CTBOD4M!1 zsD0kBv-eRmN3#w{tnhFe(3$CJYAf@dV;u=jMBQiJ1^@tYPc;hE0irZi>J?a@-pLOD zu&P~i78C`SLGBCf6Ud|e4Q$I-k9i#c091BrUEt^rfTf|*U=dj}HjW{;Se+2IhU%jd zccmNY<+H!M4*&ql+g0Yex(i_S437*!+|l32R6hFxBK#HjolJsne4iT$Jea}uL8pk7 zg}6LWpaB3tCc)v)KDQIP{;NF_p877U`s(?zP<<8T31pENPX;X_TSApi$7fStf+K}& zr|<)q6iZHAA=nH+f-a;7oKwI1fACMLekiy4no9n5AI2DCj4{R-V~jDz7-P(T;yYh@ V^6If}(3}7O002ovPDHLkV1l%zTaEw# literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_open_pressed.png b/src/qt/qdarkstyle/dark/rc/branch_open_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..441c27344e097f84e48e0512ea3e389f6038417d GIT binary patch literal 421 zcmV;W0b2fvP)A) zh>hK>WTmFLcQYe-saaT9DJ2_4BCevWZIogq+HerY!jM5x)62Lop1+&;@uM& z)0fZ*&<`{R{_-nRxWGCogt&B4uDo*-+%KXKi$5f0mtdNSFi1U zR8UJm9k9`3J1LMa&u7|hLMgU^Fi8I8;XZP)KKmHdANU78v*MXalyW|X%bG~Necpas zuF8O6k@Mx`UbS5{4FKpJcRPzAxdv_wh@R$>m$i2Nf~fDGQPVU{`*Yp_S1V~n#B@xB P00000NkvXXu0mjfvA4MB literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/branch_open_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/branch_open_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0e43e8b733a90f3835db0d458e9eade622aab3e7 GIT binary patch literal 860 zcmV-i1Ec(jP)r4~Ya87z!ydVBMHll2RDjS+W448-s+<3Q2>V z+RkxNqtk08*n4NX;Cz<j`lv_wN(Ydvt@+klXNsjg<2fgHZUO*(C83KLj?*rw;{olrSU+r(7_L@DP zN;sbRP~elI!+WZgPmJ}(|5$9Q<3q9e8N!aLRW;wQZ|SJ^o;{~Am8yuu(_OBIpL;cr zye~j>ufT2B>C1u2!0?9FLu*3`mr{FyA$HRk93ji27dT`=yP~QMfx<(-pz75CHdmlDy zV#|rK4EJZulPSk$T-~aZk-#tsV0D#DzOcRdw10mOF*r{-~WDmEE1JrLz z1s`8k(<9L0x=sao|4L7?vs4{Rx&VMkBE13SJWyMFu5cZt2`cZ1lRu5}n(NjnM|69( z`@ldc`;~kF0O8n|bt2Apz`BRL_O~THx*qL>|XJ>cTM&I(>Gxt36-pkB6 z@UKhy1J1bz5%LCQ4dHe!Rg?>a6N6TK-#;D+P_vEKBJ2(W%Sn+a+d**e?Et`;a}N#j z9r&f_s|91Kp6C6{qiPt2x2~h8EXW>k)1Z&~ouKX-hjrJ`nsZO{C^}3v=bqJFL+h?_ zn8ZwHRapaAFs3>$fW<-~-dk4(0pbgnm+iw;EEa#n#qK1r8+jKwb8g)rp8z8C`F-F2 zIxas~0BdbYkpo}}AO^WR?in*~F^g2ys4-uX;*%;j02hWYQ6BdMg`K|wV682wvfCTg zqrme%&K+Qc^_QZ$DI!tY^Qo6G?N*Plek<^U`Xn!q>Ofq41z0i2fwi`jtj%Km!~lI- zQjyQ9YG$=QQTlg4*g@Iv3Ouo4_(DKtu|83%18qC?s3)lGtMa}#Gn@4j1Bgf@s++*& zn6%8+PYeJM1VLSd?U4z>RuE*fJ`(_d?|B~vjslq0`pf_$j$&%-GXp^TC@``CSioXr zV_NGIW&RzPJntJ&N==+l-7VP#v>V90Ht$!n*<6l`oeu&CCji$`RGt^WRjU>6EvHGW za|8yhM98`zdo|}|u~4Y~>EUKmv)Np}YPHIOyaOVGR+6=0gGq%P8m~O#lD@ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_checked@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_checked@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e7a6b1afebb28e00f68002787be4863dd9d1353e GIT binary patch literal 1238 zcmV;{1S$K8P)R`O*EU7s)>Bk<*Up;Ffv8fEnp;nifJ;j+ zAOWJS`VqKLkw_#V610>He1cYL1ga>PD!l}xmD+21L9kpl&f4A{!hs&E1luo%?g+2f zuD$X2Pn!Knd+^NI^ZME69gnRUV9Jy!#~I4fsKcza?7<}_{s_PVfYSh8FEp~r*$40x zz&0`6+cg>w7KyyHlTrn+Z2MgT{Q%%C2|<=gm%*QzhVkpm8YxK?%uId9StigHj^51! zz&wGrc5Qo!nG^r$L;-BqU1G-9#l%)7^iAJ!zDTT%D;(N>D^mQ7nN}3|4-La`h{%^3 zXHJ+|wQXAupk5&2bpR(v>cQ{DrNfv29cFFTaeqh1_5}PE_}*pHH1~=KUN)9x%_yq2 z!N5DA;%;AWo{bKSV=2(G2bVCK^Z$7N9(;OKZXN(k)7%Su?=paAq2l@By^Sy?!0=J` z|1r~QyWRdNh{djsMJ!G+NV{zJ*Jm4?FpW~AucSeuyhPKOT+!*FB< zRVFd9H==Fg1Q?m&)orw&gqYaJX0M6!fa8KzbpToDxo%qvu)^REhDG;P!n&^OJ9)2N zdk5^e?wlI%BL-gq@W$|W)n`2Jxo$h}^=mCahgqY5e*$nSruvi`@Rxb}sI>qs*S$_L zkFF3O=Ix`l0`wf`3^Ue>?x&UlbeJ`TaR71kF>c^7aT z=S`ong5ku3K)-kj*4xcyFU$EY*S*dqTVIgd0X^4k`;5l`u3|V>XYds@;72>IJC}NX zMb;PO7C;NIg5jN9QkFg^ut?+uglkAi1%TcL<7~?1O0m8`+Ebvd>wjcRg*3{s zzCh|@Fk>ntQl|928%ra~pw7Zmm` zkUbTuvA&?tm!Y&&sM7j^LIqeP@&biE24Q@W1;OzY`lKrB3krW7Za14fPf^YjXcNG5 z0M7}u=_$(jte?z^q?GjmbB)FT!24zNH7T|DDqJOT0_=wmm{~0;7U{&qz8`H9C&1J2 zfoG2(W839su|&RCH2NwT+`Bf>ZW%s>1$et(VJ_dU5#A zA8xt4pzk=#uf~Q60N~}8VcdwTNt_25&E^e&mx~Lk6d2&8SzW)G)FA7osqX>IOAW1f zGHseV%(l66c(Llbj@#x20G>>;ZEnhxDaV`t0Om6J(~hb@2><{907*qoM6N<$g3+H> A7XSbN literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_checked_disabled.png b/src/qt/qdarkstyle/dark/rc/checkbox_checked_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..e3cb2f127c00859d32fefd9e9da0349efe2ab982 GIT binary patch literal 731 zcmV<10wn#3P)HuaD4eE+5*Tl` z63k?+T&XRG!PNvU5|S(@C>I&VxJf7n69WIVsg2c6-Pl4YXyHbfds_J3^c zZ}r}}=brC--?^7}FZ}P2;=t7#@oq%!0$o5;Ks>v^8mj4BHnZ#<2zg&3c6?Zn7eG7E z5D+;|t#(9iwsoA_+xYr%)g34}5Qz<56l2~4KT#dBLd?IN&HM<0{aP%3%H-)qWE?nw z>Lu5Sx`Gm8Mgc)}D3{Gl2SMz@`H<;|oe)u;IW4{pV0rSo0IU%6L6Uo+`F*$cc{k=2 z(Bx5jELfa-{@r;z?Z)a#fw3M4; zl^gVfWHM=~;VC}1Z(sseKYzOeT=vEk#{P#`forsYv_D-OtOv);FW60NA&dfx)zpcTfb z4Y~!oWsKUjTJOU5?|5-8^9Bf4Oso=K2X^7$02x&AV)XP6G&+wve-f|;VDj`HmjDUX zyR|>KvEMCFO(W8W$aus~i01d_J!iNhp{IYKQ9|{-qC5Z$s_B9#Z(_ub4~t5g01qlf zFeszB?9_cXaOh^V@#WJ>TgTZ&M4Et;1a~{y0p6jS$YnDx1FHFt;1{nC38>@aaNz&| N002ovPDHLkV1hVXQ0@Q# literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0c8c28a245d8e611165f6719580fa9fd9e382d86 GIT binary patch literal 1334 zcmV-61y}RUF5^znNJ~dLdOBQfYc|n}{K)NN>GtT!BL? zk-$cc&@|bNy?U_+5?LTIruF2_=n@(wnr2%tgvJ13HZ6Lhk{Des#RFjv7;M9-S=gDM z2lmPA?Cj1g^JfRy&+X0pX5MeU`TpK}GkF6vXwcv!Lw159k))!u%7nXxowm75X1ri^k);4V{fTat@CAT&7n1Z5%96$(EzYKvszu4w?$AA$ z7y;o9fHSV<<_~8;7!J30?rp5E{Zc8Yq5$24i4ib9^(HqTA&Q3EJM$asYb&Ow%?=iA zzgTjR@r;Q_C5aw1V|O#1POBcIdt_p7mcG_1U1+cPykv&aPZ#(TPa01x1J~59ir>C+``wNr+ zHCTUj@9DYE-RLt=0@$^_1iEhLgQpz=vl8s-k9V+5>o3ft{&cI~KscZt))%nR{#sw)*a5wsp-Y7k1L(5$Ea__ z^Ffe_#(MhW9meDJw!Xlz0K~Xw5z@pGP3cP^2-X)k7C@ENTLAVf!b(aZ2-X)k7GOC& zl?7qkDo&I_P^>R-WenKgX}b-^V~emRmgrlSq-g}e`T|!3$YjO~#C#prrSLky7cF9Z zvA)2ySzvK?@((+uV1-}S7q~hN+AM`?_-1{9s{+(e3TF6feSzx>p`(_9-_{p+vJyN( zDfn)EfhPjgSPFHqzQD700lTG8FY60DeHpS*3U#x-z*7M-nel=o^LqfyHd$;+62D(B z>kB-89bQOJK2aE#8JGv~9Kdr1<`u?eyPwRw#FwwaKhC7K0KDx-U$qj5ufp}jOn|(; z5sSsD?I#X2Cb{R0F=hhf^o?CKpLa7UKQZP`z?Lz_On_B=L(}+*%X#^RrqWe?n^8U` zmkGdxyZSaUO+@<=t?sAiEz!P2D}hTEV#a3!Oav(Gw9Nrn|L*|dv>d|paS}mnmM+~f zPTAtKl~CJuc~DZ4c|OqF$;PE4GmlynRewYA2%p;34lb@NLt2o8|mHllc+}@c7 zQPjKCJck(=S(=%=RVkqA9KW%?wi15zjbB03g=6>M5M@cj(9%rmo2pTEZl(Wij)1P> suIs@4Hb=k~1CML@ZLUFs1}B?;0S^@mnVy2*k^lez07*qoM6N<$f|$p70{{R3 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_checked_focus.png b/src/qt/qdarkstyle/dark/rc/checkbox_checked_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..58982ce87b318a62270413bdc4e395e373e261fd GIT binary patch literal 655 zcmV;A0&x9_P)Ff`2%9LyP}AKT|$Z^_y+=N zmC7V#2&q=EFknzYLDB@lErJVn0YS36mG}peIzhoAmB}27owux;+3Zesw9&76+;?a0 znRDOFya)d}>JF6O`(})n5oN)ZJc<|&G4%*l>a+UXQ$VTe$KWSv!g3X0vRSNJ z!f#`|3`_$=?JQ9Sh)$^GS-guHfJ7+-+5*CY%ggpOnlt*A497yO&?EQU6sw*Reg$Ck zpgE%tXXWQApt$V`{qz=M6d)0D^{i{6vnDgK;z-AS6N(Q?ZURczcm&+(j7eJiD*}q! zo=84mo$S=V@bb?KNVDD?xuAJg75BTm?;`BCs#C3xwAh%|-XQw>I*=3}2gYS@wd_vB z4PkvC+iNIBb?n!y_#Qy2^%n-SeqaHT)@*NdgzlEF^UyJ32az;~n$y|?E%lmLq{U`N>oW-eXnf@bU9Ctsm-U$iq_$!R z>$3}>)rv@(1NMRaNSZsZ^?}U44oKSp!y&Xbka^v_n_|_Mli|TB0hl^K zJi_Fk5&*4x+cZL;-GT^JjHi&-i&YD#b?o7WB6;#j;b%Y`p-PxbJD60+bEot>y$>dV pa5PJ{&STy4=j6bqk#;ou&o8D<>#ezM%N_s#002ovPDHLkV1foQFx>zE literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ba33ba4fbca7c1be6773c54b4a8f42b118baa911 GIT binary patch literal 1269 zcmVEgPeCgA1CnsEgJWEzr4N7kyJ^ z=FN2GF?W8{zEAQNbMATXo_pT++_^Kk7iiF+!A?e^ICamkX>A236x3OP6bbAXV0Y5N z)dPVi0z4u(XTZ4HQozmG9$63jUT6YJlY9%{HvnGM5@~wO1M*>|Uw+=o$p~yArE`LV z0H?A21`h!30H;egH~=#6j}A;g=OhM1_*pWsr3m?X=_h;~)a;v?s_dsd<`s$z!NjdY zYgoAcu2@)CD@)oV zPk>UHtxy~T@utH(zo#Hayc1(h39PN)1l%>hY*IehE`tYvO0O)zkaGZ59Om}w*j&^k zKtY{#UQ=ZFZomAaKg?vQ^vaS@hMhL=*Z`jd2&CvTn7E}qx|C4Om~va>b+1oN0toDP zULRV+g6_c5!YB3vULPL?xL0_2o9*kt8@u1?HFzPkLukr6fGBj8*`|~l0_D_(h2y3e zqjyir-*JCC_X;SD^RTjb8!J-7{>0!5;za^J(6vEcHp; zK60Ia$IG|`pyt-~9624gkKE1y#YuJuIFfWfxl};+44X{wI{?jF`3ZPEZeO`fK)Cb) z08eQcSK{`SyAp^jeUXt$pUlVYFINhPDt!p%_Pm6zbo8041Voj-vgBfv7oJhbO$pQ^ z{ohW@pSt?Zg#xmWzKs?Iym5oCSX4us3lrglVHl(LdgVcs?>}C~C6RQcZxdSqU1hde zIKlc)F#J zrxfxaeVf<`sPxG^DW8TqR!bo-(znqv2kduoS%DFl z;5y*feq4sgU~*BV0s$GQ^x=yjhp309z6Q{)HMHc3bZDyXV{_Fl=Lhn5Y!1L8!29(a fn`_XZ!OrGCw>RmF`CV2H00000NkvXXu0mjfWxP?5 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_checked_pressed.png b/src/qt/qdarkstyle/dark/rc/checkbox_checked_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..f104bb240315fcdd6104f7d5dfbab95df3538510 GIT binary patch literal 704 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 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d32c78f36c2aaa5ae15b3f4fa8bdb3ee6278630 GIT binary patch literal 1003 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|WD1 zPZ!6KiaBp*+vfxYiX7Yjx#Go=8!IxEj;(Ai4aknY;~^kpvSgVm-?bYWn+uH-CtNuq zareqmMjunXW#9Ze_=08|gv722WuNgXA!Wr!`MevS`kXJ?$?->3-G98TsQ$L?`#Xor z_wOlx@4G`hKttp$&stSY0go5I);YCEq%+8{K49N)H8k~XFjD}7!ReOc-tm85=9E=r zZuMI&C15AZy|L{!!!B8Yn@$?;Z1LxORF+GnR!W6(@E&=j(8F-!?TT&JHb}P=$KJKw z|NL{Y{%h5%rV1tk-OYt}Wpi~~G;UnI8$9d$`Lj3dwsD8W{q_l+@UgjbeU_B%=Y>Bq zOG>u9X}VJ?-0NoR`s14<+kBN}*$O2y=1*?iaQAsYvV+2e3wy1(?0rF4%NsZ3(lwk?{9@I~1?@F1vh^l}+`G;p-a=(##w7oLjGw@#Rcn zuCDXv55dK=8}7}LnO#>`e7OCQdVA?sp4DY+-=d1&@T|D?Fn7z%eUdp_uD^+U%afr! zg>e(>2{%cF=!P8Z%o6pk7B;<>gY%*pUskFT8IBRw||(5W8F5 z(~zrVdgQ^|=#uw_6S;EjIk_Z1RA+uPb=W^g=(5e1?8w8v1dSA|Ek8|8h!I+;$aHYW zl({lLHG`ag2%qR#D%a2>%y2KUva?8o!YO< z8K3-T<&XtNaju&1Ke=h^>Ew%O^$FAHXoi~C;qbN?T6aWw{k zVjJUmyAr>zc_;MU@O#;^)w`FoELu=~DW+Yr!@qZV-Zk%x9mmc;f1bAMn|vkfqPU!0 z)y`9tnVW+jpKRydd@blyO>SSqy;Cb+^Oge{=Xv&IKD#x?X< z3nRE6+zr^^A}=r?rhO9?2PA9z%)+i9No+B8bih8V;?||kS3eZ@!e^I81NAenWw?!~ z3%-FbS+AWmx-ZQ-@;!apHCGAK)IV6+O_q+}7VRT)+PI zQZ`2exeF}H+6X5xACheEO9-o#Hg#HtaZtXI(^_H)|H^P1_zn;avqT*rdZ1UP`G|S| z5^)F&0m6eT>)0phYD;(daAgeOqf`M@03Qx8|58GH<{jjpz``rn9$@`Qn>r~xA0g%&dRKocsU>5i~(T!0NEUkSpmS~+BRtj3_qd>b&S6ucWa3S^q$mkZ&JSV zhVT)PMW_?zCN(Ac%FW)S6ZL2l3>DhUy7d`2YX_07*qo IM6N<$f;X7N)&Kwi literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d6403ca424b193c5f80c7afefd7aa92202534086 GIT binary patch literal 930 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|Rr2 zr;B4q#hkaZ_xcA1O0>`4-WtK)J6A%*>huDYNoIL7GGXZuDvv`y4vB~=DFYJ&HH!nzHNNw zdB*m`8z)aZ8}e%2)oDeY#-duyO(mLd#BWU9vZE^ChvJ9Gi$6tHw$Ie@kC&f5|NpN$ z_Pi(jUwK~GePCh46tjNU3EfAV_WX%n8gf>B)uie*ix(K@?0>>&<&gd<*s3Y(ta$9@ zhC3?CN>#R!xxOx6-TrY-&$jI=IrjRS@xlU6*L4$~{XA&o-GA<6)fy*W$r%^EEazd5 zcs^xC9P_4wQkR5HWmfUL06Ofw>feU_x4GAQoDA6LAC?q8kKt!#?&3xK0e(LYb?@F> zq+(+j#@h&VKFjex*SDPd`F4_x15lyINr8Y*t=4<)Foj44EHrwdzxu?D*-bT_@oAex zey6yG9Q(7eAWtB%K_Rx$Vb=4FtFwishRtJDE;5N(eu|;>@4rt#w-s_{iwWMkeYjMq z%Aufr`_;7HRUFyW{T2FmcT-+ZwL@M|dtfc2jN;EHANMU5zAC=cQ`Ri^%!!6`ns?P-)CLRoD!teX zWT#(ho5(0>!S=>5^YDbd^V-^Oew@5uB4cU=cTKmaw{p#A6O*2ajNE@WtvbOv*~};4 z$swoxYi4apv|)M1Wz^@Pzu~}pRjo|3X$SA^Z0eb9CU)BHKy-ia^%UtHo)@+;+_qrO z;oi_|d;lv`K_=kGLw$aqj9ryQk5t##&XIPJpY-dEe*LKeg}ThMicY_acKEsQU-;>e zFgN()sVupbrhe?ozt*ktD^>V8O&ce>Fe$2|QUSJQFeY zf!~Olp;o(cxc&Cr59-rbpB}YBffOnhFono`cPE0bi5NLR5H)KX%Vj^n-8dgoj%F+Y zc2HdfUIG|ym5>Aowb~Uw;k_|}M#V;vaL3$P=fL^3?KkD;=cO|n#p8Z~d&)#$B5>~l z!P^RAnbI3YKLFu7uH6*m{jbgJ7q24E9Y~}LGm4f5fCGdTwG!#V%)kQUh^IhxYvn|c zEYKWa?WQ1Rb!+9stLWA<;PlY5kHh5eZox!gA~0S7p#k;f z0;y36bS^q68%4D{cJ(6?$)oxL6)T#t#0VOd?j3H}#24469e5GwAd+{ny@k%hB+uy1 zM&H9E&^vov-}^Bed;SfG2s{KH_(64g{vDBYebe0aW6ggjmjFYChd-R4{{R3007*qo IM6N<$f>ws&v;Y7A literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aa7493edc603095e2474b6c96e954c16f83b8907 GIT binary patch literal 995 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|WC^ zPZ!6KiaBp*+j>L?iX8v{{HZ7VMlCU=h>~^AqLY;FwuH%wn7_WSm`pZ)y) zegA)N_xDM6xHUw&Uh}9<3VHecwfksDdvai}sqtrxM?1n8rKFa{&fa-2$@zJdK^5Z@_wN(~Emm<pINR^MoI4e0Ia9IVL4C&J$)YmkN4zi@(Wu5qeg=yY4{t4*d08Hkip*ihcYm9?Gj>TE z$C*3(tnO{q4|4t?%F$EiW3ZTQK`4Vxls@B(M$@z_EN<3nF5Q-!_$=o3w?0piT;Uk7 zjp3#Sa|-u_ULyyr%mZp=Ie8`~KF9C+Ro~oru`cKAM#F}(Gi%S@N!Yk}l~G6Ux7=*M z9!8!x!|l9tvt_SMHB{1DeC|$~Lc-ZjLkH$%i|^Iu@(l+WCL+C9eY?#sFU zxx4>J#@)YAUzEV4Q1Jbehx`1yTX(!}n0hh2mgSw_{53rX&U{I#T=KVcPfH7*uVGK) zWMhl)b{Br%r3E>Ba&zA7+ShXY*@m+Y3Nw?7xmq7peHJ%gFSllj;cO0Iu4V9a^>bP0 Hl+XkKTa3d6 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_unchecked.png b/src/qt/qdarkstyle/dark/rc/checkbox_unchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..e363ed6200510a57a017a3e012489733586ffa18 GIT binary patch literal 385 zcmV-{0e=38P)z(n4Gr>L_!$PQ1z zGZ+(}fEVa;1Eg#$)R98?99py~KZCY$@SgGZCg-$Wz7PI8Qa+f+@jc1|&;#6xJP9yG z7~Oi_+u49c91m4_1U8@%Dj${TMXx{tpe@4i#`B(!0_MwQpS`{cyzjQ@!1w)CCGs3& zOt;x`CJJ{5{lk}NeBIb<2yE(*1Ngqb+HKPTkfMZ#^G4xL4>YPnUW`D9GS_i{TiHLq z#GVA`oC^38Y=8~00XDz}*Z><~1BwAjHoewvbbWazM9gNh>t@TD01m?VTU%fe$1kcp0VzV150Jm7ft$a%b9ON~kgsMT+34IUKmQ?X fvej%{Ud=3@@DOG=Em^2!00000NkvXXu0mjfoS&pw literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_unchecked@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_unchecked@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..520f5e2a2ddaa5dfe4841068101232f84890241b GIT binary patch literal 847 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|PUo zr;B4q#hkaZ{r!alMUI|d8{r(0l=wqAcy|GF>CvEltO+WDE413u1AO#A!Ue^=|fxx3f9>$>GVejH!- z+V;Tm#-%(R`2w1g*2L_*Qt#lBq#(;7$KWCDZG5*=ZbFUNR$-;`1N||1Q3~^WE;I(D z#g-Sm-1GJd*MuoCd9MXq^BGI7KYB2E%IiA5XYD*1AVUg-3E?T@_=nhnMFYz)!!KUDJ|Fm7A)M}`SLYUK`}pMG*N z&`)7FQTSNv@vdfX-V4`7V#+^oH~8o}TuW>?aU#<$Ec)-6`RyGOj=aiLF_SsNDe182 z{*R`+Zk^d;X}m1#O|KQ1&zSEC`@MQMPa1Dv{`!Z?1!p&~WpH0OCbdABVHc~-Q?T!ko%-kBWiQCLitU0*mZA-!ADGLI2H@?Z8v*lUBHH8UpA5?`be&Y6) z?V!ZTU1?lVf|Hb*HeU8fHJ%}SRbyvT%u?I?^K)8uq&@ig&w0k&$4aLU&f%WD)bY*c zqA7k$gL1E$%siVWd!o0LL+ENi?b%Cxk7b1BtY&55>?}>OIX^$E{joz3kmeHMZ~7dl zY%-Bmmfz=xyuduMlOey`%cIwJhqxrERIg6AlZ}Y;;JaHH_x%9NhxpzzIx=tGpPgrF zRQ&Klh}ryloeAa{`xmZcI{4F@-*;xn@n>p%zuzVwW?_#i%Hi9@8)Bxo>5gQ-{&i!s f^o%azf;j5O1!3RpF?~@myg;CY2_Iku0_hGv`=*jcS|)<^1mSd z!g@o1JI6zdDO&ZhIgcOw?KL<5TYG8u9OnPFn`$4#$Ia)w(@@ngInbX+NUP-d`Tl%% z#($xkm9@4X;OPjkGg>L$#~`k;u;gC+ym#dcQ>!+o_3Yv5i4>DsoLE1}^QYF;s@*-2 zJR&u&Suf`sykt%GVL0=10V19P;%c?@Pw@Q2~xJCH&)G{Ys^E@p-hgH+`pZ06p0z;O;)78&qol`;+0L9gsrT_o{ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9c80ad75a564587acf3f9c57d3ad56067ff535d1 GIT binary patch literal 868 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|T>| zr;B4q#hkaZ_xlG2iX7j6Uz}rt-zR0JcX|=x;l4g=N{d&pDtlgBveZTRg5W= z?^|?!ZuP_`4cz6-F8T}&CpNx*vFc}1$r<*$&3%GX_I_abwCCz1_J*lXukgw4(_m$3 z4tgPDc0E)gV9zU?O-FO@Pg;|9ua;?oE~~~?-UBCX`56QzmYV#Z`CmHd%)#UnF%QxY zEHGEt7|kErd*sB!F3b1n4llEEwyl1rBVid5^Sh2MMq>@*Ev79S*)q5<9Ftn0>mZ%o zu#F*?8iF5~SfFAU#Gl%$AR}Af@#$3I!$~`r9b#DiIz!N5rCCJBPV4W&y5%By z{Pr)!C*BNdIAK^2al7Ga$u5N>C6O!6XS$n-boMVY?PGSH_#vPyBq%g&Fhy|4Mx*S@UY%>e8MQb^7YNKQ|;g zO-T9hgnjnfwpk1Q-?!X<|FO?PuZ!hpm#qvi5nTL0G-_>T*9lI8;%CcN79H9c;lMTb z@X@N@igQ9@&6986F>BD}m@Z)vW955$&e5cuH~ui*FMhc7yz#P&z-+_d>FVdQ&MBb@ E03v&eMF0Q* literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_focus.png b/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..366b868dee695590176db0f87c1e0bd6511f86fd GIT binary patch literal 387 zcmV-}0et?6P)H2BfwfvlFRP$a zjFmC5HgPt<9%#T)lbLG)lOTeHnTdt}mhZp(d-DD--i7}zZ5NVT_f+#akN^iI`7D9d zxo*-kJ?#bP++`!A3&Xo$W_T;ZUC=bdf(G*F^(4Cb25>ZWKgW-V=g1nooN8W%d7tHOK}0+?ZvT>uAVz4=e_ z>O;160sM&qKmZ5;0U!VbfB+BxHUXA`X4QsTt@?{y0I4DFPTj7`e0_I}NWTF%*Nvc& z$&)G|IuAa~TcydBMgJ^^U4Z!dg7Cq4iG002ovPDHLkV1m0=pceoD literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png b/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4ab217356ec7678b69022302d17ae5d1521590d4 GIT binary patch literal 850 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|PUQ zr;B4q#hkaZ_xg(jiX1&Za}8_GO6h%7(veb+k`zr%=er4QoSeZFbtry;=?spgvpf!^ z>#W?UpkksEa!p5Q%bleObCVx#vOdEjue7_|d{6w=?{}?FR;s^0n^UO&pui%}c#l`$ z^<9&ED|;HGlrCs4lyz8i>ej!hN}Y2WVmnSB_tbg!#jyUSv$(W^;pR3&r+mgOcc)yE zDpV-QS}i}{@ztJ1#k?=(U7zc6YCfw)oNVn@r_V=~^OLIQs2AS+k*s65@zs9zA4*eB zdi`>%viJC5uKTrq!UNAb?UTnDE=}b*F03g(A@11RmK(woBCkp;>~CBeFQmSmZ9~Du z!d2WVX<;9yT;XZh{WSH%&ua|!t*4dQ{?tBvX{}ZMFFo+hEx9L-S6#vz--&KjT_MZx z-OGFDW0m*q@jY=r4lc8C6R3FTS#vjIHhaTcM>&BS;fSn!y#$LGaYKeH0Sc$`coP8cmp?%w~|t-zYKScaSbkg6cFSACIJV|j#buIb}9a#n|4 zz7XZ8k$U|$xLnq$x})aXW1bzM7R+l{BOdc?5KHJaJ`mMldX6ER@ftM*h0`5Aerdn* zgRS*j0MGNqxkWDPgnsB=ofztT?p>n&oW5-*8Fx=@*gIjJNpQe)kCq$JeVuy?Jil~w zpKjFnn<1(kDj3dOb?pO73`=lTRgd!PC{xWt~$(69C}Gct!vK literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png b/src/qt/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..d9a0bf71c7412b08d6c9b2baa40e5832794c3fdf GIT binary patch literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv(mfq~K0 z)5S3)qV?_djeds$M2>y@ueq>i8teRp+{~OmnAAS-tx=nDP-4zi$1(xQ7u+9sjvY~7 z(aG$6zmZi&v+*&5X~Y4?+ZGl3KW;hs-8;X%`oVtpNzGm6Yob?Oci=4udNq^zVAPWD z&*JUmSwo`xV_T&Y7=@I6&GXuOigN|Gh|8AWuj22%Wn8t^(RreJ%k++#;z!$;ubh$} z{LM{u_EU+cHM*BN_P2cPbg??1)Lqojd4HbUli3bag5Mq~&VD{u%43G>Pdz8aD`)?2 zWiJS_{+zFLNJc}B>5nJR0R}iKWBh#ft?BI*j~F&PH!xh$tzH}y_B1s=M5utZ$@W0h z5_XZCX^(XT(#83go1HdHSnu-dw zr;B4q#hkaZef@<4McVEMUsNnv*~0%lZ^PX!M|%HpAM^;iGb5~X?Iwf9_ywHYzR}8W z{X9(=|FOPXBF&|JUBt75(}=4!cFUB+G%sx<+uR-Jv#g%`eY&Uq{afBUMjp1qscyF< zMSOKy);9k0Wcto{kIjHrVr(w z3kF!flA4lzdY}2vT{Hf%EU5W2d&)JYSI=wSa>l&=XIn3J=$6c@3CZsS?U)Rzf~MR} zXe#XsE*7}+<=S48zGHdTug*1R^UX`X?|)$FA&v`t3wi|?$T~VD_wXJ8DIwO4+;@=uDv!zT5AD!&=}W3|@S-D=cYe3KtCZT5t#~4D`&}ho#)VoIA@@H|yd0{x zPTa`2?)$viB|RLSPEi?$RTY&ca9m8=9?HHl^^^Be*G=}9-&`s`y=-NL)^vssQhTqN zxP~aqurI$nWpYN6VovK?&LB01zN`7M z;usRq`u3coAcF!A%SN&Pax;@yQe^s%9LN)85V%%-&X;dZiVVY#L(JwAn3rz+qP`HQ Oi^0>?&t;ucLK6T#7a&3a literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal@2x.png b/src/qt/qdarkstyle/dark/rc/line_horizontal@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..63be00c16164f95fbc46cc18c95b355113450966 GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP|(`b z#WAE}&f5!&oD2#AEC;XulXdO>q4~riO-Lu26{r9R4*WlM>-jR}NoiIJXB$c&Vhjv> YuK#OgUg^NQMiC_9>FVdQ&MBb@0I^#o5dZ)H literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal_disabled.png b/src/qt/qdarkstyle/dark/rc/line_horizontal_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..941f14a3859bc35e7616a391a976263c5d2552eb GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5D5&k} z;usRq`u3b7BZC6Zkqx~08Z%h`L^DVpS2ny5#>kMk_xYVC2fU6kHt5?(y PP#c4%tDnm{r-UW|i*q6+ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..972fa080044aa8222dfa5a7918029b49832e265b GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP|()X z#WAE}&f5!&oD2#AEC;XWscmTbtNlasi9?!@PBbe}2@o9kf9%%tWy+J%tQ5{Rlt9E7 a81`J>mB_>#xxObKB;x7n=d#Wzp$PyCA|>zu literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal_focus.png b/src/qt/qdarkstyle/dark/rc/line_horizontal_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..221fd4607f550b911111bc52ce98cd12d72b0f01 GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5D5&Y_ z;usRq`u3b7BZC6Zkqx}TJLb7K9Q)|Ovn7zHIx#fmQg$xh4`7du`dY0AVHUp@M N!PC{xWt~$(697p!AiV$p literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal_focus@2x.png b/src/qt/qdarkstyle/dark/rc/line_horizontal_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7e6505cae37d16066409cb58f9c1402084680a20 GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP|(`b z#WAE}&f5!&oD2#AEC;U#Z8KX`$7MNTCd=tCMxX*9_^^NDx1BFLmdxbyFjkO-h%qp{ YH*L#edUes+I0+=;>FVdQ&MBb@0EK2F`v3p{ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal_pressed.png b/src/qt/qdarkstyle/dark/rc/line_horizontal_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9f9113323f8d5352881bf3280cb963b13545f526 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5D5&M> z;usRq`u3b7BZC6Zkqx}Q6|>}dntL8kl*m}k(6HfNab8h^>SKlj;&S`MnGD|UjGhM6 O#o+1c=d#Wzp$PzGR3Q5R literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..465680c3b0243987662baf76b0999c61237fe71b GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP|(KH z#WAE}&f5!&oD2#AEC;Xqlx^y7{VP(WV9YsfEfY`$5Im?)ep`H5(9>9ULYjjWM2vyq YUbfR}CX>s|vI!s&Pgg&ebxsLQ0C=w=S^xk5 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_vertical.png b/src/qt/qdarkstyle/dark/rc/line_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..6ee62c156fd1947f3d3821d6b25d7e259d517c07 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}{5K z;usRq`u5yGUIqgWX2UCg%Uw2b$TH2_SFhx*bL!Q}S2t_+oc*B$REh)|`0Zx0H@-Z_ QvlJxg>FVdQ&MBb@02<#TM*si- literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_vertical@2x.png b/src/qt/qdarkstyle/dark/rc/line_vertical@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d65e74c6209c87034ed09bdcd73a655073f83cdf GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;iB( zi(^Q|oVOP?@-`SS9C0|L;P}Q~q{-FkG@E;3dHmj|8x`06j=WzhSIp5LJLg{~QwF0i zF z;usRq`u3cmAcFx1i=*1TfCkn-(F#fn?!5k=t}K@NHRWrL-MzFLL7-wJaDe^EF&0y) R&Z&AJK~Gmdmvv4FO#l<;A^ZRU literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_vertical_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/line_vertical_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b052de522eb00b5831483e57d0b20cefc5848357 GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;j-U zi(^Q|oVOPYMH>tljs$dV*E+zoX+s0kk*T8W^A&IA?b_4BYuI00`@J~cx#G>EFa9D9 z+!gTe~DWM4fhL0d6 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/line_vertical_focus@2x.png b/src/qt/qdarkstyle/dark/rc/line_vertical_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..24a2b771c30a916357902567cbbcd16ebdd0f2ac GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;iB( zi(^Q|oVOPYMH>tljs!#ne{Bq?N#NS`=z+1yZQtqB3l*+?-E+ToelbVCrr&=T#w`uY z7@{148FUwDHi%siap2D2TEJ?;dVy&cQwF0i&7^r#99bGpKAE%@=w=2_S3j3^P6%QJSU(5G!WA|nIKnC3f znhjzXL>#y?xE8RQuwG!A#gxJ5%ebXs8AFsqFs-DYu|_;(X^3fa-UDuM9cu+l_9 z^P`|biUd=VF1iRTEy)XO+in6&v_go$yP!okwS-KsN?Z_O3T1Y8X5N`~tHr=dt99o6 zcQG^TJ3ISbcmA)Q=RD_}|Nr?s58Uan**NzP4Mm)Mu-VXRun1BMhJzTwlmq8n;Ly_+ zi6sA50fX7>G7Exku$42+d%;0_VzJn_|4G2Wz`%URtv!sfrDPfg>&0|RW`l*An&G<& zg`iL=^P^{>#lPVOp#pCf`W-XvUn_cV%Iu1Mt3=7+riMD*U(kwrfXh}{w zn|%)P4iLxim3KDA<1LqFEFhD~#D$#~EC7z>NB?=Ty}kYSsffoTnM~H#)Yl(EYy)nX zf)$?UU7S`xGMSuLQ&;~zuoUco7j1dX%!1jFmm$g0zP}r+%OHn>WuE5^hka_s2i4X! z928m#^iD+HKQt6^^ZD(DtrLoZ1&EB`ghOy7Okie`)SdDDxUlV*dsNbDGt-1CFyQ;0 zj<|pr2@1E`+uGW$hi2oXeg6%xw}FO9CVd0+rWcKV6edX|5_OGD^Dlvxm~6f0MNXE- zoN%-&-UE=?{_*4)-~Sw}YYK9JMz8~EKYK{h*yK7oIz~;rRm`pK@YtAubUJ;%;0fTj zn}1yYB%C$v=k^MFK@u~>&b05p8aBjYEj?hDfrnD5p@*vk1ZEomGwei1N5^Q{p2=k5 zpuGTQvw1k}UElW~80(n{g5v<@7M`jSV6w*n5MPJW6wF=$YG=V*Mq@#?qe7DOO{ul2 zT7VHLwNjNqwtf!e#aQ%YxG!n2)NH8|ppsF#H5>{sP<*ZeBx2!yKA$h=UQ|AaPE}MT zOw;>J5sf?LD3vQPRBY8Q9P=;>3^H>Tfc$XJb=`9AtK|nSbO^~7y@J+CnL5cFAz4MN zeyps^^SrSeRXWfc0SMflDgn`G^eWgH!Gimmo41EkUK{!Kb!NO32JnR!ZP_2T zrn1=$z*68x&s#M1H>fz_foXSX68nE~oW-><&dmcFEMI%pFm1E!UaA2p2bwE_0;!UxyRB#T*|Sr zXAc7}W1RIOkyTR)7#J9s@6^=&09qpPL2E3sYqAfCBp1NU3X_am+RyC*y$@VK+{T zQ{b7Bb55dHrc*8qI*v1(&*uYRA+8%EU@gWbpjc2TC?@o4n)w4O6dSVSt7@^GBZ!dY!n1fvCTDL$<^&^dyjr?s{9@@(?n+4vXz WXZM{iMREE70000} literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_checked@2x.png b/src/qt/qdarkstyle/dark/rc/radio_checked@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e190476212f1d5a496f444d581232f975e8d6189 GIT binary patch literal 2718 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 V>VUGh1^NI0002ovPDHLkV1jGCL5lzY literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_checked_focus.png b/src/qt/qdarkstyle/dark/rc/radio_checked_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..4bd472e160a5c7e26dbfee8ce8ee94e4af48665a GIT binary patch literal 1232 zcmV;>1TXuEP)c2>>p0}8zeon6f~NQ%JFR<{fUCDUx?JzdP~ zIOEQ)JJy}&X81q<=RN1VU;pPBxYVI)lBc)3CXu7j@*ImA%mhIIjv#uBb}2_X)2yHW zR|7NCPDOhyFl&gUT{&r0SChW_PX?xL_La$G+yHv45bDL=?hrmxj)TJ^y?-Z(j*OSM zL5g!h4Z!sU_6~xUWE%8))dps6^-VG7ZNP0nuTbmAv3#_1ma>CRsnsDhg-2z-2GmL% zj@F{ihtxe}1Jky+HW8cw#sOOysV6h@b#hSQ^YB22M;t#B*MpW|P6g}k-Obv6K?C(2 zzJfE}4b*|xWxB&NyrNi*coDYh+gXXd2I$FJseKQtw=^Z$Z_wZIT~M9P_RjD7i%)NN zO^9(R(tONBAYu-Ic4XnhG6BgMdu=N1TA`&$c@y>=Bv)L4)D}-uaF^kaTvn6zwdh3g zWvfH|6rRU^2^d*<#+;J$!k#AHDHW;P?BSOu-3{DI)PhX2I{My)((y|84S-<1+E09P z+*nx3%HsLyj5c03BOTXc7bkb1MQ4Rx%qx0r>ARwVsh{{7%>BUelR4fm<*lF0YS0sy zA;D-xeLGK=#`ZLk27UzYNTs>6pMhjxAt2-(2U>KtFFtLHYr(4vGaNdiU%zXsuPr`H zmc0!iI5zb&fa87npYVApPa+YY0)|x~T@YmSKapi+o)o?Sur#~B0aQ~M_)8g)wV-P8 zq6a@%`W(c;JSP(>7{~{MICqWmho$yn4cLWGasgvU6u8B8eFrgA7~ICQZFfWxH^Cr%f+kM@1wN(}f{00(X?qmVneNQm;WxpUju(-$im zu)|J(;5e_0MBzQ)Vrs$Jm<%75JBo7)YG3y=Ff7S-0HXy{-*@raWg2w=`R!`eEv@NX zq;ogQ7HAPbR7m$T@J)k`0$&5;hF#6lQnKu^@EoFwt?n9*2=tDx7K&~ioW>1<@zUkOpV}m489#%;WZPp;jz*xTDRH5t$dwP(5eBeAwa4v zw@K)6U~8sZ51n6*r?vU^1aSq{e8fb+hC{-i<`QAU-Uj_tz8F@0I&J_h2Xg*2B4%Co5ve^lMk6V4_A_E}b1H^Yh%YeTeb#G_0_MV?NV0}xq`DWp5z%9TLORblUVdGGm(iu}| zcD^Z{1oX&i*z>Tyt&~1!ft`}}m=TU2fF3D?dTehGiSSu2%fV!%_w+F0s2t;SaD51I zp7U*a-v{T*nAPI07X3Dm#*iv}s?9Tn*8=wpCEsGd(8^4czPwOwRe#N9q)Uv^_~14G00000Sb literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_checked_focus@2x.png b/src/qt/qdarkstyle/dark/rc/radio_checked_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aed5e0c94d5361564b31f53d50cb7476957bc2e9 GIT binary patch literal 2656 zcmV-m3ZM0fP)N+^RdmaYLzaG70#E10BI zf-Jj>8y}_OBPu4w#3UwKrHe+5#t4>G2DO5vB9&xdcK|I>tHiYs*BX12};HXK;Tsa!OK%?}?$2 z){d0H@f42{a0q}w03rak?ftzc=ncTUjwqJ*PT@P1)>g3qj7#a8j}|%Q<+vkC4nShDj+A5XCU|}T%>q~fs!P_aHxc|(8Eml@+YbVqodz{A zV6Y5E2sjQ<1Ard_hzIywZY^i5n#R{k(O*&k8d4f-r9}X~o}+j>s3$4&xCNf-ZQ;j7 z`A#bCL~t5u&jL6lPaC^LUeeplzxGEzP(lF4cIZ4%4-u&Li=uRIwA$S9!eoBZU;l2@ zCRJ4v#ZLg;1mFmNxuDy6Up6=4X4+zX7axFjnZzi2E6D48C05Wwl)1U5m79w8TL8Yd zST$*jYbpI2z(7x-uqf{Eg0431D8^@T0ce*=jJERup5rUoY{=%7&Fn48Uq6xP&@dRK z`~$9tb*$!uo=MzRs4r7g!zbC9IXd5+5l`MYPQ=Z@S@%pJ{ndxGyr2eHI&fH0FH8*d*fSq zYS+cwRgBR3PMu(dW*R#R;xGWi05||Pk=i6{)+&b1qSpWt6Dd0v;KeTM9*Pa!ty~*a zH8cQ;PG>H_OI)VS(Fp5SG;wnw+G>-ks)=C+q$>d&Uq~Gh>kN4B@HFNvXrog|oim?Q z^~XE4jKnyXd2M_M6I~OT$yYBh0EteG2ejO+4dS?-R(2O6YHUhVX>}KfV+-Nuz)J#u z)!V{lg^&}AbtD|U3gEDPHiFl5xA5M4b@C5_5&`|eXPjS1=f^ytSR&=zM=4c8=KfgoeZp*HVaA zg>ego$o9l&{e8?54G81Lx8Z&g@3~Be4fqUKS=sCsPWpQs?vM3 zNWk~Qg!Ti|qG>%Eb|>@=%=G+Gg09UsH^}L%E~&2pIKyR1D{5{HlqYdu)ZPc6F_2dZ zh}Oht8+sQGPh%c{w_K*9HW>UM7dK}BB2k=&zOAZ#4KM3y;s-&ECKlm*f|rGfD;>P4 zexY)9W*-)`(IK?JQ_I+ka&dD8K+stpgXNN-2FEPX07!QPamoo9%?h3F8spQ3)|Yd#RRpvq-> zX-ym7^YixM?4%-A`gy42GK11JfrOiBDS7@lDSMwXD*y)gwx<$36QL|@jNudlhX;zO z3`Qmv>RUksOXJZl+7tbp>@h(01P{TQx3V~Hy6m(-nU#b=Yfy2-z^9!j_&M1DAiv?h zv_RmyA7Z6)dZyjT?D1(AM))~d0gy$FkML=r2JY9v&yQh2g$I9@rM9$Vk6EZ1)B{z6~?x~5|{0QX9;sx~S20G}fOz7--Z@@{xcm;jT@$9_btR0r9Q z0I=PC?Y|@3*t^aSoFP^ifxFKW9!52QsLQnH^)~Ktb8-xV@a(ACzEj*F{41oqk_ZgI z&Os z{kw?{<$c|BUCdpS9uAdTW=MQ6a7(^j2H<3GC3N{|SpnF4wzkq!kC^P|xe;^BEdaI# zDlRWJMjXrzBGiq-7
  • +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 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_unchecked@2x.png b/src/qt/qdarkstyle/dark/rc/radio_unchecked@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2160a32ed532593c6ed5b88651e64a56f5a54704 GIT binary patch literal 2167 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 P00000NkvXXu0mjf>yPoi literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4de5d0d2d8411305a232bf65c59408ce6d9b7e75 GIT binary patch literal 2277 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 By{P~I literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png b/src/qt/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..eaf7bc26b9e24e84a85420e7aafbb2d726c2cbc4 GIT binary patch literal 2127 zcmV-V2(b5wP)jyBY zS_2)`bSXTd%K(LX5Yr7&6(Lh-tV6Kd*`0__P+b>y$=}1FoyB}3=YIeu88Wq z(`A@RYcG?*1d106I0wK;0098U&iwWZ+6$OB5ybZP`Fy9;+Dc}?^tdibTe}G4d;pXB zl|*<4Mq8{kPj@t64@mi|(r*JK*2QtPg_Z)C?PqENuM1q2`X`?2yp2g8^ZJ8uOtWG1 zAcU!Y<;;P11uk!o;2A&eh@uS$Z`1`!+lL5#rx%(9ume<^tl4J*_`6a#Y%PwD0MaK7 zD$9UTG8iXdJfJ!N-vkiqCFgc)xujzO-zY|ZQ3lk-HO)$`0KS-|_&BJ|l-Xo~7up;6 zuYz(%6-ozi6=~-IoS)+y-6C&kkMIxu(GL`1z_gfd1oaew3a=xseaVMp_0G#bA6k0=RE^KS!i9&J~W8oy^cfhn3jiFI1T#ZM2=%`sd z7#a@%i3U6Z==aVTp~q`un%r02J`Eu3g8(jcgt~$OM%up1?!u*(2&6`jFiRxtbVSQV zJw9uzg1uGk)qrq|W&pg!5fa449rf%gMsF#wWe!g<$OZt19O22`M{s*@^>P~^5zsF@ z!F7p7?k+-SNs*}M2M|{}V}kCP^rFtnRVSwbb#crDFvAf_rmbl%US??#I)>kn*zX9P z`?-&BTP}W111$6t=P{+)IZ@9K{1jPAtZ!nP(0XT##@?Kbo7Dh8 z^IQST=Y3N*P%y@$nRBxJ4KfTk(_>C|#!_kg(Pw!j$L?3r0l<0JjyhO|DPCTN0Tus2 zEr4=I=+B)^-0$TLdaR(OIP0Sf?Ui0m zh5@9TWQl_2*aj2Y7U2|tlp|DL9hI|#&tiaQl7tq6;+?-#$ovZc$DPOCJ7Oqd*3+l} z;G7RQ{bmzSJ2_c8LAYjAZOZknJzvS#0Et49*Y%VQ09H&FfxHh5?}zb^&m%zfTUwbdmq^ zN{nV1fOB0jq0LLnFyPGE+Adc;Vy>4r*ikbHQ{Y}vJ{B5{Jzidp`2f1!q6p3RS6=C1 zU|pI8z0fwBsZ3rLlm)O3J)0WNRK`_TM0K9;DocfC8ITK{AzHIG8#Su|JL=gb;H6J0 z0~N`j^)81GTGU>S8vsmjgx(L0`LsPwp#mZxEt`=YXhIJ*qr16_l+!(|3*a`AJo43Q#vwq)8-EEJNAG%CQlL7j@{s}in8;gQ1;mS?b2vBG zW6z6%c8OJ`&D{jz?(^ZwU`iczt-7p`T*Y8|i_WhM>Q5Ps2i`aZUY~E{fqrb1ye_K1 zfuQ}BK<_P<1hggqvvOwxKP)tFKB$W-ln&yDgq8vLyr+0eD#aT*n|QR4oc-S_8`rIr z)&MB;6rG^-kV0lvAsZHZ!>p|eb|1zfQOn`puLJ-Pv}$b1EM4EkbfLM6>cwkfnrWyO z0AsQg9|5!pGMf;>ONE+I9aZ^AgPAgR9>974*@odskxSYme6m0K0Ux%@*R-n2SUn7& zp%+>b#5P%OrNLh%{7nXjD}p$YG)S8hsI=u6r8LHY7*E(bfLEjElbT$@J47x?MA%u3 ze&3$swQ*e|=>Y(x?hLym{%mX-PxR-O_rl+SOtZ|iNvJo}G66Nd<_6vdxGHoMPx`q> zv1B8;nhlz0j9ql*V~6qmO!GdV%~ob@$7^_{Ki>oNg#j7L*0idM7PF1)M3EB!j3Y5h z!btS2+#E&EXLAPt?IX=T5!({=*gIIZ;|^mO!}#CCe*qR9)Kii#ABX?|002ovPDHLk FV1k*V>5KpX literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/radio_unchecked_pressed.png b/src/qt/qdarkstyle/dark/rc/radio_unchecked_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa343e885eeb7ea901cb64386583472eb51b39 GIT binary patch literal 1027 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 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..fa449d6ee0b1130a904cb056bf8dccc2076cb16d GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpzq z;usRq`u6%kP6h=YmV?1MXAZG?3tsA&Cg5N5&W@kybFWL9cG9|z%H8Rv(HpL=wOzSS n<}VLWCjz`Vzry42P0iN~M~Vb@@6}n|1CsJ|^>bP0l+XkK!#OQv literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..682575ee24619be08bf856409bbcb15048889ee4 GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1Gdz zi(^Q|oVOP?@*Z*!VY&EMuZicR=|v_%(Tl96k!lOMd=e%)mZb9weO6+R-(cRkq&_VA z|3QlMqX kmQ#05v--Yo`Vuky&wDj2ws~4z1A3Uj)78&qol`;+00!P|8~^|S literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..568b0fbe181d513a059d24cc44be6bc3c23a4503 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq0y z;usRq`u6%pUZ85$Koh>S!z}9#%urkNj7{mtr*(fgPi6})Oxbm&bmsndfr}GnoctTL oUgj?kP%8plnja{9bLQMdd^gxR6(>}8Tm(sZy85}Sb4q9e0Boo)3IG5A literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4d15f1478b6107c5165ebd9d1711b7e32c3fc651 GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1H2@ zi(^Q|oVT+#3LY{LIXX{LN!XC_INJpSL0;top93Z?{J&7`S3j30 z^EDUOZ?K=ozx3HGm90-c?YS>!`#t(*@1KfEYmWPPE<2wHmudKohqrI;@;nXoNj&ERq1z97*cw!n}<*MT|;(*7)7nR0Vh_1o=6HV(di kp3hW1Tb17x7tDOfs-v!CATZDAGtkQnp00i_>zopr0Lw3F!vFvP literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..cdb96bfb96328d04ea1edaa46a62eddf869c7673 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpzq z;usRq`u6%kPM~VH#O|_Bw~qJt`yb68Vnr9G?7CC3bML#r#R)S`{*78M n^Opyx69GQW51c&rmgWnF#_K$LzgPBKf}}iM{an^LB{Ts57xglG literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..23e06a0152f4b8c8a742a145648763b717bd97fc GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1G#* zi(^Q|oVOP?3N|@Nus-}A&9XIuT~{JkH;xD?D3uyDsed?}*^@zt{Rz*V%Z+^-E6TdEfqZ&;6|L3^(OIzr6FhZn84d9~0&a z%o%J8*e~!n@Gp>TkaI9*ux&_VsA4$F@P%O(;|oSADR5`0sImOM>we0A2JhHaM&YUF hf~LRwuDbG|a4VCVPI~Q8N1%5ZJYD@<);T3K0RW6iZG8X$ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce6f8d89d7ae7dbbdc62afb62a68a1057bb1f1d GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq0y z;usRq`u6%kPM~VH#BR5uhHZuOpK->lbP0l+XkKd5UwL z^&c#kY>;y>X0UBYW2j;{%kYI^7UK&>6Xpxd8EgyKFYq|O5})z4*}Q$iB}Vu>hO literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..136ebae2cfae25550de157e420476a787a190921 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_WI@ z#WAE}&fDu7c@H`8um)H=D@ZLlbA&5orp9aof0bDsibY#qI7!Q%+8bWC^GDfp4xkbk>s8LKv1J4{RL(s(bH z%D3&=wBXl53`1_I8OQ!X`wuQSHl+#EBAa! jg?$`e=KCBbEqQPDQIm_kdSB)lph*m#u6{1-oD!M<#3L&2 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cca8f6d961b68d1981802e36a70ac11600781b44 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_V<( z#WAE}&fDu7c@H@VupFrEau9K0?ch@=boI+&2%*s~$1vy<$mAnQk;mE9l$O`)0KhRBFY}dF1jc*suB)natSX i-*l-}e}c-(-MqUaxY(PGQu%=fF?hQAxvXL_{u literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d4dd49dec9b18ff2afc1843b720f83449e1a8bdd GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_Wh0 z#WAE}&fDu7c@H@VupFp;!5GL@s$iv1cVnPh6nXOSZ}SIsyF`!Yu#sVkWmZ_8wBNJ_o(pa%x`uCaXnrAT-G@yGywqO CGfUC{ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..768ebaf4ca4d2eb8cf15b00d918ea43c1d6295c0 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp?v z;usRq`u6fd!2=2+EEij6X)sKVDiCS*GMu@vQKa>d($BQ{R@+}WOcK#~8+dDm!`_g; m|F+vR{PYU2`oKC#r8Qbcf{XnM=SxnYVGN$GelF{r5}E*d*DOW= literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2f170ffd8f91f1cc140c62a3eb9304bbe1550e10 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_Wt4 z#WAE}&fDu7c@H@VupFrEaxigH-r~?8bCJ8#RXOCLlg_M)pp@FIo5u(V{DtWr~Y0_ zZE;ZhT5kr1|A+N2NZfh+sWX1TS$&W>Kqso(z4gTe~DWM4fOFv9H literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..01e3501324a5b0302e32440035c27221a8cbfe91 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp_w z;usRq`u6%pUIqmoX2)iUo`Vx5R40iyD*7C+mw$cBLnP#zUbVWkvXIQ#7jZ%U>_ANj jprHG!XV#WD$A52`LNqvje_PyH1CsP~^>bP0l+XkKZZ;^a literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..68d768e5e13abf35760f1b23954c0031ad92a188 GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1F_k zi(^Q|oVOP?@*WBha5-q*RnYciR>na=(Tl96k!lOMd=e%)zHoa4W@Om|FVdQ&MBb@0Ita|CjbBd literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9f20421c8b76e0431bfde488092a91350b64b8 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1Gg! zi(^Q|oVT|P1rIqeuwLX(q4K^ z_xIzU6KCvXI>S8u`QL8_Wp8@C8K)iZKk$P$@dDF_%0IU%gVP%32QXAOtY!Gd5Y708 zaU0VO<{Z`y>^Ha)_&10ikW0{Russk)6$NL1o3O6m`uW-x2IDymoHM2sPs(}6yL+-= V!1L$ZD}f$l@O1TaS?83{1ORIoYfu0H literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..b592e61c161f720b2348a369b1dd52a9b0a66184 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq9# z;usRq`u6%pUIqmoX2<3mn!3X2OiOaa3|n6Qc%K|A-PxnGTWR;4-c+e=mFr*f0ren2 h!|d;pymQ_A`gd=-%vK|j+*${c^K|udS?83{1OR>ZDMSDO literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a593a7e761473ff439a4dcb4cc79f0557149f016 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1Ftc zi(^Q|oVOP?iZ%rZxLl0wULf{*0jrYsChk`o_>@*NFq>SS^4juDZ{4@__)wQQk*oXH ze>Th8diT3vZFP@rx2*Wb%+Ra9e=JYR literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..a806257e0643aa63891216b8399d6c364e39e3e1 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp_w z;usRq`u4gbFM|RP%fV)al}rV}_E(*QvO6s5-u$bcnXhWpwWe=Pnc1|=8_)JGvj%EH i0(tk+O-ke}?cOo<9by$ol-f5DB>4qa4lfZV7X`JRg{qTjgqZ}qjswy literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..2a14f5cbd0cf823964f405146395eb9f1057ad8a GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}{2J z;usRq`u6NX-UA9E3>TXn8v+e-d@lvg`s3^6Utcv0UseRV3s g6KQA9NlPa4?!C^&qN*6G1T==h)78&qol`;+0EAsB;Q#;t literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..35371feeab2f481fa6eeb39ca2bfbeb31430a15e GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_W$7 z#WAE}&f5zcc@G8fumo5;D@ZLlbA&5orp9aof0bDsib+vlg4^{cem^z2`?D)h2MDB3 z$lai`zWS+|`;(>a3z^qO{**X=`?Iyot=0Cmc1n+;oX_U&kbaO;#+gTe~DWM4f>#!#n literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a2173c5eef07938886ce6c7853121601fafbf40e GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_W9= z#WAE}&f5zca}Onmv|fCl-qF!$#F*54p+afanh9pS+>tsDw@i#}R<&5Zr|M|!cAy?0 zXec+hcJTSnA}R0duaevC_>HsTUcLVI`R{Lg`y9Ub4?kBe?Ymk!H=nJ-d^Y2>iy?Q* nUwjH!{4DF%Zgz-%h7UFM+!y&d6y`@C2Z?yP`njxgN@xNAcr!_+ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..e31c694b05f39da714a97ffccb64b11de637ffb5 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}`>F z;usRq`u6NXQ3e49hKtFXp@t2vz7K3~2F+X2)%E-3twt5k{oLw7(ab0M*VSH&V0bin ep^E3Fqim^rSXoY5_Wb}F!r`!5GL@s$iv1@?<(ERRny3r}BK k_H9+-TOo*Mh6C?w8T|eUacJ2;Zv+W>y85}Sb4q9e0Nl_=761SM literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..4ee7aaaabd6a1d4ebcc276259a2de91fd38a4548 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C}`v9 z;usRq`u41%D1#!yfeVgmObI8Nb{j0`I9x5FAi~vsWW)MrY?D;>>b>#!D(|qb=UOCkg-n literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d8bf93bf65e449dc92fc861d918f94f15a25cd82 GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP_WF? z#WAE}&f5zId7B(WST00%8<-_2Z#!_XV3W9hi`$AOrw-pW;m+T*{*GefH7xZ`<@^5AE&dt88Dw^Lm5nft6d>UU+}Hx%cF^ jX-mGjPlxDaVEFc(Rcsj_M}c6=OpuVLtDnm{r-UW|$Tmjs literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent.png b/src/qt/qdarkstyle/dark/rc/transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..67753617fec23bbc57360e16d16bdd82ab984743 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C@AIW t;usRq`t~3rBaqjm@PB=thXaWDo=rf3fzh3DK?jh-;OXk;vd$@?2>=W@7CHa` literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent@2x.png b/src/qt/qdarkstyle/dark/rc/transparent@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4012944b58252423bd3c84fbf6f5e698b1a39bf0 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP*B~| w#WAE}&f9~Gyg=Te1>gO1`OFspnaH4_oY}#FfwBM7$v}{>r>mdKI;Vst07yI;1ONa4 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent_disabled.png b/src/qt/qdarkstyle/dark/rc/transparent_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..67753617fec23bbc57360e16d16bdd82ab984743 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C@AIW t;usRq`t~3rBaqjm@PB=thXaWDo=rf3fzh3DK?jh-;OXk;vd$@?2>=W@7CHa` literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/transparent_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4012944b58252423bd3c84fbf6f5e698b1a39bf0 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP*B~| w#WAE}&f9~Gyg=Te1>gO1`OFspnaH4_oY}#FfwBM7$v}{>r>mdKI;Vst07yI;1ONa4 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent_focus.png b/src/qt/qdarkstyle/dark/rc/transparent_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..67753617fec23bbc57360e16d16bdd82ab984743 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C@AIW t;usRq`t~3rBaqjm@PB=thXaWDo=rf3fzh3DK?jh-;OXk;vd$@?2>=W@7CHa` literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent_focus@2x.png b/src/qt/qdarkstyle/dark/rc/transparent_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4012944b58252423bd3c84fbf6f5e698b1a39bf0 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP*B~| w#WAE}&f9~Gyg=Te1>gO1`OFspnaH4_oY}#FfwBM7$v}{>r>mdKI;Vst07yI;1ONa4 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent_pressed.png b/src/qt/qdarkstyle/dark/rc/transparent_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..67753617fec23bbc57360e16d16bdd82ab984743 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C@AIW t;usRq`t~3rBaqjm@PB=thXaWDo=rf3fzh3DK?jh-;OXk;vd$@?2>=W@7CHa` literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/transparent_pressed@2x.png b/src/qt/qdarkstyle/dark/rc/transparent_pressed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4012944b58252423bd3c84fbf6f5e698b1a39bf0 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP*B~| w#WAE}&f9~Gyg=Te1>gO1`OFspnaH4_oY}#FfwBM7$v}{>r>mdKI;Vst07yI;1ONa4 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_close.png b/src/qt/qdarkstyle/dark/rc/window_close.png new file mode 100644 index 0000000000000000000000000000000000000000..0b67d3bccbea881e7292a15a6bd8c5ceff8a833e GIT binary patch literal 733 zcmV<30wVp1P)pW?_>eo!Ch^y;0j!U1>is&LWna-;Q*01 z1Iz4KK<0TsNSuK)z{)*Ia06gL`m^xVY4>RL2JshG^;gw@&%dg>ZTR0qh6B&@9;#UH z1n#2p#&H@S>jZgT*hcg%@LSN=#+Wa+1YAG-3VMHV86hk-ZTq|qxElluD93=+&&ao? zX*^(@0MI+JH5ST=8w8#D;ehD9F=&*NEg-5>!VQAX1RNq&-I@?^oW?c6Qi{a!G!g^& z$pjqfwv4%)5CCY}_Gya5OjU`@Z;o_Zrg0RXYmtbiZJ&zDt2Bw8@6Q*(d%izEfX@`c zA$Aue!}G#L6+KKy-YB}*GUg%+F33p&u8J(D!E*%$5-(Nspo~P%_n!-LS_NJxP$2PQ zc$lVzmlEg$!X-iX(}sAiOdwOT~*bU{&*BKDthjD;ar*8WgbLNBhiaAc+;4D0N3}s zAiIfrr8<$@flRotHiQH8$GS?Q6OrgyQ77_VM%i%N-b-8K2Ehu-PQ0$dA4_E+s}rdL zZV)_C<+2LAghVIphwj7{2K0|B^RIKeJT$GJz;Q)?f?})NNVmk!c z9$u%tT1Rllv3I707f9Sp2#8vnKo9t#Xtxe{Ttbm$;5*==(Pmw>|NZz2mhXU3cIlrL P00000NkvXXu0mjfqIOUF literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_close@2x.png b/src/qt/qdarkstyle/dark/rc/window_close@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bb8ac7da5e1effb673af3b7f611cf244b133546f GIT binary patch literal 1620 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 KMNUMnLSTY+R5hyr literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_close_focus@2x.png b/src/qt/qdarkstyle/dark/rc/window_close_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..692ce24f2f1d6632e0edd5d9e1a1eda38aa3ce50 GIT binary patch literal 1659 zcmV->288*EP) zEOo2$hp-9@SWsTD$rApERI4SDIAv=z37{SfMHp5oDwSeICa`Q{DMt6O=x*qAxAgAo zeoyKY`j+>eKKFdTI_LH4rzbejfe!TlEcIGEb;BNg_%1(`?6ScT%+~E|?q{_reYn>J z_M^<3_8mR&uOa0Hn_jy1$OB%#`Ks=A#&!XC@t5}418={Qak^vcwwxv^)2gOcc>)@n zvoR-I0*-cUz0VPSzj{F%?TfB6!S=R)t%rGlqvmZfw_w=>>rGUUV)P4m%h z-_Qo8iR!FA=-lXe9{`Y_w~RMi0!9K3xb01^)QhSI#15?NygiTEGVpjn_#I5=szp_L zZSDvFh7&@P<{<(A3>So?%|ieHfZT#*&D$b@5X|drZC1BJa)&B6XU~~z8Tdv(_#HzN zwSv~80)qg+{z6F0JoLO1?5)bQs+cB#jmTg)Drd`?l8uJu-$`-JJEzG|^AMv0TFTB@ z4%s5`SU~tc&FhtZJ0Yg|yUuB1eOkYbb4F|c5FY~4+3Jjb7w3$fp%remKSz| z1jeBs^Od4Pe!T6dzB{0$T0!g1X_D|xSjx@WbDbMa^TBNoIzOm+NT35+$}iXp-rEh} z>jB~akm+otsNVyO&D*oiYy~(L`AOp*(qy%uUk_GsLx}-^{vd2S{C=5-gaJT22qrdU zK*-%?3g#gN006l;d(mXq3G0Mt8Tagv&ex{(ULyJ0lnMYy5JHOPA%Sm!oz%EO>pal) z$B1AV_dL3gmU&3A16sQTO)?~YEf(Li}|wsz+>+Kj|AlS46pI( ztp3vopx9 z5!eaa=*+Ex{v4V=xC7#vmk*!$-Bc}V&Cn$RJK+$vHd?k5q4|S4AiH4S#oHP&%vWZ$ z99l$(GG!YV_BIK3LL`8==0Q`{f|deeV{2^QUUp`05dgv96OYEDAnXcYn9R4-gzz?W zzxCOv5C}V71DfW8XCCQF+U5c3Gg|S|C15iuR`8U=R>w+qe3zJRwVD5B)FB32lBTLN zT8xTKQgJ)Myw22T^_R}QE&%yA?A!jZ-2%Q9ka%Crx0EZ{S#$Ol0T6(Xz0+uYT7PR_ z?0#GPu>Ub%0rLQrSuM-!G6CZNJT32k(z)2{{{>!(%4D#G*OmP=-%{i2R#OB)(3#Ga zUKhdb-BPs7*JgDiw8*s8xcEjxP!Dh202*(9^_0QZAv8Tq=3A;3w1jkpT_M=@&Xq0z zX6~xNU%S?u=GP1AN-`{}&S-H*2*!sG{o7sbTBV@mLXj|F$Uezc2UEhHYbfDqVe*kjQNiZ(ytvUbz002ovPDHLk FV1l9ZC7u8P literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_close_pressed.png b/src/qt/qdarkstyle/dark/rc/window_close_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..53ae7f38e01bf510e75fb5910d9e2f282b9e48c6 GIT binary patch literal 744 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 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_grip_disabled@2x.png b/src/qt/qdarkstyle/dark/rc/window_grip_disabled@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3d8de6de36c412fb1e00e453faced3dd1b83be GIT binary patch literal 764 zcmV%%=! zE-Q0T|KLwCUefytDIfvpK;mg(f8lv`rC1439uk;>o z1lWKdlQ&Xc2yg^H5Y%J6H+KQ9;FVJM``zXzy+7AY&?Wp~r@1%op4zcldI(zQHKGnVDb+@FMb7&oeR;3>iN2Owf1umD{y@N~w2x-lSLO ze+eimJiuJa#oCzUY{cE&{b}>Ez{7+mz$N@)r|BFX&NvDB4qvM5tOFzPOnG7)`ve36 z|6b1{#U3&u;P2VFjUo7iy!4NKLLMnM&{G1I8;$wP$Ae=9i$j-F!zbjWhBuuD+DUNn zYS%fIW#F>|!iG@?nJox;Wc{~RG`;sZKtkgL>EfHR;BDn-eCdF&r zAY>@V?fxVIzHm4JUYN3J?k( z6~KsZfCccBB6$}#2MCRu0>r=p(vWyo>RiU7z6j7 zgpu$Kuy9U7Bi_~x;;!D1o?%Yy ztV3Y?>rdty(WZm9gLqG!&pc>uLDfB)RV8TMU$0Nv8>5k)d+$mB0000*MwG%=Uy8Mzzwj~-`x;#YWkbp!51uY#d z{{SRhAs%@MgjY1wbbwoa2NDtuLUKL|gk(1BINqI^omu;qvv)tuIoe%YR|Csh*0L74 ztnLl?u1=;clb%TYXt(Xb=Pmm-d3~j>jfJT0P<^B$pk)T*v7Q6hCwp4;Y|Vdlhw8&$ z_^)H#;0{+sV9ny-a&&(o?|wOfYu%Zl*&?CthZPDZnGWWCmj?0kOmPhB_#K zcQX@A0bb};KF`TaFlqRzGr`#5JMVSdOs~)7&G_lOlz^tf!zIoNhk^$?7;W3>ym?jN zVa5{>68`H>czC!#K=kmL_Dy<|&ztu(Dip9N@Br=nLNC)E=om-vQ}Rl~_cHCF^Lb@I zp#MDqn**(`Z0I|%KCxUHeo9_xc-MK5`zN@5g*LD@u~g|;Nx#a*zaD@)ARNNpO zp&L}<5{Lx}shN>FQ79*1fQh*wHA5AlwrOLhP8jfLKl%5`ww?_CeMps9tJ`lRTHk?r z9}RkE0IE`4=?F{ygV&qNFl9P0;^ef1~+fTQbAC&~i!%GcdgO?V-7B3}$ z3+_FDEABNw5!_nJNRCt{2n!RolK@>*MbqJveUEY8n=0{K<-hdi##d9Db(Lf}8DIz2@UdOR_W_D)dTkhWdH0Nk`b~PH<)TTCd znM?8>fa@wZ2e%P@D#8z)N-`O@zs=silGng|R3+)vQ9T4oC`d_%z|Gm7Qa(d-UuW=g z2LG>=>tm;N9NdwTJ_jhFt2=I`TfKcEe2LU0$gJ%Ju z!GlKuA;N<=$l6K3XNqxqy)2!LfkQ;lZJR7~sK?fLP$cfqKt29%qlZIR#Kf!&$Q84f3;=4E*2?dE~;71%w!x&`daT*`DT zB_%J@U~T7tA>h-?hrd*L44eW#fqIrRIcA=SHnI%XcHY9e(eCe*o1^Ve^KLzOam{Al drZ#nn>n~S6f1Wg9ytDuS002ovPDHLkV1j_lN~-_> literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_minimize.png b/src/qt/qdarkstyle/dark/rc/window_minimize.png new file mode 100644 index 0000000000000000000000000000000000000000..d8c54ebf21606cbae2de731e1f341a9138736c3c GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C|K+1 z;usRq`u36{U$cWi>%;msYm=1@U)1if1RkEKb-|W-lewdU#}4Q6RSSGQUa4i@d!Bao z|B@87_R+E$&vW}chx^mR~MI6zZt^iW!W{pG8qCL!r~Q&hoTl`sFF>=a#oe2Wm!EC?{*ez<+{%vN?ytJ0ZAHeP8L_%;9CVrHAQ zVY^*#>#EN6yftsd?CHHH^F9llJH4sKv%i^f*0P%?yN@njQrlma=ac>VcJr!Lar=)) z{)&myS@-3BT->ClZz7M4dfAyhtO{3rR&P3#Ijfh~Ks%ZF&hG66NtXXunyggKNUL2n;J-DdOr S`&~>QL4uyHelF{r5}E+6{fF}a literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_minimize_disabled.png b/src/qt/qdarkstyle/dark/rc/window_minimize_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..cc51ed0eed66b9ed3a25a9b80b7f6affc4b266f7 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DA?%f z;usRq`u36`UsHfU%ftHl-@)iLA7$BbvM z%Qm0%*{GnTRAg}boMG5I2F%I7IEQ`0`$&ct$1m!?fBu(MVA|HpDje)5 zoHmrn9om0d!c5n8{kg?#t?_x{R~2Z39PH zgOXw?$BeX7yCXiyv6%L^{QUo9r}8-&V`WC5B@nPSVgKFkq#GwMEm7P%&na@+!{xuX zGmE4@ua-V-P;`0alDWrjJq?`s=UDds9rJzXJx(?{a57=T?p535RIN`0=q-0$QToF` zdVdY?^+(I?rrmyOUsLIMYkO($BLm3;v43r9KN(*xoTJLT#n-4|=Ck@h754JGMFFJe))Zkzmp#IsBX0xtY4y(GNAC;IkwwucPA1@A9k z_~-Y{Lop7QL@Ufs$k@CxdagIm%;Hc-N5|P(#<5$!)+^oE9=~<2mv7wsdnN4WCXEL#j%~mCvw6wgj*`Hbs%^KvO$)C6 zWw*Xd|NbSP|8G7_O1acmzogPmpS!@C({l@(n)LI{n;IH5xefM5JNF6b?LV8I$~gOK z>yqOQHVgOZ9eiaoUz}A({oA8W&L{O%_qHv09j<=;s$1^wpYjfm6j@--WZ*ffF22qB TAa6~;e2|!@tDnm{r-UW|_tcKI literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_minimize_pressed.png b/src/qt/qdarkstyle/dark/rc/window_minimize_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb532126cca0da275d835554739ea80de58009d GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DA?lZ z;usRq`u5UB-lhPFBOm{NzteccR-(aIC+CHX5;2debKM-JuUYeI;1L|=wPzFQ63=a6sY4{q*h4Co4|`FO~NXTE6RD-R}Pu z2i~1L+7@X#wL~X#?ee^xI#25EhaLU#v+9eO{A9*&?$ckN4boT3Or%6w4Mz4CrT698MxXe*PB&NmACt!)4n~+;8Js_| XuKj3ZY8KF!2@>;k^>bP0l+XkKfIEg2 literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_undock.png b/src/qt/qdarkstyle/dark/rc/window_undock.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f4542590029068f56d8ca10aef9a26e8998702 GIT binary patch literal 521 zcmV+k0`~ohP)z<-xS z-E>_y(|BvqBf`N0yS zwc3BZQmgNVZK7%Pge+N>btfX9NdN-Ds?^jz1jiB?&Pd$|y-nM;ANy|vL)Z;<=M_|y z+7iJ@3UdHhp=g&R^|%YV86Xc*7zZGfQcH1*d!AMTryd38aW@fS4S?BQD>(qS2?2t6 zn76FZ(DkdL6olCE=bk6Azpk-=h7*7Zz}NxOoO+=WVWH}%LPUk*kH*pgl0|l zP?|CHBY*mb9T11aS??clo9A0qM?C|W9flRb?fGo>B2I0m0|c*zV~&<*7}s&@I{=n%fHBv=ISlF*j`?;+T-ZR<4Q+JCMuSOkc~Jr-O700000 LNkvXXu0mjf!j$2^ literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_undock@2x.png b/src/qt/qdarkstyle/dark/rc/window_undock@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f0efa3429e3a4d1e63eba95202a35f2c7e5bb541 GIT binary patch literal 880 zcmV-$1CRWPP)GtbQzGXrQenlwXk1FUXto*ig3rWiCvzzBf;1a!q=mw{CRFKy>?^CN?UTb(M$ zGN4+o-!ec84CLd)k%9o%15cJs^L@KIM%3W7nlnkDcPF*+0Kh<=Kr6Q6Oth;LsRvXY z=Qc4`5W~P@rpe&Zpq>!gfc-JQ^A*75M5G-P1h`wd?A6veA@n~u&}dAd#~Kgp4~GNo z{}I{%28|^n>G%oK9@>C|rLHFl(%u&#PRDiLGK;bI7ICoa4tMzM)7~qyxER_1)dEzb z4NxsWHQE5x0#uWF1G;X6YPH%W7{()Jx&iRTZuRZDvmR9p0n7xKJz8$=?YyW|Du1HJ z3X!utRmZtYj0FJarG*4w!!zz#R{nFSA9dad`gW>qhk#w*m?g#=sA)U^STMX#w&OgM zOcH2-?KtBAPfI2~A{j8|Y}>sqmB43!ZQCUj5Kn8~QYHe-poJ4Sc4>0;>0Ei@u zft5LveIOCoX8?ikNF<6288W(j2AtGWUSb(tp$|lw22~`4WPo9KywdJFCvb@qL}&ws z3x&uVoldN8Y#<{MxC^P@3Tp#Y3s8+VK(zqXXaiIWP>nV~wE)#<15^u8jW$5F0M$f! zAE1gW-A;Uuz;0_ns(JtetF2|JGJwEKt!1e(fB<(pmz!@bPm2Lf4?G$4Zn&2w!KgGr zxL+;?zZX8$J%9k0!J}5OxY(}FY3u=q&*iiI{c}S@L))Dy`;M9uSZk&DW|_s|q=Wj0 z0OM!UNs@tnNJI^q13pM3iVG2cl!)uU8uN^&0QMx3#o!k_@3}-^p8@4^{tE~v;cdVn z44x>JO5Y`72QGu9Lg5*KUP~kl56zZM^Q~0$Km&-#GmH6g5FSI_aQMyOamy^sNG9oe z<65n{*U0du0o(-Pf~1%OK`w)q;r)GLSyoLtpGKoeH~#>CZqr=Ym^>E%0000NrHtajs`yObGe+^GQj+De4B*W2T=nUfznQsFf%}eH!*U%7~NR8 z%4c4@0@Rj3Q4_1gbYO?_BLZek5*M*pEZ`dez)q{ic8GT~H0?FN{%`GF@5qPm5`eK9 zgd{}(-1!Cg)o2Vo>$vIcQq%+hY+7T%!t?3s`!O5<3;_BL&~n#v6M@o-ns99007_QS zrwXucMO~?YyQnBvq&;iY%Lc47o?= zVz<}KI@=1s*BSA04dVcs?C1z2MGWD@<7l#22bWc4U$7_4i5>#jZdIcKG=k8z@6gdN zpFX^OZ`8rk2=JZ{`@pps0Gcg(l_N(C9Y!Oe>;T$A0}XEWYZ1U6N32zjR7Tr!pm0to z`xkWc%pj`o<^iB7@BJUjAHs}>9I+z<1MlSr@Mo#3P7J))S&%VZ=accM?Y)H^yuk=J zxvcYEEwi{VQ~a&pzG)fDVD*8r*w&70jcx%&55FUvr zSS|z%C*otzMCluTGc-Rx&o70}#8Y2aR{%Oute;?3IOuXR9=#>9NXa*@{?71WrfEX} y+5zkoX(msK1JiZ6y6exM-2GgEdJ2W2hWQOC4$$<*Z0nBz0000QHL3{%#4JuuH0bK+U zmrflVM3>?dI9W+L7Z*VahElMPP&>G|DAcLB$Dt-RwYN=7YlilpZjy7)|K;3!4;Pqq z(WsB9Dkl>iQDjgKz-mOV7K2SkQwoh8`Wy?8s&aCn!!-bF5se4c>}s^>LMXDRL`M{- zU=9FlYF8B92PwdJ*{31`8SYpc5$9WTJEx4?FXNYZL$g002ovPDHLkV1i1s)BOMd literal 0 HcmV?d00001 diff --git a/src/qt/qdarkstyle/dark/rc/window_undock_focus@2x.png b/src/qt/qdarkstyle/dark/rc/window_undock_focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1aef06053dae8b69236fd2d7d30b6b560798d0de GIT binary patch literal 866 zcmV-o1D*VdP)jB<_YFB!UVSg4uvYB!z{d#e#@fC_WP0onsS3cV>4pGkfEWZ~%SN>in73YXJLNVy%6Yw^w+m_L&g)Ke(F4D7N0o13=fh_kRc+ zfS|$F_-Q|W-a`a{-qzS@KYrfRK}DLq=Sz7fa&HlZY|&M{V}9PZ%2V7JNdUGD*d__U zwgKBD0oXQRo7e}?v=KT|(B8D;UX{yZAoetypDDU;!kVEV5M_b$?7*E;Kfi|6+HlQA z2Xh6T5p@s1F4IOl2=4%1EDdlm$e%Up1OacSTK5*n6sr@W=3wLG0f6WR^*mG56_aIr z1IQILL~zVx;SG`^G?^_ZXR3fFfZVM1i@Iy7U;E3P8;Wz|P1$e36e&H?i z76?hx&C>r}0Do_n|FHv;uTJrMqxqht=BV#lQwVswly`bst?T_X27GFDk(MBQG$HE= zfY1{Yg`z@7Pfh6hTmjBa0KZHWi@@iK>)bXW>0^6YiM6;{?9rvOPJ!WuaH87g00L2wn}j`g1OVx;ws~I4fISR3`xozdHWhcRm$zh?mcF*OO9nnh zb$}N&&^^A;CIR_@7GF0etVyRuMCD$E{f>)oJL~I1cVz?gn2R%t{6b$TPG!ky5k*1a zu;p~Cd;ITkEPwdiLFGe8Jml zY1jMb-Bf-G+G@{5i2~a`0gC?%*;L%I=t^an7CTPh=qd1DFn5MxI8QP{9~h1TXbizu5Q-oy5ySL`u4g`s zC0E@#2MQo&jGhIoDFCfObOcfWw0J&y^HsSHnqTGEfEfp@m)N-v4*;!zmFqUr*UNSA zH3GW&&2x+)hX4WA7!GI`oJNA@0Ji76^^t)NgyXGd6xMb9aOs-h`5$cJJXwbi4*;!A zoF_{gJqN%Dec|}2Jx<=e&*AN@u0C<_-rz&Vb)U~?Q-RMGL5LY9x%_PNUN5V-FjN4t z4ai0XAlra!Q~VgYF5MHnK49i{;FiYOEq1|hzj)_|S)mY2l%^87-?()B|kjOcu; zgTQiSJFws%ah&iRz~Wfa|3Sxv&cO^c&P7PO68WRB3P832*{A?y8<33(K(+zdr~qUe zkc|pJwgK6w0Aw4Gji37gvS_dH?Y|m|r47*<0feQ}rbq=q4AZ4;Q3{~2q3fB_#;63q z0WI!yZ#W78a0Ygx+mP;S>qyv_0oo~ z3%TW%?%q`Z=S39s0|Tz)C+{qX&~`ir%}?AmMHZ>}#r3#h9 f2K5vQMTGeSI^NJROB6I}00000NkvXXu0mjf`R$iJ literal 0 HcmV?d00001 From af68fd6bc4b4e28380ccf1a9b9f79155ee60f231 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 16 Jan 2024 13:40:40 +0600 Subject: [PATCH 0003/1190] Fixed active menu items in QMenuBar being vertically offset --- src/qt/qdarkstyle/dark/darkstyle.qss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index d785d6078..96e883b2b 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -140,6 +140,7 @@ QStatusBar QToolTip { QStatusBar QLabel { /* Fixes Spyder #9120, #9121 */ background: transparent; + padding: 0px; } /* QCheckBox -------------------------------------------------------------- @@ -376,8 +377,6 @@ QMenuBar::item:pressed { border: 0px solid #455364; background-color: #1A72BB; color: #DFE1E2; - margin-bottom: 0px; - padding-bottom: 0px; } /* QMenu ------------------------------------------------------------------ From b4bdfa70b6a49fe159c71c118a021858650e35cd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 16 Jan 2024 14:58:41 +0600 Subject: [PATCH 0004/1190] Finalize dynamic dark mode switching Make QMenuBar items spaced identically --- src/qt/qdarkstyle/dark/darkstyle.qss | 3 ++- src/qt/qt_mainwindow.hpp | 1 + src/qt/qt_styleoverride.cpp | 3 ++- src/qt/qt_winrawinputfilter.cpp | 29 ++++++++++++++++++++++++---- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index 96e883b2b..4c433c2a9 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -362,7 +362,8 @@ QMenuBar:focus { QMenuBar::item { background: transparent; - padding: 4px; + padding-left: 7px; + padding-right: 7px; } QMenuBar::item:selected { diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 553f9602c..049747130 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -178,6 +178,7 @@ private: friend class ProgSettings; friend class RendererCommon; friend class RendererStack; // For UI variable access by non-primary renderer windows. + friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. }; #endif // QT_MAINWINDOW_HPP diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index fab111172..60a7162a5 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -56,7 +56,8 @@ StyleOverride::polish(QWidget *widget) } widget->setWindowFlag(Qt::WindowContextHelpButtonHint, false); #ifdef Q_OS_WINDOWS - BOOL DarkMode = TRUE; + extern bool windows_is_light_theme(); + BOOL DarkMode = !windows_is_light_theme(); DwmSetWindowAttribute((HWND)widget->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); #endif } diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 57fd44126..6032c9fca 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -50,11 +51,13 @@ #include <86box/mouse.h> #include <86box/plat.h> #include <86box/86box.h> +#include <86box/video.h> #include #include #include "qt_rendererstack.hpp" +#include "ui_qt_mainwindow.h" bool windows_is_light_theme() { // based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application @@ -170,13 +173,31 @@ WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *mess QTextStream ts(&f); qApp->setStyleSheet(ts.readAll()); } - // From Dolphin emulator code: - // TODO: When switching from light to dark, the window decorations remain light. Qt seems very - // convinced that it needs to change these in response to this message, so even if we set them - // to dark here, Qt sets them back to light afterwards. + QTimer::singleShot(1000, [this] () { + BOOL DarkMode = TRUE; + DwmSetWindowAttribute((HWND)window->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); + window->ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api); + for (int i = 1; i < MONITORS_NUM; i++) { + if (window->renderers[i] && !window->renderers[i]->isHidden()) + window->renderers[i]->switchRenderer((RendererStack::Renderer) vid_api); + } + }); } else { qApp->setStyleSheet(""); + QTimer::singleShot(1000, [this] () { + BOOL DarkMode = FALSE; + DwmSetWindowAttribute((HWND)window->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); + }); } + + QTimer::singleShot(1000, [this] () { + window->resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); + for (int i = 1; i < MONITORS_NUM; i++) { + if (window->renderers[i] && !window->renderers[i]->isHidden()) { + window->resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i); + } + } + }); } /* Stop processing of Alt-F4 */ From b6582383337e926c719c96a9ee36b9100d42d074 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 16 Jan 2024 17:11:33 +0600 Subject: [PATCH 0005/1190] Force all widgets to be embedded windows on Windows --- src/qt/qt_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index afe3a9469..b9e608103 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -176,6 +176,7 @@ main(int argc, char *argv[]) #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); + QApplication::SetAttribute(Qt::AA_NativeWindows); if (!windows_is_light_theme()) { QFile f(":qdarkstyle/dark/darkstyle.qss"); From 25ec6f65c45001bb4669b584e4722df6688c1a6c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 17 Jan 2024 00:40:35 +0600 Subject: [PATCH 0006/1190] Fix incorrect casing --- src/qt/qt_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index b9e608103..23fafc3ce 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -176,7 +176,7 @@ main(int argc, char *argv[]) #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); - QApplication::SetAttribute(Qt::AA_NativeWindows); + QApplication::setAttribute(Qt::AA_NativeWindows); if (!windows_is_light_theme()) { QFile f(":qdarkstyle/dark/darkstyle.qss"); From fe3aab2a0e6c32b0ef377a676b601dec1de479e6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 17 Jan 2024 00:56:07 +0600 Subject: [PATCH 0007/1190] Only the main window and its childs should be native widgets --- src/qt/qt_main.cpp | 1 - src/qt/qt_styleoverride.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 23fafc3ce..afe3a9469 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -176,7 +176,6 @@ main(int argc, char *argv[]) #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); - QApplication::setAttribute(Qt::AA_NativeWindows); if (!windows_is_light_theme()) { QFile f(":qdarkstyle/dark/darkstyle.qss"); diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index 60a7162a5..43a9d9980 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -16,6 +16,8 @@ */ #include "qt_styleoverride.hpp" +#include "qt_mainwindow.hpp" + #include #include @@ -26,6 +28,8 @@ #endif #endif +extern MainWindow* main_window; + int StyleOverride::styleHint( StyleHint hint, @@ -59,6 +63,9 @@ StyleOverride::polish(QWidget *widget) extern bool windows_is_light_theme(); BOOL DarkMode = !windows_is_light_theme(); DwmSetWindowAttribute((HWND)widget->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); + if (main_window->isAncestorOf(widget)) { + widget->setAttribute(Qt::WA_NativeWindow); + } #endif } From 50e1a8846362d4bb94d87a1ebcea58ae53d9a2b1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 17 Jan 2024 01:26:11 +0600 Subject: [PATCH 0008/1190] Revert "Only the main window and its childs should be native widgets" This reverts commit fe3aab2a0e6c32b0ef377a676b601dec1de479e6. --- src/qt/qt_main.cpp | 1 + src/qt/qt_styleoverride.cpp | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index afe3a9469..23fafc3ce 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -176,6 +176,7 @@ main(int argc, char *argv[]) #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); + QApplication::setAttribute(Qt::AA_NativeWindows); if (!windows_is_light_theme()) { QFile f(":qdarkstyle/dark/darkstyle.qss"); diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index 43a9d9980..60a7162a5 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -16,8 +16,6 @@ */ #include "qt_styleoverride.hpp" -#include "qt_mainwindow.hpp" - #include #include @@ -28,8 +26,6 @@ #endif #endif -extern MainWindow* main_window; - int StyleOverride::styleHint( StyleHint hint, @@ -63,9 +59,6 @@ StyleOverride::polish(QWidget *widget) extern bool windows_is_light_theme(); BOOL DarkMode = !windows_is_light_theme(); DwmSetWindowAttribute((HWND)widget->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); - if (main_window->isAncestorOf(widget)) { - widget->setAttribute(Qt::WA_NativeWindow); - } #endif } From dd37f51aace6a0a99a6bee425e1069c114b014d3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 17 Jan 2024 01:28:33 +0600 Subject: [PATCH 0009/1190] Grayscale colors --- src/qt/qdarkstyle/dark/darkstyle.qss | 715 ++++++++++++++------------- 1 file changed, 359 insertions(+), 356 deletions(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index 4c433c2a9..d119b5410 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -22,6 +22,9 @@ See Qt documentation: Resetting everything helps to unify styles across different operating systems --------------------------------------------------------------------------- */ + +/* Changed to be fully grayscale. */ + * { padding: 0px; margin: 0px; @@ -41,27 +44,27 @@ QToolBar * { --------------------------------------------------------------------------- */ QWidget { - background-color: #19232D; - border: 0px solid #455364; + background-color: #222222; + border: 0px solid #525252; padding: 0px; - color: #DFE1E2; - selection-background-color: #346792; - selection-color: #DFE1E2; + color: #E3E3E3; + selection-background-color: #616161; + selection-color: #E3E3E3; } QWidget:disabled { - background-color: #19232D; - color: #788D9C; - selection-background-color: #26486B; - selection-color: #788D9C; + background-color: #222222; + color: #8B8B8B; + selection-background-color: #444444; + selection-color: #8B8B8B; } QWidget::item:selected { - background-color: #346792; + background-color: #616161; } QWidget::item:hover:!selected { - background-color: #1A72BB; + background-color: #666666; } /* QMainWindow ------------------------------------------------------------ @@ -71,15 +74,15 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow --------------------------------------------------------------------------- */ QMainWindow::separator { - background-color: #455364; - border: 0px solid #19232D; + background-color: #525252; + border: 0px solid #222222; spacing: 0px; padding: 2px; } QMainWindow::separator:hover { - background-color: #60798B; - border: 0px solid #1A72BB; + background-color: #767676; + border: 0px solid #666666; } QMainWindow::separator:horizontal { @@ -102,8 +105,8 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip --------------------------------------------------------------------------- */ QToolTip { - background-color: #346792; - color: #DFE1E2; + background-color: #616161; + color: #E3E3E3; /* If you remove the border property, background stops working on Windows */ border: none; /* Remove padding, for fix combo box tooltip */ @@ -117,9 +120,9 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar --------------------------------------------------------------------------- */ QStatusBar { - border: 1px solid #455364; + border: 1px solid #525252; /* Fixes Spyder #9120, #9121 */ - background: #455364; + background: #525252; /* Fixes #205, white vertical borders separating items */ } @@ -128,9 +131,9 @@ QStatusBar::item { } QStatusBar QToolTip { - background-color: #1A72BB; - border: 1px solid #19232D; - color: #19232D; + background-color: #666666; + border: 1px solid #222222; + color: #222222; /* Remove padding, for fix combo box tooltip */ padding: 0px; /* Reducing transparency to read better */ @@ -149,8 +152,8 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox --------------------------------------------------------------------------- */ QCheckBox { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; spacing: 4px; outline: none; padding-top: 4px; @@ -162,8 +165,8 @@ QCheckBox:focus { } QCheckBox QWidget:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; } QCheckBox::indicator { @@ -217,7 +220,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox --------------------------------------------------------------------------- */ QGroupBox { font-weight: bold; - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; padding: 2px; margin-top: 6px; @@ -275,8 +278,8 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton --------------------------------------------------------------------------- */ QRadioButton { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; spacing: 4px; padding-top: 4px; padding-bottom: 4px; @@ -289,15 +292,15 @@ QRadioButton:focus { } QRadioButton:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; border: none; outline: none; } QRadioButton QWidget { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; spacing: 0px; padding: 0px; outline: none; @@ -349,15 +352,15 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar --------------------------------------------------------------------------- */ QMenuBar { - background-color: #19232D; + background-color: #222222; padding: 2px; - border: 1px solid #455364; - color: #DFE1E2; - selection-background-color: #1A72BB; + border: 1px solid #525252; + color: #E3E3E3; + selection-background-color: #666666; } QMenuBar:focus { - border: 1px solid #346792; + border: 1px solid #616161; } QMenuBar::item { @@ -369,15 +372,15 @@ QMenuBar::item { QMenuBar::item:selected { padding: 4px; background: transparent; - border: 0px solid #455364; - background-color: #1A72BB; + border: 0px solid #525252; + background-color: #666666; } QMenuBar::item:pressed { padding: 4px; - border: 0px solid #455364; - background-color: #1A72BB; - color: #DFE1E2; + border: 0px solid #525252; + background-color: #666666; + color: #E3E3E3; } /* QMenu ------------------------------------------------------------------ @@ -386,33 +389,33 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu --------------------------------------------------------------------------- */ QMenu { - border: 0px solid #455364; - color: #DFE1E2; + border: 0px solid #525252; + color: #E3E3E3; margin: 0px; - background-color: #37414F; - selection-background-color: #1A72BB; + background-color: #414141; + selection-background-color: #666666; } QMenu::separator { height: 1px; - background-color: #60798B; - color: #DFE1E2; + background-color: #767676; + color: #E3E3E3; } QMenu::item { - background-color: #37414F; + background-color: #414141; padding: 4px 24px 4px 28px; /* Reserve space for selection border */ - border: 1px transparent #455364; + border: 1px transparent #525252; } QMenu::item:selected { - color: #DFE1E2; - background-color: #1A72BB; + color: #E3E3E3; + background-color: #666666; } QMenu::item:pressed { - background-color: #1A72BB; + background-color: #666666; } QMenu::icon { @@ -512,9 +515,9 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox --------------------------------------------------------------------------- */ QAbstractItemView { - alternate-background-color: #19232D; - color: #DFE1E2; - border: 1px solid #455364; + alternate-background-color: #222222; + color: #E3E3E3; + border: 1px solid #525252; border-radius: 4px; } @@ -528,24 +531,24 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea --------------------------------------------------------------------------- */ QAbstractScrollArea { - background-color: #19232D; - border: 1px solid #455364; + background-color: #222222; + border: 1px solid #525252; border-radius: 4px; /* fix #159 */ padding: 2px; /* remove min-height to fix #244 */ - color: #DFE1E2; + color: #E3E3E3; } QAbstractScrollArea:disabled { - color: #788D9C; + color: #8B8B8B; } /* QScrollArea ------------------------------------------------------------ --------------------------------------------------------------------------- */ QScrollArea QWidget QWidget:disabled { - background-color: #19232D; + background-color: #222222; } /* QScrollBar ------------------------------------------------------------- @@ -556,53 +559,53 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar QScrollBar:horizontal { height: 16px; margin: 2px 16px 2px 16px; - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; - background-color: #19232D; + background-color: #222222; } QScrollBar:vertical { - background-color: #19232D; + background-color: #222222; width: 16px; margin: 16px 2px 16px 2px; - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; } QScrollBar::handle:horizontal { - background-color: #60798B; - border: 1px solid #455364; + background-color: #767676; + border: 1px solid #525252; border-radius: 4px; min-width: 8px; } QScrollBar::handle:horizontal:hover { - background-color: #346792; - border: #346792; + background-color: #616161; + border: #616161; border-radius: 4px; min-width: 8px; } QScrollBar::handle:horizontal:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QScrollBar::handle:vertical { - background-color: #60798B; - border: 1px solid #455364; + background-color: #767676; + border: 1px solid #525252; min-height: 8px; border-radius: 4px; } QScrollBar::handle:vertical:hover { - background-color: #346792; - border: #346792; + background-color: #616161; + border: #616161; border-radius: 4px; min-height: 8px; } QScrollBar::handle:vertical:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QScrollBar::add-line:horizontal { @@ -695,38 +698,38 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets --------------------------------------------------------------------------- */ QTextEdit { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; border-radius: 4px; - border: 1px solid #455364; + border: 1px solid #525252; } QTextEdit:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QTextEdit:selected { - background: #346792; - color: #455364; + background: #616161; + color: #525252; } /* QPlainTextEdit --------------------------------------------------------- --------------------------------------------------------------------------- */ QPlainTextEdit { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; border-radius: 4px; - border: 1px solid #455364; + border: 1px solid #525252; } QPlainTextEdit:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QPlainTextEdit:selected { - background: #346792; - color: #455364; + background: #616161; + color: #525252; } /* QSizeGrip -------------------------------------------------------------- @@ -747,8 +750,8 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar --------------------------------------------------------------------------- */ QToolBar { - background-color: #19232D; - border-bottom: 1px solid #19232D; + background-color: #222222; + border-bottom: 1px solid #222222; padding: 1px; font-weight: bold; spacing: 2px; @@ -756,7 +759,7 @@ QToolBar { QToolBar:disabled { /* Fixes #272 */ - background-color: #19232D; + background-color: #222222; } QToolBar::handle:horizontal { @@ -780,9 +783,9 @@ QToolBar::separator:vertical { } QToolButton#qt_toolbar_ext_button { - background: #19232D; + background: #222222; border: 0px; - color: #DFE1E2; + color: #E3E3E3; image: url(":/qss_icons/dark/rc/arrow_right.png"); } @@ -790,9 +793,9 @@ QToolButton#qt_toolbar_ext_button { --------------------------------------------------------------------------- */ QAbstractSpinBox { - background-color: #19232D; - border: 1px solid #455364; - color: #DFE1E2; + background-color: #222222; + border: 1px solid #525252; + color: #E3E3E3; /* This fixes 103, 111 */ padding-top: 2px; /* This fixes 103, 111 */ @@ -804,11 +807,11 @@ QAbstractSpinBox { } QAbstractSpinBox:up-button { - background-color: transparent #19232D; + background-color: transparent #222222; subcontrol-origin: border; subcontrol-position: top right; - border-left: 1px solid #455364; - border-bottom: 1px solid #455364; + border-left: 1px solid #525252; + border-bottom: 1px solid #525252; border-top-left-radius: 0; border-bottom-left-radius: 0; margin: 1px; @@ -827,11 +830,11 @@ QAbstractSpinBox::up-arrow:hover { } QAbstractSpinBox:down-button { - background-color: transparent #19232D; + background-color: transparent #222222; subcontrol-origin: border; subcontrol-position: bottom right; - border-left: 1px solid #455364; - border-top: 1px solid #455364; + border-left: 1px solid #525252; + border-top: 1px solid #525252; border-top-left-radius: 0; border-bottom-left-radius: 0; margin: 1px; @@ -850,17 +853,17 @@ QAbstractSpinBox::down-arrow:hover { } QAbstractSpinBox:hover { - border: 1px solid #346792; - color: #DFE1E2; + border: 1px solid #616161; + color: #E3E3E3; } QAbstractSpinBox:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QAbstractSpinBox:selected { - background: #346792; - color: #455364; + background: #616161; + color: #525252; } /* ------------------------------------------------------------------------ */ @@ -872,17 +875,17 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe --------------------------------------------------------------------------- */ QLabel { - background-color: #19232D; - border: 0px solid #455364; + background-color: #222222; + border: 0px solid #525252; padding: 2px; margin: 0px; - color: #DFE1E2; + color: #E3E3E3; } QLabel:disabled { - background-color: #19232D; - border: 0px solid #455364; - color: #788D9C; + background-color: #222222; + border: 0px solid #525252; + color: #8B8B8B; } /* QTextBrowser ----------------------------------------------------------- @@ -891,68 +894,68 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea --------------------------------------------------------------------------- */ QTextBrowser { - background-color: #19232D; - border: 1px solid #455364; - color: #DFE1E2; + background-color: #222222; + border: 1px solid #525252; + color: #E3E3E3; border-radius: 4px; } QTextBrowser:disabled { - background-color: #19232D; - border: 1px solid #455364; - color: #788D9C; + background-color: #222222; + border: 1px solid #525252; + color: #8B8B8B; border-radius: 4px; } QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { - border: 1px solid #455364; + border: 1px solid #525252; } /* QGraphicsView ---------------------------------------------------------- --------------------------------------------------------------------------- */ QGraphicsView { - background-color: #19232D; - border: 1px solid #455364; - color: #DFE1E2; + background-color: #222222; + border: 1px solid #525252; + color: #E3E3E3; border-radius: 4px; } QGraphicsView:disabled { - background-color: #19232D; - border: 1px solid #455364; - color: #788D9C; + background-color: #222222; + border: 1px solid #525252; + color: #8B8B8B; border-radius: 4px; } QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { - border: 1px solid #455364; + border: 1px solid #525252; } /* QCalendarWidget -------------------------------------------------------- --------------------------------------------------------------------------- */ QCalendarWidget { - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; } QCalendarWidget:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; } /* QLCDNumber ------------------------------------------------------------- --------------------------------------------------------------------------- */ QLCDNumber { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; } QLCDNumber:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; } /* QProgressBar ----------------------------------------------------------- @@ -961,30 +964,30 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar --------------------------------------------------------------------------- */ QProgressBar { - background-color: #19232D; - border: 1px solid #455364; - color: #DFE1E2; + background-color: #222222; + border: 1px solid #525252; + color: #E3E3E3; border-radius: 4px; text-align: center; } QProgressBar:disabled { - background-color: #19232D; - border: 1px solid #455364; - color: #788D9C; + background-color: #222222; + border: 1px solid #525252; + color: #8B8B8B; border-radius: 4px; text-align: center; } QProgressBar::chunk { - background-color: #346792; - color: #19232D; + background-color: #616161; + color: #222222; border-radius: 4px; } QProgressBar::chunk:disabled { - background-color: #26486B; - color: #788D9C; + background-color: #444444; + color: #8B8B8B; border-radius: 4px; } @@ -997,8 +1000,8 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton --------------------------------------------------------------------------- */ QPushButton { - background-color: #455364; - color: #DFE1E2; + background-color: #525252; + color: #E3E3E3; border-radius: 4px; padding: 2px; outline: none; @@ -1006,43 +1009,43 @@ QPushButton { } QPushButton:disabled { - background-color: #455364; - color: #788D9C; + background-color: #525252; + color: #8B8B8B; border-radius: 4px; padding: 2px; } QPushButton:checked { - background-color: #60798B; + background-color: #767676; border-radius: 4px; padding: 2px; outline: none; } QPushButton:checked:disabled { - background-color: #60798B; - color: #788D9C; + background-color: #767676; + color: #8B8B8B; border-radius: 4px; padding: 2px; outline: none; } QPushButton:checked:selected { - background: #60798B; + background: #767676; } QPushButton:hover { - background-color: #54687A; - color: #DFE1E2; + background-color: #666666; + color: #E3E3E3; } QPushButton:pressed { - background-color: #60798B; + background-color: #767676; } QPushButton:selected { - background: #60798B; - color: #DFE1E2; + background: #767676; + color: #E3E3E3; } QPushButton::menu-indicator { @@ -1062,8 +1065,8 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton --------------------------------------------------------------------------- */ QToolButton { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; border-radius: 4px; padding: 2px; outline: none; @@ -1074,53 +1077,53 @@ QToolButton { } QToolButton:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; border-radius: 4px; padding: 2px; } QToolButton:checked { - background-color: #60798B; + background-color: #767676; border-radius: 4px; padding: 2px; outline: none; } QToolButton:checked:disabled { - background-color: #60798B; - color: #788D9C; + background-color: #767676; + color: #8B8B8B; border-radius: 4px; padding: 2px; outline: none; } QToolButton:checked:hover { - background-color: #54687A; - color: #DFE1E2; + background-color: #666666; + color: #E3E3E3; } QToolButton:checked:pressed { - background-color: #60798B; + background-color: #767676; } QToolButton:checked:selected { - background: #60798B; - color: #DFE1E2; + background: #767676; + color: #E3E3E3; } QToolButton:hover { - background-color: #54687A; - color: #DFE1E2; + background-color: #666666; + color: #E3E3E3; } QToolButton:pressed { - background-color: #60798B; + background-color: #767676; } QToolButton:selected { - background: #60798B; - color: #DFE1E2; + background: #767676; + color: #E3E3E3; } QToolButton[popupMode="0"] { @@ -1139,7 +1142,7 @@ QToolButton[popupMode="1"]::menu-button { QToolButton[popupMode="1"]::menu-button:hover { border: none; - border-left: 1px solid #455364; + border-left: 1px solid #525252; border-radius: 0; } @@ -1157,11 +1160,11 @@ QToolButton::menu-button { } QToolButton::menu-button:hover { - border: 1px solid #346792; + border: 1px solid #616161; } QToolButton::menu-button:checked:hover { - border: 1px solid #346792; + border: 1px solid #616161; } QToolButton::menu-indicator { @@ -1189,8 +1192,8 @@ QToolButton::menu-arrow:hover { --------------------------------------------------------------------------- */ QCommandLinkButton { background-color: transparent; - border: 1px solid #455364; - color: #DFE1E2; + border: 1px solid #525252; + color: #E3E3E3; border-radius: 4px; padding: 0px; margin: 0px; @@ -1198,7 +1201,7 @@ QCommandLinkButton { QCommandLinkButton:disabled { background-color: transparent; - color: #788D9C; + color: #8B8B8B; } /* ------------------------------------------------------------------------ */ @@ -1210,9 +1213,9 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox --------------------------------------------------------------------------- */ QComboBox { - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; - selection-background-color: #346792; + selection-background-color: #616161; padding-left: 4px; padding-right: 4px; /* padding-right = 36; 4 + 16*2 See scrollbar size */ @@ -1226,41 +1229,41 @@ QComboBox { } QComboBox QAbstractItemView { - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 0; - background-color: #19232D; - selection-background-color: #346792; + background-color: #222222; + selection-background-color: #616161; } QComboBox QAbstractItemView:hover { - background-color: #19232D; - color: #DFE1E2; + background-color: #222222; + color: #E3E3E3; } QComboBox QAbstractItemView:selected { - background: #346792; - color: #455364; + background: #616161; + color: #525252; } QComboBox QAbstractItemView:alternate { - background: #19232D; + background: #222222; } QComboBox:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; } QComboBox:hover { - border: 1px solid #346792; + border: 1px solid #616161; } QComboBox:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QComboBox:on { - selection-background-color: #346792; + selection-background-color: #616161; } QComboBox::indicator { @@ -1274,7 +1277,7 @@ QComboBox::indicator { } QComboBox::indicator:alternate { - background: #19232D; + background: #222222; } QComboBox::item { @@ -1290,14 +1293,14 @@ QComboBox::item { } QComboBox::item:alternate { - background: #19232D; + background: #222222; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; width: 12px; - border-left: 1px solid #455364; + border-left: 1px solid #525252; } QComboBox::down-arrow { @@ -1316,7 +1319,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider --------------------------------------------------------------------------- */ QSlider:disabled { - background: #19232D; + background: #222222; } QSlider:focus { @@ -1324,48 +1327,48 @@ QSlider:focus { } QSlider::groove:horizontal { - background: #455364; - border: 1px solid #455364; + background: #525252; + border: 1px solid #525252; height: 4px; margin: 0px; border-radius: 4px; } QSlider::groove:vertical { - background: #455364; - border: 1px solid #455364; + background: #525252; + border: 1px solid #525252; width: 4px; margin: 0px; border-radius: 4px; } QSlider::add-page:vertical { - background: #346792; - border: 1px solid #455364; + background: #616161; + border: 1px solid #525252; width: 4px; margin: 0px; border-radius: 4px; } QSlider::add-page:vertical :disabled { - background: #26486B; + background: #444444; } QSlider::sub-page:horizontal { - background: #346792; - border: 1px solid #455364; + background: #616161; + border: 1px solid #525252; height: 4px; margin: 0px; border-radius: 4px; } QSlider::sub-page:horizontal:disabled { - background: #26486B; + background: #444444; } QSlider::handle:horizontal { - background: #9DA9B5; - border: 1px solid #455364; + background: #A9A9A9; + border: 1px solid #525252; width: 8px; height: 8px; margin: -8px 0px; @@ -1373,17 +1376,17 @@ QSlider::handle:horizontal { } QSlider::handle:horizontal:hover { - background: #346792; - border: 1px solid #346792; + background: #616161; + border: 1px solid #616161; } QSlider::handle:horizontal:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QSlider::handle:vertical { - background: #9DA9B5; - border: 1px solid #455364; + background: #A9A9A9; + border: 1px solid #525252; width: 8px; height: 8px; margin: 0 -8px; @@ -1391,12 +1394,12 @@ QSlider::handle:vertical { } QSlider::handle:vertical:hover { - background: #346792; - border: 1px solid #346792; + background: #616161; + border: 1px solid #616161; } QSlider::handle:vertical:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } /* QLineEdit -------------------------------------------------------------- @@ -1405,7 +1408,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit --------------------------------------------------------------------------- */ QLineEdit { - background-color: #19232D; + background-color: #222222; padding-top: 2px; /* This QLineEdit fix 103, 111 */ padding-bottom: 2px; @@ -1413,28 +1416,28 @@ QLineEdit { padding-left: 4px; padding-right: 4px; border-style: solid; - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; - color: #DFE1E2; + color: #E3E3E3; } QLineEdit:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; } QLineEdit:hover { - border: 1px solid #346792; - color: #DFE1E2; + border: 1px solid #616161; + color: #E3E3E3; } QLineEdit:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QLineEdit:selected { - background-color: #346792; - color: #455364; + background-color: #616161; + color: #525252; } /* QTabWiget -------------------------------------------------------------- @@ -1444,7 +1447,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabb --------------------------------------------------------------------------- */ QTabWidget { padding: 2px; - selection-background-color: #455364; + selection-background-color: #525252; } QTabWidget QWidget { @@ -1453,7 +1456,7 @@ QTabWidget QWidget { } QTabWidget::pane { - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; margin: 0px; /* Fixes double border inside pane with pyqt5 */ @@ -1461,8 +1464,8 @@ QTabWidget::pane { } QTabWidget::pane:selected { - background-color: #455364; - border: 1px solid #346792; + background-color: #525252; + border: 1px solid #616161; } /* QTabBar ---------------------------------------------------------------- @@ -1500,104 +1503,104 @@ QTabBar::tab, QDockWidget QTabBar::tab { } QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { - border-bottom: 3px solid #26486B; - color: #788D9C; - background-color: #455364; + border-bottom: 3px solid #444444; + color: #8B8B8B; + background-color: #525252; } QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { - border-top: 3px solid #26486B; - color: #788D9C; - background-color: #455364; + border-top: 3px solid #444444; + color: #8B8B8B; + background-color: #525252; } QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { - border-right: 3px solid #26486B; - color: #788D9C; - background-color: #455364; + border-right: 3px solid #444444; + color: #8B8B8B; + background-color: #525252; } QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { - border-left: 3px solid #26486B; - color: #788D9C; - background-color: #455364; + border-left: 3px solid #444444; + color: #8B8B8B; + background-color: #525252; } QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { - border-bottom: 3px solid #19232D; - color: #788D9C; - background-color: #19232D; + border-bottom: 3px solid #222222; + color: #8B8B8B; + background-color: #222222; } QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { - border-top: 3px solid #19232D; - color: #788D9C; - background-color: #19232D; + border-top: 3px solid #222222; + color: #8B8B8B; + background-color: #222222; } QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { - border-right: 3px solid #19232D; - color: #788D9C; - background-color: #19232D; + border-right: 3px solid #222222; + color: #8B8B8B; + background-color: #222222; } QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { - border-left: 3px solid #19232D; - color: #788D9C; - background-color: #19232D; + border-left: 3px solid #222222; + color: #8B8B8B; + background-color: #222222; } QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { - border-bottom: 2px solid #19232D; + border-bottom: 2px solid #222222; margin-top: 2px; } QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { - border-top: 2px solid #19232D; + border-top: 2px solid #222222; margin-bottom: 2px; } QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { - border-left: 2px solid #19232D; + border-left: 2px solid #222222; margin-right: 2px; } QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { - border-right: 2px solid #19232D; + border-right: 2px solid #222222; margin-left: 2px; } QTabBar::tab:top, QDockWidget QTabBar::tab:top { - background-color: #455364; + background-color: #525252; margin-left: 2px; padding-left: 4px; padding-right: 4px; padding-top: 2px; padding-bottom: 2px; min-width: 5px; - border-bottom: 3px solid #455364; + border-bottom: 3px solid #525252; border-top-left-radius: 4px; border-top-right-radius: 4px; } QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { - background-color: #54687A; - border-bottom: 3px solid #259AE9; + background-color: #666666; + border-bottom: 3px solid #898989; border-top-left-radius: 4px; border-top-right-radius: 4px; } QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { - border: 1px solid #1A72BB; - border-bottom: 3px solid #1A72BB; + border: 1px solid #666666; + border-bottom: 3px solid #666666; /* Fixes spyder-ide/spyder#9766 and #243 */ padding-left: 3px; padding-right: 3px; } QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { - border-top: 3px solid #455364; - background-color: #455364; + border-top: 3px solid #525252; + background-color: #525252; margin-left: 2px; padding-left: 4px; padding-right: 4px; @@ -1609,22 +1612,22 @@ QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { } QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { - background-color: #54687A; - border-top: 3px solid #259AE9; + background-color: #666666; + border-top: 3px solid #898989; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; } QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { - border: 1px solid #1A72BB; - border-top: 3px solid #1A72BB; + border: 1px solid #666666; + border-top: 3px solid #666666; /* Fixes spyder-ide/spyder#9766 and #243 */ padding-left: 3px; padding-right: 3px; } QTabBar::tab:left, QDockWidget QTabBar::tab:left { - background-color: #455364; + background-color: #525252; margin-top: 2px; padding-left: 2px; padding-right: 2px; @@ -1636,20 +1639,20 @@ QTabBar::tab:left, QDockWidget QTabBar::tab:left { } QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { - background-color: #54687A; - border-right: 3px solid #259AE9; + background-color: #666666; + border-right: 3px solid #898989; } QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { - border: 1px solid #1A72BB; - border-right: 3px solid #1A72BB; + border: 1px solid #666666; + border-right: 3px solid #666666; /* Fixes different behavior #271 */ margin-right: 0px; padding-right: -1px; } QTabBar::tab:right, QDockWidget QTabBar::tab:right { - background-color: #455364; + background-color: #525252; margin-top: 2px; padding-left: 2px; padding-right: 2px; @@ -1661,13 +1664,13 @@ QTabBar::tab:right, QDockWidget QTabBar::tab:right { } QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { - background-color: #54687A; - border-left: 3px solid #259AE9; + background-color: #666666; + border-left: 3px solid #898989; } QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { - border: 1px solid #1A72BB; - border-left: 3px solid #1A72BB; + border: 1px solid #666666; + border-left: 3px solid #666666; /* Fixes different behavior #271 */ margin-left: 0px; padding-left: 0px; @@ -1675,17 +1678,17 @@ QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hov QTabBar QToolButton, QDockWidget QTabBar QToolButton { /* Fixes #136 */ - background-color: #455364; + background-color: #525252; height: 12px; width: 12px; } QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { - background-color: #455364; + background-color: #525252; } QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { - border: 1px solid #346792; + border: 1px solid #616161; } QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { @@ -1708,9 +1711,9 @@ QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::righ --------------------------------------------------------------------------- */ QDockWidget { - outline: 1px solid #455364; - background-color: #19232D; - border: 1px solid #455364; + outline: 1px solid #525252; + background-color: #222222; + border: 1px solid #525252; border-radius: 4px; titlebar-close-icon: url(":/qss_icons/dark/rc/transparent.png"); titlebar-normal-icon: url(":/qss_icons/dark/rc/transparent.png"); @@ -1721,7 +1724,7 @@ QDockWidget::title { padding: 3px; spacing: 4px; border: none; - background-color: #455364; + background-color: #525252; } QDockWidget::close-button { @@ -1867,10 +1870,10 @@ QTreeView, QListView, QTableView, QColumnView { - background-color: #19232D; - border: 1px solid #455364; - color: #DFE1E2; - gridline-color: #455364; + background-color: #222222; + border: 1px solid #525252; + color: #E3E3E3; + gridline-color: #525252; border-radius: 4px; } @@ -1878,45 +1881,45 @@ QTreeView:disabled, QListView:disabled, QTableView:disabled, QColumnView:disabled { - background-color: #19232D; - color: #788D9C; + background-color: #222222; + color: #8B8B8B; } QTreeView:selected, QListView:selected, QTableView:selected, QColumnView:selected { - background-color: #346792; - color: #455364; + background-color: #616161; + color: #525252; } QTreeView:focus, QListView:focus, QTableView:focus, QColumnView:focus { - border: 1px solid #1A72BB; + border: 1px solid #666666; } QTreeView::item:pressed, QListView::item:pressed, QTableView::item:pressed, QColumnView::item:pressed { - background-color: #346792; + background-color: #616161; } QTreeView::item:selected:active, QListView::item:selected:active, QTableView::item:selected:active, QColumnView::item:selected:active { - background-color: #346792; + background-color: #616161; } QTreeView::item:selected:!active, QListView::item:selected:!active, QTableView::item:selected:!active, QColumnView::item:selected:!active { - color: #DFE1E2; - background-color: #37414F; + color: #E3E3E3; + background-color: #414141; } QTreeView::item:!selected:hover, @@ -1924,13 +1927,13 @@ QListView::item:!selected:hover, QTableView::item:!selected:hover, QColumnView::item:!selected:hover { outline: 0; - color: #DFE1E2; - background-color: #37414F; + color: #E3E3E3; + background-color: #414141; } QTableCornerButton::section { - background-color: #19232D; - border: 1px transparent #455364; + background-color: #222222; + border: 1px transparent #525252; border-radius: 0px; } @@ -1940,21 +1943,21 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview --------------------------------------------------------------------------- */ QHeaderView { - background-color: #455364; - border: 0px transparent #455364; + background-color: #525252; + border: 0px transparent #525252; padding: 0; margin: 0; border-radius: 0; } QHeaderView:disabled { - background-color: #455364; - border: 1px transparent #455364; + background-color: #525252; + border: 1px transparent #525252; } QHeaderView::section { - background-color: #455364; - color: #DFE1E2; + background-color: #525252; + color: #E3E3E3; border-radius: 0; text-align: left; font-size: 13px; @@ -1965,15 +1968,15 @@ QHeaderView::section::horizontal { padding-bottom: 0; padding-left: 4px; padding-right: 4px; - border-left: 1px solid #19232D; + border-left: 1px solid #222222; } QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { - border-left: 1px solid #455364; + border-left: 1px solid #525252; } QHeaderView::section::horizontal:disabled { - color: #788D9C; + color: #8B8B8B; } QHeaderView::section::vertical { @@ -1981,21 +1984,21 @@ QHeaderView::section::vertical { padding-bottom: 0; padding-left: 4px; padding-right: 4px; - border-top: 1px solid #19232D; + border-top: 1px solid #222222; } QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { - border-top: 1px solid #455364; + border-top: 1px solid #525252; } QHeaderView::section::vertical:disabled { - color: #788D9C; + color: #8B8B8B; } QHeaderView::down-arrow { /* Those settings (border/width/height/background-color) solve bug */ /* transparent arrow background and size */ - background-color: #455364; + background-color: #525252; border: none; height: 12px; width: 12px; @@ -2005,7 +2008,7 @@ QHeaderView::down-arrow { } QHeaderView::up-arrow { - background-color: #455364; + background-color: #525252; border: none; height: 12px; width: 12px; @@ -2022,54 +2025,54 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox QToolBox { padding: 0px; border: 0px; - border: 1px solid #455364; + border: 1px solid #525252; } QToolBox:selected { padding: 0px; - border: 2px solid #346792; + border: 2px solid #616161; } QToolBox::tab { - background-color: #19232D; - border: 1px solid #455364; - color: #DFE1E2; + background-color: #222222; + border: 1px solid #525252; + color: #E3E3E3; border-top-left-radius: 4px; border-top-right-radius: 4px; } QToolBox::tab:disabled { - color: #788D9C; + color: #8B8B8B; } QToolBox::tab:selected { - background-color: #60798B; - border-bottom: 2px solid #346792; + background-color: #767676; + border-bottom: 2px solid #616161; } QToolBox::tab:selected:disabled { - background-color: #455364; - border-bottom: 2px solid #26486B; + background-color: #525252; + border-bottom: 2px solid #444444; } QToolBox::tab:!selected { - background-color: #455364; - border-bottom: 2px solid #455364; + background-color: #525252; + border-bottom: 2px solid #525252; } QToolBox::tab:!selected:disabled { - background-color: #19232D; + background-color: #222222; } QToolBox::tab:hover { - border-color: #1A72BB; - border-bottom: 2px solid #1A72BB; + border-color: #666666; + border-bottom: 2px solid #666666; } QToolBox QScrollArea { padding: 0px; border: 0px; - background-color: #19232D; + background-color: #222222; } /* QFrame ----------------------------------------------------------------- @@ -2083,7 +2086,7 @@ https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color /* (dot) .QFrame fix #141, #126, #123 */ .QFrame { border-radius: 4px; - border: 1px solid #455364; + border: 1px solid #525252; /* No frame */ /* HLine */ /* HLine */ @@ -2091,19 +2094,19 @@ https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color .QFrame[frameShape="0"] { border-radius: 4px; - border: 1px transparent #455364; + border: 1px transparent #525252; } .QFrame[frameShape="4"] { max-height: 2px; border: none; - background-color: #455364; + background-color: #525252; } .QFrame[frameShape="5"] { max-width: 2px; border: none; - background-color: #455364; + background-color: #525252; } /* QSplitter -------------------------------------------------------------- @@ -2112,22 +2115,22 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter --------------------------------------------------------------------------- */ QSplitter { - background-color: #455364; + background-color: #525252; spacing: 0px; padding: 0px; margin: 0px; } QSplitter::handle { - background-color: #455364; - border: 0px solid #19232D; + background-color: #525252; + border: 0px solid #222222; spacing: 0px; padding: 1px; margin: 0px; } QSplitter::handle:hover { - background-color: #9DA9B5; + background-color: #A9A9A9; } QSplitter::handle:horizontal { @@ -2144,9 +2147,9 @@ QSplitter::handle:vertical { --------------------------------------------------------------------------- */ QDateEdit, QDateTimeEdit { - selection-background-color: #346792; + selection-background-color: #616161; border-style: solid; - border: 1px solid #455364; + border: 1px solid #525252; border-radius: 4px; /* This fixes 103, 111 */ padding-top: 2px; @@ -2158,14 +2161,14 @@ QDateEdit, QDateTimeEdit { } QDateEdit:on, QDateTimeEdit:on { - selection-background-color: #346792; + selection-background-color: #616161; } QDateEdit::drop-down, QDateTimeEdit::drop-down { subcontrol-origin: padding; subcontrol-position: top right; width: 12px; - border-left: 1px solid #455364; + border-left: 1px solid #525252; } QDateEdit::down-arrow, QDateTimeEdit::down-arrow { @@ -2179,23 +2182,23 @@ QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:foc } QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { - background-color: #19232D; + background-color: #222222; border-radius: 4px; - border: 1px solid #455364; - selection-background-color: #346792; + border: 1px solid #525252; + selection-background-color: #616161; } /* QAbstractView ---------------------------------------------------------- --------------------------------------------------------------------------- */ QAbstractView:hover { - border: 1px solid #346792; - color: #DFE1E2; + border: 1px solid #616161; + color: #E3E3E3; } QAbstractView:selected { - background: #346792; - color: #455364; + background: #616161; + color: #525252; } /* PlotWidget ------------------------------------------------------------- From 0aebb62726e1cbf090ea3596a7bfd5277792d9e6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 17 Jan 2024 01:34:09 +0600 Subject: [PATCH 0010/1190] Avoid QToolBar spacing --- src/qt/qdarkstyle/dark/darkstyle.qss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index d119b5410..865ce9e66 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -754,7 +754,6 @@ QToolBar { border-bottom: 1px solid #222222; padding: 1px; font-weight: bold; - spacing: 2px; } QToolBar:disabled { From 3374ff4eb2a8c8ed5f323f0a5e07a5b310454160 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 17 Jan 2024 13:37:19 +0600 Subject: [PATCH 0011/1190] Use Windows 11 Notepad's background color --- src/qt/qdarkstyle/dark/darkstyle.qss | 146 +++++++++++++-------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index 865ce9e66..2cbd2e257 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -44,7 +44,7 @@ QToolBar * { --------------------------------------------------------------------------- */ QWidget { - background-color: #222222; + background-color: #272727; border: 0px solid #525252; padding: 0px; color: #E3E3E3; @@ -53,7 +53,7 @@ QWidget { } QWidget:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; selection-background-color: #444444; selection-color: #8B8B8B; @@ -75,7 +75,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow --------------------------------------------------------------------------- */ QMainWindow::separator { background-color: #525252; - border: 0px solid #222222; + border: 0px solid #272727; spacing: 0px; padding: 2px; } @@ -120,9 +120,9 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar --------------------------------------------------------------------------- */ QStatusBar { - border: 1px solid #525252; + border: 1px solid #272727; /* Fixes Spyder #9120, #9121 */ - background: #525252; + background: #272727; /* Fixes #205, white vertical borders separating items */ } @@ -132,8 +132,8 @@ QStatusBar::item { QStatusBar QToolTip { background-color: #666666; - border: 1px solid #222222; - color: #222222; + border: 1px solid #272727; + color: #272727; /* Remove padding, for fix combo box tooltip */ padding: 0px; /* Reducing transparency to read better */ @@ -152,7 +152,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox --------------------------------------------------------------------------- */ QCheckBox { - background-color: #222222; + background-color: #272727; color: #E3E3E3; spacing: 4px; outline: none; @@ -165,7 +165,7 @@ QCheckBox:focus { } QCheckBox QWidget:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; } @@ -278,7 +278,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton --------------------------------------------------------------------------- */ QRadioButton { - background-color: #222222; + background-color: #272727; color: #E3E3E3; spacing: 4px; padding-top: 4px; @@ -292,14 +292,14 @@ QRadioButton:focus { } QRadioButton:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; border: none; outline: none; } QRadioButton QWidget { - background-color: #222222; + background-color: #272727; color: #E3E3E3; spacing: 0px; padding: 0px; @@ -352,7 +352,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar --------------------------------------------------------------------------- */ QMenuBar { - background-color: #222222; + background-color: #272727; padding: 2px; border: 1px solid #525252; color: #E3E3E3; @@ -515,7 +515,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox --------------------------------------------------------------------------- */ QAbstractItemView { - alternate-background-color: #222222; + alternate-background-color: #272727; color: #E3E3E3; border: 1px solid #525252; border-radius: 4px; @@ -531,7 +531,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea --------------------------------------------------------------------------- */ QAbstractScrollArea { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; border-radius: 4px; /* fix #159 */ @@ -548,7 +548,7 @@ QAbstractScrollArea:disabled { --------------------------------------------------------------------------- */ QScrollArea QWidget QWidget:disabled { - background-color: #222222; + background-color: #272727; } /* QScrollBar ------------------------------------------------------------- @@ -561,11 +561,11 @@ QScrollBar:horizontal { margin: 2px 16px 2px 16px; border: 1px solid #525252; border-radius: 4px; - background-color: #222222; + background-color: #272727; } QScrollBar:vertical { - background-color: #222222; + background-color: #272727; width: 16px; margin: 16px 2px 16px 2px; border: 1px solid #525252; @@ -698,7 +698,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets --------------------------------------------------------------------------- */ QTextEdit { - background-color: #222222; + background-color: #272727; color: #E3E3E3; border-radius: 4px; border: 1px solid #525252; @@ -717,7 +717,7 @@ QTextEdit:selected { --------------------------------------------------------------------------- */ QPlainTextEdit { - background-color: #222222; + background-color: #272727; color: #E3E3E3; border-radius: 4px; border: 1px solid #525252; @@ -750,15 +750,15 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar --------------------------------------------------------------------------- */ QToolBar { - background-color: #222222; - border-bottom: 1px solid #222222; + background-color: #272727; + border-bottom: 1px solid #272727; padding: 1px; font-weight: bold; } QToolBar:disabled { /* Fixes #272 */ - background-color: #222222; + background-color: #272727; } QToolBar::handle:horizontal { @@ -782,7 +782,7 @@ QToolBar::separator:vertical { } QToolButton#qt_toolbar_ext_button { - background: #222222; + background: #272727; border: 0px; color: #E3E3E3; image: url(":/qss_icons/dark/rc/arrow_right.png"); @@ -792,7 +792,7 @@ QToolButton#qt_toolbar_ext_button { --------------------------------------------------------------------------- */ QAbstractSpinBox { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #E3E3E3; /* This fixes 103, 111 */ @@ -806,7 +806,7 @@ QAbstractSpinBox { } QAbstractSpinBox:up-button { - background-color: transparent #222222; + background-color: transparent #272727; subcontrol-origin: border; subcontrol-position: top right; border-left: 1px solid #525252; @@ -829,7 +829,7 @@ QAbstractSpinBox::up-arrow:hover { } QAbstractSpinBox:down-button { - background-color: transparent #222222; + background-color: transparent #272727; subcontrol-origin: border; subcontrol-position: bottom right; border-left: 1px solid #525252; @@ -874,7 +874,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe --------------------------------------------------------------------------- */ QLabel { - background-color: #222222; + background-color: #272727; border: 0px solid #525252; padding: 2px; margin: 0px; @@ -882,7 +882,7 @@ QLabel { } QLabel:disabled { - background-color: #222222; + background-color: #272727; border: 0px solid #525252; color: #8B8B8B; } @@ -893,14 +893,14 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea --------------------------------------------------------------------------- */ QTextBrowser { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #E3E3E3; border-radius: 4px; } QTextBrowser:disabled { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #8B8B8B; border-radius: 4px; @@ -914,14 +914,14 @@ QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pre --------------------------------------------------------------------------- */ QGraphicsView { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #E3E3E3; border-radius: 4px; } QGraphicsView:disabled { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #8B8B8B; border-radius: 4px; @@ -940,7 +940,7 @@ QCalendarWidget { } QCalendarWidget:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; } @@ -948,12 +948,12 @@ QCalendarWidget:disabled { --------------------------------------------------------------------------- */ QLCDNumber { - background-color: #222222; + background-color: #272727; color: #E3E3E3; } QLCDNumber:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; } @@ -963,7 +963,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar --------------------------------------------------------------------------- */ QProgressBar { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #E3E3E3; border-radius: 4px; @@ -971,7 +971,7 @@ QProgressBar { } QProgressBar:disabled { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #8B8B8B; border-radius: 4px; @@ -980,7 +980,7 @@ QProgressBar:disabled { QProgressBar::chunk { background-color: #616161; - color: #222222; + color: #272727; border-radius: 4px; } @@ -1064,7 +1064,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton --------------------------------------------------------------------------- */ QToolButton { - background-color: #222222; + background-color: #272727; color: #E3E3E3; border-radius: 4px; padding: 2px; @@ -1076,7 +1076,7 @@ QToolButton { } QToolButton:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; border-radius: 4px; padding: 2px; @@ -1230,12 +1230,12 @@ QComboBox { QComboBox QAbstractItemView { border: 1px solid #525252; border-radius: 0; - background-color: #222222; + background-color: #272727; selection-background-color: #616161; } QComboBox QAbstractItemView:hover { - background-color: #222222; + background-color: #272727; color: #E3E3E3; } @@ -1245,11 +1245,11 @@ QComboBox QAbstractItemView:selected { } QComboBox QAbstractItemView:alternate { - background: #222222; + background: #272727; } QComboBox:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; } @@ -1276,7 +1276,7 @@ QComboBox::indicator { } QComboBox::indicator:alternate { - background: #222222; + background: #272727; } QComboBox::item { @@ -1292,7 +1292,7 @@ QComboBox::item { } QComboBox::item:alternate { - background: #222222; + background: #272727; } QComboBox::drop-down { @@ -1318,7 +1318,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider --------------------------------------------------------------------------- */ QSlider:disabled { - background: #222222; + background: #272727; } QSlider:focus { @@ -1407,7 +1407,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit --------------------------------------------------------------------------- */ QLineEdit { - background-color: #222222; + background-color: #272727; padding-top: 2px; /* This QLineEdit fix 103, 111 */ padding-bottom: 2px; @@ -1421,7 +1421,7 @@ QLineEdit { } QLineEdit:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; } @@ -1526,46 +1526,46 @@ QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:di } QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { - border-bottom: 3px solid #222222; + border-bottom: 3px solid #272727; color: #8B8B8B; - background-color: #222222; + background-color: #272727; } QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { - border-top: 3px solid #222222; + border-top: 3px solid #272727; color: #8B8B8B; - background-color: #222222; + background-color: #272727; } QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { - border-right: 3px solid #222222; + border-right: 3px solid #272727; color: #8B8B8B; - background-color: #222222; + background-color: #272727; } QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { - border-left: 3px solid #222222; + border-left: 3px solid #272727; color: #8B8B8B; - background-color: #222222; + background-color: #272727; } QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { - border-bottom: 2px solid #222222; + border-bottom: 2px solid #272727; margin-top: 2px; } QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { - border-top: 2px solid #222222; + border-top: 2px solid #272727; margin-bottom: 2px; } QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { - border-left: 2px solid #222222; + border-left: 2px solid #272727; margin-right: 2px; } QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { - border-right: 2px solid #222222; + border-right: 2px solid #272727; margin-left: 2px; } @@ -1711,7 +1711,7 @@ QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::righ --------------------------------------------------------------------------- */ QDockWidget { outline: 1px solid #525252; - background-color: #222222; + background-color: #272727; border: 1px solid #525252; border-radius: 4px; titlebar-close-icon: url(":/qss_icons/dark/rc/transparent.png"); @@ -1869,7 +1869,7 @@ QTreeView, QListView, QTableView, QColumnView { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #E3E3E3; gridline-color: #525252; @@ -1880,7 +1880,7 @@ QTreeView:disabled, QListView:disabled, QTableView:disabled, QColumnView:disabled { - background-color: #222222; + background-color: #272727; color: #8B8B8B; } @@ -1931,7 +1931,7 @@ QColumnView::item:!selected:hover { } QTableCornerButton::section { - background-color: #222222; + background-color: #272727; border: 1px transparent #525252; border-radius: 0px; } @@ -1967,7 +1967,7 @@ QHeaderView::section::horizontal { padding-bottom: 0; padding-left: 4px; padding-right: 4px; - border-left: 1px solid #222222; + border-left: 1px solid #272727; } QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { @@ -1983,7 +1983,7 @@ QHeaderView::section::vertical { padding-bottom: 0; padding-left: 4px; padding-right: 4px; - border-top: 1px solid #222222; + border-top: 1px solid #272727; } QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { @@ -2033,7 +2033,7 @@ QToolBox:selected { } QToolBox::tab { - background-color: #222222; + background-color: #272727; border: 1px solid #525252; color: #E3E3E3; border-top-left-radius: 4px; @@ -2060,7 +2060,7 @@ QToolBox::tab:!selected { } QToolBox::tab:!selected:disabled { - background-color: #222222; + background-color: #272727; } QToolBox::tab:hover { @@ -2071,7 +2071,7 @@ QToolBox::tab:hover { QToolBox QScrollArea { padding: 0px; border: 0px; - background-color: #222222; + background-color: #272727; } /* QFrame ----------------------------------------------------------------- @@ -2122,7 +2122,7 @@ QSplitter { QSplitter::handle { background-color: #525252; - border: 0px solid #222222; + border: 0px solid #272727; spacing: 0px; padding: 1px; margin: 0px; @@ -2181,7 +2181,7 @@ QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:foc } QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { - background-color: #222222; + background-color: #272727; border-radius: 4px; border: 1px solid #525252; selection-background-color: #616161; From aea2e4c4a2c872ade297730d6da0a2246d2a93cd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 18 Jan 2024 01:47:12 +0600 Subject: [PATCH 0012/1190] Make it more similar to Windows 10/11 --- src/qt/qdarkstyle/dark/darkstyle.qss | 43 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index 2cbd2e257..6e1ec4b06 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -373,13 +373,13 @@ QMenuBar::item:selected { padding: 4px; background: transparent; border: 0px solid #525252; - background-color: #666666; + background-color: #383838; } QMenuBar::item:pressed { padding: 4px; border: 0px solid #525252; - background-color: #666666; + background-color: #383838; color: #E3E3E3; } @@ -392,7 +392,7 @@ QMenu { border: 0px solid #525252; color: #E3E3E3; margin: 0px; - background-color: #414141; + background-color: #2C2C2C; selection-background-color: #666666; } @@ -403,7 +403,7 @@ QMenu::separator { } QMenu::item { - background-color: #414141; + background-color: #2C2C2C; padding: 4px 24px 4px 28px; /* Reserve space for selection border */ border: 1px transparent #525252; @@ -411,11 +411,11 @@ QMenu::item { QMenu::item:selected { color: #E3E3E3; - background-color: #666666; + background-color: #353535; } QMenu::item:pressed { - background-color: #666666; + background-color: #353535; } QMenu::icon { @@ -999,51 +999,54 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton --------------------------------------------------------------------------- */ QPushButton { - background-color: #525252; + background-color: #333333; color: #E3E3E3; border-radius: 4px; - padding: 2px; + padding: 4px; outline: none; - border: none; + border: 1px solid white; } QPushButton:disabled { - background-color: #525252; + background-color: #333333; color: #8B8B8B; border-radius: 4px; - padding: 2px; + padding: 4px; + border: 1px solid #9B9B9B; } QPushButton:checked { - background-color: #767676; + background-color: #666666; border-radius: 4px; - padding: 2px; + padding: 4px; outline: none; } QPushButton:checked:disabled { - background-color: #767676; + background-color: #525252; color: #8B8B8B; border-radius: 4px; - padding: 2px; + padding: 4px; outline: none; } QPushButton:checked:selected { - background: #767676; + background: #454545; } QPushButton:hover { - background-color: #666666; + background-color: #454545; color: #E3E3E3; + border: 1px solid #9B9B9B; } QPushButton:pressed { - background-color: #767676; + background-color: #666666; + border: 1px solid #9B9B9B; } QPushButton:selected { - background: #767676; + background: #333333; color: #E3E3E3; } @@ -1255,6 +1258,7 @@ QComboBox:disabled { QComboBox:hover { border: 1px solid #616161; + background-color: #454545; } QComboBox:focus { @@ -1263,6 +1267,7 @@ QComboBox:focus { QComboBox:on { selection-background-color: #616161; + background-color: #666666; } QComboBox::indicator { From a8c75fb0af3c4d1dac3ee49b26dc2d7c9aa0239a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:34:51 +0900 Subject: [PATCH 0013/1190] added IBM ESDI Integrated Fixed Disk --- src/disk/hdc.c | 1 + src/disk/hdc_esdi_mca.c | 233 ++++++++++++++++++++++++++++++++++------ 2 files changed, 203 insertions(+), 31 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 908cbce07..3ec6358d8 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -77,6 +77,7 @@ static const struct { { &xtide_acculogic_device }, { &xtide_device }, { &esdi_ps2_device }, + { &esdi_integrated_device }, { &ide_pci_device }, { &ide_pci_2ch_device }, { &ide_vlb_device }, diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index c906c7ca1..047089a1e 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -150,6 +150,11 @@ typedef struct esdi_t { uint8_t pos_regs[8]; } esdi_t; +enum { + ESDI_IS_ADAPTER, + ESDI_IS_INTEGRATED +}; + #define STATUS_DMA_ENA (1 << 7) #define STATUS_IRQ_PENDING (1 << 6) #define STATUS_CMD_IN_PROGRESS (1 << 5) @@ -635,32 +640,48 @@ esdi_callback(void *priv) break; case CMD_GET_DEV_CONFIG: - ESDI_DRIVE_ONLY(); - - if (!drive->present) { - device_not_present(dev); - return; + if (dev->cmd_dev == ATTN_HOST_ADAPTER) + { + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + /* INT 13, AX=1C0B - ESDI FIXED DISK - GET ADAPTER CONFIGURATION */ + /* The PS/55 will test sector buffer after this request is done. */ + dev->status_len = 6; + dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0; + dev->status_data[2] = 0; + /* bit 15-12: chip revision = 0011b, bit 11-8: sector buffer size = n * 256 bytes (n must be < 6) */ + dev->status_data[3] = 0x3200; + dev->status_data[4] = 0; + dev->status_data[5] = 0; } + else + { + ESDI_DRIVE_ONLY(); + if (!drive->present) { + device_not_present(dev); + return; + } - if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) - fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); - - dev->status_len = 6; - dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0x10; /*Zero defect*/ - dev->status_data[2] = drive->sectors & 0xffff; - dev->status_data[3] = drive->sectors >> 16; - dev->status_data[4] = drive->tracks; - dev->status_data[5] = drive->hpc | (drive->spt << 16); + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + dev->status_len = 6; + dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0x10; /*Zero defect*/ + dev->status_data[2] = drive->sectors & 0xffff; + dev->status_data[3] = drive->sectors >> 16; + dev->status_data[4] = drive->tracks; + dev->status_data[5] = drive->hpc | (drive->spt << 16); + } esdi_mca_log("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", - drive->sectors, - dev->status_data[0], dev->status_data[1], - dev->status_data[2], dev->status_data[3], - dev->status_data[4], dev->status_data[5]); + drive->sectors, + dev->status_data[0], dev->status_data[1], + dev->status_data[2], dev->status_data[3], + dev->status_data[4], dev->status_data[5]); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); @@ -674,7 +695,7 @@ esdi_callback(void *priv) dev->status_len = 5; dev->status_data[0] = CMD_GET_POS_INFO | STATUS_LEN(5) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0xffdd; /*MCA ID*/ + dev->status_data[1] = dev->pos_regs[1] | (dev->pos_regs[0] << 8); /*MCA ID*/ dev->status_data[2] = dev->pos_regs[3] | (dev->pos_regs[2] << 8); dev->status_data[3] = 0xff; dev->status_data[4] = 0xff; @@ -1171,6 +1192,62 @@ esdi_mca_write(int port, uint8_t val, void *priv) } } +static void +esdi_integrated_mca_write(int port, uint8_t val, void* priv) +{ + esdi_t* dev = (esdi_t*)priv; + + esdi_mca_log("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", + port, val, dev->pos_regs[2], dev->pos_regs[3]); + + if (port < 0x102) + return; + + /* Save the new value. */ + dev->pos_regs[port & 7] = val; + + io_removehandler(ESDI_IOADDR_PRI, 8, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); + + switch (dev->pos_regs[2] & 0x3c) { + case 0x14: + dev->dma = 5; + break; + case 0x18: + dev->dma = 6; + break; + case 0x1c: + dev->dma = 7; + break; + case 0x00: + dev->dma = 0; + break; + case 0x04: + dev->dma = 1; + break; + case 0x0c: + dev->dma = 3; + break; + case 0x10: + dev->dma = 4; + break; + + default: + break; + } + + if (dev->pos_regs[2] & 1) { + io_sethandler(ESDI_IOADDR_PRI, 8, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); + + /* Say hello. */ + esdi_mca_log("ESDI: I/O=3510, IRQ=14, DMA=%d\n", + dev->dma); + } +} + static uint8_t esdi_mca_feedb(void *priv) { @@ -1179,6 +1256,14 @@ esdi_mca_feedb(void *priv) return (dev->pos_regs[2] & 1); } +static void esdi_reset(void* priv) +{ + esdi_t* dev = (esdi_t*)priv; + dev->in_reset = 1; + esdi_mca_set_callback(dev, ESDI_TIME * 50); + dev->status = STATUS_BUSY; +} + static void * esdi_init(UNUSED(const device_t *info)) { @@ -1195,10 +1280,12 @@ esdi_init(UNUSED(const device_t *info)) /* Mark as unconfigured. */ dev->irq_status = 0xff; - rom_init_interleaved(&dev->bios_rom, - BIOS_FILE_H, BIOS_FILE_L, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_disable(&dev->bios_rom.mapping); + if (info->local == ESDI_IS_ADAPTER) { + rom_init_interleaved(&dev->bios_rom, + BIOS_FILE_H, BIOS_FILE_L, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + } dev->drives[0].present = dev->drives[1].present = 0; @@ -1231,12 +1318,28 @@ esdi_init(UNUSED(const device_t *info)) break; } - /* Set the MCA ID for this controller, 0xFFDD. */ - dev->pos_regs[0] = 0xff; - dev->pos_regs[1] = 0xdd; + /* Set the MCA ID for this controller. */ + if (info->local == ESDI_IS_ADAPTER) { + dev->pos_regs[0] = 0xff; + dev->pos_regs[1] = 0xdd; + } + else if (info->local == ESDI_IS_INTEGRATED) + { + dev->pos_regs[0] = 0x9f; + dev->pos_regs[1] = 0xdf; + } /* Enable the device. */ - mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); + if (info->local == ESDI_IS_INTEGRATED) { + /* The slot number of this controller is fixed by the planar. IBM PS/55 5551-T assigns it #5. */ + int slotno = device_get_config_int("in_esdi_slot"); + if (slotno) + mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev, slotno - 1); + else + mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev); + } + else + mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); /* Mark for a reset. */ dev->in_reset = 1; @@ -1276,7 +1379,7 @@ const device_t esdi_ps2_device = { .name = "IBM PS/2 ESDI Fixed Disk Adapter (MCA)", .internal_name = "esdi_mca", .flags = DEVICE_MCA, - .local = 0, + .local = ESDI_IS_ADAPTER, .init = esdi_init, .close = esdi_close, .reset = NULL, @@ -1285,3 +1388,71 @@ const device_t esdi_ps2_device = { .force_redraw = NULL, .config = NULL }; + +static device_config_t +esdi_integrated_config[] = +{ + { + .name = "in_esdi_slot", + .description = "Slot #", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "Auto", + .value = 0 + }, + { + .description = "1", + .value = 1 + }, + { + .description = "2", + .value = 2 + }, + { + .description = "3", + .value = 3 + }, + { + .description = "4", + .value = 4 + }, + { + .description = "5", + .value = 5 + }, + { + .description = "6", + .value = 6 + }, + { + .description = "7", + .value = 7 + }, + { + .description = "8", + .value = 8 + } + }, + .default_int = 0 + }, + { + .type = -1 + } +}; + +const device_t +esdi_integrated_device = { + .name = "IBM Integrated Fixed Disk Controller (MCA)", + .internal_name = "esdi_integrated_mca", + .flags = DEVICE_MCA, + .local = ESDI_IS_INTEGRATED, + .init = esdi_init, + .close = esdi_close, + .reset = esdi_reset, + {.available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = esdi_integrated_config +}; From bb9b4dc64fe079a9edfb0e0e7670303a5c85d50a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:38:48 +0900 Subject: [PATCH 0014/1190] Added IBM-J 5576 keyboard and scancode set 8Ah --- src/device/keyboard.c | 116 ++++++++ src/device/keyboard_at.c | 555 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 668 insertions(+), 3 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index ea81e7525..4b8bc7365 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -18,10 +18,13 @@ * Copyright 2015-2019 Miran Grca. * Copyright 2017-2019 Fred N. van Kempen. */ +#include #include #include #include +#include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/machine.h> #include <86box/keyboard.h> @@ -49,6 +52,24 @@ uint16_t key_uncapture_1 = 0x04f; /* Numpad End */ uint16_t key_uncapture_2 = 0x14f; /* End */ #endif +#ifdef ENABLE_KBC_AT_LOG +int kbc_at_do_log = ENABLE_KBC_AT_LOG; + +static void +kbc_at_log(const char* fmt, ...) +{ + va_list ap; + + if (kbc_at_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define kbc_at_log(fmt, ...) +#endif + void (*keyboard_send)(uint16_t val); static int recv_key[512] = { 0 }; /* keyboard input buffer */ @@ -64,6 +85,64 @@ static uint8_t num_lock = 0; static uint8_t scroll_lock = 0; static uint8_t shift = 0; +static int key5576mode = 0; + +typedef struct { + const uint16_t sc; + const uint8_t mk[4]; + const uint8_t brk[4]; +} scconvtbl; + +static scconvtbl scconv55_82[18 + 1] = +{ + // clang-format off + {.sc = 0x02 , .mk = { 0x5f, 0 }, .brk = { 0xf0, 0x5f, 0 } }, /* '1' -> 'Clear/ /SysRq' */ + {.sc = 0x03 , .mk = { 0x48, 0 }, .brk = { 0xf0, 0x48, 0 } }, /* '2' -> '終了 (Exit)' */ + {.sc = 0x04 , .mk = { 0x38, 0 }, .brk = { 0xf0, 0x38, 0 } }, /* '3' -> 'メッセージ (Message)/ /応答 (Respond)' */ + {.sc = 0x05 , .mk = { 0x30, 0 }, .brk = { 0xf0, 0x30, 0 } }, /* '4' -> 'サイズ変換 (Change Size)/ /横倍角 (2x Width)' */ + {.sc = 0x06 , .mk = { 0x20, 0 }, .brk = { 0xf0, 0x20, 0 } }, /* '5' -> '単語登録 (Register Word)/ /再交換 (Re-change)' */ + {.sc = 0x07 , .mk = { 0x28, 0 }, .brk = { 0xf0, 0x28, 0 } }, /* '6' -> '漢字 (Kanji)/ /番号 (Number)' */ + {.sc = 0x08 , .mk = { 0x60, 0 }, .brk = { 0xf0, 0x60, 0 } }, /* '7' -> '取消 (Cancel)' */ + {.sc = 0x09 , .mk = { 0x40, 0 }, .brk = { 0xf0, 0x40, 0 } }, /* '8' -> 'コピー (Copy)/ /移動 (Move)' */ + {.sc = 0x3d , .mk = { 0x1f, 0 }, .brk = { 0xf0, 0x1f, 0 } }, /* 'F3' -> 'Cr Bnk/領域呼出 (Call Range)/All Cr/登録 (Register)' */ + {.sc = 0x3e , .mk = { 0x27, 0 }, .brk = { 0xf0, 0x27, 0 } }, /* 'F4' -> '割込み (Interrupt)' */ + {.sc = 0x3f , .mk = { 0x2f, 0 }, .brk = { 0xf0, 0x2f, 0 } }, /* 'F5' -> 'UF1' */ + {.sc = 0x40 , .mk = { 0x5e, 0 }, .brk = { 0xf0, 0x5e, 0 } }, /* 'F6' -> 'UF2' */ + {.sc = 0x41 , .mk = { 0x08, 0 }, .brk = { 0xf0, 0x08, 0 } }, /* 'F7' -> 'UF3' */ + {.sc = 0x42 , .mk = { 0x10, 0 }, .brk = { 0xf0, 0x10, 0 } }, /* 'F8' -> 'UF4' */ + {.sc = 0x43 , .mk = { 0x50, 0 }, .brk = { 0xf0, 0x50, 0 } }, /* 'F9' -> 'EOF/Erase/ErInp' */ + {.sc = 0x44 , .mk = { 0x18, 0 }, .brk = { 0xf0, 0x18, 0 } }, /* 'F10' -> 'Attn/ /CrSel' */ + {.sc = 0x57 , .mk = { 0x17, 0 }, .brk = { 0xf0, 0x17, 0 } }, /* 'F11' -> 'PA1/ /DvCncl' */ + {.sc = 0x58 , .mk = { 0x37, 0 }, .brk = { 0xf0, 0x37, 0 } }, /* 'F12' -> 'PA2/ /PA3' */ + {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ + // clang-format on +}; + +static scconvtbl scconv55_8a[18 + 1] = +{ + // clang-format off + {.sc = 0x02 , .mk = { 0x48 }, .brk = { 0 } }, /* '1' -> 'Clear/ /SysRq' */ + {.sc = 0x03 , .mk = { 0x49 }, .brk = { 0 } }, /* '2' -> '終了 (Exit)' */ + {.sc = 0x04 , .mk = { 0x46 }, .brk = { 0 } }, /* '3' -> 'メッセージ (Message)/ /応答 (Respond)' */ + {.sc = 0x05 , .mk = { 0x44 }, .brk = { 0 } }, /* '4' -> 'サイズ変換 (Change Size)/ /横倍角 (2x Width)' */ + {.sc = 0x06 , .mk = { 0x42 }, .brk = { 0 } }, /* '5' -> '単語登録 (Register Word)/ /再交換 (Re-change)' */ + {.sc = 0x07 , .mk = { 0x43 }, .brk = { 0 } }, /* '6' -> '漢字 (Kanji)/ /番号 (Number)' */ + {.sc = 0x08 , .mk = { 0x40 }, .brk = { 0 } }, /* '7' -> '取消 (Cancel)' */ + {.sc = 0x09 , .mk = { 0x51 }, .brk = { 0 } }, /* '8' -> 'コピー (Copy)/ /移動 (Move)' */ + {.sc = 0x3d , .mk = { 0x76 }, .brk = { 0 } }, /* 'F3' -> 'Cr Bnk/領域呼出 (Call Range)/All Cr/登録 (Register)' */ + {.sc = 0x3e , .mk = { 0x77 }, .brk = { 0 } }, /* 'F4' -> '割込み (Interrupt)' */ + {.sc = 0x3f , .mk = { 0x78 }, .brk = { 0 } }, /* 'F5' -> 'UF1' */ + {.sc = 0x40 , .mk = { 0x79 }, .brk = { 0 } }, /* 'F6' -> 'UF2' */ + {.sc = 0x41 , .mk = { 0x7a }, .brk = { 0 } }, /* 'F7' -> 'UF3' */ + {.sc = 0x42 , .mk = { 0x7b }, .brk = { 0 } }, /* 'F8' -> 'UF4' */ + {.sc = 0x43 , .mk = { 0x7c }, .brk = { 0 } }, /* 'F9' -> 'EOF/Erase/ErInp' */ + {.sc = 0x44 , .mk = { 0x7d }, .brk = { 0 } }, /* 'F10' -> 'Attn/ /CrSel' */ + {.sc = 0x57 , .mk = { 0x7e }, .brk = { 0 } }, /* 'F11' -> 'PA1/ /DvCncl' */ + {.sc = 0x58 , .mk = { 0x7f }, .brk = { 0 } }, /* 'F12' -> 'PA2/ /PA3' */ + {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ + // clang-format on +}; + void keyboard_init(void) { @@ -119,6 +198,36 @@ key_process(uint16_t scan, int down) oldkey[scan] = down; + pclog("keyboard : %04X,%d in process\n", scan, down); + + c = 0; + /* According to Japanese DOS K3.3 manual (N:SC18-2194-1), + IBM 5576-002, -003 keyboards have the one-time key conversion mode + that emulates 18 out of 131 keys on IBM 5576-001 keyboard. + It is triggered by pressing L-Shift (⇧) + L-Ctrl + R-Alt (前面キー) + when the scancode set is 82h or 8ah. + */ + if (key5576mode) { + int i = 0; + if (!down) { + /* Do and exit the 5576-001 emulation when a key is pressed other than trigger keys. */ + if (scan != 0x1d && scan != 0x2a && scan != 0x138) + { + key5576mode = 0; + pclog("keyboard : 5576-001 key emulation disabled.\n"); + } + } + while (scconv55_8a[i].sc != 0) + { + if (scconv55_8a[i].sc == scan) { + while (scconv55_8a[i].mk[c] != 0) + keyboard_send(scconv55_8a[i].mk[c++]); + return; + } + i++; + } + } + if (down && (codes[scan].mk[0] == 0)) return; @@ -145,6 +254,13 @@ key_process(uint16_t scan, int down) if (fake_shift_needed(scan)) keyboard_send(0x101); } + + /* Enter the 5576-001 emulation mode. */ + if (keyboard_mode == 0x8a && down && ((keyboard_get_shift() & 0x43) == 0x43)) + { + key5576mode = 1; + pclog("keyboard : 5576-001 key emulation enabled.\n"); + } } /* Handle a keystroke event from the UI layer. */ diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index bcb4d646b..2900ec17a 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -53,10 +53,10 @@ const uint8_t id_bytes[16][4] = { { 0x00, 0x00, 0x00, 0x00 }, /* AT 84-key */ { 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, /* FLAG_PS2 = 0x08 */ { 0xab, 0x83, 0x00, 0x00 }, /* PS/2 101-key */ { 0xab, 0x83, 0x00, 0x00 }, /* PS/2 102-key */ - { 0xab, 0x90, 0x00, 0x00 }, /* PS/2 106-key JIS */ + { 0xab, 0x90, 0x00, 0x00 }, /* PS/55 106-key JIS (IBM-J 5576-002) */ /* Japanese keyboard ID - TODO: Find the actual Korean one. */ { 0xab, 0x90, 0x00, 0x00 }, /* PS/2 Korean */ { 0x00, 0x00, 0x00, 0x00 }, @@ -1630,6 +1630,548 @@ static const scancode scancode_set3[512] = { // clang-format on }; +/* IBM Japan 5576-001, 002 and 003 keyboards have three extra scancode sets; 81h, 82h, 8ah. + Scancode set 81h and 82h are not implemented yet. + To implement them, we need take the following into consideration. + * Add a UI to switch the type of keyboards and keyboard IDs. + * Add modified scancode set 1 and 2 (in these modes, language input keys are used as an alternative key). + * Japanese keyboards traditionally use a typewriter layout. Its key mapping doesn't match with foreign keyboards. + + 5576 keyboards kept 101-key compatible scancode sets because PS/55 had to support western (PS/2) versions of operating systems. + The default scancode set is 2. + In Japanese DOS, the keyboard driver confirms its keyboard ID, and sends a command to switch the scancode set to 8Ah. + + The OADG standard and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. + Three extra scancode sets are no longer available. Instead, language input keys are available in scancode set 1 and 2. + However, it has a different key mapping. + Users have to choose the correct keyboard layout on setup, and the driver needs to remap keys. + + [Japanese DOS and keyboard scancode set] + | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | PC DOS 5 | + |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| + | IBM 101-key | n/a | n/a | n/a | n/a | 2 | n/a | 2 | + | IBM-J 5576-00x (obsolete) | 8A | 8A | 8A | 82 | 82 | 82 | 2 | + | OADG (modern JA standard) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ + +/* Scancode set 8Ah : 5556 keyboard compatible scancode set used by J-DOS */ +static scancode scancode_set8a[512] = +{ + // clang-format off + {.mk = { 0 }, .brk = { 0 } }, /* 000 */ + {.mk = { 0x3d, 0 }, .brk = { 0 } }, /* 001 */ + {.mk = { 0x24, 0 }, .brk = { 0 } }, /* 002 */ + {.mk = { 0x25, 0 }, .brk = { 0 } }, /* 003 */ + {.mk = { 0x26, 0 }, .brk = { 0 } }, /* 004 */ + {.mk = { 0x27, 0 }, .brk = { 0 } }, /* 005 */ + {.mk = { 0x28, 0 }, .brk = { 0 } }, /* 006 */ + {.mk = { 0x29, 0 }, .brk = { 0 } }, /* 007 */ + {.mk = { 0x2a, 0 }, .brk = { 0 } }, /* 008 */ + {.mk = { 0x2b, 0 }, .brk = { 0 } }, /* 009 */ + {.mk = { 0x2c, 0 }, .brk = { 0 } }, /* 00a */ + {.mk = { 0x2d, 0 }, .brk = { 0 } }, /* 00b */ + {.mk = { 0x2e, 0 }, .brk = { 0 } }, /* 00c */ + {.mk = { 0x2f, 0 }, .brk = { 0 } }, /* 00d */ + {.mk = { 0x3e, 0 }, .brk = { 0 } }, /* 00e */ + {.mk = { 0x3c, 0 }, .brk = { 0 } }, /* 00f */ + {.mk = { 0x18, 0 }, .brk = { 0 } }, /* 010 */ + {.mk = { 0x19, 0 }, .brk = { 0 } }, /* 011 */ + {.mk = { 0x1a, 0 }, .brk = { 0 } }, /* 012 */ + {.mk = { 0x1b, 0 }, .brk = { 0 } }, /* 013 */ + {.mk = { 0x1c, 0 }, .brk = { 0 } }, /* 014 */ + {.mk = { 0x1d, 0 }, .brk = { 0 } }, /* 015 */ + {.mk = { 0x1e, 0 }, .brk = { 0 } }, /* 016 */ + {.mk = { 0x1f, 0 }, .brk = { 0 } }, /* 017 */ + {.mk = { 0x20, 0 }, .brk = { 0 } }, /* 018 */ + {.mk = { 0x21, 0 }, .brk = { 0 } }, /* 019 */ + {.mk = { 0x22, 0 }, .brk = { 0 } }, /* 01a */ + {.mk = { 0x23, 0 }, .brk = { 0 } }, /* 01b */ + {.mk = { 0x3b, 0 }, .brk = { 0 } }, /* 01c */ + {.mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 01d LCTRL */ + {.mk = { 0x0c, 0 }, .brk = { 0 } }, /* 01e */ + {.mk = { 0x0d, 0 }, .brk = { 0 } }, /* 01f */ + {.mk = { 0x0e, 0 }, .brk = { 0 } }, /* 020 */ + {.mk = { 0x0f, 0 }, .brk = { 0 } }, /* 021 */ + {.mk = { 0x10, 0 }, .brk = { 0 } }, /* 022 */ + {.mk = { 0x11, 0 }, .brk = { 0 } }, /* 023 */ + {.mk = { 0x12, 0 }, .brk = { 0 } }, /* 024 */ + {.mk = { 0x13, 0 }, .brk = { 0 } }, /* 025 */ + {.mk = { 0x14, 0 }, .brk = { 0 } }, /* 026 */ + {.mk = { 0x15, 0 }, .brk = { 0 } }, /* 027 */ + {.mk = { 0x16, 0 }, .brk = { 0 } }, /* 028* */ + {.mk = { 0x45, 0 }, .brk = { 0 } }, /* 029 Hankaku, Zenkaku */ + {.mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 02a LSHIFT */ + {.mk = { 0x17, 0 }, .brk = { 0 } }, /* 02b Mu */ + {.mk = { 0x01, 0 }, .brk = { 0 } }, /* 02c */ + {.mk = { 0x02, 0 }, .brk = { 0 } }, /* 02d */ + {.mk = { 0x03, 0 }, .brk = { 0 } }, /* 02e */ + {.mk = { 0x04, 0 }, .brk = { 0 } }, /* 02f */ + {.mk = { 0x05, 0 }, .brk = { 0 } }, /* 030 */ + {.mk = { 0x06, 0 }, .brk = { 0 } }, /* 031 */ + {.mk = { 0x07, 0 }, .brk = { 0 } }, /* 032 */ + {.mk = { 0x08, 0 }, .brk = { 0 } }, /* 033 */ + {.mk = { 0x09, 0 }, .brk = { 0 } }, /* 034 */ + {.mk = { 0x0a, 0 }, .brk = { 0 } }, /* 035 */ + {.mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 036 RSHIFT */ + {.mk = { 0x64, 0 }, .brk = { 0 } }, /* 037 * (asterisk) */ + {.mk = { 0x3A, 0 }, .brk = { 0xba, 0 } }, /* 038 LALT = Kanji */ + {.mk = { 0x34, 0 }, .brk = { 0 } }, /* 039 */ + {.mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 03a CAPSLOCK */ + {.mk = { 0x68, 0 }, .brk = { 0 } }, /* 03b F1 */ + {.mk = { 0x69, 0 }, .brk = { 0 } }, /* 03c */ + {.mk = { 0x6a, 0 }, .brk = { 0 } }, /* 03d */ + {.mk = { 0x6b, 0 }, .brk = { 0 } }, /* 03e */ + {.mk = { 0x6c, 0 }, .brk = { 0 } }, /* 03f */ + {.mk = { 0x6d, 0 }, .brk = { 0 } }, /* 040 */ + {.mk = { 0x6e, 0 }, .brk = { 0 } }, /* 041 */ + {.mk = { 0x6f, 0 }, .brk = { 0 } }, /* 042 */ + {.mk = { 0x70, 0 }, .brk = { 0 } }, /* 043 */ + {.mk = { 0x71, 0 }, .brk = { 0 } }, /* 044 F10 */ + {.mk = { 0 }, .brk = { 0 } }, /* 045 NUMLOCKCLEAR -> Shift + SCRLOCK :TODO */ + {.mk = { 0x75, 0 }, .brk = { 0 } }, /* 046 SCROLLLOCK */ + {.mk = { 0x5d, 0 }, .brk = { 0 } }, /* 047 KP7 */ + {.mk = { 0x5e, 0 }, .brk = { 0 } }, /* 048 */ + {.mk = { 0x5f, 0 }, .brk = { 0 } }, /* 049 */ + {.mk = { 0x67, 0 }, .brk = { 0 } }, /* 04a KP_MINUS */ + {.mk = { 0x5a, 0 }, .brk = { 0 } }, /* 04b */ + {.mk = { 0x5b, 0 }, .brk = { 0 } }, /* 04c */ + {.mk = { 0x5c, 0 }, .brk = { 0 } }, /* 04d */ + {.mk = { 0x63, 0 }, .brk = { 0 } }, /* 04e */ + {.mk = { 0x57, 0 }, .brk = { 0 } }, /* 04f */ + {.mk = { 0x58, 0 }, .brk = { 0 } }, /* 050 */ + {.mk = { 0x59, 0 }, .brk = { 0 } }, /* 051 */ + {.mk = { 0x55, 0 }, .brk = { 0 } }, /* 052 KP0 */ + {.mk = { 0x56, 0 }, .brk = { 0 } }, /* 053 KP_PERIOD */ + {.mk = { 0 }, .brk = { 0 } }, /* 054 */ + {.mk = { 0 }, .brk = { 0 } }, /* 055 */ + {.mk = { 0 }, .brk = { 0 } }, /* 056 */ + {.mk = { 0x72, 0 }, .brk = { 0 } }, /* 057 F11 */ + {.mk = { 0x73, 0 }, .brk = { 0 } }, /* 058 F12 */ + {.mk = { 0 }, .brk = { 0 } }, /* 059 */ + {.mk = { 0 }, .brk = { 0 } }, /* 05a */ + {.mk = { 0 }, .brk = { 0 } }, /* 05b */ + {.mk = { 0 }, .brk = { 0 } }, /* 05c */ + {.mk = { 0 }, .brk = { 0 } }, /* 05d */ + {.mk = { 0 }, .brk = { 0 } }, /* 05e */ + {.mk = { 0 }, .brk = { 0 } }, /* 05f */ + {.mk = { 0 }, .brk = { 0 } }, /* 060 */ + {.mk = { 0 }, .brk = { 0 } }, /* 061 */ + {.mk = { 0 }, .brk = { 0 } }, /* 062 */ + {.mk = { 0 }, .brk = { 0 } }, /* 063 */ + {.mk = { 0 }, .brk = { 0 } }, /* 064 */ + {.mk = { 0 }, .brk = { 0 } }, /* 065 */ + {.mk = { 0 }, .brk = { 0 } }, /* 066 */ + {.mk = { 0 }, .brk = { 0 } }, /* 067 */ + {.mk = { 0 }, .brk = { 0 } }, /* 068 */ + {.mk = { 0 }, .brk = { 0 } }, /* 069 */ + {.mk = { 0 }, .brk = { 0 } }, /* 06a */ + {.mk = { 0 }, .brk = { 0 } }, /* 06b */ + {.mk = { 0 }, .brk = { 0 } }, /* 06c */ + {.mk = { 0 }, .brk = { 0 } }, /* 06d */ + {.mk = { 0 }, .brk = { 0 } }, /* 06e */ + {.mk = { 0 }, .brk = { 0 } }, /* 06f */ + {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 070 Kana */ + {.mk = { 0 }, .brk = { 0 } }, /* 071 */ + {.mk = { 0 }, .brk = { 0 } }, /* 072 */ + {.mk = { 0x0b, 0 }, .brk = { 0 } }, /* 073 Ro, Underline */ + {.mk = { 0 }, .brk = { 0 } }, /* 074 */ + {.mk = { 0 }, .brk = { 0 } }, /* 075 */ + {.mk = { 0 }, .brk = { 0 } }, /* 076 */ + {.mk = { 0 }, .brk = { 0 } }, /* 077 */ + {.mk = { 0 }, .brk = { 0 } }, /* 078 */ + {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 079 Henkan */ + {.mk = { 0 }, .brk = { 0 } }, /* 07a */ + {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 07b Muhenkan */ + {.mk = { 0 }, .brk = { 0 } }, /* 07c */ + {.mk = { 0x30, 0 }, .brk = { 0 } }, /* 07d Yen, Vertical line */ + {.mk = { 0 }, .brk = { 0 } }, /* 07e */ + {.mk = { 0 }, .brk = { 0 } }, /* 07f */ + {.mk = { 0 }, .brk = { 0 } }, /* 080 */ + {.mk = { 0 }, .brk = { 0 } }, /* 081 */ + {.mk = { 0 }, .brk = { 0 } }, /* 082 */ + {.mk = { 0 }, .brk = { 0 } }, /* 083 */ + {.mk = { 0 }, .brk = { 0 } }, /* 084 */ + {.mk = { 0 }, .brk = { 0 } }, /* 085 */ + {.mk = { 0 }, .brk = { 0 } }, /* 086 */ + {.mk = { 0 }, .brk = { 0 } }, /* 087 */ + {.mk = { 0 }, .brk = { 0 } }, /* 088 */ + {.mk = { 0 }, .brk = { 0 } }, /* 089 */ + {.mk = { 0 }, .brk = { 0 } }, /* 08a */ + {.mk = { 0 }, .brk = { 0 } }, /* 08b */ + {.mk = { 0 }, .brk = { 0 } }, /* 08c */ + {.mk = { 0 }, .brk = { 0 } }, /* 08d */ + {.mk = { 0 }, .brk = { 0 } }, /* 08e */ + {.mk = { 0 }, .brk = { 0 } }, /* 08f */ + {.mk = { 0 }, .brk = { 0 } }, /* 090 */ + {.mk = { 0 }, .brk = { 0 } }, /* 091 */ + {.mk = { 0 }, .brk = { 0 } }, /* 092 */ + {.mk = { 0 }, .brk = { 0 } }, /* 093 */ + {.mk = { 0 }, .brk = { 0 } }, /* 094 */ + {.mk = { 0 }, .brk = { 0 } }, /* 095 */ + {.mk = { 0 }, .brk = { 0 } }, /* 096 */ + {.mk = { 0 }, .brk = { 0 } }, /* 097 */ + {.mk = { 0 }, .brk = { 0 } }, /* 098 */ + {.mk = { 0 }, .brk = { 0 } }, /* 099 */ + {.mk = { 0 }, .brk = { 0 } }, /* 09a */ + {.mk = { 0 }, .brk = { 0 } }, /* 09b */ + {.mk = { 0 }, .brk = { 0 } }, /* 09c */ + {.mk = { 0 }, .brk = { 0 } }, /* 09d */ + {.mk = { 0 }, .brk = { 0 } }, /* 09e */ + {.mk = { 0 }, .brk = { 0 } }, /* 09f */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0aa */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ab */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ac */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ad */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ae */ + {.mk = { 0 }, .brk = { 0 } }, /* 0af */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ba */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0be */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bf */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ca */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ce */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cf */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0da */ + {.mk = { 0 }, .brk = { 0 } }, /* 0db */ + {.mk = { 0 }, .brk = { 0 } }, /* 0dc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0dd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0de */ + {.mk = { 0 }, .brk = { 0 } }, /* 0df */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ea */ + {.mk = { 0 }, .brk = { 0 } }, /* 0eb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ec */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ed */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ee */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ef */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fa */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fe */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ff */ + {.mk = { 0x47, 0 }, .brk = { 0 } }, /* 100 Pause */ + {.mk = { 0 }, .brk = { 0 } }, /* 101 */ + {.mk = { 0 }, .brk = { 0 } }, /* 102 */ + {.mk = { 0 }, .brk = { 0 } }, /* 103 */ + {.mk = { 0 }, .brk = { 0 } }, /* 104 */ + {.mk = { 0 }, .brk = { 0 } }, /* 105 */ + {.mk = { 0 }, .brk = { 0 } }, /* 106 */ + {.mk = { 0 }, .brk = { 0 } }, /* 107 */ + {.mk = { 0 }, .brk = { 0 } }, /* 108 */ + {.mk = { 0 }, .brk = { 0 } }, /* 109 */ + {.mk = { 0 }, .brk = { 0 } }, /* 10a */ + {.mk = { 0 }, .brk = { 0 } }, /* 10b */ + {.mk = { 0 }, .brk = { 0 } }, /* 10c */ + {.mk = { 0 }, .brk = { 0 } }, /* 10d */ + {.mk = { 0 }, .brk = { 0 } }, /* 10e */ + {.mk = { 0 }, .brk = { 0 } }, /* 10f */ + {.mk = { 0 }, .brk = { 0 } }, /* 110 */ + {.mk = { 0 }, .brk = { 0 } }, /* 112 */ + {.mk = { 0 }, .brk = { 0 } }, /* 113 */ + {.mk = { 0 }, .brk = { 0 } }, /* 113 */ + {.mk = { 0 }, .brk = { 0 } }, /* 114 */ + {.mk = { 0 }, .brk = { 0 } }, /* 115 */ + {.mk = { 0 }, .brk = { 0 } }, /* 116 */ + {.mk = { 0 }, .brk = { 0 } }, /* 117 */ + {.mk = { 0 }, .brk = { 0 } }, /* 118 */ + {.mk = { 0 }, .brk = { 0 } }, /* 119 */ + {.mk = { 0 }, .brk = { 0 } }, /* 11a */ + {.mk = { 0 }, .brk = { 0 } }, /* 11b */ + {.mk = { 0x60, 0 }, .brk = { 0 } }, /* 11c KP_Enter */ + {.mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 11d R-Ctrl */ + {.mk = { 0 }, .brk = { 0 } }, /* 11e */ + {.mk = { 0 }, .brk = { 0 } }, /* 11f */ + {.mk = { 0 }, .brk = { 0 } }, /* 120 */ + {.mk = { 0 }, .brk = { 0 } }, /* 121 */ + {.mk = { 0 }, .brk = { 0 } }, /* 122 */ + {.mk = { 0 }, .brk = { 0 } }, /* 123 */ + {.mk = { 0 }, .brk = { 0 } }, /* 124 */ + {.mk = { 0 }, .brk = { 0 } }, /* 125 */ + {.mk = { 0 }, .brk = { 0 } }, /* 126 */ + {.mk = { 0 }, .brk = { 0 } }, /* 127 */ + {.mk = { 0 }, .brk = { 0 } }, /* 128 */ + {.mk = { 0 }, .brk = { 0 } }, /* 129 */ + {.mk = { 0 }, .brk = { 0 } }, /* 12a */ + {.mk = { 0 }, .brk = { 0 } }, /* 12b */ + {.mk = { 0 }, .brk = { 0 } }, /* 12c */ + {.mk = { 0 }, .brk = { 0 } }, /* 12d */ + {.mk = { 0 }, .brk = { 0 } }, /* 12e */ + {.mk = { 0 }, .brk = { 0 } }, /* 12f */ + {.mk = { 0 }, .brk = { 0 } }, /* 130 */ + {.mk = { 0 }, .brk = { 0 } }, /* 131 */ + {.mk = { 0 }, .brk = { 0 } }, /* 132 */ + {.mk = { 0 }, .brk = { 0 } }, /* 133 */ + {.mk = { 0 }, .brk = { 0 } }, /* 134 */ + {.mk = { 0x65, 0 }, .brk = { 0 } }, /* 135 KP_DIVIDE */ + {.mk = { 0 }, .brk = { 0 } }, /* 136 */ + {.mk = { 0x74, 0 }, .brk = { 0 } }, /* 137 PRINTSCREEN */ + {.mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 138* R-Alt */ + {.mk = { 0 }, .brk = { 0 } }, /* 139 */ + {.mk = { 0 }, .brk = { 0 } }, /* 13a */ + {.mk = { 0 }, .brk = { 0 } }, /* 13b */ + {.mk = { 0 }, .brk = { 0 } }, /* 13c */ + {.mk = { 0 }, .brk = { 0 } }, /* 13d */ + {.mk = { 0 }, .brk = { 0 } }, /* 13e */ + {.mk = { 0 }, .brk = { 0 } }, /* 13f */ + {.mk = { 0 }, .brk = { 0 } }, /* 140 */ + {.mk = { 0 }, .brk = { 0 } }, /* 141 */ + {.mk = { 0 }, .brk = { 0 } }, /* 142 */ + {.mk = { 0 }, .brk = { 0 } }, /* 143 */ + {.mk = { 0 }, .brk = { 0 } }, /* 144 */ + {.mk = { 0 }, .brk = { 0 } }, /* 145 */ + {.mk = { 0 }, .brk = { 0 } }, /* 146 */ + {.mk = { 0x4c, 0 }, .brk = { 0 } }, /* 147 Home */ + {.mk = { 0x4e, 0 }, .brk = { 0 } }, /* 148 Up */ + {.mk = { 0x52, 0 }, .brk = { 0 } }, /* 149 PageUp */ + {.mk = { 0 }, .brk = { 0 } }, /* 14a */ + {.mk = { 0x4b, 0 }, .brk = { 0 } }, /* 14b Left */ + {.mk = { 0 }, .brk = { 0 } }, /* 14c */ + {.mk = { 0x4d, 0 }, .brk = { 0 } }, /* 14d Right */ + {.mk = { 0 }, .brk = { 0 } }, /* 14e */ + {.mk = { 0x53, 0 }, .brk = { 0 } }, /* 14f End */ + {.mk = { 0x4a, 0 }, .brk = { 0 } }, /* 150 Down */ + {.mk = { 0x54, 0 }, .brk = { 0 } }, /* 151 PageDown */ + {.mk = { 0x4f, 0 }, .brk = { 0 } }, /* 152 Ins */ + {.mk = { 0x50, 0 }, .brk = { 0 } }, /* 153 Del */ + {.mk = { 0 }, .brk = { 0 } }, /* 154 */ + {.mk = { 0 }, .brk = { 0 } }, /* 155 */ + {.mk = { 0 }, .brk = { 0 } }, /* 156 */ + {.mk = { 0 }, .brk = { 0 } }, /* 157 */ + {.mk = { 0 }, .brk = { 0 } }, /* 158 */ + {.mk = { 0 }, .brk = { 0 } }, /* 159 */ + {.mk = { 0 }, .brk = { 0 } }, /* 15a */ + {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 15b LGUI->Muhenkan (in emulator only) */ + {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 15c RGUI->Henkan (in emulator only) */ + {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 15d APPLICATION->Kana (in emulator only) */ + {.mk = { 0 }, .brk = { 0 } }, /* 15e */ + {.mk = { 0 }, .brk = { 0 } }, /* 15f */ + {.mk = { 0 }, .brk = { 0 } }, /* 160 */ + {.mk = { 0 }, .brk = { 0 } }, /* 161 */ + {.mk = { 0 }, .brk = { 0 } }, /* 162 */ + {.mk = { 0 }, .brk = { 0 } }, /* 163 */ + {.mk = { 0 }, .brk = { 0 } }, /* 164 */ + {.mk = { 0 }, .brk = { 0 } }, /* 165 */ + {.mk = { 0 }, .brk = { 0 } }, /* 166 */ + {.mk = { 0 }, .brk = { 0 } }, /* 167 */ + {.mk = { 0 }, .brk = { 0 } }, /* 168 */ + {.mk = { 0 }, .brk = { 0 } }, /* 169 */ + {.mk = { 0 }, .brk = { 0 } }, /* 16a */ + {.mk = { 0 }, .brk = { 0 } }, /* 16b */ + {.mk = { 0 }, .brk = { 0 } }, /* 16c */ + {.mk = { 0 }, .brk = { 0 } }, /* 16d */ + {.mk = { 0 }, .brk = { 0 } }, /* 16e */ + {.mk = { 0 }, .brk = { 0 } }, /* 16f */ + {.mk = { 0 }, .brk = { 0 } }, /* 170 */ + {.mk = { 0 }, .brk = { 0 } }, /* 171 */ + {.mk = { 0 }, .brk = { 0 } }, /* 172 */ + {.mk = { 0 }, .brk = { 0 } }, /* 173 */ + {.mk = { 0 }, .brk = { 0 } }, /* 174 */ + {.mk = { 0 }, .brk = { 0 } }, /* 175 */ + {.mk = { 0 }, .brk = { 0 } }, /* 176 */ + {.mk = { 0 }, .brk = { 0 } }, /* 177 */ + {.mk = { 0 }, .brk = { 0 } }, /* 178 */ + {.mk = { 0 }, .brk = { 0 } }, /* 179 */ + {.mk = { 0 }, .brk = { 0 } }, /* 17a */ + {.mk = { 0 }, .brk = { 0 } }, /* 17b */ + {.mk = { 0 }, .brk = { 0 } }, /* 17c */ + {.mk = { 0 }, .brk = { 0 } }, /* 17d */ + {.mk = { 0 }, .brk = { 0 } }, /* 17e */ + {.mk = { 0 }, .brk = { 0 } }, /* 17f */ + {.mk = { 0 }, .brk = { 0 } }, /* 180 */ + {.mk = { 0 }, .brk = { 0 } }, /* 181 */ + {.mk = { 0 }, .brk = { 0 } }, /* 182 */ + {.mk = { 0 }, .brk = { 0 } }, /* 183 */ + {.mk = { 0 }, .brk = { 0 } }, /* 184 */ + {.mk = { 0 }, .brk = { 0 } }, /* 185 */ + {.mk = { 0 }, .brk = { 0 } }, /* 186 */ + {.mk = { 0 }, .brk = { 0 } }, /* 187 */ + {.mk = { 0 }, .brk = { 0 } }, /* 188 */ + {.mk = { 0 }, .brk = { 0 } }, /* 189 */ + {.mk = { 0 }, .brk = { 0 } }, /* 18a */ + {.mk = { 0 }, .brk = { 0 } }, /* 18b */ + {.mk = { 0 }, .brk = { 0 } }, /* 18c */ + {.mk = { 0 }, .brk = { 0 } }, /* 18d */ + {.mk = { 0 }, .brk = { 0 } }, /* 18e */ + {.mk = { 0 }, .brk = { 0 } }, /* 18f */ + {.mk = { 0 }, .brk = { 0 } }, /* 190 */ + {.mk = { 0 }, .brk = { 0 } }, /* 191 */ + {.mk = { 0 }, .brk = { 0 } }, /* 192 */ + {.mk = { 0 }, .brk = { 0 } }, /* 193 */ + {.mk = { 0 }, .brk = { 0 } }, /* 194 */ + {.mk = { 0 }, .brk = { 0 } }, /* 195 */ + {.mk = { 0 }, .brk = { 0 } }, /* 196 */ + {.mk = { 0 }, .brk = { 0 } }, /* 197 */ + {.mk = { 0 }, .brk = { 0 } }, /* 198 */ + {.mk = { 0 }, .brk = { 0 } }, /* 199 */ + {.mk = { 0 }, .brk = { 0 } }, /* 19a */ + {.mk = { 0 }, .brk = { 0 } }, /* 19b */ + {.mk = { 0 }, .brk = { 0 } }, /* 19c */ + {.mk = { 0 }, .brk = { 0 } }, /* 19d */ + {.mk = { 0 }, .brk = { 0 } }, /* 19e */ + {.mk = { 0 }, .brk = { 0 } }, /* 19f */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1aa */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ab */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ac */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ad */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ae */ + {.mk = { 0 }, .brk = { 0 } }, /* 1af */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ba */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bc */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1be */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bf */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ca */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cv */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ce */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cf */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1da */ + {.mk = { 0 }, .brk = { 0 } }, /* 1db */ + {.mk = { 0 }, .brk = { 0 } }, /* 1dc */ + {.mk = { 0 }, .brk = { 0 } }, /* 1dd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1de */ + {.mk = { 0 }, .brk = { 0 } }, /* 1df */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ea */ + {.mk = { 0 }, .brk = { 0 } }, /* 1eb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ec */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ed */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ee */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ef */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fa */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fc */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fe */ + {.mk = { 0 }, .brk = { 0 } } /* 1ff */ + // clang-format on +}; + #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -1664,6 +2206,10 @@ keyboard_at_set_scancode_set(void) case 0x03: keyboard_set_table(scancode_set3); break; + + case 0x8a: + keyboard_set_table(scancode_set8a); + break; } } @@ -1922,19 +2468,22 @@ keyboard_at_write(void *priv) break; case 0xf0: /* Get/set scancode set */ - kbc_at_dev_queue_add(dev, (val > 3) ? 0xfe : 0xfa, 0); switch (val) { case 0x00: + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK */ keyboard_at_log("%s: Get scan code set [%02X]\n", dev->name, keyboard_mode); kbc_at_dev_queue_add(dev, keyboard_mode, 0); break; case 0x01 ... 0x03: + case 0x8a: + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK */ keyboard_mode = val; keyboard_at_log("%s: Set scan code set [%02X]\n", dev->name, keyboard_mode); keyboard_at_set_scancode_set(); break; default: /* Fatal so any instance of anything attempting to set scan code > 3 can be reported to us. */ + kbc_at_dev_queue_add(dev, 0xfe, 0); /* Resend */ fatal("%s: Scan code set [%02X] invalid, resend\n", dev->name, val); dev->flags |= FLAG_CTRLDAT; dev->state = DEV_STATE_MAIN_WANT_IN; From 048a9409809b1dbefb1b424a817d6a0b52dfce57 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:41:08 +0900 Subject: [PATCH 0015/1190] Added a machine PS/55 model 5551T --- src/machine/m_ps2_mca.c | 260 +++++++++++++++++++++++++++++++++++- src/machine/machine_table.c | 40 ++++++ 2 files changed, 297 insertions(+), 3 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index cb83d9be7..fc2e3313b 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -67,6 +67,8 @@ #include <86box/port_92.h> #include <86box/serial.h> #include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_vga.h> #include <86box/machine.h> #include <86box/plat_unused.h> @@ -103,6 +105,8 @@ static struct ps2_t { int pending_cache_miss; serial_t *uart; + + vga_t* mb_vga; } ps2; /*The model 70 type 3/4 BIOS performs cache testing. Since 86Box doesn't have any @@ -140,6 +144,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; +static void mem_encoding_update(void); #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -358,6 +363,61 @@ model_80_read(uint16_t port) return 0xff; } +static uint8_t +ps55_model_50t_read(uint16_t port) +{ + ps2_mca_log(" Read SysBrd %04X xx %04X:%04X\n", port, cs >> 4, cpu_state.pc); + switch (port) + { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) + Bit 3-0: Memory Card ID (Connector 2) + + Memory Card ID: 7h = 2 MB Memory Card 2 or 3 Installed + 5h = 4 MB Memory Card 2 Installed + */ + switch (mem_size / 1024) + { + case 2: + if (ps2.option[1] & 0x04) val = 0xff; + else val = 0x7f; + break; + case 4: + if (ps2.option[1] & 0x04) val = 0xff; + else val = 0x77; + break; + case 6: + if (ps2.option[1] & 0x04) val = 0x7f; + else val = 0x77; + break; + case 8: + default: + if (ps2.option[1] & 0x04) val = 0x5f; + else val = 0x77; + break; + } + ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); + return val; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + } + return 0xff; +} + static void model_50_write(uint16_t port, uint8_t val) { @@ -655,6 +715,78 @@ model_80_write(uint16_t port, uint8_t val) } } +static void +ps55_model_50t_write(uint16_t port, uint8_t val)//pcem55 +{ + ps2_mca_log(" Write SysBrd %04X %02X %04X:%04X\n", port, val, cs >> 4, cpu_state.pc); + switch (port) + { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) + { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) + { + switch ((val >> 5) & 3) + { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; + default: + break; + } + } + ps2.option[0] = val; + break; + case 0x103: + ps2.option[1] = val; + break; + case 0x104: + if ((ps2.option[2] ^ val) & 1) { + mem_encoding_update(); + if (val & 1)/* Disable E0000 - E0FFF(Make 2 KB hole for Display Adapter) */ + { + ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); + //mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + //mem_mapping_disable(&bios_mapping[0]); + } + else/* Enable E0000 - E0FFF for BIOS */ + { + ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); + //mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); + //mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); + //mem_mapping_enable(&bios_mapping[0]); + } + } + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + default: + break; + } +} + uint8_t ps2_mca_read(uint16_t port, UNUSED(void *priv)) { @@ -793,7 +925,16 @@ ps2_mca_write(uint16_t port, uint8_t val, UNUSED(void *priv)) if (!(ps2.setup & PS2_SETUP_IO)) ps2.planar_write(port, val); else if (!(ps2.setup & PS2_SETUP_VGA)) + { + if (ps2.mb_vga) + { + if (vga_isenabled(ps2.mb_vga)) + vga_disable(ps2.mb_vga); + if (val & 1) + vga_enable(ps2.mb_vga); + } ps2.pos_vga = val; + } else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) mca_write(port, val); break; @@ -1150,7 +1291,27 @@ mem_encoding_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) } mem_encoding_update(); } - +static void +mem_encoding_write_ps55(uint16_t addr, uint8_t val, void* p) +{ + //ps2_mca_log(" Write Memory Encoding %04X %02X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + switch (addr) + { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + default: + break; + } + mem_encoding_update(); + if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ + { + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } +} static uint8_t mem_encoding_read_cached(uint16_t addr, UNUSED(void *priv)) { @@ -1311,7 +1472,7 @@ ps2_mca_board_model_70_type34_init(int is_type4, int slots) } if (gfxcard[0] == VID_INTERNAL) - device_add(&ps1vga_mca_device); + ps2.mb_vga = device_add(&ps1vga_mca_device); } static void @@ -1385,7 +1546,7 @@ ps2_mca_board_model_80_type2_init(void) } if (gfxcard[0] == VID_INTERNAL) - device_add(&ps1vga_mca_device); + ps2.mb_vga = device_add(&ps1vga_mca_device); ps2.split_size = 0; } @@ -1576,3 +1737,96 @@ machine_ps2_model_70_type4_init(const machine_t *model) return ret; } + +void +ps55_mca_board_model_50t_init() +{ + ps2_mca_board_common_init(); + + //mem_remap_top(256); + ps2.split_addr = mem_size * 1024; + /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ + mca_init(5); + device_add(&keyboard_ps2_mca_1_device); + + ps2.planar_read = ps55_model_50t_read; + ps2.planar_write = ps55_model_50t_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write_ps55, NULL, NULL, NULL); + + ps2.mem_regs[1] = 2; + ps2.option[2] &= 0xfe; /* Bit 0: Disable E0000-E0FFFh (4 KB) */ + + //resize bios_mapping 0,1 + //mem_mapping_set_addr(&bios_mapping[0], 0xe0000, 0x1000); + //mem_mapping_set_exec(&bios_mapping[0], rom + (0x20000 & biosmask)); + //mem_mapping_set_addr(&bios_mapping[1], 0xe1000, 0x7000); + //mem_mapping_set_exec(&bios_mapping[1], rom + (0x21000 & biosmask)); + //mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); + //mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x23000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); + + mem_mapping_add(&ps2.split_mapping, + (mem_size + 256) * 1024, + 256 * 1024, + ps2_read_split_ram, + ps2_read_split_ramw, + ps2_read_split_raml, + ps2_write_split_ram, + ps2_write_split_ramw, + ps2_write_split_raml, + &ram[0xa0000], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.split_mapping); + + if (mem_size > 8192) { + /* Only 8 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(8); + } + + if (gfxcard[0] == VID_INTERNAL) + ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); +} + +int +machine_ps55_model_50t_init(const machine_t* model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ibmps55_m50t/38F6933.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + /* begin ps2 common init */ + machine_common_init(model); + + device_add(&fdc_at_ps55_device); + + dma16_init(); + ps2_dma_init(); + device_add(&ps_no_nmi_nvr_device); + pic2_init(); + + int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; + pit_ps2_init(pit_type); + + nmi_mask = 0x80; + + ps2.uart = device_add_inst(&ns16550_device, 1); + /* end ps2 common init */ + + /* + * Planar ID + * FFFAh - PS/55 model 5551-S0x, T0x (stage 1?) + * FFEEh - PS/55 model 5551-S1x, T1x (stage 2?) + * POST (P/N 38F6933) determination: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + */ + ps2.planar_id = 0xffee; + ps55_mca_board_model_50t_init(); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a9d83f241..c005c9282 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5468,6 +5468,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has IBM PS/55 5551-Sxx, Txx stage 2 firmware. */ + { + .name = "[MCA] IBM PS/55 model 5550-T", + .internal_name = "ibmps55_m50t", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps55_model_50t_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL, + .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_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 16384, + .step = 2048 + }, + .nvrmask = 63, + .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 + }, /* 386DX/486 machines */ /* Has AMIKey F KBC firmware. */ From d46121497c111acf42ac02c661d47fb229baa0b5 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:42:43 +0900 Subject: [PATCH 0016/1190] Added IBM Display Adapter II for PS/55 emulation --- src/video/CMakeLists.txt | 2 +- src/video/vid_ps55da2.c | 3153 ++++++++++++++++++++++++++++++++++++++ src/video/vid_svga.c | 22 +- src/video/vid_table.c | 2 + src/video/vid_vga.c | 34 + 5 files changed, 3209 insertions(+), 4 deletions(-) create mode 100644 src/video/vid_ps55da2.c diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 2f7607ad6..96d669ae1 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -27,7 +27,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c - vid_bochs_vbe.c) + vid_bochs_vbe.c vid_ps55da2.c ) if(G100) target_compile_definitions(vid PRIVATE USE_G100) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c new file mode 100644 index 000000000..13f823c83 --- /dev/null +++ b/src/video/vid_ps55da2.c @@ -0,0 +1,3153 @@ +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/timer.h> +#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> +#include <86box/vid_svga_render.h> +#include "cpu.h" + +#define DA2_FONTROM_PATH "roms/video/da2/PS55FNTJ.BIN" +#define DA2_FONTROM_SIZE 1024*1024 +#define DA2_MASK_MMIO 0x1ffff +#define DA2_MASK_GRAM 0x1ffff +#define DA2_MASK_CRAM 0xfff +#define DA2_MASK_GAIJIRAM 0x3ffff +#define DA2_PIXELCLOCK 58000000.0 +#define DA2_BLT_MEMSIZE 0x80 +#define DA2_BLT_REGSIZE 0x40 +#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) +#define DA2_DEBUG_BLTLOG_MAX 256*1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLT_USEDRESET 0xfefefe + +#define DA2_BLT_CIDLE 0 +#define DA2_BLT_CFILLRECT 1 +#define DA2_BLT_CFILLTILE 2 +#define DA2_BLT_CCOPYF 3 +#define DA2_BLT_CCOPYR 4 +#define DA2_BLT_CDONE 5 +#define DA2_BLT_CLOAD 6 +/* POS ID = 0xeffe : Display Adapter II, III, V */ +#define DA2_POSID_H 0xef +#define DA2_POSID_L 0xfe +/* + [Identification] + POS ID SYS ID + EFFFh * Display Adapter (PS/55 Model 5571-S0A) [Toledo] + E013h * Layout Display Terminal (PS/55-5571 RPQ model) [LDT] + EFFEh * Display Adapter II (I/O 3E0:0A = xx0x xxxx) [Atlas] + |- FFF2h Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5530Z-SX) + |- FDFEh Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5550-V2) + |- * Display Adapter III,V (I/O 3E0:0A = xx1x xxxx) + ECECh FF4Fh Display Adapter B1 (PS/55 Model 5531Z-SX) [Atlas-KENT] + |- * Display Adapter IV + ECCEh * Display Adapter IV + 901Fh * Display Adapter A2 + 901Dh * Display Adapter A1 [Atlas II] + 901Eh * Plasma Display Adapter + EFD8h * Display Adapter/J [Atlas-SP2] + + [Japanese DOS and Display Adapter compatibility] + | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | + |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| + | EFFFh | Display Adapter | X | | | ? | | + | FFEDh | ? [Atlas EVT] | X | | | ? | | + | FFFDh | ? [LDT EVT] | X | | | ? | | + | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | + | E013h | ? [LDT] | X | X | X | X | | + | ECCEh | Display Adapter IV | | X | X | X | | + | ECECh | Display Adapter IV,B1 | | X | X | X | X | + | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | + | EFD8h | Display Adapter /J | | | X | X | X | +*/ +/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ +#define OldLSI 0x20 /* DA-2 or DA-3,5 */ +#define Mon_ID3 0x10 +#define FontCard 0x08 /* ? */ +/* IO 3E0/3E1:0Ah Hardware Configuration Value H (imported from OS/2 DDK) */ +#define AddPage 0x08 /* ? */ +#define Mon_ID2 0x04 +#define Mon_ID1 0x02 +#define Mon_ID0 0x01 +/* Monitor ID (imported from OS/2 DDK 1.2) */ +//#define StarbuckC 0x0A //1010b IBM 8514, 9518 color 1040x768 +//#define StarbuckM 0x09 //1001b x grayscale +//#define Lark_B 0x02 //0010b IBM 9517 color 1040x768 +//#define Dallas 0x0B //1011b IBM 8515, 9515 color 1040x740 B palette +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ + +/* DA2 Registers (imported from OS/2 DDK) */ +#define AC_REG 0x3EE +#define AC_DMAE 0x80 +#define AC_FONT_SEL 0x40 +#define FONT_BANK 0x3EF +#define LS_INDEX 0x3E0 +#define LS_DATA 0x3E1 +#define LS_RESET 0x00 +#define LS_MODE 0x02 +#define LS_STATUS 0x03 /* added */ +#define LS_MMIO 0x08 /* added */ +#define LS_CONFIG1 0x0a +#define LS_CONFIG2 0x0b /* added */ +#define LF_INDEX 0x3e2 +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_MMIO_MODE 0x0B /* added */ +#define LC_INDEX 0x3E4 +#define LC_DATA 0x3E5 +#define LC_HORIZONTAL_TOTAL 0x00 +#define LC_H_DISPLAY_ENABLE_END 0x01 +#define LC_START_H_BLANKING 0x02 +#define LC_END_H_BLANKING 0x03 +#define LC_START_HSYNC_PULSE 0x04 +#define LC_END_HSYNC_PULSE 0x05 +#define LC_VERTICAL_TOTALJ 0x06 +#define LC_CRTC_OVERFLOW 0x07 +#define LC_PRESET_ROW_SCANJ 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 +#define LC_CURSOR_ROW_START 0x0A +#define LC_CURSOR_ROW_END 0x0B +#define LC_START_ADDRESS_HIGH 0x0C +#define LC_START_ADDRESS_LOW 0x0D +#define LC_CURSOR_LOC_HIGH 0x0E +#define LC_ROW_CURSOR_LOC 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_COLUMN_CURSOR_LOC 0x0F +#define LC_VERTICAL_SYNC_START 0x10 +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_VERTICAL_SYNC_END 0x11 +#define LC_LIGHT_PEN_LOW 0x11 +#define LC_V_DISPLAY_ENABLE_END 0x12 +#define LC_OFFSET 0x13 +#define LC_UNDERLINE_LOCATION 0x14 +#define LC_START_VERTICAL_BLANK 0x15 +#define LC_END_VERTICAL_BLANK 0x16 +#define LC_LC_MODE_CONTROL 0x17 +#define LC_LINE_COMPAREJ 0x18 +#define LC_START_H_DISPLAY_ENAB 0x19 +#define LC_START_V_DISPLAY_ENAB 0x1A +#define LC_VIEWPORT_COMMAND 0x1B +#define LC_VIEWPORT_SELECT 0x1C +#define LC_VIEWPORT_PRIORITY 0x1D +#define LC_COMMAND 0x1E +#define LC_COMPATIBILITY 0x1F +#define LC_VIEWPORT_NUMBER 0x1F +#define LV_PORT 0x3E8 +#define LV_PALETTE_0 0x00 +#define LV_MODE_CONTROL 0x10 +#define LV_OVERSCAN_COLOR 0x11 +#define LV_COLOR_PLANE_ENAB 0x12 +#define LV_PANNING 0x13 +#define LV_VIEWPORT1_BG 0x14 +#define LV_VIEWPORT2_BG 0x15 +#define LV_VIEWPORT3_BG 0x16 +#define LV_BLINK_COLOR 0x17 +#define LV_BLINK_CODE 0x18 +#define LV_GR_CURSOR_ROTATION 0x19 +#define LV_GR_CURSOR_COLOR 0x1A +#define LV_GR_CURSOR_CONTROL 0x1B +#define LV_COMMAND 0x1C +#define LV_VP_BORDER_LINE 0x1D +#define LV_SYNC_POLARITY 0x1F +#define LV_CURSOR_CODE_0 0x20 +#define LV_GRID_COLOR_0 0x34 +#define LV_GRID_COLOR_1 0x35 +#define LV_GRID_COLOR_2 0x36 +#define LV_GRID_COLOR_3 0x37 +#define LV_ATTRIBUTE_CNTL 0x38 +#define LV_CURSOR_COLOR 0x3A +#define LV_CURSOR_CONTROL 0x3B +#define LV_RAS_STATUS_VIDEO 0x3C +#define LV_PAS_STATUS_CNTRL 0x3D +#define LV_IDENTIFICATION 0x3E +#define LV_OUTPUT 0x3E +#define LV_COMPATIBILITY 0x3F +#define LG_INDEX 0x3EA +#define LG_DATA 0x3EB +#define LG_SET_RESETJ 0x00 +#define LG_ENABLE_SRJ 0x01 +#define LG_COLOR_COMPAREJ 0x02 +#define LG_DATA_ROTATION 0x03 +#define LG_READ_MAP_SELECT 0x04 +#define LG_MODE 0x05 +#define LG_COMPLEMENT 0x06 +#define LG_COLOR_DONT_CARE 0x07 +#define LG_BIT_MASK_LOW 0x08 +#define LG_BIT_MASK_HIGH 0x09 +#define LG_MAP_MASKJ 0x0A +#define LG_COMMAND 0x0B +#define LG_SET_RESET_2 0x10 + +#ifdef ENABLE_DA2_LOG +int da2_do_log = ENABLE_DA2_LOG; + +static void +da2_log(const char* fmt, ...) +{ + va_list ap; + + if (da2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define da2_log(fmt, ...) +#endif +#ifndef RELEASE_BUILD +# define ENABLE_DA2_DEBUGBLT 1 +#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]; + uint8_t gdcreg[64]; + uint8_t reg3ee[16]; + int gdcaddr; + uint8_t attrregs[0x40]; + int attraddr, attrff; + int attr_palette_enable; + //uint8_t seqregs[64]; + int outflipflop; + int inflipflop; + int iolatch; + + int ioctladdr; + int fctladdr; + int crtcaddr; + + uint8_t miscout; + //int vidclock; + + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; + + uint32_t gdcla[8]; + //int gdcramlatched; + 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; + int dac_r, dac_g; + + //IO 3DAh Input Status Register 2 + uint8_t cgastat; + + uint8_t plane_mask; + + int fb_only; + + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + uint8_t writemask; + uint32_t charseta, charsetb; + + uint8_t egapal[16]; + uint32_t pallook[512]; + PALETTE vgapal; + + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int rowcount; + double clock; + uint32_t ma_latch, ca_adj; + + uint64_t dispontime, dispofftime; + pc_timer_t timer; + uint64_t da2const; + + uint8_t scrblank; + + int dispon; + int hdisp_on; + + uint32_t ma, maback, ca; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink, blinkconf; + int scrollcache; + int char_width; + + int firstline, lastline; + int firstline_draw, lastline_draw; + int displine; + + /* 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; + /* addr >> 12 = xx000h */ + uint8_t *changedvram; + /* (vram size - 1) >> 3 = 0x1FFFF */ + uint32_t vram_display_mask; + uint32_t banked_mask; + + uint32_t write_bank, read_bank; + + int fullchange; + + //int video_res_x, video_res_y, video_bpp; + //int video_res_override; /*If clear then SVGA code will set above variables, if + // set then card code will*/ + //int frames, writelines; + + void (*render)(struct da2_t* da2); + //void (*recalctimings_ex)(struct da2_t* da2); + + //void (*video_out)(uint16_t addr, uint8_t val, void* p); + //uint8_t(*video_in) (uint16_t addr, void* p); + + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + //void* p; + + /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ + //int hsync_divisor; + + /* end VGA compatible regs*/ + struct + { + int enable; + mem_mapping_t mapping; + uint8_t ram[256 * 1024]; + uint8_t font[DA2_FONTROM_SIZE]; + } mmio; + + mem_mapping_t linear_mapping; + + uint32_t bank[2]; + uint32_t mask; + + int type; + + struct { + int bitshift_destr; + int raster_op; + uint8_t payload[DA2_BLT_MEMSIZE]; + int32_t reg[DA2_BLT_REGSIZE];//must be signed int + int32_t* debug_reg;//for debug + int debug_reg_ip;//for debug + int payload_addr; + pc_timer_t timer; + int64_t timerspeed; + int exec; + int indata; + int32_t destaddr; + int32_t srcaddr; + int32_t size_x, tile_w; + int32_t size_y; + int16_t destpitch; + int16_t srcpitch; + int32_t fcolor; + int32_t maskl, maskr; + int x, y; + } bitblt; + + FILE* mmdbg_fp; + FILE* mmrdbg_fp; + uint32_t mmdbg_vidaddr; + uint32_t mmrdbg_vidaddr; + + uint8_t pos_regs[8]; + svga_t *mb_vga; + + int vidsys_ena; + + 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); + +typedef union { + uint32_t d; + uint8_t b[4]; +} DA2_VidSeq32; + +typedef struct { + uint32_t p8[8]; +} pixel32; + +/* safety read for internal functions */ +uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) +{ + if (addr & ~da2->vram_mask) return -1; + return da2->vram[addr]; +} + +void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) +{ + uint32_t writepx[8]; + destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ + //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; + da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; + destaddr <<= 3; + /* read destination data with big endian order */ + for (int i = 0; i < 8; i++) + writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) + | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + + DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; + DA2_VidSeq32 mask32; mask32.d = 0; + mask32.b[3] = mask32in.b[0]; + mask32.b[2] = mask32in.b[1]; + mask32.d &= 0xffff0000; + for (int i = 0; i < 8; i++) + { + if (da2->bitblt.bitshift_destr > 0) + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; + switch (da2->bitblt.raster_op) { + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; + } + } + for (int i = 0; i < 8; i++) { + da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; + da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; + } +} + +void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + //fill data with input color + for (int i = 0; i < 8; i++) + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +/* +Param Desc +01 Color +03 Bit Shift +04 Select plane? +05 Dir(10 or 11) + Command?(40 or 48) +08 Mask Left +09 Mask Right +0A Plane Mask? +0B ROP?(8h or 200h + 0-3h) +0D +20 Exec (1) +21 ? +22 ? +23 Tile W +28 Tile H +29 Dest Addr +2A Src Addr +2B Tile Addr +33 Size W +35 Size H + +*/ +void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + srcaddr &= 0xfffffffe; + srcaddr <<= 3; + for (int i = 0; i < 8; i++) + srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) + | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { + uint8_t pixeldata = 0; + for (int j = 0; j < 8; j++) { + if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; + } + return pixeldata; +} +void print_pixelbyte(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) + { + da2_log("%X", pixel1tohex(addr, i, da2)); + } +} + +void da2_bitblt_load(da2_t* da2) +{ + uint32_t value32; + uint64_t value64; + //da2_log("BITBLT loading params\n"); + //da2_log("BitBlt memory:\n"); + //if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + // { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + // } + int i = 0; + while (i < DA2_BLT_MEMSIZE) + { + if (da2->bitblt.reg[0x20] & 0x1) + break; + switch (da2->bitblt.payload[i]) { + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + //da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 3; + break; + case 0x91: + value32 = da2->bitblt.payload[i + 5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + //da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 5; + break; + case 0x99: + value64 = da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + //da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + //da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + i += 7; + break; + case 0x00: + break; + default: + da2_log("da2_ParseBLT: Unknown PreOP!\n"); + break; + } + i++; + } + da2->bitblt.exec = DA2_BLT_CIDLE; + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; + /* [89] 20: 0001 (1) then execute payload */ + if (da2->bitblt.reg[0x20] & 0x1) + { +#ifdef ENABLE_DA2_DEBUGBLT + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); + } + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; + } + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; + da2->bitblt.debug_reg_ip++; + if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR + da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); + for (int i = 0; i <= 0xb; i++) + da2_log("%02x ", da2->gdcreg[i]); + da2_log("\n"); + + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destpitch = da2->bitblt.reg[0x21]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + { + da2->bitblt.destaddr -= 2; + da2->bitblt.size_x += 1; + da2->bitblt.destpitch -= 2; + da2->bitblt.srcpitch -= 2; + } + da2->bitblt.fcolor = da2->bitblt.reg[0x0]; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + + if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode + { + da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); + da2->bitblt.exec = DA2_BLT_CDONE; + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {//Fill a rectangle (or draw a line) + da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.exec = DA2_BLT_CFILLRECT; + da2->bitblt.destaddr += 2; + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle ??(transfer tile data multiple times) os/2 only + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle (transfer tile data multiple times) + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {//Block transfer (range copy) + da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr += 2; + da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {//Block copy but reversed direction + da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); + } + //do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle + while (timer_is_enabled(&da2->bitblt.timer) && da2->bitblt.exec != DA2_BLT_CDONE) + { + da2_bitblt_exec(da2); + } + } +} +void da2_bitblt_exec(void* p) +{ + da2_t* da2 = (da2_t*)p; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + switch (da2->bitblt.exec) + { + case DA2_BLT_CIDLE: + timer_disable(&da2->bitblt.timer); + break; + case DA2_BLT_CLOAD: + da2_bitblt_load(da2); + da2->bitblt.indata = 0; + break; + case DA2_BLT_CFILLRECT: + //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CFILLTILE: + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CCOPYF: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr += 2; + break; + case DA2_BLT_CCOPYR: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr -= da2->bitblt.destpitch; + da2->bitblt.srcaddr -= da2->bitblt.srcpitch; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + break; + case DA2_BLT_CDONE: + //initialize regs with fefefefeh, clear regs with fefeh for debug dump + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; + else da2->bitblt.exec = DA2_BLT_CIDLE; + break; + } +} +void da2_out(uint16_t addr, uint16_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + int oldval; +/* +3E0 3E1 Sequencer Registers (undoc) +3E2 3E3 Font Registers (undoc) +3E4 3E5 CRT Control Registers (undoc) +3E8 3E9 Attribute Controller Registers (undoc) +3EA 3EB 3EC Graphics Contoller Registers +*/ + switch (addr) + { + case 0x3c6: /* PEL Mask */ + da2->dac_mask = val; + break; + case 0x3C7: /* Read Address */ + da2->dac_read = val; + da2->dac_pos = 0; + break; + case 0x3C8: /* Write Address */ + da2->dac_write = val; + da2->dac_read = val - 1; + 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_log("DS %X\n",DS); + da2->dac_status = 0; + da2->fullchange = changeframecount; + switch (da2->dac_pos) + { + case 0: + da2->dac_r = val; + da2->dac_pos++; + break; + case 1: + da2->dac_g = val; + da2->dac_pos++; + break; + case 2: + da2->vgapal[da2->dac_write].r = da2->dac_r; + da2->vgapal[da2->dac_write].g = da2->dac_g; + da2->vgapal[da2->dac_write].b = val; + //if (da2->ramdac_type == RAMDAC_8BIT) + // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); + //else + da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); + da2->dac_pos = 0; + da2->dac_write = (da2->dac_write + 1) & 255; + break; + } + break; + case LS_INDEX: + 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); + 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); + oldval = da2->ioctl[da2->ioctladdr]; + //if (da2->ioctladdr == 0x3) return;//monitor color + da2->ioctl[da2->ioctladdr] = val; + if (oldval != val) { + if (da2->ioctladdr == LS_RESET && val & 0x01) /* Mode register */ + da2_reset_ioctl(da2); + else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + da2_updatevidselector(da2); + } + else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ + { + da2->bitblt.indata = 1; + if (da2->bitblt.exec == DA2_BLT_CIDLE) + { + da2->bitblt.exec = DA2_BLT_CLOAD; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + } + } + } + break; + case LF_INDEX: + 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); + if (da2->fctladdr > 0x1f) return; + oldval = da2->fctl[da2->fctladdr]; + da2->fctl[da2->fctladdr] = val; + if (da2->fctladdr == 0 && oldval != val) + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + } + break; + case LC_INDEX: + da2->crtcaddr = val; + break; + case LC_DATA: + 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); + if (!(da2->crtc[da2->crtcaddr] ^ val)) return; + switch (da2->crtcaddr) { + case LC_CRTC_OVERFLOW: + //return; + break; + case LC_MAXIMUM_SCAN_LINE: + if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; + break; + case LC_START_ADDRESS_HIGH: + //if (da2->crtc[0x1c] & 0x40) return; + break; + case LC_VERTICAL_TOTALJ: /* Vertical Total */ + case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ + case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ + case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ + //val = 0x400; //for debugging bitblt + break; + case LC_VIEWPORT_SELECT: /* ViewPort Select? */ + //return; + break; + case LC_VIEWPORT_NUMBER: /* Compatibility? */ + break; + } + da2->crtc[da2->crtcaddr] = val; + switch (da2->crtcaddr) { + case LC_H_DISPLAY_ENABLE_END: + case LC_VERTICAL_TOTALJ: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + case LC_VERTICAL_SYNC_START: + case LC_V_DISPLAY_ENABLE_END: + case LC_START_VERTICAL_BLANK: + case LC_END_VERTICAL_BLANK: + case LC_VIEWPORT_PRIORITY: + da2->fullchange = changeframecount; + da2_recalctimings(da2); + break; + default: + break; + } + 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); + if (!da2->attrff) + { + // da2->attraddr = val & 31; + da2->attraddr = val & 0x3f; + if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) + { + da2->fullchange = 3; + da2->attr_palette_enable = val & 0x20; + da2_recalctimings(da2); + } + //da2_log("set attraddr: %X\n", da2->attraddr); + } + else + { + if ((da2->attraddr == LV_PANNING) && (da2->attrregs[LV_PANNING] != val)) + da2->fullchange = changeframecount; + if (da2->attrregs[da2->attraddr & 0x3f] != val) + da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrregs[da2->attraddr & 0x3f], val); + da2->attrregs[da2->attraddr & 0x3f] = val; + //da2_log("set attrreg %x: %x\n", da2->attraddr & 31, val); + if (da2->attraddr < 16) + da2->fullchange = changeframecount; + //if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr == 0x14 || da2->attraddr < 0x10) + if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) + { + for (int c = 0; c < 16; c++) + { + //if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrregs[c] & 0xf) | ((da2->attrregs[0x14] & 0xf) << 4); + //else da2->egapal[c] = (da2->attrregs[c] & 0x3f) | ((da2->attrregs[0x14] & 0xc) << 4); + if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrregs[c] & 0xf; + else da2->egapal[c] = da2->attrregs[c] & 0x3f; + } + } + if (da2->attraddr == LV_COLOR_PLANE_ENAB) + { + if ((val & 0xff) != da2->plane_mask) + da2->fullchange = changeframecount; + da2->plane_mask = val & 0xff; + } + if (da2->attraddr == LV_CURSOR_CONTROL) + { + switch (val & 0x18) { + case 0x08://fast blink + da2->blinkconf = 0x10; + break; + case 0x18://slow blink + da2->blinkconf = 0x20; + break; + default://no blink + da2->blinkconf = 0xff; + break; + } + } + switch (da2->attraddr) + { + case LV_MODE_CONTROL: + case LV_ATTRIBUTE_CNTL: + case LV_COMPATIBILITY: + da2_recalctimings(da2); + break; + default: + break; + } + } + da2->attrff ^= 1; + break; + case LG_INDEX: + da2->gdcaddr = val; + break; + case LG_DATA: + //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + //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); + switch (da2->gdcaddr & 0x1f) + { + case LG_READ_MAP_SELECT: + da2->readplane = val & 0x7; + break; + case LG_MODE: + da2->writemode = val & 3; + break; + case LG_MAP_MASKJ: + da2->writemask = val & 0xff; + break; + case LG_COMMAND: + break; + case LG_SET_RESET_2: + da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + return; + } + da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; + break; + //case 0x3ed: /* used by Windows 3.1 display driver */ + // da2->gdcreg[5] = val & 0xff; + // break; + default: + da2_log("DA2? Out addr %03X val %02X\n", addr, val); + break; + } +} + +uint16_t da2_in(uint16_t addr, void *p) +{ + da2_t * da2 = (da2_t *)p; + //svga_t *svga = &da2->svga; + uint16_t temp; + +// if (addr != 0x3da) da2_log("IN gd5429 %04X\n", addr); + switch (addr) + { + case 0x3c3: + temp = 0; + break; + case 0x3c6: temp = da2->dac_mask; + break; + case 0x3c7: temp = da2->dac_status; + break; + case 0x3c8: temp = da2->dac_write; + break; + case 0x3c9: + da2->dac_status = 3; + switch (da2->dac_pos) + { + case 0: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].r & 0x3f; + break; + case 1: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].g & 0x3f; + break; + case 2: + da2->dac_pos = 0; + da2->dac_read = (da2->dac_read + 1) & 255; + temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; + break; + } + break; + case LS_INDEX: + temp = da2->ioctladdr; + break; + case LS_DATA: + //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) + if (da2->ioctladdr > 0xf) return 0xff; + temp = da2->ioctl[da2->ioctladdr]; + if (da2->ioctladdr == LS_STATUS) { /* Status register */ + //da2_log("Read 3E1 DAC status: %d, %d, %d\n", da2->vgapal[0].r, da2->vgapal[0].g, da2->vgapal[0].b); + //da2_log("attr palette: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->attrregs[i]); + //da2_log("\n"); + //da2_log("vram A0000h: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[i]); + //da2_log("\n"); + //da2_log("vram B8000h: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[0x18000 + i]); + //da2_log("\n"); + //da2_log("vram E0000h: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->cram[i]); + //da2_log("\n"); + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrregs[LV_COMPATIBILITY] & 0x08) + temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ + else + temp |= 0x80; /* Active when the RGB output voltage is lowand the cable is connected to the color monitor. + If the cable or the monitor is wrong, it becomes inactive. */ + temp &= 0xf6;//idle + if (da2->bitblt.exec != DA2_BLT_CIDLE) + { + //da2_log("exec:%d\n", da2->bitblt.exec); + temp |= 0x08;//wait(bit 3 + bit 0) + //if (!da2->bitblt.timer.enabled) + //{ + // da2_log("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 |= 0x01; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + } + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + break; + case LF_INDEX: + temp = da2->fctladdr; + break; + case LF_DATA: + if (da2->fctladdr > 0x1f) return 0xff; + temp = da2->fctl[da2->fctladdr]; + break; + case LC_INDEX: + temp = da2->crtcaddr; + break; + case LC_DATA: + if (da2->crtcaddr > 0x1f) return 0xff; + temp = da2->crtc[da2->crtcaddr]; + break; + case LV_PORT: + temp = da2->attraddr | da2->attr_palette_enable; + break; + case 0x3E9: + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ + { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + else + temp = da2->attrregs[da2->attraddr]; + //da2_log("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: + temp = da2->gdcaddr; + 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); + break; + } + //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +/* +* Write I/O +* out b(idx), out b(data), out b(data) +* out b(idx), out w(data) +* out b(idx), out w(data), out b(data) +* out w(idx) +* Read I/O +* out b(idx), in b(data) +* out b(idx), in b, in b(data) +* out b(idx), in w(data) +*/ +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->inflipflop = 0; + switch (addr) + { + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + if (da2->outflipflop) + { + /* out b(idx), out b(data), out b(data) */ + da2->iolatch |= (uint16_t)val << 8; + da2->outflipflop = 0; + } + else + {// + da2->iolatch = val; + da2->outflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + default: + da2->iolatch = val; + da2->outflipflop = 0; + break; + } + da2_out(addr, da2->iolatch, da2); +} +void da2_outw(uint16_t addr, uint16_t val, void* p) +{ + //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + switch (addr) + { + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + da2_out(addr, val & 0xff, da2); + da2->iolatch = val >> 8; + da2_out(addr + 1, da2->iolatch, da2); + da2->outflipflop = 1; + break; + case LV_PORT: + da2->attrff = 0; + da2_out(addr, val & 0xff, da2); + da2_out(addr, val >> 8, da2); + 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_out(LG_DATA, val >> 8, da2); + break; + case 0x3ED: + da2->gdcaddr = LG_MODE; + da2_out(LG_DATA, val, da2); + break; + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + default: + da2_out(addr, val, da2); + da2->outflipflop = 0; + break; + case 0x3EE: + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2->reg3ee[val & 0xff] = val >> 8; + break; + } +} +uint8_t da2_inb(uint16_t addr, void* p) +{ + uint8_t temp; + da2_t* da2 = (da2_t*)p; + da2->outflipflop = 0; + switch (addr) + { + case LC_DATA: + if (da2->inflipflop) + { + /* out b(idx), in b(low data), in b(high data) */ + temp = da2->iolatch >> 8; + da2->inflipflop = 0; + } + else + {// + da2->iolatch = da2_in(addr, da2); + temp = da2->iolatch & 0xff; + da2->inflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + case LS_DATA: + case LF_DATA: + case LG_DATA: + default: + temp = da2_in(addr, da2) & 0xff; + da2->inflipflop = 0; + break; + } + //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +uint16_t da2_inw(uint16_t addr, void* p) +{ + //uint16_t temp; + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + da2->outflipflop = 0; + return da2_in(addr, da2); +} +/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ +uint8_t da2_in_ISR(uint16_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t temp = 0; + if (addr == 0x3da) { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} + +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); +} + +/* +The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. + [Character drawing] + SBCS: + 1 2 ... 13 + 1 | H.Grid + |---------------- + 2 | Space + 3 V| + .| + G| Font Pattern + r| (12x24 pixels) + i| + d| +26 |________________ +27 Space + ---------------- +28 Underscore ] + ---------------- >Cursor Position +29 ] + + DBCS: + 1 2 ... 13 1 2 ... 12 13 + 1 | H.Grid | H.Grid | + -|--------------------------|- + 2 | Space | Space | + -|--------------------------|- + 3 V| | |S + .| | |p + G| Font Pattern |a + r| (24x24 pixels) |c + i| | |e + d| | | +26 |_____________|____________| +27 | Space | Space + ------------------------------ +28 | Underscore | Underscore ] + ------------------------------ >Cursor Position +29 | | ] + + [Attributes] + Video mode 08h: + 7 6 5 4 3 2 1 0 + Blink |Under |HGrid |VGrid |Bright|Revers|FntSet|DBCS/SBCS| + + Video mode 0Eh: + -Blue |-Green|HGrid |VGrid |-Red |Revers|FntSet|DBCS/SBCS| + + Bit 1 switches the font bank to the Extended SBCS. DOS K3.x loads APL characters from $SYSEX24.FNT into it. + DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. + This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. + +[Font ROM Map (DA2)] +The Font ROM is accessed via 128 KB memory window located on A0000-BFFFFh. +I don't know how much data the actual Font ROM has. +Here information, I researched it by disassembling J-DOS. + +Bank 0 + 4800- * +Bank 1, 2, 3 + * - * +Bank 4 + * -0DB6Fh ( 4800-8DB6Fh;IBMJ 100-1F7Dh) : JIS X 0208 DBCS (24 x 24) +10000-16D1Fh (90000-96D1Fh;IBMJ 2000-2183h) : IBM Extended Characters +18000-1BFFFh (98000-9BFFFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) +1FD20- * +Bank 5 + * -0D09Fh (9FD20-AD09Fh;IBMJ 2384-2673h) : Gaiji 752 chs (maybe blank) +10000-13FFFh (B0000-B3FFFh;around IBMJ 271C-27FFh) : Extended SBCS (13 x 30) +14000-146FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho + (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters + + The signature 80h, 01h must be placed at Bank 0:1AFFEh to run OS/2 J1.3. + +[Gaiji RAM Map (DA2)] + Bank 0 00000-1FFFFh placed between A0000h-BFFFFh + 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes + 1F800-1FFFFh(BF800-BFFFFh): Gaiji Resident (SJIS: F040-F04Fh, IBM: 2384-2393h) 16 chs + + Bank 1 20000-3FFFFh placed between A0000h-BFFFFh + 20000-33FFFh(A0000-B3FFFh): Gaiji Resident (SJIS: F050-F39Ch, IBM: 2394-2613h) 640 chs + 34000-37FFFh(B4000-B7FFFh): Basic SBCS(00-FFh, ATTR bit 1 = off) + 38000-3AFFFh(B8000-BAFFFh): Gaiji Resident (SJIS: F39D-F3FCh, IBM: 2614-2673h) 96 chs + 3C000-3FFFFh(BC000-BFFFFh): Extended SBCS(00-FFh, ATTR bit 1 = on) + +[IBMJ code to Gaiji address conv tbl from DOS K3.3] + A B C + 2ADC, 2C5F, +5524 --> 8000 + 2614, 2673, +90EC --> B700 + 2384, 2613, +906C --> B3F0 + 0682, 1F7D, +0000 + + 8000 - 8183h 184h(388 characters) IBM Extended Characters + B3F0 - B75Fh 370h(880 characters) User-defined Characters +*/ + +/* Get character line pattern from jfont rom or gaiji volatile memory */ +uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { + da2_t* da2 = (da2_t*)p; + uint32_t font = 0; + int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) + if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) + if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { + font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 + font <<= 8; //1111 1111 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 + font >>= 1; //0111 1111 1222 2000 + font <<= 4; //0111 1111 1222 2000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 + font <<= 8; //0111 1111 1222 2000 2222 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 + font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 + //font >>= 1;//put blank at column 1 (and 26) + } + else if (code >= 0xb000 && code <= 0xb75f) + { + //convert code->address in gaiji memory + code -= 0xb000; + code *= 0x80; + //code += 0xf800; + font = da2->mmio.ram[code + line * 4]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 1]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 2]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 3]; + } + else if (code > DA2_FONTROM_SIZE) + font = 0xffffffff; + else + font = 0; + return font; +} + +/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ +uint8_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 getPS55ForeColor(uint8_t attr, da2_t* da2) +{ + uint8_t foreground = ~attr & 0x08;// 0000 1000 + foreground <<= 2; //0010 0000 + foreground |= ~attr & 0xc0;// 1110 0000 + foreground >>= 4;//0000 1110 + if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + return foreground; +} + +void da2_render_blank(da2_t* da2) +{ + int x, xx; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + for (x = 0; x < da2->hdisp; x++) + { + for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + } +} +/* Display Adapter Mode 8, E Drawing */ +static void da2_render_text(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //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->vram_display_mask]; + attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; + //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); + if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80)//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); + if (attr & 0x04) {//reverse 0000 0100 + bg = fg; + fg = 0; + } + } + else + {//--Parse attribute byte in monochrome mode-- + if (attr & 0x08) fg = 3;//Highlight 0000 1000 + else fg = 2; + bg = 0;//Background is always color #0 (default is black) + if (!(~attr & 0xCC))//Invisible 11xx 11xx -> 00xx 00xx + { + fg = bg; + attr &= 0x33;//disable blinkking, underscore, highlight and reverse + } + if (attr & 0x04) {//reverse 0000 0100 + bg = fg; + fg = 0; + } + // Blinking 1000 0000 + fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; + //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); + } + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + //draw -= 13; + // SBCS or DBCS left half + if (chr_wide == 0) { + if (attr & 0x01) chr_wide = 1; + //chr_wide = 0; + // Stay drawing If the char code is DBCS and not at last column. + if (chr_wide) { + //Get high DBCS code from the next video address + chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } + else { + // the char code is SBCS (ANK) + uint32_t fontbase; + if (attr & 0x02)//second map of SBCS font + fontbase = 0x3c000; + else + fontbase = 0x34000; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. + if (da2->sc == 27 && attr & 0x40 && ~da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) {//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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//vertical line (white) + } + if (da2->sc == 0 && attr & 0x20 && ~da2->attrregs[LV_PAS_STATUS_CNTRL]) {//HGrid + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[(da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 + fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); + bg = 0; + if (attr & 0x04) {//Color 0 if reverse + bg = fg; + fg = 0; + } + for (uint32_t n = 0; n < cursorwidth; n++) + if (p[n] == da2->pallook[da2->egapal[cursorcolor]] || da2->egapal[bg] == da2->egapal[cursorcolor]) + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[fg]] : da2->pallook[da2->egapal[bg]]; + else + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +/* Display Adapter Mode 3 Drawing */ +static void da2_render_textm3(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr, extattr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) + { + chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; + extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; + //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + bg = attr >> 4; + //if (da2->blink) bg &= ~0x8; + //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; + fg = attr & 0xf; + fg = IRGBtoBGRI(fg); + bg = IRGBtoBGRI(bg); + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + // SBCS or DBCS left half + if (chr_wide == 0) { + if (extattr & 0x01) chr_wide = 1; + // Stay drawing if the char code is DBCS and not at last column. + if (chr_wide) { + //Get high DBCS code from the next video address + chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } + else { + // the char code is SBCS (ANK) + uint32_t fontbase; + fontbase = 0x34000; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //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[0x1f] & 0x20 ? 26 : 13); + //int cursorcolor = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[0x1a]) : 2;//Choose color 2 if mode 8 + //fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + //bg = 0; + //if (attr & 0x04) {//Color 0 if reverse + // bg = fg; + // fg = 0; + //} + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +void da2_render_color_4bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + da2->plane_mask &= 0x0f;//safety + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); + p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); + p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); + p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); + p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); + p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); + p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); + p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); + p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_render_color_8bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | + ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); + p[0] = da2->pallook[dat]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | + ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); + p[1] = da2->pallook[dat]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | + ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); + p[2] = da2->pallook[dat]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | + ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); + p[3] = da2->pallook[dat]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | + ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); + p[4] = da2->pallook[dat]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | + ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); + p[5] = da2->pallook[dat]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | + ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); + p[6] = da2->pallook[dat]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | + ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); + p[7] = da2->pallook[dat]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_updatevidselector(da2_t* da2) { + /* if VGA passthrough mode */ + da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); + if (da2->ioctl[LS_MODE] & 0x02) + { + da2->override = 1; + svga_set_override(da2->mb_vga, 0); + } + else + { + svga_set_override(da2->mb_vga, 1); + da2->override = 0; + } +} + + +void da2_recalctimings(da2_t* da2) +{ + double crtcconst; + double _dispontime, _dispofftime, disptime; + + da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w + da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w + da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w + da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare + da2->split = 0xfff; + da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w + da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + + if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { + da2->hdisp--; + da2->dispend -= 29; + } + else { + //da2->vtotal += 2; + da2->dispend--; + //da2->vsyncstart++; + //da2->split++; + //da2->vblankstart++; + //da2->hdisp--; + } + + da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; + da2->htotal += 1; + + da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline + + da2->clock = da2->da2const; + + da2->lowres = da2->attrregs[LC_VERTICAL_SYNC_START] & 0x40; + + da2->interlace = 0; + + //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + da2->ca_adj = 0; + + da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; + + da2->hdisp_time = da2->hdisp; + da2->render = da2_render_blank; + //determine display mode + //if (da2->attr_palette_enable && (da2->attrregs[0x1f] & 0x08)) + if (da2->attrregs[LV_COMPATIBILITY] & 0x08) + { + //if (da2->ioctl[0] & 0x01)//256 color mode + //{ + // da2_log("Set videomode to PS/55 8 bpp graphics.\n"); + // da2->vram_display_mask = 0x1ffff; + // da2->render = da2_render_color_8bpp; + //} + //else + if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode + da2->hdisp *= 16; + da2->char_width = 13; + da2->hdisp_old = da2->hdisp; + //if (da2->plane_mask == 0x01) {//PS/55 monochrome + // da2_log("Set videomode to PS/55 Monochrome graphics.\n"); + // //da2->render = da2_render_mono; + // da2->render = da2_render_color_4bpp; + // da2->vram_display_mask = 0x1ffff; + //} + if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) {//PS/55 256 color + da2_log("Set videomode to PS/55 8 bpp graphics.\n"); + da2->render = da2_render_color_8bpp; + da2->vram_display_mask = DA2_MASK_GRAM; + } + else {//PS/55 8-color + da2_log("Set videomode to PS/55 4 bpp graphics.\n"); + da2->vram_display_mask = DA2_MASK_GRAM; + da2->render = da2_render_color_4bpp; + } + } + else {//text mode + if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) {//PS/55 Mode 03 + da2_log("Set videomode to PS/55 Mode 03 text.\n"); + da2->render = da2_render_textm3; + da2->vram_display_mask = DA2_MASK_CRAM; + } + else {//PS/55 text(color/mono) + da2_log("Set videomode to PS/55 Mode 8/E text.\n"); + da2->render = da2_render_text; + da2->vram_display_mask = DA2_MASK_CRAM; + } + da2->hdisp *= 13; + da2->hdisp_old = da2->hdisp; + da2->char_width = 13; + } + } + else + { + da2_log("Set videomode to blank.\n"); + } + //if (!da2->scrblank && da2->attr_palette_enable) + //{ + //da2->render = da2_draw_text; + //} + + // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + + /*da2->char_width = 13;*///PS55TEXT = 13, GFX = 16 + //if (da2->recalctimings_ex) + // da2->recalctimings_ex(da2); + + if (da2->vblankstart < da2->dispend) + da2->dispend = da2->vblankstart; + + crtcconst = da2->clock * da2->char_width; + + disptime = da2->htotal; + _dispontime = da2->hdisp_time; + + da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); + //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + da2->dispontime = (uint64_t)_dispontime; + da2->dispofftime = (uint64_t)_dispofftime; + if (da2->dispontime < TIMER_USEC) + da2->dispontime = TIMER_USEC; + if (da2->dispofftime < TIMER_USEC) + 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->render %08X\n", da2->render); +} + +uint8_t da2_mca_read(int port, void *p) +{ + da2_t *da2 = (da2_t *)p; + return da2->pos_regs[port & 7]; +} + +static void da2_mapping_update(da2_t *da2) +{ + if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; + da2->old_pos2 = da2->pos_regs[2]; + //da2_recalc_mapping(da2); + if (da2->pos_regs[2] & 0x01) + { + da2_log("DA2 enable registers\n"); + for (int i = 0; i < 8; i++) + da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); + io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, 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); + } + else + { + da2_log("DA2 disable registers\n"); + 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); + io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + } +} + +void da2_mca_write(int port, uint8_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + + da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); + + if (port < 0x102) + return; + da2->pos_regs[port & 7] = val; + + da2_mapping_update(da2); +} + +static uint8_t da2_mca_feedb(void* priv) +{ + const da2_t* da2 = (da2_t*)priv; + + return da2->pos_regs[2] & 0x01; +} + +static void da2_mca_reset(void *p) +{ + da2_t *da2 = (da2_t *)p; + da2_reset(da2); + da2_mca_write(0x102, 0, da2); +} +// +static void da2_gdcropB(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + } + } + } +} +static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { + uint8_t bitmask_l = bitmask & 0xff; + uint8_t bitmask_h = bitmask >> 8; + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + } + } + } +} + +static uint8_t da2_mmio_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + if (da2->fctl[LF_MMIO_SEL] == 0x80) + //linear access + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); + else + { + //64k bank switch access + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { + case 0xb0://Gaiji RAM + addr &= DA2_MASK_GAIJIRAM;//safety access + //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); + return da2->mmio.ram[addr]; + break; + case 0x10://Font ROM + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + if (addr > DA2_FONTROM_SIZE) return 0xff; + return da2->mmio.font[addr]; + break; + default: + return 0xff;//invalid memory access + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode + { + cycles -= video_timing_read_b; + //readmode 1 + //da2_log("da2_rp: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->readplane, addr); + for (int i = 0; i < 8; i++) + da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte + //da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read in word + //da2->gdcramlatched = 1; + //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint8_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); + } + return ~ret; + } + else return da2->gdcla[da2->readplane]; + } + else //text mode 3 + { + cycles -= video_timing_read_b; + return da2->vram[addr]; + } +} +static uint16_t da2_mmio_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + if (da2->ioctl[LS_MMIO] & 0x10) { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + cycles -= video_timing_read_w; + addr &= DA2_MASK_MMIO; + for (int i = 0; i < 8; i++) + da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch + //da2->gdcramlatched = 1; + ////debug + //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) + //{ + // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 16; i++) + //{ + // int pixeldata = 0; + // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; + // fprintf(da2->mmrdbg_fp, "%X", pixeldata); + //} + //da2->mmrdbg_vidaddr = addr; + //// + + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint16_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); + } + return ~ret; + } + else + { + //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + return da2->gdcla[da2->readplane]; + } + } + else { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } +} + +static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("da2_mmio_write %x %x\n", addr, val); + if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); + //Gaiji RAM + if (da2->fctl[LF_MMIO_SEL] == 0x80) + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy + else + { + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + switch (da2->fctl[LF_MMIO_MODE]) { + case 0xb0://Gaiji RAM 1011 0000 + addr &= DA2_MASK_GAIJIRAM;//safety access + da2->mmio.ram[addr] = val; + break; + case 0x10://Font ROM 0001 0000 + //Read-Only + break; + case 0x00: + //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + if (addr >= DA2_BLT_MEMSIZE) + { + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + return; + } + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + break; + default: + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + uint8_t wm = da2->writemask; + //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); + //debug + //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, "\nB %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 8; i++) + //{ + // int pixeldata = 0; + // if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + // fprintf(da2->mmdbg_fp, "%X", pixeldata); + //} + //da2->mmdbg_vidaddr = addr; + //} + + cycles -= video_timing_write_b; + + da2->changedvram[addr >> 12] = changeframecount; + addr <<= 3; + + //if (GCLATCHCOND) { + //if (da2->writemode == 2) { + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + //} + //else { + // for (int i = 0; i < 8; i++) + // da2->gdcsrc[i] = da2->vram[addr | i];//read in byte from vram + //} + //da2->gdcramlatched = 0; + //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); + //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropB(addr, da2); + return; + } + + switch (da2->writemode) + { + case 2: + //case 1: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) 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, 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], da2->gdcreg[LG_BIT_MASK_LOW], 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 2: + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); + da2_gdcropB(addr, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + wm = da2->gdcreg[LG_BIT_MASK_LOW]; + da2->gdcreg[LG_BIT_MASK_LOW] &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + da2_gdcropB(addr, da2); + da2->gdcreg[LG_BIT_MASK_LOW] = wm; + 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[addr] = val; + da2->fullchange = 2; + } +} +uint16_t rightRotate(uint16_t data, uint8_t count) +{ + return (data >> count) | (data << (sizeof(data) * 8 - count)); +} +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t wm = da2->writemask; + uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + bitmask <<= 8; + bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; + //debug + //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 ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 16; i++) + //{ + // int pixeldata = 0; + // if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); + // fprintf(da2->mmdbg_fp, "%X", pixeldata); + //} + //da2->mmdbg_vidaddr = addr; + //} + //cycles -= video_timing_write_w; + //cycles_lost += video_timing_write_w; + + //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); + //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 >> 12] = changeframecount; + da2->changedvram[(addr + 1) >> 12] = changeframecount; + addr <<= 3; + + //if (((da2->gdcreg[LG_COMMAND] & 0x03) || da2->writemode == 2) && da2->writemode != 1) { + //if (GCLATCHCOND) { + //if (da2->writemode == 2) { + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + //} + //else { + // for (int i = 0; i < 8; i++) + // da2->gdcsrc[i] = (uint16_t)(da2->vram[addr | i]) | ((uint16_t)(da2->vram[(addr + 8) | i]) << 8);//read in word + //} + //da2->gdcramlatched = 0; + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + return; + } + //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + switch (da2->writemode)// writemode 0 or 2 rop(0b) 0 or 3 + { + case 2: + //case 1: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; + da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + } + break; + //case 2:win + + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = val & 0xff; + da2->vram[(addr + 8) | i] = val >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else da2->gdcinput[i] = val; + + //for (int i = 0; i < 8; i++)//draft20240722 0211 + // da2->gdcla[i] = 0;//read in word + da2_gdcropW(addr, bitmask, da2); + // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + //case 2: + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + da2->vram[addr | i] = wdata & 0xff; + da2->vram[(addr + 8) | i] = wdata >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + wm = bitmask; + bitmask &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2_gdcropW(addr, bitmask, da2); + bitmask = wm; + break; + } + //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); +} +static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0x1ffff) != 0xA0000) return; + if (da2->ioctl[LS_MMIO] & 0x10) { + //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + addr &= DA2_MASK_MMIO; + //return; + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_gc_writeW(addr, val, da2); + } + else {//mode 3h text + //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } +} + +static void da2_code_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0xfff) != 0xE0000) return; + addr &= DA2_MASK_CRAM; + da2->cram[addr] = val; + da2->fullchange = 2; +} +static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); + cycles -= video_timing_write_b; + da2_code_write(addr, val, da2); +} +static void da2_code_writew(uint32_t addr, uint16_t val, void* p) +{ + //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_write_w; + da2_code_write(addr, val & 0xff, da2); + da2_code_write(addr + 1, val >> 8, da2); +} + +static uint8_t da2_code_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return 0xff; + addr &= DA2_MASK_CRAM; + return da2->cram[addr]; +} +static uint8_t da2_code_readb(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_b; + return da2_code_read(addr, da2); +} +static uint16_t da2_code_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_w; + return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); + //return 0; +} + +void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) +{ + if (wx != xsize || wy != ysize) { + xsize = wx; + ysize = wy; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(32, 0, xsize, ysize); + frames++; + + video_res_x = wx; + video_res_y = wy; + video_bpp = 8; +} + +void da2_poll(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + int x; + + if (!da2->linepos) + { + timer_advance_u64(&da2->timer, da2->dispofftime); + // if (output) printf("Display off %f\n",vidtime); + da2->cgastat |= 1; + da2->linepos = 1; + + if (da2->dispon) + { + da2->hdisp_on = 1; + + da2->ma &= da2->vram_display_mask; + if (da2->firstline == 2000) + { + da2->firstline = da2->displine; + video_wait_for_buffer(); + } + + //RENDER + if (!da2->override) + da2->render(da2); + + if (da2->lastline < da2->displine) + da2->lastline = da2->displine; + } + + //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + da2->displine++; + if (da2->interlace) + da2->displine++; + if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) + { + //da2_log("Vsync off at line %i\n",displine); + da2->cgastat &= ~8; + } + da2->vslines++; + if (da2->displine > 1200) + da2->displine = 0; + // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + // displine, vc, ma); + } + else + { + // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + timer_advance_u64(&da2->timer, da2->dispontime); + + // if (output) printf("Display on %f\n",vidtime); + if (da2->dispon) + da2->cgastat &= ~1; + da2->hdisp_on = 0; + + da2->linepos = 0; + if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_END] & 31)) + da2->con = 0; + if (da2->dispon) + { + if (da2->sc == da2->rowcount) + { + da2->linecountff = 0; + da2->sc = 0; + + da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) + if (da2->interlace) + da2->maback += (da2->rowoffset << 1); + da2->maback &= da2->vram_display_mask; + da2->ma = da2->maback; + } + else + { + da2->sc++; + da2->sc &= 31; + da2->ma = da2->maback; + } + } + //da2->hsync_divisor = !da2->hsync_divisor; + + //disable for 256 color mode + //if (da2->hsync_divisor && (da2->crtc[0x17] & 4)) + // return; + + da2->vc++; + da2->vc &= 2047; + + if (da2->vc == da2->dispend) + { + //if (da2->vblank_start) + // da2->vblank_start(da2); + // da2_log("VC dispend\n"); + da2->dispon = 0; + //if (da2->crtc[10] & 0x20) da2->cursoron = 0; + //else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) {//in text mode + if (da2->attrregs[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + { + da2->cursoron = (da2->blink | 1) & da2->blinkconf; + } + else + { + da2->cursoron = 0; + } + if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute + da2->fullchange = 2; + } + da2->blink++; + + for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) + { + if (da2->changedvram[x]) + da2->changedvram[x]--; + } + // memset(changedvram,0,2048); del + if (da2->fullchange) + { + da2->fullchange--; + //da2->fps++; + } + } + if (da2->vc == da2->vsyncstart) + { + int wx, wy; + // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + da2->dispon = 0; + 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; + + da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); + + //readflash = 0; + + da2->firstline = 2000; + da2->lastline = 0; + + da2->firstline_draw = 2000; + da2->lastline_draw = 0; + + da2->oddeven ^= 1; + + 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; + + //if (!da2->video_res_override) + //{ + //da2->video_res_x = wx; + //da2->video_res_y = wy + 1; + + if (da2->ioctl[LS_MODE] & 1) /*Text mode*/ + { + //da2->video_res_x /= da2->char_width; + //da2->video_res_y /= (da2->crtc[9] & 31) + 1; + //da2->video_bpp = 0; + } + else + { + //if (da2->crtc[9] & 0x80) + // da2->video_res_y /= 2; + //if (!(da2->crtc[0x17] & 2)) + // da2->video_res_y *= 4; + //else if (!(da2->crtc[0x17] & 1)) + // da2->video_res_y *= 2; + //da2->video_res_y /= (da2->crtc[9] & 31) + 1; + //if (da2->render == da2_render_8bpp_lowres || + // da2->render == da2_render_15bpp_lowres || + // da2->render == da2_render_16bpp_lowres || + // da2->render == da2_render_24bpp_lowres || + // da2->render == da2_render_32bpp_lowres) + //da2->video_res_x /= 2; + + //switch (da2->gdcreg[5] & 0x60) + //{ + //case 0x00: da2->video_bpp = 4; break; + //case 0x20: da2->video_bpp = 2; break; + //case 0x40: case 0x60: da2->video_bpp = da2->bpp; break; + //} + //da2->video_bpp = da2->bpp; + } + //} + //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma + (da2->rowoffset << 1); + + // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + + //if (da2->vsync_callback) + // da2->vsync_callback(da2); + } + if (da2->vc == da2->vtotal) + { + // da2_log("VC vtotal\n"); + + + // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + da2->vc = 0; + da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->dispon = 1; + da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + da2->scrollcache = da2->attrregs[LV_PANNING] & 7; + //da2->linecountff = 0; + + //da2->hwcursor_on = 0; + //da2->hwcursor_latch = da2->hwcursor; + + //da2->overlay_on = 0; + //da2->overlay_latch = da2->overlay; + // da2_log("Latch HWcursor addr %08X\n", da2_hwcursor_latch.addr); + + // da2_log("ADDR %08X\n",hwcursor_addr); + } + if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_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 da2_loadfont(char* fname, void* p) { + da2_t* da2 = (da2_t*)p; + uint8_t buf; + //uint32_t code = 0; + uint64_t fsize; + if (!fname) return; + if (*fname == '\0') return; + FILE* mfile = rom_fopen(fname, "rb"); + if (!mfile) { + //da2_log("MSG: Can't open binary ROM font file: %s\n", fname); + return; + } + fseek(mfile, 0, SEEK_END); + fsize = ftell(mfile);//get filesize + fseek(mfile, 0, SEEK_SET); + if (fsize > DA2_FONTROM_SIZE) { + fsize = DA2_FONTROM_SIZE;//truncate read data + //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); + //fclose(mfile); + //return 1; + } + uint32_t j = 0; + while (ftell(mfile) < fsize) { + fread(&buf, sizeof(uint8_t), 1, mfile); + da2->mmio.font[j] = buf; + j++; + } + fclose(mfile); + return; +} + +/* 12-bit DAC color palette for IBMJ Display Adapter with color monitor */ +static uint8_t ps55_palette_color[64][3] = +{ +{0x00,0x00,0x00},{0x00,0x00,0x2A},{0x00,0x2A,0x00},{0x00,0x2A,0x2A},{0x2A,0x00,0x00},{0x2A,0x00,0x2A},{0x2A,0x2A,0x00},{0x2A,0x2A,0x2A}, +{0x00,0x00,0x15},{0x00,0x00,0x3F},{0x00,0x2A,0x15},{0x00,0x2A,0x3F},{0x2A,0x00,0x15},{0x2A,0x00,0x3F},{0x2A,0x2A,0x15},{0x2A,0x2A,0x3F}, +{0x00,0x15,0x00},{0x00,0x15,0x2A},{0x00,0x3F,0x00},{0x00,0x3F,0x2A},{0x2A,0x15,0x00},{0x2A,0x15,0x2A},{0x2A,0x3F,0x00},{0x2A,0x3F,0x2A}, +{0x00,0x15,0x15},{0x00,0x15,0x3F},{0x00,0x3F,0x15},{0x00,0x3F,0x3F},{0x2A,0x15,0x15},{0x2A,0x15,0x3F},{0x2A,0x3F,0x15},{0x2A,0x3F,0x3F}, +{0x15,0x00,0x00},{0x15,0x00,0x2A},{0x15,0x2A,0x00},{0x15,0x2A,0x2A},{0x3F,0x00,0x00},{0x3F,0x00,0x2A},{0x3F,0x2A,0x00},{0x3F,0x2A,0x2A}, +{0x15,0x00,0x15},{0x15,0x00,0x3F},{0x15,0x2A,0x15},{0x15,0x2A,0x3F},{0x3F,0x00,0x15},{0x3F,0x00,0x3F},{0x3F,0x2A,0x15},{0x3F,0x2A,0x3F}, +{0x15,0x15,0x00},{0x15,0x15,0x2A},{0x15,0x3F,0x00},{0x15,0x3F,0x2A},{0x3F,0x15,0x00},{0x3F,0x15,0x2A},{0x3F,0x3F,0x00},{0x3F,0x3F,0x2A}, +{0x15,0x15,0x15},{0x15,0x15,0x3F},{0x15,0x3F,0x15},{0x15,0x3F,0x3F},{0x3F,0x15,0x15},{0x3F,0x15,0x3F},{0x3F,0x3F,0x15},{0x3F,0x3F,0x3F} +}; + +void da2_reset_ioctl(da2_t* da2) +{ + da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ + da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ + da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ +} + +static void +da2_reset(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + + /* Initialize drawing */ + da2->bitblt.exec = DA2_BLT_CIDLE; + da2->render = da2_render_blank; + da2_reset_ioctl(da2); + + da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ + da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->ioctl[LS_CONFIG1] = OldLSI | Mon_ID3 | Page_Two; /* Configuration(Low) : DA - 2, Monitor ID 3, 1024 KB */ + da2->ioctl[LS_CONFIG2] = Mon_ID1; /* Configuration (High): Monitor ID 0-2 */ + da2->fctl[0] = 0x2b; /* 3E3h:0 */ + da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ + da2->attrregs[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ + da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ + da2->ma_latch = 0; + //da2->gdcramlatched = 0; + da2->interlace = 0; + da2->attrregs[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attr_palette_enable = 0; /* disable attribute generator */ + + /* Set default color palette (Display driver of Win 3.1 won't reset palette) */ + da2_out(0x3c8, 0, da2); + for (int i = 0; i < 256; i++) { + da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); + } +} + +static void *da2_init() +{ + //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM + + if (svga_get_pri() == NULL) + return NULL; + svga_t *mb_vga = svga_get_pri(); + mb_vga->cable_connected = 0; + + da2_t* da2 = malloc(sizeof(da2_t)); + da2->mb_vga = mb_vga; + + da2->dispontime = 1000ull << 32; + da2->dispofftime = 1000ull << 32; + int memsize = 1024 * 1024; + da2->vram = malloc(memsize); + da2->vram_mask = memsize - 1; + //da2->gram_display_mask = (memsize - 1) >> 3; + da2->cram = malloc(0x1000); + //da2->cram_display_mask = 0x1000 - 1; + da2->vram_display_mask = DA2_MASK_CRAM; + da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2_loadfont(DA2_FONTROM_PATH, da2); + + mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ +#ifdef ENABLE_DA2_DEBUGBLT + da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); + da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); + da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.payload_addr = 0; + da2_reset(da2); + + mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); + + mem_mapping_disable(&da2->mmio.mapping); + + mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + + mem_mapping_disable(&da2->cmapping); + + timer_add(&da2->timer, da2_poll, da2, 0); + da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + + return da2; +} +static int da2_available() +{ + return rom_present(DA2_FONTROM_PATH); +} + +void da2_close(void *p) +{ + da2_t *da2 = (da2_t *)p; + + /* dump mem for debug */ +#ifndef RELEASE_BUILD + FILE* f; + f = fopen("da2_cram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->cram, 0x1000, 1, f); + fclose(f); + } + f = fopen("da2_vram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vram, 1024*1024, 1, f); + fclose(f); + } + f = fopen("da2_gram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->mmio.ram, 256*1024, 1, f); + fclose(f); + } + f = fopen("da2_attrpal.dmp", "wb"); + if (f != NULL) { + fwrite(da2->attrregs, 32, 1, f); + fclose(f); + } + f = fopen("da2_dacrgb.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vgapal, 3*256, 1, f); + fclose(f); + } + f = fopen("da2_daregs.txt", "w"); + if (f != NULL) { + for (int i=0;i<0x10;i++) + fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (int i = 0; i < 0x40; i++) + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrregs[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + fclose(f); + } +#ifdef ENABLE_DA2_DEBUGBLT + f = fopen("da2_bltdump.csv", "w"); + if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + /* print header */ + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) + fprintf(f, "\"%02X\"\t", y); + } + fprintf(f, "\n"); + /* print data */ + for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) + ; + else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) + fprintf(f, "\"\"\t"); + else + fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); + } + fprintf(f, "\n"); + } + fclose(f); + } + if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); + if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); + free(da2->bitblt.debug_reg); +#endif +#endif + free(da2->cram); + free(da2->vram); + free(da2->changedvram); + free(da2); +} + +void da2_speed_changed(void *p) +{ + da2_t* da2 = (da2_t*)p; + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + da2_recalctimings(da2); +} + +void da2_force_redraw(void *p) +{ + da2_t* da2 = (da2_t*)p; + + da2->fullchange = changeframecount; +} + +//void da2_add_status_info(char *s, int max_len, void *p) +//{ +// da2_t* da2 = (da2_t*)p; +// char temps[128]; +// if (!(da2->pos_regs[2] & 0x01)) strcpy(temps, "Render: DA2 disabled\n"); +// else if (da2->render == da2_render_blank) strcpy(temps, "Render: DA2 blank\n"); +// else if (da2->render == da2_render_text) strcpy(temps, "Render: DA2 text (mode 8 or E)\n"); +// else if (da2->render == da2_render_textm3) strcpy(temps, "Render: DA2 EGA compatible text (mode 3)\n"); +// else if (da2->render == da2_render_color_4bpp) strcpy(temps, "Render: DA2 4 bpp graphics (mode A or D)\n"); +// else if (da2->render == da2_render_color_8bpp) strcpy(temps, "Render: DA2 8 bpp graphics (mode F)\n"); +// else strcpy(temps, "Render: DA2 unknown render\n"); +// strncat(s, temps, max_len); +// +// sprintf(temps, "Resolution : %i x %i\n", da2->video_res_x, da2->video_res_y); +// strncat(s, temps, max_len); +// +// sprintf(temps, "Refresh rate : %i Hz\n", da2->frames); +// da2->frames = 0; +// strncat(s, temps, max_len); +// +// sprintf(temps, "Render lines : %i\n\n", da2->writelines); +// da2->writelines = 0; +// strncat(s, temps, max_len); +//} + +const device_t ps55da2_device = { + .name = "IBM Display Adapter II (MCA)", + .internal_name = "ps55da2", + .flags = DEVICE_MCA, + .local = 0, + .init = da2_init, + .close = da2_close, + .reset = da2_reset, + { .available = da2_available }, + .speed_changed = da2_speed_changed, + .force_redraw = da2_force_redraw, + .config = NULL +}; + +void +da2_device_add(void) +{ + if (!da2_standalone_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&ps55da2_device); + else + return; +} diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 93c1eb669..6d952ddb7 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -431,10 +431,24 @@ svga_in(uint16_t addr, void *priv) ret = svga->attrregs[svga->attraddr]; break; case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - ret = 0; + if (svga->cable_connected) + { + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) + ret = 0; + else + ret = 0x10; + } else - ret = 0x10; + { + // The Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). + // When the monitor cable is connected to the Display Adapter, this port returns the value as no cable connection. + // The Power-on Self Test of PS/55 tries detecting the monitor on the planar VGA. + // If it fails, then the POST reads the NVRAM set by the reference diskette, and sets the BIOS Data Area (Mem 487h, 489h). + if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) + ret = 0; + else + ret = 0x10; + } break; case 0x3c3: ret = vga_on; @@ -1359,6 +1373,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 32; svga->translate_address = NULL; + + svga->cable_connected = 1; svga->ksc5601_english_font_type = 0; vga_on = 1; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index b6e1bd2f9..cda3f95e0 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -367,6 +367,8 @@ video_post_reset(void) if (xga_standalone_enabled) xga_device_add(); + if (da2_standalone_enabled) + da2_device_add(); /* Reset the graphics card (or do nothing if it was already done by the machine's init function). */ video_reset(gfxcard[0]); diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 8b2e761a3..699cfe85e 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -103,6 +103,39 @@ vga_in(uint16_t addr, void *priv) return temp; } +void vga_disable(void* p) +{ + vga_t* vga = (vga_t*)p; + svga_t* svga = &vga->svga; + + pclog("vga_disable %04X:%04X\n", cs >> 4, cpu_state.pc); + io_removehandler(0x03a0, 0x0040, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + mem_mapping_disable(&svga->mapping); + svga->vga_enabled = 0; +} + +void vga_enable(void* p) +{ + vga_t* vga = (vga_t*)p; + svga_t* svga = &vga->svga; + + pclog("vga_enable %04X:%04X\n", cs >> 4, cpu_state.pc); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + if (!(svga->miscout & 1)) + io_sethandler(0x03a0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + + mem_mapping_enable(&svga->mapping); + svga->vga_enabled = 1; +} + +int vga_isenabled(void* p) +{ + vga_t* vga = (vga_t*)p; + svga_t* svga = &vga->svga; + + return svga->vga_enabled; +} + static void * vga_init(const device_t *info) { @@ -149,6 +182,7 @@ ps1vga_init(const device_t *info) vga->svga.bpp = 8; vga->svga.miscout = 1; + vga->svga.vga_enabled = 1; return vga; } From 7c5e82b2abf58ea514998113976beb8404604f53 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:44:11 +0900 Subject: [PATCH 0017/1190] Added PS/55 fdc emulation, fixed a bug in MT read --- src/floppy/fdc.c | 110 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 8 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 3fd492bd2..a878853e4 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -734,6 +734,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } + /* FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. + If it fails, then floppy drives will be treated as DD drives. */ + if (fdc->flags & FDC_FLAG_PS55) { + if (val & 0x04) + { + fdc->tfifo = 8; + fdc->fifointest = 1; + } + else { + fdc->tfifo = 1; + fdc->fifointest = 0; + } + } return; case 4: if (!(fdc->flags & FDC_FLAG_NO_DSR_RESET)) { @@ -761,6 +775,14 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->dsr = val; return; case 5: /*Command register*/ + if (fdc->fifointest) + { + pclog("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); + fifo_write(val, fdc->fifo_p); + if (fifo_get_full(fdc->fifo_p)) + fdc->stat &= ~0x80; + break; + } if ((fdc->stat & 0xf0) == 0xb0) { if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { fdc->dat = val; @@ -1249,7 +1271,27 @@ fdc_read(uint16_t addr, void *priv) ret |= 0x40; if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; - } else + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* Status Register A (PS/2, PS/55) */ + /* | INT PEND | nDRV2 | STEP | nTRK0 | HDSEL | nIDX | nWP | DIR | */ + ret = 0x04; + if (!fdc->seek_dir) /* DIRECTION */ + ret |= 0x01; + if (!writeprot[drive]) /* nWRITEPROT */ + ret |= 0x02; + if (fdd_get_head(drive)) /* HDSEL */ + ret |= 0x08; + if (!fdd_track0(drive)) /* nTRK0 */ + ret |= 0x10; + if (fdc->step) /* STEP */ + ret |= 0x20; + if (!fdd_get_type(1)) /* -Drive 2 Installed */ + ret |= 0x40; + if (fdc->fintr || fdc->reset_stat) /* INTR */ + ret |= 0x80; + } + else ret = 0xff; break; case 1: /* STB */ @@ -1277,7 +1319,19 @@ fdc_read(uint16_t addr, void *priv) default: break; } - } else { + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* Status Register B (PS/2, PS/55) */ + /* | 1 | 1 | DS0 | WD TOGGLE | RD TOGGLE | WE | MOT EN1 | MOT EN0 | */ + ret = 0xc0; + if (motoron[0]) /* Bit 0: MOT EN0 */ + ret |= 1; + if (motoron[1]) /* Bit 1: MOT EN1 */ + ret |= 2; + if(real_drive(fdc, fdc->dor & 3) == 0) /* Bit 5: Drive Select 0 */ + ret |= 0x20; + } + else { if (is486 || !fdc->enable_3f1) ret = 0xff; else { @@ -1326,7 +1380,12 @@ fdc_read(uint16_t addr, void *priv) ret = 0x10; else ret = 0x00; - } else if (!fdc->enh_mode) + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* error when ret = 1, 2*/ + ret = (fdc->fifointest) ? 4 : 0; + } + else if (!fdc->enh_mode) ret = 0x20; else ret = fdc->rwc[drive] << 4; @@ -1335,6 +1394,11 @@ fdc_read(uint16_t addr, void *priv) ret = fdc->stat; break; case 5: /*Data*/ + if (fdc->fifointest) + { + ret = fifo_read(fdc->fifo_p); + break; + } if ((fdc->stat & 0xf0) == 0xf0) { fdc->stat &= ~0x80; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { @@ -1377,7 +1441,18 @@ fdc_read(uint16_t addr, void *priv) ret |= (fdc->rate & 0x03); } else ret = 0x00; - } else { + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* Digital Input Register (PS/2, PS/55) */ + /* | DSKCHG | 1 | 1 | 1 | 1 | DRATE1 | DRATE0 | nHDEN | */ + ret = 0x78; + ret |= (fdc->rate & 0x03) << 1; + if (fdc->rate == 1 || fdc->rate == 2) + ret |= 0x01; + if (fdc->dor & (0x10 << drive)) + ret |= (fdd_changed[drive] || drive_empty[drive]) ? 0x80 : 0x00; + } + else { if (fdc->dor & (0x10 << drive)) { if ((drive == 1) && (fdc->flags & FDC_FLAG_TOSHIBA)) ret = 0x00; @@ -1409,7 +1484,7 @@ static void fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -1635,6 +1710,8 @@ fdc_callback(void *priv) return; } if (fdd_get_head(real_drive(fdc, fdc->drive)) == 0) { + fdc->sector = 1; + fdc->head |= 1; fdd_set_head(real_drive(fdc, fdc->drive), 1); if (!fdd_is_double_sided(real_drive(fdc, fdc->drive))) { fdc_noidam(fdc); @@ -1646,6 +1723,7 @@ fdc_callback(void *priv) else if (fdc->params[5] == 0) fdc->sector++; ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + //fdc_log("cb_rwsect: %d %d %d %d %d %xh\n", real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); switch (fdc->interrupt) { case 5: case 9: @@ -1708,7 +1786,7 @@ fdc_callback(void *priv) } else { fdc->interrupt = -2; fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; @@ -1800,7 +1878,7 @@ fdc_error(fdc_t *fdc, int st5, int st6) timer_disable(&fdc->timer); fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -1964,6 +2042,7 @@ fdc_noidam(fdc_t *fdc) void fdc_nosector(fdc_t *fdc) { + pclog("nosector error\n"); fdc_error(fdc, 4, 0); } @@ -2209,7 +2288,7 @@ fdc_reset(void *priv) fdc->enable_3f1 = 1; fdc_update_enh_mode(fdc, 0); - if (fdc->flags & FDC_FLAG_PS1) + if (fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55)) fdc_update_densel_polarity(fdc, 0); else fdc_update_densel_polarity(fdc, 1); @@ -2230,6 +2309,7 @@ fdc_reset(void *priv) fdc->fifo = 0; fdc->tfifo = 1; + fdc->fifointest = 0; if (fdc->flags & FDC_FLAG_PCJR) { fdc->dma = 0; @@ -2551,6 +2631,20 @@ const device_t fdc_at_ps1_2121_device = { .config = NULL }; +const device_t fdc_at_ps55_device = { + .name = "PC/AT Floppy Drive Controller (PS/55)", + .internal_name = "fdc_at_ps55", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_PS55, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + {.available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc_at_smc_device = { .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .internal_name = "fdc_at_smc", From 4b5943dd7d05cc060245af0889e7a3e8b7ffebb9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:46:15 +0900 Subject: [PATCH 0018/1190] Added a display configuration for IBM DA2 --- src/qt/qt_settingsdisplay.cpp | 6 ++++++ src/qt/qt_settingsdisplay.ui | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index db8c30e5d..42617c4be 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -25,6 +25,7 @@ extern "C" { #include <86box/machine.h> #include <86box/video.h> #include <86box/vid_xga_device.h> +#include <86box/vid_ps55da2.h> } #include "qt_deviceconfig.hpp" @@ -56,6 +57,7 @@ SettingsDisplay::save() voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; ibm8514_standalone_enabled = ui->checkBox8514->isChecked() ? 1 : 0; xga_standalone_enabled = ui->checkBoxXga->isChecked() ? 1 : 0; + da2_standalone_enabled = ui->checkBoxDa2->isChecked() ? 1 : 0; } void @@ -162,6 +164,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) bool machineSupports8514 = ((machineHasIsa16 || machineHasMca) && !videoCardHas8514); bool machineSupportsXga = (((machineHasIsa16 && device_available(&xga_isa_device)) || (machineHasMca && device_available(&xga_device))) && !videoCardHasXga); + bool machineSupportsDa2 = machineHasMca && device_available(&ps55da2_device); ui->checkBox8514->setEnabled(machineSupports8514); ui->checkBox8514->setChecked(ibm8514_standalone_enabled && machineSupports8514); @@ -169,6 +172,9 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) ui->checkBoxXga->setEnabled(machineSupportsXga); ui->checkBoxXga->setChecked(xga_standalone_enabled && machineSupportsXga); + ui->checkBoxDa2->setEnabled(machineSupportsDa2); + ui->checkBoxDa2->setChecked(da2_standalone_enabled && machineSupportsDa2); + ui->pushButtonConfigureXga->setEnabled(ui->checkBoxXga->isEnabled() && ui->checkBoxXga->isChecked()); int c = 2; diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index a9b7e6e2c..e3e081848 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -113,6 +113,13 @@ + + + + IBM PS/55 Display Adapter Graphics + + + @@ -133,7 +140,7 @@ - + Qt::Vertical From 44ce0dc2827216f2f240970ed642ba09722b330c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:52:16 +0900 Subject: [PATCH 0019/1190] Added DA2 config, Changed ca keys for PS/55 --- src/86box.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/86box.c b/src/86box.c index 5e1f58413..82eedbd78 100644 --- a/src/86box.c +++ b/src/86box.c @@ -186,6 +186,7 @@ int voodoo_enabled = 0; /* (C) video o int lba_enhancer_enabled = 0; /* (C) enable Vision Systems LBA Enhancer */ int ibm8514_standalone_enabled = 0; /* (C) video option */ int xga_standalone_enabled = 0; /* (C) video option */ +int da2_standalone_enabled = 0; /* (C) video option */ uint32_t mem_size = 0; /* (C) memory size (Installed on system board)*/ uint32_t isa_mem_size = 0; /* (C) memory size (ISA Memory Cards) */ @@ -1061,12 +1062,13 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { + /* Use R-Alt because 5576-002 keyboard assigns L-Alt as */ keyboard_input(1, 0x1D); /* Ctrl key pressed */ - keyboard_input(1, 0x38); /* Alt key pressed */ + keyboard_input(1, 0x138); /* R-Alt key pressed */ keyboard_input(1, sc); usleep(50000); keyboard_input(0, sc); - keyboard_input(0, 0x38); /* Alt key released */ + keyboard_input(0, 0x138); /* R-Alt key released */ keyboard_input(0, 0x1D); /* Ctrl key released */ } From a241a3ae8fdcbe716fd27d3a83b29fbdb8b1ee68 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:54:08 +0900 Subject: [PATCH 0020/1190] added/updated headers --- src/include/86box/86box.h | 1 + src/include/86box/fdc.h | 4 +++- src/include/86box/hdc.h | 1 + src/include/86box/machine.h | 1 + src/include/86box/mca.h | 1 + src/include/86box/vid_ps55da2.h | 24 ++++++++++++++++++++++++ src/include/86box/vid_svga.h | 5 +++++ src/include/86box/vid_vga.h | 4 ++++ src/include/86box/video.h | 3 +++ 9 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/vid_ps55da2.h diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index c91b8d406..d21bba49c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -137,6 +137,7 @@ extern int sound_is_float; /* (C) sound uses FP values */ extern int voodoo_enabled; /* (C) video option */ extern int ibm8514_standalone_enabled; /* (C) video option */ extern int xga_standalone_enabled; /* (C) video option */ +extern int da2_standalone_enabled; /* (C) video option */ extern uint32_t mem_size; /* (C) memory size (Installed on system board) */ extern uint32_t isa_mem_size; /* (C) memory size (ISA Memory Cards) */ extern int cpu; /* (C) cpu type */ diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index ef78239cd..0d71dd374 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -52,6 +52,7 @@ #define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ #define FDC_FLAG_NO_DSR_RESET 0x1000 /* Has no DSR reset */ #define FDC_FLAG_NEC 0x2000 /* Is NEC upd765-compatible */ +#define FDC_FLAG_PS55 0x4000 /* PS/55 */ #define FDC_FLAG_SEC 0x10000 /* Is Secondary */ #define FDC_FLAG_TER 0x20000 /* Is Tertiary */ #define FDC_FLAG_QUA 0x40000 /* Is Quaternary */ @@ -100,7 +101,6 @@ typedef struct fdc_t { uint8_t densel_force; uint8_t fifo; uint8_t tfifo; - uint8_t fifobufpos; uint8_t drv2en; uint8_t gap; @@ -145,6 +145,7 @@ typedef struct fdc_t { int drvrate[4]; void *fifo_p; + int fifointest; sector_id_t read_track_sector; sector_id_t format_sector_id; @@ -252,6 +253,7 @@ extern const device_t fdc_at_qua_device; extern const device_t fdc_at_actlow_device; extern const device_t fdc_at_ps1_device; extern const device_t fdc_at_ps1_2121_device; +extern const device_t fdc_at_ps55_device; extern const device_t fdc_at_smc_device; extern const device_t fdc_at_ali_device; extern const device_t fdc_at_winbond_device; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 48235bb1e..734cdf37a 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -53,6 +53,7 @@ extern const device_t st506_xt_toshiba_t1200_device; /* st506_xt_toshiba_t1 extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ extern const device_t esdi_ps2_device; /* esdi_mca */ +extern const device_t esdi_integrated_device; /* esdi_mca */ extern const device_t ide_isa_device; /* isa_ide */ extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 8afd5e28f..fe867a4dc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -887,6 +887,7 @@ extern int machine_ps2_model_70_type3_init(const machine_t *); extern int machine_ps2_model_80_init(const machine_t *); extern int machine_ps2_model_80_axx_init(const machine_t *); extern int machine_ps2_model_70_type4_init(const machine_t *); +extern int machine_ps55_model_50t_init(const machine_t*); /* m_tandy.c */ extern int tandy1k_eeprom_read(void); diff --git a/src/include/86box/mca.h b/src/include/86box/mca.h index e048a6131..2d31fe33d 100644 --- a/src/include/86box/mca.h +++ b/src/include/86box/mca.h @@ -3,6 +3,7 @@ extern void mca_init(int nr_cards); extern void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv); +extern void mca_add_to_slot(uint8_t(*read)(int addr, void* priv), void (*write)(int addr, uint8_t val, void* priv), uint8_t(*feedb)(void* priv), void (*reset)(void* priv), void* priv, int c); extern void mca_set_index(int index); extern uint8_t mca_read(uint16_t port); extern uint8_t mca_read_index(uint16_t port, int index); diff --git a/src/include/86box/vid_ps55da2.h b/src/include/86box/vid_ps55da2.h new file mode 100644 index 000000000..70007be19 --- /dev/null +++ b/src/include/86box/vid_ps55da2.h @@ -0,0 +1,24 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * IBM PS/55 Display Adapter II emulation. + * + * + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#ifndef VIDEO_DA2_DEVICE_H +#define VIDEO_DA2_DEVICE_H + +#ifdef EMU_DEVICE_H +extern const device_t ps55da2_device; +#endif +#endif /*VIDEO_DA2_DEVICE_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 3d68c1a34..72b755cf1 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -216,6 +216,11 @@ typedef struct svga_t { int override; void *priv; + int vga_enabled; + /* The PS/55 POST BIOS has a special monitor detection for its internal VGA + when the monitor is connected to the Display Adapter. */ + int cable_connected; + uint8_t crtc[256]; uint8_t gdcreg[256]; uint8_t attrregs[32]; diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index bc552b285..62cee8e9f 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -33,4 +33,8 @@ static video_timings_t timing_vga = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; void vga_out(uint16_t addr, uint8_t val, void *priv); uint8_t vga_in(uint16_t addr, void *priv); +void vga_disable(void* p); +void vga_enable(void* p); +int vga_isenabled(void* p); + #endif /*VIDEO_VGA_H*/ diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 9cbd0399f..3db41d2ab 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -313,6 +313,9 @@ extern const device_t mach32_mca_device; extern const device_t mach32_pci_device; extern const device_t mach32_onboard_pci_device; +/* IBM Display Adapter (PS/55) */ +extern void da2_device_add(void); + /* ATi Mach64 */ extern const device_t mach64gx_isa_device; extern const device_t mach64gx_vlb_device; From 84f49c355344eece68892faffe8c57e5816864a0 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 23:30:16 +0900 Subject: [PATCH 0021/1190] Fixed text cursor size changing --- src/video/vid_ps55da2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 13f823c83..0378cbc3c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1568,7 +1568,6 @@ static void da2_render_text(da2_t* da2) } //Draw character for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - //draw -= 13; // SBCS or DBCS left half if (chr_wide == 0) { if (attr & 0x01) chr_wide = 1; @@ -1742,7 +1741,7 @@ static void da2_render_textm3(da2_t* da2) // fg = 0; //} for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + p[n] = da2->pallook[da2->egapal[fg]]; } da2->ma += 2; p += 13; @@ -2684,7 +2683,7 @@ void da2_poll(void* priv) da2->hdisp_on = 0; da2->linepos = 0; - if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_END] & 31)) + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) da2->con = 0; if (da2->dispon) { @@ -2854,7 +2853,7 @@ void da2_poll(void* priv) // da2_log("ADDR %08X\n",hwcursor_addr); } - if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_START] & 31)) + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } // printf("2 %i\n",da2_vsyncstart); From 935c8b6ed893e08f52a69e55a99f0fed719aede7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:04:42 +0900 Subject: [PATCH 0022/1190] cleanup code --- src/video/vid_ps55da2.c | 192 +++------------------------------------- 1 file changed, 12 insertions(+), 180 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 0378cbc3c..c5e64694d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -259,14 +259,12 @@ typedef struct da2_t int crtcaddr; uint8_t miscout; - //int vidclock; uint32_t decode_mask; uint32_t vram_max; uint32_t vram_mask; uint32_t gdcla[8]; - //int gdcramlatched; uint32_t gdcinput[8]; uint32_t gdcsrc[8]; uint32_t debug_vramold[8]; @@ -275,7 +273,6 @@ typedef struct da2_t int dac_read, dac_write, dac_pos; int dac_r, dac_g; - //IO 3DAh Input Status Register 2 uint8_t cgastat; uint8_t plane_mask; @@ -336,24 +333,11 @@ typedef struct da2_t int fullchange; - //int video_res_x, video_res_y, video_bpp; - //int video_res_override; /*If clear then SVGA code will set above variables, if - // set then card code will*/ - //int frames, writelines; - void (*render)(struct da2_t* da2); - //void (*recalctimings_ex)(struct da2_t* da2); - - //void (*video_out)(uint16_t addr, uint8_t val, void* p); - //uint8_t(*video_in) (uint16_t addr, void* p); /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ - int override; - //void* p; - - /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ - //int hsync_divisor; + int override; /* end VGA compatible regs*/ struct @@ -852,7 +836,6 @@ void da2_out(uint16_t addr, uint16_t val, void *p) 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_log("DS %X\n",DS); da2->dac_status = 0; da2->fullchange = changeframecount; switch (da2->dac_pos) @@ -887,10 +870,9 @@ void da2_out(uint16_t addr, uint16_t val, void *p) //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); oldval = da2->ioctl[da2->ioctladdr]; - //if (da2->ioctladdr == 0x3) return;//monitor color da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { - if (da2->ioctladdr == LS_RESET && val & 0x01) /* Mode register */ + if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ da2_reset_ioctl(da2); else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ { @@ -1077,10 +1059,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) uint16_t da2_in(uint16_t addr, void *p) { da2_t * da2 = (da2_t *)p; - //svga_t *svga = &da2->svga; uint16_t temp; -// if (addr != 0x3da) da2_log("IN gd5429 %04X\n", addr); switch (addr) { case 0x3c3: @@ -1119,19 +1099,6 @@ uint16_t da2_in(uint16_t addr, void *p) if (da2->ioctladdr > 0xf) return 0xff; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ - //da2_log("Read 3E1 DAC status: %d, %d, %d\n", da2->vgapal[0].r, da2->vgapal[0].g, da2->vgapal[0].b); - //da2_log("attr palette: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->attrregs[i]); - //da2_log("\n"); - //da2_log("vram A0000h: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[i]); - //da2_log("\n"); - //da2_log("vram B8000h: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[0x18000 + i]); - //da2_log("\n"); - //da2_log("vram E0000h: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->cram[i]); - //da2_log("\n"); if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrregs[LV_COMPATIBILITY] & 0x08) temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ else @@ -1872,7 +1839,6 @@ void da2_updatevidselector(da2_t* da2) { } } - void da2_recalctimings(da2_t* da2) { double crtcconst; @@ -1921,24 +1887,11 @@ void da2_recalctimings(da2_t* da2) //if (da2->attr_palette_enable && (da2->attrregs[0x1f] & 0x08)) if (da2->attrregs[LV_COMPATIBILITY] & 0x08) { - //if (da2->ioctl[0] & 0x01)//256 color mode - //{ - // da2_log("Set videomode to PS/55 8 bpp graphics.\n"); - // da2->vram_display_mask = 0x1ffff; - // da2->render = da2_render_color_8bpp; - //} - //else if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode da2->hdisp *= 16; da2->char_width = 13; da2->hdisp_old = da2->hdisp; - //if (da2->plane_mask == 0x01) {//PS/55 monochrome - // da2_log("Set videomode to PS/55 Monochrome graphics.\n"); - // //da2->render = da2_render_mono; - // da2->render = da2_render_color_4bpp; - // da2->vram_display_mask = 0x1ffff; - //} - if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) {//PS/55 256 color + 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_GRAM; @@ -1950,7 +1903,7 @@ void da2_recalctimings(da2_t* da2) } } else {//text mode - if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) {//PS/55 Mode 03 + if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; @@ -1976,7 +1929,6 @@ void da2_recalctimings(da2_t* da2) // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - /*da2->char_width = 13;*///PS55TEXT = 13, GFX = 16 //if (da2->recalctimings_ex) // da2->recalctimings_ex(da2); @@ -2174,12 +2126,8 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode { cycles -= video_timing_read_b; - //readmode 1 - //da2_log("da2_rp: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->readplane, addr); for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte - //da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read in word - //da2->gdcramlatched = 1; //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 uint8_t ret = 0; @@ -2212,7 +2160,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch - //da2->gdcramlatched = 1; + ////debug //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ @@ -2320,16 +2268,9 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) da2->changedvram[addr >> 12] = changeframecount; addr <<= 3; - //if (GCLATCHCOND) { - //if (da2->writemode == 2) { - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - //} - //else { - // for (int i = 0; i < 8; i++) - // da2->gdcsrc[i] = da2->vram[addr | i];//read in byte from vram - //} - //da2->gdcramlatched = 0; + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2346,7 +2287,6 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) switch (da2->writemode) { case 2: - //case 1: for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; break; @@ -2372,7 +2312,6 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) //// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; - //case 2: case 1: if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { @@ -2445,17 +2384,8 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; - //if (((da2->gdcreg[LG_COMMAND] & 0x03) || da2->writemode == 2) && da2->writemode != 1) { - //if (GCLATCHCOND) { - //if (da2->writemode == 2) { - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - //} - //else { - // for (int i = 0; i < 8; i++) - // da2->gdcsrc[i] = (uint16_t)(da2->vram[addr | i]) | ((uint16_t)(da2->vram[(addr + 8) | i]) << 8);//read in word - //} - //da2->gdcramlatched = 0; + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { @@ -2468,10 +2398,9 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) } //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); - switch (da2->writemode)// writemode 0 or 2 rop(0b) 0 or 3 + switch (da2->writemode) { case 2: - //case 1: for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { @@ -2479,8 +2408,6 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; } break; - //case 2:win - case 0: if (da2->gdcreg[LG_DATA_ROTATION] & 15) val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work @@ -2498,14 +2425,10 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) for (int i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; else da2->gdcinput[i] = val; - - //for (int i = 0; i < 8; i++)//draft20240722 0211 - // da2->gdcla[i] = 0;//read in word da2_gdcropW(addr, bitmask, da2); // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; - //case 2: case 1: if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { @@ -2649,7 +2572,6 @@ void da2_poll(void* priv) video_wait_for_buffer(); } - //RENDER if (!da2->override) da2->render(da2); @@ -2705,20 +2627,12 @@ void da2_poll(void* priv) da2->ma = da2->maback; } } - //da2->hsync_divisor = !da2->hsync_divisor; - - //disable for 256 color mode - //if (da2->hsync_divisor && (da2->crtc[0x17] & 4)) - // return; da2->vc++; da2->vc &= 2047; if (da2->vc == da2->dispend) { - //if (da2->vblank_start) - // da2->vblank_start(da2); - // da2_log("VC dispend\n"); da2->dispon = 0; //if (da2->crtc[10] & 0x20) da2->cursoron = 0; //else da2->cursoron = da2->blink & 16; @@ -2745,7 +2659,6 @@ void da2_poll(void* priv) if (da2->fullchange) { da2->fullchange--; - //da2->fps++; } } if (da2->vc == da2->vsyncstart) @@ -2764,8 +2677,6 @@ void da2_poll(void* priv) da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); - //readflash = 0; - da2->firstline = 2000; da2->lastline = 0; @@ -2788,48 +2699,7 @@ void da2_poll(void* priv) da2->maback <<= 1; da2->ca <<= 1; - //if (!da2->video_res_override) - //{ - //da2->video_res_x = wx; - //da2->video_res_y = wy + 1; - - if (da2->ioctl[LS_MODE] & 1) /*Text mode*/ - { - //da2->video_res_x /= da2->char_width; - //da2->video_res_y /= (da2->crtc[9] & 31) + 1; - //da2->video_bpp = 0; - } - else - { - //if (da2->crtc[9] & 0x80) - // da2->video_res_y /= 2; - //if (!(da2->crtc[0x17] & 2)) - // da2->video_res_y *= 4; - //else if (!(da2->crtc[0x17] & 1)) - // da2->video_res_y *= 2; - //da2->video_res_y /= (da2->crtc[9] & 31) + 1; - //if (da2->render == da2_render_8bpp_lowres || - // da2->render == da2_render_15bpp_lowres || - // da2->render == da2_render_16bpp_lowres || - // da2->render == da2_render_24bpp_lowres || - // da2->render == da2_render_32bpp_lowres) - //da2->video_res_x /= 2; - - //switch (da2->gdcreg[5] & 0x60) - //{ - //case 0x00: da2->video_bpp = 4; break; - //case 0x20: da2->video_bpp = 2; break; - //case 0x40: case 0x60: da2->video_bpp = da2->bpp; break; - //} - //da2->video_bpp = da2->bpp; - } - //} - //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma + (da2->rowoffset << 1); - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); - - //if (da2->vsync_callback) - // da2->vsync_callback(da2); } if (da2->vc == da2->vtotal) { @@ -2842,16 +2712,6 @@ void da2_poll(void* priv) da2->dispon = 1; da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; da2->scrollcache = da2->attrregs[LV_PANNING] & 7; - //da2->linecountff = 0; - - //da2->hwcursor_on = 0; - //da2->hwcursor_latch = da2->hwcursor; - - //da2->overlay_on = 0; - //da2->overlay_latch = da2->overlay; - // da2_log("Latch HWcursor addr %08X\n", da2_hwcursor_latch.addr); - - // da2_log("ADDR %08X\n",hwcursor_addr); } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; @@ -2933,7 +2793,6 @@ da2_reset(void* priv) da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ da2->ma_latch = 0; - //da2->gdcramlatched = 0; da2->interlace = 0; da2->attrregs[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ @@ -2964,9 +2823,7 @@ static void *da2_init() int memsize = 1024 * 1024; da2->vram = malloc(memsize); da2->vram_mask = memsize - 1; - //da2->gram_display_mask = (memsize - 1) >> 3; da2->cram = malloc(0x1000); - //da2->cram_display_mask = 0x1000 - 1; da2->vram_display_mask = DA2_MASK_CRAM; da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h da2_loadfont(DA2_FONTROM_PATH, da2); @@ -3052,6 +2909,7 @@ void da2_close(void *p) fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); fclose(f); } +#endif #ifdef ENABLE_DA2_DEBUGBLT f = fopen("da2_bltdump.csv", "w"); if (f != NULL && da2->bitblt.debug_reg_ip > 0) { @@ -3078,7 +2936,6 @@ void da2_close(void *p) if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); free(da2->bitblt.debug_reg); -#endif #endif free(da2->cram); free(da2->vram); @@ -3100,31 +2957,6 @@ void da2_force_redraw(void *p) da2->fullchange = changeframecount; } -//void da2_add_status_info(char *s, int max_len, void *p) -//{ -// da2_t* da2 = (da2_t*)p; -// char temps[128]; -// if (!(da2->pos_regs[2] & 0x01)) strcpy(temps, "Render: DA2 disabled\n"); -// else if (da2->render == da2_render_blank) strcpy(temps, "Render: DA2 blank\n"); -// else if (da2->render == da2_render_text) strcpy(temps, "Render: DA2 text (mode 8 or E)\n"); -// else if (da2->render == da2_render_textm3) strcpy(temps, "Render: DA2 EGA compatible text (mode 3)\n"); -// else if (da2->render == da2_render_color_4bpp) strcpy(temps, "Render: DA2 4 bpp graphics (mode A or D)\n"); -// else if (da2->render == da2_render_color_8bpp) strcpy(temps, "Render: DA2 8 bpp graphics (mode F)\n"); -// else strcpy(temps, "Render: DA2 unknown render\n"); -// strncat(s, temps, max_len); -// -// sprintf(temps, "Resolution : %i x %i\n", da2->video_res_x, da2->video_res_y); -// strncat(s, temps, max_len); -// -// sprintf(temps, "Refresh rate : %i Hz\n", da2->frames); -// da2->frames = 0; -// strncat(s, temps, max_len); -// -// sprintf(temps, "Render lines : %i\n\n", da2->writelines); -// da2->writelines = 0; -// strncat(s, temps, max_len); -//} - const device_t ps55da2_device = { .name = "IBM Display Adapter II (MCA)", .internal_name = "ps55da2", From 6aec2f04dd548e97a55a71968cca8f912744295c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:07:24 +0900 Subject: [PATCH 0023/1190] Fixed ESDI hung-up issue when ctrl+alt+del reset --- src/disk/hdc_esdi_mca.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 047089a1e..bdb037fee 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1259,9 +1259,12 @@ esdi_mca_feedb(void *priv) static void esdi_reset(void* priv) { esdi_t* dev = (esdi_t*)priv; - dev->in_reset = 1; - esdi_mca_set_callback(dev, ESDI_TIME * 50); - dev->status = STATUS_BUSY; + pclog("esdi reset %d %x\n", dev->in_reset, dev->status); + if (!dev->in_reset) { + dev->in_reset = 1; + esdi_mca_set_callback(dev, ESDI_TIME * 50); + dev->status = STATUS_BUSY; + } } static void * @@ -1272,6 +1275,7 @@ esdi_init(UNUSED(const device_t *info)) uint8_t c; uint8_t i; + pclog("esdi init\n"); dev = malloc(sizeof(esdi_t)); if (dev == NULL) return (NULL); @@ -1334,9 +1338,9 @@ esdi_init(UNUSED(const device_t *info)) /* The slot number of this controller is fixed by the planar. IBM PS/55 5551-T assigns it #5. */ int slotno = device_get_config_int("in_esdi_slot"); if (slotno) - mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev, slotno - 1); + mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev, slotno - 1); else - mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev); + mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev); } else mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); @@ -1348,6 +1352,7 @@ esdi_init(UNUSED(const device_t *info)) /* Set the reply timer. */ timer_add(&dev->timer, esdi_callback, dev, 0); + pclog("esdi init finish\n"); return dev; } From 3c6695cdeafb5b6fbf5a1e98c2747f4e9054d861 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:08:51 +0900 Subject: [PATCH 0024/1190] Removed debug logging --- src/disk/hdc_esdi_mca.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index bdb037fee..adc5cd6a0 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1259,7 +1259,6 @@ esdi_mca_feedb(void *priv) static void esdi_reset(void* priv) { esdi_t* dev = (esdi_t*)priv; - pclog("esdi reset %d %x\n", dev->in_reset, dev->status); if (!dev->in_reset) { dev->in_reset = 1; esdi_mca_set_callback(dev, ESDI_TIME * 50); @@ -1275,7 +1274,6 @@ esdi_init(UNUSED(const device_t *info)) uint8_t c; uint8_t i; - pclog("esdi init\n"); dev = malloc(sizeof(esdi_t)); if (dev == NULL) return (NULL); @@ -1352,7 +1350,6 @@ esdi_init(UNUSED(const device_t *info)) /* Set the reply timer. */ timer_add(&dev->timer, esdi_callback, dev, 0); - pclog("esdi init finish\n"); return dev; } From c3b2ddfcb18d0414b06b03ee161e3ec6a1eee4b7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:56:25 +0900 Subject: [PATCH 0025/1190] added comment for 5576 keyb --- src/device/keyboard_at.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 2900ec17a..161a13e0c 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1631,21 +1631,23 @@ static const scancode scancode_set3[512] = { }; /* IBM Japan 5576-001, 002 and 003 keyboards have three extra scancode sets; 81h, 82h, 8ah. - Scancode set 81h and 82h are not implemented yet. To implement them, we need take the following into consideration. * Add a UI to switch the type of keyboards and keyboard IDs. * Add modified scancode set 1 and 2 (in these modes, language input keys are used as an alternative key). - * Japanese keyboards traditionally use a typewriter layout. Its key mapping doesn't match with foreign keyboards. + * Japanese keyboards traditionally use a bit-paired layout. Its key mapping doesn't match with foreign keyboards. 5576 keyboards kept 101-key compatible scancode sets because PS/55 had to support western (PS/2) versions of operating systems. The default scancode set is 2. In Japanese DOS, the keyboard driver confirms its keyboard ID, and sends a command to switch the scancode set to 8Ah. + Japanese OS/2 and Windows use the scancode set 82h. - The OADG standard and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. + The OADG standard (1991-) and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. Three extra scancode sets are no longer available. Instead, language input keys are available in scancode set 1 and 2. - However, it has a different key mapping. + However, their physical key layout is a bit-paired layout. Users have to choose the correct keyboard layout on setup, and the driver needs to remap keys. + Currently, scancode set 81h and 82h are not implemented yet. Also, the key layout is designed to match with the Japanese keyboard. + [Japanese DOS and keyboard scancode set] | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | PC DOS 5 | |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| From 351d8c8441b5d32a88b601a2fd306595933dcbe4 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:37:19 +0900 Subject: [PATCH 0026/1190] added i/o port 3e9 write --- src/video/vid_ps55da2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index c5e64694d..143c478dc 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1022,6 +1022,10 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } da2->attrff ^= 1; break; + case 0x3E9: + /* VZ Editor's CURSOR.COM writes via this port */ + da2->attrregs[da2->attraddr & 0x3f] = val; + break; case LG_INDEX: da2->gdcaddr = val; break; From 2c8c519b82135c7e3332a4621b9718c06cbe8f83 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:38:32 +0900 Subject: [PATCH 0027/1190] Removed debug logging --- src/video/vid_vga.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 699cfe85e..8d4439f95 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -108,7 +108,6 @@ void vga_disable(void* p) vga_t* vga = (vga_t*)p; svga_t* svga = &vga->svga; - pclog("vga_disable %04X:%04X\n", cs >> 4, cpu_state.pc); io_removehandler(0x03a0, 0x0040, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); mem_mapping_disable(&svga->mapping); svga->vga_enabled = 0; @@ -119,7 +118,6 @@ void vga_enable(void* p) vga_t* vga = (vga_t*)p; svga_t* svga = &vga->svga; - pclog("vga_enable %04X:%04X\n", cs >> 4, cpu_state.pc); io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); if (!(svga->miscout & 1)) io_sethandler(0x03a0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); From ee280e10f1da6bfb5798593c1c8f90d00e23c154 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:39:40 +0900 Subject: [PATCH 0028/1190] removed debug logging --- src/floppy/fdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index a878853e4..af1aa37c6 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -777,7 +777,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 5: /*Command register*/ if (fdc->fifointest) { - pclog("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); + fdc_log("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); fifo_write(val, fdc->fifo_p); if (fifo_get_full(fdc->fifo_p)) fdc->stat &= ~0x80; From 05e663a5c30c715bb47d733c1e06bb57c031a016 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:34:26 +0900 Subject: [PATCH 0029/1190] merged ps55 fdc with ps2 fdc --- src/floppy/fdc.c | 27 +++++++++++++-------------- src/machine/m_ps2_mca.c | 20 ++------------------ 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index af1aa37c6..f317fd948 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -734,10 +734,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } - /* FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ - if (fdc->flags & FDC_FLAG_PS55) { + if (fdc->flags & FDC_FLAG_PS2) { if (val & 0x04) { fdc->tfifo = 8; @@ -1272,7 +1272,7 @@ fdc_read(uint16_t addr, void *priv) if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* Status Register A (PS/2, PS/55) */ /* | INT PEND | nDRV2 | STEP | nTRK0 | HDSEL | nIDX | nWP | DIR | */ ret = 0x04; @@ -1320,7 +1320,7 @@ fdc_read(uint16_t addr, void *priv) break; } } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* Status Register B (PS/2, PS/55) */ /* | 1 | 1 | DS0 | WD TOGGLE | RD TOGGLE | WE | MOT EN1 | MOT EN0 | */ ret = 0xc0; @@ -1381,7 +1381,7 @@ fdc_read(uint16_t addr, void *priv) else ret = 0x00; } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* error when ret = 1, 2*/ ret = (fdc->fifointest) ? 4 : 0; } @@ -1442,7 +1442,7 @@ fdc_read(uint16_t addr, void *priv) } else ret = 0x00; } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* Digital Input Register (PS/2, PS/55) */ /* | DSKCHG | 1 | 1 | 1 | 1 | DRATE1 | DRATE0 | nHDEN | */ ret = 0x78; @@ -1484,7 +1484,7 @@ static void fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc, 1); - if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -1786,7 +1786,7 @@ fdc_callback(void *priv) } else { fdc->interrupt = -2; fdc_int(fdc, 1); - if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; @@ -1878,7 +1878,7 @@ fdc_error(fdc_t *fdc, int st5, int st6) timer_disable(&fdc->timer); fdc_int(fdc, 1); - if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -2042,7 +2042,6 @@ fdc_noidam(fdc_t *fdc) void fdc_nosector(fdc_t *fdc) { - pclog("nosector error\n"); fdc_error(fdc, 4, 0); } @@ -2288,7 +2287,7 @@ fdc_reset(void *priv) fdc->enable_3f1 = 1; fdc_update_enh_mode(fdc, 0); - if (fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55)) + if (fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2)) fdc_update_densel_polarity(fdc, 0); else fdc_update_densel_polarity(fdc, 1); @@ -2631,11 +2630,11 @@ const device_t fdc_at_ps1_2121_device = { .config = NULL }; -const device_t fdc_at_ps55_device = { - .name = "PC/AT Floppy Drive Controller (PS/55)", +const device_t fdc_at_ps2_device = { + .name = "PC/AT Floppy Drive Controller (PS/2 internal)", .internal_name = "fdc_at_ps55", .flags = 0, - .local = FDC_FLAG_AT | FDC_FLAG_PS55, + .local = FDC_FLAG_AT | FDC_FLAG_PS2, .init = fdc_init, .close = fdc_close, .reset = fdc_reset, diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index fc2e3313b..72776b22d 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1557,7 +1557,7 @@ machine_ps2_common_init(const machine_t *model) machine_common_init(model); if (fdc_current[0] == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_ps2_device); dma16_init(); ps2_dma_init(); @@ -1801,23 +1801,7 @@ machine_ps55_model_50t_init(const machine_t* model) if (bios_only || !ret) return ret; - /* begin ps2 common init */ - machine_common_init(model); - - device_add(&fdc_at_ps55_device); - - dma16_init(); - ps2_dma_init(); - device_add(&ps_no_nmi_nvr_device); - pic2_init(); - - int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; - pit_ps2_init(pit_type); - - nmi_mask = 0x80; - - ps2.uart = device_add_inst(&ns16550_device, 1); - /* end ps2 common init */ + machine_ps2_common_init(model); /* * Planar ID From dd1d835e152fd90dcb0b4154eda1e6678c483952 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Mon, 2 Sep 2024 13:23:00 -0700 Subject: [PATCH 0030/1190] Use F8+F12 to release mouse on all platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that Ctrl+End was used on non-Win32 platforms because WxWidgets couldn’t use non-modifier keys as a keyboard sequence. Qt can, and F8+F12 interferes with the operation of software a lot less than Ctrl+End does (try doing some text editing!). 86Box hasn’t used WxWidgets for quite some time and this platform limitation hack has long outlived its necessity. --- src/device/keyboard.c | 12 +----------- src/include/86box/plat.h | 4 ++-- src/qt/qt_platform.cpp | 4 ++-- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index ea81e7525..de384c81e 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -31,23 +31,13 @@ int keyboard_scan; -#ifdef _WIN32 -/* Windows: F8+F12 */ +/* F8+F12 */ uint16_t key_prefix_1_1 = 0x042; /* F8 */ uint16_t key_prefix_1_2 = 0x000; /* Invalid */ uint16_t key_prefix_2_1 = 0x000; /* Invalid */ uint16_t key_prefix_2_2 = 0x000; /* Invalid */ uint16_t key_uncapture_1 = 0x058; /* F12 */ uint16_t key_uncapture_2 = 0x000; /* Invalid */ -#else -/* WxWidgets cannot do two regular keys.. CTRL+END */ -uint16_t key_prefix_1_1 = 0x01d; /* Left Ctrl */ -uint16_t key_prefix_1_2 = 0x11d; /* Right Ctrl */ -uint16_t key_prefix_2_1 = 0x000; /* Invalid */ -uint16_t key_prefix_2_2 = 0x000; /* Invalid */ -uint16_t key_uncapture_1 = 0x04f; /* Numpad End */ -uint16_t key_uncapture_2 = 0x14f; /* End */ -#endif void (*keyboard_send)(uint16_t val); diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 4a310ab44..225c45ae1 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -32,8 +32,8 @@ /* String ID numbers. */ enum { STRING_MOUSE_CAPTURE, /* "Click to capture mouse" */ - STRING_MOUSE_RELEASE, /* "Press F8+F12/Ctrl+End to release mouse" */ - STRING_MOUSE_RELEASE_MMB, /* "Press F8+F12/Ctrl+End or middle button to release mouse" */ + STRING_MOUSE_RELEASE, /* "Press F8+F12 to release mouse" */ + STRING_MOUSE_RELEASE_MMB, /* "Press F8+F12 or middle button to release mouse" */ STRING_INVALID_CONFIG, /* "Invalid configuration" */ STRING_NO_ST506_ESDI_CDROM, /* "MFM/RLL or ESDI CD-ROM drives never existed" */ STRING_NET_ERROR, /* "Failed to initialize network driver" */ diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index a200e38ec..f22b0f388 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -583,6 +583,8 @@ c16stombs(char dst[], const uint16_t src[], int len) } #endif +# define MOUSE_CAPTURE_KEYSEQ "F8+F12" + #ifdef _WIN32 # if defined(__amd64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) # define LIB_NAME_GS "gsdll64.dll" @@ -592,12 +594,10 @@ c16stombs(char dst[], const uint16_t src[], int len) # define LIB_NAME_GPCL "gpcl6dll32.dll" # endif # define LIB_NAME_PCAP "Npcap" -# define MOUSE_CAPTURE_KEYSEQ "F8+F12" #else # define LIB_NAME_GS "libgs" # define LIB_NAME_GPCL "libgpcl6" # define LIB_NAME_PCAP "libpcap" -# define MOUSE_CAPTURE_KEYSEQ "Ctrl+End" #endif QMap ProgSettings::translatedstrings; From 60a84cfb5bc948dbfa71a7f62354ea21b885ffb0 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:53:20 +0900 Subject: [PATCH 0031/1190] +character drawing in bitblt (experimental) * Changed comment format. * Updated Font ROM map written in comment --- src/video/vid_ps55da2.c | 514 ++++++++++++++++++++++++++-------------- 1 file changed, 337 insertions(+), 177 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 143c478dc..6a90a3dc3 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -39,16 +39,19 @@ #define DA2_FONTROM_PATH "roms/video/da2/PS55FNTJ.BIN" #define DA2_FONTROM_SIZE 1024*1024 +#define DA2_FONTROM_BASESBCS 0x98000 +#define DA2_GAIJIRAM_SBCS 0x34000 +#define DA2_GAIJIRAM_SBEX 0x3c000 #define DA2_MASK_MMIO 0x1ffff #define DA2_MASK_GRAM 0x1ffff #define DA2_MASK_CRAM 0xfff #define DA2_MASK_GAIJIRAM 0x3ffff #define DA2_PIXELCLOCK 58000000.0 -#define DA2_BLT_MEMSIZE 0x80 +#define DA2_BLT_MEMSIZE 0x100 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256*1024 -#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLTLOG_MAX 256*1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe #define DA2_BLT_CIDLE 0 @@ -56,8 +59,9 @@ #define DA2_BLT_CFILLTILE 2 #define DA2_BLT_CCOPYF 3 #define DA2_BLT_CCOPYR 4 -#define DA2_BLT_CDONE 5 -#define DA2_BLT_CLOAD 6 +#define DA2_BLT_CPUTCHAR 5 +#define DA2_BLT_CDONE 6 +#define DA2_BLT_CLOAD 7 /* POS ID = 0xeffe : Display Adapter II, III, V */ #define DA2_POSID_H 0xef #define DA2_POSID_L 0xfe @@ -124,9 +128,9 @@ #define LS_CONFIG1 0x0a #define LS_CONFIG2 0x0b /* added */ #define LF_INDEX 0x3e2 -#define LF_DATA 0x3e3 -#define LF_MMIO_SEL 0x08 /* added */ -#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ #define LF_MMIO_MODE 0x0B /* added */ #define LC_INDEX 0x3E4 #define LC_DATA 0x3E5 @@ -212,27 +216,31 @@ #define LG_MAP_MASKJ 0x0A #define LG_COMMAND 0x0B #define LG_SET_RESET_2 0x10 - -#ifdef ENABLE_DA2_LOG -int da2_do_log = ENABLE_DA2_LOG; - -static void -da2_log(const char* fmt, ...) -{ - va_list ap; - - if (da2_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define da2_log(fmt, ...) + +#ifndef RELEASE_BUILD +#define ENABLE_DA2_LOG 1 +#endif + +#ifdef ENABLE_DA2_LOG +int da2_do_log = ENABLE_DA2_LOG; + +static void +da2_log(const char* fmt, ...) +{ + va_list ap; + + if (da2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define da2_log(fmt, ...) +#endif +#ifndef RELEASE_BUILD +# define ENABLE_DA2_DEBUGBLT 1 #endif -#ifndef RELEASE_BUILD -# define ENABLE_DA2_DEBUGBLT 1 -#endif typedef struct da2_t { @@ -246,7 +254,7 @@ typedef struct da2_t uint8_t gdcreg[64]; uint8_t reg3ee[16]; int gdcaddr; - uint8_t attrregs[0x40]; + uint8_t attrc[0x40]; int attraddr, attrff; int attr_palette_enable; //uint8_t seqregs[64]; @@ -300,7 +308,7 @@ typedef struct da2_t pc_timer_t timer; uint64_t da2const; - uint8_t scrblank; + //uint8_t scrblank; int dispon; int hdisp_on; @@ -329,7 +337,7 @@ typedef struct da2_t uint32_t vram_display_mask; uint32_t banked_mask; - uint32_t write_bank, read_bank; + //uint32_t write_bank, read_bank; int fullchange; @@ -337,7 +345,7 @@ typedef struct da2_t /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ - int override; + int override; /* end VGA compatible regs*/ struct @@ -348,12 +356,12 @@ typedef struct da2_t uint8_t font[DA2_FONTROM_SIZE]; } mmio; - mem_mapping_t linear_mapping; + //mem_mapping_t linear_mapping; - uint32_t bank[2]; - uint32_t mask; + //uint32_t bank[2]; + //uint32_t mask; - int type; + //int type; struct { int bitshift_destr; @@ -386,7 +394,7 @@ typedef struct da2_t uint8_t pos_regs[8]; svga_t *mb_vga; - int vidsys_ena; + //int vidsys_ena; int old_pos2; } da2_t; @@ -406,7 +414,7 @@ typedef union { typedef struct { uint32_t p8[8]; } pixel32; - + /* safety read for internal functions */ uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) { @@ -505,6 +513,22 @@ void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } +void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + if (srcaddr >= DA2_FONTROM_SIZE) { + da2_log("DA2 Putchar Addr Error %x\n", srcaddr); + return; + } + for (int i = 0; i < 8; i++) + srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) + | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) + | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) + | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +#ifdef ENABLE_DA2_DEBUGBLT uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { @@ -515,15 +539,58 @@ uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { void print_pixelbyte(uint32_t addr, da2_t* da2) { for (int i = 0; i < 8; i++) { - da2_log("%X", pixel1tohex(addr, i, da2)); + pclog("%X", pixel1tohex(addr, i, da2)); } } - +void print_bytetobin(uint8_t b) { + for (int i = 0; i < 8; i++) + { + if(b & 0x80) + pclog("1"); + else + pclog("0"); + b <<= 1; + } +} +//Convert internal char code to Shift JIS code +inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } +inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } +uint16_t IBMJtoSJIS(uint16_t knj) +{ + if (knj < 0x100) return 0xffff; + knj -= 0x100; + if (knj <= 0x1f7d) + ;/* do nothing */ + else if (knj >= 0xb700 && knj <= 0xb75f) { + knj -= 0x90ec; + } + else if (knj >= 0xb3f0 && knj <= 0xb67f) { + knj -= 0x906c; + } + else if (knj >= 0x8000 && knj <= 0x8183) + { + knj -= 0x5524; + } + else + return 0xffff; + uint32_t knj1 = knj / 0xBC; + uint32_t knj2 = knj - (knj1 * 0xBC); + knj1 += 0x81; + if (knj1 > 0x9F) knj1 += 0x40; + knj2 += 0x40; + if (knj2 > 0x7E) knj2++; + //if (!isKanji1(knj1)) return 0xffff; + //if (!isKanji2(knj2)) return 0xffff; + knj = knj1 << 8; + knj |= knj2; + return knj; +} +#endif void da2_bitblt_load(da2_t* da2) { uint32_t value32; uint64_t value64; - //da2_log("BITBLT loading params\n"); + da2_log("BITBLT loading params\n"); //da2_log("BitBlt memory:\n"); //if (da2->bitblt.payload[0] != 0) // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) @@ -544,7 +611,7 @@ void da2_bitblt_load(da2_t* da2) value32 = da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - //da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 3; break; @@ -556,7 +623,7 @@ void da2_bitblt_load(da2_t* da2) value32 |= da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - //da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 5; break; @@ -573,8 +640,8 @@ void da2_bitblt_load(da2_t* da2) value64 <<= 8; value64 |= da2->bitblt.payload[i + 2]; da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - //da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - //da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); i += 7; break; case 0x00: @@ -635,14 +702,50 @@ void da2_bitblt_load(da2_t* da2) da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); da2->bitblt.exec = DA2_BLT_CDONE; } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {//Fill a rectangle (or draw a line) + else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + /* Todo: addressing */ + //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + //{ + // da2->bitblt.destaddr += 2; + // da2->bitblt.size_x -= 1; + // da2->bitblt.destpitch += 2; + // da2->bitblt.srcpitch += 2; + //} + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle ??(transfer tile data multiple times) os/2 only + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -653,7 +756,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle (transfer tile data multiple times) + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -664,7 +767,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {//Block transfer (range copy) + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; @@ -674,7 +777,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {//Block copy but reversed direction + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; @@ -686,11 +789,6 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.size_x, da2->bitblt.size_y); //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); } - //do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle - while (timer_is_enabled(&da2->bitblt.timer) && da2->bitblt.exec != DA2_BLT_CDONE) - { - da2_bitblt_exec(da2); - } } } void da2_bitblt_exec(void* p) @@ -704,8 +802,8 @@ void da2_bitblt_exec(void* p) timer_disable(&da2->bitblt.timer); break; case DA2_BLT_CLOAD: - da2_bitblt_load(da2); da2->bitblt.indata = 0; + da2_bitblt_load(da2); break; case DA2_BLT_CFILLRECT: //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); @@ -799,8 +897,47 @@ void da2_bitblt_exec(void* p) da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; break; + case DA2_BLT_CPUTCHAR: + //da2->bitblt.y += 2; + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; + pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + //da2->bitblt.srcaddr += 2; + if(da2->bitblt.reg[0x12] < 0x100) + da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + else + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + pclog("\n"); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + //if (1) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 3) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += 130; + //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + //da2->bitblt.srcaddr += -1; + } + else if (da2->bitblt.x == 0) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; + ////da2->bitblt.srcaddr += 2; + //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + break; case DA2_BLT_CDONE: - //initialize regs with fefefefeh, clear regs with fefeh for debug dump + /* initialize regs for debug dump */ for (int i = 0; i < DA2_BLT_REGSIZE; i++) { if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; } @@ -809,6 +946,21 @@ void da2_bitblt_exec(void* p) break; } } +void da2_bitblt_dopayload(da2_t* da2) { + if (da2->bitblt.exec == DA2_BLT_CIDLE) + { + da2->bitblt.exec = DA2_BLT_CLOAD; + //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ + da2_log("da2 Do bitblt\n"); + while (da2->bitblt.exec != DA2_BLT_CIDLE) + { + da2_bitblt_exec(da2); + } + da2_log("da2 End bitblt %x\n", da2->bitblt.exec); + } +} + void da2_out(uint16_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *)p; @@ -867,8 +1019,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) 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); 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); + 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); oldval = da2->ioctl[da2->ioctladdr]; da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { @@ -882,12 +1034,7 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ { - da2->bitblt.indata = 1; - if (da2->bitblt.exec == DA2_BLT_CIDLE) - { - da2->bitblt.exec = DA2_BLT_CLOAD; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - } + //da2->bitblt.indata = 1; } } break; @@ -910,8 +1057,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) break; case LC_DATA: 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); + //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); if (!(da2->crtc[da2->crtcaddr] ^ val)) return; switch (da2->crtcaddr) { case LC_CRTC_OVERFLOW: @@ -955,10 +1102,10 @@ void 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_log("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 & 31; da2->attraddr = val & 0x3f; if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) { @@ -970,47 +1117,44 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } else { - if ((da2->attraddr == LV_PANNING) && (da2->attrregs[LV_PANNING] != val)) + if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) da2->fullchange = changeframecount; - if (da2->attrregs[da2->attraddr & 0x3f] != val) - da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrregs[da2->attraddr & 0x3f], val); - da2->attrregs[da2->attraddr & 0x3f] = val; - //da2_log("set attrreg %x: %x\n", da2->attraddr & 31, val); + 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->attrc[da2->attraddr & 0x3f] = val; + //da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) da2->fullchange = changeframecount; - //if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr == 0x14 || da2->attraddr < 0x10) if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { for (int c = 0; c < 16; c++) { - //if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrregs[c] & 0xf) | ((da2->attrregs[0x14] & 0xf) << 4); - //else da2->egapal[c] = (da2->attrregs[c] & 0x3f) | ((da2->attrregs[0x14] & 0xc) << 4); - if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrregs[c] & 0xf; - else da2->egapal[c] = da2->attrregs[c] & 0x3f; - } - } - if (da2->attraddr == LV_COLOR_PLANE_ENAB) - { - if ((val & 0xff) != da2->plane_mask) - da2->fullchange = changeframecount; - da2->plane_mask = val & 0xff; - } - if (da2->attraddr == LV_CURSOR_CONTROL) - { - switch (val & 0x18) { - case 0x08://fast blink - da2->blinkconf = 0x10; - break; - case 0x18://slow blink - da2->blinkconf = 0x20; - break; - default://no blink - da2->blinkconf = 0xff; - break; + //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); + //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); + if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; + else da2->egapal[c] = da2->attrc[c] & 0x3f; } } switch (da2->attraddr) { + case LV_COLOR_PLANE_ENAB: + if ((val & 0xff) != da2->plane_mask) + da2->fullchange = changeframecount; + da2->plane_mask = val & 0xff; + break; + case LV_CURSOR_CONTROL: + switch (val & 0x18) { + case 0x08://fast blink + da2->blinkconf = 0x10; + break; + case 0x18://slow blink + da2->blinkconf = 0x20; + break; + default://no blink + da2->blinkconf = 0xff; + break; + } + break; case LV_MODE_CONTROL: case LV_ATTRIBUTE_CNTL: case LV_COMPATIBILITY: @@ -1022,9 +1166,9 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } da2->attrff ^= 1; break; - case 0x3E9: - /* VZ Editor's CURSOR.COM writes via this port */ - da2->attrregs[da2->attraddr & 0x3f] = val; + case 0x3E9: + /* VZ Editor's CURSOR.COM writes data via this port */ + da2->attrc[da2->attraddr & 0x3f] = val; break; case LG_INDEX: da2->gdcaddr = val; @@ -1103,15 +1247,17 @@ uint16_t da2_in(uint16_t addr, void *p) if (da2->ioctladdr > 0xf) return 0xff; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ - if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrregs[LV_COMPATIBILITY] & 0x08) + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrc[LV_COMPATIBILITY] & 0x08) temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ else temp |= 0x80; /* Active when the RGB output voltage is lowand the cable is connected to the color monitor. If the cable or the monitor is wrong, it becomes inactive. */ temp &= 0xf6;//idle + if (da2->bitblt.indata) /* for OS/2 J1.3 */ + da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { - //da2_log("exec:%d\n", da2->bitblt.exec); + //da2_log("exec:%x\n", da2->bitblt.exec); temp |= 0x08;//wait(bit 3 + bit 0) //if (!da2->bitblt.timer.enabled) //{ @@ -1152,7 +1298,7 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->cgastat; } else - temp = da2->attrregs[da2->attraddr]; + 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->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ break; @@ -1161,7 +1307,7 @@ uint16_t 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_log("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); @@ -1386,12 +1532,18 @@ Bank 1, 2, 3 Bank 4 * -0DB6Fh ( 4800-8DB6Fh;IBMJ 100-1F7Dh) : JIS X 0208 DBCS (24 x 24) 10000-16D1Fh (90000-96D1Fh;IBMJ 2000-2183h) : IBM Extended Characters -18000-1BFFFh (98000-9BFFFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) -1FD20- * +18000-1BFCFh (98000-9BFCFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) +1C000-1FFFFh (9C000-9FFFFh;around IBMJ 22AA-238Eh) : Codepage 437 characters (13 x 30) Bank 5 +00000-0C68Fh (A0000-AC68Fh;around IBMJ 238E-2650h) : Gaiji (24 x 24) + * -0D09Fh (9FD20-AD09Fh;IBMJ 2384-2673h) : Gaiji 752 chs (maybe blank) 10000-13FFFh (B0000-B3FFFh;around IBMJ 271C-27FFh) : Extended SBCS (13 x 30) -14000-146FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho + +14000-147FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho +16000-17FFFh (B6000-B7FFFh;around IBMJ h) : Codepage 850 characters (13 x 30) +18000-1A3FFh (B8000-BA3FFh;around IBMJ h) : Shape Icons? (32 x 32) + (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters The signature 80h, 01h must be placed at Bank 0:1AFFEh to run OS/2 J1.3. @@ -1470,7 +1622,7 @@ uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) foreground <<= 2; //0010 0000 foreground |= ~attr & 0xc0;// 1110 0000 foreground >>= 4;//0000 1110 - if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette return foreground; } @@ -1510,7 +1662,7 @@ static void da2_render_text(da2_t* da2) chr = da2->cram[(da2->ma) & da2->vram_display_mask]; attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80)//IO 3E8h, Index 1Dh + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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); @@ -1561,9 +1713,9 @@ static void da2_render_text(da2_t* da2) // the char code is SBCS (ANK) uint32_t fontbase; if (attr & 0x02)//second map of SBCS font - fontbase = 0x3c000; + fontbase = DA2_GAIJIRAM_SBEX; else - fontbase = 0x34000; + fontbase = DA2_GAIJIRAM_SBCS; uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font font <<= 8; font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font @@ -1587,25 +1739,25 @@ static void 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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode + if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {//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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//vertical line (white) + p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//vertical line (white) } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrregs[LV_PAS_STATUS_CNTRL]) {//HGrid + 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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) + p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? 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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 - fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); + 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); bg = 0; if (attr & 0x04) {//Color 0 if reverse bg = fg; @@ -1677,7 +1829,7 @@ static void da2_render_textm3(da2_t* da2) else { // the char code is SBCS (ANK) uint32_t fontbase; - fontbase = 0x34000; + fontbase = DA2_FONTROM_BASESBCS; uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font font <<= 8; font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font @@ -1704,8 +1856,8 @@ static void da2_render_textm3(da2_t* da2) 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->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[0x1a]) : 2;//Choose color 2 if mode 8 - //fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + //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; //bg = 0; //if (attr & 0x04) {//Color 0 if reverse // bg = fg; @@ -1876,9 +2028,9 @@ void da2_recalctimings(da2_t* da2) da2->clock = da2->da2const; - da2->lowres = da2->attrregs[LC_VERTICAL_SYNC_START] & 0x40; + //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - da2->interlace = 0; + //da2->interlace = 0; //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b da2->ca_adj = 0; @@ -1888,8 +2040,8 @@ void da2_recalctimings(da2_t* da2) da2->hdisp_time = da2->hdisp; da2->render = da2_render_blank; //determine display mode - //if (da2->attr_palette_enable && (da2->attrregs[0x1f] & 0x08)) - if (da2->attrregs[LV_COMPATIBILITY] & 0x08) + //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode da2->hdisp *= 16; @@ -1907,7 +2059,7 @@ void da2_recalctimings(da2_t* da2) } } else {//text mode - if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) { + if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; @@ -2118,7 +2270,7 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); if (addr > DA2_FONTROM_SIZE) return 0xff; return da2->mmio.font[addr]; break; @@ -2165,6 +2317,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) for (int i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch +#ifdef ENABLE_DA2_DEBUGBLT ////debug //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ @@ -2179,7 +2332,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) // fprintf(da2->mmrdbg_fp, "%X", pixeldata); //} //da2->mmrdbg_vidaddr = addr; - //// +#endif if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 uint16_t ret = 0; @@ -2200,7 +2353,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) else { return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); } -} +} static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) { @@ -2231,12 +2384,15 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) break; case 0x00: //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx - if (addr >= DA2_BLT_MEMSIZE) - { - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - return; - } + //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + //if (addr >= DA2_BLT_MEMSIZE) + //{ + // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + // return; + //} + da2->bitblt.indata = 1; + if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); da2->bitblt.payload[da2->bitblt.payload_addr] = val; da2->bitblt.payload_addr++; break; @@ -2249,23 +2405,25 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) { uint8_t wm = da2->writemask; //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); +#ifdef ENABLE_DA2_DEBUGBLT //debug //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, "\nB %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 8; i++) - //{ - // int pixeldata = 0; - // if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); - // fprintf(da2->mmdbg_fp, "%X", pixeldata); - //} - //da2->mmdbg_vidaddr = addr; + if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + { + fprintf(da2->mmdbg_fp, "\nB %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 8; i++) + { + int pixeldata = 0; + if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; //} +#endif cycles -= video_timing_write_b; @@ -2273,7 +2431,7 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch + da2->gdcsrc[i] = da2->gdcla[i];//use latch //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2361,24 +2519,26 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; +#ifdef ENABLE_DA2_DEBUGBLT //debug //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 ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 16; i++) - //{ - // int pixeldata = 0; - // if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); - // fprintf(da2->mmdbg_fp, "%X", pixeldata); - //} - //da2->mmdbg_vidaddr = addr; + 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 ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 16; i++) + { + int pixeldata = 0; + if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; //} - //cycles -= video_timing_write_w; +#endif + cycles -= video_timing_write_w; //cycles_lost += video_timing_write_w; //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); @@ -2585,8 +2745,8 @@ void da2_poll(void* priv) //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); da2->displine++; - if (da2->interlace) - da2->displine++; + //if (da2->interlace) + // da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { //da2_log("Vsync off at line %i\n",displine); @@ -2641,7 +2801,7 @@ void da2_poll(void* priv) //if (da2->crtc[10] & 0x20) da2->cursoron = 0; //else da2->cursoron = da2->blink & 16; if (da2->ioctl[LS_MODE] & 1) {//in text mode - if (da2->attrregs[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking { da2->cursoron = (da2->blink | 1) & da2->blinkconf; } @@ -2673,8 +2833,8 @@ void da2_poll(void* priv) da2->cgastat |= 8; x = da2->hdisp; - if (da2->interlace && !da2->oddeven) da2->lastline++; - if (da2->interlace && da2->oddeven) da2->firstline--; + //if (da2->interlace && !da2->oddeven) da2->lastline++; + //if (da2->interlace && da2->oddeven) da2->firstline--; wx = x; wy = da2->lastline - da2->firstline; @@ -2695,8 +2855,8 @@ void da2_poll(void* priv) //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; +/* 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; @@ -2715,7 +2875,7 @@ void da2_poll(void* priv) da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; - da2->scrollcache = da2->attrregs[LV_PANNING] & 7; + da2->scrollcache = da2->attrc[LV_PANNING] & 7; } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; @@ -2793,12 +2953,12 @@ da2_reset(void* priv) da2->ioctl[LS_CONFIG2] = Mon_ID1; /* Configuration (High): Monitor ID 0-2 */ da2->fctl[0] = 0x2b; /* 3E3h:0 */ da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ - da2->attrregs[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ da2->ma_latch = 0; da2->interlace = 0; - da2->attrregs[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Display driver of Win 3.1 won't reset palette) */ @@ -2889,7 +3049,7 @@ void da2_close(void *p) } f = fopen("da2_attrpal.dmp", "wb"); if (f != NULL) { - fwrite(da2->attrregs, 32, 1, f); + fwrite(da2->attrc, 32, 1, f); fclose(f); } f = fopen("da2_dacrgb.dmp", "wb"); @@ -2906,7 +3066,7 @@ void da2_close(void *p) for (int i = 0; i < 0x20; i++) fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrregs[i]); + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); for (int i = 0; i < 0x10; i++) fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); for (int i = 0; i < 0x10; i++) @@ -2939,7 +3099,7 @@ void da2_close(void *p) } if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); + free(da2->bitblt.debug_reg); #endif free(da2->cram); free(da2->vram); From 738087ae132c677735d2b277ab5cc3cdd4e6ce1c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 Jan 2025 23:28:08 -0500 Subject: [PATCH 0032/1190] Cleanups in device --- src/device.c | 249 +++++++++++++++++++------------------ src/include/86box/device.h | 26 ++-- 2 files changed, 138 insertions(+), 137 deletions(-) diff --git a/src/device.c b/src/device.c index 9a904f550..5b733df46 100644 --- a/src/device.c +++ b/src/device.c @@ -19,7 +19,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2008-2019 Sarah Walker. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -89,38 +89,38 @@ device_init(void) } void -device_set_context(device_context_t *c, const device_t *dev, int inst) +device_set_context(device_context_t *ctx, const device_t *dev, int inst) { - memset(c, 0, sizeof(device_context_t)); - c->dev = dev; - c->instance = inst; + memset(ctx, 0, sizeof(device_context_t)); + ctx->dev = dev; + ctx->instance = inst; if (inst) { - sprintf(c->name, "%s #%i", dev->name, inst); + sprintf(ctx->name, "%s #%i", dev->name, inst); /* If a numbered section is not present, but a non-numbered of the same name is, rename the non-numbered section to numbered. */ - const void *sec = config_find_section(c->name); + const void *sec = config_find_section(ctx->name); void * single_sec = config_find_section((char *) dev->name); if ((sec == NULL) && (single_sec != NULL)) - config_rename_section(single_sec, c->name); + config_rename_section(single_sec, ctx->name); } else if (!strcmp(dev->name, "PS/2 Mouse")) { - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); /* Migrate the old "Standard PS/2 Mouse" section */ - const void *sec = config_find_section(c->name); + const void *sec = config_find_section(ctx->name); void * old_sec = config_find_section("Standard PS/2 Mouse"); if ((sec == NULL) && (old_sec != NULL)) - config_rename_section(old_sec, c->name); + config_rename_section(old_sec, ctx->name); } else if (!strcmp(dev->name, "Microsoft RAMCard")) { - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); - /* Migrate the old "Standard PS/2 Mouse" section */ - const void *sec = config_find_section(c->name); + /* Migrate the old "Microsoft RAMCard for IBM PC" section */ + const void *sec = config_find_section(ctx->name); void * old_sec = config_find_section("Microsoft RAMCard for IBM PC"); if ((sec == NULL) && (old_sec != NULL)) - config_rename_section(old_sec, c->name); + config_rename_section(old_sec, ctx->name); } else - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); } static void @@ -153,7 +153,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) { device_t *init_dev = NULL; void *priv = NULL; - int c; + int16_t c; if (params != NULL) { init_dev = calloc(1, sizeof(device_t)); @@ -162,7 +162,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) } else init_dev = (device_t *) dev; - for (c = 0; c < 256; c++) { + for (c = 0; c < DEVICE_MAX; c++) { if (!inst && (devices[c] == dev)) { device_log("DEVICE: device already exists!\n"); return (NULL); @@ -244,6 +244,7 @@ void * device_add_linked(const device_t *dev, void *priv) { void *ret; + device_common_priv = priv; ret = device_add_common(dev, NULL, NULL, 0); device_common_priv = NULL; @@ -311,7 +312,8 @@ device_close_all(void) #endif if (devices[c]->close != NULL) devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; + devices[c] = NULL; + device_priv[c] = NULL; } } } @@ -372,7 +374,7 @@ device_available(const device_t *dev) if (dev != NULL) { config = dev->config; if (config != NULL) { - while (config->type != -1) { + while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { int roms_present = 0; @@ -414,7 +416,7 @@ device_get_bios_file(const device_t *dev, const char *internal_name, int file_no if (dev != NULL) { config = dev->config; if (config != NULL) { - while (config->type != -1) { + while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { bios = config->bios; @@ -452,7 +454,7 @@ device_has_config(const device_t *dev) config = dev->config; - while (config->type != -1) { + while (config->type != CONFIG_END) { c++; config++; } @@ -543,8 +545,7 @@ device_get_name(const device_t *dev, int bus, char *name) strcat(pbus, ")"); /* Allocate the temporary device name string and set it to all zeroes. */ - tname = (char *) malloc(strlen(dev->name) + 1); - memset(tname, 0x00, strlen(dev->name) + 1); + tname = (char *) calloc(1, strlen(dev->name) + 1); /* First strip the bus string with parentheses. */ fbus = strstr(dev->name, pbus); @@ -612,256 +613,256 @@ device_get_instance(void) } const char * -device_get_config_string(const char *s) +device_get_config_string(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_string((char *) device_current.name, (char *) s, (char *) c->default_string)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_string((char *) device_current.name, (char *) str, (char *) cfg->default_string)); - c++; + cfg++; } return (NULL); } int -device_get_config_int(const char *s) +device_get_config_int(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_int_ex(const char *s, int def) +device_get_config_int_ex(const char *str, int def) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) device_current.name, (char *) s, def)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, def)); - c++; + cfg++; } return def; } int -device_get_config_hex16(const char *s) +device_get_config_hex16(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_hex16((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_hex20(const char *s) +device_get_config_hex20(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_hex20((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_mac(const char *s, int def) +device_get_config_mac(const char *str, int def) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_mac((char *) device_current.name, (char *) s, def)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_mac((char *) device_current.name, (char *) str, def)); - c++; + cfg++; } return def; } void -device_set_config_int(const char *s, int val) +device_set_config_int(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_int((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_int((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_hex16(const char *s, int val) +device_set_config_hex16(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_hex16((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_hex16((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_hex20(const char *s, int val) +device_set_config_hex20(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_hex20((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_hex20((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_mac(const char *s, int val) +device_set_config_mac(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_mac((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_mac((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } int -device_is_valid(const device_t *device, int m) +device_is_valid(const device_t *device, int mch) { if (device == NULL) return 1; - if ((device->flags & DEVICE_PCJR) && !machine_has_bus(m, MACHINE_BUS_PCJR)) + if ((device->flags & DEVICE_PCJR) && !machine_has_bus(mch, MACHINE_BUS_PCJR)) return 0; - if ((device->flags & DEVICE_XTKBC) && machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + if ((device->flags & DEVICE_XTKBC) && machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) return 0; - if ((device->flags & DEVICE_AT) && !machine_has_bus(m, MACHINE_BUS_ISA16)) + if ((device->flags & DEVICE_AT) && !machine_has_bus(mch, MACHINE_BUS_ISA16)) return 0; - if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) return 0; - if ((device->flags & DEVICE_PS2) && !machine_has_bus(m, MACHINE_BUS_PS2_PORTS)) + if ((device->flags & DEVICE_PS2) && !machine_has_bus(mch, MACHINE_BUS_PS2_PORTS)) return 0; - if ((device->flags & DEVICE_ISA) && !machine_has_bus(m, MACHINE_BUS_ISA)) + if ((device->flags & DEVICE_ISA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) return 0; - if ((device->flags & DEVICE_CBUS) && !machine_has_bus(m, MACHINE_BUS_CBUS)) + if ((device->flags & DEVICE_CBUS) && !machine_has_bus(mch, MACHINE_BUS_CBUS)) return 0; - if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_ISA)) + if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) return 0; - if ((device->flags & DEVICE_MCA) && !machine_has_bus(m, MACHINE_BUS_MCA)) + if ((device->flags & DEVICE_MCA) && !machine_has_bus(mch, MACHINE_BUS_MCA)) return 0; - if ((device->flags & DEVICE_HIL) && !machine_has_bus(m, MACHINE_BUS_HIL)) + if ((device->flags & DEVICE_HIL) && !machine_has_bus(mch, MACHINE_BUS_HIL)) return 0; - if ((device->flags & DEVICE_EISA) && !machine_has_bus(m, MACHINE_BUS_EISA)) + if ((device->flags & DEVICE_EISA) && !machine_has_bus(mch, MACHINE_BUS_EISA)) return 0; - if ((device->flags & DEVICE_AT32) && !machine_has_bus(m, MACHINE_BUS_AT32)) + if ((device->flags & DEVICE_AT32) && !machine_has_bus(mch, MACHINE_BUS_AT32)) return 0; - if ((device->flags & DEVICE_OLB) && !machine_has_bus(m, MACHINE_BUS_OLB)) + if ((device->flags & DEVICE_OLB) && !machine_has_bus(mch, MACHINE_BUS_OLB)) return 0; - if ((device->flags & DEVICE_VLB) && !machine_has_bus(m, MACHINE_BUS_VLB)) + if ((device->flags & DEVICE_VLB) && !machine_has_bus(mch, MACHINE_BUS_VLB)) return 0; - if ((device->flags & DEVICE_PCI) && !machine_has_bus(m, MACHINE_BUS_PCI)) + if ((device->flags & DEVICE_PCI) && !machine_has_bus(mch, MACHINE_BUS_PCI)) return 0; - if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_PCI)) + if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_PCI)) return 0; - if ((device->flags & DEVICE_USB) && !machine_has_bus(m, MACHINE_BUS_USB)) + if ((device->flags & DEVICE_USB) && !machine_has_bus(mch, MACHINE_BUS_USB)) return 0; - if ((device->flags & DEVICE_AGP) && !machine_has_bus(m, MACHINE_BUS_AGP)) + if ((device->flags & DEVICE_AGP) && !machine_has_bus(mch, MACHINE_BUS_AGP)) return 0; - if ((device->flags & DEVICE_AC97) && !machine_has_bus(m, MACHINE_BUS_AC97)) + if ((device->flags & DEVICE_AC97) && !machine_has_bus(mch, MACHINE_BUS_AC97)) return 0; return 1; } int -machine_get_config_int(char *s) +machine_get_config_int(char *str) { - const device_t *d = machine_get_device(machine); - const device_config_t *c; + const device_t *dev = machine_get_device(machine); + const device_config_t *cfg; - if (d == NULL) + if (dev == NULL) return 0; - c = d->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) d->name, s, c->default_int)); + cfg = dev->config; + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) dev->name, str, cfg->default_int)); - c++; + cfg++; } return 0; } char * -machine_get_config_string(char *s) +machine_get_config_string(char *str) { - const device_t *d = machine_get_device(machine); - const device_config_t *c; + const device_t *dev = machine_get_device(machine); + const device_config_t *cfg; - if (d == NULL) + if (dev == NULL) return 0; - c = d->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_string((char *) d->name, s, (char *) c->default_string)); + cfg = dev->config; + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_string((char *) dev->name, str, (char *) cfg->default_string)); - c++; + cfg++; } return NULL; @@ -881,7 +882,7 @@ const device_t device_none = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -895,7 +896,7 @@ const device_t device_internal = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 67a30b1c8..1c2ec5203 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -18,7 +18,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2008-2019 Sarah Walker. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -197,12 +197,12 @@ extern "C" { #endif extern void device_init(void); -extern void device_set_context(device_context_t *c, const device_t *dev, int inst); +extern void device_set_context(device_context_t *ctx, const device_t *dev, int inst); extern void device_context(const device_t *dev); extern void device_context_inst(const device_t *dev, int inst); extern void device_context_restore(void); -extern void *device_add(const device_t *d); -extern void *device_add_linked(const device_t *d, void *priv); +extern void *device_add(const device_t *dev); +extern void *device_add_linked(const device_t *dev, void *priv); extern void *device_add_params(const device_t *dev, void *params); extern void device_add_ex(const device_t *dev, void *priv); extern void device_add_ex_params(const device_t *dev, void *priv, void *params); @@ -223,27 +223,27 @@ extern void device_get_name(const device_t *dev, int bus, char *name); extern int device_has_config(const device_t *dev); extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no); -extern int device_is_valid(const device_t *, int m); +extern int device_is_valid(const device_t *, int mch); extern const device_t* device_context_get_device(void); extern int device_get_config_int(const char *name); -extern int device_get_config_int_ex(const char *s, int dflt_int); +extern int device_get_config_int_ex(const char *str, int def); extern int device_get_config_hex16(const char *name); extern int device_get_config_hex20(const char *name); -extern int device_get_config_mac(const char *name, int dflt_int); -extern void device_set_config_int(const char *s, int val); -extern void device_set_config_hex16(const char *s, int val); -extern void device_set_config_hex20(const char *s, int val); -extern void device_set_config_mac(const char *s, int val); +extern int device_get_config_mac(const char *name, int def); +extern void device_set_config_int(const char *str, int val); +extern void device_set_config_hex16(const char *str, int val); +extern void device_set_config_hex20(const char *str, int val); +extern void device_set_config_mac(const char *str, int val); extern const char *device_get_config_string(const char *name); extern int device_get_instance(void); #define device_get_config_bios device_get_config_string extern const char *device_get_internal_name(const device_t *dev); -extern int machine_get_config_int(char *s); -extern char *machine_get_config_string(char *s); +extern int machine_get_config_int(char *str); +extern char *machine_get_config_string(char *str); extern const device_t device_none; extern const device_t device_internal; From 1ee305d0f3979ab8b04ee777f2cc0a1d3da8e3ff Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 23:22:00 -0500 Subject: [PATCH 0033/1190] devices -> midi_out_devices in sound/midi.c --- src/sound/midi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sound/midi.c b/src/sound/midi.c index 78794ef24..e9b4a82b6 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -71,7 +71,7 @@ typedef struct const device_t *device; } MIDI_OUT_DEVICE, MIDI_IN_DEVICE; -static const MIDI_OUT_DEVICE devices[] = { +static const MIDI_OUT_DEVICE midi_out_devices[] = { // clang-format off { &device_none }, #ifdef USE_FLUIDSYNTH @@ -106,8 +106,8 @@ static const MIDI_IN_DEVICE midi_in_devices[] = { int midi_out_device_available(int card) { - if (devices[card].device) - return device_available(devices[card].device); + if (midi_out_devices[card].device) + return device_available(midi_out_devices[card].device); return 1; } @@ -115,21 +115,21 @@ midi_out_device_available(int card) const device_t * midi_out_device_getdevice(int card) { - return devices[card].device; + return midi_out_devices[card].device; } int midi_out_device_has_config(int card) { - if (!devices[card].device) + if (!midi_out_devices[card].device) return 0; - return devices[card].device->config ? 1 : 0; + return midi_out_devices[card].device->config ? 1 : 0; } const char * midi_out_device_get_internal_name(int card) { - return device_get_internal_name(devices[card].device); + return device_get_internal_name(midi_out_devices[card].device); } int @@ -137,8 +137,8 @@ midi_out_device_get_from_internal_name(char *s) { int c = 0; - while (devices[c].device != NULL) { - if (!strcmp(devices[c].device->internal_name, s)) + while (midi_out_devices[c].device != NULL) { + if (!strcmp(midi_out_devices[c].device->internal_name, s)) return c; c++; } @@ -149,8 +149,8 @@ midi_out_device_get_from_internal_name(char *s) void midi_out_device_init(void) { - if ((midi_output_device_current > 0) && devices[midi_output_device_current].device) - device_add(devices[midi_output_device_current].device); + if ((midi_output_device_current > 0) && midi_out_devices[midi_output_device_current].device) + device_add(midi_out_devices[midi_output_device_current].device); midi_output_device_last = midi_output_device_current; } From cbbf91b790d585421b8b97697a442789f1a35674 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 01:09:09 -0500 Subject: [PATCH 0034/1190] Add other BIOS versions to ibmpc --- src/machine/m_xt.c | 60 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index db511c332..b31e58bdf 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -61,6 +61,29 @@ machine_xt_common_init(const machine_t *model, int fixed_floppy) static const device_config_t ibmpc_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5150_5700671", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "5700671 (10/19/81)", .internal_name = "ibm5150_5700671", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_19OCT81_5700671_U33.BIN", "" } }, + { .name = "5700051 (04/24/81)", .internal_name = "ibm5150_5700051", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_24APR81_5700051_U33.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", @@ -94,27 +117,36 @@ const device_t ibmpc_device = { int machine_pc_init(const machine_t *model) { - int ret; - uint8_t enable_5161; - uint8_t enable_basic; + int ret = 0; + int ret2; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 40960, 0); device_context_restore(); - ret = bios_load_linear("roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN", - 0x000fe000, 40960, 0); - if (enable_basic && ret) { - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", - 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", - 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", - 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", - 0x000fc000, 8192, 0); + ret2 = bios_load_aux_linear("roms/machines/ibmpc/ibm-basic-1.00.rom", + 0x000f6000, 32768, 0); + if (!ret2) { + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", + 0x000f6000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", + 0x000f8000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", + 0x000fa000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", + 0x000fc000, 8192, 0); + } } if (bios_only || !ret) From 312536f51e14bc8f924521b71b2edb815e707c9b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 01:09:27 -0500 Subject: [PATCH 0035/1190] A few updates to ibmpc82 --- src/machine/m_xt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index b31e58bdf..d38dd6bc6 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -224,7 +224,7 @@ machine_pc82_init(const machine_t *model) int ret2; uint8_t enable_5161; uint8_t enable_basic; - const char* fn; + const char *fn; /* No ROMs available. */ if (!device_available(model->device)) @@ -241,13 +241,13 @@ machine_pc82_init(const machine_t *model) ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom", 0x000f6000, 32768, 0); if (!ret2) { - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f6", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U29 - 5000019.bin", 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f8", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U30 - 5000021.bin", 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fa", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U31 - 5000022.bin", 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fc", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U32 - 5000023.bin", 0x000fc000, 8192, 0); } } From c01022db46ec2a78ca9142798770ccc60dc09d31 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 02:33:13 -0500 Subject: [PATCH 0036/1190] Add other BIOS versions to ibmxt (82) --- src/machine/m_xt.c | 65 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index d38dd6bc6..9a56c4870 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -267,12 +267,45 @@ machine_pc82_init(const machine_t *model) static const device_config_t ibmxt_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5160_1501512_5000027", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, +#if 0 + { .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } }, + { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, +#endif + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", .type = CONFIG_BINARY, .default_int = 1 }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -294,26 +327,28 @@ const device_t ibmxt_device = { int machine_xt_init(const machine_t *model) { - int ret; - uint8_t enable_5161; - uint8_t enable_basic; + int ret; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); - device_context_restore(); + enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); - ret = bios_load_linear("roms/machines/ibmxt/xt.rom", - 0x000f0000, 65536, 0); - if (!ret) { - ret = bios_load_linear("roms/machines/ibmxt/1501512.u18", - 0x000fe000, 65536, 0x6000); - if (ret) { - bios_load_aux_linear("roms/machines/ibmxt/1501512.u18", - 0x000f8000, 24576, 0); - bios_load_aux_linear("roms/machines/ibmxt/5000027.u19", - 0x000f0000, 32768, 0); - } + if (enable_basic && ret) { + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } + device_context_restore(); if (bios_only || !ret) return ret; From a6b8f826fee27d55710c2e3019e68e550a8e17cc Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 03:24:12 -0500 Subject: [PATCH 0037/1190] Fixes --- src/machine/m_xt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 9a56c4870..1977c88df 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -278,11 +278,11 @@ static const device_config_t ibmxt_config[] = { .bios = { { .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, -#if 0 { .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } }, { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, +#if 0 // The following are Diagnostic ROMs. { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, @@ -327,7 +327,7 @@ const device_t ibmxt_device = { int machine_xt_init(const machine_t *model) { - int ret; + int ret = 0; uint8_t enable_5161; uint8_t enable_basic; const char *fn; From 3ffaf21f605a00046af145d17bc40db238d8fd69 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 03:24:38 -0500 Subject: [PATCH 0038/1190] Add other BIOS versions to ibmxt (86) --- src/machine/m_xt.c | 50 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 1977c88df..7b59686d6 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -383,6 +383,33 @@ machine_genxt_init(const machine_t *model) static const device_config_t ibmxt86_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5160_050986", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501512 (05/09/86)", .internal_name = "ibm5160_050986", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } }, + { .name = "5000026 (01/10/86)", .internal_name = "ibm5160_011086", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } }, + { .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } }, +#if 0 + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, +#endif + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", @@ -410,21 +437,26 @@ const device_t ibmxt86_device = { int machine_xt86_init(const machine_t *model) { - int ret; - uint8_t enable_5161; + int ret = 0; + uint8_t enable_5161; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); - device_context_restore(); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); - ret = bios_load_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000fe000, 65536, 0x6000); if (ret) { - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000f8000, 24576, 0); - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", - 0x000f0000, 32768, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } + device_context_restore(); if (bios_only || !ret) return ret; From 78a81b0d7fda7223400dc0eb424d54bab893e6d2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 10 Jan 2025 21:56:04 +0100 Subject: [PATCH 0039/1190] AT / PS/2 keyboard: It turns out a few other commands also cancel the pending command, fixes #4981. --- src/device/keyboard_at.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 882174e4e..af3d5d5fc 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1961,18 +1961,24 @@ keyboard_at_write(void *priv) } } else { if (dev->flags & FLAG_CTRLDAT) { - /* Special case - another command during another command that wants input - proceed + /* + Special case - another command during another command that wants input - proceed as normal but do not cancel the command (so keep waiting for input), unless the - command in progress is ED (Set/reset LEDs). */ - if (val == 0xed) { - keyboard_scan = 1; + command in progress is ED (Set/reset LEDs). + + It appears to also apply to command EE (Echo), F4 (Enable), F5 (Diable and Set + Default), and F6 (SetDefault). + */ + if ((val == 0xed) || (val == 0xee) || (val == 0xf4) || (val == 0xf5) || (val == 0xf6)) dev->flags &= ~FLAG_CTRLDAT; - } else + else dev->state = DEV_STATE_MAIN_WANT_IN; } switch (val) { case 0xed: /* set/reset LEDs */ + if ((dev->flags & FLAG_CTRLDAT) && (dev->command == 0xed)) + keyboard_scan = 1; dev->command = val; keyboard_at_log("%s: set/reset LEDs\n", dev->name); dev->flags |= FLAG_CTRLDAT; From f774618b1eb59df04a6b56b2053e65b3cd7db2f1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 10 Jan 2025 23:40:54 +0100 Subject: [PATCH 0040/1190] SiS 5513 PCI to ISA bridge: fix a typo in a revision check. --- src/chipset/sis_5513_p2i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index ef9a6746d..4205db161 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -106,7 +106,7 @@ sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev) { memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs)); - if (dev->rev == 0b0) { + if (dev->rev == 0xb0) { dev->apc_regs[0x03] = 0x80; dev->apc_regs[0x04] = 0x38; dev->apc_regs[0x07] = 0x01; From 28c296fc753046b7455a97265ae58b4bf9bcbc4d Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2025 00:12:13 +0100 Subject: [PATCH 0041/1190] More case ranges in src/chipset/ali1531.c. --- src/chipset/ali1531.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index 9eb75f7cd..06d0a0a60 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -225,12 +225,8 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) ali1531_shadow_recalc(val, dev); break; - case 0x50: - case 0x51: - case 0x52: - case 0x54: - case 0x55: - case 0x56: + case 0x50 ... 0x52: + case 0x54 ... 0x56: dev->pci_conf[addr] = val; break; @@ -247,8 +243,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x86; break; - case 0x59: - case 0x5a: + case 0x59 ... 0x5a: case 0x5c: dev->pci_conf[addr] = val; break; @@ -270,8 +265,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); break; - case 0x70: - case 0x71: + case 0x70 ... 0x71: dev->pci_conf[addr] = val; break; @@ -283,8 +277,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x2b; break; - case 0x76: - case 0x77: + case 0x76 ... 0x77: dev->pci_conf[addr] = val; break; From 035b8deee2cf2b9ed6ad34d5ee0c220b6090a7fa Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 22:53:52 -0500 Subject: [PATCH 0042/1190] Random warning fixes --- src/cdrom/cdrom_image_backend.c | 4 +-- src/cdrom/cdrom_mitsumi.c | 47 +++++++++++++++------------------ src/qt/dummy_cdrom_ioctl.c | 7 ++++- src/unix/dummy_cdrom_ioctl.c | 7 ++++- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 9d065a0cb..ad1756055 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1195,7 +1195,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void *) cdi_insert_track(cdi, session, 0xa0 + i); + (void) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); @@ -1393,7 +1393,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void *) cdi_insert_track(cdi, session, 0xa0 + i); + (void) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c index 0cebfe7f6..c3c362b1b 100644 --- a/src/cdrom/cdrom_mitsumi.c +++ b/src/cdrom/cdrom_mitsumi.c @@ -156,9 +156,9 @@ mitsumi_cdrom_is_ready(const cdrom_t *dev) static void mitsumi_cdrom_reset(mcd_t *dev) { - cdrom_t cdrom; - - dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | STAT_CHANGE) : 0; + cdrom_t *cdrom = calloc(1, sizeof(cdrom_t)); + + dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | STAT_CHANGE) : 0; dev->cmdrd_count = 0; dev->cmdbuf_count = 0; dev->buf_count = 0; @@ -176,12 +176,12 @@ mitsumi_cdrom_reset(mcd_t *dev) static int mitsumi_cdrom_read_sector(mcd_t *dev, int first) { - cdrom_t cdrom; + cdrom_t *cdrom = calloc(1, sizeof(cdrom_t)); uint8_t status; - int ret; + int ret = 0; if (dev->drvmode == DRV_MODE_CDDA) { - status = cdrom_mitsumi_audio_play(&cdrom, dev->readmsf, dev->readcount); + status = cdrom_mitsumi_audio_play(cdrom, dev->readmsf, dev->readcount); if (status == 1) return status; else @@ -195,15 +195,15 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first) dev->data = 0; return 0; } - cdrom_stop(&cdrom); - ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); + cdrom_stop(cdrom); + ret = cdrom_readsector_raw(cdrom, dev->buf, cdrom->seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); if (ret <= 0) return 0; if (dev->mode & 0x40) { dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff); dev->buf[13] = CD_BCD((dev->readmsf >> 8) & 0xff); } - dev->readmsf = cdrom_lba_to_msf_accurate(cdrom.seek_pos + 1); + dev->readmsf = cdrom_lba_to_msf_accurate(cdrom->seek_pos + 1); dev->buf_count = dev->dmalen + 1; dev->buf_idx = 0; dev->data = 1; @@ -224,7 +224,7 @@ static uint8_t mitsumi_cdrom_in(uint16_t port, void *priv) { mcd_t *dev = (mcd_t *) priv; - uint8_t ret; + uint8_t ret = 0xff; pclog("Mitsumi CD-ROM IN=%03x\n", port); switch (port & 1) { @@ -259,14 +259,14 @@ mitsumi_cdrom_in(uint16_t port, void *priv) break; } - return 0xff; + return ret; } static void mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) { mcd_t *dev = (mcd_t *) priv; - cdrom_t cdrom; + cdrom_t *cdrom = calloc(1, sizeof(cdrom_t)); pclog("Mitsumi CD-ROM OUT=%03x, val=%02x\n", port, val); switch (port & 1) { @@ -348,19 +348,19 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) break; } if (!dev->cmdrd_count) - dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; + dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; return; } dev->cmd = val; dev->cmdbuf_idx = 0; dev->cmdrd_count = 0; dev->cmdbuf_count = 1; - dev->cmdbuf[0] = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; + dev->cmdbuf[0] = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; dev->data = 0; switch (val) { case CMD_GET_INFO: - if (mitsumi_cdrom_is_ready(&cdrom)) { - cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1])); + if (mitsumi_cdrom_is_ready(cdrom)) { + cdrom_get_track_buffer(cdrom, &(dev->cmdbuf[1])); dev->cmdbuf_count = 10; dev->readcount = 0; } else { @@ -369,8 +369,8 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) } break; case CMD_GET_Q: - if (mitsumi_cdrom_is_ready(&cdrom)) { - cdrom_get_q(&cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC); + if (mitsumi_cdrom_is_ready(cdrom)) { + cdrom_get_q(cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC); dev->cmdbuf_count = 11; dev->readcount = 0; } else { @@ -386,7 +386,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) break; case CMD_STOPCDDA: case CMD_STOP: - cdrom_stop(&cdrom); + cdrom_stop(cdrom); dev->drvmode = DRV_MODE_STOP; dev->cur_toc_track = 0; break; @@ -395,7 +395,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) break; case CMD_READ1X: case CMD_READ2X: - if (mitsumi_cdrom_is_ready(&cdrom)) { + if (mitsumi_cdrom_is_ready(cdrom)) { dev->readcount = 0; dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ; dev->cmdrd_count = 6; @@ -411,7 +411,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) dev->cmdbuf_count = 3; break; case CMD_EJECT: - cdrom_stop(&cdrom); + cdrom_stop(cdrom); cdrom_eject(0); dev->readcount = 0; break; @@ -440,10 +440,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) static void * mitsumi_cdrom_init(UNUSED(const device_t *info)) { - mcd_t *dev; - - dev = malloc(sizeof(mcd_t)); - memset(dev, 0x00, sizeof(mcd_t)); + mcd_t *dev = calloc(1, sizeof(mcd_t)); dev->irq = MCD_DEFAULT_IRQ; dev->dma = MCD_DEFAULT_DMA; diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index 4ed0333a7..fb0224bc6 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -134,9 +134,14 @@ plat_cdrom_get_last_block(void *local) } int -plat_cdrom_ext_medium_changed(void *local) +plat_cdrom_ext_medium_changed(UNUSED(void *local)) { +#if 0 dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + + plat_cdrom_read_toc(ioctl); +#endif + int ret = 0; dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index 4ed0333a7..fb0224bc6 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -134,9 +134,14 @@ plat_cdrom_get_last_block(void *local) } int -plat_cdrom_ext_medium_changed(void *local) +plat_cdrom_ext_medium_changed(UNUSED(void *local)) { +#if 0 dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + + plat_cdrom_read_toc(ioctl); +#endif + int ret = 0; dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); From 0931e82bd195fd4b8fe0bc774f7ba27ad043e7e1 Mon Sep 17 00:00:00 2001 From: GetDizzy Date: Sat, 11 Jan 2025 00:10:38 -0500 Subject: [PATCH 0043/1190] Add BIOS selection to Packard Bell PB450. --- src/machine/m_at_386dx_486.c | 51 +++++++++++++++++++++++++++++++++--- src/machine/machine_table.c | 3 ++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 1c35d7290..2a4b6f3c6 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -684,20 +684,64 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } +static const device_config_t pb450_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "pci10a", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "PCI 1.0A", .internal_name = "pci10a", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/OPTI802.bin", "" } }, + { .name = "PNP 1.1A", .internal_name = "pnp11a", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/PNP11A.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t pb450_device = { + .name = "Packard Bell PB450 Devices", + .internal_name = "pb450_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pb450_config +}; + int machine_at_pb450_init(const machine_t *model) { - int ret; + int ret = 0; + const char* fn; - ret = bios_load_linear("roms/machines/pb450/OPTI802.bin", - 0x000e0000, 131072, 0); + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + device_context(model->device); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + if (bios_only || !ret) return ret; machine_at_common_init_ex(model, 2); device_add(&ide_vlb_2ch_device); + /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add these? */ pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -713,6 +757,7 @@ machine_at_pb450_init(const machine_t *model) device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_sec_device); device_add(&intel_flash_bxt_device); + /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add this? */ device_add(&phoenix_486_jumper_pci_device); return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3fc3bcc8a..06aea8597 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -63,6 +63,7 @@ extern const device_t ibmxt_device; extern const device_t ibmxt86_device; extern const device_t ibmat_device; extern const device_t ibmxt286_device; +extern const device_t pb450_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -6888,7 +6889,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &pb450_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = &gd5428_vlb_onboard_device, From 3b092bcdb2ec8e2b9194c4c509a99ac9fed4b607 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 01:31:57 -0500 Subject: [PATCH 0044/1190] Cleaning --- src/config.c | 100 ++++++++++++++---------------- src/game/joystick_standard.c | 21 +++---- src/game/joystick_sw_pad.c | 25 ++++---- src/qt/qt_settingsinput.cpp | 16 ++--- src/qt/sdl_joystick.c | 108 ++++++++++++++++----------------- src/qt/win_joystick_rawinput.c | 59 +++++++++--------- 6 files changed, 155 insertions(+), 174 deletions(-) diff --git a/src/config.c b/src/config.c index 2f1561f18..5119d45ff 100644 --- a/src/config.c +++ b/src/config.c @@ -475,8 +475,6 @@ load_input_devices(void) { ini_section_t cat = ini_find_section(config, "Input devices"); char temp[512]; - int c; - int d; char *p; p = ini_section_get_string(cat, "mouse_type", NULL); @@ -495,8 +493,8 @@ load_input_devices(void) /* Workaround for ini_section_get_int returning 0 on non-integer data */ joystick_type = joystick_get_from_internal_name("2axis_2button"); else { - c = ini_section_get_int(cat, "joystick_type", 8); - switch (c) { + int js = ini_section_get_int(cat, "joystick_type", 8); + switch (js) { case JS_TYPE_2AXIS_4BUTTON: joystick_type = joystick_get_from_internal_name("2axis_4button"); break; @@ -527,25 +525,25 @@ load_input_devices(void) } else joystick_type = JS_TYPE_NONE; - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - sprintf(temp, "joystick_%i_nr", c); - joystick_state[c].plat_joystick_nr = ini_section_get_int(cat, temp, 0); + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + sprintf(temp, "joystick_%i_nr", js); + joystick_state[js].plat_joystick_nr = ini_section_get_int(cat, temp, 0); - if (joystick_state[c].plat_joystick_nr) { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) { - sprintf(temp, "joystick_%i_axis_%i", c, d); - joystick_state[c].axis_mapping[d] = ini_section_get_int(cat, temp, d); + if (joystick_state[js].plat_joystick_nr) { + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) { + sprintf(temp, "joystick_%i_axis_%i", js, axis_nr); + joystick_state[js].axis_mapping[axis_nr] = ini_section_get_int(cat, temp, axis_nr); } - for (d = 0; d < joystick_get_button_count(joystick_type); d++) { - sprintf(temp, "joystick_%i_button_%i", c, d); - joystick_state[c].button_mapping[d] = ini_section_get_int(cat, temp, d); + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) { + sprintf(temp, "joystick_%i_button_%i", js, button_nr); + joystick_state[js].button_mapping[button_nr] = ini_section_get_int(cat, temp, button_nr); } - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { - sprintf(temp, "joystick_%i_pov_%i", c, d); + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { + sprintf(temp, "joystick_%i_pov_%i", js, pov_nr); p = ini_section_get_string(cat, temp, "0, 0"); - joystick_state[c].pov_mapping[d][0] = joystick_state[c].pov_mapping[d][1] = 0; - sscanf(p, "%i, %i", &joystick_state[c].pov_mapping[d][0], - &joystick_state[c].pov_mapping[d][1]); + joystick_state[js].pov_mapping[js][pov_nr] = joystick_state[js].pov_mapping[pov_nr][1] = 0; + sscanf(p, "%i, %i", &joystick_state[js].pov_mapping[pov_nr][0], + &joystick_state[js].pov_mapping[pov_nr][1]); } } } @@ -743,11 +741,9 @@ load_ports(void) ini_section_t cat = ini_find_section(config, "Ports (COM & LPT)"); char *p; char temp[512]; - int c; - memset(temp, 0, sizeof(temp)); - for (c = 0; c < SERIAL_MAX; c++) { + for (int c = 0; c < SERIAL_MAX; c++) { sprintf(temp, "serial%d_enabled", c + 1); com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1); @@ -758,7 +754,7 @@ load_ports(void) config_log("Serial Port %d: passthrough enabled.\n\n", c + 1); } - for (c = 0; c < PARALLEL_MAX; c++) { + for (int c = 0; c < PARALLEL_MAX; c++) { sprintf(temp, "lpt%d_enabled", c + 1); lpt_ports[c].enabled = !!ini_section_get_int(cat, temp, (c == 0) ? 1 : 0); @@ -776,11 +772,10 @@ load_storage_controllers(void) ini_section_t migration_cat; char *p; char temp[512]; - int c; int min = 0; int free_p = 0; - for (c = min; c < SCSI_CARD_MAX; c++) { + for (int c = min; c < SCSI_CARD_MAX; c++) { sprintf(temp, "scsicard_%d", c + 1); p = ini_section_get_string(cat, temp, NULL); @@ -932,7 +927,7 @@ load_storage_controllers(void) ini_section_delete_var(cat, "cassette_ui_writeprot"); } - for (c = 0; c < 2; c++) { + for (int c = 0; c < 2; c++) { sprintf(temp, "cartridge_%02i_fn", c + 1); p = ini_section_get_string(cat, temp, ""); @@ -2140,50 +2135,49 @@ save_input_devices(void) ini_section_t cat = ini_find_or_create_section(config, "Input devices"); char temp[512]; char tmp2[512]; - int c; - int d; ini_section_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); if (!joystick_type) { ini_section_delete_var(cat, "joystick_type"); - for (c = 0; c < 16; c++) { - sprintf(tmp2, "joystick_%i_nr", c); + for (int js = 0; js < MAX_PLAT_JOYSTICKS; js++) { + sprintf(tmp2, "joystick_%i_nr", js); ini_section_delete_var(cat, tmp2); - for (d = 0; d < 16; d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); + for (int axis_nr = 0; axis_nr < 16; axis_nr++) { + sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); ini_section_delete_var(cat, tmp2); } - for (d = 0; d < 16; d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); + for (int button_nr = 0; button_nr < 16; button_nr++) { + sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); ini_section_delete_var(cat, tmp2); } - for (d = 0; d < 16; d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); + for (int pov_nr = 0; pov_nr < 16; pov_nr++) { + sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); ini_section_delete_var(cat, tmp2); } } } else { ini_section_set_string(cat, "joystick_type", joystick_get_internal_name(joystick_type)); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - sprintf(tmp2, "joystick_%i_nr", c); - ini_section_set_int(cat, tmp2, joystick_state[c].plat_joystick_nr); + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + sprintf(tmp2, "joystick_%i_nr", js); + ini_section_set_int(cat, tmp2, joystick_state[js].plat_joystick_nr); - if (joystick_state[c].plat_joystick_nr) { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); - ini_section_set_int(cat, tmp2, joystick_state[c].axis_mapping[d]); + if (joystick_state[js].plat_joystick_nr) { + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) { + sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); + ini_section_set_int(cat, tmp2, joystick_state[js].axis_mapping[axis_nr]); } - for (d = 0; d < joystick_get_button_count(joystick_type); d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); - ini_section_set_int(cat, tmp2, joystick_state[c].button_mapping[d]); + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) { + sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); + ini_section_set_int(cat, tmp2, joystick_state[js].button_mapping[button_nr]); } - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); - sprintf(temp, "%i, %i", joystick_state[c].pov_mapping[d][0], joystick_state[c].pov_mapping[d][1]); + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { + sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); + sprintf(temp, "%i, %i", joystick_state[js].pov_mapping[pov_nr][0], + joystick_state[js].pov_mapping[pov_nr][1]); ini_section_set_string(cat, tmp2, temp); } } @@ -2341,10 +2335,8 @@ save_ports(void) { ini_section_t cat = ini_find_or_create_section(config, "Ports (COM & LPT)"); char temp[512]; - int c; - int d; - for (c = 0; c < SERIAL_MAX; c++) { + for (int c = 0; c < SERIAL_MAX; c++) { sprintf(temp, "serial%d_enabled", c + 1); if (((c < 2) && com_ports[c].enabled) || ((c >= 2) && !com_ports[c].enabled)) ini_section_delete_var(cat, temp); @@ -2358,9 +2350,9 @@ save_ports(void) ini_section_delete_var(cat, temp); } - for (c = 0; c < PARALLEL_MAX; c++) { + for (int c = 0; c < PARALLEL_MAX; c++) { sprintf(temp, "lpt%d_enabled", c + 1); - d = (c == 0) ? 1 : 0; + int d = (c == 0) ? 1 : 0; if (lpt_ports[c].enabled == d) ini_section_delete_var(cat, temp); else diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 1d1568738..201574126 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -62,17 +62,13 @@ joystick_standard_read(UNUSED(void *priv)) { uint8_t ret = 0xf0; - if (JOYSTICK_PRESENT(0)) { - if (joystick_state[0].button[0]) - ret &= ~0x10; - if (joystick_state[0].button[1]) - ret &= ~0x20; - } - if (JOYSTICK_PRESENT(1)) { - if (joystick_state[1].button[0]) - ret &= ~0x40; - if (joystick_state[1].button[1]) - ret &= ~0x80; + for (int js = 0; js < 2; js++) { + if (JOYSTICK_PRESENT(js)) { + if (joystick_state[js].button[0]) + ret &= ~0x10; + if (joystick_state[js].button[1]) + ret &= ~0x20; + } } return ret; @@ -140,9 +136,7 @@ joystick_standard_read_axis_4button(UNUSED(void *priv), int axis) case 1: return joystick_state[0].axis[1]; case 2: - return 0; case 3: - return 0; default: return 0; } @@ -162,7 +156,6 @@ joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis) case 2: return joystick_state[0].axis[2]; case 3: - return 0; default: return 0; } diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index cab008d0a..711a5fa1e 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -119,8 +119,7 @@ sw_parity(uint16_t data) static void * sw_init(void) { - sw_data *sw = (sw_data *) malloc(sizeof(sw_data)); - memset(sw, 0, sizeof(sw_data)); + sw_data *sw = (sw_data *) calloc(1, sizeof(sw_data)); timer_add(&sw->poll_timer, sw_timer_over, sw, 0); timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0); @@ -191,24 +190,24 @@ sw_write(void *priv) sw->poll_data = 1; } - for (uint8_t c = 0; c < 4; c++) { + for (uint8_t js = 0; js < MAX_JOYSTICKS; js++) { uint16_t data = 0x3fff; - if (!JOYSTICK_PRESENT(c)) + if (!JOYSTICK_PRESENT(js)) break; - if (joystick_state[c].axis[1] < -16383) + if (joystick_state[js].axis[1] < -16383) data &= ~1; - if (joystick_state[c].axis[1] > 16383) + if (joystick_state[js].axis[1] > 16383) data &= ~2; - if (joystick_state[c].axis[0] > 16383) + if (joystick_state[js].axis[0] > 16383) data &= ~4; - if (joystick_state[c].axis[0] < -16383) + if (joystick_state[js].axis[0] < -16383) data &= ~8; - for (uint8_t b = 0; b < 10; b++) { - if (joystick_state[c].button[b]) - data &= ~(1 << (b + 4)); + for (uint8_t button_nr = 0; button_nr < 10; button_nr++) { + if (joystick_state[js].button[button_nr]) + data &= ~(1 << (button_nr + 4)); } if (sw_parity(data)) @@ -216,10 +215,10 @@ sw_write(void *priv) if (sw->poll_mode) { sw->poll_left += 5; - sw->poll_data |= (data << (c * 15 + 3)); + sw->poll_data |= (data << (js * 15 + 3)); } else { sw->poll_left += 15; - sw->poll_data |= (data << (c * 15 + 1)); + sw->poll_data |= (data << (js * 15 + 1)); } } } diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 05e44c2c0..d7b69442c 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -178,15 +178,17 @@ updateJoystickConfig(int type, int joystick_nr, QWidget *parent) joystick_state[joystick_nr].plat_joystick_nr = jc.selectedDevice(); if (joystick_state[joystick_nr].plat_joystick_nr) { - for (int c = 0; c < joystick_get_axis_count(type); c++) { - joystick_state[joystick_nr].axis_mapping[c] = get_axis(jc, c, joystick_nr); + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(type); axis_nr++) { + joystick_state[joystick_nr].axis_mapping[axis_nr] = get_axis(jc, axis_nr, joystick_nr); } - for (int c = 0; c < joystick_get_button_count(type); c++) { - joystick_state[joystick_nr].button_mapping[c] = jc.selectedButton(c); + + for (int button_nr = 0; button_nr < joystick_get_button_count(type); button_nr++) { + joystick_state[joystick_nr].button_mapping[button_nr] = jc.selectedButton(button_nr); } - for (int c = 0; c < joystick_get_pov_count(type) * 2; c += 2) { - joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(jc, c, joystick_nr); - joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(jc, c + 1, joystick_nr); + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(type) * 2; pov_nr += 2) { + joystick_state[joystick_nr].pov_mapping[pov_nr][0] = get_pov(jc, pov_nr, joystick_nr); + joystick_state[joystick_nr].pov_mapping[pov_nr][1] = get_pov(jc, pov_nr + 1, joystick_nr); } } } diff --git a/src/qt/sdl_joystick.c b/src/qt/sdl_joystick.c index d56612872..221e12078 100644 --- a/src/qt/sdl_joystick.c +++ b/src/qt/sdl_joystick.c @@ -54,28 +54,26 @@ joystick_init(void) joysticks_present = SDL_NumJoysticks(); memset(sdl_joy, 0, sizeof(sdl_joy)); - for (int c = 0; c < joysticks_present; c++) { - sdl_joy[c] = SDL_JoystickOpen(c); + for (int js = 0; js < joysticks_present; js++) { + sdl_joy[js] = SDL_JoystickOpen(js); - if (sdl_joy[c]) { - int d; + if (sdl_joy[js]) { + strncpy(plat_joystick_state[js].name, SDL_JoystickNameForIndex(js), 64); + plat_joystick_state[js].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[js]), MAX_JOY_AXES); + plat_joystick_state[js].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[js]), MAX_JOY_BUTTONS); + plat_joystick_state[js].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[js]), MAX_JOY_POVS); - strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64); - plat_joystick_state[c].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[c]), MAX_JOY_AXES); - plat_joystick_state[c].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[c]), MAX_JOY_BUTTONS); - plat_joystick_state[c].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[c]), MAX_JOY_POVS); - - for (d = 0; d < plat_joystick_state[c].nr_axes; d++) { - snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d); - plat_joystick_state[c].axis[d].id = d; + for (int axis_nr = 0; axis_nr < plat_joystick_state[js].nr_axes; axis_nr++) { + snprintf(plat_joystick_state[js].axis[axis_nr].name, sizeof(plat_joystick_state[js].axis[axis_nr].name), "Axis %i", axis_nr); + plat_joystick_state[js].axis[axis_nr].id = axis_nr; } - for (d = 0; d < plat_joystick_state[c].nr_buttons; d++) { - snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d); - plat_joystick_state[c].button[d].id = d; + for (int buttons_nr = 0; buttons_nr < plat_joystick_state[js].nr_buttons; buttons_nr++) { + snprintf(plat_joystick_state[js].button[buttons_nr].name, sizeof(plat_joystick_state[js].button[buttons_nr].name), "Button %i", buttons_nr); + plat_joystick_state[js].button[buttons_nr].id = buttons_nr; } - for (d = 0; d < plat_joystick_state[c].nr_povs; d++) { - snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d); - plat_joystick_state[c].pov[d].id = d; + for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) { + snprintf(plat_joystick_state[js].pov[pov_nr].name, sizeof(plat_joystick_state[js].pov[pov_nr].name), "POV %i", pov_nr); + plat_joystick_state[js].pov[pov_nr].id = pov_nr; } } } @@ -84,11 +82,9 @@ joystick_init(void) void joystick_close(void) { - int c; - - for (c = 0; c < joysticks_present; c++) { - if (sdl_joy[c]) - SDL_JoystickClose(sdl_joy[c]); + for (int js = 0; js < joysticks_present; js++) { + if (sdl_joy[js]) + SDL_JoystickClose(sdl_joy[js]); } } @@ -132,57 +128,55 @@ joystick_get_axis(int joystick_nr, int mapping) void joystick_process(void) { - int c; - int d; - if (!joystick_type) return; SDL_JoystickUpdate(); - for (c = 0; c < joysticks_present; c++) { - int b; + for (int js = 0; js < joysticks_present; js++) { + for (int axis_nr = 0; axis_nr < plat_joystick_state[js].nr_axes; axis_nr++) + plat_joystick_state[js].a[axis_nr] = SDL_JoystickGetAxis(sdl_joy[js], axis_nr); - for (b = 0; b < plat_joystick_state[c].nr_axes; b++) - plat_joystick_state[c].a[b] = SDL_JoystickGetAxis(sdl_joy[c], b); + for (int button_nr = 0; button_nr < plat_joystick_state[js].nr_buttons; button_nr++) + plat_joystick_state[js].b[button_nr] = SDL_JoystickGetButton(sdl_joy[js], button_nr); - for (b = 0; b < plat_joystick_state[c].nr_buttons; b++) - plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b); + for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) + plat_joystick_state[js].p[pov_nr] = SDL_JoystickGetHat(sdl_joy[js], pov_nr); - for (b = 0; b < plat_joystick_state[c].nr_povs; b++) - plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b); - // pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); +#if 0 + pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, joystick_state[js].x, joystick_state[js].y, joystick_state[js].b[0], joystick_state[js].b[1], joysticks_present); +#endif } - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - if (joystick_state[c].plat_joystick_nr) { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + if (joystick_state[js].plat_joystick_nr) { + int joystick_nr = joystick_state[js].plat_joystick_nr - 1; - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { - int x, y; - double angle, magnitude; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]); - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; - angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); - magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { + int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); + int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); + double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + double magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) - joystick_state[c].pov[d] = -1; + joystick_state[js].pov[pov_nr] = -1; else - joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; } } else { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = 0; + + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = 0; + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) + joystick_state[js].pov[pov_nr] = -1; } } } diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index bb05c3f5c..811425a98 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -412,7 +412,7 @@ win_joystick_handle(PRAWINPUT raw) /* Read buttons */ USAGE usage_list[128] = { 0 }; ULONG usage_length = plat_joystick_state[j].nr_buttons; - memset(plat_joystick_state[j].b, 0, 32 * sizeof(int)); + memset(plat_joystick_state[j].b, 0, MAX_JOY_BUTTONS * sizeof(int)); r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length, raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); @@ -425,8 +425,8 @@ win_joystick_handle(PRAWINPUT raw) } /* Read axes */ - for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) { - const struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; + for (int axis_nr = 0; axis_nr < plat_joystick_state[j].nr_axes; axis_nr++) { + const struct raw_axis_t *axis = &raw_joystick_state[j].axis[axis_nr]; ULONG uvalue = 0; LONG value = 0; LONG center = (axis->max - axis->min + 1) / 2; @@ -453,15 +453,15 @@ win_joystick_handle(PRAWINPUT raw) value = value * 32768 / center; } - plat_joystick_state[j].a[a] = value; + plat_joystick_state[j].a[axis_nr] = value; #if 0 - joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); + joystick_log("%s %-06d ", plat_joystick_state[j].axis[axis_nr].name, plat_joystick_state[j].a[axis_nr]); #endif } /* read povs */ - for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) { - const struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; + for (int pov_nr = 0; pov_nr < plat_joystick_state[j].nr_povs; pov_nr++) { + const struct raw_pov_t *pov = &raw_joystick_state[j].pov[pov_nr]; ULONG uvalue = 0; LONG value = -1; @@ -474,10 +474,10 @@ win_joystick_handle(PRAWINPUT raw) value %= 36000; } - plat_joystick_state[j].p[p] = value; + plat_joystick_state[j].p[pov_nr] = value; #if 0 - joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); + joystick_log("%s %-3d ", plat_joystick_state[j].pov[pov_nr].name, plat_joystick_state[j].p[pov_nr]); #endif } #if 0 @@ -508,44 +508,45 @@ joystick_get_axis(int joystick_nr, int mapping) void joystick_process(void) { - int d; - if (joystick_type == JS_TYPE_NONE) return; - for (int c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - if (joystick_state[c].plat_joystick_nr) { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + if (joystick_state[js].plat_joystick_nr) { + int joystick_nr = joystick_state[js].plat_joystick_nr - 1; - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]); - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { int x; int y; double angle; double magnitude; - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); + y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) - joystick_state[c].pov[d] = -1; + joystick_state[js].pov[pov_nr] = -1; else - joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; } } else { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = 0; + + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = 0; + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) + joystick_state[js].pov[pov_nr] = -1; } } } From 6ec9c33940bbe864fb58f670fb1925d28cc32241 Mon Sep 17 00:00:00 2001 From: GetDizzy Date: Sat, 11 Jan 2025 02:19:32 -0500 Subject: [PATCH 0045/1190] Formatting fixes. --- src/machine/m_at_386dx_486.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 2a4b6f3c6..43ba9a6d9 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -707,10 +707,10 @@ static const device_config_t pb450_config[] = { }; const device_t pb450_device = { - .name = "Packard Bell PB450 Devices", + .name = "Packard Bell PB450 Devices", .internal_name = "pb450_device", - .flags = 0, - .local = 0, + .flags = 0, + .local = 0, .init = NULL, .close = NULL, .reset = NULL, From 8cb220d84b249851202489ee3f69e7c12492d5ba Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 03:39:15 -0500 Subject: [PATCH 0046/1190] Corrections --- src/config.c | 8 ++++---- src/qt/sdl_joystick.c | 13 +++++++++---- src/qt/win_joystick_rawinput.c | 14 ++++---------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/config.c b/src/config.c index 5119d45ff..24efcf264 100644 --- a/src/config.c +++ b/src/config.c @@ -541,7 +541,7 @@ load_input_devices(void) for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { sprintf(temp, "joystick_%i_pov_%i", js, pov_nr); p = ini_section_get_string(cat, temp, "0, 0"); - joystick_state[js].pov_mapping[js][pov_nr] = joystick_state[js].pov_mapping[pov_nr][1] = 0; + joystick_state[js].pov_mapping[pov_nr][0] = joystick_state[js].pov_mapping[pov_nr][1] = 0; sscanf(p, "%i, %i", &joystick_state[js].pov_mapping[pov_nr][0], &joystick_state[js].pov_mapping[pov_nr][1]); } @@ -2145,15 +2145,15 @@ save_input_devices(void) sprintf(tmp2, "joystick_%i_nr", js); ini_section_delete_var(cat, tmp2); - for (int axis_nr = 0; axis_nr < 16; axis_nr++) { + for (int axis_nr = 0; axis_nr < MAX_JOY_AXES; axis_nr++) { sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); ini_section_delete_var(cat, tmp2); } - for (int button_nr = 0; button_nr < 16; button_nr++) { + for (int button_nr = 0; button_nr < MAX_JOY_BUTTONS; button_nr++) { sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); ini_section_delete_var(cat, tmp2); } - for (int pov_nr = 0; pov_nr < 16; pov_nr++) { + for (int pov_nr = 0; pov_nr < MAX_JOY_POVS; pov_nr++) { sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); ini_section_delete_var(cat, tmp2); } diff --git a/src/qt/sdl_joystick.c b/src/qt/sdl_joystick.c index 221e12078..03159ba7f 100644 --- a/src/qt/sdl_joystick.c +++ b/src/qt/sdl_joystick.c @@ -67,9 +67,9 @@ joystick_init(void) snprintf(plat_joystick_state[js].axis[axis_nr].name, sizeof(plat_joystick_state[js].axis[axis_nr].name), "Axis %i", axis_nr); plat_joystick_state[js].axis[axis_nr].id = axis_nr; } - for (int buttons_nr = 0; buttons_nr < plat_joystick_state[js].nr_buttons; buttons_nr++) { - snprintf(plat_joystick_state[js].button[buttons_nr].name, sizeof(plat_joystick_state[js].button[buttons_nr].name), "Button %i", buttons_nr); - plat_joystick_state[js].button[buttons_nr].id = buttons_nr; + for (int button_nr = 0; button_nr < plat_joystick_state[js].nr_buttons; button_nr++) { + snprintf(plat_joystick_state[js].button[button_nr].name, sizeof(plat_joystick_state[js].button[button_nr].name), "Button %i", button_nr); + plat_joystick_state[js].button[button_nr].id = button_nr; } for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) { snprintf(plat_joystick_state[js].pov[pov_nr].name, sizeof(plat_joystick_state[js].pov[pov_nr].name), "POV %i", pov_nr); @@ -143,7 +143,12 @@ joystick_process(void) plat_joystick_state[js].p[pov_nr] = SDL_JoystickGetHat(sdl_joy[js], pov_nr); #if 0 - pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, joystick_state[js].x, joystick_state[js].y, joystick_state[js].b[0], joystick_state[js].b[1], joysticks_present); + pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, + joystick_state[js].x, + joystick_state[js].y, + joystick_state[js].b[0], + joystick_state[js].b[1], + joysticks_present); #endif } diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index 811425a98..c293dcaca 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -522,16 +522,10 @@ joystick_process(void) joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { - int x; - int y; - double angle; - double magnitude; - - x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); - y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); - - angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); - magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); + int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); + double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + double magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) joystick_state[js].pov[pov_nr] = -1; From f9ac37decd8cafc870a6927dd0a68ce1dd005872 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 04:04:39 -0500 Subject: [PATCH 0047/1190] Missed fix --- src/game/joystick_sw_pad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 711a5fa1e..238e84d11 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -190,7 +190,7 @@ sw_write(void *priv) sw->poll_data = 1; } - for (uint8_t js = 0; js < MAX_JOYSTICKS; js++) { + for (uint8_t js = 0; js < 4; js++) { uint16_t data = 0x3fff; if (!JOYSTICK_PRESENT(js)) From 7d3d15853de68f8fbcb37844498cae3839b608c4 Mon Sep 17 00:00:00 2001 From: GetDizzy Date: Sat, 11 Jan 2025 04:11:54 -0500 Subject: [PATCH 0048/1190] Remove outdated TODOs. --- src/machine/m_at_386dx_486.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 43ba9a6d9..d3c7a21d2 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -741,7 +741,6 @@ machine_at_pb450_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ide_vlb_2ch_device); - /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add these? */ pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -757,7 +756,6 @@ machine_at_pb450_init(const machine_t *model) device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_sec_device); device_add(&intel_flash_bxt_device); - /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add this? */ device_add(&phoenix_486_jumper_pci_device); return ret; From 49f5c358d85feb6850a5d656b23afcef809ceae8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 04:37:18 -0500 Subject: [PATCH 0049/1190] Revert two fixes as batty has that covered --- src/cdrom/cdrom_image_backend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index ad1756055..9d065a0cb 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1195,7 +1195,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void) cdi_insert_track(cdi, session, 0xa0 + i); + (void *) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); @@ -1393,7 +1393,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void) cdi_insert_track(cdi, session, 0xa0 + i); + (void *) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); From af12421a5baea3ac8d6448ee21bb8283279e94f7 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sat, 11 Jan 2025 22:45:17 +0100 Subject: [PATCH 0050/1190] Update machine.h --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index ad8b47638..0cd3564ee 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -807,6 +807,7 @@ extern int machine_at_p2bls_init(const machine_t *); extern int machine_at_lgibmx7g_init(const machine_t *); extern int machine_at_p3bf_init(const machine_t *); extern int machine_at_bf6_init(const machine_t *); +extern int machine_at_bx6_init(const machine_t *); extern int machine_at_ax6bc_init(const machine_t *); extern int machine_at_atc6310bxii_init(const machine_t *); extern int machine_at_686bx_init(const machine_t *); From c64c5bcbcdf509b55e54c5ac0c06b653c681dccb Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sat, 11 Jan 2025 23:04:17 +0100 Subject: [PATCH 0051/1190] Update m_at_slot1.c --- src/machine/m_at_slot1.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 415998364..a3ff921e3 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -359,6 +359,37 @@ machine_at_bf6_init(const machine_t *model) return ret; } +int +machine_at_bx6_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/bx6/BX6_EG.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977f_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + + return ret; +} + int machine_at_ax6bc_init(const machine_t *model) { From e00d7b8e1d1ad1044f0dbbc2803acf2c7ffec646 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sat, 11 Jan 2025 23:18:49 +0100 Subject: [PATCH 0052/1190] Update machine_table.c --- src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 06aea8597..4947b8898 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14632,6 +14632,47 @@ const machine_t machines[] = { }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ + +{ + .name = "[i440LX] ABIT BX6", + .internal_name = "bx6", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_bx6_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1500, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .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 + }, + { .name = "[i440BX] ABIT BF6", .internal_name = "bf6", From fabe71150cb600ef7c290f93f5416c4b6c64e7d9 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 18:13:56 -0500 Subject: [PATCH 0053/1190] Various improvements & Cleanups Some ported from ANightly's work --- src/device/CMakeLists.txt | 2 +- src/device/serial_passthrough.c | 8 ++--- src/device/unittester.c | 6 ++-- src/disk/hdc_xta.c | 8 ++--- src/disk/hdc_xtide.c | 4 +-- src/floppy/fdd_pcjs.c | 4 +++ src/include/86box/86box.h | 5 +++ src/machine/m_at_286_386sx.c | 4 --- src/machine/m_ps1.c | 2 +- src/network/CMakeLists.txt | 5 ++- src/network/net_rtl8139.c | 7 ++-- src/network/network.c | 2 ++ src/qt/qt_harddiskdialog.cpp | 12 +++++-- src/qt/qt_vulkanrenderer.cpp | 9 ++--- src/qt/qt_vulkanrenderer.hpp | 6 +++- src/qt/qt_vulkanwindowrenderer.cpp | 38 ++++++++++++++++++-- src/qt/qt_vulkanwindowrenderer.hpp | 2 +- src/qt/qt_winrawinputfilter.cpp | 40 ++++++++++++--------- src/qt/win_serial_passthrough.c | 2 +- src/scsi/scsi_aha154x.c | 2 +- src/scsi/scsi_ncr53c400.c | 2 +- src/sound/midi_fluidsynth.c | 33 ++++++----------- src/sound/resid-fp/siddefs-fp.h | 4 +++ src/sound/snd_opl2board.c | 4 +-- src/sound/snd_pas16.c | 1 + src/video/vid_et3000.c | 23 ++++++------ src/video/vid_et4000.c | 4 +-- src/video/vid_ht216.c | 57 +++++++++++------------------- src/video/vid_mga.c | 22 ++++-------- 29 files changed, 178 insertions(+), 140 deletions(-) diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index ae3fbf3f2..c9da627ef 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -57,7 +57,7 @@ add_library(dev OBJECT mouse_microtouch_touchscreen.c ) -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC) target_link_libraries(86Box atomic) endif() diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index eec9fa62a..ed5abe618 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -282,8 +282,8 @@ static const device_config_t serial_passthrough_config[] = { .type = CONFIG_SERPORT, .default_string = "", .file_filter = NULL, - .spinner = {}, - .selection = {} + .spinner = { 0 }, + .selection = { { 0 } } }, #ifdef _WIN32 { @@ -292,8 +292,8 @@ static const device_config_t serial_passthrough_config[] = { .type = CONFIG_STRING, .default_string = "\\\\.\\pipe\\86Box\\test", .file_filter = NULL, - .spinner = {}, - .selection = {} + .spinner = { 0 }, + .selection = { { 0 } } }, #endif { diff --git a/src/device/unittester.c b/src/device/unittester.c index e52f3b56f..614438fcb 100644 --- a/src/device/unittester.c +++ b/src/device/unittester.c @@ -104,8 +104,8 @@ struct unittester_state { /* 0x04: Exit */ uint8_t exit_code; }; -static struct unittester_state unittester; -static const struct unittester_state unittester_defaults = { +static struct unittester_state unittester; +static struct unittester_state unittester_defaults = { .trigger_port = 0x0080, .iobase_port = 0xFFFF, .fsm1 = UT_FSM1_WAIT_8, @@ -589,7 +589,7 @@ unittester_trigger_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) static void * unittester_init(UNUSED(const device_t *info)) { - unittester = (struct unittester_state) unittester_defaults; + unittester = unittester_defaults; unittester_exit_enabled = !!device_get_config_int("exit_enabled"); diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index a4ef45c43..a65ab5c69 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1114,7 +1114,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "", .default_int = 0x0320, .file_filter = "", - .spinner = { 0 }, /*W2*/ + .spinner = { 0 }, .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, @@ -1128,7 +1128,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "", .default_int = 5, .file_filter = "", - .spinner = { 0 }, /*W3*/ + .spinner = { 0 }, .selection = { { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 4", .value = 4 }, @@ -1142,7 +1142,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "", .default_int = 0xc8000, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, @@ -1156,7 +1156,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "rev_1", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Revision 1.0", .internal_name = "rev_1", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_1_BIOS_FILE, "" } }, diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 9899e2a0f..b324b4d32 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -238,7 +238,7 @@ static const device_config_t xtide_config[] = { .default_string = "xt", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } }, @@ -260,7 +260,7 @@ static const device_config_t xtide_at_config[] = { .default_string = "at", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } }, diff --git a/src/floppy/fdd_pcjs.c b/src/floppy/fdd_pcjs.c index b7b3cc69d..76f8ca7dc 100644 --- a/src/floppy/fdd_pcjs.c +++ b/src/floppy/fdd_pcjs.c @@ -20,7 +20,11 @@ #include #include #include +#ifndef _MSC_VER #include +#else +#include +#endif #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index ffa670b7e..503518a2b 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -191,8 +191,13 @@ extern void pclog_ex(const char *fmt, va_list); extern void fatal_ex(const char *fmt, va_list); #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 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/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index ead31c21c..c3dc5c772 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -222,10 +222,6 @@ machine_at_ataripc4_init(const machine_t *model) ret = bios_load_interleaved("roms/machines/ataripc4/AMI_PC4X_1.7_EVEN.BIN", "roms/machines/ataripc4/AMI_PC4X_1.7_ODD.BIN", -#if 0 - ret = bios_load_interleaved("roms/machines/ataripc4/ami_pc4x_1.7_even.bin", - "roms/machines/ataripc4/ami_pc4x_1.7_odd.bin", -#endif 0x000f0000, 65536, 0); if (bios_only || !ret) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 42bc49de2..3c9f1819f 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -252,7 +252,7 @@ static const device_config_t ps1_2011_config[] = { .default_string = "english_us", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "English (US)", .internal_name = "english_us", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/FC0000_US.BIN", "" } }, diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 0d42cbd8d..71f41f059 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -41,7 +41,10 @@ pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) target_link_libraries(86Box PkgConfig::SLIRP) if(WIN32) - target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi iconv) + target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi) + if (NOT MSVC) + target_link_libraries(PkgConfig::SLIRP INTERFACE iconv) + endif() if(STATIC_BUILD) add_compile_definitions(LIBSLIRP_STATIC) endif() diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index f04f9b7a3..0dac29a8c 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -28,6 +28,9 @@ #include #include #include +#ifdef _MVC_VER +#include +#endif #include #define HAVE_STDARG_H #include <86box/86box.h> @@ -531,14 +534,14 @@ rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) if (size > wrapped) { dma_bm_write(s->RxBuf + s->RxBufAddr, - buf, size - wrapped, 1); + (uint8_t *) buf, size - wrapped, 1); } /* reset buffer pointer */ s->RxBufAddr = 0; dma_bm_write(s->RxBuf + s->RxBufAddr, - buf + (size - wrapped), wrapped, 1); + (uint8_t *) buf + (size - wrapped), wrapped, 1); s->RxBufAddr = wrapped; diff --git a/src/network/network.c b/src/network/network.c index e60f50eb1..f4b03ee79 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -54,7 +54,9 @@ #include #include #include +#ifndef _MSC_VER #include +#endif #include #define HAVE_STDARG_H #include <86box/86box.h> diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index f2326ef8b..2acaaeacc 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -230,7 +230,11 @@ static HarddiskDialog *callbackPtr = nullptr; static MVHDGeom create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, uint8_t heads, uint8_t spt) { - MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; + MVHDGeom _86box_geometry = { + .cyl = cyl, + .heads = heads, + .spt = spt + }; MVHDGeom vhd_geometry; adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); @@ -256,7 +260,11 @@ create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, static MVHDGeom create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize) { - MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; + MVHDGeom _86box_geometry = { + .cyl = cyl, + .heads = heads, + .spt = spt + }; MVHDGeom vhd_geometry; adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); int vhd_error = 0; diff --git a/src/qt/qt_vulkanrenderer.cpp b/src/qt/qt_vulkanrenderer.cpp index 9227cdcb3..13728b82e 100644 --- a/src/qt/qt_vulkanrenderer.cpp +++ b/src/qt/qt_vulkanrenderer.cpp @@ -30,10 +30,11 @@ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ +#include "qt_vulkanrenderer.hpp" #include #include -#include "qt_vulkanrenderer.hpp" + #if QT_CONFIG(vulkan) # include @@ -676,7 +677,7 @@ VulkanRenderer2::initResources() v_texcoord = texcoord; gl_Position = ubuf.mvp * position; } -#endif +#endif /* 0 */ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv")); #if 0 #version 440 @@ -691,7 +692,7 @@ VulkanRenderer2::initResources() { fragColor = texture(tex, v_texcoord); } -#endif +#endif /* 0 */ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv")); // Graphics pipeline @@ -1009,4 +1010,4 @@ VulkanRenderer2::startNextFrame() m_window->frameReady(); m_window->requestUpdate(); // render continuously, throttled by the presentation rate } -#endif +#endif /* QT_CONFIG(vulkan) */ diff --git a/src/qt/qt_vulkanrenderer.hpp b/src/qt/qt_vulkanrenderer.hpp index d4580d848..2c131e5d7 100644 --- a/src/qt/qt_vulkanrenderer.hpp +++ b/src/qt/qt_vulkanrenderer.hpp @@ -31,6 +31,8 @@ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ +#ifndef VULKANRENDERER_HPP +#define VULKANRENDERER_HPP #include #include @@ -90,4 +92,6 @@ private: QMatrix4x4 m_proj; }; -#endif +#endif // QT_CONFIG(vulkan) + +#endif // VULKANRENDERER_HPP diff --git a/src/qt/qt_vulkanwindowrenderer.cpp b/src/qt/qt_vulkanwindowrenderer.cpp index 60ad5be96..ab46b5961 100644 --- a/src/qt/qt_vulkanwindowrenderer.cpp +++ b/src/qt/qt_vulkanwindowrenderer.cpp @@ -1,3 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2022 Cacodemon345 +** Copyright (C) 2017 The Qt Company Ltd. +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ #include "qt_vulkanwindowrenderer.hpp" #include @@ -697,7 +729,7 @@ public: # if VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162 case VK_ERROR_INCOMPATIBLE_VERSION_KHR: return "VK_ERROR_INCOMPATIBLE_VERSION_KHR"; -# endif +# endif /* VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162 */ case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; case VK_ERROR_NOT_PERMITTED_EXT: @@ -788,7 +820,7 @@ public: m_devFuncs->vkDeviceWaitIdle(m_window->device()); } }; -# endif +# endif /* 0*/ VulkanWindowRenderer::VulkanWindowRenderer(QWidget *parent) : QVulkanWindow(parent->windowHandle()) @@ -851,4 +883,4 @@ VulkanWindowRenderer::getBuffers() { return std::vector { std::make_tuple((uint8_t *) renderer->mappedPtr, &this->buf_usage[0]) }; } -#endif +#endif /* QT_CONFIG(vulkan) */ diff --git a/src/qt/qt_vulkanwindowrenderer.hpp b/src/qt/qt_vulkanwindowrenderer.hpp index 828d091e6..de9f46b6f 100644 --- a/src/qt/qt_vulkanwindowrenderer.hpp +++ b/src/qt/qt_vulkanwindowrenderer.hpp @@ -35,6 +35,6 @@ private: VulkanRenderer2 *renderer; }; -#endif +#endif // QT_CONFIG(vulkan) #endif // VULKANWINDOWRENDERER_HPP diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index a1da0af61..73e8a2995 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -56,14 +56,18 @@ std::unique_ptr WindowsRawInputFilter::Register(MainWindow *window) { RAWINPUTDEVICE rid[2] = { - {.usUsagePage = 0x01, - .usUsage = 0x06, - .dwFlags = RIDEV_NOHOTKEYS, - .hwndTarget = nullptr}, - { .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = 0, - .hwndTarget = nullptr} + { + .usUsagePage = 0x01, + .usUsage = 0x06, + .dwFlags = RIDEV_NOHOTKEYS, + .hwndTarget = nullptr + }, + { + .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = 0, + .hwndTarget = nullptr + } }; if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE)) @@ -89,14 +93,18 @@ WindowsRawInputFilter::WindowsRawInputFilter(MainWindow *window) WindowsRawInputFilter::~WindowsRawInputFilter() { RAWINPUTDEVICE rid[2] = { - {.usUsagePage = 0x01, - .usUsage = 0x06, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL}, - { .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL} + { + .usUsagePage = 0x01, + .usUsage = 0x06, + .dwFlags = RIDEV_REMOVE, + .hwndTarget = NULL + }, + { + .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = RIDEV_REMOVE, + .hwndTarget = NULL + } }; if (hook_enabled) diff --git a/src/qt/win_serial_passthrough.c b/src/qt/win_serial_passthrough.c index 2b77bd219..c1802ce73 100644 --- a/src/qt/win_serial_passthrough.c +++ b/src/qt/win_serial_passthrough.c @@ -88,7 +88,7 @@ plat_serpt_set_params(void *priv) const serial_passthrough_t *dev = (serial_passthrough_t *) priv; if (dev->mode == SERPT_MODE_HOSTSER) { - DCB serialattr = {}; + DCB serialattr = { 0 }; GetCommState((HANDLE) dev->master_fd, &serialattr); #define BAUDRATE_RANGE(baud_rate, min, max) \ if (baud_rate >= min && baud_rate < max) { \ diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 58779e7ac..937213b85 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1421,7 +1421,7 @@ static const device_config_t aha_154xcp_config[] = { .default_string = "v1_02_en", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 1.02 (English)", .internal_name = "v1_02_en", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp102.bin", diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index bea918660..6622ec59a 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -841,7 +841,7 @@ static const device_config_t rt1000b_config[] = { .default_string = "v8_10r", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 8.10R", .internal_name = "v8_10r", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_810R_ROM, "" } }, diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index ccedb8c41..51383bdcf 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -330,8 +330,7 @@ static const device_config_t fluidsynth_config[] = { .name = "output_gain", .description = "Output Gain", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -347,8 +346,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_voices", .description = "Chorus Voices", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 99 }, @@ -358,8 +356,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_level", .description = "Chorus Level", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -369,8 +366,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_speed", .description = "Chorus Speed", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 10, .max = 500 }, @@ -380,8 +376,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_depth", .description = "Chorus Depth", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 2560 }, @@ -391,8 +386,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_waveform", .description = "Chorus Waveform", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "Sine", .value = 0 @@ -414,8 +408,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_room_size", .description = "Reverb Room Size", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -425,8 +418,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_damping", .description = "Reverb Damping", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -436,8 +428,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_width", .description = "Reverb Width", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 1000 }, @@ -447,8 +438,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_level", .description = "Reverb Level", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -458,8 +448,7 @@ static const device_config_t fluidsynth_config[] = { .name = "interpolation", .description = "Interpolation Method", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "None", .value = 0 diff --git a/src/sound/resid-fp/siddefs-fp.h b/src/sound/resid-fp/siddefs-fp.h index 9411b1694..22e40f4fb 100644 --- a/src/sound/resid-fp/siddefs-fp.h +++ b/src/sound/resid-fp/siddefs-fp.h @@ -24,7 +24,11 @@ #define RESID_BRANCH_HINTS true // Compiler specifics. +#ifndef _MSC_VER #define HAVE_BUILTIN_EXPECT true +#else +#define HAVE_BUILTIN_EXPECT false +#endif // Branch prediction macros, lifted off the Linux kernel. #if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT diff --git a/src/sound/snd_opl2board.c b/src/sound/snd_opl2board.c index dea7752d0..f1bda3398 100644 --- a/src/sound/snd_opl2board.c +++ b/src/sound/snd_opl2board.c @@ -173,8 +173,8 @@ static const device_config_t opl2board_config[] = { .type = CONFIG_SERPORT, .default_string = "", .file_filter = NULL, - .spinner = {}, - .selection = {} + .spinner = { 0 }, + .selection = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index fab2a6a75..ed82afebf 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -86,6 +86,7 @@ * Copyright 2008-2024 Sarah Walker. * Copyright 2024 Miran Grca. */ +#define _USE_MATH_DEFINES #include #include #include diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index a7d2a749f..45a2fc199 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -548,17 +548,20 @@ et3000_available(void) } static const device_config_t et3000_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { .description = "256 KB", - .value = 256 }, - { .description = "512 KB", - .value = 512 }, - { .description = "" } } }, + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + } + }, { .type = CONFIG_END } + // clang-format on }; const device_t et3000_isa_device = { diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index caf8d03c7..ad8cf5c46 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -972,7 +972,7 @@ static const device_config_t et4000_tc6058af_config[] = { .default_string = "v1_10", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 1.10", .internal_name = "v1_10", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 32768, .files = { TC6058AF_BIOS_ROM_PATH, "" } }, @@ -1019,7 +1019,7 @@ static const device_config_t et4000_bios_config[] = { .default_string = "v8_01", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 8.01", .internal_name = "v8_01", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 32768, .files = { BIOS_ROM_PATH, "" } }, diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index c1f5cbeaf..a249631ee 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1701,52 +1701,37 @@ ht216_force_redraw(void *priv) ht216->svga.fullchange = changeframecount; } +// clang-format off static const device_config_t v7_vga_1024i_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { .description = "256 KB", - .value = 256 }, - { .description = "512 KB", - .value = 512 }, - { .description = "" } } }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + } + }, { .type = CONFIG_END } }; -// clang-format off static const device_config_t ht216_32_standalone_config[] = { { - .name = "monitor_type", + .name = "monitor_type", .description = "Monitor type", - .type = CONFIG_SELECTION, + .type = CONFIG_SELECTION, .default_int = 0x18, - .selection = { - { - .description = "Mono Interlaced", - .value = 0x00 - }, - { - .description = "Mono Non-Interlaced", - .value = 0x08 - }, - { - .description = "Color Interlaced", - .value = 0x10 - }, - { - .description = "Color Non-Interlaced", - .value = 0x18 - }, - { - .description = "" - } + .selection = { + { .description = "Mono Interlaced", .value = 0x00 }, + { .description = "Mono Non-Interlaced", .value = 0x08 }, + { .description = "Color Interlaced", .value = 0x10 }, + { .description = "Color Non-Interlaced", .value = 0x18 }, + { .description = "" } } }, - { - .type = CONFIG_END - } + { .type = CONFIG_END } }; // clang-format on diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 1bdbecdf6..2b9e63af4 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -6851,8 +6851,7 @@ static const device_config_t mystique_config[] = { .name = "memory", .description = "Memory size", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "2 MB", .value = 2 @@ -6865,15 +6864,11 @@ static const device_config_t mystique_config[] = { .description = "8 MB", .value = 8 }, - { - .description = "" - } + { .description = "" } }, .default_int = 8 }, - { - .type = CONFIG_END - } + { .type = CONFIG_END } // clang-format on }; @@ -6883,8 +6878,7 @@ static const device_config_t millennium_ii_config[] = { .name = "memory", .description = "Memory size", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "4 MB", .value = 4 @@ -6897,15 +6891,11 @@ static const device_config_t millennium_ii_config[] = { .description = "16 MB", .value = 16 }, - { - .description = "" - } + { .description = "" } }, .default_int = 8 }, - { - .type = CONFIG_END - } + { .type = CONFIG_END } // clang-format on }; From abb066f6ef2efa9c83daad8ec50bcfb1fbcc29d8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 21 Dec 2022 04:17:04 -0500 Subject: [PATCH 0054/1190] Initial Micro Solutions CompatiCard support --- src/floppy/CMakeLists.txt | 1 + src/floppy/fdc.c | 21 ++- src/floppy/fdc_compaticard.c | 355 +++++++++++++++++++++++++++++++++++ src/include/86box/fdc_ext.h | 4 + 4 files changed, 372 insertions(+), 9 deletions(-) create mode 100644 src/floppy/fdc_compaticard.c diff --git a/src/floppy/CMakeLists.txt b/src/floppy/CMakeLists.txt index d86ff4bc2..c16ca06f4 100644 --- a/src/floppy/CMakeLists.txt +++ b/src/floppy/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(fdd OBJECT fdd.c fdc.c + fdc_compaticard.c fdc_magitronic.c fdc_monster.c fdc_pii15xb.c diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 546174c57..4cb2a8491 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -103,15 +103,18 @@ typedef const struct { 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 }, - { &fdc_monster_device }, - { NULL } + { &device_none }, + { &device_internal }, + { &fdc_b215_device }, + { &fdc_pii151b_device }, + { &fdc_pii158b_device }, + { &fdc_compaticard_i_device }, + { &fdc_compaticard_ii_device }, +#if 0 + { &fdc_compaticard_iv_device }, +#endif + { &fdc_monster_device }, + { NULL } // clang-format on }; diff --git a/src/floppy/fdc_compaticard.c b/src/floppy/fdc_compaticard.c new file mode 100644 index 000000000..a693c9cb2 --- /dev/null +++ b/src/floppy/fdc_compaticard.c @@ -0,0 +1,355 @@ +/* + * 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 Micro Solutions CompatiCard I/II/IV. + * + * Authors: Jasmine Iwanek, + * + * Copyright 2022-2025 Jasmine Iwanek. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/machine.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> + +#define DEVICE_COMPATICARD_I 0 +#define DEVICE_COMPATICARD_II 1 +#define DEVICE_COMPATICARD_IV 2 + +#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) +#define ROM_COMPATICARD_IV "roms/floppy/compaticard/ccivbios1.05.bin" + +#define CR_2_MASK 0x2f /* 00101111b */ + +typedef struct compaticard_s { + rom_t bios_rom; + fdc_t *fdc; + /* + * 7 - Reserved - Set to 0 + * 6 - Reserved - Set to 0 + * 5 - Programmable Pin 2 Logic I sets Pin 2 low (TODO) + * 4 - Reserved - Set to 0 + * 3-0 - Data Transfer Rate Select (TODO) + * 0000---250 Kbps + * 0001-300 Kbps + * 1111-500 Kbps + */ + uint8_t cr_2; +} compaticard_t; + +static void +compaticard_out(uint16_t port, uint8_t val, void *priv) +{ + compaticard_t *dev = (compaticard_t *) priv; + + dev->cr_2 = (val & CR_2_MASK); +} + +static uint8_t +compaticard_in(uint16_t port, void *priv) +{ + compaticard_t *dev = (compaticard_t *) priv; + uint8_t ret = (dev->cr_2 &CR_2_MASK); + + return ret; +} + +static void +compaticard_close(void *priv) +{ + compaticard_t *dev = (compaticard_t *) priv; + + free(dev); +} + +static void * +compaticard_init(const device_t *info) +{ + compaticard_t *dev = calloc(1, sizeof(compaticard_t)); + uint16_t base_addr = device_get_config_hex16("base"); + uint8_t irq = 6; + uint8_t dma = 2; + uint16_t cr2_addr = 0x7f2; // Control Register 2 + + // CompatiCard II & IV have configurable IRQ and DMA + if (info->local >= DEVICE_COMPATICARD_II) { + irq = device_get_config_int("irq"); + dma = device_get_config_int("dma"); + } + + // Only on CompatiCard IV + if ((info->local == DEVICE_COMPATICARD_IV) && (BIOS_ADDR != 0)) + rom_init(&dev->bios_rom, ROM_COMPATICARD_IV, BIOS_ADDR, 0x2000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL); + + // TODO: Make this neater + switch (base_addr) { + case FDC_SECONDARY_ADDR: + cr2_addr = 0x772; + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_sec_device); + else + dev->fdc = device_add(&fdc_xt_sec_device); + break; + + case FDC_TERTIARY_ADDR: + cr2_addr = 0x762; + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_ter_device); + else + dev->fdc = device_add(&fdc_xt_ter_device); + break; + + case FDC_QUATERNARY_ADDR: + cr2_addr = 0x7e2; + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_qua_device); + else + dev->fdc = device_add(&fdc_xt_qua_device); + break; + + default: + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_device); + else + dev->fdc = device_add(&fdc_xt_device); + break; + } + + fdc_set_irq(dev->fdc, irq); + fdc_set_dma_ch(dev->fdc, dma); + + io_sethandler(cr2_addr, 0x0001, + compaticard_in, NULL, NULL, + compaticard_out, NULL, NULL, + dev); + + return dev; +} + +static int compaticard_iv_available(void) +{ + return rom_present(ROM_COMPATICARD_IV); +} + +static const device_config_t compaticard_i_config[] = { +// clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x3f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x3f0", .value = 0x3f0 }, + { .description = "0x370", .value = 0x370 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +static const device_config_t compaticard_ii_config[] = { +// clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x3f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x3f0", .value = 0x3f0 }, + { .description = "0x370", .value = 0x370 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +static const device_config_t compaticard_iv_config[] = { +// clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x3f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x3f0", .value = 0x3f0 }, + { .description = "0x370", .value = 0x370 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + } + }, + { + .name = "bios_addr", + .description = "BIOS Address:", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xce000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "CE00H", .value = 0xce000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DE00H", .value = 0xde000 }, + { .description = "E000H", .value = 0xe0000 }, + { .description = "E800H", .value = 0xe8000 }, + { .description = "EE00H", .value = 0xee000 }, + { .description = "" } + } + }, +#if 0 + { + .name = "autoboot_enabled", + .description = "Enable Autoboot", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +const device_t fdc_compaticard_i_device = { + .name = "Micro Solutions CompatiCard I", + .internal_name = "compaticard_i", + .flags = DEVICE_ISA, + .local = 0, + .init = compaticard_init, + .close = compaticard_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = compaticard_i_config +}; + +const device_t fdc_compaticard_ii_device = { + .name = "Micro Solutions CompatiCard II", + .internal_name = "compaticard_ii", + .flags = DEVICE_ISA, + .local = 1, + .init = compaticard_init, + .close = compaticard_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = compaticard_ii_config +}; + +const device_t fdc_compaticard_iv_device = { + .name = "Micro Solutions CompatiCard IV", + .internal_name = "compaticard_iv", + .flags = DEVICE_ISA, + .local = 2, + .init = compaticard_init, + .close = compaticard_close, + .reset = NULL, + .available = compaticard_iv_available, + .speed_changed = NULL, + .force_redraw = NULL, + .config = compaticard_iv_config +}; diff --git a/src/include/86box/fdc_ext.h b/src/include/86box/fdc_ext.h index 4b33ed7a1..e6348139b 100644 --- a/src/include/86box/fdc_ext.h +++ b/src/include/86box/fdc_ext.h @@ -34,6 +34,10 @@ extern const device_t fdc_b215_device; extern const device_t fdc_pii151b_device; extern const device_t fdc_pii158b_device; +extern const device_t fdc_compaticard_i_device; +extern const device_t fdc_compaticard_ii_device; +extern const device_t fdc_compaticard_iv_device; + extern const device_t fdc_monster_device; extern void fdc_card_init(void); From 2d0f03a708d7ac4ba0f4b7ae719b56f82d8ac99e Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:47:23 +0100 Subject: [PATCH 0055/1190] Fixed a BX6-related typo --- 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 4947b8898..330b7d52a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14634,7 +14634,7 @@ const machine_t machines[] = { firmware. */ { - .name = "[i440LX] ABIT BX6", + .name = "[i440BX] ABIT BX6", .internal_name = "bx6", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_INTEL_440BX, From 204b24022f291ce7b4a5f3af9fee8d644f4f4c00 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 15:21:31 +0000 Subject: [PATCH 0056/1190] Implement the rivatimer and cyclical logging from my main NV3 branch so that we can get it reviewed and merged. --- src/86box.c | 152 ++++++++++++- src/include/86box/86box.h | 5 +- src/include/86box/nv/vid_nv_rivatimer.h | 84 ++++++++ src/video/nv/nv_rivatimer.c | 274 ++++++++++++++++++++++++ 4 files changed, 502 insertions(+), 13 deletions(-) create mode 100644 src/include/86box/nv/vid_nv_rivatimer.h create mode 100644 src/video/nv/nv_rivatimer.c diff --git a/src/86box.c b/src/86box.c index 8fa74fd4b..8450c8b6b 100644 --- a/src/86box.c +++ b/src/86box.c @@ -103,6 +103,7 @@ #include <86box/machine_status.h> #include <86box/apm.h> #include <86box/acpi.h> +#include <86box/nv/vid_nv_rivatimer.h> // Disable c99-designator to avoid the warnings about int ng #ifdef __clang__ @@ -252,12 +253,37 @@ static volatile atomic_int do_pause_ack = 0; static volatile atomic_int pause_ack = 0; #ifndef RELEASE_BUILD -static char buff[1024]; -static int seen = 0; + +#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 */ + +static char buff[LOG_SIZE_BUFFER]; +static char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; +static int32_t cyclic_last_line = 0; +static int32_t log_cycles = 0; + +static int seen = 0; static int suppr_seen = 1; #endif +/* + Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic +*/ +void +pclog_ensure_stdlog_open() +{ + if (stdlog == NULL) { + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; + } +} + /* * Log something to the logfile or stdout. * @@ -269,19 +295,12 @@ void pclog_ex(const char *fmt, va_list ap) { #ifndef RELEASE_BUILD - char temp[1024]; + char temp[LOG_SIZE_BUFFER]; if (strcmp(fmt, "") == 0) return; - if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; - } + pclog_ensure_stdlog_open(); vsprintf(temp, fmt, ap); if (suppr_seen && !strcmp(buff, temp)) @@ -298,6 +317,114 @@ pclog_ex(const char *fmt, va_list ap) #endif } + +/* +Starfrost, 7-8 January 2025: + +For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. + +Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm +*/ +void +pclog_ex_cyclic(const char* fmt, va_list ap) +{ +#ifndef RELEASE_BUILD + char temp[LOG_SIZE_BUFFER]; + + cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; + + vsprintf(temp, fmt, ap); + + pclog_ensure_stdlog_open(); + + strncpy(cyclic_buff[cyclic_last_line], temp, LOG_SIZE_BUFFER); + + uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; + + // Random numbers + uint32_t base = 257; + uint32_t mod = 1000000007; + + uint32_t repeat_order = 0; + bool is_cycle = false; + + // compute the set of hashes for the current log buffer + for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) + { + if (cyclic_buff[log_line][0] == '\0') + continue; // skip + + for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) + { + hashes[log_line] = hashes[log_line] * base + cyclic_buff[log_line][log_line_char] % mod; + } + } + + + // Now see if there are real cycles... + // We implement a minimum repeat size. + for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) + { + //TODO: Log what we need for cycle 1. + //TODO: Command line option that lets us turn off this behaviour. + for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) + { + if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) + { + repeat_order = check_size; + break; + } + } + + is_cycle = (repeat_order != 0); + + // if there still is a cycle.. + if (is_cycle) + break; + + } + + if (is_cycle) + { + if (cyclic_last_line % repeat_order == 0) + { + log_cycles++; + + if (log_cycles == 1) + { + // 'Replay' the last few log entries so they actually show up + // Todo: is this right? + + for (uint32_t index = cyclic_last_line - 1; index > (cyclic_last_line - repeat_order); index--) + { + // *very important* to prevent out of bounds index + uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; + fprintf(stdlog, "%s", temp); + + } + + fprintf(stdlog, "%s", temp); // allow normal logging + } + + + if (log_cycles > 1 && log_cycles < 100) + fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log_cycles); + else if (log_cycles == 100) + fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); + } + } + else + { + log_cycles = 0; + fprintf(stdlog, "%s", temp); + } + + cyclic_last_line++; + +#endif + +} + void pclog_toggle_suppr(void) { @@ -1427,6 +1554,9 @@ pc_run(void) pc_reset_hard_init(); } + /* Update the guest-CPU independent timer for devices with independent clock speed */ + rivatimer_update_all(); + /* Run a block of code. */ startblit(); cpu_exec((int32_t) cpu_s->rspeed / 100); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 503518a2b..05c2a901e 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -187,8 +187,9 @@ extern int config_changed; /* config has changed */ /* Function prototypes. */ #ifdef HAVE_STDARG_H -extern void pclog_ex(const char *fmt, va_list); -extern void fatal_ex(const char *fmt, va_list); +extern void pclog_ex(const char *fmt, va_list ap); +extern void fatal_ex(const char *fmt, va_list ap); +extern void pclog_ex_cyclic(const char* fmt, va_list ap); #endif extern void pclog_toggle_suppr(void); #ifdef _MSC_VER diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h new file mode 100644 index 000000000..d5bb86b90 --- /dev/null +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -0,0 +1,84 @@ +/* + * 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. + * + * Fast, high-frequency, guest CPU-independent timer for Riva emulation. + * + * + * Authors: Connor Hyde, I need a better email address ;^) + * + * Copyright 2024-2025 starfrost + */ + +/* +RivaTimer + +This is a fast, high-frequency, guest CPU-independent timer. + +The main 86box timer is dependent on the TSC (time-stamp counter) register of the emulated CPU core. +This is fine for most purposes and has advantages in the fields of synchronisation and integrates neatly with +the clock dividers of the PC architecture, but in the case of the RIVA 128 it does not particularly suffice +(although it can be made to work with various techniques) since the clock source on the RIVA 128 is on the board itself +and the GPU has several different clocks that control different parts of the GPU (e.g., PTIMER runs on the memory clock but the core gpu is using the pixel clock). + +As faster graphics cards that offload more and more of the 3D graphics pipeline are emulated in the future, more and more work needs to be done by the emulator and +issues of synchronisation with a host CPU will simply make that work harder. Some features that are required for + +Architecture Brand Name 3D Features +NV1 (1995) NV1 Some weird URBS rectangle crap but feature set generally similar to nv3 but a bit worse +NV3 (1997) RIVA 128 (ZX) Triangle setup, edge-slope calculations, edge interpolation, span-slope calculations, span interpolation (Color-buffer, z-buffer, texture mapping, filtering) +NV4 (1998) RIVA TNT NV3 + 2x1 pixel pipelines + 32-bit colour + larger textures + trilinear + more ram (16mb) +NV5 (1999) RIVA TNT2 NV4 + higher clock speed +NV10 (1999) GeForce 256 NV5 + initial geometry transformation + lighting (8x lights) + MPEG-2 motion compensation + 4x1 pixel pipelines +NV15 (2000) GeForce 2 NV10 + First attempt at programmability + 4x2 pixel pipelines +NV20 (2001) GeForce 3 Programmable shaders! + +As you can see, the performance basically exponentially increases over a period of only 4 years. + +So I decided to create this timer that is completely separate from the CPU Core. +*/ + +#pragma once +#include +#include +#include +#include +#include <86Box\86box.h> + +#ifdef _WIN32 +#include +// Linux & MacOS should have the same API since OSX 10.12 +#else +#include +#endif + +typedef struct rivatimer_s +{ + struct rivatimer_s* prev; // Previous Rivatimer + double period; // Period in uS before firing + double value; // The current value of the rivatimer + bool running; // Is this RivaTimer running? + struct rivatimer_s* next; // Next RivaTimer + void (*callback)(); // Callback to call on fire + #ifdef _WIN32 + LARGE_INTEGER starting_time; // Starting time. + #else + struct timespec starting_time; // Starting time. + #endif + double time; // Accumulated time in uS. +} rivatimer_t; + +void rivatimer_init(); // Initialise the Rivatimer. +rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time)); +void rivatimer_destroy(rivatimer_t* rivatimer_ptr); + +void rivatimer_update_all(); +void rivatimer_start(rivatimer_t* rivatimer_ptr); +void rivatimer_stop(rivatimer_t* rivatimer_ptr); +double rivatimer_get_time(rivatimer_t* rivatimer_ptr); +void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time)); +void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period); diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c new file mode 100644 index 000000000..343ec02ff --- /dev/null +++ b/src/video/nv/nv_rivatimer.c @@ -0,0 +1,274 @@ +/* + * 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. + * + * Fast, high-frequency, CPU-independent timer. + * + * + * + * Authors: Connor Hyde, I need a better email address ;^) + * + * Copyright 2024-2025 starfrost + */ + +/* See vid_nv_rivatimer.h comments for rationale behind not using the regular timer system + +Notes applicable to this file: +Since Windows XP, QueryPerformanceCounter and QueryPerformanceFrequency cannot fail so they are not checked. + +*/ + +#include <86Box/nv/vid_nv_rivatimer.h> + +#ifdef _WIN32 +LARGE_INTEGER performance_frequency; +#endif + +rivatimer_t* rivatimer_head; // The head of the rivatimer list. +rivatimer_t* rivatimer_tail; // The tail of the rivatimer list. + +/* Functions only used in this translation unit */ +bool rivatimer_really_exists(rivatimer_t* rivatimer); // Determine if a rivatimer really exists in the linked list. + +void rivatimer_init() +{ + // Destroy all the rivatimers. + rivatimer_t* rivatimer_ptr = rivatimer_head; + + if (!rivatimer_ptr) + return; + + while (rivatimer_ptr) + { + // since we are destroing it + rivatimer_t* old_next = rivatimer_ptr->next; + rivatimer_destroy(rivatimer_ptr); + + rivatimer_ptr = old_next; + } + + + #ifdef _WIN32 + // Query the performance frequency. + QueryPerformanceFrequency(&performance_frequency); + #endif +} + +// Creates a rivatimer. +rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time)) +{ + rivatimer_t* new_rivatimer = NULL; + + // See i + if (period <= 0 + || !callback) + { + fatal("Invalid rivatimer_create call: period <= 0 or no callback"); + } + + // If there are no rivatimers, create one + if (!rivatimer_head) + { + rivatimer_head = calloc(1, sizeof(rivatimer_t)); + rivatimer_head->prev = NULL; // indicate this is the first in the list even if we don't strictly need to + rivatimer_tail = rivatimer_head; + new_rivatimer = rivatimer_head; + } + else // Otherwise add a new one to the list + { + rivatimer_tail->next = calloc(1, sizeof(rivatimer_t)); + rivatimer_tail = rivatimer_tail->next; + new_rivatimer = rivatimer_tail; + } + + // sanity check + if (new_rivatimer) + { + new_rivatimer->running = false; + new_rivatimer->period = period; + new_rivatimer->next = NULL; // indicate this is the last in the list + new_rivatimer->callback = callback; + } + + return new_rivatimer; +} + +// Determines if a rivatimer really exists. +bool rivatimer_really_exists(rivatimer_t* rivatimer) +{ + rivatimer_t* current = rivatimer_head; + + if (!current) + return false; + + while (current) + { + if (current == rivatimer) + return true; + + current = current->next; + } + + return false; +} + +// Destroy a rivatimer. +void rivatimer_destroy(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place. Punch starfrost in the face"); + + // Case: We are destroying the head + if (rivatimer_ptr == rivatimer_head) + { + // This is the only rivatimer + if (rivatimer_ptr->next == NULL) + { + rivatimer_head = NULL; + rivatimer_tail = NULL; + } + // This is not the only rivatimer + else + { + rivatimer_head = rivatimer_ptr->next; + rivatimer_head->prev = NULL; + // This is the only rivatimer and now there is only one + if (!rivatimer_head->next) + rivatimer_tail = rivatimer_head; + } + } + // Case: We are destroying the tail + else if (rivatimer_ptr == rivatimer_tail) + { + // We already covered the case where there is only one item above + rivatimer_tail = rivatimer_ptr->prev; + rivatimer_tail->next = NULL; + } + // Case: This is not the first or last rivatimer, so we don't need to set the head or tail + else + { + // Fix the break in the chain that this + if (rivatimer_ptr->next) + rivatimer_ptr->prev->next = rivatimer_ptr->next; + if (rivatimer_ptr->prev) + rivatimer_ptr->next->prev = rivatimer_ptr->prev; + } + + free(rivatimer_ptr); + rivatimer_ptr = NULL; //explicitly set to null +} + +void rivatimer_update_all() +{ + rivatimer_t* rivatimer_ptr = rivatimer_head; + + if (!rivatimer_ptr) + return; + + while (rivatimer_ptr) + { + // if it's not running skip it + if (!rivatimer_ptr->running) + { + rivatimer_ptr = rivatimer_ptr->next; + continue; + } + + #ifdef _WIN32 + LARGE_INTEGER current_time; + + QueryPerformanceCounter(¤t_time); + + double microseconds = ((double)current_time.QuadPart / 1000000.0) - (rivatimer_ptr->starting_time.QuadPart / 1000000.0); + #else + struct timespec current_time; + + clock_gettime(CLOCK_REALTIME, ¤t_time); + + double microseconds = ((double)current_time.tv_sec * 1000000.0) + ((double)current_time.tv_nsec / 1000.0); + #endif + + rivatimer_ptr->time += microseconds; + + // Reset the current time so we can actually restart + #ifdef _WIN32 + QueryPerformanceCounter(&rivatimer_ptr->starting_time); + #else + clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time); + #endif + + // Time to fire + if (microseconds > rivatimer_ptr->period) + { + if (!rivatimer_ptr->callback) + { + pclog("Eh? No callback in RivaTimer?"); + continue; + } + + rivatimer_ptr->callback(microseconds); + } + + rivatimer_ptr = rivatimer_ptr->next; + } + +} + +void rivatimer_start(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + if (rivatimer_ptr->period <= 0) + fatal("rivatimer_start: Zero period!"); + + rivatimer_ptr->running = true; + + // Start off so rivatimer_update_all can actually update. + #ifdef _WIN32 + QueryPerformanceCounter(&rivatimer_ptr->starting_time); + #else + clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time); + #endif +} + +void rivatimer_stop(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + rivatimer_ptr->running = false; + rivatimer_ptr->time = 0; +} + +// Get the current time value of a rivatimer +double rivatimer_get_time(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + return rivatimer_ptr->time; +} + +void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time)) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + if (!callback) + fatal("rivatimer_set_callback: No callback!"); + + rivatimer_ptr->callback = callback; +} + +void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + rivatimer_ptr->period = period; +} \ No newline at end of file From 6eaec5b756fab78c94fcb861155acb7ed2c576fe Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 15:31:54 +0000 Subject: [PATCH 0057/1190] forgot to port over some parts --- src/timer.c | 4 ++++ src/video/CMakeLists.txt | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/timer.c b/src/timer.c index 6ddf8ebb5..2b92a1958 100644 --- a/src/timer.c +++ b/src/timer.c @@ -4,6 +4,7 @@ #include #include <86box/86box.h> #include <86box/timer.h> +#include <86Box/nv/vid_nv_rivatimer.h> uint64_t TIMER_USEC; uint32_t timer_target; @@ -168,6 +169,9 @@ timer_init(void) timer_target = 0ULL; tsc = 0; + /* Initialise the CPU-independent timer */ + rivatimer_init(); + timer_inited = 1; } diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index bbd329b7e..3d8e14c5e 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -27,7 +27,9 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c - vid_bochs_vbe.c) + vid_bochs_vbe.c + nv/nv_rivatimer.c + ) if(G100) target_compile_definitions(vid PRIVATE USE_G100) From 55f476617d67cc476f48c42cfe04554019afe82b Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 19:07:27 +0000 Subject: [PATCH 0058/1190] Don't punch me in the face, and also fix the compilation, and also fix a stupid bug in log replay. --- src/86box.c | 5 ++--- src/include/86box/nv/vid_nv_rivatimer.h | 6 +++--- src/video/nv/nv_rivatimer.c | 12 ++++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/86box.c b/src/86box.c index 8450c8b6b..b5a4de15e 100644 --- a/src/86box.c +++ b/src/86box.c @@ -271,8 +271,7 @@ static int suppr_seen = 1; /* Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic */ -void -pclog_ensure_stdlog_open() +void pclog_ensure_stdlog_open() { if (stdlog == NULL) { if (log_path[0] != '\0') { @@ -399,7 +398,7 @@ pclog_ex_cyclic(const char* fmt, va_list ap) { // *very important* to prevent out of bounds index uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; - fprintf(stdlog, "%s", temp); + fprintf(stdlog, "%s", cyclic_buff[real_index]); } diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index d5bb86b90..627bbcdcf 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -63,7 +63,7 @@ typedef struct rivatimer_s double value; // The current value of the rivatimer bool running; // Is this RivaTimer running? struct rivatimer_s* next; // Next RivaTimer - void (*callback)(); // Callback to call on fire + void (*callback)(void); // Callback to call on fire #ifdef _WIN32 LARGE_INTEGER starting_time; // Starting time. #else @@ -72,11 +72,11 @@ typedef struct rivatimer_s double time; // Accumulated time in uS. } rivatimer_t; -void rivatimer_init(); // Initialise the Rivatimer. +void rivatimer_init(void); // Initialise the Rivatimer. rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time)); void rivatimer_destroy(rivatimer_t* rivatimer_ptr); -void rivatimer_update_all(); +void rivatimer_update_all(void); void rivatimer_start(rivatimer_t* rivatimer_ptr); void rivatimer_stop(rivatimer_t* rivatimer_ptr); double rivatimer_get_time(rivatimer_t* rivatimer_ptr); diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c index 343ec02ff..ee8c13916 100644 --- a/src/video/nv/nv_rivatimer.c +++ b/src/video/nv/nv_rivatimer.c @@ -120,7 +120,7 @@ bool rivatimer_really_exists(rivatimer_t* rivatimer) void rivatimer_destroy(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place."); // Case: We are destroying the head if (rivatimer_ptr == rivatimer_head) @@ -221,7 +221,7 @@ void rivatimer_update_all() void rivatimer_start(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place."); if (rivatimer_ptr->period <= 0) fatal("rivatimer_start: Zero period!"); @@ -239,7 +239,7 @@ void rivatimer_start(rivatimer_t* rivatimer_ptr) void rivatimer_stop(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place."); rivatimer_ptr->running = false; rivatimer_ptr->time = 0; @@ -249,7 +249,7 @@ void rivatimer_stop(rivatimer_t* rivatimer_ptr) double rivatimer_get_time(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place."); return rivatimer_ptr->time; } @@ -257,7 +257,7 @@ double rivatimer_get_time(rivatimer_t* rivatimer_ptr) void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time)) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place."); if (!callback) fatal("rivatimer_set_callback: No callback!"); @@ -268,7 +268,7 @@ void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place."); rivatimer_ptr->period = period; } \ No newline at end of file From cbfeed7ea46acbc6d2481798b1dc920b8bcbc50d Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 19:09:35 +0000 Subject: [PATCH 0059/1190] Fix incorrect include --- src/include/86box/nv/vid_nv_rivatimer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index 627bbcdcf..8ccc0f0df 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -47,7 +47,7 @@ So I decided to create this timer that is completely separate from the CPU Core. #include #include #include -#include <86Box\86box.h> +#include <86Box/86box.h> #ifdef _WIN32 #include From 8c48478706d8b7c53fc6afe0ddc5498fcab8f1f1 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 19:11:20 +0000 Subject: [PATCH 0060/1190] fix the screwed up callbacks --- src/include/86box/nv/vid_nv_rivatimer.h | 2 +- src/video/nv/nv_rivatimer.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index 8ccc0f0df..a4fe85e92 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -63,7 +63,7 @@ typedef struct rivatimer_s double value; // The current value of the rivatimer bool running; // Is this RivaTimer running? struct rivatimer_s* next; // Next RivaTimer - void (*callback)(void); // Callback to call on fire + void (*callback)(double real_time); // Callback to call on fire #ifdef _WIN32 LARGE_INTEGER starting_time; // Starting time. #else diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c index ee8c13916..44e5901d1 100644 --- a/src/video/nv/nv_rivatimer.c +++ b/src/video/nv/nv_rivatimer.c @@ -34,7 +34,7 @@ rivatimer_t* rivatimer_tail; // The tail of the rivatimer list. /* Functions only used in this translation unit */ bool rivatimer_really_exists(rivatimer_t* rivatimer); // Determine if a rivatimer really exists in the linked list. -void rivatimer_init() +void rivatimer_init(void) { // Destroy all the rivatimers. rivatimer_t* rivatimer_ptr = rivatimer_head; @@ -162,7 +162,7 @@ void rivatimer_destroy(rivatimer_t* rivatimer_ptr) rivatimer_ptr = NULL; //explicitly set to null } -void rivatimer_update_all() +void rivatimer_update_all(void) { rivatimer_t* rivatimer_ptr = rivatimer_head; From 8dc456cce5c2eb87e744ec1d82858a98f14ffec3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 12 Jan 2025 20:37:50 +0100 Subject: [PATCH 0061/1190] NCR 5380-based changes of the day (January 12, 2025) 1. Sanity check for the SCSI temp_buffer if it's allocated or not. 2. Data reads and writes in non-DMA mode should be accessible only when DMA mode is Idle (as in, no DMA at all, whereas DMA mode will go to the SCSI controllers' callbacks). --- src/scsi/scsi_ncr5380.c | 47 ++++++++++++++++++++++++++------------- src/scsi/scsi_ncr53c400.c | 38 +++++++++++++++++++++++-------- src/scsi/scsi_t128.c | 2 ++ 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 527ff373f..092cc08e9 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -197,20 +197,29 @@ ncr5380_bus_read(ncr_t *ncr) phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); if (phase == SCSI_PHASE_DATA_IN) { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->state = STATE_DATAIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; + if (ncr->dma_mode == DMA_IDLE) { + ncr5380_log("Phase Data In.\n"); + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + + ncr->state = STATE_DATAIN; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; + } } else if (phase == SCSI_PHASE_DATA_OUT) { if (ncr->new_phase & BUS_IDLE) { ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; - } else - ncr->state = STATE_DATAOUT; + } else { + if (ncr->dma_mode == DMA_IDLE) + ncr->state = STATE_DATAOUT; + } } else if (phase == SCSI_PHASE_STATUS) { + ncr5380_log("Phase Status.\n"); ncr->cur_bus |= BUS_REQ; ncr->state = STATE_STATUS; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; } else if (phase == SCSI_PHASE_MESSAGE_IN) { + ncr5380_log("Phase Message In.\n"); ncr->state = STATE_MESSAGEIN; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; } else if (phase == SCSI_PHASE_MESSAGE_OUT) { @@ -335,19 +344,22 @@ ncr5380_bus_update(ncr_t *ncr, int bus) if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { if (ncr->data_pos >= dev->buffer_length) { ncr->cur_bus &= ~BUS_REQ; + ncr5380_log("CMD Phase1 DataIn.\n"); scsi_device_command_phase1(dev); ncr->new_phase = SCSI_PHASE_STATUS; ncr->wait_data = 4; ncr->wait_complete = 8; } else { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ ncr->data_wait |= 1; - ncr5380_log("DMA mode idle in\n"); + ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); ncr->timer(ncr->priv, ncr->period); } else { - ncr5380_log("DMA mode IN.\n"); + ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); ncr->clear_req = 3; } @@ -359,7 +371,8 @@ ncr5380_bus_update(ncr_t *ncr, int bus) case STATE_DATAOUT: dev = &scsi_devices[ncr->bus][ncr->target_id]; if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); if (ncr->data_pos >= dev->buffer_length) { ncr->cur_bus &= ~BUS_REQ; @@ -439,12 +452,12 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) switch (port & 7) { case 0: /* Output data register */ - ncr5380_log("Write: Output data register, val = %02x\n", val); + ncr5380_log("[%04X:%08X]: Write: Output data register, val=%02x\n", CS, cpu_state.pc, val); ncr->output_data = val; break; case 1: /* Initiator Command Register */ - ncr5380_log("Write: Initiator command register\n"); + ncr5380_log("[%04X:%08X]: Write: Initiator command register, val=%02x.\n", CS, cpu_state.pc, val); if ((val & 0x80) && !(ncr->icr & 0x80)) { ncr5380_log("Resetting the 5380\n"); ncr5380_reset(ncr); @@ -465,7 +478,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 3: /* Target Command Register */ - ncr5380_log("Write: Target Command register\n"); + ncr5380_log("Write: Target Command register, val=%02x.\n", val); ncr->tcr = val; break; @@ -482,7 +495,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 7: /* start DMA Initiator Receive */ - ncr5380_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); + ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr->dma_initiator_receive_ext) @@ -510,13 +523,13 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ncr5380_log("Read: Current SCSI data register\n"); if (ncr->icr & ICR_DBP) { /*Return the data from the output register if on data bus phase from ICR*/ - ncr5380_log("Data Bus Phase, ret = %02x\n", ncr->output_data); ret = ncr->output_data; + ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x.\n", CS, cpu_state.pc, ret, ncr->clear_req, ncr->wait_data); } else { /*Return the data from the SCSI bus*/ ncr5380_bus_read(ncr); - ncr5380_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus)); ret = BUS_GETDATA(ncr->cur_bus); + ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret); } break; @@ -595,7 +608,9 @@ ncr5380_read(uint16_t port, ncr_t *ncr) break; case 6: - ret = ncr->tx_data; + ncr5380_log("Read: Input Data.\n"); + ncr5380_bus_read(ncr); + ret = BUS_GETDATA(ncr->cur_bus); break; case 7: /* reset Parity/Interrupt */ diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 6622ec59a..997e8f152 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -148,6 +148,12 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) ncr400->busy = 1; if (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0))) timer_on_auto(&ncr400->timer, ncr->period / 250.0); + else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) { + if (scsi_device_get_callback(dev) > 0.0) + timer_on_auto(&ncr400->timer, 100.0); + else + timer_on_auto(&ncr400->timer, 40.0); + } } } break; @@ -181,13 +187,14 @@ 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 (ncr->mode & MODE_MONITOR_BUSY) - timer_on_auto(&ncr400->timer, ncr->period); + timer_on_auto(&ncr400->timer, (ncr->period / 4.0) * 3.0); else if (scsi_device_get_callback(dev) > 0.0) timer_on_auto(&ncr400->timer, 40.0); else timer_on_auto(&ncr400->timer, ncr->period); - ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); + ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", + ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); } break; @@ -244,6 +251,12 @@ ncr53c400_read(uint32_t addr, void *priv) ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl); if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0)) timer_on_auto(&ncr400->timer, ncr->period / 250.0); + else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) { + if (scsi_device_get_callback(dev) > 0.0) + timer_on_auto(&ncr400->timer, 100.0); + else + timer_on_auto(&ncr400->timer, 40.0); + } } } break; @@ -397,16 +410,20 @@ t130b_in(uint16_t port, void *priv) } static void -ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv)) +ncr53c400_dma_mode_ext(void *priv, void *ext_priv) { - ncr_t *ncr = (ncr_t *) priv; + ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; + ncr_t *ncr = (ncr_t *) priv; /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!(ncr->mode & MODE_DMA)) { - ncr53c400_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; + ncr53c400_log("BlockCountLoaded=%d.\n", ncr400->block_count_loaded); + if (!ncr400->block_count_loaded) { + if (!(ncr->mode & MODE_DMA)) { + ncr53c400_log("No DMA mode\n"); + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } } } @@ -474,6 +491,7 @@ ncr53c400_callback(void *priv) ncr400->block_count = (ncr400->block_count - 1) & 0xff; ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count); if (!ncr400->block_count) { + ncr->dma_mode = DMA_IDLE; ncr400->block_count_loaded = 0; ncr53c400_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -527,6 +545,7 @@ 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) { + ncr->dma_mode = DMA_IDLE; ncr400->block_count_loaded = 0; ncr53c400_log("IO End of read transfer\n"); ncr->isr |= STATUS_END_OF_DMA; @@ -544,6 +563,7 @@ ncr53c400_callback(void *priv) break; } + ncr53c400_log("Bus Read.\n"); ncr5380_bus_read(ncr); if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index c878bbb91..faad87052 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -287,6 +287,7 @@ write_again: t128->block_count = (t128->block_count - 1) & 0xff; t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); if (!t128->block_count) { + ncr->dma_mode = DMA_IDLE; t128->block_loaded = 0; t128_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -343,6 +344,7 @@ read_again: t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); if (!t128->block_count) { t128->block_loaded = 0; + ncr->dma_mode = DMA_IDLE; t128_log("IO End of read transfer\n"); ncr->isr |= STATUS_END_OF_DMA; timer_stop(&t128->timer); From 4f15889638cb38a51e790c49391535040e13d10a Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 23:09:03 +0000 Subject: [PATCH 0062/1190] fix compile by fixing capitalisation --- src/include/86box/nv/vid_nv_rivatimer.h | 2 +- src/timer.c | 2 +- src/video/nv/nv_rivatimer.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index a4fe85e92..59f6cfebf 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -47,7 +47,7 @@ So I decided to create this timer that is completely separate from the CPU Core. #include #include #include -#include <86Box/86box.h> +#include <86box/86box.h> #ifdef _WIN32 #include diff --git a/src/timer.c b/src/timer.c index 2b92a1958..a3a7c9efb 100644 --- a/src/timer.c +++ b/src/timer.c @@ -4,7 +4,7 @@ #include #include <86box/86box.h> #include <86box/timer.h> -#include <86Box/nv/vid_nv_rivatimer.h> +#include <86box/nv/vid_nv_rivatimer.h> uint64_t TIMER_USEC; uint32_t timer_target; diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c index 44e5901d1..12d40c026 100644 --- a/src/video/nv/nv_rivatimer.c +++ b/src/video/nv/nv_rivatimer.c @@ -22,7 +22,7 @@ Since Windows XP, QueryPerformanceCounter and QueryPerformanceFrequency cannot f */ -#include <86Box/nv/vid_nv_rivatimer.h> +#include <86box/nv/vid_nv_rivatimer.h> #ifdef _WIN32 LARGE_INTEGER performance_frequency; From 31207c98d656e2a68fd9c4b1d7d5c4774bdaa6a2 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 23:15:43 +0000 Subject: [PATCH 0063/1190] hopefully the final issue...fix missing prototype --- src/86box.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/86box.c b/src/86box.c index b5a4de15e..219535c84 100644 --- a/src/86box.c +++ b/src/86box.c @@ -266,6 +266,9 @@ static int32_t log_cycles = 0; static int seen = 0; static int suppr_seen = 1; + +// Functions only used in this translation unit +void pclog_ensure_stdlog_open(); #endif /* @@ -273,6 +276,7 @@ static int suppr_seen = 1; */ void pclog_ensure_stdlog_open() { +#ifndef RELEASE_BUILD if (stdlog == NULL) { if (log_path[0] != '\0') { stdlog = plat_fopen(log_path, "w"); @@ -281,6 +285,7 @@ void pclog_ensure_stdlog_open() } else stdlog = stdout; } +#endif } /* From fa3fb7ecccb0c73cb0c33f74865eb65621f911d8 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 23:22:22 +0000 Subject: [PATCH 0064/1190] explicit void... --- src/86box.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/86box.c b/src/86box.c index 219535c84..85cbb9957 100644 --- a/src/86box.c +++ b/src/86box.c @@ -268,13 +268,13 @@ static int seen = 0; static int suppr_seen = 1; // Functions only used in this translation unit -void pclog_ensure_stdlog_open(); +void pclog_ensure_stdlog_open(void); #endif /* Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic */ -void pclog_ensure_stdlog_open() +void pclog_ensure_stdlog_open(void) { #ifndef RELEASE_BUILD if (stdlog == NULL) { From be878ede582870a70532890b85fbd43e6f242e8d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 13 Jan 2025 00:56:04 +0100 Subject: [PATCH 0065/1190] Okay, maybe for the 53c400 only so. Based on my tests, the former 5380 commit will apply to the 53c400 only, for now... --- src/scsi/scsi_ncr5380.c | 4 ++-- src/scsi/scsi_t128.c | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 092cc08e9..0c3af9282 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -197,7 +197,7 @@ ncr5380_bus_read(ncr_t *ncr) phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); if (phase == SCSI_PHASE_DATA_IN) { - if (ncr->dma_mode == DMA_IDLE) { + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext) { ncr5380_log("Phase Data In.\n"); if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; @@ -210,7 +210,7 @@ ncr5380_bus_read(ncr_t *ncr) ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; } else { - if (ncr->dma_mode == DMA_IDLE) + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext) ncr->state = STATE_DATAOUT; } } else if (phase == SCSI_PHASE_STATUS) { diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index faad87052..c878bbb91 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -287,7 +287,6 @@ write_again: t128->block_count = (t128->block_count - 1) & 0xff; t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); if (!t128->block_count) { - ncr->dma_mode = DMA_IDLE; t128->block_loaded = 0; t128_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -344,7 +343,6 @@ read_again: t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); if (!t128->block_count) { t128->block_loaded = 0; - ncr->dma_mode = DMA_IDLE; t128_log("IO End of read transfer\n"); ncr->isr |= STATUS_END_OF_DMA; timer_stop(&t128->timer); From f039fce49749779cf70d4f83545fd6d5da761f72 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 04:16:08 +0100 Subject: [PATCH 0066/1190] PIC: Signal to the CPU to end the block on IRR read, fixes stalls in waiting for IRQ, fixes #5108. --- src/pic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pic.c b/src/pic.c index 82905261a..f8e83c40b 100644 --- a/src/pic.c +++ b/src/pic.c @@ -17,6 +17,7 @@ * Copyright 2015-2020 Andrew Jenner. * Copyright 2016-2020 Miran Grca. */ +#include #include #include #include @@ -491,12 +492,13 @@ pic_read(uint16_t addr, void *priv) else dev->data_bus = 0x00; #endif - } + } else + cpu_block_end = 1; /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, simply read whatever is currently on the data bus. */ } - pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus); + pic_log("pic_read(%04X) = %02X\n", addr, dev->data_bus); return dev->data_bus; } From 123ff3b5e767864e8f1381ed18aeb3fa17966bbd Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 04:35:23 +0100 Subject: [PATCH 0067/1190] Fix NEC Vx0 INS*/OUS* timings calculation. --- src/cpu/808x.c | 53 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index d815551ae..0c1fb0f4d 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1634,28 +1634,55 @@ cpu_data_opff_rm(void) } } +uint8_t +cpu_inb(uint16_t port) +{ + uint8_t ret; + + wait(4, 0); + old_cycles = cycles; + + ret = inb(port); + + resub_cycles(); +} + uint16_t cpu_inw(uint16_t port) { - if (is8086 && !(port & 1)) { - wait(4, 0); - } else { - wait(8, 0); - } + uint16_t ret; - return inw(port); + if (is8086 && !(port & 1)) + wait(4, 0); + else + wait(8, 0); + + ret = inw(port); + + resub_cycles(); +} + +void +cpu_outb(uint16_t port, uint16_t val) +{ + wait(4, 0); + + outb(port, val); + + resub_cycles(); } void cpu_outw(uint16_t port, uint16_t val) { - if (is8086 && !(port & 1)) { + if (is8086 && !(port & 1)) wait(4, 0); - } else { + else wait(8, 0); - } - return outw(port, val); + outw(port, val); + + resub_cycles(); } /* Executes instructions up to the specified number of cycles. */ @@ -1804,8 +1831,7 @@ execx86(int cycs) writememw(es, DI, cpu_inw(DX)); DI += (cpu_state.flags & D_FLAG) ? -2 : 2; } else { - wait(4, 0); - writememb(es, DI, inb(DX)); + writememb(es, DI, cpu_inb(DX)); DI += (cpu_state.flags & D_FLAG) ? -1 : 1; } @@ -1833,8 +1859,7 @@ execx86(int cycs) cpu_outw(DX, readmemw(dest_seg, SI)); SI += (cpu_state.flags & D_FLAG) ? -2 : 2; } else { - wait(4, 0); - outb(DX, readmemb(dest_seg + SI)); + cpu_outb(DX, readmemb(dest_seg + SI)); SI += (cpu_state.flags & D_FLAG) ? -1 : 1; } if (in_rep == 0) From b1f94abc27131792c4b33be5588a736ac1f3c916 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 05:01:00 +0100 Subject: [PATCH 0068/1190] Fixed the fix. --- src/cpu/808x.c | 52 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 0c1fb0f4d..f37672a5c 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1637,52 +1637,72 @@ cpu_data_opff_rm(void) uint8_t cpu_inb(uint16_t port) { + int old_cycles = cycles; uint8_t ret; - wait(4, 0); + wait(is_mazovia ? 5 : 4, 1); old_cycles = cycles; ret = inb(port); - resub_cycles(); + resub_cycles(old_cycles); + + return ret; } uint16_t cpu_inw(uint16_t port) { + int old_cycles = cycles; uint16_t ret; - if (is8086 && !(port & 1)) - wait(4, 0); - else - wait(8, 0); + wait(is_mazovia ? 5 : 4, 1); + if (is8086 && !(port & 1)) { + old_cycles = cycles; + ret = inw(port); + } else { + wait(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; + ret = inb(port++); + ret |= (inb(port) << 8); + } - ret = inw(port); + resub_cycles(old_cycles); - resub_cycles(); + return ret; } void cpu_outb(uint16_t port, uint16_t val) { - wait(4, 0); + int old_cycles = cycles; + + wait(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; outb(port, val); - resub_cycles(); + resub_cycles(old_cycles); } void cpu_outw(uint16_t port, uint16_t val) { - if (is8086 && !(port & 1)) - wait(4, 0); - else - wait(8, 0); + int old_cycles = cycles; - outw(port, val); + wait(is_mazovia ? 5 : 4, 1); - resub_cycles(); + if (is8086 && !(port & 1)) { + old_cycles = cycles; + outw(port, val); + } else { + wait(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; + outb(port++, val); + outb(port, val >> 8); + } + + resub_cycles(old_cycles); } /* Executes instructions up to the specified number of cycles. */ From ec175738ee48899770c7275179beb2746dc26312 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 05:38:10 +0100 Subject: [PATCH 0069/1190] FIX timings of SYSCALL/SYSRET/SYSENTER/SYSEXIT/FXSAVE/FXSTOR. --- src/cpu/x86_ops_amd.h | 12 ++---------- src/cpu/x86_ops_i686.h | 28 ++++++++++------------------ 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h index 9e6bcce55..54da4a79d 100644 --- a/src/cpu/x86_ops_amd.h +++ b/src/cpu/x86_ops_amd.h @@ -22,12 +22,8 @@ opSYSCALL(uint32_t fetchdat) ret = syscall_op(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } @@ -41,12 +37,8 @@ opSYSRET(uint32_t fetchdat) ret = sysret(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index 5e5dc3c7c..a67571875 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -18,12 +18,8 @@ opSYSENTER(uint32_t fetchdat) { int ret = sysenter(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } @@ -33,12 +29,8 @@ opSYSEXIT(uint32_t fetchdat) { int ret = sysexit(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } @@ -118,7 +110,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward); } - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + // CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES(1); } else { /* FXSAVE */ writememw(easeg, cpu_state.eaaddr, i387_get_control_word()); @@ -163,7 +156,7 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.signExp); } - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES(1); } return cpu_state.abrt; @@ -327,7 +320,8 @@ fx_save_stor_common(uint32_t fetchdat, int bits) } } - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + // CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES(1); } else { /* FXSAVE */ if ((twd & 0x0003) != 0x0003) @@ -372,7 +366,7 @@ fx_save_stor_common(uint32_t fetchdat, int bits) cpu_state.eaaddr = old_eaaddr; - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES(1); } return cpu_state.abrt; @@ -400,8 +394,7 @@ static int opHINT_NOP_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + CLOCK_CYCLES(1); return 0; } @@ -409,7 +402,6 @@ static int opHINT_NOP_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + CLOCK_CYCLES(1); return 0; } From ad056b136c1413fdf371114d9524186312cde807 Mon Sep 17 00:00:00 2001 From: eddmanx Date: Mon, 13 Jan 2025 17:09:01 +0400 Subject: [PATCH 0070/1190] Update README.md - added the Avalonia86 manager --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ce38632e6..c01a852b5 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ It is also recommended to use a manager application with 86Box for easier handli * [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only) * [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia) +* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux) * [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python) * [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested) * [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only) From f3016bc93eb3361cc389a30be71cd274da5382e7 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 22:48:44 +0700 Subject: [PATCH 0071/1190] Added onboard sound to 4 machines --- src/machine/m_at_socket7.c | 4 ++++ src/machine/m_at_socket7_3v.c | 4 ++++ src/machine/m_at_socket8.c | 8 ++++++++ src/machine/machine_table.c | 8 ++++---- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index f80d2d421..52b16c212 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -849,6 +849,10 @@ machine_at_gw2kte_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 40ae221a0..4b980f2b0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -694,6 +694,10 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index e6f78f6a2..59c412447 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -249,6 +249,10 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -283,6 +287,10 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 330b7d52a..b9ee8af40 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13989,7 +13989,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14004,7 +14004,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cs4236b_device, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ @@ -14113,7 +14113,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14128,7 +14128,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cs4236b_device, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ From a7472005ba746d9522e8b45657bd728f72577edb Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 23:00:29 +0700 Subject: [PATCH 0072/1190] Added Maxtium Computer SmartBX --- src/include/86box/machine.h | 1 + src/machine/m_at_socket370.c | 32 ++++++++++++++++++++++++++++ src/machine/machine_table.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0cd3564ee..6edcb6ac4 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -839,6 +839,7 @@ extern int machine_at_atc7020bxii_init(const machine_t *); extern int machine_at_m773_init(const machine_t *); extern int machine_at_ambx133_init(const machine_t *); extern int machine_at_awo671r_init(const machine_t *); +extern int machine_at_smartbx_init(const machine_t *); extern int machine_at_63a1_init(const machine_t *); extern int machine_at_s370sba_init(const machine_t *); extern int machine_at_apas3_init(const machine_t *); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 9be2d45b8..3513859cb 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -402,6 +402,38 @@ machine_at_awo671r_init(const machine_t *model) return ret; } +int +machine_at_smartbx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/smartbx/sbx107.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977ef_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + int machine_at_63a1_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b9ee8af40..d3dcd47f4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15758,6 +15758,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[i440BX] Maxtium Computer SmartBX", + .internal_name = "smartbx", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_smartbx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_A97 | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 393216, + .step = 8192 + }, + .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 + }, /* 440ZX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC From 49aa0edd2256a5adcad2cace7067281bf5f1b951 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 23:14:11 +0700 Subject: [PATCH 0073/1190] Added Dell Dimension X30 --- src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 22 ++++++++++++++++++++ src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 6edcb6ac4..4e4b2e558 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -519,6 +519,7 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); extern int machine_at_decpclpv_init(const machine_t *); +extern int machine_at_dellx30_init(const machine_t *); extern int machine_at_acerv10_init(const machine_t *); extern int machine_at_acera1g_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index d3c7a21d2..dbe91de51 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -482,6 +482,28 @@ machine_at_decpclpv_init(const machine_t *model) return ret; } +int +machine_at_dellx30_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dellx30/shk2a03.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&sis_85c461_device); + device_add(&keyboard_ps2_acer_pci_device); + device_add(&fdc37c665_ide_device); + device_add(&ide_opti611_vlb_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d3dcd47f4..75198b3e3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6936,6 +6936,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has FDC37C665 SIO with OPTi 82c611 IDE onboard */ + { + .name = "[SiS 461] Dell Dimension X30", + .internal_name = "dellx30", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_461, /* Chipset relabeled as Micronics MIC 471 */ + .init = machine_at_dellx30_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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .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 + }, /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. The photo of the board shows an AMIKey KBC which is indeed F. */ From 3b4d6d1f9e708b3599c756c33db238ab33021a7b Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 23:33:20 +0700 Subject: [PATCH 0074/1190] Forgotten one change --- src/machine/machine_table.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 75198b3e3..cac50fbcf 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11240,7 +11240,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -11255,7 +11255,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, @@ -12263,7 +12263,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -12278,7 +12278,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix From d39a8b9867cee2879c05cae606ff7715708223a2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 17:36:56 +0100 Subject: [PATCH 0075/1190] Reverted the PIC fix as it was apparently a red herring. --- src/pic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pic.c b/src/pic.c index f8e83c40b..fa7ff3662 100644 --- a/src/pic.c +++ b/src/pic.c @@ -492,8 +492,7 @@ pic_read(uint16_t addr, void *priv) else dev->data_bus = 0x00; #endif - } else - cpu_block_end = 1; + } /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, simply read whatever is currently on the data bus. */ } From c924a60be7abb1b74644fb7fb375632fc375824f Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Tue, 14 Jan 2025 00:06:25 +0700 Subject: [PATCH 0076/1190] Removed flash device from X30 Fixes BootBlock error --- src/machine/m_at_386dx_486.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index dbe91de51..28e5c8549 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -499,7 +499,6 @@ machine_at_dellx30_init(const machine_t *model) device_add(&keyboard_ps2_acer_pci_device); device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_device); - device_add(&intel_flash_bxt_device); return ret; } From b002fed6023890e0056ea5e54aff74260547938a Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Tue, 14 Jan 2025 00:13:54 +0700 Subject: [PATCH 0077/1190] Removed non-working SmartBX --- src/include/86box/machine.h | 1 - src/machine/m_at_socket370.c | 32 ---------------------------- src/machine/machine_table.c | 41 ------------------------------------ 3 files changed, 74 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 4e4b2e558..48e9be1c3 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -840,7 +840,6 @@ extern int machine_at_atc7020bxii_init(const machine_t *); extern int machine_at_m773_init(const machine_t *); extern int machine_at_ambx133_init(const machine_t *); extern int machine_at_awo671r_init(const machine_t *); -extern int machine_at_smartbx_init(const machine_t *); extern int machine_at_63a1_init(const machine_t *); extern int machine_at_s370sba_init(const machine_t *); extern int machine_at_apas3_init(const machine_t *); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 3513859cb..9be2d45b8 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -402,38 +402,6 @@ machine_at_awo671r_init(const machine_t *model) return ret; } -int -machine_at_smartbx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/smartbx/sbx107.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977ef_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - - return ret; -} - int machine_at_63a1_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cac50fbcf..1aeb28526 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15798,47 +15798,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ - { - .name = "[i440BX] Maxtium Computer SmartBX", - .internal_name = "smartbx", - .type = MACHINE_TYPE_SOCKET370, - .chipset = MACHINE_CHIPSET_INTEL_440BX, - .init = machine_at_smartbx_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET370, - .block = CPU_BLOCK_NONE, - .min_bus = 66666667, - .max_bus = 100000000, - .min_voltage = 1300, - .max_voltage = 3500, - .min_multi = 1.5, - .max_multi = 8.0 - }, - .bus_flags = MACHINE_PS2_A97 | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, - .ram = { - .min = 8192, - .max = 393216, - .step = 8192 - }, - .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 - }, /* 440ZX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC From ffe6af94cfaa48e16cd6e5921705b58091fc6790 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Tue, 14 Jan 2025 00:26:05 +0700 Subject: [PATCH 0078/1190] Removed non-working X30 --- src/include/86box/machine.h | 1 - src/machine/m_at_386dx_486.c | 21 ------------------- src/machine/machine_table.c | 40 ------------------------------------ 3 files changed, 62 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 48e9be1c3..0cd3564ee 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -519,7 +519,6 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); extern int machine_at_decpclpv_init(const machine_t *); -extern int machine_at_dellx30_init(const machine_t *); extern int machine_at_acerv10_init(const machine_t *); extern int machine_at_acera1g_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 28e5c8549..d3c7a21d2 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -482,27 +482,6 @@ machine_at_decpclpv_init(const machine_t *model) return ret; } -int -machine_at_dellx30_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/dellx30/shk2a03.bin", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&sis_85c461_device); - device_add(&keyboard_ps2_acer_pci_device); - device_add(&fdc37c665_ide_device); - device_add(&ide_opti611_vlb_device); - - return ret; -} - static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 1aeb28526..baba2723c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6936,46 +6936,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has FDC37C665 SIO with OPTi 82c611 IDE onboard */ - { - .name = "[SiS 461] Dell Dimension X30", - .internal_name = "dellx30", - .type = MACHINE_TYPE_486_S3, - .chipset = MACHINE_CHIPSET_SIS_461, /* Chipset relabeled as Micronics MIC 471 */ - .init = machine_at_dellx30_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_VLB, - .flags = MACHINE_IDE | MACHINE_APM, - .ram = { - .min = 1024, - .max = 65536, - .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 - }, /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. The photo of the board shows an AMIKey KBC which is indeed F. */ From 29ec9fa9ba5bb383dbda07716a9630e822442e55 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 13 Jan 2025 21:10:12 +0100 Subject: [PATCH 0079/1190] More NCR53c400 fixes (January 13th, 2025) Getting on my nerves, NCR 5380... --- src/include/86box/scsi_ncr5380.h | 1 + src/scsi/scsi_ncr5380.c | 9 +++++---- src/scsi/scsi_ncr53c400.c | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 55692075b..09307fed6 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -104,6 +104,7 @@ typedef struct ncr_t { int state; int clear_req; int wait_data; + int wait_data_back; int wait_complete; int command_pos; int data_pos; diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 0c3af9282..c5fddc801 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -197,7 +197,7 @@ ncr5380_bus_read(ncr_t *ncr) phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); if (phase == SCSI_PHASE_DATA_IN) { - if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext) { + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext || (ncr->wait_data_back == 1)) { ncr5380_log("Phase Data In.\n"); if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; @@ -210,11 +210,12 @@ ncr5380_bus_read(ncr_t *ncr) ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; } else { - if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext) + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext || (ncr->wait_data_back == 1)) ncr->state = STATE_DATAOUT; } } else if (phase == SCSI_PHASE_STATUS) { ncr5380_log("Phase Status.\n"); + ncr->wait_data_back = 0; ncr->cur_bus |= BUS_REQ; ncr->state = STATE_STATUS; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; @@ -359,7 +360,7 @@ ncr5380_bus_update(ncr_t *ncr, int bus) ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); ncr->timer(ncr->priv, ncr->period); } else { - ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); + pclog("DMA mode IN=%d.\n", ncr->data_pos); ncr->clear_req = 3; } @@ -495,7 +496,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 7: /* start DMA Initiator Receive */ - ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); + pclog("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr->dma_initiator_receive_ext) diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 997e8f152..e028c7b42 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -193,6 +193,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) else timer_on_auto(&ncr400->timer, ncr->period); + ncr->wait_data_back = ncr->wait_data; ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); } From c9985798d3f785ef09c0ac053d25a554b95d15e1 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 13 Jan 2025 22:04:29 +0100 Subject: [PATCH 0080/1190] Remove excess logs. --- src/scsi/scsi_ncr5380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index c5fddc801..e5dff88f8 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -360,7 +360,7 @@ ncr5380_bus_update(ncr_t *ncr, int bus) ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); ncr->timer(ncr->priv, ncr->period); } else { - pclog("DMA mode IN=%d.\n", ncr->data_pos); + ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); ncr->clear_req = 3; } @@ -496,7 +496,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 7: /* start DMA Initiator Receive */ - pclog("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); + ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr->dma_initiator_receive_ext) From 40c52048a60057fcee0e31baa186ca7980881670 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Mon, 13 Jan 2025 23:20:57 +0100 Subject: [PATCH 0081/1190] Added a couple of Quantum Fireball SE/EX drives --- src/disk/hdd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index b861b5e50..5243f016b 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -448,9 +448,13 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Quantum Fireball 640AT", .internal_name = "FB64A341", .model = "QUANTUM FIREBALL 640AT", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3.1, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Quantum Fireball TM1080AT", .internal_name = "TM10A462", .model = "QUANTUM FIREBALL TM1.0A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Quantum Fireball TM1.2AT", .internal_name = "TM12A012", .model = "QUANTUM FIREBALL TM1.2A", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball EX5.1AT", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-2] Samsung PLS-31274A", .internal_name = "PLS31274A", .model = "SAMSUNG PLS-31274A", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 45, .track_seek_ms = 4.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 }, { .name = "[ATA-2] Samsung Winner-1", .internal_name = "WNR31601A", .model = "SAMSUNG WNR-31601A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Seagate Medalist (ST3780A)", .internal_name = "ST3780A", .model = "ST3780A", .zones = 8, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 16 }, From 5b101aad81915c64b677c2e92cd5c60be809bd97 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 23:22:37 +0100 Subject: [PATCH 0082/1190] AT KBC: Fast track command AE (enable keyboard) because the LG MultiNet sends command A7 immediately after it, fixes keyboard lock-ups in its CMOS Setup. --- src/device/kbc_at.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 5c3c9ac6e..74be59017 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2127,6 +2127,13 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) } else if (fast_reset && ((val & 0xf0) == 0xf0)) { pulse_output(dev, val & 0x0f); + dev->state = STATE_MAIN_IBF; + return; + } else if (val == 0xae) { + /* Fast track it because of the LG MultiNet. */ + kbc_at_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + dev->state = STATE_MAIN_IBF; return; } From b1f54b9b84b0a653808fef789be987b34cfcbe03 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Tue, 14 Jan 2025 00:31:13 +0000 Subject: [PATCH 0083/1190] Move cyclical logging to the new logging system per obat feedback. --- src/86box.c | 113 +------------------------- src/include/86box/86box.h | 1 - src/include/86box/log.h | 7 ++ src/log.c | 167 +++++++++++++++++++++++++++++++++++--- 4 files changed, 162 insertions(+), 126 deletions(-) diff --git a/src/86box.c b/src/86box.c index 85cbb9957..97c211bee 100644 --- a/src/86box.c +++ b/src/86box.c @@ -254,14 +254,9 @@ static volatile atomic_int pause_ack = 0; #ifndef RELEASE_BUILD -#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 */ +#define LOG_SIZE_BUFFER 1024 /* Log size buffer */ static char buff[LOG_SIZE_BUFFER]; -static char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; -static int32_t cyclic_last_line = 0; -static int32_t log_cycles = 0; static int seen = 0; @@ -322,112 +317,6 @@ pclog_ex(const char *fmt, va_list ap) } -/* -Starfrost, 7-8 January 2025: - -For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. - -Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm -*/ -void -pclog_ex_cyclic(const char* fmt, va_list ap) -{ -#ifndef RELEASE_BUILD - char temp[LOG_SIZE_BUFFER]; - - cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; - - vsprintf(temp, fmt, ap); - - pclog_ensure_stdlog_open(); - - strncpy(cyclic_buff[cyclic_last_line], temp, LOG_SIZE_BUFFER); - - uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; - - // Random numbers - uint32_t base = 257; - uint32_t mod = 1000000007; - - uint32_t repeat_order = 0; - bool is_cycle = false; - - // compute the set of hashes for the current log buffer - for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) - { - if (cyclic_buff[log_line][0] == '\0') - continue; // skip - - for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) - { - hashes[log_line] = hashes[log_line] * base + cyclic_buff[log_line][log_line_char] % mod; - } - } - - - // Now see if there are real cycles... - // We implement a minimum repeat size. - for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) - { - //TODO: Log what we need for cycle 1. - //TODO: Command line option that lets us turn off this behaviour. - for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) - { - if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) - { - repeat_order = check_size; - break; - } - } - - is_cycle = (repeat_order != 0); - - // if there still is a cycle.. - if (is_cycle) - break; - - } - - if (is_cycle) - { - if (cyclic_last_line % repeat_order == 0) - { - log_cycles++; - - if (log_cycles == 1) - { - // 'Replay' the last few log entries so they actually show up - // Todo: is this right? - - for (uint32_t index = cyclic_last_line - 1; index > (cyclic_last_line - repeat_order); index--) - { - // *very important* to prevent out of bounds index - uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; - fprintf(stdlog, "%s", cyclic_buff[real_index]); - - } - - fprintf(stdlog, "%s", temp); // allow normal logging - } - - - if (log_cycles > 1 && log_cycles < 100) - fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log_cycles); - else if (log_cycles == 100) - fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); - } - } - else - { - log_cycles = 0; - fprintf(stdlog, "%s", temp); - } - - cyclic_last_line++; - -#endif - -} void pclog_toggle_suppr(void) diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 05c2a901e..96aeb645c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -189,7 +189,6 @@ extern int config_changed; /* config has changed */ #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 pclog_ex_cyclic(const char* fmt, va_list ap); #endif extern void pclog_toggle_suppr(void); #ifdef _MSC_VER diff --git a/src/include/86box/log.h b/src/include/86box/log.h index 9d3568069..7f0b96d60 100644 --- a/src/include/86box/log.h +++ b/src/include/86box/log.h @@ -12,9 +12,11 @@ * * Authors: Miran Grca, * Fred N. van Kempen, + * Connor Hyde * * Copyright 2021 Miran Grca. * Copyright 2021 Fred N. van Kempen. + * Copyright 2025 Connor Hyde. */ #ifndef EMU_LOG_H @@ -26,11 +28,16 @@ extern "C" { # 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 */ + /* Function prototypes. */ extern void log_set_suppr_seen(void *priv, int suppr_seen); extern void log_set_dev_name(void *priv, char *dev_name); # ifdef HAVE_STDARG_H extern void log_out(void *priv, const char *fmt, va_list); +extern void log_out_cyclic(void* priv, const char *fmt, va_list); extern void log_fatal(void *priv, const char *fmt, ...); # endif extern void *log_open(char *dev_name); diff --git a/src/log.c b/src/log.c index b5267d70b..a4d84e616 100644 --- a/src/log.c +++ b/src/log.c @@ -12,12 +12,15 @@ * * Authors: Miran Grca, * Fred N. van Kempen, - * + * Connor Hyde + * * Copyright 2021 Miran Grca. * Copyright 2021 Fred N. van Kempen. + * Copyright 2025 Connor Hyde. */ #include #include +#include #include #include #include @@ -36,13 +39,31 @@ #ifndef RELEASE_BUILD typedef struct log_t { - char buff[1024]; - char *dev_name; - int seen; - int suppr_seen; + char buff[1024]; + char *dev_name; + int seen; + int suppr_seen; + char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; // Cyclical log buffer. This is 32kb, might calloc? + int32_t cyclic_last_line; + int32_t log_cycles; } log_t; extern FILE *stdlog; /* file to log output to */ +// Functions only used in this translation unit +void log_ensure_stdlog_open(void); + +void +log_ensure_stdlog_open(void) +{ + if (stdlog == NULL) { + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; + } +} void log_set_suppr_seen(void *priv, int suppr_seen) @@ -91,14 +112,7 @@ log_out(void *priv, const char *fmt, va_list ap) if (strcmp(fmt, "") == 0) return; - if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; - } + log_ensure_stdlog_open(); vsprintf(temp, fmt, ap); if (log->suppr_seen && !strcmp(log->buff, temp)) @@ -117,6 +131,131 @@ log_out(void *priv, const char *fmt, va_list ap) fflush(stdlog); } + +/* +Starfrost, 7-8 January 2025: + +For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. + +Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm +*/ +void +log_out_cyclic(void* priv, const char* fmt, va_list ap) +{ +#ifndef RELEASE_BUILD + // get our new logging system instance. + log_t* log = (log_t*)priv; + + // does the log actually exist? + if (!log) + return; + + // is the string empty? + if (fmt[0] == '\0') + return; + + // ensure stdlog is open + log_ensure_stdlog_open(); + + char temp[LOG_SIZE_BUFFER] = {0}; + + log->cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; + + vsprintf(temp, fmt, ap); + + log_copy(log, log->cyclic_buff[log->cyclic_last_line], temp, LOG_SIZE_BUFFER); + + uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; + + // Random numbers + uint32_t base = 257; + uint32_t mod = 1000000007; + + uint32_t repeat_order = 0; + bool is_cycle = false; + + // compute the set of hashes for the current log buffer + for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) + { + if (log->cyclic_buff[log_line][0] == '\0') + continue; // skip + + for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) + { + hashes[log_line] = hashes[log_line] * base + log->cyclic_buff[log_line][log_line_char] % mod; + } + } + + + // Now see if there are real cycles... + // We implement a minimum repeat size. + for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) + { + //TODO: Log what we need for cycle 1. + //TODO: Command line option that lets us turn off this behaviour. + for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) + { + if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) + { + repeat_order = check_size; + break; + } + } + + is_cycle = (repeat_order != 0); + + // if there still is a cycle.. + if (is_cycle) + break; + + } + + if (is_cycle) + { + if (log->cyclic_last_line % repeat_order == 0) + { + log->log_cycles++; + + if (log->log_cycles == 1) + { + // 'Replay' the last few log entries so they actually show up + // Todo: is this right? + + for (uint32_t index = log->cyclic_last_line - 1; index > (log->cyclic_last_line - repeat_order); index--) + { + // *very important* to prevent out of bounds index + uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; + log_copy(log, temp, log->cyclic_buff[real_index], LOG_SIZE_BUFFER); + + fprintf(stdlog, "%s", log->cyclic_buff[real_index]); + + } + + // restore the original line + log_copy(log, temp, log->cyclic_buff[log->cyclic_last_line], LOG_SIZE_BUFFER); + + fprintf(stdlog, "%s", temp); // allow normal logging + } + + + if (log->log_cycles > 1 && log->log_cycles < 100) + fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log->log_cycles); + else if (log->log_cycles == 100) + fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); + } + } + else + { + log->log_cycles = 0; + fprintf(stdlog, "%s", temp); + } + + log->cyclic_last_line++; + +#endif + +} + void log_fatal(void *priv, const char *fmt, ...) { @@ -145,6 +284,8 @@ log_open(char *dev_name) log->dev_name = dev_name; log->suppr_seen = 1; + log->cyclic_last_line = 0; + log->log_cycles = 0; return (void *) log; } From 8fda1aca83241f04d02cea5efe2db78d76a539a8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2025 01:35:22 +0100 Subject: [PATCH 0084/1190] Acer V35N: Do not add the NVR - it is already added by the Super I/O chip. --- src/machine/m_at_socket7.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index f80d2d421..2dbb83684 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -58,10 +58,6 @@ machine_at_acerv35n_init(const machine_t *model) return ret; machine_at_common_init_ex(model, 2); - /* Yes, it's called amstrad_mega_pc_nvr_device, but it's basically the - standard AT NVR, just initialized to 0x00's (perhaps that should be the - default behavior?). */ - device_add(&amstrad_megapc_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); From efd5a6a47483e454d2cf496c87488aee939c2f34 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2025 02:38:44 +0100 Subject: [PATCH 0085/1190] SCAMP: Fixed EMS memory states, fixes #1966. --- src/chipset/scamp.c | 140 ++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 122318862..00f9798cb 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -101,6 +101,8 @@ typedef struct scamp_t { int ram_interleaved[2]; int ibank_shift[2]; + int ram_flags[24]; + port_92_t *port_92; } scamp_t; @@ -593,6 +595,35 @@ scamp_ems_write(uint32_t addr, uint8_t val, void *priv) ram[addr] = val; } +static void +scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size) +{ + uint8_t flags; + + if ((addr >= 0x000a0000) && (addr < 0x00100000)) { + flags = dev->ram_flags[(addr - 0x000a0000) >> 14]; + + if (flags & 4) + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else switch (flags & 3) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } + } +} + static void recalc_ems(scamp_t *dev) { @@ -630,34 +661,48 @@ recalc_ems(scamp_t *dev) if (new_mappings[segment] < (mem_size * 1024)) { mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]); mem_mapping_enable(&dev->ems_mappings[segment]); - } else + dev->ram_flags[segment] |= 0x04; + } else { mem_mapping_disable(&dev->ems_mappings[segment]); + dev->ram_flags[segment] &= 0xfb; + } + + scamp_mem_update_state(dev, 0xa0000 + segment * 0x4000, 0x4000); } } + + flushmmucache_nopc(); } static void -shadow_control(uint32_t addr, uint32_t size, int state, int ems_enable) +shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state) { - if (ems_enable) - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else - switch (state) { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - default: - break; - } + dev->ram_flags[(addr - 0x000a0000) >> 14] &= 0xfc; + dev->ram_flags[(addr - 0x000a0000) >> 14] |= state; + + if (size == 0x8000) { + dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] &= 0xfc; + dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] |= state; + } + + switch (state) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } + + scamp_mem_update_state(dev, addr, size); flushmmucache_nopc(); } @@ -669,47 +714,38 @@ shadow_recalc(scamp_t *dev) uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS]; uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS]; uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS]; - uint32_t ems_enable; - - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) { - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP) /*Axxx/Bxxx/Dxxx*/ - ems_enable = (dev->cfg_regs[CFG_EMSEN2] & 0xf) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 4) | ((dev->cfg_regs[CFG_EMSEN2] & 0xf0) << 8); - else /*Cxxx/Dxxx/Exxx*/ - ems_enable = (dev->cfg_regs[CFG_EMSEN2] << 8) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 16); - } else - ems_enable = 0; /*Enabling remapping will disable all shadowing*/ if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) mem_remap_top(384); - shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00001); - shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00002); - shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00004); - shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00008); + shadow_control(dev, 0xa0000, 0x4000, abaxs & 3); + shadow_control(dev, 0xa0000, 0x4000, abaxs & 3); + shadow_control(dev, 0xa8000, 0x4000, (abaxs >> 2) & 3); + shadow_control(dev, 0xa8000, 0x4000, (abaxs >> 2) & 3); - shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00010); - shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00020); - shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00040); - shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00080); + shadow_control(dev, 0xb0000, 0x4000, (abaxs >> 4) & 3); + shadow_control(dev, 0xb0000, 0x4000, (abaxs >> 4) & 3); + shadow_control(dev, 0xb8000, 0x4000, (abaxs >> 6) & 3); + shadow_control(dev, 0xb8000, 0x4000, (abaxs >> 6) & 3); - shadow_control(0xc0000, 0x4000, caxs & 3, ems_enable & 0x00100); - shadow_control(0xc4000, 0x4000, (caxs >> 2) & 3, ems_enable & 0x00200); - shadow_control(0xc8000, 0x4000, (caxs >> 4) & 3, ems_enable & 0x00400); - shadow_control(0xcc000, 0x4000, (caxs >> 6) & 3, ems_enable & 0x00800); + shadow_control(dev, 0xc0000, 0x4000, caxs & 3); + shadow_control(dev, 0xc4000, 0x4000, (caxs >> 2) & 3); + shadow_control(dev, 0xc8000, 0x4000, (caxs >> 4) & 3); + shadow_control(dev, 0xcc000, 0x4000, (caxs >> 6) & 3); - shadow_control(0xd0000, 0x4000, daxs & 3, ems_enable & 0x01000); - shadow_control(0xd4000, 0x4000, (daxs >> 2) & 3, ems_enable & 0x02000); - shadow_control(0xd8000, 0x4000, (daxs >> 4) & 3, ems_enable & 0x04000); - shadow_control(0xdc000, 0x4000, (daxs >> 6) & 3, ems_enable & 0x08000); + shadow_control(dev, 0xd0000, 0x4000, daxs & 3); + shadow_control(dev, 0xd4000, 0x4000, (daxs >> 2) & 3); + shadow_control(dev, 0xd8000, 0x4000, (daxs >> 4) & 3); + shadow_control(dev, 0xdc000, 0x4000, (daxs >> 6) & 3); - shadow_control(0xe0000, 0x4000, feaxs & 3, ems_enable & 0x10000); - shadow_control(0xe4000, 0x4000, feaxs & 3, ems_enable & 0x20000); - shadow_control(0xe8000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x40000); - shadow_control(0xec000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x80000); + shadow_control(dev, 0xe0000, 0x4000, feaxs & 3); + shadow_control(dev, 0xe4000, 0x4000, feaxs & 3); + shadow_control(dev, 0xe8000, 0x4000, (feaxs >> 2) & 3); + shadow_control(dev, 0xec000, 0x4000, (feaxs >> 2) & 3); - shadow_control(0xf0000, 0x8000, (feaxs >> 4) & 3, 0); - shadow_control(0xf8000, 0x8000, (feaxs >> 6) & 3, 0); + shadow_control(dev, 0xf0000, 0x8000, (feaxs >> 4) & 3); + shadow_control(dev, 0xf8000, 0x8000, (feaxs >> 6) & 3); } static void From c36e6be6e248da16b2828a84a76dc57364e912d9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2025 06:27:41 +0100 Subject: [PATCH 0086/1190] NEAT: Fix EMS and implement Shadow RAM and top 128K of conventional memory on/off, closes #1375. --- src/chipset/neat.c | 367 +++++++++++++++++++++++++++++---------------- 1 file changed, 238 insertions(+), 129 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 97c4b8f1a..94f0d66e1 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -37,6 +37,9 @@ #define EMS_MAXPAGE 4 #define EMS_PGSIZE 16384 +#define EMS_PGMASK 16383 + +#define REG_MASK 0x0f /* CS8221 82C211 controller registers. */ #define REG_RA0 0x60 /* PROCCLK selector */ @@ -194,37 +197,47 @@ #define RB10_P0EXT 0xc0 /* page 0 extension */ #define RB10_P0EXT_SH 6 -#define REG_RB11 0x6f /* Miscellaneous */ -#define RB11_MASK 0xe6 /* 111R R11R */ -#define RB11_GA20 0x02 /* gate for A20 */ -#define RB11_RASTMO 0x04 /* enable RAS timeout counter */ -#define RB11_EMSLEN 0xe0 /* EMS memory chunk size */ -#define RB11_EMSLEN_SH 5 +#define REG_RB12 0x6f /* Miscellaneous */ +#define RB12_MASK 0xe6 /* 111R R11R */ +#define RB12_GA20 0x02 /* gate for A20 */ +#define RB12_RASTMO 0x04 /* enable RAS timeout counter */ +#define RB12_EMSLEN 0xe0 /* EMS memory chunk size */ +#define RB12_EMSLEN_SH 5 -typedef struct emspage_t { - int8_t enabled; /* 1=ENABLED */ +#define RAM_FLAG_EMS 0x08 +#define RAM_FLAG_ROMCS 0x04 +#define RAM_FLAG_SHREAD 0x02 +#define RAM_FLAG_SHWRITE 0x01 +#define RAM_FMASK_EMS 0x08 +#define RAM_FMASK_SHADOW 0x07 + +typedef struct ram_page_t { + int8_t enabled; /* 1=ENABLED */ char pad; - uint16_t page; /* selected page in EMS block */ - uint32_t start; /* start of EMS in RAM */ - uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ -} emspage_t; + uint32_t phys_base; + uint32_t virt_base; + mem_mapping_t mapping; /* mapping entry for page */ +} ram_page_t; typedef struct neat_t { - uint8_t regs[128]; /* all the CS8221 registers */ - uint8_t indx; /* programmed index into registers */ + uint8_t ram_flags[32]; + uint8_t regs[128]; /* all the CS8221 registers */ + uint8_t indx; /* programmed index into registers */ - char pad; + char pad; - uint16_t ems_base; /* configured base address */ - uint16_t ems_oldbase; - uint32_t ems_frame; /* configured frame address */ - uint32_t ems_oldframe; - uint16_t ems_size; /* EMS size in KB */ - uint16_t ems_pages; /* EMS size in pages */ - emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */ + uint16_t ems_base; /* configured base address */ + uint32_t ems_frame; /* configured frame address */ + uint16_t ems_size; /* EMS size in KB */ + uint16_t ems_pages; /* EMS size in pages */ + + ram_page_t ems[EMS_MAXPAGE]; /* EMS page registers */ + ram_page_t shadow[32]; /* Shadow RAM pages */ } neat_t; +static uint8_t defaults[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 }; + #ifdef ENABLE_NEAT_LOG int neat_do_log = ENABLE_NEAT_LOG; @@ -247,11 +260,11 @@ neat_log(const char *fmt, ...) static uint8_t ems_readb(uint32_t addr, void *priv) { - neat_t *dev = (neat_t *) priv; - uint8_t ret = 0xff; + ram_page_t *dev = (ram_page_t *) priv; + uint8_t ret = 0xff; /* Grab the data. */ - ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); + ret = *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]); return ret; } @@ -260,11 +273,11 @@ ems_readb(uint32_t addr, void *priv) static uint16_t ems_readw(uint32_t addr, void *priv) { - neat_t *dev = (neat_t *) priv; - uint16_t ret = 0xffff; + ram_page_t *dev = (ram_page_t *) priv; + uint16_t ret = 0xffff; /* Grab the data. */ - ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); + ret = *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]); return ret; } @@ -273,40 +286,113 @@ ems_readw(uint32_t addr, void *priv) static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - neat_t *dev = (neat_t *) priv; + ram_page_t *dev = (ram_page_t *) priv; /* Write the data. */ - *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; + *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val; } /* Write one word to paged RAM. */ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - neat_t *dev = (neat_t *) priv; + ram_page_t *dev = (ram_page_t *) priv; /* Write the data. */ - *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; + *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val; +} + +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->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) { + dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask; + dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags; + + new_flags = dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]; + + neat_log("neat_mem_update_state(): %08X-%08X: %02X\n", addr, addr + size - 1, new_flags); + + if (new_flags & RAM_FLAG_EMS) + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else if (new_flags & RAM_FLAG_ROMCS) + mem_set_mem_state(addr, size, MEM_READ_ROMCS | MEM_WRITE_ROMCS); + else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } + } + + flushmmucache_nopc(); +} + +static void +shadow_recalc(neat_t *dev) +{ + for (uint8_t i = 8; i < 32; i++) { + int romcs = 0; + int write = 1; + int shadow_reg = REG_RB3 + ((i - 8) >> 3); + int shadow_bit = i & 7; + int ram_flags; + int read; + + if (i > 16) { + int rb1_romcs_bit = 7 - (i >> 2); + int rb1_write_bit = rb1_romcs_bit + 4; + + romcs = !(dev->regs[REG_RB1] & (1 << rb1_romcs_bit)); + write = !(dev->regs[REG_RB1] & (1 << rb1_write_bit)); + } else if (i <= 8) + shadow_bit ^= 4; + + read = dev->regs[shadow_reg] & (1 << shadow_bit); + write = write && read; + + ram_flags = romcs ? RAM_FLAG_ROMCS : 0x00; + ram_flags |= read ? RAM_FLAG_SHREAD : 0x00; + ram_flags |= write ? RAM_FLAG_SHWRITE : 0x00; + + if ((ram_flags > 0x00) && !(ram_flags & RAM_FLAG_ROMCS)) + mem_mapping_set_addr(&(dev->shadow[i].mapping), dev->shadow[i].virt_base, EMS_PGSIZE); + else + mem_mapping_disable(&(dev->shadow[i].mapping)); + + neat_mem_update_state(dev, dev->shadow[i].virt_base, EMS_PGSIZE, ram_flags, RAM_FMASK_SHADOW); + } } /* Re-calculate the active-page physical address. */ static void -ems_recalc(neat_t *dev, emspage_t *ems) +ems_recalc(neat_t *dev, ram_page_t *ems) { - if (ems->page >= dev->ems_pages) { - /* That page does not exist. */ - ems->enabled = 0; - } + uint32_t page = ems->phys_base / EMS_PGSIZE; - /* Pre-calculate the page address in EMS RAM. */ - ems->addr = ram + ems->start + (ems->page * EMS_PGSIZE); + if ((dev->regs[REG_RB7] & RB7_EMSEN) && ems->enabled && + (page >= 0x40) && (page < (0x40 + dev->ems_pages))) { + neat_log("ems_recalc(): %08X-%08X -> %08X-%08X\n", + ems->virt_base, ems->virt_base + EMS_PGSIZE - 1, + ems->phys_base, ems->phys_base + EMS_PGSIZE - 1); + mem_mapping_set_addr(&ems->mapping, ems->virt_base, EMS_PGSIZE); - if (ems->enabled) { /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&ems->mapping, ems->addr); + mem_mapping_set_exec(&ems->mapping, ram + ems->phys_base); - /* Enable this page. */ - mem_mapping_enable(&ems->mapping); + if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS); #if NEAT_DEBUG > 1 neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", @@ -315,15 +401,18 @@ ems_recalc(neat_t *dev, emspage_t *ems) } else { /* Disable this page. */ mem_mapping_disable(&ems->mapping); + + if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS); } } static void ems_write(uint16_t port, uint8_t val, void *priv) { - neat_t *dev = (neat_t *) priv; - emspage_t *ems; - int vpage; + neat_t *dev = (neat_t *) priv; + ram_page_t *ems; + int vpage; #if NEAT_DEBUG > 1 neat_log("NEAT: ems_write(%04x, %02x)\n", port, val); @@ -337,8 +426,7 @@ ems_write(uint16_t port, uint8_t val, void *priv) case 0x0008: case 0x0009: ems->enabled = !!(val & 0x80); - ems->page &= 0x0180; /* clear lower bits */ - ems->page |= (val & 0x7f); /* add new bits */ + ems->phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE); ems_recalc(dev, ems); break; default: @@ -358,7 +446,7 @@ ems_read(uint16_t port, void *priv) switch (port & 0x000f) { case 0x0008: /* page number register */ - ret = dev->ems[vpage].page & 0x7f; + ret = (dev->ems[vpage].phys_base / EMS_PGSIZE) & 0x7f; if (dev->ems[vpage].enabled) ret |= 0x80; break; @@ -373,68 +461,21 @@ ems_read(uint16_t port, void *priv) return ret; } -/* Initialize the EMS module. */ static void -ems_init(neat_t *dev, int en) +ems_update(neat_t *dev, int en) { - uint8_t j; - - /* Remove if needed. */ - if (!en) { - if (dev->ems_base > 0) - for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { - /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); - - /* Remove I/O handler. */ - io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - } - -#ifdef ENABLE_NEAT_LOG - neat_log("NEAT: EMS disabled\n"); -#endif - - return; - } - - /* Get configured I/O address. */ - j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; - dev->ems_base = 0x0208 + (0x10 * j); - - /* Get configured frame address. */ - j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; - dev->ems_frame = 0xC0000 + (EMS_PGSIZE * j); - - /* - * For each supported page (we can have a maximum of 4), - * create, initialize and disable the mappings, and set - * up the I/O control handler. - */ for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { - /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE, - ems_readb, ems_readw, NULL, - ems_writeb, ems_writew, NULL, - ram, MEM_MAPPING_EXTERNAL, - dev); - - /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); - /* Set up an I/O port handler. */ - io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + io_handler(en, dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - /* - * TODO: update the 'high_mem' mapping to reflect that we now - * have NN MB less extended memory available.. - */ + if (en) + dev->ems[i].virt_base = dev->ems_frame + (i * EMS_PGSIZE); + + ems_recalc(dev, &(dev->ems[i])); } - neat_log("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n", - dev->ems_base, dev->ems_frame); + flushmmucache_nopc(); } static void @@ -442,6 +483,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) { neat_t *dev = (neat_t *) priv; uint8_t xval; + uint8_t j; uint8_t *reg; int i; @@ -493,6 +535,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB1: val &= RB1_MASK; *reg = (*reg & ~RB1_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg); #endif @@ -501,6 +544,10 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB2: val &= RB2_MASK; *reg = (*reg & ~RB2_MASK) | val; + if (val & RB2_TOP128) + neat_mem_update_state(dev, 0x00080000, 0x00020000, RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE, RAM_FMASK_SHADOW); + else + neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, RAM_FMASK_SHADOW); #if NEAT_DEBUG > 1 neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); #endif @@ -509,6 +556,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB3: val &= RB3_MASK; *reg = (*reg & ~RB3_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg); #endif @@ -517,6 +565,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB4: val &= RB4_MASK; *reg = (*reg & ~RB4_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg); #endif @@ -525,6 +574,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB5: val &= RB5_MASK; *reg = (*reg & ~RB5_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg); #endif @@ -544,10 +594,9 @@ neat_write(uint16_t port, uint8_t val, void *priv) #if NEAT_DEBUG > 1 neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); #endif - if (val & RB7_EMSEN) - ems_init(dev, 1); - else if (xval & RB7_EMSEN) - ems_init(dev, 0); + + if (xval & RB7_EMSEN) + ems_update(dev, !!(val & RB7_EMSEN)); if (xval & RB7_UMAREL) { if (val & RB7_UMAREL) @@ -571,10 +620,19 @@ neat_write(uint16_t port, uint8_t val, void *priv) #if NEAT_DEBUG > 1 neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); #endif - if (dev->regs[REG_RB7] & RB7_EMSEN) { - ems_init(dev, 0); - ems_init(dev, 1); - } + + ems_update(dev, 0); + + /* Get configured I/O address. */ + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); + + /* Get configured frame address. */ + j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + + if (dev->regs[REG_RB7] & RB7_EMSEN) + ems_update(dev, 1); break; case REG_RB10: @@ -584,23 +642,29 @@ neat_write(uint16_t port, uint8_t val, void *priv) neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); #endif - dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21; - dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21; - dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21; - dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21; - for (i = 0; i < EMS_MAXPAGE; i++) - ems_recalc(dev, &dev->ems[i]); + dev->ems[3].phys_base = (dev->ems[3].phys_base & 0x001fffff) | + (((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21); + dev->ems[2].phys_base = (dev->ems[2].phys_base & 0x001fffff) | + (((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21); + dev->ems[1].phys_base = (dev->ems[1].phys_base & 0x001fffff) | + (((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21); + dev->ems[0].phys_base = (dev->ems[0].phys_base & 0x001fffff) | + (((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21); + + if (dev->regs[REG_RB7] & RB7_EMSEN) + for (i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &dev->ems[i]); break; - case REG_RB11: - val &= RB11_MASK; - *reg = (*reg & ~RB11_MASK) | val; + case REG_RB12: + val &= RB12_MASK; + *reg = (*reg & ~RB12_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB11=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg); #endif - i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH; + i = (val & RB12_EMSLEN) >> RB12_EMSLEN_SH; switch (i) { - case 0: /* "less than 2MB" */ + case 0: /* "less than 1MB" */ dev->ems_size = 512; break; @@ -617,10 +681,18 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; } dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; + + if (dev->regs[REG_RB7] & RB7_EMSEN) + for (i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &dev->ems[i]); + if (dev->regs[REG_RB7] & RB7_EMSEN) { neat_log("NEAT: EMS %iKB (%i pages)\n", dev->ems_size, dev->ems_pages); } + + mem_a20_key = val & RB12_GA20; + mem_a20_recalc(); break; default: @@ -629,6 +701,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; } break; + default: break; } @@ -646,8 +719,10 @@ neat_read(uint16_t port, void *priv) break; case 0x23: - if ((dev->indx >= 0x60) && (dev->indx <= 0x6f)) + if ((dev->indx >= 0x60) && (dev->indx <= 0x6e)) ret = dev->regs[dev->indx]; + else if (dev->indx == 0x6f) + ret = (dev->regs[dev->indx] & 0xfd) | (mem_a20_key & 2); break; default: @@ -674,16 +749,50 @@ neat_init(UNUSED(const device_t *info)) { neat_t *dev; uint8_t dram_mode = 0; - uint8_t i; + uint8_t j; /* Create an instance. */ dev = (neat_t *) malloc(sizeof(neat_t)); memset(dev, 0x00, sizeof(neat_t)); + /* Get configured I/O address. */ + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); + + /* Get configured frame address. */ + j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + + mem_mapping_disable(&ram_mid_mapping); + + /* + * For each supported page (we can have a maximum of 4), + * create, initialize and disable the mappings, and set + * up the I/O control handler. + */ + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i].mapping, + dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE, + ems_readb, ems_readw, NULL, + ems_writeb, ems_writew, NULL, + ram, MEM_MAPPING_INTERNAL, + &(dev->ems[i])); + + /* Disable for now. */ + mem_mapping_disable(&dev->ems[i].mapping); + } + + for (uint8_t i = 0; i < 32; i++) { + dev->shadow[i].virt_base = dev->shadow[i].phys_base = + (i * EMS_PGSIZE) + 0x00080000; + dev->shadow[i].enabled = 1; + } + /* Initialize some of the registers to specific defaults. */ - for (i = REG_RA0; i <= REG_RB11; i++) { + for (uint8_t i = REG_RA0; i <= REG_RB12; i++) { dev->indx = i; - neat_write(0x0023, 0x00, dev); + neat_write(0x0023, defaults[i & REG_MASK], dev); } /* From b36d2c5abad252cb073cf382120762c22d7daccf Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:59:53 +0100 Subject: [PATCH 0087/1190] Few corrections to Quantum Fireball series --- src/disk/hdd.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 5243f016b..035bc83c6 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -448,13 +448,6 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Quantum Fireball 640AT", .internal_name = "FB64A341", .model = "QUANTUM FIREBALL 640AT", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3.1, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Quantum Fireball TM1080AT", .internal_name = "TM10A462", .model = "QUANTUM FIREBALL TM1.0A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Quantum Fireball TM1.2AT", .internal_name = "TM12A012", .model = "QUANTUM FIREBALL TM1.2A", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-2] Samsung PLS-31274A", .internal_name = "PLS31274A", .model = "SAMSUNG PLS-31274A", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 45, .track_seek_ms = 4.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 }, { .name = "[ATA-2] Samsung Winner-1", .internal_name = "WNR31601A", .model = "SAMSUNG WNR-31601A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Seagate Medalist (ST3780A)", .internal_name = "ST3780A", .model = "ST3780A", .zones = 8, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 16 }, @@ -501,6 +494,9 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92049U6)", .internal_name = "92049U6", .model = "Maxtor 92049U6", .zones = 16, .avg_spt = 90, .heads = 6, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92732U8)", .internal_name = "92732U8", .model = "Maxtor 92732U8", .zones = 16, .avg_spt = 90, .heads = 8, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-4] Quantum Bigfoot TX4.3AT", .internal_name = "TX043A011", .model = "QUANTUM BIGFOOT TX4.3A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[ATA-4] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 2122", .internal_name = "ST32122A", .model = "ST32122A", .zones = 16, .avg_spt = 115, .heads = 2, .rpm = 4500, .full_stroke_ms = 23, .track_seek_ms = 3.8, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 3321", .internal_name = "ST33221A", .model = "ST33221A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 4321", .internal_name = "ST34321A", .model = "ST34321A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, @@ -513,9 +509,15 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-4] Western Digital Caviar 33200", .internal_name = "AC33200", .model = "WDC AC33200-00LA", .zones = 16, .avg_spt = 110, .heads = 5, .rpm = 5200, .full_stroke_ms = 40, .track_seek_ms = 3, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-5] IBM Travelstar 6GN", .internal_name = "DARA206000", .model = "IBM-DARA-206000", .zones = 12, .avg_spt = 92, .heads = 2, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] IBM Travelstar 9GN", .internal_name = "DARA209000", .model = "IBM-DARA-209000", .zones = 12, .avg_spt = 92, .heads = 3, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] IBM/Hitachi Travelstar 12GN", .internal_name = "DARA212000", .model = "IBM-DARA-212000", .zones = 12, .avg_spt = 92, .heads = 4, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Either Hitachi or IBM OEM + { .name = "[ATA-5] IBM/Hitachi Travelstar 12GN", .internal_name = "DARA212000", .model = "IBM-DARA-212000", .zones = 12, .avg_spt = 92, .heads = 4, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Either Hitachi or IBM OEM { .name = "[ATA-5] Maxtor DiamondMax VL 17", .internal_name = "90871U2", .model = "Maxtor 90871U2", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-5] Maxtor DiamondMax VL 20", .internal_name = "91021U2", .model = "Maxtor 91021U2", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Quantum Fireball EX3.2A", .internal_name = "EX32A012", .model = "QUANTUM FIREBALL EX3.2A", .zones = 1, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX6.4A", .internal_name = "EX64A012", .model = "QUANTUM FIREBALL EX6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV0682D)", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 89, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, From 46426d5e929bb9d2d24f2e85118c412ce4d2aa3f Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:16:04 +0100 Subject: [PATCH 0088/1190] Update cdrom.h for TEAC CD-532E/NEC CDR-1900A --- src/include/86box/cdrom.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index efb45ecfb..7272f5e8c 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -95,6 +95,7 @@ enum CDROM_TYPE_NEC_77_106, CDROM_TYPE_NEC_211_100, CDROM_TYPE_NEC_464_105, + CDROM_TYPE_NEC_CDR_1900A_100, CDROM_TYPE_ShinaKen_DM3x1S_104, CDROM_TYPE_SONY_CDU541_10i, CDROM_TYPE_SONY_CDU561_18k, @@ -102,6 +103,7 @@ enum CDROM_TYPE_PHILIPS_CDD2600_107, CDROM_TYPE_PIONEER_DRM604X_2403, CDROM_TYPE_PLEXTOR_PX32TS_103, + CDROM_TYPE_TEAC_CD532E_20A, CDROM_TYPE_TEAC_CD50_100, CDROM_TYPE_TEAC_R55S_10R, CDROM_TYPE_TEXEL_DM3024_100, @@ -145,9 +147,11 @@ static const struct { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, + { "NEC", "CDR-1900A", "1.00", "NEC CDR-1900A 1.00", "NEC_CDR-1900A_1.00", BUS_TYPE_IDE }, { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, + { "TEAC", "CD-532E", "2.0A", "TEAC CD-532E 2.0A", "TEAC_CD_532E_2.0A", BUS_TYPE_IDE }, { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, { "CHINON", "CD-ROM CDS-431", "H42 ", "[SCSI-1] CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, From 68a8392baf2cbd5d94554ac43099c4f59949bd9a Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:31:21 +0100 Subject: [PATCH 0089/1190] Add TEAC CD-532E (32X)/NEC CDR-1900A (32X) --- src/scsi/scsi_cdrom.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index ad7f0d1c0..ddbb65849 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -4097,6 +4097,10 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "3.08 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */ break; + case CDROM_TYPE_NEC_CDR_1900A_100: + ide_padstr((char *) (ide->buffer + 23), "1.00 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "NEC CDR-1900A ", 40); /* Model */ + break; case CDROM_TYPE_PHILIPS_PCA403CD_U31P: ide_padstr((char *) (ide->buffer + 23), "U31P ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "PHILIPS CD-ROM PCA403CD ", 40); /* Model */ @@ -4109,6 +4113,10 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */ break; + case CDROM_TYPE_TEAC_CD_532E_20A: + ide_padstr((char *) (ide->buffer + 23), "2.0A ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TEAC CD-532E ", 40); /* Model */ + break; case CDROM_TYPE_TOSHIBA_5302TA_0305: ide_padstr((char *) (ide->buffer + 23), "0305 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5302TA ", 40); /* Model */ From 514abd4abde47b7e968d9f93194e3756964ba634 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:42:49 +0100 Subject: [PATCH 0090/1190] Update scsi_cdrom.c --- 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 ddbb65849..cdf653626 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -4113,7 +4113,7 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */ break; - case CDROM_TYPE_TEAC_CD_532E_20A: + case CDROM_TYPE_TEAC_CD532E_20A: ide_padstr((char *) (ide->buffer + 23), "2.0A ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "TEAC CD-532E ", 40); /* Model */ break; From 1aee794ae1cae4f684fed8251bd4ccef0bc09d27 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:58:29 +0100 Subject: [PATCH 0091/1190] Update cdrom.h From 9bb96bd836eae91c53725ae162f5d0c8fdd46e41 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 18:47:54 +0100 Subject: [PATCH 0092/1190] Fireball EX/CR now complete --- src/disk/hdd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 035bc83c6..e79f0f6c0 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -495,6 +495,7 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92732U8)", .internal_name = "92732U8", .model = "Maxtor 92732U8", .zones = 16, .avg_spt = 90, .heads = 8, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-4] Quantum Bigfoot TX4.3AT", .internal_name = "TX043A011", .model = "QUANTUM BIGFOOT TX4.3A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, { .name = "[ATA-4] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Quantum Fireball SE4.3A", .internal_name = "SE43A011", .model = "QUANTUM FIREBALL SE4.3A", .zones = 2, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 2122", .internal_name = "ST32122A", .model = "ST32122A", .zones = 16, .avg_spt = 115, .heads = 2, .rpm = 4500, .full_stroke_ms = 23, .track_seek_ms = 3.8, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, @@ -517,7 +518,10 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-5] Quantum Fireball EX6.4A", .internal_name = "EX64A012", .model = "QUANTUM FIREBALL EX6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR4.3A", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR6.4A", .internal_name = "CR64A011", .model = "QUANTUM FIREBALL CR6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR8.4A", .internal_name = "CR84A011", .model = "QUANTUM FIREBALL CR8.4A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR13.0A", .internal_name = "CR13A011", .model = "QUANTUM FIREBALL CR13.0A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV0682D)", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 89, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, From 70891ffdb5b944c907b85f094a747c1ccdc3a303 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 18:59:31 +0100 Subject: [PATCH 0093/1190] Updated INQUIRY --- src/include/86box/cdrom.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 7272f5e8c..07ca72d36 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -80,9 +80,11 @@ enum CDROM_TYPE_NEC_273_420, CDROM_TYPE_NEC_280_105, CDROM_TYPE_NEC_280_308, + CDROM_TYPE_NEC_CDR_1900A_100 CDROM_TYPE_PHILIPS_PCA403CD_U31P, CDROM_TYPE_SONY_CDU76_10i, CDROM_TYPE_SONY_CDU311_30h, + CDROM_TYPE_TEAC_CD532E_20A, CDROM_TYPE_TOSHIBA_5302TA_0305, CDROM_TYPE_TOSHIBA_5702B_TA70, CDROM_TYPE_CHINON_CDS431_H42, From 1d6a49d7494c4a5cb3251161e286d3004bf5b9a8 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Tue, 14 Jan 2025 19:11:56 +0100 Subject: [PATCH 0094/1190] Update cdrom.h --- src/include/86box/cdrom.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 07ca72d36..5d90d84a4 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -80,7 +80,7 @@ enum CDROM_TYPE_NEC_273_420, CDROM_TYPE_NEC_280_105, CDROM_TYPE_NEC_280_308, - CDROM_TYPE_NEC_CDR_1900A_100 + CDROM_TYPE_NEC_CDR_1900A_100, CDROM_TYPE_PHILIPS_PCA403CD_U31P, CDROM_TYPE_SONY_CDU76_10i, CDROM_TYPE_SONY_CDU311_30h, @@ -97,7 +97,6 @@ enum CDROM_TYPE_NEC_77_106, CDROM_TYPE_NEC_211_100, CDROM_TYPE_NEC_464_105, - CDROM_TYPE_NEC_CDR_1900A_100, CDROM_TYPE_ShinaKen_DM3x1S_104, CDROM_TYPE_SONY_CDU541_10i, CDROM_TYPE_SONY_CDU561_18k, @@ -105,7 +104,6 @@ enum CDROM_TYPE_PHILIPS_CDD2600_107, CDROM_TYPE_PIONEER_DRM604X_2403, CDROM_TYPE_PLEXTOR_PX32TS_103, - CDROM_TYPE_TEAC_CD532E_20A, CDROM_TYPE_TEAC_CD50_100, CDROM_TYPE_TEAC_R55S_10R, CDROM_TYPE_TEXEL_DM3024_100, From bf3be9c0c7837e730b93cc2d5837c87c2602d3c9 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 14 Jan 2025 16:27:54 -0500 Subject: [PATCH 0095/1190] Correct EV-165A's name --- src/device/isamem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index a3baf466d..94f554473 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -1622,7 +1622,7 @@ static const device_config_t ev165a_config[] = { }; static const device_t ev165a_device = { - .name = "Everex Magi Magic EV-165A", + .name = "Everex Maxi Magic EV-165A", .internal_name = "ev165a", .flags = DEVICE_ISA, .local = ISAMEM_EV165A_CARD, From 7eef0665b5db8eba65e08f9dbbf76e427f038f3e Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 14 Jan 2025 16:45:07 -0500 Subject: [PATCH 0096/1190] Fix EV-165A config --- src/device/isamem.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index 94f554473..83e938abd 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -1547,12 +1547,12 @@ static const device_config_t ev165a_config[] = { .description = "Memory size", .type = CONFIG_SPINNER, .default_string = "", - .default_int = 512, + .default_int = 256, .file_filter = "", .spinner = { .min = 0, .max = 2048, - .step = 512 + .step = 256 }, .selection = { { 0 } } }, @@ -1561,12 +1561,12 @@ static const device_config_t ev165a_config[] = { .description = "Start Address", .type = CONFIG_SPINNER, .default_string = "", - .default_int = 0, + .default_int = 64, .file_filter = "", .spinner = { - .min = 0, - .max = 896, - .step = 128 + .min = 64, + .max = 640, + .step = 64 }, .selection = { { 0 } } }, @@ -1579,8 +1579,8 @@ static const device_config_t ev165a_config[] = { .file_filter = "", .spinner = { .min = 0, - .max = 16384, - .step = 128 + .max = 2048, + .step = 256 }, .selection = { { 0 } } }, From 4e8802c23ee9e7d771328398aa91863edf98f282 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2025 00:37:02 +0100 Subject: [PATCH 0097/1190] Fix maximum amount of RAM on a few NEAT machine where it was set unrealistically high. --- 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 330b7d52a..47a33fa8c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3597,7 +3597,7 @@ const machine_t machines[] = { .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 512, - .max = 16384, + .max = 5120, .step = 128 }, .nvrmask = 127, @@ -3637,7 +3637,7 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, From 7bc89f6feb0bf631294382c4c1945555696b0c12 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 07:13:21 +0700 Subject: [PATCH 0098/1190] Added a plenty of IDE CD-ROM models -Added other four ATA-3 models -Corrections to Western Digital pre-ATA-4 HDD models --- src/disk/hdd.c | 30 ++++++++++++++------------ src/include/86box/cdrom.h | 22 ++++++++++++++++++++ src/scsi/scsi_cdrom.c | 44 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index e79f0f6c0..328d8dcb0 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -431,10 +431,10 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-1] Quantum ProDrive LPS 105", .internal_name = "LPS105AT", .model = "QUANTUM PRODRIVE 105", .zones = 1, .avg_spt = 170, .heads = 2, .rpm = 3662, .full_stroke_ms = 45, .track_seek_ms = 5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Quantum ProDrive LPS 120AT", .internal_name = "GM12A012", .model = "QUANTUM PRODRIVE 120AT", .zones = 1, .avg_spt = 150, .heads = 2, .rpm = 3605, .full_stroke_ms = 45, .track_seek_ms = 4, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Seagate ST3243A", .internal_name = "ST3243A", .model = "ST3243A", .zones = 1, .avg_spt = 140, .heads = 4, .rpm = 3811, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 140", .internal_name = "WDAC140", .model = "WDC WDAC140-50", .zones = 4, .avg_spt = 170, .heads = 2, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 8, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 280", .internal_name = "WDAC280", .model = "WDC WDAC280-00", .zones = 4, .avg_spt = 170, .heads = 4, .rpm = 3595, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 1210", .internal_name = "WDAC1210", .model = "WDC WDAC1210-21F", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 3314, .full_stroke_ms = 33, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 2120", .internal_name = "WDAC2120", .model = "WDC WDAC2120-00M", .zones = 4, .avg_spt = 140, .heads = 2, .rpm = 3605, .full_stroke_ms = 28, .track_seek_ms = 2.8, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 140", .internal_name = "AC140", .model = "WDC AC140", .zones = 4, .avg_spt = 170, .heads = 2, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 8, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 280", .internal_name = "AC280", .model = "WDC AC280", .zones = 4, .avg_spt = 170, .heads = 4, .rpm = 3595, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 1210", .internal_name = "AC1210", .model = "WDC AC1210F", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 3314, .full_stroke_ms = 33, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 2120", .internal_name = "AC2120", .model = "WDC AC2120M", .zones = 4, .avg_spt = 140, .heads = 2, .rpm = 3605, .full_stroke_ms = 28, .track_seek_ms = 2.8, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, { .name = "[ATA-2] IBM DBOA-2720", .internal_name = "DBOA2720", .model = "IBM-DBOA-2720", .zones = 2, .avg_spt = 135, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-2] IBM DeskStar 4 (DCAA-32880)", .internal_name = "DCAA32880", .model = "IBM-DCAA-32880", .zones = 8, .avg_spt = 85, .heads = 2, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, { .name = "[ATA-2] IBM DeskStar 4 (DCAA-33610)", .internal_name = "DCAA33610", .model = "IBM-DCAA-33610", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, @@ -460,14 +460,15 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Seagate Medalist 1270SL", .internal_name = "ST51270A", .model = "ST51270A", .zones = 8, .avg_spt = 105, .heads = 3, .rpm = 5736, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Seagate Medalist 3240", .internal_name = "ST33240A", .model = "ST33240A", .zones = 16, .avg_spt = 125, .heads = 8, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Toshiba MK2101MAN (HDD2616)", .internal_name = "HDD2616", .model = "TOSHIBA MK2101MAN", .zones = 8, .avg_spt = 130, .heads = 10, .rpm = 4200, .full_stroke_ms = 36, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Western Digital Caviar 2540", .internal_name = "WDAC2540", .model = "WDC WDAC2540-00H", .zones = 4, .avg_spt = 250, .heads = 2, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 2850", .internal_name = "WDAC2850", .model = "WDC WDAC2850-00F", .zones = 4, .avg_spt = 230, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 11000", .internal_name = "WDAC11000", .model = "WDC WDAC11000-00H", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 21200", .internal_name = "WDAC21200", .model = "WDC WDAC21200-00H", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 5200, .full_stroke_ms = 39, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 21600", .internal_name = "WDAC21600", .model = "WDC WDAC21600-00H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000-32LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "WDAC22100", .model = "WDC WDAC22100-18H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "WDAC31200", .model = "WDC WDAC31200-00F", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, + { .name = "[ATA-2] Western Digital Caviar 2540", .internal_name = "AC2540", .model = "WDC AC2540H", .zones = 4, .avg_spt = 250, .heads = 2, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 2850", .internal_name = "AC2850", .model = "WDC AC2850F", .zones = 4, .avg_spt = 230, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 11000", .internal_name = "AC11000", .model = "WDC AC11000H", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 21200", .internal_name = "AC21200", .model = "WDC AC21200H", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 5200, .full_stroke_ms = 39, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 21600", .internal_name = "AC21600", .model = "WDC AC21600H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "AC22100", .model = "WDC AC22100H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "AC31200", .model = "WDC AC31200F", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, + { .name = "[ATA-3] Connor CFS1275A", .internal_name = "CFS1275A", .model = "Connor Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, @@ -475,9 +476,12 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-3] Fujitsu MPA3052AT", .internal_name = "MPA3052AT", .model = "FUJITSU MPA3052AT", .zones = 16, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Samsung Voyager 6", .internal_name = "SV0844A", .model = "SAMSUNG SV0844A", .zones = 8, .avg_spt = 105, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-3] Samsung Winner 5X", .internal_name = "WU33205A", .model = "SAMSUNG WU33205A", .zones = 16, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Seagate Medalist 636", .internal_name = "ST3636A", .model = "Seagate Technology 636MB - ST3636A", .zones = 2, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-3] Seagate Medalist 1082", .internal_name = "ST31082A", .model = "Seagate Technology 1082MB - ST31082A", .zones = 4, .avg_spt = 130, .heads = 3, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-3] Seagate Medalist 1276", .internal_name = "ST31276A", .model = "Seagate Technology 1275MB - ST31276A", .zones = 4, .avg_spt = 130, .heads = 3, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, { .name = "[ATA-3] Seagate Medalist 1720", .internal_name = "ST31720A", .model = "ST31720A", .zones = 4, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Seagate Medalist 2132", .internal_name = "ST32132A", .model = "ST32132A", .zones = 8, .avg_spt = 125, .heads = 6, .rpm = 4500, .full_stroke_ms = 30, .track_seek_ms = 2.3, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 16 }, - { .name = "[ATA-3] Western Digital Caviar 21700", .internal_name = "WDAC21700", .model = "WDC WDAC21700-40H", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5200, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, // Apple Computer OEM only, not retail version + { .name = "[ATA-3] Western Digital Caviar 21700", .internal_name = "AC21700", .model = "WDC AC21700H", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5200, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, // Apple Computer OEM only, not retail version { .name = "[ATA-4] Fujitsu MPB3021AT", .internal_name = "MPB3021AT", .model = "FUJITSU MPB3021AT", .zones = 7, .avg_spt = 100, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 16 }, { .name = "[ATA-4] Fujitsu MPD3043AT", .internal_name = "MPD3043AT", .model = "FUJITSU MPD3043AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 29, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-4] Fujitsu MPD3064AT", .internal_name = "MPD3064AT", .model = "FUJITSU MPD3064AT", .zones = 7, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 5d90d84a4..d7868951e 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -65,11 +65,17 @@ enum { enum { CDROM_TYPE_86BOX_100, + CDROM_TYPE_ASUS_CDS500_141, + CDROM_TYPE_ASUS_CDS520_132, CDROM_TYPE_AZT_CDA46802I_115, CDROM_TYPE_BTC_BCD36XH_U10, CDROM_TYPE_GOLDSTAR_CRD_8160B_314, CDROM_TYPE_HITACHI_CDR_8130_0020, + CDROM_TYPE_HLDTST_GCE8525B_101, CDROM_TYPE_KENWOOD_UCR_421_208E, + CDROM_TYPE_LG_CRN8245B_120, + CDROM_TYPE_LTN48125S_1S07, + CDROM_TYPE_MATSHITA_585_Z18P, CDROM_TYPE_MATSHITA_587_7S13, CDROM_TYPE_MATSHITA_588_LS15, CDROM_TYPE_MATSHITA_571_10e, @@ -84,9 +90,14 @@ enum CDROM_TYPE_PHILIPS_PCA403CD_U31P, CDROM_TYPE_SONY_CDU76_10i, CDROM_TYPE_SONY_CDU311_30h, + CDROM_TYPE_SONY_CDU5225_NYS4, + CDROM_TYPE_TEAC_CD516E_10G, + CDROM_TYPE_TEAC_CD524EA_30D, CDROM_TYPE_TEAC_CD532E_20A, CDROM_TYPE_TOSHIBA_5302TA_0305, CDROM_TYPE_TOSHIBA_5702B_TA70, + CDROM_TYPE_TOSHIBA_6702B_1007, + CDROM_TYPE_TOSHIBA_M1802_1051, CDROM_TYPE_CHINON_CDS431_H42, CDROM_TYPE_CHINON_CDX435_M62, CDROM_TYPE_DEC_RRD45_0436, @@ -132,11 +143,17 @@ static const struct const int bus_type; } cdrom_drive_types[] = { { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, + { "ASUS", "CD-S500/A", "1.41", "ASUS CD-S500/A 1.15", "ASUS_CD-S500A_1.41", BUS_TYPE_IDE }, + { "ASUS", "CD-S520/A4", "1.32", "ASUS CD-S520/A4 1.32", "ASUS_CD-S520A4_1.32", BUS_TYPE_IDE }, { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, + { "HL-DT-ST", "GCE-8525B", "1.01", "HL-DT-ST GCE-8525B 1.01", "HL-DT-ST_GCE-8525B_1.01", BUS_TYPE_IDE }, { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, + { "LG", "CRN-8245B", "1.20", "LG CRN-8245B 1.20", "LG_CRN-8245B_1.20", BUS_TYPE_IDE }, + { "LITE-ON", "LTN48125S", "1S07", "LITE-ON LTN48125S 1S07", "LITE-ON_LTN48125S_1S07", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-585", "Z18P", "MATSHITA CD-ROM CR-585 Z18P", "MATSHITA_CD-ROM_CR-585_Z18P", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, @@ -151,9 +168,14 @@ static const struct { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU5225", "NYS4", "SONY CD-ROM CDU5225 NYS4", "SONY_CD-ROM_CDU5225_NYS4", BUS_TYPE_IDE }, + { "TEAC", "CD-516E", "1.0G", "TEAC CD-516E 1.0G", "TEAC_CD-516E_1.0G", BUS_TYPE_IDE }, + { "TEAC", "CD-524EA", "3.0D", "TEAC CD-524EA 3.0D", "TEAC_CD-524EA_3.0D", BUS_TYPE_IDE }, { "TEAC", "CD-532E", "2.0A", "TEAC CD-532E 2.0A", "TEAC_CD_532E_2.0A", BUS_TYPE_IDE }, { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, + { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1.15", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, { "CHINON", "CD-ROM CDS-431", "H42 ", "[SCSI-1] CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, { "CHINON", "CD-ROM CDX-435", "M62 ", "[SCSI-1] CHINON CD-ROM CDX-435 M62", "CHINON_CD-ROM_CDX-435_M62", BUS_TYPE_SCSI }, { "DEC", "RRD45 (C) DEC", "0436", "[SCSI-1] DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index cdf653626..9f8a86fc9 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -4037,6 +4037,14 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ } else { switch (dev->drv->type) { + case CDROM_TYPE_ASUS_CDS500_141: + ide_padstr((char *) (ide->buffer + 23), "1.41 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "ASUS CD-S500/A ", 40); /* Model */ + break; + case CDROM_TYPE_ASUS_CDS520_132: + ide_padstr((char *) (ide->buffer + 23), "1.32 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "ASUS CD-S520/A4 ", 40); /* Model */ + break; case CDROM_TYPE_AZT_CDA46802I_115: ide_padstr((char *) (ide->buffer + 23), "1.15 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "AZT CDA46802I ", 40); /* Model */ @@ -4053,10 +4061,26 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "0020 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "HITACHI CDR-8130 ", 40); /* Model */ break; + case CDROM_TYPE_HLDTST_GCE8525B_101: + ide_padstr((char *) (ide->buffer + 23), "1.01 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST GCE-8525B ", 40); /* Model */ + break; case CDROM_TYPE_KENWOOD_UCR_421_208E: ide_padstr((char *) (ide->buffer + 23), "208E ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "KENWOOD CD-ROM UCR-421 ", 40); /* Model */ break; + case CDROM_TYPE_LG_CRN8245B_120: + ide_padstr((char *) (ide->buffer + 23), "1.20 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "LG CD-ROM CRN-8245B ", 40); /* Model */ + break; + case CDROM_TYPE_LTN48125S_1S07: + ide_padstr((char *) (ide->buffer + 23), "1S07 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "LTN48125S ", 40); /* Model */ + break; + case CDROM_TYPE_MATSHITA_585_Z18P: + ide_padstr((char *) (ide->buffer + 23), "Z18P ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-585 ", 40); /* Model */ + break; case CDROM_TYPE_MATSHITA_587_7S13: ide_padstr((char *) (ide->buffer + 23), "7S13 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-587 ", 40); /* Model */ @@ -4113,6 +4137,18 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */ break; + case CDROM_TYPE_SONY_CDU5225_NYS4: + ide_padstr((char *) (ide->buffer + 23), "NYS4 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU5225 ", 40); /* Model */ + break; + case CDROM_TYPE_TEAC_CD516E_10G: + ide_padstr((char *) (ide->buffer + 23), "1.0G ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TEAC CD-516E ", 40); /* Model */ + break; + case CDROM_TYPE_TEAC_CD524EA_30D: + ide_padstr((char *) (ide->buffer + 23), "3.0D ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TEAC CD-524EA ", 40); /* Model */ + break; case CDROM_TYPE_TEAC_CD532E_20A: ide_padstr((char *) (ide->buffer + 23), "2.0A ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "TEAC CD-532E ", 40); /* Model */ @@ -4125,6 +4161,14 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "TA70 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5702B ", 40); /* Model */ break; + case CDROM_TYPE_TOSHIBA_6702B_1007: + ide_padstr((char *) (ide->buffer + 23), "1007 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6702B ", 40); /* Model */ + break; + case CDROM_TYPE_TOSHIBA_M1802_1051: + ide_padstr((char *) (ide->buffer + 23), "1051 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TOSHIBA DVD-ROM SD-M1802 ", 40); /* Model */ + break; } } From 6b89a2e74d39373474cfb0b2148aa74006c90f64 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 07:30:48 +0700 Subject: [PATCH 0099/1190] Small name fixes to CDR-1900A --- src/include/86box/cdrom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index d7868951e..f579c8dc0 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -164,7 +164,7 @@ static const struct { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, - { "NEC", "CDR-1900A", "1.00", "NEC CDR-1900A 1.00", "NEC_CDR-1900A_1.00", BUS_TYPE_IDE }, + { "NEC", "CDR-1900A", "1.00", "NEC CDR-1900A 1.00", "NEC_CDR-1900A_1.00", BUS_TYPE_IDE }, { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, From 75b99232839aec74dee4a6e13db5ee3a1bba2b08 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 07:45:13 +0700 Subject: [PATCH 0100/1190] Correct the revision names --- src/include/86box/cdrom.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index f579c8dc0..3895833a6 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -143,7 +143,7 @@ static const struct const int bus_type; } cdrom_drive_types[] = { { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, - { "ASUS", "CD-S500/A", "1.41", "ASUS CD-S500/A 1.15", "ASUS_CD-S500A_1.41", BUS_TYPE_IDE }, + { "ASUS", "CD-S500/A", "1.41", "ASUS CD-S500/A 1.41", "ASUS_CD-S500A_1.41", BUS_TYPE_IDE }, { "ASUS", "CD-S520/A4", "1.32", "ASUS CD-S520/A4 1.32", "ASUS_CD-S520A4_1.32", BUS_TYPE_IDE }, { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, @@ -175,7 +175,7 @@ static const struct { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, - { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1.15", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, + { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1051", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, { "CHINON", "CD-ROM CDS-431", "H42 ", "[SCSI-1] CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, { "CHINON", "CD-ROM CDX-435", "M62 ", "[SCSI-1] CHINON CD-ROM CDX-435 M62", "CHINON_CD-ROM_CDX-435_M62", BUS_TYPE_SCSI }, { "DEC", "RRD45 (C) DEC", "0436", "[SCSI-1] DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, From 6d1d6d8830e1bc9caf11c9e1f6475edd5c1bb0eb Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2025 04:30:59 +0100 Subject: [PATCH 0101/1190] NEAT: More fixes, closes #5145. --- src/chipset/neat.c | 252 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 193 insertions(+), 59 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 94f0d66e1..3b223bed4 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -231,6 +231,8 @@ typedef struct neat_t { uint16_t ems_size; /* EMS size in KB */ uint16_t ems_pages; /* EMS size in pages */ + uint32_t remap_base; + ram_page_t ems[EMS_MAXPAGE]; /* EMS page registers */ ram_page_t shadow[32]; /* Shadow RAM pages */ } neat_t; @@ -238,6 +240,9 @@ typedef struct neat_t { static uint8_t defaults[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 }; +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 }; + #ifdef ENABLE_NEAT_LOG int neat_do_log = ENABLE_NEAT_LOG; @@ -262,10 +267,17 @@ ems_readb(uint32_t addr, void *priv) { ram_page_t *dev = (ram_page_t *) priv; uint8_t ret = 0xff; +#ifdef ENABLE_NEAT_LOG + uint32_t old = addr; +#endif /* Grab the data. */ - ret = *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]); + addr = addr - dev->virt_base + dev->phys_base; + if (addr < (mem_size << 10)) + ret = *(uint8_t *) &(ram[addr]); + + neat_log("[R08] %08X -> %08X (%08X): ret = %02X\n", old, addr, (mem_size << 10), ret); return ret; } @@ -275,10 +287,17 @@ ems_readw(uint32_t addr, void *priv) { ram_page_t *dev = (ram_page_t *) priv; uint16_t ret = 0xffff; +#ifdef ENABLE_NEAT_LOG + uint32_t old = addr; +#endif /* Grab the data. */ - ret = *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]); + addr = addr - dev->virt_base + dev->phys_base; + if (addr < (mem_size << 10)) + ret = *(uint16_t *) &(ram[addr]); + + neat_log("[R16] %08X -> %08X (%08X): ret = %04X\n", old, addr, (mem_size << 10), ret); return ret; } @@ -287,9 +306,16 @@ static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { ram_page_t *dev = (ram_page_t *) priv; +#ifdef ENABLE_NEAT_LOG + uint32_t old = addr; +#endif /* Write the data. */ - *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val; + addr = addr - dev->virt_base + dev->phys_base; + neat_log("[W08] %08X -> %08X (%08X): val = %02X\n", old, addr, (mem_size << 10), val); + + if (addr < (mem_size << 10)) + *(uint8_t *) &(ram[addr]) = val; } /* Write one word to paged RAM. */ @@ -297,9 +323,16 @@ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { ram_page_t *dev = (ram_page_t *) priv; +#ifdef ENABLE_NEAT_LOG + uint32_t old = addr; +#endif /* Write the data. */ - *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val; + addr = addr - dev->virt_base + dev->phys_base; + neat_log("[W16] %08X -> %08X (%08X): val = %04X\n", old, addr, (mem_size << 10), val); + + if (addr < (mem_size << 10)) + *(uint16_t *) &(ram[addr]) = val; } static void @@ -379,10 +412,11 @@ shadow_recalc(neat_t *dev) static void ems_recalc(neat_t *dev, ram_page_t *ems) { - uint32_t page = ems->phys_base / EMS_PGSIZE; + uint32_t page = ems->phys_base / EMS_PGSIZE; - if ((dev->regs[REG_RB7] & RB7_EMSEN) && ems->enabled && - (page >= 0x40) && (page < (0x40 + dev->ems_pages))) { + neat_log("ems_recalc(): %08X, %04X, %04X\n", ems->virt_base, page, dev->ems_pages); + + if ((dev->regs[REG_RB7] & RB7_EMSEN) && ems->enabled && (page < dev->ems_pages)) { neat_log("ems_recalc(): %08X-%08X -> %08X-%08X\n", ems->virt_base, ems->virt_base + EMS_PGSIZE - 1, ems->phys_base, ems->phys_base + EMS_PGSIZE - 1); @@ -405,14 +439,20 @@ ems_recalc(neat_t *dev, ram_page_t *ems) if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS); } + + flushmmucache_nopc(); } static void ems_write(uint16_t port, uint8_t val, void *priv) { - neat_t *dev = (neat_t *) priv; + neat_t *dev = (neat_t *) priv; ram_page_t *ems; int vpage; + int8_t old_enabled; + uint32_t old_phys_base; + int8_t new_enabled; + uint32_t new_phys_base; #if NEAT_DEBUG > 1 neat_log("NEAT: ems_write(%04x, %02x)\n", port, val); @@ -422,12 +462,29 @@ ems_write(uint16_t port, uint8_t val, void *priv) vpage = (port / EMS_PGSIZE); ems = &dev->ems[vpage]; + neat_log("Port: %04X, val: %02X\n", port, val); + switch (port & 0x000f) { case 0x0008: case 0x0009: - ems->enabled = !!(val & 0x80); - ems->phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE); - ems_recalc(dev, ems); + old_enabled = ems->enabled; + old_phys_base = ems->phys_base; + new_enabled = !!(val & 0x80); + new_phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE); + + if ((old_enabled != new_enabled) || (old_phys_base != new_phys_base)) { + if (old_enabled && (old_enabled == new_enabled)) { + ems->enabled = 0; + ems_recalc(dev, ems); + } + + ems->enabled = !!(val & 0x80); + + if (old_phys_base != new_phys_base) + ems->phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE); + + ems_recalc(dev, ems); + } break; default: break; @@ -454,6 +511,8 @@ ems_read(uint16_t port, void *priv) break; } + neat_log("Port: %04X, ret: %02X\n", port, ret); + #if NEAT_DEBUG > 1 neat_log("NEAT: ems_read(%04x) = %02x\n", port, ret); #endif @@ -462,20 +521,76 @@ ems_read(uint16_t port, void *priv) } static void -ems_update(neat_t *dev, int en) +ems_recalc_all(neat_t *dev) +{ + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &(dev->ems[i])); +} + +static void +ems_update_virt_base(neat_t *dev) +{ + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) + dev->ems[i].virt_base = dev->ems_frame + (i * EMS_PGSIZE); +} + +static void +ems_remove_handlers(neat_t *dev) { for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + neat_log("Removing I/O handler at %04X-%04X\n", + dev->ems_base + (i * EMS_PGSIZE), dev->ems_base + (i * EMS_PGSIZE) + 1); + /* Clean up any previous I/O port handler. */ + io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + } +} + +static void +ems_set_handlers(neat_t *dev) +{ + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + neat_log("Setting up I/O handler at %04X-%04X\n", + dev->ems_base + (i * EMS_PGSIZE), dev->ems_base + (i * EMS_PGSIZE) + 1); /* Set up an I/O port handler. */ - io_handler(en, dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - - if (en) - dev->ems[i].virt_base = dev->ems_frame + (i * EMS_PGSIZE); - - ems_recalc(dev, &(dev->ems[i])); + io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); } - flushmmucache_nopc(); + ems_recalc_all(dev); +} + +static void +remap_update(neat_t *dev, uint8_t val) +{ + if (dev->regs[REG_RB7] & RB7_UMAREL) { + mem_remap_top_ex(0, (dev->remap_base >= 1024) ? dev->remap_base : 1024); + neat_log("0 kB at %08X\n", ((dev->remap_base >= 1024) ? dev->remap_base : 1024) << 10); + } + + if (val & RB7_EMSEN) + dev->remap_base = mem_size - dev->ems_size; + else + dev->remap_base = mem_size; + neat_log("Total contiguous memory now: %i kB\n", dev->remap_base); + + if (dev->remap_base >= 640) + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + else + 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); + else + mem_mapping_disable(&ram_high_mapping); + + if (val & RB7_UMAREL) { + mem_remap_top_ex(384, (dev->remap_base >= 1024) ? dev->remap_base : 1024); + neat_log("384 kB at %08X\n", ((dev->remap_base >= 1024) ? dev->remap_base : 1024) << 10); + } + + /* Yes, this has to be done on every step because mem_remap_top_ex() reenables it. */ + mem_mapping_disable(&ram_mid_mapping); } static void @@ -590,20 +705,21 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB7: val &= RB7_MASK; - *reg = val; + + if (xval & (RB7_EMSEN | RB7_UMAREL)) + remap_update(dev, val); + + dev->regs[REG_RB7] = val; + + if (xval & RB7_EMSEN) + ems_remove_handlers(dev); + + if ((xval & RB7_EMSEN) && (val & RB7_EMSEN)) + ems_set_handlers(dev); + #if NEAT_DEBUG > 1 neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); #endif - - if (xval & RB7_EMSEN) - ems_update(dev, !!(val & RB7_EMSEN)); - - if (xval & RB7_UMAREL) { - if (val & RB7_UMAREL) - mem_remap_top(384); - else - mem_remap_top(0); - } break; case REG_RB8: @@ -621,18 +737,20 @@ neat_write(uint16_t port, uint8_t val, void *priv) neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); #endif - ems_update(dev, 0); + ems_remove_handlers(dev); /* Get configured I/O address. */ - j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; - dev->ems_base = 0x0208 + (0x10 * j); + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); /* Get configured frame address. */ j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + ems_update_virt_base(dev); + if (dev->regs[REG_RB7] & RB7_EMSEN) - ems_update(dev, 1); + ems_set_handlers(dev); break; case REG_RB10: @@ -642,18 +760,32 @@ neat_write(uint16_t port, uint8_t val, void *priv) neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); #endif - dev->ems[3].phys_base = (dev->ems[3].phys_base & 0x001fffff) | - (((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21); - dev->ems[2].phys_base = (dev->ems[2].phys_base & 0x001fffff) | - (((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21); - dev->ems[1].phys_base = (dev->ems[1].phys_base & 0x001fffff) | - (((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21); - dev->ems[0].phys_base = (dev->ems[0].phys_base & 0x001fffff) | - (((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21); + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + ram_page_t *ems = &(dev->ems[i]); + + uint32_t old_phys_base = ems->phys_base & 0xffe00000; + uint32_t new_phys_base = (((val & masks[i]) >> shifts[i]) << 21); - if (dev->regs[REG_RB7] & RB7_EMSEN) - for (i = 0; i < EMS_MAXPAGE; i++) - ems_recalc(dev, &dev->ems[i]); + if (new_phys_base != old_phys_base) { + int8_t old_enabled = ems->enabled; + + if ((dev->regs[REG_RB7] & RB7_EMSEN) && old_enabled) { + ems->enabled = 0; + ems_recalc(dev, &(dev->ems[i])); + } + + ems->phys_base = ems->phys_base - old_phys_base + new_phys_base; + + if ((dev->regs[REG_RB7] & RB7_EMSEN) && old_enabled) { + ems->enabled = old_enabled; + ems_recalc(dev, &(dev->ems[i])); + } + } + } + + neat_log("%08X, %08X, %08X, %08X\n", + dev->ems[0].phys_base, dev->ems[1].phys_base, + dev->ems[2].phys_base, dev->ems[3].phys_base); break; case REG_RB12: @@ -680,15 +812,12 @@ neat_write(uint16_t port, uint8_t val, void *priv) default: break; } - dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; - - if (dev->regs[REG_RB7] & RB7_EMSEN) - for (i = 0; i < EMS_MAXPAGE; i++) - ems_recalc(dev, &dev->ems[i]); if (dev->regs[REG_RB7] & RB7_EMSEN) { - neat_log("NEAT: EMS %iKB (%i pages)\n", - dev->ems_size, dev->ems_pages); + remap_update(dev, dev->regs[REG_RB7]); + + neat_log("NEAT: EMS %iKB\n", + dev->ems_size); } mem_a20_key = val & RB12_GA20; @@ -756,12 +885,17 @@ neat_init(UNUSED(const device_t *info)) memset(dev, 0x00, sizeof(neat_t)); /* Get configured I/O address. */ - j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; - dev->ems_base = 0x0208 + (0x10 * j); + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); /* Get configured frame address. */ - j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; - dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + + ems_update_virt_base(dev); + + dev->ems_pages = (mem_size << 10) / EMS_PGSIZE; + dev->remap_base = mem_size; mem_mapping_disable(&ram_mid_mapping); @@ -773,10 +907,10 @@ neat_init(UNUSED(const device_t *info)) for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { /* Create and initialize a page mapping. */ mem_mapping_add(&dev->ems[i].mapping, - dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE, + 0x00000000, 0x00000000, ems_readb, ems_readw, NULL, ems_writeb, ems_writew, NULL, - ram, MEM_MAPPING_INTERNAL, + ram + dev->ems[i].virt_base, MEM_MAPPING_INTERNAL, &(dev->ems[i])); /* Disable for now. */ From 0063a9f4039fac7dd8ee35820ed9228788c3f0b5 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 12:33:26 +0700 Subject: [PATCH 0102/1190] Name corrections to LG CRN-8245B --- src/include/86box/cdrom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 3895833a6..008f0ddc4 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -151,7 +151,7 @@ static const struct { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, { "HL-DT-ST", "GCE-8525B", "1.01", "HL-DT-ST GCE-8525B 1.01", "HL-DT-ST_GCE-8525B_1.01", BUS_TYPE_IDE }, { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, - { "LG", "CRN-8245B", "1.20", "LG CRN-8245B 1.20", "LG_CRN-8245B_1.20", BUS_TYPE_IDE }, + { "LG", "CD-ROM CRN-8245B", "1.20", "LG CD-ROM CRN-8245B 1.20", "LG_CD-ROM_CRN-8245B_1.20", BUS_TYPE_IDE }, { "LITE-ON", "LTN48125S", "1S07", "LITE-ON LTN48125S 1S07", "LITE-ON_LTN48125S_1S07", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-585", "Z18P", "MATSHITA CD-ROM CR-585 Z18P", "MATSHITA_CD-ROM_CR-585_Z18P", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, From 72571d6211877d5b5934f74d0ca540b757f2d852 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 14:26:31 +0700 Subject: [PATCH 0103/1190] Added other two models (1x DVD/1x CD) Also updated the revision on CRN-8245B --- src/include/86box/cdrom.h | 8 ++++++-- src/scsi/scsi_cdrom.c | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 008f0ddc4..7acfa2cc3 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -72,9 +72,11 @@ enum CDROM_TYPE_GOLDSTAR_CRD_8160B_314, CDROM_TYPE_HITACHI_CDR_8130_0020, CDROM_TYPE_HLDTST_GCE8525B_101, + CDROM_TYPE_HLDTST_GSA4160_A302, CDROM_TYPE_KENWOOD_UCR_421_208E, - CDROM_TYPE_LG_CRN8245B_120, + CDROM_TYPE_LG_CRN8245B_130, CDROM_TYPE_LTN48125S_1S07, + CDROM_TYPE_LTN526D_YSR5, CDROM_TYPE_MATSHITA_585_Z18P, CDROM_TYPE_MATSHITA_587_7S13, CDROM_TYPE_MATSHITA_588_LS15, @@ -150,9 +152,11 @@ static const struct { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, { "HL-DT-ST", "GCE-8525B", "1.01", "HL-DT-ST GCE-8525B 1.01", "HL-DT-ST_GCE-8525B_1.01", BUS_TYPE_IDE }, + { "HL-DT-ST", "DVDRAM GSA-4160", "A302", "HL-DT-ST DVDRAM GSA-4160 A302", "HL-DT-ST_DVDRAM_GSA-4160_A302", BUS_TYPE_IDE }, { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, - { "LG", "CD-ROM CRN-8245B", "1.20", "LG CD-ROM CRN-8245B 1.20", "LG_CD-ROM_CRN-8245B_1.20", BUS_TYPE_IDE }, + { "LG", "CD-ROM CRN-8245B", "1.30", "LG CD-ROM CRN-8245B 1.30", "LG_CD-ROM_CRN-8245B_1.30", BUS_TYPE_IDE }, { "LITE-ON", "LTN48125S", "1S07", "LITE-ON LTN48125S 1S07", "LITE-ON_LTN48125S_1S07", BUS_TYPE_IDE }, + { "LITE-ON", "LTN526D", "YSR5", "LITE-ON LTN526D YSR5", "LITE-ON_LTN526D_YSR5", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-585", "Z18P", "MATSHITA CD-ROM CR-585 Z18P", "MATSHITA_CD-ROM_CR-585_Z18P", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 9f8a86fc9..1eabc59f6 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -4065,18 +4065,26 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "1.01 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST GCE-8525B ", 40); /* Model */ break; + case CDROM_TYPE_HLDTST_GSA4160_A302: + ide_padstr((char *) (ide->buffer + 23), "A302 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST DVDRAM GSA-4160 ", 40); /* Model */ + break; case CDROM_TYPE_KENWOOD_UCR_421_208E: ide_padstr((char *) (ide->buffer + 23), "208E ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "KENWOOD CD-ROM UCR-421 ", 40); /* Model */ break; - case CDROM_TYPE_LG_CRN8245B_120: - ide_padstr((char *) (ide->buffer + 23), "1.20 ", 8); /* Firmware */ + case CDROM_TYPE_LG_CRN8245B_130: + ide_padstr((char *) (ide->buffer + 23), "1.30 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "LG CD-ROM CRN-8245B ", 40); /* Model */ break; case CDROM_TYPE_LTN48125S_1S07: ide_padstr((char *) (ide->buffer + 23), "1S07 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "LTN48125S ", 40); /* Model */ break; + case CDROM_TYPE_LTN526D_YSR5: + ide_padstr((char *) (ide->buffer + 23), "YSR5 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "LTN526D ", 40); /* Model */ + break; case CDROM_TYPE_MATSHITA_585_Z18P: ide_padstr((char *) (ide->buffer + 23), "Z18P ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-585 ", 40); /* Model */ From 2a16c3cea657753ce1bc1d0ba0e6a2c0204adee4 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 16:42:13 +0700 Subject: [PATCH 0104/1190] Added other five models I have forgotten Also changed the HL-DT-ST CD-ROM to reflect the model revision. --- src/include/86box/cdrom.h | 84 ++++++++++++++++++++++----------------- src/scsi/scsi_cdrom.c | 24 ++++++++++- 2 files changed, 69 insertions(+), 39 deletions(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 7acfa2cc3..bd50604bb 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -71,12 +71,15 @@ enum CDROM_TYPE_BTC_BCD36XH_U10, CDROM_TYPE_GOLDSTAR_CRD_8160B_314, CDROM_TYPE_HITACHI_CDR_8130_0020, - CDROM_TYPE_HLDTST_GCE8525B_101, + CDROM_TYPE_HITACHI_GD7500_A1, + CDROM_TYPE_HLDTST_GCR8526B_101, CDROM_TYPE_HLDTST_GSA4160_A302, CDROM_TYPE_KENWOOD_UCR_421_208E, CDROM_TYPE_LG_CRN8245B_130, + CDROM_TYPE_LG_CRD8322B_106, CDROM_TYPE_LTN48125S_1S07, CDROM_TYPE_LTN526D_YSR5, + CDROM_TYPE_MATSHITA_583_107, CDROM_TYPE_MATSHITA_585_Z18P, CDROM_TYPE_MATSHITA_587_7S13, CDROM_TYPE_MATSHITA_588_LS15, @@ -98,6 +101,8 @@ enum CDROM_TYPE_TEAC_CD532E_20A, CDROM_TYPE_TOSHIBA_5302TA_0305, CDROM_TYPE_TOSHIBA_5702B_TA70, + CDROM_TYPE_TOSHIBA_6202B_1512, + CDROM_TYPE_TOSHIBA_6402B_1008, CDROM_TYPE_TOSHIBA_6702B_1007, CDROM_TYPE_TOSHIBA_M1802_1051, CDROM_TYPE_CHINON_CDS431_H42, @@ -144,42 +149,47 @@ static const struct const char *internal_name; const int bus_type; } cdrom_drive_types[] = { - { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, - { "ASUS", "CD-S500/A", "1.41", "ASUS CD-S500/A 1.41", "ASUS_CD-S500A_1.41", BUS_TYPE_IDE }, - { "ASUS", "CD-S520/A4", "1.32", "ASUS CD-S520/A4 1.32", "ASUS_CD-S520A4_1.32", BUS_TYPE_IDE }, - { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, - { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, - { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, - { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, - { "HL-DT-ST", "GCE-8525B", "1.01", "HL-DT-ST GCE-8525B 1.01", "HL-DT-ST_GCE-8525B_1.01", BUS_TYPE_IDE }, - { "HL-DT-ST", "DVDRAM GSA-4160", "A302", "HL-DT-ST DVDRAM GSA-4160 A302", "HL-DT-ST_DVDRAM_GSA-4160_A302", BUS_TYPE_IDE }, - { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, - { "LG", "CD-ROM CRN-8245B", "1.30", "LG CD-ROM CRN-8245B 1.30", "LG_CD-ROM_CRN-8245B_1.30", BUS_TYPE_IDE }, - { "LITE-ON", "LTN48125S", "1S07", "LITE-ON LTN48125S 1S07", "LITE-ON_LTN48125S_1S07", BUS_TYPE_IDE }, - { "LITE-ON", "LTN526D", "YSR5", "LITE-ON LTN526D YSR5", "LITE-ON_LTN526D_YSR5", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-585", "Z18P", "MATSHITA CD-ROM CR-585 Z18P", "MATSHITA_CD-ROM_CR-585_Z18P", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, - { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, - { "MATSHITA", "CR-572", "1.0j", "MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE }, - { "MITSUMI", "CRMC-FX4820T", "D02A", "MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:260", "1.00", "NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:260", "1.01", "NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, - { "NEC", "CDR-1900A", "1.00", "NEC CDR-1900A 1.00", "NEC_CDR-1900A_1.00", BUS_TYPE_IDE }, - { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, - { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, - { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, - { "SONY", "CD-ROM CDU5225", "NYS4", "SONY CD-ROM CDU5225 NYS4", "SONY_CD-ROM_CDU5225_NYS4", BUS_TYPE_IDE }, - { "TEAC", "CD-516E", "1.0G", "TEAC CD-516E 1.0G", "TEAC_CD-516E_1.0G", BUS_TYPE_IDE }, - { "TEAC", "CD-524EA", "3.0D", "TEAC CD-524EA 3.0D", "TEAC_CD-524EA_3.0D", BUS_TYPE_IDE }, - { "TEAC", "CD-532E", "2.0A", "TEAC CD-532E 2.0A", "TEAC_CD_532E_2.0A", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, - { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1051", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, + { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, + { "ASUS", "CD-S500/A", "1.41", "ASUS CD-S500/A 1.41", "ASUS_CD-S500A_1.41", BUS_TYPE_IDE }, + { "ASUS", "CD-S520/A4", "1.32", "ASUS CD-S520/A4 1.32", "ASUS_CD-S520A4_1.32", BUS_TYPE_IDE }, + { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, + { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, + { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, + { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, + { "HITACHI", "GD-7500", "A1 ", "HITACHI GD-7500 A1", "HITACHI_GD-7500_A1", BUS_TYPE_IDE }, + { "HL-DT-ST", "CD-ROM GCR-8526B", "1.01", "HL-DT-ST CD-ROM GCR-8526B 1.01", "HL-DT-ST_CD-ROM_GCR-8526B_1.01", BUS_TYPE_IDE }, + { "HL-DT-ST", "DVDRAM GSA-4160", "A302", "HL-DT-ST DVDRAM GSA-4160 A302", "HL-DT-ST_DVDRAM_GSA-4160_A302", BUS_TYPE_IDE }, + { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, + { "LG", "CD-ROM CRN-8245B", "1.30", "LG CD-ROM CRN-8245B 1.30", "LG_CD-ROM_CRN-8245B_1.30", BUS_TYPE_IDE }, + { "LG", "CD-ROM CRD-8322B", "1.06", "LG CD-ROM CRD-8322B 1.06", "LG_CD-ROM_CRD-8322B_1.06", BUS_TYPE_IDE }, + { "LITE-ON", "LTN48125S", "1S07", "LITE-ON LTN48125S 1S07", "LITE-ON_LTN48125S_1S07", BUS_TYPE_IDE }, + { "LITE-ON", "LTN526D", "YSR5", "LITE-ON LTN526D YSR5", "LITE-ON_LTN526D_YSR5", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-583", "1.07", "MATSHITA CD-ROM CR-583 1.07", "MATSHITA_CD-ROM_CR-583_1.07", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-585", "Z18P", "MATSHITA CD-ROM CR-585 Z18P", "MATSHITA_CD-ROM_CR-585_Z18P", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, + { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, + { "MATSHITA", "CR-572", "1.0j", "MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE }, + { "MITSUMI", "CRMC-FX4820T", "D02A", "MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:260", "1.00", "NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:260", "1.01", "NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, + { "NEC", "CDR-1900A", "1.00", "NEC CDR-1900A 1.00", "NEC_CDR-1900A_1.00", BUS_TYPE_IDE }, + { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU5225", "NYS4", "SONY CD-ROM CDU5225 NYS4", "SONY_CD-ROM_CDU5225_NYS4", BUS_TYPE_IDE }, + { "TEAC", "CD-516E", "1.0G", "TEAC CD-516E 1.0G", "TEAC_CD-516E_1.0G", BUS_TYPE_IDE }, + { "TEAC", "CD-524EA", "3.0D", "TEAC CD-524EA 3.0D", "TEAC_CD-524EA_3.0D", BUS_TYPE_IDE }, + { "TEAC", "CD-532E", "2.0A", "TEAC CD-532E 2.0A", "TEAC_CD_532E_2.0A", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6202B", "1512", "TOSHIBA CD-ROM XM-6202B 1512", "TOSHIBA_CD-ROM_XM-6202B_1512", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6402B", "1008", "TOSHIBA CD-ROM XM-6402B 1008", "TOSHIBA_CD-ROM_XM-6402B_1008", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, + { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1051", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, { "CHINON", "CD-ROM CDS-431", "H42 ", "[SCSI-1] CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, { "CHINON", "CD-ROM CDX-435", "M62 ", "[SCSI-1] CHINON CD-ROM CDX-435 M62", "CHINON_CD-ROM_CDX-435_M62", BUS_TYPE_SCSI }, { "DEC", "RRD45 (C) DEC", "0436", "[SCSI-1] DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 1eabc59f6..91773c62c 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -4061,9 +4061,13 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "0020 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "HITACHI CDR-8130 ", 40); /* Model */ break; - case CDROM_TYPE_HLDTST_GCE8525B_101: + case CDROM_TYPE_HITACHI_GD7500_A1: + ide_padstr((char *) (ide->buffer + 23), "A1 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "HITACHI GD-7500 ", 40); /* Model */ + break; + case CDROM_TYPE_HLDTST_GCR8526B_101: ide_padstr((char *) (ide->buffer + 23), "1.01 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST GCE-8525B ", 40); /* Model */ + ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST CD-ROM GCR-8526B ", 40); /* Model */ break; case CDROM_TYPE_HLDTST_GSA4160_A302: ide_padstr((char *) (ide->buffer + 23), "A302 ", 8); /* Firmware */ @@ -4077,6 +4081,10 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "1.30 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "LG CD-ROM CRN-8245B ", 40); /* Model */ break; + case CDROM_TYPE_LG_CRD8322B_106: + ide_padstr((char *) (ide->buffer + 23), "1.06 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "LG CD-ROM CRD-8322B ", 40); /* Model */ + break; case CDROM_TYPE_LTN48125S_1S07: ide_padstr((char *) (ide->buffer + 23), "1S07 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "LTN48125S ", 40); /* Model */ @@ -4085,6 +4093,10 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "YSR5 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "LTN526D ", 40); /* Model */ break; + case CDROM_TYPE_MATSHITA_583_107: + ide_padstr((char *) (ide->buffer + 23), "1.07 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-583 ", 40); /* Model */ + break; case CDROM_TYPE_MATSHITA_585_Z18P: ide_padstr((char *) (ide->buffer + 23), "Z18P ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-585 ", 40); /* Model */ @@ -4169,6 +4181,14 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) ide_padstr((char *) (ide->buffer + 23), "TA70 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5702B ", 40); /* Model */ break; + case CDROM_TYPE_TOSHIBA_6202B_1512: + ide_padstr((char *) (ide->buffer + 23), "1512 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6202B ", 40); /* Model */ + break; + case CDROM_TYPE_TOSHIBA_6402B_1008: + ide_padstr((char *) (ide->buffer + 23), "1008 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6402B ", 40); /* Model */ + break; case CDROM_TYPE_TOSHIBA_6702B_1007: ide_padstr((char *) (ide->buffer + 23), "1007 ", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6702B ", 40); /* Model */ From cd5ad1f6c145386d0f0a902307123d52da4752d7 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 15 Jan 2025 20:12:29 +0700 Subject: [PATCH 0105/1190] Added one recently-added ATA-1 HDD model --- src/disk/hdd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 328d8dcb0..90d01bf9c 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -419,6 +419,7 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-1] Conner CP3024", .internal_name = "CP3024", .model = "Conner Peripherals 20MB - CP3024", .zones = 1, .avg_spt = 33, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3044", .internal_name = "CP3044", .model = "Conner Peripherals 40MB - CP3044", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3104", .internal_name = "CP3104", .model = "Conner Peripherals 104MB - CP3104", .zones = 1, .avg_spt = 33, .heads = 8, .rpm = 3500, .full_stroke_ms = 45, .track_seek_ms = 8, .rcache_num_seg = 4, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work + { .name = "[ATA-1] Conner CFS420A", .internal_name = "CFS420A", .model = "Conner Peripherals 420MB - CFS420A", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, { .name = "[ATA-1] HP Kittyhawk", .internal_name = "C3014A", .model = "HP C3014A", .zones = 6, .avg_spt = 180, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, { .name = "[ATA-1] IBM H3256-A3", .internal_name = "H3256A3", .model = "IBM-H3256-A3", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, { .name = "[ATA-1] IBM H3342-A4", .internal_name = "H3342A4", .model = "IBM-H3342-A4", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, From 2f5940fee34ca0f77b390cb718d6669f1b7c0c32 Mon Sep 17 00:00:00 2001 From: greblosdier <51314920+greblosdier@users.noreply.github.com> Date: Wed, 15 Jan 2025 12:57:51 -0800 Subject: [PATCH 0106/1190] Update 386_dynarec.c Changed exec386_dynarec_dyn from inline to noinline to resolve NEW_DYNAREC build issue on Linux x86_64. --- src/cpu/386_dynarec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 590d6f5c7..d86412103 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -386,7 +386,7 @@ block_ended: cpu_end_block_after_ins = 0; } -static __inline void +static void __attribute__((noinline)) exec386_dynarec_dyn(void) { uint32_t start_pc = 0; From a582223e41c68b7d3dc79e317e4ea528e8a35c44 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 00:58:53 +0100 Subject: [PATCH 0107/1190] NEAT: Actually properly initialize the shadow RAM mappings, fixes #5148. --- src/chipset/neat.c | 47 +++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 3b223bed4..057a9a246 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -345,23 +345,27 @@ neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_fla new_flags = dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]; - neat_log("neat_mem_update_state(): %08X-%08X: %02X\n", addr, addr + size - 1, new_flags); - - if (new_flags & RAM_FLAG_EMS) + if (new_flags & RAM_FLAG_EMS) { + neat_log("neat_mem_update_state(): %08X-%08X: %02X (EMS)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else if (new_flags & RAM_FLAG_ROMCS) + } else if (new_flags & RAM_FLAG_ROMCS) { + neat_log("neat_mem_update_state(): %08X-%08X: %02X (ROMCS)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_ROMCS | MEM_WRITE_ROMCS); - else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) { + } else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) { case 0: + neat_log("neat_mem_update_state(): %08X-%08X: %02X (RE | WE)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); break; case 1: + neat_log("neat_mem_update_state(): %08X-%08X: %02X (RE | WI)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); break; case 2: + neat_log("neat_mem_update_state(): %08X-%08X: %02X (RI | WE)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); break; case 3: + neat_log("neat_mem_update_state(): %08X-%08X: %02X (RI | WI)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); break; default: @@ -383,14 +387,24 @@ shadow_recalc(neat_t *dev) int ram_flags; int read; - if (i > 16) { + if (i >= 16) { int rb1_romcs_bit = 7 - (i >> 2); int rb1_write_bit = rb1_romcs_bit + 4; romcs = !(dev->regs[REG_RB1] & (1 << rb1_romcs_bit)); write = !(dev->regs[REG_RB1] & (1 << rb1_write_bit)); - } else if (i <= 8) + neat_log("Shadow %08X-%08X: [%02X, %02X] %02X:%02X, %02X, %02X\n", + dev->shadow[i].virt_base, dev->shadow[i].virt_base + EMS_PGSIZE - 1, + dev->regs[REG_RB1], dev->regs[shadow_reg], + shadow_reg, shadow_bit, + rb1_romcs_bit, rb1_write_bit); + } else { shadow_bit ^= 4; + neat_log("Shadow %08X-%08X: [--, %02X] %02X:%02X, shadow bit ^= 4\n", + dev->shadow[i].virt_base, dev->shadow[i].virt_base + EMS_PGSIZE - 1, + dev->regs[shadow_reg], + shadow_reg, shadow_bit); + } read = dev->regs[shadow_reg] & (1 << shadow_bit); write = write && read; @@ -425,8 +439,7 @@ ems_recalc(neat_t *dev, ram_page_t *ems) /* Update the EMS RAM address for this page. */ mem_mapping_set_exec(&ems->mapping, ram + ems->phys_base); - if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) - neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS); + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS); #if NEAT_DEBUG > 1 neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", @@ -436,11 +449,8 @@ ems_recalc(neat_t *dev, ram_page_t *ems) /* Disable this page. */ mem_mapping_disable(&ems->mapping); - if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) - neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS); + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS); } - - flushmmucache_nopc(); } static void @@ -921,6 +931,17 @@ neat_init(UNUSED(const device_t *info)) dev->shadow[i].virt_base = dev->shadow[i].phys_base = (i * EMS_PGSIZE) + 0x00080000; dev->shadow[i].enabled = 1; + + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->shadow[i].mapping, + dev->shadow[i].virt_base, EMS_PGSIZE, + ems_readb, ems_readw, NULL, + ems_writeb, ems_writew, NULL, + ram + dev->shadow[i].virt_base, MEM_MAPPING_INTERNAL, + &(dev->shadow[i])); + + /* Disable for now. */ + mem_mapping_disable(&dev->shadow[i].mapping); } /* Initialize some of the registers to specific defaults. */ From fbafb7507b22d0c5b265b29de37f7025ed74ec82 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 01:14:23 +0100 Subject: [PATCH 0108/1190] Dynamic recompiler: Only disable inline if not on Windows or MacOS. --- src/cpu/386_dynarec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index d86412103..7ad4f30c5 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -386,7 +386,11 @@ block_ended: cpu_end_block_after_ins = 0; } +#if defined(_WIN32) || defined(__APPLE__) +static __inline void +#else static void __attribute__((noinline)) +#endif exec386_dynarec_dyn(void) { uint32_t start_pc = 0; From 48b3bbb7971827d7481b7a2c77f9ca6763f10cb9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 03:34:38 +0100 Subject: [PATCH 0109/1190] NEAT: RA0-RA2 defaults and RA0 alt. reset. --- src/chipset/neat.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 057a9a246..3c9838e06 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -237,7 +237,7 @@ typedef struct neat_t { ram_page_t shadow[32]; /* Shadow RAM pages */ } neat_t; -static uint8_t defaults[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, +static uint8_t defaults[16] = { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 }; static uint8_t masks[4] = { RB10_P0EXT, RB10_P1EXT, RB10_P2EXT, RB10_P3EXT }; @@ -628,6 +628,8 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RA0: val &= RA0_MASK; *reg = (*reg & ~RA0_MASK) | val | (RA0_REV_ID << RA0_REV_SH); + if ((xval & 0x20) && (val & 0x20)) + outb(0x64, 0xfe); #if NEAT_DEBUG > 1 neat_log("NEAT: RA0=%02x(%02x)\n", val, *reg); #endif From a94a5bb0b54e20294fbaaec6b667843dc30ecb6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 05:48:37 +0100 Subject: [PATCH 0110/1190] Improved the Linux new dynamic recompiler freeze workaround per patch by Dax. --- src/cpu/386_dynarec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 7ad4f30c5..5991cf100 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -386,10 +386,10 @@ block_ended: cpu_end_block_after_ins = 0; } -#if defined(_WIN32) || defined(__APPLE__) -static __inline void +#if defined(__linux__) && !defined(__clang__) && defined(USE_NEW_DYNAREC) +static inline void __attribute__((optimize("O2"))) #else -static void __attribute__((noinline)) +static __inline void #endif exec386_dynarec_dyn(void) { From d8eb77849ca146965e05da889855b02ed6f523bd Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 5 May 2024 23:27:31 -0400 Subject: [PATCH 0111/1190] Corrections to the SixPakPlus --- src/device/isamem.c | 2 +- src/device/isartc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index 83e938abd..f63a5a5a1 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -1310,7 +1310,7 @@ static const device_config_t a6pak_config[] = { .file_filter = "", .spinner = { .min = 0, - .max = 576, + .max = 384, .step = 64 }, .selection = { { 0 } } diff --git a/src/device/isartc.c b/src/device/isartc.c index 7721d9885..b56718400 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -714,8 +714,9 @@ static const device_config_t a6pak_config[] = { { { "Disabled", -1 }, { "IRQ2", 2 }, - { "IRQ3", 3 }, + { "IRQ4", 4 }, { "IRQ5", 5 }, + { "IRQ7", 7 }, { "" } }, }, From 3f3b921831cf689b532f93d7ef51b5e32f37ec2f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 May 2024 06:40:57 -0400 Subject: [PATCH 0112/1190] Add Generic MM58167 RTC --- src/device/isartc.c | 122 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 11 deletions(-) diff --git a/src/device/isartc.c b/src/device/isartc.c index b56718400..61b07dc1a 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -76,17 +76,23 @@ #include <86box/machine.h> #include <86box/io.h> #include <86box/device.h> +#include <86box/mem.h> #include <86box/nvr.h> +#include <86box/rom.h> #include <86box/ui.h> #include <86box/plat.h> #include <86box/pic.h> #include <86box/isartc.h> -#define ISARTC_EV170 0 -#define ISARTC_DTK 1 -#define ISARTC_P5PAK 2 -#define ISARTC_A6PAK 3 -#define ISARTC_VENDEX 4 +#define ISARTC_EV170 0 +#define ISARTC_DTK 1 +#define ISARTC_P5PAK 2 +#define ISARTC_A6PAK 3 +#define ISARTC_VENDEX 4 +#define ISARTC_MM58167 10 + +#define ISARTC_ROM_MM58167_1 "roms/rtc/glatick/GLaTICK_0.8.5_NS_RP.ROM" +#define ISARTC_ROM_MM58167_2 "roms/rtc/glatick/GLaTICK_0.8.5_86B.ROM" #define ISARTC_DEBUG 0 @@ -101,6 +107,7 @@ typedef struct rtcdev_t { int8_t irq; /* configured IRQ channel */ int8_t base_addrsz; uint32_t base_addr; /* configured I/O address */ + rom_t rom; /* BIOS ROM, If configured */ /* Fields for the specific driver. */ void (*f_wr)(uint16_t, uint8_t, void *); @@ -524,6 +531,14 @@ isartc_init(const device_t *info) /* Do per-board initialization. */ switch (dev->board) { + case ISARTC_MM58167: /* Generic MM58167 RTC */ + { + int rom_addr = device_get_config_hex20("bios_addr"); + if (rom_addr != -1) + rom_init(&dev->rom, ISARTC_ROM_MM58167_1, + rom_addr, 0x0800, 0x7ff, 0, MEM_MAPPING_EXTERNAL); + + } case ISARTC_EV170: /* Everex EV-170 Magic I/O */ dev->flags |= FLAG_YEAR80; dev->base_addr = device_get_config_hex16("base"); @@ -738,6 +753,90 @@ static const device_t a6pak_device = { .config = a6pak_config }; +static const device_config_t mm58167_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x02C0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { "240H", 0x0240 }, + { "2C0H", 0x02c0 }, + { "340H", 0x0340 }, + { "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = -1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { "Disabled", -1 }, + { "IRQ2", 2 }, + { "IRQ5", 5 }, + { "IRQ7", 7 }, + { "" } + }, + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xcc000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = -1 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "CA00H", .value = 0xca000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "CE00H", .value = 0xce000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D200H", .value = 0xd2000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D600H", .value = 0xd6000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DA00H", .value = 0xda000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "DE00H", .value = 0xde000 }, + { .description = "E000H", .value = 0xe0000 }, + { .description = "E200H", .value = 0xe2000 }, + { .description = "E400H", .value = 0xe4000 }, + { .description = "E600H", .value = 0xe6000 }, + { .description = "E800H", .value = 0xe8000 }, + { .description = "EA00H", .value = 0xea000 }, + { .description = "EC00H", .value = 0xec000 }, + { .description = "EE00H", .value = 0xee000 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_t mm58167_device = { + .name = "Generic MM58167 RTC", + .internal_name = "rtc_mm58167", + .flags = DEVICE_ISA, + .local = ISARTC_MM58167, + .init = isartc_init, + .close = isartc_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mm58167_config +}; + /* Onboard RTC devices */ const device_t vendex_xt_rtc_onboard_device = { .name = "National Semiconductor MM58167 (Vendex)", @@ -757,12 +856,13 @@ static const struct { const device_t *dev; } boards[] = { // clang-format off - { &device_none }, - { &ev170_device }, - { &pii147_device }, - { &p5pak_device }, - { &a6pak_device }, - { NULL }, + { &device_none }, + { &ev170_device }, + { &pii147_device }, + { &p5pak_device }, + { &a6pak_device }, + { &mm58167_device }, + { NULL } // clang-format on }; From 3189bf7fb8eea58c3654b8875d3378e5e1ae8169 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 13 Jan 2025 22:06:59 -0500 Subject: [PATCH 0113/1190] Cleanups in isartc --- src/device/isartc.c | 111 ++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 41 deletions(-) diff --git a/src/device/isartc.c b/src/device/isartc.c index 61b07dc1a..77f35ffc7 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -629,24 +629,36 @@ isartc_close(void *priv) static const device_config_t ev170_config[] = { // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x02C0, "", { 0 }, - { - { "240H", 0x0240 }, - { "2C0H", 0x02c0 }, - { "" } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x02C0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "240H", .value = 0x0240 }, + { .description = "2C0H", .value = 0x02c0 }, + { .description = "" } }, }, { - "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, - { - { "Disabled", -1 }, - { "IRQ2", 2 }, - { "IRQ5", 5 }, - { "IRQ7", 7 }, - { "" } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = -1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = -1 }, + { .description = "IRQ2", .value = 2 }, + { .description = "IRQ5", .value = 5 }, + { .description = "IRQ7", .value = 7 }, + { .description = "" } }, }, - { "", "", -1 } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -658,7 +670,7 @@ static const device_t ev170_device = { .init = isartc_init, .close = isartc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ev170_config @@ -667,14 +679,20 @@ static const device_t ev170_device = { static const device_config_t pii147_config[] = { // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x0240, "", { 0 }, - { - { "Clock 1", 0x0240 }, - { "Clock 2", 0x0340 }, - { "" } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0240, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Clock 1", .value = 0x0240 }, + { .description = "Clock 2", .value = 0x0340 }, + { .description = "" } }, }, - { "", "", -1 } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -686,7 +704,7 @@ static const device_t pii147_device = { .init = isartc_init, .close = isartc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pii147_config @@ -695,16 +713,22 @@ static const device_t pii147_device = { static const device_config_t p5pak_config[] = { // clang-format off { - "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, - { - { "Disabled", -1 }, - { "IRQ2", 2 }, - { "IRQ3", 3 }, - { "IRQ5", 5 }, - { "" } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = -1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", -1 }, + { .description = "IRQ2", 2 }, + { .description = "IRQ3", 3 }, + { .description = "IRQ5", 5 }, + { .description = "" } }, }, - { "", "", -1 } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -716,7 +740,7 @@ static const device_t p5pak_device = { .init = isartc_init, .close = isartc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = p5pak_config @@ -725,17 +749,22 @@ static const device_t p5pak_device = { static const device_config_t a6pak_config[] = { // clang-format off { - "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, - { - { "Disabled", -1 }, - { "IRQ2", 2 }, - { "IRQ4", 4 }, - { "IRQ5", 5 }, - { "IRQ7", 7 }, - { "" } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = -1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = -1 }, + { .description = "IRQ2", .value = 2 }, + { .description = "IRQ3", .value = 3 }, + { .description = "IRQ5", .value = 5 }, + { .description = "" } }, }, - { "", "", -1 } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -747,7 +776,7 @@ static const device_t a6pak_device = { .init = isartc_init, .close = isartc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = a6pak_config @@ -846,7 +875,7 @@ const device_t vendex_xt_rtc_onboard_device = { .init = isartc_init, .close = isartc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL From b61751a6d0944482dfe2526a2538d0d40f6416ff Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 15 Jan 2025 23:45:00 -0500 Subject: [PATCH 0114/1190] CONFIG_BIOS for ibmat (5170) --- src/machine/m_at.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index fea87c8f6..93d111510 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -153,6 +153,29 @@ machine_at_ps2_ide_init(const machine_t *model) static const device_config_t ibmat_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5170_111585", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "62X082x (11/15/85)", .internal_name = "ibm5170_111585", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47.BIN", "" } }, + + { .name = "61X9266 (11/15/85) (Alt)", .internal_name = "ibm5170_111585_alt", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27_61X9266.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47_61X9265.BIN", "" } }, + + { .name = "648009x (06/10/85)", .internal_name = "ibm5170_061085", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_10JUN85_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JUN85_U47.BIN", "" } }, + + { .name = "618102x (01/10/84)", .internal_name = "ibm5170_011084", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_10JAN84_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JAN84_U47.BIN", "" } }, + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", @@ -180,17 +203,21 @@ const device_t ibmat_device = { int machine_at_ibm_init(const machine_t *model) { - int ret; - uint8_t enable_5161; + int ret; + uint8_t enable_5161; + const char *fn[2]; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); + fn[0] = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + fn[1] = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + ret = bios_load_interleaved(fn[0], fn[1], 0x000f0000, 65536, 0); device_context_restore(); - ret = bios_load_interleaved("roms/machines/ibmat/62x0820.u27", - "roms/machines/ibmat/62x0821.u47", - 0x000f0000, 65536, 0); - if (bios_only || !ret) return ret; From 2eb65625f93338ce3da36cc2b90f6d80c54013c8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 16 Jan 2025 00:36:23 -0500 Subject: [PATCH 0115/1190] GlaBIOS for 5150/5160 --- src/machine/m_xt.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 7b59686d6..2988ec201 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -74,6 +74,13 @@ static const device_config_t ibmpc_config[] = { .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_19OCT81_5700671_U33.BIN", "" } }, { .name = "5700051 (04/24/81)", .internal_name = "ibm5150_5700051", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_24APR81_5700051_U33.BIN", "" } }, + + // GlaBIOS for IBM PC + { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8P.ROM", "" } }, + { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VP.ROM", "" } }, + // The following are Diagnostic ROMs. { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, @@ -177,6 +184,13 @@ static const device_config_t ibmpc82_config[] = { .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_27OCT82_1501476_U33.BIN", "" } }, { .name = "5000024 (08/16/82)", .internal_name = "ibm5150_5000024", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_16AUG82_5000024_U33.BIN", "" } }, + + // GlaBIOS for IBM PC + { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8P.ROM", "" } }, + { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VP.ROM", "" } }, + // The following are Diagnostic ROMs. { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, @@ -283,6 +297,12 @@ static const device_config_t ibmxt_config[] = { { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, #if 0 + // GlaBIOS for IBM XT + { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "" } }, + { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "" } }, + // The following are Diagnostic ROMs. { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, @@ -399,6 +419,12 @@ static const device_config_t ibmxt86_config[] = { { .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } }, #if 0 + // GlaBIOS for IBM XT + { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "" } }, + { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "" } }, + // The following are Diagnostic ROMs. { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, From 43cf6e0b51b537ef708f531edb2b2de340f7154f Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Thu, 16 Jan 2025 13:07:23 +0700 Subject: [PATCH 0116/1190] Added 9 more ATA-4/ATA-5 HDD models -Small corrections to ATA-4 Western Digital HDD models -Line fixes to cdrom.h --- src/disk/hdd.c | 27 ++++++++++++++++++--------- src/include/86box/cdrom.h | 12 ++++++------ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 90d01bf9c..6872c7ae1 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -507,30 +507,39 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-4] Seagate Medalist 3321", .internal_name = "ST33221A", .model = "ST33221A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 4321", .internal_name = "ST34321A", .model = "ST34321A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 6531", .internal_name = "ST36531A", .model = "ST36531A", .zones = 16, .avg_spt = 115, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Seagate Medalist 8420", .internal_name = "ST38420A", .model = "ST38420A", .zones = 16, .avg_spt = 90, .heads = 2, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Seagate Medalist 8420", .internal_name = "ST38420A", .model = "ST38420A", .zones = 16, .avg_spt = 90, .heads = 4, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Seagate Medalist 13030", .internal_name = "ST313030A", .model = "ST313030A", .zones = 16, .avg_spt = 90, .heads = 6, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Seagate Medalist 17240", .internal_name = "ST317240A", .model = "ST317240A", .zones = 16, .avg_spt = 90, .heads = 8, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-4] Toshiba MK4006MAV", .internal_name = "MK4006MAV", .model = "TOSHIBA MK4006MAV", .zones = 8, .avg_spt = 130, .heads = 6, .rpm = 4200, .full_stroke_ms = 25, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Western Digital Caviar 14300", .internal_name = "AC14300", .model = "WDC AC14300-00RT", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 5.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-4] Western Digital Caviar 23200", .internal_name = "AC23200", .model = "WDC AC23200-00LB", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Western Digital Caviar 26400", .internal_name = "AC26400", .model = "WDC AC26400-00RN", .zones = 16, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Western Digital Caviar 33200", .internal_name = "AC33200", .model = "WDC AC33200-00LA", .zones = 16, .avg_spt = 110, .heads = 5, .rpm = 5200, .full_stroke_ms = 40, .track_seek_ms = 3, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Western Digital Caviar 14300", .internal_name = "AC14300", .model = "WDC AC14300RT", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 5.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Western Digital Caviar 23200", .internal_name = "AC23200", .model = "WDC AC23200LB", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Western Digital Caviar 26400", .internal_name = "AC26400", .model = "WDC AC26400RN", .zones = 16, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Western Digital Caviar 33200", .internal_name = "AC33200", .model = "WDC AC33200LA", .zones = 16, .avg_spt = 110, .heads = 5, .rpm = 5200, .full_stroke_ms = 40, .track_seek_ms = 3, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-5] IBM Travelstar 6GN", .internal_name = "DARA206000", .model = "IBM-DARA-206000", .zones = 12, .avg_spt = 92, .heads = 2, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] IBM Travelstar 9GN", .internal_name = "DARA209000", .model = "IBM-DARA-209000", .zones = 12, .avg_spt = 92, .heads = 3, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] IBM/Hitachi Travelstar 12GN", .internal_name = "DARA212000", .model = "IBM-DARA-212000", .zones = 12, .avg_spt = 92, .heads = 4, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Either Hitachi or IBM OEM { .name = "[ATA-5] Maxtor DiamondMax VL 17", .internal_name = "90871U2", .model = "Maxtor 90871U2", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-5] Maxtor DiamondMax VL 20", .internal_name = "91021U2", .model = "Maxtor 91021U2", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20 (91021U2)", .internal_name = "91021U2", .model = "Maxtor 91021U2", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20 (91531U3)", .internal_name = "91531U3", .model = "Maxtor 91531U3", .zones = 16, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20 (92041U4)", .internal_name = "92041U4", .model = "Maxtor 92041U4", .zones = 16, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Quantum Fireball EX3.2A", .internal_name = "EX32A012", .model = "QUANTUM FIREBALL EX3.2A", .zones = 1, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball EX6.4A", .internal_name = "EX64A012", .model = "QUANTUM FIREBALL EX6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR4.3A", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR6.4A", .internal_name = "CR64A011", .model = "QUANTUM FIREBALL CR6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR8.4A", .internal_name = "CR84A011", .model = "QUANTUM FIREBALL CR8.4A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR4.3A", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR6.4A", .internal_name = "CR64A011", .model = "QUANTUM FIREBALL CR6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR8.4A", .internal_name = "CR84A011", .model = "QUANTUM FIREBALL CR8.4A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Quantum Fireball CR13.0A", .internal_name = "CR13A011", .model = "QUANTUM FIREBALL CR13.0A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV0682D)", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1364D)", .internal_name = "SV1364D", .model = "SAMSUNG SV1364D", .zones = 8, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1705D)", .internal_name = "SV1705D", .model = "SAMSUNG SV1705D", .zones = 8, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV2046D)", .internal_name = "SV2046D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 89, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 8.4gb", .internal_name = "ST38410A", .model = "ST38410A", .zones = 16, .avg_spt = 89, .heads = 2, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 13gb", .internal_name = "ST313021A", .model = "ST313021A", .zones = 16, .avg_spt = 89, .heads = 4, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 17.2gb", .internal_name = "ST317221A", .model = "ST317221A", .zones = 16, .avg_spt = 89, .heads = 3, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Western Digital Caviar 102AA", .internal_name = "WD102AA", .model = "WDC WD102AA-00ANA0", .zones = 16, .avg_spt = 95, .heads = 8, .rpm = 5400, .full_stroke_ms = 12, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Western Digital Expert", .internal_name = "WD135BA", .model = "WDC WD135BA-60AK", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 1920, .max_multiple = 32 }, // clang-format on diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index bd50604bb..f28bba517 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -184,12 +184,12 @@ static const struct { "TEAC", "CD-516E", "1.0G", "TEAC CD-516E 1.0G", "TEAC_CD-516E_1.0G", BUS_TYPE_IDE }, { "TEAC", "CD-524EA", "3.0D", "TEAC CD-524EA 3.0D", "TEAC_CD-524EA_3.0D", BUS_TYPE_IDE }, { "TEAC", "CD-532E", "2.0A", "TEAC CD-532E 2.0A", "TEAC_CD_532E_2.0A", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6202B", "1512", "TOSHIBA CD-ROM XM-6202B 1512", "TOSHIBA_CD-ROM_XM-6202B_1512", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6402B", "1008", "TOSHIBA CD-ROM XM-6402B 1008", "TOSHIBA_CD-ROM_XM-6402B_1008", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, - { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1051", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6202B", "1512", "TOSHIBA CD-ROM XM-6202B 1512", "TOSHIBA_CD-ROM_XM-6202B_1512", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6402B", "1008", "TOSHIBA CD-ROM XM-6402B 1008", "TOSHIBA_CD-ROM_XM-6402B_1008", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, + { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1051", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, { "CHINON", "CD-ROM CDS-431", "H42 ", "[SCSI-1] CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, { "CHINON", "CD-ROM CDX-435", "M62 ", "[SCSI-1] CHINON CD-ROM CDX-435 M62", "CHINON_CD-ROM_CDX-435_M62", BUS_TYPE_SCSI }, { "DEC", "RRD45 (C) DEC", "0436", "[SCSI-1] DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, From 15684d6665d671ab59d163d2d4d3d9ab80341b09 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 16 Jan 2025 01:18:00 -0500 Subject: [PATCH 0117/1190] Initialized ret to 0 --- src/machine/m_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 93d111510..3f5e88011 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -203,7 +203,7 @@ const device_t ibmat_device = { int machine_at_ibm_init(const machine_t *model) { - int ret; + int ret = 0; uint8_t enable_5161; const char *fn[2]; From fceca8d1db0829939b637e6b6b810a378c641f85 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Thu, 16 Jan 2025 20:51:32 +0700 Subject: [PATCH 0118/1190] Added note on CFS1275A --- src/disk/hdd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 6872c7ae1..f10d1f3bf 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -469,7 +469,7 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "AC22100", .model = "WDC AC22100H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "AC31200", .model = "WDC AC31200F", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, - { .name = "[ATA-3] Connor CFS1275A", .internal_name = "CFS1275A", .model = "Connor Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, + { .name = "[ATA-3] Connor CFS1275A", .internal_name = "CFS1275A", .model = "Connor Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, // Either ATA-2 or ATA-3 { .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, From 7696b1c13126c70ccc4de8a8c39748488667c72b Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Fri, 17 Jan 2025 03:02:19 +0700 Subject: [PATCH 0119/1190] A small fix to SV2046D --- src/disk/hdd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index f10d1f3bf..c17f64863 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -535,7 +535,7 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1364D)", .internal_name = "SV1364D", .model = "SAMSUNG SV1364D", .zones = 8, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1705D)", .internal_name = "SV1705D", .model = "SAMSUNG SV1705D", .zones = 8, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Samsung SpinPoint V6800 (SV2046D)", .internal_name = "SV2046D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV2046D)", .internal_name = "SV2046D", .model = "SAMSUNG SV2046D", .zones = 8, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 89, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 8.4gb", .internal_name = "ST38410A", .model = "ST38410A", .zones = 16, .avg_spt = 89, .heads = 2, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Seagate U8 - 13gb", .internal_name = "ST313021A", .model = "ST313021A", .zones = 16, .avg_spt = 89, .heads = 4, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, From ba86e5116f67dba7756f6451bfa59e4b3b67bc53 Mon Sep 17 00:00:00 2001 From: Ectoplasm Date: Thu, 16 Jan 2025 22:28:34 +0200 Subject: [PATCH 0120/1190] GlaBIOS for Juko ST --- src/machine/m_xt.c | 52 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 2988ec201..ef3a84e24 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -594,13 +594,59 @@ machine_xt_dtk_init(const machine_t *model) return ret; } +static const device_config_t jukopc_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "jukost", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "Bios 2.30", .internal_name = "jukost", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { "roms/machines/jukopc/000o001.bin", "" } }, + // GlaBIOS for Juko ST + { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8S_2.ROM", "" } }, + { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VS_2.ROM", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t jukopc_device = { + .name = "Juko ST Devices", + .internal_name = "jukopc_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = jukopc_config +}; + int machine_xt_jukopc_init(const machine_t *model) { - int ret; + int ret = 0; + const char *fn; - ret = bios_load_linear("roms/machines/jukopc/000o001.bin", - 0x000fe000, 8192, 0); + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 8192, 0); + device_context_restore(); if (bios_only || !ret) return ret; From b293aa518c03e91f0a926695ab1edadb966e8cc2 Mon Sep 17 00:00:00 2001 From: Ectoplasm Date: Thu, 16 Jan 2025 22:31:45 +0200 Subject: [PATCH 0121/1190] GlaBIOS for Juko ST --- src/machine/machine_table.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 47a33fa8c..14ad58f95 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -64,6 +64,7 @@ extern const device_t ibmxt86_device; extern const device_t ibmat_device; extern const device_t ibmxt286_device; extern const device_t pb450_device; +extern const device_t jukopc_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -954,7 +955,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &jukopc_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From 54a0bb8522dbf2a061f762b43f6846e1dae1d160 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 16 Jan 2025 22:37:52 +0100 Subject: [PATCH 0122/1190] 1st set of changes (video-related) of the day (January 16th, 2025) ATI Mach8-based (add-on only): Do not override the clone VGA banked mapping with the standard VGA when needed. Fixes issues with banked mapping with ATI 8514/A enabled on cards with clone mappings such as Cirrus, Video7, Paradise/WD, etc. --- src/video/vid_ati_mach8.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 558f37f5b..d294f61e9 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -3493,14 +3493,17 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 dev->vendor_mode = 1; } svga_recalctimings(svga); - mach32_updatemapping(mach, svga); + 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); break; case 0x32ee: case 0x32ef: WRITE8(port, mach->local_cntl, val); - mach32_updatemapping(mach, svga); + if ((dev->local & 0xff) >= 0x01) + mach32_updatemapping(mach, svga); break; case 0x36ee: @@ -3546,7 +3549,8 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", port, mach->accel.clock_sel & 0x01, val, dev->hdisp, dev->vdisp); mach_log("Vendor ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); - mach32_updatemapping(mach, svga); + if ((dev->local & 0xff) >= 0x01) + mach32_updatemapping(mach, svga); break; case 0x52ee: @@ -3580,7 +3584,8 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; - mach32_updatemapping(mach, svga); + if ((dev->local & 0xff) >= 0x01) + mach32_updatemapping(mach, svga); break; case 0x62ee: From 9a13eb7413bbe655a5ffd4de8481cc2e2cc7ad74 Mon Sep 17 00:00:00 2001 From: greblosdier <51314920+greblosdier@users.noreply.github.com> Date: Thu, 16 Jan 2025 13:46:01 -0800 Subject: [PATCH 0123/1190] Fix incorrect chipset for MVI486 Changes the chipset of the Mylex MVI486 from Opti 82C895 to 82C495 --- 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 47a33fa8c..58ad404f4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5962,10 +5962,10 @@ const machine_t machines[] = { /* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix copyright. */ { - .name = "[OPTi 895] Mylex MVI486", + .name = "[OPTi 495] Mylex MVI486", .internal_name = "mvi486", .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .chipset = MACHINE_CHIPSET_OPTI_495, .init = machine_at_mvi486_init, .p1_handler = NULL, .gpio_handler = NULL, From 5d25309027fac853bb8a2d890fe889c4c8f6e561 Mon Sep 17 00:00:00 2001 From: greblosdier <51314920+greblosdier@users.noreply.github.com> Date: Thu, 16 Jan 2025 13:49:43 -0800 Subject: [PATCH 0124/1190] Fixes incorrect chipset model for MVI486 Fixes MVI486 to use Opti 495 chipset --- src/machine/m_at_386dx_486.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index d3c7a21d2..656db503b 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -834,7 +834,7 @@ machine_at_mvi486_init(const machine_t *model) machine_at_common_init(model); - device_add(&opti895_device); + device_add(&opti495_device); device_add(&keyboard_at_device); device_add(&pc87311_ide_device); From ef8a3d8d427bfbc327331fc9d4f72c39f9dce6c8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 23:18:41 +0100 Subject: [PATCH 0125/1190] SCAMP: Reworked a lot of stuff, backfill EMS should now also work. --- src/chipset/scamp.c | 848 +++++++++++++++++++++++++++----------------- 1 file changed, 520 insertions(+), 328 deletions(-) diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 00f9798cb..31e24eeba 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -47,13 +47,35 @@ #define ID_VL82C311 0xd6 -#define RAMMAP_REMP386 (1 << 4) +#define RAMMAP_ROMMOV 0x60 +#define RAMMAP_ROMMOV1 (1 << 6) +#define RAMMAP_ROMMOV0 (1 << 5) +#define RAMMAP_REMP384 (1 << 4) #define EMSEN1_EMSMAP (1 << 4) +#define EMSEN1_BFENAB (1 << 6) #define EMSEN1_EMSENAB (1 << 7) #define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) +#define EMS_MAXPAGE 4 +#define EMS_PGSIZE 16384 +#define EMS_PGMASK 16383 + +#define MEM_FLAG_SLOTBUS 0x40 +#define MEM_FLAG_REMAP 0x20 +#define MEM_FLAG_MEMCARD 0x10 +#define MEM_FLAG_EMS 0x08 +#define MEM_FLAG_ROMCS 0x04 +#define MEM_FLAG_READ 0x02 +#define MEM_FLAG_WRITE 0x01 +#define MEM_FMASK_SLOTBUS 0x40 +#define MEM_FMASK_REMAP 0x20 +#define MEM_FMASK_MEMCARD 0x10 +#define MEM_FMASK_EMS 0x08 +#define MEM_FMASK_ROMCS 0x04 +#define MEM_FMASK_RW 0x03 + /*Commodore SL386SX requires proper memory slot decoding to detect memory size. Therefore we emulate the SCAMP memory address decoding, and therefore are limited to the DRAM combinations supported by the actual chip*/ @@ -72,38 +94,43 @@ typedef struct ram_struct_t { int bank; } ram_struct_t; -typedef struct ems_struct_t { - void *parent; - int segment; -} ems_struct_t; +typedef struct card_mem_t { + int in_ram; + uint32_t virt_addr; + uint32_t phys_addr; + uint8_t *mem; +} mem_page_t; typedef struct scamp_t { - int cfg_index; - uint8_t cfg_regs[256]; - int cfg_enable; - int ram_config; + int cfg_index; + uint8_t cfg_regs[256]; + int cfg_enable; + int ram_config; int ems_index; int ems_autoinc; - uint16_t ems[0x24]; - mem_mapping_t ems_mappings[20]; /*a0000-effff*/ - uint32_t mappings[20]; + uint16_t ems[64]; mem_mapping_t ram_mapping[2]; ram_struct_t ram_struct[2]; - ems_struct_t ems_struct[20]; - uint32_t ram_virt_base[2]; - uint32_t ram_phys_base[2]; - uint32_t ram_mask[2]; - int row_virt_shift[2]; - int row_phys_shift[2]; - int ram_interleaved[2]; - int ibank_shift[2]; + uint32_t ram_virt_base[2]; + uint32_t ram_phys_base[2]; + uint32_t ram_mask[2]; + int row_virt_shift[2]; + int row_phys_shift[2]; + int ram_interleaved[2]; + int ibank_shift[2]; - int ram_flags[24]; + int mem_flags[64]; + mem_mapping_t mem_mappings[64]; /* The entire first 1 MB of memory space. */ + mem_page_t mem_pages[64]; - port_92_t *port_92; + uint32_t card_mem_size; + uint8_t *card_mem; + mem_page_t card_pages[4]; + + port_92_t *port_92; } scamp_t; static const struct { @@ -149,6 +176,70 @@ static const struct { { { BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED }, 0}, /*Undocumented - probably wrong!*/ }; +#ifdef ENABLE_SCAMP_LOG +int scamp_do_log = ENABLE_SCAMP_LOG; + +static void +scamp_log(const char *fmt, ...) +{ + va_list ap; + + if (scamp_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define scamp_log(fmt, ...) +#endif + +/* Read one byte from paged RAM. */ +static uint8_t +scamp_mem_readb(uint32_t addr, void *priv) +{ + mem_page_t *dev = (mem_page_t *) priv; + uint8_t ret = 0xff; + + if (dev->mem != NULL) + ret = *(uint8_t *) &(dev->mem[addr & EMS_PGMASK]); + + return ret; +} + +/* Read one word from paged RAM. */ +static uint16_t +scamp_mem_readw(uint32_t addr, void *priv) +{ + mem_page_t *dev = (mem_page_t *) priv; + uint16_t ret = 0xffff; + + if (dev->mem != NULL) + ret = *(uint16_t *) &(dev->mem[addr & EMS_PGMASK]); + + return ret; +} + +/* Write one byte to paged RAM. */ +static void +scamp_mem_writeb(uint32_t addr, uint8_t val, void *priv) +{ + mem_page_t *dev = (mem_page_t *) priv; + + if (dev->mem != NULL) + *(uint8_t *) &(dev->mem[addr & EMS_PGMASK]) = val; +} + +/* Write one word to paged RAM. */ +static void +scamp_mem_writew(uint32_t addr, uint16_t val, void *priv) +{ + mem_page_t *dev = (mem_page_t *) priv; + + if (dev->mem != NULL) + *(uint16_t *) &(dev->mem[addr & EMS_PGMASK]) = val; +} + /* The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous, so we use separate routines for that special case */ static uint8_t @@ -334,208 +425,193 @@ recalc_mappings(void *priv) /* Once the BIOS programs the correct DRAM configuration, switch to regular linear memory mapping */ if (cur_rammap == ram_configs[dev->ram_config].rammap) { - mem_mapping_set_handler(&ram_low_mapping, - mem_read_ram, mem_read_ramw, mem_read_raml, - mem_write_ram, mem_write_ramw, mem_write_raml); - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_disable(&ram_low_mapping); + + for (uint8_t i = 0; i < 40; i++) + mem_mapping_enable(&(dev->mem_mappings[i])); + if (mem_size > 1024) mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); mem_mapping_enable(&ram_high_mapping); - return; } else { mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_read, NULL, NULL, ram_mirrored_write, NULL, NULL); + mem_mapping_disable(&ram_low_mapping); - } - if (rammap[cur_rammap].bank[0] == BANK_NONE) - bank_nr = 1; + for (uint8_t i = 0; i < 40; i++) + mem_mapping_disable(&(dev->mem_mappings[i])); - for (; bank_nr < 2; bank_nr++) { - old_virt_base = virt_base; - phys_bank = ram_configs[dev->ram_config].bank[bank_nr]; + if (rammap[cur_rammap].bank[0] == BANK_NONE) + bank_nr = 1; - dev->ram_virt_base[bank_nr] = virt_base; + for (; bank_nr < 2; bank_nr++) { + old_virt_base = virt_base; + phys_bank = ram_configs[dev->ram_config].bank[bank_nr]; - if (virt_base == 0) { - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_NONE: - fatal(" Bank %i is empty!\n }\n}\n", bank_nr); - break; + dev->ram_virt_base[bank_nr] = virt_base; - case BANK_256K: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); - } - virt_base += (1 << 19); - dev->row_virt_shift[bank_nr] = 10; - break; + if (virt_base == 0) { + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_NONE: + fatal(" Bank %i is empty!\n }\n}\n", bank_nr); + break; - case BANK_256K_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); - } - virt_base += (1 << 20); - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_256K: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + } + virt_base += (1 << 19); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_1M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 21); - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_256K_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + } + virt_base += (1 << 20); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_1M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (3 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 22); - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_1M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 21); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_4M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (7 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 23); - dev->row_virt_shift[bank_nr] = 12; - break; + case BANK_1M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (3 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 22); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_4M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (15 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 24); - dev->row_virt_shift[bank_nr] = 12; - break; + case BANK_4M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (7 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 23); + dev->row_virt_shift[bank_nr] = 12; + break; - default: - break; + case BANK_4M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (15 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 24); + dev->row_virt_shift[bank_nr] = 12; + break; + + default: + break; + } + } else { + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_NONE: + break; + + case BANK_256K: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 19), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 19); + dev->row_virt_shift[bank_nr] = 10; + break; + + case BANK_256K_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 20); + dev->row_virt_shift[bank_nr] = 10; + break; + + case BANK_1M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 21), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 21); + dev->row_virt_shift[bank_nr] = 11; + break; + + case BANK_1M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 22), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 22); + dev->row_virt_shift[bank_nr] = 11; + break; + + case BANK_4M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 23), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 23); + dev->row_virt_shift[bank_nr] = 12; + break; + + case BANK_4M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 24), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 24); + dev->row_virt_shift[bank_nr] = 12; + break; + + default: + break; + } } - } else { + switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_NONE: - break; - case BANK_256K: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 19), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 19); - dev->row_virt_shift[bank_nr] = 10; - break; - - case BANK_256K_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 20); - dev->row_virt_shift[bank_nr] = 10; - break; - case BANK_1M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 21), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 21); - dev->row_virt_shift[bank_nr] = 11; - break; - - case BANK_1M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 22), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 22); - dev->row_virt_shift[bank_nr] = 11; - break; - case BANK_4M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 23), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 23); - dev->row_virt_shift[bank_nr] = 12; - break; - - case BANK_4M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 24), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 24); - dev->row_virt_shift[bank_nr] = 12; - break; - - default: - break; - } - } - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_256K: - case BANK_1M: - case BANK_4M: - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], ram_mirrored_read, NULL, NULL, ram_mirrored_write, NULL, NULL); - break; - - case BANK_256K_INTERLEAVED: - case BANK_1M_INTERLEAVED: - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_interleaved_read, NULL, NULL, - ram_mirrored_interleaved_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_interleaved_read, NULL, NULL, - ram_mirrored_interleaved_write, NULL, NULL); - break; - - case BANK_4M_INTERLEAVED: - if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) { - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_256k_in_4mi_read, NULL, NULL, - ram_mirrored_256k_in_4mi_write, NULL, NULL); if (!old_virt_base) mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_256k_in_4mi_read, NULL, NULL, - ram_mirrored_256k_in_4mi_write, NULL, NULL); - } else { + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); + break; + + case BANK_256K_INTERLEAVED: + case BANK_1M_INTERLEAVED: mem_mapping_set_handler(&dev->ram_mapping[bank_nr], ram_mirrored_interleaved_read, NULL, NULL, ram_mirrored_interleaved_write, NULL, NULL); @@ -543,131 +619,137 @@ recalc_mappings(void *priv) mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_interleaved_read, NULL, NULL, ram_mirrored_interleaved_write, NULL, NULL); - } - break; + break; - default: - break; + case BANK_4M_INTERLEAVED: + if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) { + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + ram_mirrored_256k_in_4mi_read, NULL, NULL, + ram_mirrored_256k_in_4mi_write, NULL, NULL); + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_256k_in_4mi_read, NULL, NULL, + ram_mirrored_256k_in_4mi_write, NULL, NULL); + } else { + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + ram_mirrored_interleaved_read, NULL, NULL, + ram_mirrored_interleaved_write, NULL, NULL); + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_interleaved_read, NULL, NULL, + ram_mirrored_interleaved_write, NULL, NULL); + } + break; + + default: + break; + } } } } static void -recalc_sltptr(scamp_t *dev) +scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask) { - uint32_t sltptr = dev->cfg_regs[CFG_SLTPTR] << 16; + int read_ext = MEM_READ_EXTERNAL; + int write_ext = MEM_WRITE_EXTERNAL; - if (sltptr >= 0xa0000 && sltptr < 0x100000) - sltptr = 0x100000; - if (sltptr > 0xfe0000) - sltptr = 0xfe0000; + 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; - if (sltptr >= 0xa0000) { - mem_set_mem_state(0, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x100000, sltptr - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(sltptr, 0x1000000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } else { - mem_set_mem_state(0, sltptr, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(sltptr, 0xa0000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - mem_set_mem_state(0x100000, 0xf00000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } -} + new_flags = dev->mem_flags[addr / EMS_PGSIZE]; -static uint8_t -scamp_ems_read(uint32_t addr, void *priv) -{ - const ems_struct_t *ems = (ems_struct_t *) priv; - const scamp_t *dev = ems->parent; - int segment = ems->segment; + if (new_flags & MEM_FLAG_ROMCS) { + read_ext = MEM_READ_ROMCS; + write_ext = MEM_WRITE_ROMCS; + } - addr = (addr & 0x3fff) | dev->mappings[segment]; - return ram[addr]; -} - -static void -scamp_ems_write(uint32_t addr, uint8_t val, void *priv) -{ - const ems_struct_t *ems = (ems_struct_t *) priv; - const scamp_t *dev = ems->parent; - int segment = ems->segment; - - addr = (addr & 0x3fff) | dev->mappings[segment]; - ram[addr] = val; -} - -static void -scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size) -{ - uint8_t flags; - - if ((addr >= 0x000a0000) && (addr < 0x00100000)) { - flags = dev->ram_flags[(addr - 0x000a0000) >> 14]; - - if (flags & 4) + if (new_flags & (MEM_FLAG_REMAP | MEM_FLAG_SLOTBUS)) { + scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (REMAP)\n", addr, addr + size - 1, new_flags); + mem_set_mem_state(addr, size, read_ext | write_ext); + } else if (new_flags & (MEM_FLAG_EMS | MEM_FLAG_MEMCARD)) { + scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (EMS)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else switch (flags & 3) { + } else switch (new_flags & (MEM_FLAG_READ | MEM_FLAG_WRITE)) { case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RE | WE)\n", addr, addr + size - 1, new_flags); + mem_set_mem_state(addr, size, read_ext | write_ext); break; case 1: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RE | WI)\n", addr, addr + size - 1, new_flags); + mem_set_mem_state(addr, size, read_ext | MEM_WRITE_INTERNAL); break; case 2: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RI | WE)\n", addr, addr + size - 1, new_flags); + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | write_ext); break; case 3: + scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RI | WI)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); break; default: break; } } + + flushmmucache_nopc(); +} + +static int +is_seg_in_ram(scamp_t *dev, uint8_t s) +{ + mem_page_t *mp = (mem_page_t *) dev->mem_mappings[s].priv; + const int ret = mp->in_ram; + + return ret; } static void recalc_ems(scamp_t *dev) { - const uint32_t ems_base[12] = { - 0xc0000, 0xc4000, 0xc8000, 0xcc000, - 0xd0000, 0xd4000, 0xd8000, 0xdc000, - 0xe0000, 0xe4000, 0xe8000, 0xec000 - }; - uint32_t new_mappings[20]; - uint16_t ems_enable; + const uint8_t seg_xlat[12] = { 40, 41, 42, 43, 52, 53, 54, 55, 44, 45, 46, 47 }; + const uint16_t seg_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8); - for (int segment = 0; segment < 20; segment++) - new_mappings[segment] = 0xa0000 + segment * 0x4000; + for (uint8_t s = 40; s < 60; s++) { + dev->mem_pages[s].phys_addr = dev->mem_pages[s].virt_addr; + dev->mem_pages[s].mem = ram + dev->mem_pages[s].phys_addr; - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) - ems_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8); - else - ems_enable = 0; + if (is_seg_in_ram(dev, s)) + mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem); - for (int segment = 0; segment < 12; segment++) { - if (ems_enable & (1 << segment)) { - uint32_t phys_addr = dev->ems[segment] << 14; - - /*If physical address is in remapped memory then adjust down to a0000-fffff range*/ - if ((dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) && phys_addr >= (mem_size * 1024) - && phys_addr < ((mem_size + 384) * 1024)) - phys_addr = (phys_addr - mem_size * 1024) + 0xa0000; - new_mappings[(ems_base[segment] - 0xa0000) >> 14] = phys_addr; - } + scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_EMS); } - for (int segment = 0; segment < 20; segment++) { - if (new_mappings[segment] != dev->mappings[segment]) { - dev->mappings[segment] = new_mappings[segment]; - if (new_mappings[segment] < (mem_size * 1024)) { - mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]); - mem_mapping_enable(&dev->ems_mappings[segment]); - dev->ram_flags[segment] |= 0x04; - } else { - mem_mapping_disable(&dev->ems_mappings[segment]); - dev->ram_flags[segment] &= 0xfb; - } + for (uint8_t i = 0; i < 36; i++) { + uint8_t s = (i < 12) ? (i + 48) : (i + 4); + uint8_t on = (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB); + uint32_t phys_addr = dev->ems[i] << 14; - scamp_mem_update_state(dev, 0xa0000 + segment * 0x4000, 0x4000); + if (i < 12) { + if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP) + s = seg_xlat[i]; + + on = on && (seg_enable & (1 << i)); + } else + on = on && (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_BFENAB); + + if (on) { + dev->mem_pages[s].phys_addr = phys_addr; + dev->mem_pages[s].mem = ram + dev->mem_pages[s].phys_addr; + + if (is_seg_in_ram(dev, s)) + mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem); + + scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_EMS, MEM_FMASK_EMS); + } else if (i >= 12) { + dev->mem_pages[s].phys_addr = dev->mem_pages[s].virt_addr; + dev->mem_pages[s].mem = ram + dev->mem_pages[s].phys_addr; + + if (is_seg_in_ram(dev, s)) + mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem); + + scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_EMS); } } @@ -677,32 +759,11 @@ recalc_ems(scamp_t *dev) static void shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state) { - dev->ram_flags[(addr - 0x000a0000) >> 14] &= 0xfc; - dev->ram_flags[(addr - 0x000a0000) >> 14] |= state; - if (size == 0x8000) { - dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] &= 0xfc; - dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] |= state; - } - - switch (state) { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - default: - break; - } - - scamp_mem_update_state(dev, addr, size); + scamp_mem_update_state(dev, addr, EMS_PGSIZE, state, MEM_FMASK_RW); + scamp_mem_update_state(dev, addr + EMS_PGSIZE, EMS_PGSIZE, state, MEM_FMASK_RW); + } else + scamp_mem_update_state(dev, addr, size, state, MEM_FMASK_RW); flushmmucache_nopc(); } @@ -710,14 +771,23 @@ shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state) static void shadow_recalc(scamp_t *dev) { - uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_ABAXS]; - uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS]; - uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS]; - uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS]; + uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_ABAXS]; + uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_CAXS]; + uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_DAXS]; + uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_FEAXS]; /*Enabling remapping will disable all shadowing*/ - if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) - mem_remap_top(384); + if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) + mem_remap_top_nomid(384); + else + mem_remap_top_nomid(0); + + for (uint8_t i = 40; i < 64; i++) { + if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) + scamp_mem_update_state(dev, (i * EMS_PGSIZE), EMS_PGSIZE, MEM_FLAG_REMAP, MEM_FMASK_REMAP); + else + scamp_mem_update_state(dev, (i * EMS_PGSIZE), EMS_PGSIZE, 0x00, MEM_FMASK_REMAP); + } shadow_control(dev, 0xa0000, 0x4000, abaxs & 3); shadow_control(dev, 0xa0000, 0x4000, abaxs & 3); @@ -748,6 +818,97 @@ shadow_recalc(scamp_t *dev) shadow_control(dev, 0xf8000, 0x8000, (feaxs >> 6) & 3); } +static void +recalc_sltptr(scamp_t *dev) +{ + uint32_t sltptr = dev->cfg_regs[CFG_SLTPTR] << 16; + + if (sltptr >= 0xa0000 && sltptr < 0x100000) + sltptr = 0x100000; + if (sltptr > 0xfe0000) + sltptr = 0xfe0000; + + if (sltptr >= 0xa0000) { + for (uint8_t i = 0; i < 40; i++) + scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_SLOTBUS); + + mem_set_mem_state(0x100000, sltptr - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(sltptr, 0x1000000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((sltptr >= 0x40000) && (sltptr <= 0x90000)) { + dev->cfg_regs[CFG_EMSEN1] &= ~EMSEN1_BFENAB; + recalc_ems(dev); + } + } else { + for (uint8_t i = 0; i < (sltptr / EMS_PGSIZE); i++) + scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_SLOTBUS); + + for (uint8_t i = (sltptr / EMS_PGSIZE); i < 40; i++) + scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_SLOTBUS, MEM_FMASK_SLOTBUS); + + mem_set_mem_state(sltptr, 0xa0000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state(0x100000, 0xf00000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + + flushmmucache_nopc(); +} + +static void +recalc_rommov(scamp_t *dev) +{ + switch ((dev->cfg_regs[CFG_RAMMAP] & RAMMAP_ROMMOV) >> 5) { + case 0x00: + scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + + scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + break; + + case 0x01: + scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + + scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + break; + + case 0x02: + scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + + scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + break; + + case 0x03: + scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + + scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS); + break; + } + + flushmmucache_nopc(); +} + static void scamp_write(uint16_t addr, uint8_t val, void *priv) { @@ -755,7 +916,7 @@ scamp_write(uint16_t addr, uint8_t val, void *priv) switch (addr) { case 0xe8: - dev->ems_index = val & 0x1f; + dev->ems_index = val & 0x3f; dev->ems_autoinc = val & 0x40; break; @@ -785,12 +946,14 @@ scamp_write(uint16_t addr, uint8_t val, void *priv) switch (dev->cfg_index) { case CFG_SLTPTR: recalc_sltptr(dev); + recalc_ems(dev); break; case CFG_RAMMAP: recalc_mappings(dev); mem_mapping_disable(&ram_remapped_mapping); shadow_recalc(dev); + recalc_rommov(dev); break; case CFG_EMSEN1: @@ -914,9 +1077,8 @@ scamp_init(UNUSED(const device_t *info)) mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_read, NULL, NULL, ram_mirrored_write, NULL, NULL); + mem_mapping_disable(&ram_mid_mapping); mem_mapping_disable(&ram_high_mapping); - mem_mapping_set_addr(&ram_mid_mapping, 0xf0000, 0x10000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0xf0000); addr = 0; for (uint8_t c = 0; c < 2; c++) { @@ -988,15 +1150,45 @@ scamp_init(UNUSED(const device_t *info)) mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - for (uint8_t c = 0; c < 20; c++) { - dev->ems_struct[c].parent = dev; - dev->ems_struct[c].segment = c; - mem_mapping_add(&dev->ems_mappings[c], - 0xa0000 + c * 0x4000, 0x4000, - scamp_ems_read, NULL, NULL, - scamp_ems_write, NULL, NULL, - ram + 0xa0000 + c * 0x4000, MEM_MAPPING_INTERNAL, (void *) &dev->ems_struct[c]); - dev->mappings[c] = 0xa0000 + c * 0x4000; + for (uint8_t i = 0; i < 12; i++) + dev->ems[i] = (0x000c0000 + (i * EMS_PGSIZE)) >> 14; + + for (uint8_t i = 0; i < 24; i++) + dev->ems[i + 12] = (0x00040000 + (i * EMS_PGSIZE)) >> 14; + + for (uint8_t i = 0; i < 64; i++) { + dev->mem_pages[i].in_ram = 1; + dev->mem_pages[i].virt_addr = i * EMS_PGSIZE; + dev->mem_pages[i].phys_addr = dev->mem_pages[i].virt_addr; + dev->mem_pages[i].mem = ram + dev->mem_pages[i].phys_addr; + + mem_mapping_add(&(dev->mem_mappings[i]), + i * EMS_PGSIZE, EMS_PGSIZE, + scamp_mem_readb, scamp_mem_readw, NULL, + scamp_mem_writeb, scamp_mem_writew, NULL, + dev->mem_pages[i].mem, MEM_MAPPING_INTERNAL, + &(dev->mem_pages[i])); + + if (i < 40) { + mem_mapping_disable(&(dev->mem_mappings[i])); + + scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_RW); + } else { + /* This is needed to the state update actually occurs. */ + dev->mem_flags[i] = MEM_FLAG_READ | MEM_FLAG_WRITE; + scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_RW); + + if (i >= 60) + scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); + } + } + + dev->card_mem = NULL; + + for (uint8_t i = 0; i < 4; i++) { + dev->card_pages[i].virt_addr = i * EMS_PGSIZE; + dev->card_pages[i].phys_addr = dev->card_pages[i].virt_addr; + dev->card_pages[i].mem = dev->card_mem + dev->card_pages[i].phys_addr; } dev->port_92 = device_add(&port_92_device); From 458f7218979790471df07408ec47f0e703eaa3b6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 23:27:44 +0100 Subject: [PATCH 0126/1190] The forgotten mem.c/h changes. --- src/include/86box/mem.h | 2 ++ src/mem/mem.c | 48 ++++++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 87be14d5b..19a331925 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -460,7 +460,9 @@ extern void mem_init(void); extern void mem_close(void); extern void mem_reset(void); extern void mem_remap_top_ex(int kb, uint32_t start); +extern void mem_remap_top_ex_nomid(int kb, uint32_t start); extern void mem_remap_top(int kb); +extern void mem_remap_top_nomid(int kb); extern void umc_smram_recalc(uint32_t start, int set); diff --git a/src/mem/mem.c b/src/mem/mem.c index aafd6223c..d1c6de49d 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -3019,8 +3019,8 @@ umc_smram_recalc(uint32_t start, int set) umc_page_recalc(c, set); } -void -mem_remap_top_ex(int kb, uint32_t start) +static void +mem_remap_top_ex_common(int kb, uint32_t start, int mid) { uint32_t c; int offset; @@ -3123,37 +3123,61 @@ mem_remap_top_ex(int kb, uint32_t start) mem_mapping_set_addr(&ram_remapped_mapping2, (start * 1024) + 0x00020000, 0x00020000); mem_mapping_set_exec(&ram_remapped_mapping2, ram + 0x000d0000); - mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); - mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); - mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); + if (mid) { + mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); + mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); + } } else { mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); mem_mapping_set_exec(&ram_remapped_mapping, ram + start_addr); mem_mapping_disable(&ram_remapped_mapping2); - mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); - mem_mapping_disable(&ram_mid_mapping2); + if (mid) { + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } } } else { mem_mapping_disable(&ram_remapped_mapping); mem_mapping_disable(&ram_remapped_mapping2); - mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); - mem_mapping_disable(&ram_mid_mapping2); + if (mid) { + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } } flushmmucache(); } +void +mem_remap_top_ex(int kb, uint32_t start) +{ + mem_remap_top_ex_common(kb, start, 1); +} + +void +mem_remap_top_ex_nomid(int kb, uint32_t start) +{ + mem_remap_top_ex_common(kb, start, 0); +} + void mem_remap_top(int kb) { mem_remap_top_ex(kb, (mem_size >= 1024) ? mem_size : 1024); } +void +mem_remap_top_nomid(int kb) +{ + mem_remap_top_ex_nomid(kb, (mem_size >= 1024) ? mem_size : 1024); +} + void mem_reset_page_blocks(void) { From 1561b43fa9981945e4e638c9a811744608cdc8b2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2025 23:28:19 +0100 Subject: [PATCH 0127/1190] NEAT: A few clean-ups. --- src/chipset/neat.c | 75 +++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 3c9838e06..73bd1b4c2 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -204,12 +204,14 @@ #define RB12_EMSLEN 0xe0 /* EMS memory chunk size */ #define RB12_EMSLEN_SH 5 -#define RAM_FLAG_EMS 0x08 -#define RAM_FLAG_ROMCS 0x04 -#define RAM_FLAG_SHREAD 0x02 -#define RAM_FLAG_SHWRITE 0x01 -#define RAM_FMASK_EMS 0x08 -#define RAM_FMASK_SHADOW 0x07 +#define MEM_FLAG_REMAP 0x10 +#define MEM_FLAG_EMS 0x08 +#define MEM_FLAG_ROMCS 0x04 +#define MEM_FLAG_READ 0x02 +#define MEM_FLAG_WRITE 0x01 +#define MEM_FMASK_REMAP 0x10 +#define MEM_FMASK_EMS 0x08 +#define MEM_FMASK_SHADOW 0x07 typedef struct ram_page_t { int8_t enabled; /* 1=ENABLED */ @@ -220,7 +222,7 @@ typedef struct ram_page_t { } ram_page_t; typedef struct neat_t { - uint8_t ram_flags[32]; + uint8_t mem_flags[32]; uint8_t regs[128]; /* all the CS8221 registers */ uint8_t indx; /* programmed index into registers */ @@ -339,19 +341,22 @@ 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->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) { - dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask; - dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags; + ((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; - new_flags = dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]; + new_flags = dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE]; - if (new_flags & RAM_FLAG_EMS) { - neat_log("neat_mem_update_state(): %08X-%08X: %02X (EMS)\n", addr, addr + size - 1, new_flags); - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } else if (new_flags & RAM_FLAG_ROMCS) { + if (new_flags & MEM_FLAG_ROMCS) { neat_log("neat_mem_update_state(): %08X-%08X: %02X (ROMCS)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) { + } else if (new_flags & MEM_FLAG_REMAP) { + neat_log("neat_mem_update_state(): %08X-%08X: %02X (REMAP)\n", addr, addr + size - 1, new_flags); + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } else if (new_flags & MEM_FLAG_EMS) { + neat_log("neat_mem_update_state(): %08X-%08X: %02X (EMS)\n", addr, addr + size - 1, new_flags); + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else switch (new_flags & (MEM_FLAG_READ | MEM_FLAG_WRITE)) { case 0: neat_log("neat_mem_update_state(): %08X-%08X: %02X (RE | WE)\n", addr, addr + size - 1, new_flags); mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); @@ -384,7 +389,7 @@ shadow_recalc(neat_t *dev) int write = 1; int shadow_reg = REG_RB3 + ((i - 8) >> 3); int shadow_bit = i & 7; - int ram_flags; + int mem_flags; int read; if (i >= 16) { @@ -409,16 +414,16 @@ shadow_recalc(neat_t *dev) read = dev->regs[shadow_reg] & (1 << shadow_bit); write = write && read; - ram_flags = romcs ? RAM_FLAG_ROMCS : 0x00; - ram_flags |= read ? RAM_FLAG_SHREAD : 0x00; - ram_flags |= write ? RAM_FLAG_SHWRITE : 0x00; + mem_flags = romcs ? MEM_FLAG_ROMCS : 0x00; + mem_flags |= read ? MEM_FLAG_READ : 0x00; + mem_flags |= write ? MEM_FLAG_WRITE : 0x00; - if ((ram_flags > 0x00) && !(ram_flags & RAM_FLAG_ROMCS)) + if ((mem_flags > 0x00) && !(mem_flags & MEM_FLAG_ROMCS)) mem_mapping_set_addr(&(dev->shadow[i].mapping), dev->shadow[i].virt_base, EMS_PGSIZE); else mem_mapping_disable(&(dev->shadow[i].mapping)); - neat_mem_update_state(dev, dev->shadow[i].virt_base, EMS_PGSIZE, ram_flags, RAM_FMASK_SHADOW); + neat_mem_update_state(dev, dev->shadow[i].virt_base, EMS_PGSIZE, mem_flags, MEM_FMASK_SHADOW); } } @@ -439,7 +444,7 @@ ems_recalc(neat_t *dev, ram_page_t *ems) /* Update the EMS RAM address for this page. */ mem_mapping_set_exec(&ems->mapping, ram + ems->phys_base); - neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS); + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, MEM_FLAG_EMS, MEM_FMASK_EMS); #if NEAT_DEBUG > 1 neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", @@ -449,7 +454,7 @@ ems_recalc(neat_t *dev, ram_page_t *ems) /* Disable this page. */ mem_mapping_disable(&ems->mapping); - neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS); + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, MEM_FMASK_EMS); } } @@ -570,11 +575,20 @@ ems_set_handlers(neat_t *dev) ems_recalc_all(dev); } +static void +remap_update_states(neat_t *dev, uint8_t flag) +{ + for (uint8_t i = 0; i < 24; i++) + neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, flag, MEM_FMASK_REMAP); +} + static void remap_update(neat_t *dev, uint8_t val) { if (dev->regs[REG_RB7] & RB7_UMAREL) { - mem_remap_top_ex(0, (dev->remap_base >= 1024) ? dev->remap_base : 1024); + mem_remap_top_ex_nomid(0, (dev->remap_base >= 1024) ? dev->remap_base : 1024); + + remap_update_states(dev, 0x00); neat_log("0 kB at %08X\n", ((dev->remap_base >= 1024) ? dev->remap_base : 1024) << 10); } @@ -595,12 +609,11 @@ remap_update(neat_t *dev, uint8_t val) mem_mapping_disable(&ram_high_mapping); if (val & RB7_UMAREL) { - mem_remap_top_ex(384, (dev->remap_base >= 1024) ? dev->remap_base : 1024); + mem_remap_top_ex_nomid(384, (dev->remap_base >= 1024) ? dev->remap_base : 1024); + + remap_update_states(dev, MEM_FLAG_REMAP); neat_log("384 kB at %08X\n", ((dev->remap_base >= 1024) ? dev->remap_base : 1024) << 10); } - - /* Yes, this has to be done on every step because mem_remap_top_ex() reenables it. */ - mem_mapping_disable(&ram_mid_mapping); } static void @@ -672,9 +685,9 @@ neat_write(uint16_t port, uint8_t val, void *priv) val &= RB2_MASK; *reg = (*reg & ~RB2_MASK) | val; if (val & RB2_TOP128) - neat_mem_update_state(dev, 0x00080000, 0x00020000, RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE, RAM_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, RAM_FMASK_SHADOW); + neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, MEM_FMASK_SHADOW); #if NEAT_DEBUG > 1 neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); #endif From 9b7d5198d7f80e955756522079b642a8137c4aa1 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 18 Jan 2025 04:14:23 +0700 Subject: [PATCH 0128/1190] Removed onboard sound from three machines Per richardg867 --- src/machine/m_at_socket7_3v.c | 3 --- src/machine/m_at_socket8.c | 6 ------ src/machine/machine_table.c | 12 ++++++------ 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 4b980f2b0..262169010 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -695,9 +695,6 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) - machine_snd = device_add(machine_get_snd_device(machine)); - device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 59c412447..6d4776637 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -250,9 +250,6 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (sound_card_current[0] == SOUND_INTERNAL) - device_add(machine_get_snd_device(machine)); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -288,9 +285,6 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (sound_card_current[0] == SOUND_INTERNAL) - device_add(machine_get_snd_device(machine)); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index baba2723c..bd31a58b1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11200,7 +11200,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -11215,7 +11215,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &sb_vibra16c_onboard_device, + .snd_device = NULL, .net_device = NULL }, @@ -13989,7 +13989,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14004,7 +14004,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &cs4236b_device, + .snd_device = NULL, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ @@ -14113,7 +14113,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14128,7 +14128,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &cs4236b_device, + .snd_device = NULL, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ From c20c211e29c1150bb88076221b72075be7509af2 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 18 Jan 2025 04:17:27 +0700 Subject: [PATCH 0129/1190] Line fixes --- src/machine/m_at_socket7_3v.c | 1 - src/machine/m_at_socket8.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 262169010..40ae221a0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -694,7 +694,6 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 6d4776637..e6f78f6a2 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -249,7 +249,6 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -284,7 +283,6 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); From f89d960b7e499d1544b9301e30e7dec222e58ff4 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 18 Jan 2025 04:29:05 +0700 Subject: [PATCH 0130/1190] Added back onboard sound to Mailman Per richardg867 --- src/machine/m_at_socket7_3v.c | 4 ++++ src/machine/machine_table.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 40ae221a0..4b980f2b0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -694,6 +694,10 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bd31a58b1..7b0de9805 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11200,7 +11200,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -11215,7 +11215,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, From 5e12d46f3285dbe2494aba30e178220c0889ad6b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Jan 2025 00:45:55 +0100 Subject: [PATCH 0131/1190] NEAT: More fixes, NEAT machines now POST again. --- src/chipset/neat.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 73bd1b4c2..000492d14 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -239,7 +239,7 @@ typedef struct neat_t { ram_page_t shadow[32]; /* Shadow RAM pages */ } neat_t; -static uint8_t defaults[16] = { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x00, +static uint8_t defaults[16] = { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 }; static uint8_t masks[4] = { RB10_P0EXT, RB10_P1EXT, RB10_P2EXT, RB10_P3EXT }; @@ -924,6 +924,16 @@ neat_init(UNUSED(const device_t *info)) mem_mapping_disable(&ram_mid_mapping); + for (int i = 0; i < 24; i++) { + if (i >= 20) + 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; + neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, 0x00, MEM_FMASK_SHADOW); + } + } + /* * For each supported page (we can have a maximum of 4), * create, initialize and disable the mappings, and set @@ -1096,7 +1106,7 @@ neat_init(UNUSED(const device_t *info)) neat_log("NEAT: **INVALID DRAM SIZE %iKB !**\n", mem_size); } if (dram_mode > 0) { - neat_log("NEAT: using DRAM mode #%i (mem=%iKB)\n", i, mem_size); + neat_log("NEAT: using DRAM mode #%i (mem=%iKB)\n", dram_mode, mem_size); } /* Set up an I/O handler for the chipset. */ From 351390b579a6d61b879f6a1a5a77ec1ed180b6d8 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 18 Jan 2025 10:59:35 -0300 Subject: [PATCH 0132/1190] CS423x: Change Control Indirect Address reserved bit readout for VS440FX BIOS --- src/sound/snd_cs423x.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index f28be9778..a75f695d9 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -147,12 +147,19 @@ cs423x_read(uint16_t addr, void *priv) ret |= 0x04; break; + case 3: /* Control Indirect Access Register */ + /* Intel VS440FX BIOS tells CS4236 from CS4232 through the upper bits. Setting them is enough. */ + ret |= 0xf0; + break; + case 4: /* Control Indirect Data Register */ ret = dev->indirect_regs[dev->regs[3]]; break; case 5: /* Control/RAM Access */ - /* Reading RAM is undocumented; the Windows drivers do so. */ + /* Reading RAM is undocumented, but performed by: + - Windows drivers (unknown purpose) + - Intel VS440FX BIOS (PnP ROM checksum recalculation) */ if (dev->ram_dl == 3) ret = dev->ram_data[dev->ram_addr++]; break; From fb3469c74e7e3660ddb98fcbead59ce1df375a87 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 18 Jan 2025 11:06:18 -0300 Subject: [PATCH 0133/1190] CS423x: Clean up RAM download state machine --- src/sound/snd_cs423x.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index a75f695d9..07f691f30 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -51,6 +51,12 @@ enum { CRYSTAL_CS4237B = 0xc8, CRYSTAL_CS4238B = 0xc9 }; +enum { + CRYSTAL_RAM_CMD = 0, + CRYSTAL_RAM_ADDR_LO = 1, + CRYSTAL_RAM_ADDR_HI = 2, + CRYSTAL_RAM_DATA = 3 +}; enum { CRYSTAL_SLAM_NONE = 0, CRYSTAL_SLAM_INDEX = 1, @@ -160,7 +166,7 @@ cs423x_read(uint16_t addr, void *priv) /* Reading RAM is undocumented, but performed by: - Windows drivers (unknown purpose) - Intel VS440FX BIOS (PnP ROM checksum recalculation) */ - if (dev->ram_dl == 3) + if (dev->ram_dl == CRYSTAL_RAM_DATA) ret = dev->ram_data[dev->ram_addr++]; break; @@ -255,7 +261,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) case 5: /* Control/RAM Access */ switch (dev->ram_dl) { - case 0: /* commands */ + case CRYSTAL_RAM_CMD: /* commands */ switch (val) { case 0x55: /* Disable PnP Key */ dev->pnp_enable = 0; @@ -273,7 +279,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) break; case 0xaa: /* Download RAM */ - dev->ram_dl = 1; + dev->ram_dl = CRYSTAL_RAM_ADDR_LO; break; default: @@ -281,17 +287,17 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) } break; - case 1: /* low address byte */ + case CRYSTAL_RAM_ADDR_LO: /* low address byte */ dev->ram_addr = val; - dev->ram_dl++; + dev->ram_dl = CRYSTAL_RAM_ADDR_HI; break; - case 2: /* high address byte */ - dev->ram_addr |= (val << 8); - dev->ram_dl++; + case CRYSTAL_RAM_ADDR_HI: /* high address byte */ + dev->ram_addr |= val << 8; + dev->ram_dl = CRYSTAL_RAM_DATA; break; - case 3: /* data */ + case CRYSTAL_RAM_DATA: /* data */ dev->ram_data[dev->ram_addr++] = val; break; @@ -303,7 +309,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) case 6: /* RAM Access End */ /* TriGem Delhi-III BIOS writes undocumented value 0x40 instead of 0x00. */ if ((val == 0x00) || (val == 0x40)) { - dev->ram_dl = 0; + dev->ram_dl = CRYSTAL_RAM_CMD; /* Update PnP state and resource data. */ cs423x_pnp_enable(dev, 1, 0); From 9dd6a1b29f764e063d953f0dda1343e64dec698a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 18 Jan 2025 11:48:14 -0300 Subject: [PATCH 0134/1190] CS423x: Add logging, which somehow never existed --- src/sound/snd_cs423x.c | 56 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 07f691f30..95a00cb56 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -15,12 +15,13 @@ * Copyright 2021-2022 RichardG. */ #include +#include #include #include #include #include #include - +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/dma.h> @@ -64,6 +65,24 @@ enum { CRYSTAL_SLAM_BYTE2 = 3 }; +#ifdef ENABLE_CS423X_LOG +int cs423x_do_log = ENABLE_CS423X_LOG; + +static void +cs423x_log(const char *fmt, ...) +{ + va_list ap; + + if (cs423x_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define cs423x_log(fmt, ...) +#endif + static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0x79, 0xBC, 0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2, 0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13, @@ -136,6 +155,8 @@ cs423x_nvram(cs423x_t *dev, uint8_t save) else (void) !fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, fp); fclose(fp); + } else { + cs423x_log("CS423x: EEPROM data %s failed\n", save ? "save" : "load"); } } @@ -166,8 +187,11 @@ cs423x_read(uint16_t addr, void *priv) /* Reading RAM is undocumented, but performed by: - Windows drivers (unknown purpose) - Intel VS440FX BIOS (PnP ROM checksum recalculation) */ - if (dev->ram_dl == CRYSTAL_RAM_DATA) - ret = dev->ram_data[dev->ram_addr++]; + if (dev->ram_dl == CRYSTAL_RAM_DATA) { + ret = dev->ram_data[dev->ram_addr]; + cs423x_log("CS423x: RAM read(%04X) = %02X\n", dev->ram_addr, ret); + dev->ram_addr++; + } break; case 7: /* Global Status */ @@ -188,6 +212,8 @@ cs423x_read(uint16_t addr, void *priv) break; } + cs423x_log("CS423x: read(%X) = %02X\n", reg, ret); + return ret; } @@ -195,7 +221,9 @@ static void cs423x_write(uint16_t addr, uint8_t val, void *priv) { cs423x_t *dev = (cs423x_t *) priv; - uint8_t reg = addr & 0x07; + uint8_t reg = addr & 7; + + cs423x_log("CS423x: write(%X, %02X)\n", reg, val); switch (reg) { case 1: /* EEPROM Interface */ @@ -295,9 +323,11 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) case CRYSTAL_RAM_ADDR_HI: /* high address byte */ dev->ram_addr |= val << 8; dev->ram_dl = CRYSTAL_RAM_DATA; + cs423x_log("CS423x: RAM start(%04X)\n", dev->ram_addr); break; case CRYSTAL_RAM_DATA: /* data */ + cs423x_log("CS423x: RAM write(%04X, %02X)\n", dev->ram_addr, val); dev->ram_data[dev->ram_addr++] = val; break; @@ -309,6 +339,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) case 6: /* RAM Access End */ /* TriGem Delhi-III BIOS writes undocumented value 0x40 instead of 0x00. */ if ((val == 0x00) || (val == 0x40)) { + cs423x_log("CS423x: RAM end\n"); dev->ram_dl = CRYSTAL_RAM_CMD; /* Update PnP state and resource data. */ @@ -332,6 +363,8 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) cs423x_t *dev = (cs423x_t *) priv; uint8_t idx; + cs423x_log("CS423x: slam_write(%02X)\n", val); + switch (dev->slam_state) { case CRYSTAL_SLAM_NONE: /* Not in SLAM: read and compare Crystal key. */ @@ -346,6 +379,7 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) } /* Enter SLAM. */ + cs423x_log("CS423x: SLAM unlocked\n"); dev->slam_state = CRYSTAL_SLAM_INDEX; } } else { @@ -356,6 +390,8 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) case CRYSTAL_SLAM_INDEX: /* Intercept the Activate Audio Device command. */ if (val == 0x79) { + cs423x_log("CS423x: Exiting SLAM\n"); + /* Apply the last logical device's configuration. */ if (dev->slam_config) { cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev); @@ -376,6 +412,7 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) case CRYSTAL_SLAM_BYTE1: case CRYSTAL_SLAM_BYTE2: /* Write register value: two bytes for I/O ports, single byte otherwise. */ + cs423x_log("CS423x: SLAM write(%02X, %02X)\n", dev->slam_reg, val); switch (dev->slam_reg) { case 0x06: /* Card Select Number */ isapnp_set_csn(dev->pnp_card, val); @@ -446,7 +483,7 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) break; } - /* Prepare for the next register, unless a two-byte read returns above. */ + /* Prepare for the next register, unless a two-byte write returns above. */ dev->slam_state = CRYSTAL_SLAM_INDEX; break; @@ -467,8 +504,11 @@ cs423x_slam_enable(cs423x_t *dev, uint8_t enable) /* Enable SLAM if the CKD bit is not set. */ if (enable && !(dev->ram_data[0x4002] & 0x10)) { + cs423x_log("CS423x: Enabling SLAM\n"); dev->slam_enable = 1; io_sethandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev); + } else { + cs423x_log("CS423x: Disabling SLAM\n"); } } @@ -484,6 +524,7 @@ cs423x_ctxswitch_write(uint16_t addr, UNUSED(uint8_t val), void *priv) /* Flip context bit. */ dev->regs[7] ^= 0x80; ctx ^= 0x80; + cs423x_log("CS423x: Context switch to %s\n", ctx ? "WSS" : "SBPro"); /* Update CD audio filter. FIXME: not thread-safe: filter function TOCTTOU in sound_cd_thread! */ @@ -553,6 +594,8 @@ cs423x_get_music_buffer(int32_t *buffer, int len, void *priv) static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) { + cs423x_log("CS423x: Updating PnP ROM=%d hwconfig=%d\n", update_rom, update_hwconfig); + if (dev->pnp_card) { /* Update PnP resource data if requested. */ if (update_rom) @@ -747,6 +790,7 @@ cs423x_init(const device_t *info) /* Initialize model-specific data. */ dev->type = info->local & 0xff; + cs423x_log("CS423x: init(%02X)\n", dev->type); switch (dev->type) { case CRYSTAL_CS4235: case CRYSTAL_CS4236B: @@ -849,6 +893,8 @@ cs423x_close(void *priv) { cs423x_t *dev = (cs423x_t *) priv; + cs423x_log("CS423x: close()\n"); + /* Save EEPROM contents to file. */ if (dev->eeprom) { cs423x_nvram(dev, 1); From f6175add8ffdbd63a61ce31be203bcf14b7be272 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 18 Jan 2025 14:57:05 -0300 Subject: [PATCH 0135/1190] CS423x: Refactor EEPROM-less mode --- src/sound/snd_cs423x.c | 82 ++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 95a00cb56..d7d99b7b3 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -87,11 +87,9 @@ static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0 0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2, 0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13, 0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A }; -static const uint8_t cs4236b_eeprom[8224] = { +static const uint8_t cs4236b_default[] = { // clang-format off /* Chip configuration */ - 0x55, 0xbb, /* magic */ - 0x00, 0x00, /* length */ 0x00, 0x03, /* CD-ROM and modem decode */ 0x80, /* misc. config */ 0x80, /* global config */ @@ -102,8 +100,9 @@ static const uint8_t cs4236b_eeprom[8224] = { 0x75, 0xb9, 0xfc, /* IRQ routing */ 0x10, 0x03, /* DMA routing */ - /* PnP resources */ - 0x00 + /* Default PnP resources */ + /* TODO: broken, not picked up by VS440FX BIOS, pending hardware research of the actual defaults */ + 0x0e, 0x63, 0x42, 0x36, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x10, 0x00, 0x14, 0x41, 0xd0, 0xff, 0xff, 0x79, 0x00 // clang-format on }; @@ -122,6 +121,7 @@ typedef struct cs423x_t { uint16_t ram_addr; uint16_t eeprom_size : 11; uint16_t pnp_offset; + uint16_t pnp_size; uint8_t type; uint8_t ad1848_type; uint8_t regs[8]; @@ -363,7 +363,8 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) cs423x_t *dev = (cs423x_t *) priv; uint8_t idx; - cs423x_log("CS423x: slam_write(%02X)\n", val); + if ((dev->slam_state != CRYSTAL_SLAM_NONE) || (val == slam_init_key[dev->key_pos])) /* cut down on ISAPnP-related noise */ + cs423x_log("CS423x: slam_write(%02X)\n", val); switch (dev->slam_state) { case CRYSTAL_SLAM_NONE: @@ -599,7 +600,7 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) if (dev->pnp_card) { /* Update PnP resource data if requested. */ if (update_rom) - isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], 384); + isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], dev->pnp_size); /* Disable PnP key if the PKD bit is set, or if it was disabled by command 0x55. */ /* But wait! The TriGem Delhi-III BIOS sends command 0x55, and its behavior doesn't @@ -753,9 +754,21 @@ cs423x_reset(void *priv) /* Clear RAM. */ memset(dev->ram_data, 0, sizeof(dev->ram_data)); + /* Load default configuration data to RAM. */ + memcpy(&dev->ram_data[0x4000], cs4236b_default, sizeof(cs4236b_default)); + dev->pnp_size = 19; + if (dev->eeprom) { - /* Load EEPROM data to RAM. */ - memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], MIN(384, ((dev->eeprom_data[2] << 8) | dev->eeprom_data[3]) - 4)); + /* Load EEPROM data to RAM if the magic bytes are present. */ + if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb)) { + cs423x_log("CS423x: EEPROM data valid, loading to RAM\n"); + dev->pnp_size = (dev->eeprom_data[2] << 8) | dev->eeprom_data[3]; + if (dev->pnp_size > 384) + dev->pnp_size = 384; + memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], sizeof(dev->eeprom_data) - 4); + } else { + cs423x_log("CS423x: EEPROM data invalid, ignoring\n"); + } /* Save EEPROM contents to file. */ cs423x_nvram(dev, 1); @@ -800,30 +813,41 @@ cs423x_init(const device_t *info) dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236; dev->pnp_offset = 0x4013; - /* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init */ + /* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init. */ dev->ad1848.xregs[25] = dev->type; if (!(info->local & CRYSTAL_NOEEPROM)) { - /* Load EEPROM contents from template. */ - memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom)); + /* Copy default configuration data. */ + memcpy(&dev->eeprom_data[4], cs4236b_default, sizeof(cs4236b_default)); + /* Load PnP resource data ROM. */ FILE *fp = rom_fopen(PNP_ROM_CS4236B, "rb"); if (fp) { - (void) !fread(&(dev->eeprom_data[23]), 1, 8201, fp); + uint16_t eeprom_pnp_offset = (dev->pnp_offset & 0x1ff) + 4; + /* This is wrong. The header field only indicates PnP resource data length, and real chips use + it to locate the firmware patch area, but we don't need any of that, so we can get away + with pretending the whole ROM is PnP data, at least until we can get full EEPROM dumps. */ + dev->pnp_size = fread(&dev->eeprom_data[eeprom_pnp_offset], 1, sizeof(dev->eeprom_data) - eeprom_pnp_offset, fp); fclose(fp); } - /* Set content size. */ - dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8; - dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff; + /* Populate EEPROM header if the PnP ROM was loaded. */ + if (dev->pnp_size) { + dev->eeprom_data[0] = 0x55; + dev->eeprom_data[1] = 0xbb; + dev->eeprom_data[2] = dev->pnp_size >> 8; + dev->eeprom_data[3] = dev->pnp_size; + } - /* Set PnP card ID and EEPROM file name. */ + /* Patch PnP ROM and set EEPROM file name. */ switch (dev->type) { case CRYSTAL_CS4235: - dev->eeprom_data[8] = 0x05; - dev->eeprom_data[16] = 0x08; - dev->eeprom_data[26] = 0x25; - dev->eeprom_data[44] = '5'; + if (dev->pnp_size) { + dev->eeprom_data[8] = 0x05; + dev->eeprom_data[16] = 0x08; + dev->eeprom_data[26] = 0x25; + dev->eeprom_data[44] = '5'; + } dev->nvr_path = "cs4235.nvr"; break; @@ -832,14 +856,18 @@ cs423x_init(const device_t *info) break; case CRYSTAL_CS4237B: - dev->eeprom_data[26] = 0x37; - dev->eeprom_data[44] = '7'; + if (dev->pnp_size) { + dev->eeprom_data[26] = 0x37; + dev->eeprom_data[44] = '7'; + } dev->nvr_path = "cs4237b.nvr"; break; case CRYSTAL_CS4238B: - dev->eeprom_data[26] = 0x38; - dev->eeprom_data[44] = '8'; + if (dev->pnp_size) { + dev->eeprom_data[26] = 0x38; + dev->eeprom_data[44] = '8'; + } dev->nvr_path = "cs4238b.nvr"; break; @@ -864,8 +892,8 @@ cs423x_init(const device_t *info) /* Initialize I2C bus for the EEPROM. */ dev->i2c = i2c_gpio_init("nvr_cs423x"); - /* Initialize I2C EEPROM if the contents are valid. */ - if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb)) + /* Initialize I2C EEPROM if enabled. */ + if (!(info->local & CRYSTAL_NOEEPROM)) dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->eeprom_data, sizeof(dev->eeprom_data), 1); /* Initialize ISAPnP. */ From 40fd79aeb9bfcf4a3fc597506995d9a250b59669 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 19 Jan 2025 09:06:39 +0100 Subject: [PATCH 0136/1190] FPU: Properly implement INT 10h FPU exception, fixes #5162. --- src/cpu/386.c | 11 ++++++++++- src/cpu/386_common.c | 1 + src/cpu/386_dynarec.c | 30 +++++++++++++++++++++++++++--- src/cpu/cpu.h | 2 ++ src/cpu/x86.c | 1 + src/cpu/x86_ops_fpu.h | 4 ++-- src/cpu/x86_ops_fpu_2386.h | 5 ++++- src/cpu/x87.c | 8 ++++---- src/cpu/x87.h | 4 ++-- src/cpu/x87_ops.h | 4 ++-- 10 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index 8b612604d..21db155e9 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -268,7 +268,8 @@ exec386_2386(int32_t cycs) } else { CHECK_READ_CS(MIN(ol, 4)); } - ins_fetch_fault = cpu_386_check_instruction_fault(); + if (is386) + ins_fetch_fault = cpu_386_check_instruction_fault(); /* Breakpoint fault has priority over other faults. */ if (ins_fetch_fault) { @@ -336,6 +337,14 @@ exec386_2386(int32_t cycs) #endif } } + } else if (new_ne) { + flags_rebuild(); + new_ne = 0; +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + cpu_state.oldpc = cpu_state.pc; + x86_int(16); } else if (trap) { flags_rebuild(); if (trap & 2) dr[6] |= 0x8000; diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index dcbe3608c..a68d866bf 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -72,6 +72,7 @@ extern uint8_t *pccache2; extern int optype; extern uint32_t pccache; +int new_ne = 0; int in_sys = 0; int unmask_a20_in_smm = 0; uint32_t old_rammask = 0xffffffff; diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 5991cf100..c4c095735 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -357,6 +357,8 @@ exec386_dynarec_int(void) CPU_BLOCK_END(); if (smi_line) CPU_BLOCK_END(); + else if (new_ne) + CPU_BLOCK_END(); else if (trap) CPU_BLOCK_END(); else if (nmi && nmi_enable && nmi_mask) @@ -366,7 +368,7 @@ exec386_dynarec_int(void) } block_ended: - if (!cpu_state.abrt && trap) { + 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; @@ -602,6 +604,8 @@ exec386_dynarec_dyn(void) if (cpu_init) CPU_BLOCK_END(); + if (new_ne) + CPU_BLOCK_END(); if ((cpu_state.flags & T_FLAG) || (trap == 2)) CPU_BLOCK_END(); if (smi_line) @@ -626,7 +630,7 @@ exec386_dynarec_dyn(void) cpu_end_block_after_ins = 0; - if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !new_ne && !x86_was_reset) codegen_block_end_recompile(block); if (x86_was_reset) @@ -702,6 +706,8 @@ exec386_dynarec_dyn(void) if (cpu_init) CPU_BLOCK_END(); + if (new_ne) + CPU_BLOCK_END(); if (cpu_state.flags & T_FLAG) CPU_BLOCK_END(); if (smi_line) @@ -726,7 +732,7 @@ exec386_dynarec_dyn(void) cpu_end_block_after_ins = 0; - if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !new_ne && !x86_was_reset) codegen_block_end(); if (x86_was_reset) @@ -809,6 +815,15 @@ exec386_dynarec(int32_t cycs) } } + if (new_ne) { +# ifndef USE_NEW_DYNAREC + oldcs = CS; +# endif + cpu_state.oldpc = cpu_state.pc; + new_ne = 0; + x86_int(16); + } + if (smi_line) enter_smm_check(0); else if (nmi && nmi_enable && nmi_mask) { @@ -977,6 +992,15 @@ block_ended: #endif } } + } else if (new_ne) { + flags_rebuild(); + + new_ne = 0; +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + cpu_state.oldpc = cpu_state.pc; + x86_int(16); } else if (trap) { flags_rebuild(); #ifdef USE_DEBUG_REGS_486 diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index f969390d2..bd841ccc6 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -814,6 +814,8 @@ extern int lock_legal_80[8]; extern int lock_legal_f6[8]; extern int lock_legal_fe[8]; +extern int new_ne; + extern int in_lock; extern int cpu_override_interpreter; diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 8a0bd830f..6f15560f3 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -271,6 +271,7 @@ reset_common(int hard) stack32 = 0; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw = 0; + new_ne = 0; if (hascache) cr0 = 1 << 30; else diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index 11f603c19..74c67c2ee 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -99,8 +99,8 @@ opWAIT(uint32_t fetchdat) if (fpu_softfloat) { if (fpu_state.swd & FPU_SW_Summary) { - if (is486 && (cr0 & 0x20)) - x86_int(16); + if (cr0 & 0x20) + new_ne = 1; else picint(1 << 13); return 1; diff --git a/src/cpu/x86_ops_fpu_2386.h b/src/cpu/x86_ops_fpu_2386.h index d8996d2e1..cc9c6dcc2 100644 --- a/src/cpu/x86_ops_fpu_2386.h +++ b/src/cpu/x86_ops_fpu_2386.h @@ -99,7 +99,10 @@ opWAIT(uint32_t fetchdat) if (fpu_softfloat) { if (fpu_state.swd & FPU_SW_Summary) { - picint(1 << 13); + if (cr0 & 0x20) + new_ne = 1; + else + picint(1 << 13); return 1; } } diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 577fa1a40..3b06cab3c 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -355,10 +355,10 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) nmi = 1; } #else - if (is486 && (cr0 & 0x20)) - x86_int(16); - else - picint(1 << 13); + if (cr0 & 0x20) + new_ne = 1; + else + picint(1 << 13); #endif // FPU_8087 } return unmasked; diff --git a/src/cpu/x87.h b/src/cpu/x87.h index 2ad0c7b10..4d53725c9 100644 --- a/src/cpu/x87.h +++ b/src/cpu/x87.h @@ -228,8 +228,8 @@ FPU_save_regi_tag(extFloat80_t reg, int tag, int stnr) #define FPU_check_pending_exceptions() \ do { \ if (fpu_state.swd & FPU_SW_Summary) { \ - if (is486 && (cr0 & 0x20)) \ - x86_int(16); \ + if (cr0 & 0x20) \ + new_ne = 1; \ else \ picint(1 << 13); \ return 1; \ diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index e1bc5858a..d33122b5c 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -99,8 +99,8 @@ typedef union { dst = src1 / (double) src2; \ else { \ fpu_log("FPU : divide by zero\n"); \ - if (is486 && (cr0 & 0x20)) \ - x86_int(16); \ + if (cr0 & 0x20) \ + new_ne = 1; \ else \ picint(1 << 13); \ return 1; \ From 59e96d2aa01c6bc0a846108858ecc3ba93a99549 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 19 Jan 2025 17:35:38 -0300 Subject: [PATCH 0137/1190] ISAPnP: Create logical devices that don't exist instead of erroring out --- src/device/isapnp.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 470147953..f69c69612 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -121,6 +121,25 @@ typedef struct { isapnp_device_t *current_ld; } isapnp_t; +static isapnp_device_t * +isapnp_create_ld(isapnp_card_t *card) +{ + /* Allocate logical device. */ + isapnp_device_t *ld = calloc(1, sizeof(isapnp_device_t)); + + /* Add to the end of the card's logical device list. */ + isapnp_device_t *prev_ld = card->first_ld; + if (prev_ld) { + while (prev_ld->next) + prev_ld = prev_ld->next; + prev_ld->next = ld; + } else { + card->first_ld = ld; + } + + return ld; +} + static void isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld) { @@ -532,8 +551,12 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin ld = ld->next; } - if (!ld) - isapnp_log("ISAPnP: CSN %02X has no device %02X\n", card->csn, val); + if (!ld) { + isapnp_log("ISAPnP: CSN %02X has no device %02X, creating one\n", card->csn, val); + dev->current_ld_card = card; + dev->current_ld = isapnp_create_ld(card); + dev->current_ld->number = val; + } break; @@ -763,8 +786,7 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) uint8_t mem_range_df = 0; uint8_t mem_range_32_df = 0; uint32_t len; - isapnp_device_t *ld = NULL; - isapnp_device_t *prev_ld = NULL; + isapnp_device_t *ld = NULL; /* Check if this is an existing card which already has logical devices. Any new logical devices will be added to the list after existing ones. @@ -912,18 +934,7 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) memset(ld->io_len, 0, sizeof(ld->io_len)); } else { /* Create logical device. */ - ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t)); - memset(ld, 0, sizeof(isapnp_device_t)); - - /* Add to end of list. */ - prev_ld = card->first_ld; - if (prev_ld) { - while (prev_ld->next) - prev_ld = prev_ld->next; - prev_ld->next = ld; - } else { - card->first_ld = ld; - } + ld = isapnp_create_ld(card); } /* Set and increment logical device number. */ From 8395f5078fc9effa42407e7b604c80049fa52d19 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 19 Jan 2025 17:45:35 -0300 Subject: [PATCH 0138/1190] CS423x: Fixes to PnP in EEPROM-less mode --- src/sound/snd_cs423x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index d7d99b7b3..b8d54ca3f 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -100,9 +100,8 @@ static const uint8_t cs4236b_default[] = { 0x75, 0xb9, 0xfc, /* IRQ routing */ 0x10, 0x03, /* DMA routing */ - /* Default PnP resources */ - /* TODO: broken, not picked up by VS440FX BIOS, pending hardware research of the actual defaults */ - 0x0e, 0x63, 0x42, 0x36, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x10, 0x00, 0x14, 0x41, 0xd0, 0xff, 0xff, 0x79, 0x00 + /* Default PnP data */ + 0x0e, 0x63, 0x42, 0x35, 0xff, 0xff, 0xff, 0xff, 0x00 /* hinted by documentation to be just the header */ // clang-format on }; @@ -343,6 +342,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) dev->ram_dl = CRYSTAL_RAM_CMD; /* Update PnP state and resource data. */ + dev->pnp_size = 384; /* we don't know the length */ cs423x_pnp_enable(dev, 1, 0); } break; @@ -756,7 +756,7 @@ cs423x_reset(void *priv) /* Load default configuration data to RAM. */ memcpy(&dev->ram_data[0x4000], cs4236b_default, sizeof(cs4236b_default)); - dev->pnp_size = 19; + dev->pnp_size = 9; if (dev->eeprom) { /* Load EEPROM data to RAM if the magic bytes are present. */ From ea28c723f1ccb093572264b312b02f528d405be3 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 19 Jan 2025 17:49:32 -0300 Subject: [PATCH 0139/1190] CS423x: Fix CS4236B game port I/O inaccuracy --- src/sound/snd_cs423x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index b8d54ca3f..2736acd82 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -879,9 +879,9 @@ cs423x_init(const device_t *info) cs423x_nvram(dev, 0); } - /* Initialize game port. The '7B and '8B game port only responds to 6 I/O ports; the remaining - 2 ports are reserved on those chips, and probably connected to the Digital Assist feature. */ - dev->gameport = gameport_add(((dev->type == CRYSTAL_CS4235) || (dev->type == CRYSTAL_CS4236B)) ? &gameport_pnp_device : &gameport_pnp_6io_device); + /* Initialize game port. The game port on all B chips only + responds to 6 I/O ports; the remaining 2 are reserved. */ + dev->gameport = gameport_add((dev->type == CRYSTAL_CS4235) ? &gameport_pnp_device : &gameport_pnp_6io_device); break; From 865297420569bfc6d5bf73aac8f8a10b879cc68b Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 19 Jan 2025 19:28:25 -0300 Subject: [PATCH 0140/1190] CS423x: Plumbing for more chips and clean-ups --- src/sound/snd_cs423x.c | 116 +++++++++++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 34 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 2736acd82..0d9af74f2 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -47,10 +47,13 @@ #define CRYSTAL_NOEEPROM 0x100 enum { - CRYSTAL_CS4235 = 0xdd, - CRYSTAL_CS4236B = 0xcb, + CRYSTAL_CS4232 = 0x32, /* no chip ID; dummy value */ + CRYSTAL_CS4236 = 0x36, /* no chip ID; dummy value */ + CRYSTAL_CS4236B = 0xab, /* report an older revision ID to make the values nice and incremental */ CRYSTAL_CS4237B = 0xc8, - CRYSTAL_CS4238B = 0xc9 + CRYSTAL_CS4238B = 0xc9, + CRYSTAL_CS4235 = 0xdd, + CRYSTAL_CS4239 = 0xde }; enum { CRYSTAL_RAM_CMD = 0, @@ -143,6 +146,7 @@ typedef struct cs423x_t { static void cs423x_slam_enable(cs423x_t *dev, uint8_t enable); static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig); static void cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); +static void cs423x_reset(void *priv); static void cs423x_nvram(cs423x_t *dev, uint8_t save) @@ -173,13 +177,15 @@ cs423x_read(uint16_t addr, void *priv) ret |= 0x04; break; - case 3: /* Control Indirect Access Register */ + case 3: /* Control Indirect Access Register (CS4236B+) */ /* Intel VS440FX BIOS tells CS4236 from CS4232 through the upper bits. Setting them is enough. */ - ret |= 0xf0; + if (dev->type >= CRYSTAL_CS4236) + ret |= 0xf0; break; - case 4: /* Control Indirect Data Register */ - ret = dev->indirect_regs[dev->regs[3]]; + case 4: /* Control Indirect Data Register (CS4236B+) / Control Data Register (CS4236) */ + if (dev->type >= CRYSTAL_CS4236B) + ret = dev->indirect_regs[dev->regs[3]]; break; case 5: /* Control/RAM Access */ @@ -193,7 +199,10 @@ cs423x_read(uint16_t addr, void *priv) } break; - case 7: /* Global Status */ + case 7: /* Global Status (CS4236+) */ + if (dev->type < CRYSTAL_CS4236) + break; + /* Context switching: take active context and interrupt flag, then clear interrupt flag. */ ret &= 0xc0; dev->regs[7] &= 0x80; @@ -225,50 +234,75 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) cs423x_log("CS423x: write(%X, %02X)\n", reg, val); switch (reg) { + case 0: /* Joystick and Power Control */ + if (dev->type <= CRYSTAL_CS4232) + val &= 0xeb; + break; + case 1: /* EEPROM Interface */ + if (dev->type <= CRYSTAL_CS4232) + val &= 0x37; if (val & 0x04) i2c_gpio_set(dev->i2c, val & 0x01, val & 0x02); break; - case 3: /* Control Indirect Access Register */ + case 2: /* Block Power Down (CS4236+) */ + if (dev->type < CRYSTAL_CS4236) + return; + break; + + case 3: /* Control Indirect Access Register (CS4236B+) */ + if (dev->type < CRYSTAL_CS4236B) + return; val &= 0x0f; break; - case 4: /* Control Indirect Data Register */ + case 4: /* Control Indirect Data Register (CS4236B+) / Control Data Register (CS4236) */ + if (dev->type < CRYSTAL_CS4236) { + return; + } else if (dev->type == CRYSTAL_CS4236) { + val &= 0x40; + break; + } switch (dev->regs[3] & 0x0f) { case 0: /* WSS Master Control */ - if (val & 0x80) + if ((dev->type < CRYSTAL_CS4235) && (val & 0x80)) ad1848_init(&dev->ad1848, dev->ad1848_type); val = 0x00; break; - case 1: /* Version / Chip ID */ - case 7: /* Reserved */ - case 9 ... 15: /* unspecified */ + case 1: /* Version / Chip ID */ + case 7: /* Reserved */ + case 10 ... 15: /* unspecified */ return; - case 2: /* 3D Space and {Center|Volume} */ - case 6: /* Upper Channel Status */ + case 2: /* 3D Space and {Center|Volume} (CS4237B+) */ if (dev->type < CRYSTAL_CS4237B) return; break; - case 3: /* 3D Enable */ + case 3: /* 3D Enable (CS4237B+) */ if (dev->type < CRYSTAL_CS4237B) return; val &= 0xe0; break; - case 4: /* Consumer Serial Port Enable */ + case 4: /* Consumer Serial Port Enable (CS423[78]B, unused on CS4235+) */ if (dev->type < CRYSTAL_CS4237B) return; val &= 0xf0; break; - case 5: /* Lower Channel Status */ + case 5: /* Lower Channel Status (CS423[78]B, unused on CS4235+) */ + if (dev->type < CRYSTAL_CS4237B) + return; + if (dev->type < CRYSTAL_CS4235) /* bit 0 changed from reserved to unused on CS4235 */ + val &= 0xfe; + break; + + case 6: /* Upper Channel Status (CS423[78]B, unused on CS4235+) */ if (dev->type < CRYSTAL_CS4237B) return; - val &= 0xfe; break; case 8: /* CS9236 Wavetable Control */ @@ -280,6 +314,16 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) ad1848_updatevolmask(&dev->ad1848); break; + case 9: /* Power Management (CS4235+) */ + if (dev->type < CRYSTAL_CS4235) + return; + if ((dev->indirect_regs[dev->regs[3]] & 0x80) && !(val & 0x80)) { + cs423x_reset(dev); + return; + } + val &= 0x83; + break; + default: break; } @@ -347,7 +391,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) } break; - case 7: /* Global Status */ + case 7: /* Global Status (CS4236+) */ return; default: @@ -557,7 +601,7 @@ cs423x_get_buffer(int32_t *buffer, int len, void *priv) ad1848_update(&dev->ad1848); /* Don't output anything if the analog section is powered down. */ - if (!(dev->indirect_regs[2] & 0xa4)) { + if (!(dev->indirect_regs[2] & 0xa4) && !(dev->indirect_regs[9] & 0x04)) { for (int c = 0; c < len * 2; c += 2) { buffer[c] += dev->ad1848.buffer[c] / 2; buffer[c + 1] += dev->ad1848.buffer[c + 1] / 2; @@ -570,26 +614,22 @@ cs423x_get_buffer(int32_t *buffer, int len, void *priv) static void cs423x_get_music_buffer(int32_t *buffer, int len, void *priv) { - cs423x_t *dev = (cs423x_t *) priv; - int opl_wss = dev->opl_wss; - const int32_t *opl_buf = NULL; + cs423x_t *dev = (cs423x_t *) priv; /* Output audio from the WSS codec, and also the OPL if we're in charge of it. */ - if (opl_wss) - opl_buf = dev->sb->opl.update(dev->sb->opl.priv); + if (dev->opl_wss) { + const int32_t *opl_buf = dev->sb->opl.update(dev->sb->opl.priv); - /* Don't output anything if the analog section is powered down. */ - if (!(dev->indirect_regs[2] & 0xa4)) { - for (int c = 0; c < len * 2; c += 2) { - if (opl_wss) { + /* Don't output anything if the analog section or DAC2 (CS4235+) is powered down. */ + if (!(dev->indirect_regs[2] & 0xa4) && !(dev->indirect_regs[9] & 0x06)) { + for (int c = 0; c < len * 2; c += 2) { buffer[c] += (opl_buf[c] * dev->ad1848.fm_vol_l) >> 16; buffer[c + 1] += (opl_buf[c + 1] * dev->ad1848.fm_vol_r) >> 16; } } - } - if (opl_wss) dev->sb->opl.reset_buffer(dev->sb->opl.priv); + } } static void @@ -625,7 +665,7 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) } /* Update SPS. */ - if (dev->type != CRYSTAL_CS4235) { + if ((dev->type >= CRYSTAL_CS4236B) && (dev->type <= CRYSTAL_CS4238B)) { if (dev->ram_data[0x4003] & 0x04) dev->indirect_regs[8] |= 0x04; else @@ -638,6 +678,14 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) else dev->ad1848.xregs[4] &= ~0x10; + /* Update VCEN. */ + if (dev->type == CRYSTAL_CS4236) { + if (dev->ram_data[0x4002] & 0x04) + dev->regs[4] |= 0x40; + else + dev->regs[4] &= ~0x40; + } + /* Inform WSS codec of the changes. */ ad1848_updatevolmask(&dev->ad1848); } From 84853cb21fbc0b1c5448ec34f2a58c04107ab57b Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 19 Jan 2025 20:23:11 -0300 Subject: [PATCH 0141/1190] AD1848: Plumbing for more CS423x chips --- src/include/86box/snd_ad1848.h | 8 ++-- src/sound/snd_ad1848.c | 87 +++++++++++++++++----------------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/include/86box/snd_ad1848.h b/src/include/86box/snd_ad1848.h index 319f9bf24..a7e38a6f8 100644 --- a/src/include/86box/snd_ad1848.h +++ b/src/include/86box/snd_ad1848.h @@ -16,7 +16,7 @@ * * Copyright 2008-2020 Sarah Walker. * Copyright 2018-2020 TheCollector1995. - * Copyright 2021 RichardG. + * Copyright 2021-2025 RichardG. */ #ifndef SOUND_AD1848_H @@ -26,8 +26,10 @@ enum { AD1848_TYPE_DEFAULT = 0, AD1848_TYPE_CS4248 = 1, AD1848_TYPE_CS4231 = 2, - AD1848_TYPE_CS4235 = 3, - AD1848_TYPE_CS4236 = 4 + AD1848_TYPE_CS4232 = 3, + AD1848_TYPE_CS4236 = 4, + AD1848_TYPE_CS4236B = 5, + AD1848_TYPE_CS4235 = 6 }; typedef struct ad1848_t { diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index 4b7941959..a0166c4e5 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -16,7 +16,7 @@ * * Copyright 2008-2020 Sarah Walker. * Copyright 2018-2020 TheCollector1995. - * Copyright 2021-2022 RichardG. + * Copyright 2021-2025 RichardG. */ #include #include @@ -33,6 +33,7 @@ #include <86box/plat_fallthrough.h> #define CS4231 0x80 +#define CS4232 0x02 #define CS4236 0x03 static int ad1848_vols_7bits[128]; @@ -57,10 +58,10 @@ ad1848_setdma(ad1848_t *ad1848, int newdma) void ad1848_updatevolmask(ad1848_t *ad1848) { - if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->xregs[4] & 0x10) || ad1848->wten)) - ad1848->wave_vol_mask = 0x3f; - else + if ((ad1848->type == AD1848_TYPE_CS4236B) && !(ad1848->xregs[4] & 0x10) && !ad1848->wten) ad1848->wave_vol_mask = 0x7f; + else + ad1848->wave_vol_mask = 0x3f; } static double @@ -106,8 +107,8 @@ ad1848_updatefreq(ad1848_t *ad1848) { double freq; - if (ad1848->type >= AD1848_TYPE_CS4235) { - if (ad1848->xregs[11] & 0x20) { + if (ad1848->type >= AD1848_TYPE_CS4232) { + if (ad1848->xregs[11] & 0x20) { /* CS4236B+ only */ freq = 16934400.0; switch (ad1848->xregs[13]) { default: @@ -182,7 +183,7 @@ ad1848_read(uint16_t addr, void *priv) case 18: case 19: - if (ad1848->type >= AD1848_TYPE_CS4235) { + if (ad1848->type >= AD1848_TYPE_CS4236B) { if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */ ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */ else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */ @@ -192,13 +193,13 @@ ad1848_read(uint16_t addr, void *priv) case 20: case 21: - /* Backdoor to the Control/RAM registers on CS4235. */ - if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) + /* Backdoor to the Control/RAM registers on CS4235+. */ + if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv); break; case 23: - if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->regs[23] & 0x08)) { + if ((ad1848->type >= AD1848_TYPE_CS4236B) && (ad1848->regs[23] & 0x08)) { if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */ ret = ad1848->regs[18 + ad1848->xindex]; else @@ -235,7 +236,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */ else ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */ - if (ad1848->type >= AD1848_TYPE_CS4235) + if (ad1848->type >= AD1848_TYPE_CS4236B) ad1848->regs[23] &= ~0x08; /* clear XRAE */ ad1848->trd = val & 0x20; ad1848->mce = val & 0x40; @@ -244,7 +245,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 1: switch (ad1848->index) { case 10: - if (ad1848->type < AD1848_TYPE_CS4235) + if (ad1848->type < AD1848_TYPE_CS4232) break; fallthrough; @@ -282,13 +283,13 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 17: /* Enable additional data formats on modes 2 and 3 where supported. */ - if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236)) + if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236B)) ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70; break; case 18: case 19: - if (ad1848->type >= AD1848_TYPE_CS4235) { + if (ad1848->type >= AD1848_TYPE_CS4236B) { if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */ ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */ temp = 1; @@ -332,8 +333,8 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 20: case 21: - /* Backdoor to the Control/RAM registers on CS4235. */ - if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) { + /* Backdoor to the Control/RAM registers on CS4235+. */ + if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) { ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv); val = ad1848->regs[ad1848->index]; } @@ -344,7 +345,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) break; case 23: - if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->regs[12] & 0x60) == 0x60)) { + if ((ad1848->type >= AD1848_TYPE_CS4236B) && ((ad1848->regs[12] & 0x60) == 0x60)) { if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */ ad1848->xindex = ((val & 0x04) << 2) | (val >> 4); break; @@ -401,7 +402,11 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 25: return; case 27: - if (ad1848->type != AD1848_TYPE_DEFAULT) + if ((ad1848->type != AD1848_TYPE_CS4232) && (ad1848->type != AD1848_TYPE_CS4236)) + return; + break; + case 29: + if ((ad1848->type != AD1848_TYPE_CS4232) && (ad1848->type != AD1848_TYPE_CS4236)) return; break; @@ -456,17 +461,13 @@ ad1848_process_mulaw(uint8_t byte) { byte = ~byte; int temp = (((byte & 0x0f) << 3) + 0x84); - int16_t dec; temp <<= ((byte & 0x70) >> 4); temp = (byte & 0x80) ? (0x84 - temp) : (temp - 0x84); if (temp > 32767) - dec = 32767; + return 32767; else if (temp < -32768) - dec = -32768; - else - dec = (int16_t) temp; - - return dec; + return -32768; + return (int16_t) temp; } static int16_t @@ -489,8 +490,7 @@ ad1848_process_alaw(uint8_t byte) dec |= 0x108; break; } - dec = (byte & 0x80) ? dec : -dec; - return (int16_t) dec; + return (int16_t) ((byte & 0x80) ? dec : -dec); } static uint32_t @@ -704,10 +704,7 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) ad1848->regs[8] = 0; ad1848->regs[9] = 0x08; ad1848->regs[10] = ad1848->regs[11] = 0; - if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231) || (type >= AD1848_TYPE_CS4235)) - ad1848->regs[12] = 0x8a; - else - ad1848->regs[12] = 0xa; + ad1848->regs[12] = (type >= AD1848_TYPE_CS4248) ? 0x8a : 0xa; ad1848->regs[13] = 0; ad1848->regs[14] = ad1848->regs[15] = 0; @@ -719,27 +716,29 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) ad1848->regs[25] = CS4231; ad1848->regs[26] = 0x80; ad1848->regs[29] = 0x80; - } else if (type >= AD1848_TYPE_CS4235) { + } else if (type >= AD1848_TYPE_CS4232) { ad1848->regs[16] = ad1848->regs[17] = 0; ad1848->regs[18] = ad1848->regs[19] = 0; ad1848->regs[20] = ad1848->regs[21] = 0; ad1848->regs[22] = ad1848->regs[23] = 0; ad1848->regs[24] = 0; - ad1848->regs[25] = CS4236; + ad1848->regs[25] = (type == AD1848_TYPE_CS4232) ? CS4232 : CS4236; ad1848->regs[26] = 0xa0; ad1848->regs[27] = ad1848->regs[29] = 0; ad1848->regs[30] = ad1848->regs[31] = 0; - ad1848->xregs[0] = ad1848->xregs[1] = 0xe8; - ad1848->xregs[2] = ad1848->xregs[3] = 0xcf; - ad1848->xregs[4] = 0x84; - ad1848->xregs[5] = 0; - ad1848->xregs[6] = ad1848->xregs[7] = 0x80; - ad1848->xregs[8] = ad1848->xregs[9] = 0; - ad1848->xregs[10] = 0x3f; - ad1848->xregs[11] = 0xc0; - ad1848->xregs[14] = ad1848->xregs[15] = 0; - ad1848->xregs[16] = ad1848->xregs[17] = 0; + if (type >= AD1848_TYPE_CS4236B) { + ad1848->xregs[0] = ad1848->xregs[1] = 0xe8; + ad1848->xregs[2] = ad1848->xregs[3] = 0xcf; + ad1848->xregs[4] = 0x84; + ad1848->xregs[5] = 0; + ad1848->xregs[6] = ad1848->xregs[7] = 0x80; + ad1848->xregs[8] = ad1848->xregs[9] = 0; + ad1848->xregs[10] = 0x3f; + ad1848->xregs[11] = 0xc0; + ad1848->xregs[14] = ad1848->xregs[15] = 0; + ad1848->xregs[16] = ad1848->xregs[17] = 0; + } } ad1848_updatefreq(ad1848); @@ -747,7 +746,7 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) ad1848->out_l = ad1848->out_r = 0; ad1848->fm_vol_l = ad1848->fm_vol_r = 65536; ad1848_updatevolmask(ad1848); - if (type == AD1848_TYPE_CS4235) + if (type >= AD1848_TYPE_CS4235) ad1848->fmt_mask = 0x50; else ad1848->fmt_mask = 0x70; From f48c50f4ba7ac469fa79ed6119ac19f7376b79fd Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 20 Jan 2025 03:26:49 +0100 Subject: [PATCH 0142/1190] The delayed video changes of the night (January 20th, 2025) Generic SVGA layer: Added function pointers of the banked mapping for use with add-on cards with their own mapping when the VGA card banked mapping is not active or viceversa (e.g.: XGA). XGA-1/2: 1. Reimplemented Area Fill and Boundary Mode as best as possible. 2. Fixed conflicts with banked mapping with VGA clones. 3. Fixed inverted colors (again) on accelerated 16bpp mode under OS/2. Video7 with ATI 8514/A add-on. Added a workaround (BIOS issue? I don't know) that disables 8514/A mode and reenables VGA mode when needed. Fixes screen freezes and polling issues with various drivers for Windows and others. --- src/include/86box/vid_svga.h | 8 + src/video/vid_cl54xx.c | 8 + src/video/vid_ht216.c | 27 +++- src/video/vid_paradise.c | 22 +-- src/video/vid_svga.c | 21 ++- src/video/vid_xga.c | 276 ++++++++++++++++++++--------------- 6 files changed, 219 insertions(+), 143 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index d38b7614b..2b26df2f3 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -202,6 +202,14 @@ typedef struct svga_t { void (*vblank_start)(struct svga_t *svga); + void (*write)(uint32_t addr, uint8_t val, void *priv); + void (*writew)(uint32_t addr, uint16_t val, void *priv); + void (*writel)(uint32_t addr, uint32_t val, void *priv); + + uint8_t (*read)(uint32_t addr, void *priv); + uint16_t (*readw)(uint32_t addr, void *priv); + uint32_t (*readl)(uint32_t addr, void *priv); + void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); float (*getclock)(int clock, void *priv); float (*getclock8514)(int clock, void *priv); diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index bc54d0d7c..08a8c7677 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4403,7 +4403,13 @@ gd54xx_init(const device_t *info) if ((vram == 1) || (vram >= 256 && vram <= 1024)) svga->decode_mask = gd54xx->vram_mask; + svga->read = gd54xx_read; + svga->readw = gd54xx_readw; + svga->write = gd54xx_write; + svga->writew = gd54xx_writew; if (gd54xx->bit32) { + svga->readl = gd54xx_readl; + svga->writel = gd54xx_writel; mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, @@ -4423,6 +4429,8 @@ gd54xx_init(const device_t *info) gd5480_vgablt_write, gd5480_vgablt_writew, gd5480_vgablt_writel, NULL, MEM_MAPPING_EXTERNAL, gd54xx); } else { + svga->readl = NULL; + svga->writel = NULL; mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, NULL, gd54xx_write, gd54xx_writew, NULL); mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index a249631ee..f349864df 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -33,9 +33,12 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/video.h> +#include <86box/vid_8514a.h> #include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> @@ -425,9 +428,8 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) svga->banked_mask = 0xffff; } - if (svga->gdcaddr <= 8) { + if (svga->gdcaddr <= 8) svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && svga->packed_chain4; - } break; case 0x3D4: @@ -625,7 +627,9 @@ ht216_remap(ht216_t *ht216) void ht216_recalctimings(svga_t *svga) { - ht216_t *ht216 = (ht216_t *) svga->priv; + ht216_t *ht216 = (ht216_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + mach_t *mach = (mach_t *) svga->ext8514; int high_res_256 = 0; @@ -672,10 +676,16 @@ ht216_recalctimings(svga_t *svga) if (!svga->scrblank && svga->attr_palette_enable) { if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { + if (svga->seqregs[1] & 8) /*40 column*/ svga->render = svga_render_text_40; - } else { + else svga->render = svga_render_text_80; + + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (svga->ext8514 != NULL) { + if (!(dev->accel.advfunc_cntl & 0x01) && !(mach->accel.clock_sel & 0x01)) /*FIXME: Possibly a BIOS bug within the V7 chips when it's used with a 8514/A card?*/ + dev->on &= ~0x01; + } } } else { if (svga->crtc[0x17] == 0xeb) { @@ -1576,10 +1586,17 @@ ht216_init(const device_t *info, uint32_t mem_size, int has_rom) if (has_rom == 4) svga->ramdac = device_add(&sc11484_nors2_ramdac_device); + svga->read = ht216_read; + svga->readw = NULL; + svga->readl = NULL; + svga->write = ht216_write; + svga->writew = ht216_writew; if ((info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { + svga->writel = ht216_writel; mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); } else { + svga->writel = NULL; mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, svga); } diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index bf038eb32..27e98d32d 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -362,11 +362,6 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->attrregs[0x10] & 0x40)) { - svga_write(addr, val, svga); - return; - } - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ @@ -400,11 +395,6 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->attrregs[0x10] & 0x40)) { - svga_writew(addr, val, svga); - return; - } - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ @@ -438,9 +428,6 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->attrregs[0x10] & 0x40)) - return svga_read(addr, svga); - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ @@ -474,9 +461,6 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->attrregs[0x10] & 0x40)) - return svga_readw(addr, svga); - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ @@ -550,6 +534,12 @@ paradise_init(const device_t *info, uint32_t memory) break; } + svga->read = paradise_read; + svga->readw = paradise_readw; + svga->readl = NULL; + svga->write = paradise_write; + svga->writew = paradise_writew; + svga->writel = NULL; mem_mapping_set_handler(&svga->mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); mem_mapping_set_p(&svga->mapping, paradise); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 6a91713fb..e6201e4bf 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -984,7 +984,7 @@ svga_recalctimings(svga_t *svga) svga_log("IBM 8514/A poll.\n"); timer_set_callback(&svga->timer, ibm8514_poll); } else { - svga_log("SVGA Poll.\n"); + svga_log("SVGA poll enabled.\n"); timer_set_callback(&svga->timer, svga_poll); } } @@ -1081,6 +1081,7 @@ svga_poll(void *priv) } } + svga_log("SVGA Poll.\n"); if (!svga->linepos) { if (svga->displine == ((svga->hwcursor_latch.y < 0) ? 0 : svga->hwcursor_latch.y) && svga->hwcursor_latch.ena) { svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - svga->hwcursor_latch.yoff; @@ -1406,16 +1407,34 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->ksc5601_english_font_type = 0; if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { + svga->read = svga_read; + svga->readw = svga_readw; + svga->readl = svga_readl; + svga->write = svga_write; + svga->writew = svga_writew; + svga->writel = svga_writel; mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); } else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_AT)) { + svga->read = svga_read; + svga->readw = svga_readw; + svga->readl = NULL; + svga->write = svga_write; + svga->writew = svga_writew; + svga->writel = NULL; mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, NULL, svga_write, svga_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, svga); } else { + svga->read = svga_read; + svga->readw = NULL; + svga->readl = NULL; + svga->write = svga_write; + svga->writew = NULL; + svga->writel = NULL; mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, NULL, NULL, svga_write, NULL, NULL, diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 3df43a29c..852ff6273 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -188,7 +188,7 @@ xga_updatemapping(svga_t *svga) mem_mapping_disable(&xga->linear_mapping); break; default: - xga_log("XGA: Extended Graphics mode.\n"); + xga_log("XGA: Extended Graphics mode, ap=%d.\n", xga->aperture_cntl); switch (xga->aperture_cntl) { case 0: xga_log("XGA: No 64KB aperture: 1MB=%x, 4MB=%x, SVGA Mapping Base=%x.\n", xga->base_addr_1mb, xga->linear_base, svga->mapping.base); @@ -201,7 +201,7 @@ xga_updatemapping(svga_t *svga) } else mem_mapping_disable(&xga->linear_mapping); - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel); switch (svga->gdcreg[6] & 0xc) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -439,9 +439,9 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) break; case 0x51: - xga_log("Reg51 write = %02x.\n", val); + xga_log("Reg51 write=%02x.\n", val & 0x07); xga->disp_cntl_2 = val; - xga->on = ((val & 7) >= 2); + xga->on = ((val & 0x07) >= 0x02); svga_recalctimings(svga); break; @@ -535,9 +535,11 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv) xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); switch (addr & 0x0f) { case 0: + xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); xga->op_mode = val; break; case 1: + xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); xga->aperture_cntl = val & 3; xga_updatemapping(svga); break; @@ -579,6 +581,7 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv) break; default: + xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); break; } } @@ -807,6 +810,7 @@ xga_ext_inb(uint16_t addr, void *priv) break; default: + xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x.\n\n", CS, cpu_state.pc, addr, ret); break; } @@ -933,6 +937,32 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, uint32_t base, int return px; } +static uint32_t +xga_accel_read_area_map_pixel(svga_t *svga, int x, int y, uint32_t base, int width) +{ + const xga_t *xga = (xga_t *) svga->xga; + uint32_t addr = base; + int bits; + uint8_t byte; + uint8_t px; + int skip = 0; + + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) + skip = 1; + + addr += (y * (width >> 3)); + addr += (x >> 3); + if (!skip) { + READ(addr, byte); + } else + byte = mem_readb_phys(addr); + + bits = 7 - (x & 7); + + px = (byte >> bits) & 1; + return px; +} + static uint32_t xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int width) { @@ -971,6 +1001,7 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int } else byte = mem_readb_phys(addr); + xga_log("4bpp read: OPMODEBIG=%02x, SRC Map=%02x, DST Map=%02x, AccessMode=%02x, SRCPIX=%02x, DSTPIX=%02x, wordpix=%04x, x=%d, y=%d, skip=%d.\n", xga->op_mode & 0x08, (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[xga->accel.dst_map] & 0x0f), xga->access_mode & 0x0f, xga->accel.src_map, xga->accel.dst_map, byte, x, y, skip); return byte; case 3: /*8-bit*/ addr += (y * width); @@ -984,19 +1015,15 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int case 4: /*16-bit*/ addr += (y * (width << 1)); addr += (x << 1); - if (xga->access_mode & 0x08) { - if (!skip) { - READW(addr, byte); - } else - byte = mem_readw_phys(addr); - } else { - if (!skip) { - READW(addr, byte); - } else { - byte = mem_readw_phys(addr); - if ((xga->access_mode & 0x07) == 0x04) - byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8); - } + + if (!skip) { + READW(addr, byte); + } else { + byte = mem_readw_phys(addr); + if ((xga->access_mode & 0x07) == 0x04) + byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8); + else if (xga->access_mode & 0x08) + byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8); } return byte; @@ -1081,17 +1108,14 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui case 4: /*16-bit*/ addr += (y * width << 1); addr += (x << 1); - if (xga->access_mode & 0x08) { - if (!skip) { - WRITEW(addr, pixel); - } + + if (!skip) { + WRITEW(addr, pixel); } else { - if (!skip) { - WRITEW(addr, pixel); - } else { - if ((xga->access_mode & 0x07) == 0x04) - pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); - } + if ((xga->access_mode & 0x07) == 0x04) + pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); + else if (xga->access_mode & 0x08) + pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); } mem_writew_phys(addr, pixel); break; @@ -1237,12 +1261,11 @@ xga_line_draw_write(svga_t *svga) uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; int y = xga->accel.blt_width; int x = 0; + int draw_pixel = 0; int16_t dx; int16_t dy; int16_t cx; int16_t cy; - int err = xga->accel.bres_err_term; - int draw_pixel = 0; cx = xga->accel.src_map_x & 0xfff; cy = xga->accel.src_map_y & 0xfff; @@ -1256,38 +1279,57 @@ xga_line_draw_write(svga_t *svga) dy |= ~0x17ff; if ((xga->accel.command & 0x30) == 0x30) - xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err); - + xga_log("Line Draw Write Fill: DX=%d, DY=%d, BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, negative XDIR=%i, negative YDIR=%i, YMAJOR=%d, ERR=%d, BRESK2=%d, BRESK1=%d, mask=%02x.\n", dx, dy, xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, (xga->accel.octant & 0x04), (xga->accel.octant & 0x02), (xga->accel.octant & 0x01), xga->accel.bres_err_term, xga->accel.bres_k2, xga->accel.bres_k1, xga->accel.command & 0xc0); if (xga->accel.pat_src == 8) { if ((xga->accel.command & 0x30) == 0x30) { while (y >= 0) { draw_pixel = 0; - if (xga->accel.octant & 0x01) { - if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (xga->accel.octant & 0x01) { /*Y Major*/ + if (xga->accel.octant & 0x02) { /*Bottom to Top*/ if (x) draw_pixel = 1; - } else { /*Top-to-Bottom*/ + } else { /*Top to Bottom*/ if (y) draw_pixel = 1; } - } else if (!(xga->accel.octant & 0x04) && (err < (xga->accel.bres_k2 + xga->accel.bres_k1))) /*X+*/ - draw_pixel = 1; - else if ((xga->accel.octant & 0x04) && (err >= 0)) /*X-*/ - draw_pixel = 1; - - if (xga->accel.command & 0xc0) { - if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - if (draw_pixel) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1) : xga->accel.frgd_color; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1); - - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - ROP(1, dest_dat, src_dat); - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } else { /*X Major*/ + if (xga->accel.octant & 0x04) { /*Right to Left*/ + if (xga->accel.bres_err_term >= 0) { + if (xga->accel.octant & 0x02) { /*Bottom to Top*/ + if (x) + draw_pixel = 1; + } else { /*Top to Bottom*/ + if (y) + draw_pixel = 1; } } + } else { /*Left to Right*/ + if (xga->accel.bres_err_term < (xga->accel.bres_k1 + xga->accel.bres_k2)) { + if (xga->accel.octant & 0x02) { /*Bottom to Top*/ + if (x) + draw_pixel = 1; + } else { /*Top to Bottom*/ + if (y) + draw_pixel = 1; + } + } + } + } + + xga_log("Draw Boundary: DX=%d, DY=%d, wrt_pix=%d, ymajor=%d, bottomtotop=%x, len=%d, err=%d, frgdmix=%02x.\n", dx, dy, draw_pixel, xga->accel.octant & 0x01, xga->accel.octant & 0x02, y, xga->accel.bres_err_term, xga->accel.frgd_mix & 0x1f); + if (xga->accel.command & 0xc0) { + if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off)) && draw_pixel) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } } } else { if (draw_pixel) { @@ -1295,7 +1337,9 @@ xga_line_draw_write(svga_t *svga) dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); } } @@ -1310,28 +1354,28 @@ xga_line_draw_write(svga_t *svga) else dy++; - if (err >= 0) { - err += xga->accel.bres_k2; + if (xga->accel.bres_err_term >= 0) { + xga->accel.bres_err_term += xga->accel.bres_k2; if (xga->accel.octant & 0x04) dx--; else dx++; } else - err += xga->accel.bres_k1; + xga->accel.bres_err_term += xga->accel.bres_k1; } else { if (xga->accel.octant & 0x04) dx--; else dx++; - if (err >= 0) { - err += xga->accel.bres_k2; + if (xga->accel.bres_err_term >= 0) { + xga->accel.bres_err_term += xga->accel.bres_k2; if (xga->accel.octant & 0x02) dy--; else dy++; } else - err += xga->accel.bres_k1; + xga->accel.bres_err_term += xga->accel.bres_k1; } x++; y--; @@ -1384,28 +1428,28 @@ xga_line_draw_write(svga_t *svga) else dy++; - if (err >= 0) { - err += xga->accel.bres_k2; + if (xga->accel.bres_err_term >= 0) { + xga->accel.bres_err_term += xga->accel.bres_k2; if (xga->accel.octant & 0x04) dx--; else dx++; } else - err += xga->accel.bres_k1; + xga->accel.bres_err_term += xga->accel.bres_k1; } else { if (xga->accel.octant & 0x04) dx--; else dx++; - if (err >= 0) { - err += xga->accel.bres_k2; + if (xga->accel.bres_err_term >= 0) { + xga->accel.bres_err_term += xga->accel.bres_k2; if (xga->accel.octant & 0x02) dy--; else dy++; } else - err += xga->accel.bres_k1; + xga->accel.bres_err_term += xga->accel.bres_k1; } y--; x++; @@ -1454,20 +1498,21 @@ xga_bitblt(svga_t *svga) if (xga->accel.dst_map_y >= 0x1800) dy |= ~0x17ff; - xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth); + xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d, frgdcol=%04x, bkgdcol=%04x.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth, frgdcol, bkgdcol); xga->accel.pattern = 0; xga->accel.filling = 0; - xga_log("XGA bitblt linear endian reverse=%d, access_mode=%x, octanty=%d, src command = %08x, " + xga_log("XGA bitblt access_mode=%x, octanty=%d, src command=%08x, " "pxsrcmap=%x, pxpatmap=%x, pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, " - "usesrcvramfr=%d, usevrambk=%d.\n", - xga->linear_endian_reverse, xga->access_mode & 0x0f, ydir, xga->accel.command, + "usesrcvramfr=%d, usevrambk=%d, frgdcol=%04x, bkgdcol=%04x, bgmix=%02x, fgmix=%02x.\n", + xga->access_mode & 0x0f, ydir, xga->accel.command, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.px_map_format[xga->accel.pat_src] & 0x0f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.src_map, xga->accel.pat_src, - xga->accel.dst_map, ((xga->accel.command >> 28) & 3), ((xga->accel.command >> 30) & 3)); + xga->accel.dst_map, ((xga->accel.command >> 28) & 3), ((xga->accel.command >> 30) & 3), + frgdcol, bkgdcol, xga->accel.bkgd_mix & 0x1f, xga->accel.frgd_mix & 0x1f); if (xga->accel.pat_src == 8) { if (srcheight == 7) @@ -1593,17 +1638,19 @@ xga_bitblt(svga_t *svga) xga->accel.px_map_width[2], xga->accel.px_map_width[3], bkgdcol); xga_log("Pattern Enabled?=%d, patwidth=%d, patheight=%d, P(%d,%d).\n", xga->accel.pattern, patwidth, patheight, xga->accel.px, xga->accel.py); - if ((((xga->accel.command >> 24) & 0x0f) == 0x0a) && ((xga->accel.bkgd_mix & 0x1f) == 5)) { - while (xga->accel.y >= 0) { - mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, patbase, patwidth + 1); - if (mix) - xga->accel.filling = !xga->accel.filling; + if (((xga->accel.command >> 24) & 0x0f) == 0x0a) { + if ((xga->accel.bkgd_mix & 0x1f) == 0x05) { + while (xga->accel.y >= 0) { + mix = xga_accel_read_area_map_pixel(svga, xga->accel.px, xga->accel.py, patbase, patwidth + 1); + if (mix) + xga->accel.filling ^= 1; - if (xga->accel.command & 0xc0) { - if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol; - if (xga->accel.filling) { - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, 1024); + xga_log("Area Fill Command: dx=%d, dy=%d, mix=%x, filling=%x.\n", dx, dy, mix, xga->accel.filling); + + if (xga->accel.command & 0xc0) { + if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off)) && xga->accel.filling) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; ROP(1, dest_dat, src_dat); @@ -1612,11 +1659,9 @@ xga_bitblt(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); } } - } - } else { - if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol; - if (xga->accel.filling) { + } else { + if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight) && xga->accel.filling) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol; dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -1627,32 +1672,35 @@ xga_bitblt(svga_t *svga) } } } - } - xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth); - xga->accel.px++; + xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth); + xga->accel.px++; - dx++; - xga->accel.x--; - if (xga->accel.x < 0) { - xga->accel.y--; - xga->accel.x = xga->accel.blt_width & 0xfff; + dx++; + xga->accel.x--; + if (xga->accel.x < 0) { + xga->accel.y--; + xga->accel.x = xga->accel.blt_width & 0xfff; - dx = xga->accel.dst_map_x; - if (xga->accel.dst_map_x >= 0x1800) - dx |= ~0x17ff; + dx = xga->accel.dst_map_x; + if (xga->accel.dst_map_x >= 0x1800) + dx |= ~0x17ff; - xga->accel.sx = xga->accel.src_map_x & 0xfff; - xga->accel.px = xga->accel.pat_map_x & 0xfff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; + xga->accel.px = xga->accel.pat_map_x & 0xfff; - xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); - xga->accel.py++; + xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); + xga->accel.py++; - dy++; - xga->accel.filling = 0; + dy++; + xga->accel.filling = 0; - if (xga->accel.y < 0) - return; + if (xga->accel.y < 0) { + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; + return; + } + } } } } else { @@ -2171,7 +2219,6 @@ exec_command: xga->accel.src_map = ((xga->accel.command >> 20) & 0x0f); xga_log("PATMAP=%x, DSTMAP=%x, SRCMAP=%x.\n", xga->accel.px_map_format[xga->accel.pat_src], xga->accel.px_map_format[xga->accel.dst_map], xga->accel.px_map_format[xga->accel.src_map]); -#ifdef ENABLE_XGA_LOG if (xga->accel.pat_src) xga_log("[%04X:%08X]: Accel Command = %02x, full = %08x, patwidth = %d, " "dstwidth = %d, srcwidth = %d, patheight = %d, dstheight = %d, " @@ -2196,7 +2243,7 @@ exec_command: xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.plane_mask); -#endif + switch ((xga->accel.command >> 24) & 0x0f) { case 2: /*Short Stroke Vectors Read */ xga_log("Short Stroke Vectors Read.\n"); @@ -2670,7 +2717,7 @@ xga_write_test(uint32_t addr, uint8_t val, void *priv) xga->vram[addr & xga->vram_mask] = val; xga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x, a5test=%d.\n", val, addr, svga->banked_mask, xga->a5_test); } - } else if (xga->aperture_cntl) + } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) xga->on = 0; } } @@ -2777,9 +2824,8 @@ xga_read_test(uint32_t addr, void *priv) addr += xga->read_bank; return xga->vram[addr & xga->vram_mask]; } - } else if (xga->aperture_cntl) { + } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) xga->on = 0; - } } return ret; } @@ -2874,7 +2920,7 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - xga_log("WrtieLL XGA=%d.\n", xga->on); + xga_log("WriteLL XGA=%d.\n", xga->on); if (!xga->on) { svga_write_linear(addr, val, svga); return; @@ -2889,13 +2935,6 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv) cycles -= svga->monitor->mon_video_timing_write_b; - if (!(xga->access_mode & 0x08)) { - if ((xga->access_mode & 0x07) == 0x04) { - if ((xga->accel.px_map_format[xga->accel.dst_map] & 0x07) == 0x04) - addr ^= 1; - } - } - xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; xga->vram[addr & xga->vram_mask] = val; } @@ -2951,14 +2990,9 @@ xga_read_linear(uint32_t addr, void *priv) cycles -= svga->monitor->mon_video_timing_read_b; - if (!(xga->access_mode & 0x08)) { - if ((xga->access_mode & 0x07) == 0x04) { - if ((xga->accel.px_map_format[xga->accel.dst_map] & 0x07) == 0x04) - addr ^= 1; - } - } + ret = xga->vram[addr & xga->vram_mask]; - return xga->vram[addr & xga->vram_mask]; + return ret; } static uint16_t @@ -3234,7 +3268,7 @@ xga_mca_reset(void *priv) svga_t *svga = (svga_t *) priv; xga_log("MCA Reset.\n"); - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel); xga_mca_write(0x102, 0, svga); } @@ -3250,7 +3284,7 @@ xga_reset(void *priv) xga->on = 0; xga->a5_test = 0; - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel); } static uint8_t From f1a856c8863ea06db030605bc0342f340cbe02f7 Mon Sep 17 00:00:00 2001 From: Ectoplasm Date: Mon, 20 Jan 2025 05:53:40 +0200 Subject: [PATCH 0143/1190] GlaBIOS for Vendex HeadStart Turbo 888-XT --- src/machine/m_xt.c | 53 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index ef3a84e24..9f232ac95 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -919,18 +919,63 @@ machine_xt_pc500_init(const machine_t *model) return ret; } +static const device_config_t vendex_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "vendex", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "Bios 2.03C", .internal_name = "vendex", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 16384, .files = { "roms/machines/vendex/Vendex Turbo 888 XT - ROM BIOS - VER 2.03C.bin", "" } }, + // GlaBIOS for Juko ST + { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 16384, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8TV.ROM", "" } }, + { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 16384, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VTV.ROM", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t vendex_device = { + .name = "Vendex 888T Devices", + .internal_name = "vendex_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = vendex_config +}; + int machine_xt_vendex_init(const machine_t *model) { - int ret; + int ret = 0; + const char *fn; - ret = bios_load_linear("roms/machines/vendex/Vendex Turbo 888 XT - ROM BIOS - VER 2.03C.bin", - 0x000fc000, 16384, 0); + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fc000, 16384, 0); + device_context_restore(); if (bios_only || !ret) return ret; - /* On-board FDC cannot be disabled */ machine_xt_clone_init(model, 1); device_add(&vendex_xt_rtc_onboard_device); From ce390fb9cde6b5f3fadec433fad176d2c0b39368 Mon Sep 17 00:00:00 2001 From: Ectoplasm Date: Mon, 20 Jan 2025 05:55:03 +0200 Subject: [PATCH 0144/1190] GlaBIOS for Vendex HeadStart Turbo 888-XT --- src/machine/machine_table.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cafbe514d..f2fb53a6f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -65,6 +65,7 @@ extern const device_t ibmat_device; extern const device_t ibmxt286_device; extern const device_t pb450_device; extern const device_t jukopc_device; +extern const device_t vendex_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -1696,7 +1697,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &vendex_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From 23ba9889d26c62270bf254e8d75e97eb445ea3ac Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:16:36 +0900 Subject: [PATCH 0145/1190] Fixed an illegal memory access error Fixed an illegal memory access error when reading font ROM data beyond 1 MB border --- src/video/vid_ps55da2.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 6a90a3dc3..d75d0aa03 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -42,6 +42,7 @@ #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_INVALIDACCESS8 0xff #define DA2_MASK_MMIO 0x1ffff #define DA2_MASK_GRAM 0x1ffff #define DA2_MASK_CRAM 0xfff @@ -1244,7 +1245,7 @@ uint16_t da2_in(uint16_t addr, void *p) break; case LS_DATA: //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) - if (da2->ioctladdr > 0xf) return 0xff; + if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrc[LV_COMPATIBILITY] & 0x08) @@ -1275,14 +1276,14 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->fctladdr; break; case LF_DATA: - if (da2->fctladdr > 0x1f) return 0xff; + if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; temp = da2->fctl[da2->fctladdr]; break; case LC_INDEX: temp = da2->crtcaddr; break; case LC_DATA: - if (da2->crtcaddr > 0x1f) return 0xff; + if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: @@ -2270,12 +2271,12 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM + if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); - if (addr > DA2_FONTROM_SIZE) return 0xff; return da2->mmio.font[addr]; break; default: - return 0xff;//invalid memory access + return DA2_INVALIDACCESS8;//invalid memory access break; } } @@ -2677,7 +2678,7 @@ static void da2_code_writew(uint32_t addr, uint16_t val, void* p) static uint8_t da2_code_read(uint32_t addr, void* p) { da2_t* da2 = (da2_t*)p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return 0xff; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } From 0be045b3cff89cd27b019700b782a1ad77643ccd Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 20 Jan 2025 12:51:27 -0300 Subject: [PATCH 0146/1190] AD1848: Fix additional data format unlocking which has been wrong this whole time --- src/sound/snd_ad1848.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index a0166c4e5..ddf8e61ec 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -273,20 +273,21 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) return; case 12: - if (ad1848->type != AD1848_TYPE_DEFAULT) - ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80; + if (ad1848->type >= AD1848_TYPE_CS4248) { + ad1848->regs[12] = 0x80 | (val & 0x70) | (ad1848->regs[12] & 0x0f); + if ((ad1848->type >= AD1848_TYPE_CS4231) && (ad1848->type < AD1848_TYPE_CS4235)) { + if (val & 0x40) + ad1848->fmt_mask |= 0x80; + else + ad1848->fmt_mask &= ~0x80; + } + } return; case 14: ad1848->count = ad1848->regs[15] | (val << 8); break; - case 17: - /* Enable additional data formats on modes 2 and 3 where supported. */ - if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236B)) - ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70; - break; - case 18: case 19: if (ad1848->type >= AD1848_TYPE_CS4236B) { From 3dea388ae4bf7cb8792f9bd6b2f690ebc446de33 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 20 Jan 2025 13:37:55 -0300 Subject: [PATCH 0147/1190] CS423x: Fix broken codec on CS4236B --- src/sound/snd_cs423x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 0d9af74f2..0a383e13f 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -12,7 +12,7 @@ * * Authors: RichardG, * - * Copyright 2021-2022 RichardG. + * Copyright 2021-2025 RichardG. */ #include #include @@ -386,7 +386,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) dev->ram_dl = CRYSTAL_RAM_CMD; /* Update PnP state and resource data. */ - dev->pnp_size = 384; /* we don't know the length */ + dev->pnp_size = (dev->type >= CRYSTAL_CS4236) ? 384 : 256; /* we don't know the length */ cs423x_pnp_enable(dev, 1, 0); } break; @@ -853,12 +853,13 @@ cs423x_init(const device_t *info) dev->type = info->local & 0xff; cs423x_log("CS423x: init(%02X)\n", dev->type); switch (dev->type) { - case CRYSTAL_CS4235: case CRYSTAL_CS4236B: case CRYSTAL_CS4237B: case CRYSTAL_CS4238B: + case CRYSTAL_CS4235: + case CRYSTAL_CS4239: /* Same WSS codec and EEPROM structure. */ - dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236; + dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236B; dev->pnp_offset = 0x4013; /* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init. */ From b48594a4cc10e4a96d4444d9010025b0230bcd7d Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 20 Jan 2025 14:20:14 -0300 Subject: [PATCH 0148/1190] AD1848: Add one more CS4235 register access backdoor --- src/sound/snd_ad1848.c | 30 ++++++++++++++++++++++++------ src/sound/snd_cs423x.c | 7 +++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index ddf8e61ec..d870b4588 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -200,10 +200,22 @@ ad1848_read(uint16_t addr, void *priv) case 23: if ((ad1848->type >= AD1848_TYPE_CS4236B) && (ad1848->regs[23] & 0x08)) { - if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */ - ret = ad1848->regs[18 + ad1848->xindex]; - else - ret = ad1848->xregs[ad1848->xindex]; + ret = ad1848->xregs[ad1848->xindex]; + switch (ad1848->xindex) { + case 0 ... 1: + /* Remapped line volume. */ + ret = ad1848->regs[18 + ad1848->xindex]; + break; + + case 26: + /* Backdoor to the Joystick Control register on CS4235+. */ + if (ad1848->type >= AD1848_TYPE_CS4235) + ret = ad1848->cram_read(0, ad1848->cram_priv); + break; + + default: + break; + } } break; @@ -353,8 +365,8 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) } switch (ad1848->xindex) { - case 0: - case 1: /* remapped line volume */ + case 0 ... 1: + /* Remapped line volume. */ ad1848->regs[18 + ad1848->xindex] = val; return; @@ -380,6 +392,12 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 25: return; + case 26: + /* Backdoor to the Joystick Control register on CS4235+. */ + if (ad1848->type >= AD1848_TYPE_CS4235) + ad1848->cram_write(0, val, ad1848->cram_priv); + break; + default: break; } diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 0a383e13f..288314a13 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -144,6 +144,7 @@ typedef struct cs423x_t { } cs423x_t; static void cs423x_slam_enable(cs423x_t *dev, uint8_t enable); +static void cs423x_ctxswitch_write(uint16_t addr, UNUSED(uint8_t val), void *priv); static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig); static void cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); static void cs423x_reset(void *priv); @@ -237,6 +238,12 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) case 0: /* Joystick and Power Control */ if (dev->type <= CRYSTAL_CS4232) val &= 0xeb; + if ((dev->type >= CRYSTAL_CS4235) && (addr == 0) && (val & 0x08)) { + /* CS4235+ through X26 backdoor only (hence the addr check): WSS off (one-way trip?) */ + io_removehandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848); + io_removehandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); + dev->wss_base = 0; + } break; case 1: /* EEPROM Interface */ From 40080101313bf30a235610792ac522761b3a94fd Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 20 Jan 2025 19:55:18 +0100 Subject: [PATCH 0149/1190] Big SCSI bus update of the day, NCR 5380 too (January 20th, 2025) 1. Separate the SCSI bus functions from NCR 5380 into true general purpose SCSI bus functions, allowing use of future legacy scsi controllers. 2. Corrected NCR 5380 chip period for the SCSI controllers based on that chip so that CD-ROM speed is correct enough per speed tests and no more breakage (I hope, report if they are still there, please!) on desyncs. 3. A NCR 5380 software reset involves asserting an IRQ. --- src/include/86box/scsi_device.h | 46 ++++ src/include/86box/scsi_ncr5380.h | 48 +--- src/scsi/scsi_device.c | 334 +++++++++++++++++++++++++++- src/scsi/scsi_ncr5380.c | 371 ++++--------------------------- src/scsi/scsi_ncr53c400.c | 128 +++++------ src/scsi/scsi_t128.c | 89 +++++--- src/sound/snd_pas16.c | 12 +- 7 files changed, 546 insertions(+), 482 deletions(-) diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 6fdac5ebd..538a96fac 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -333,6 +333,20 @@ #define BUS_IDLE (1 << 31) +#define STATE_IDLE 0 +#define STATE_COMMAND 1 +#define STATE_DATAIN 2 +#define STATE_DATAOUT 3 +#define STATE_STATUS 4 +#define STATE_MESSAGEIN 5 +#define STATE_SELECT 6 +#define STATE_MESSAGEOUT 7 +#define STATE_MESSAGE_ID 8 + +#define PIO_TX_BUS 0 +#define DMA_IN_TX_BUS 1 +#define DMA_OUT_TX_BUS 2 + #define PHASE_IDLE 0x00 #define PHASE_COMMAND 0x01 #define PHASE_DATA_IN 0x02 @@ -420,6 +434,36 @@ typedef struct scsi_device_t { void (*command_stop)(scsi_common_t *sc); } scsi_device_t; +typedef struct scsi_bus_t { + int tx_mode; + int clear_req; + int wait_data; + int wait_complete; + int bus_out; + int bus_in; + int command_pos; + int command_issued; + int data_pos; + int msgout_pos; + int is_msgout; + int state; + int dma_on_pio_enabled; + uint8_t data; + uint8_t msglun; + uint8_t data_wait; + uint8_t command[16]; + uint8_t msgout[4]; + uint8_t target_id; + uint8_t bus_device; + uint32_t bus_phase; + double period; + double speed; + double divider; + double multi; + void *priv; + void (*timer)(void *priv, double period); +} scsi_bus_t; + /* These are based on the INQUIRY values. */ #define SCSI_NONE 0x0060 #define SCSI_FIXED_DISK 0x0000 @@ -454,6 +498,8 @@ extern void scsi_device_init(void); extern void scsi_reset(void); extern uint8_t scsi_get_bus(void); +extern int scsi_bus_read(scsi_bus_t *scsi_bus); +extern void scsi_bus_update(scsi_bus_t *scsi_bus, int bus); extern void scsi_bus_set_speed(uint8_t bus, double speed); extern double scsi_bus_get_speed(uint8_t bus); diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 09307fed6..0b8a4efd8 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -44,6 +44,9 @@ #define ICR_ACK 0x10 #define ICR_ARB_LOST 0x20 #define ICR_ARB_IN_PROGRESS 0x40 +#define ICR_RST 0x80 +#define ICR_PHASE 0x9e +#define ICR_WRITE 0x9f #define MODE_ARBITRATE 0x01 #define MODE_DMA 0x02 @@ -63,70 +66,33 @@ #define TCR_REQ 0x08 #define TCR_LAST_BYTE_SENT 0x80 - -#define STATE_IDLE 0 -#define STATE_COMMAND 1 -#define STATE_DATAIN 2 -#define STATE_DATAOUT 3 -#define STATE_STATUS 4 -#define STATE_MESSAGEIN 5 -#define STATE_SELECT 6 -#define STATE_MESSAGEOUT 7 -#define STATE_MESSAGE_ID 8 - -#define DMA_IDLE 0 -#define DMA_SEND 1 -#define DMA_INITIATOR_RECEIVE 2 - typedef struct ncr_t { uint8_t icr; uint8_t mode; uint8_t tcr; - uint8_t data_wait; uint8_t isr; uint8_t output_data; - uint8_t target_id; uint8_t tx_data; - uint8_t msglun; uint8_t irq_state; - uint8_t command[20]; - uint8_t msgout[4]; uint8_t bus; - int msgout_pos; - int is_msgout; - - int dma_mode; - int cur_bus; - int bus_in; - int new_phase; - int state; - int clear_req; - int wait_data; - int wait_data_back; - int wait_complete; - int command_pos; - int data_pos; - int irq; double period; void *priv; - void (*dma_mode_ext)(void *priv, void *ext_priv); + void (*dma_mode_ext)(void *priv, void *ext_priv, uint8_t val); int (*dma_send_ext)(void *priv, void *ext_priv); int (*dma_initiator_receive_ext)(void *priv, void *ext_priv); void (*timer)(void *ext_priv, double period); + + scsi_bus_t scsibus; } ncr_t; -extern int ncr5380_cmd_len[8]; - extern void ncr5380_irq(ncr_t *ncr, int set_irq); -extern void ncr5380_set_irq(ncr_t *ncr, int irq); +extern void ncr5380_set_irq(ncr_t *ncr, int irq); extern uint32_t ncr5380_get_bus_host(ncr_t *ncr); -extern void ncr5380_bus_read(ncr_t *ncr); -extern void ncr5380_bus_update(ncr_t *ncr, int bus); extern void ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr); extern uint8_t ncr5380_read(uint16_t port, ncr_t *ncr); diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index 4442b2680..33d3fa89a 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -16,10 +16,14 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017-2018 Fred N. van Kempen. */ +#include #include #include #include +#include +#include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/hdd.h> @@ -29,9 +33,29 @@ #include <86box/plat_unused.h> scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; - +int scsi_command_length[8] = { 6, 10, 10, 6, 16, 12, 10, 6 }; uint8_t scsi_null_device_sense[18] = { 0x70, 0, SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 0, 0, 0, 0, 0, ASC_INV_LUN, 0, 0, 0, 0, 0 }; +#define SET_BUS_STATE(scsi_bus, state) scsi_bus->bus_out = (scsi_bus->bus_out & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) + +#ifdef ENABLE_SCSI_DEVICE_LOG +int scsi_device_do_log = ENABLE_SCSI_DEVICE_LOG; + +static void +scsi_device_log(const char *fmt, ...) +{ + va_list ap; + + if (scsi_device_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define scsi_device_log(fmt, ...) +#endif + static uint8_t scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb) { @@ -189,3 +213,311 @@ scsi_device_init(void) } } } + +int +scsi_device_get_id(uint8_t data) +{ + for (uint8_t c = 0; c < SCSI_ID_MAX; c++) { + if (data & (1 << c)) + return c; + } + + return -1; +} + + +static int +scsi_device_get_msg(uint8_t *msgp, int len) +{ + uint8_t msg = msgp[0]; + if ((msg == 0) || ((msg >= 0x02) && (msg <= 0x1f)) || (msg >= 0x80)) + return 1; + + if ((msg >= 0x20) && (msg <= 0x2f)) + return 2; + + if (len < 2) + return 3; + + return msgp[1]; +} + +int +scsi_bus_read(scsi_bus_t *scsi_bus) +{ + scsi_device_t *dev; + int phase; + + /*Wait processes to handle bus requests*/ + if (scsi_bus->clear_req) { + scsi_bus->clear_req--; + if (!scsi_bus->clear_req) { + scsi_device_log("Prelude to command data\n"); + SET_BUS_STATE(scsi_bus, scsi_bus->bus_phase); + scsi_bus->bus_out |= BUS_REQ; + } + } + + if (scsi_bus->wait_data) { + scsi_bus->wait_data--; + if (!scsi_bus->wait_data) { + dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id]; + SET_BUS_STATE(scsi_bus, scsi_bus->bus_phase); + phase = scsi_bus->bus_out & SCSI_PHASE_MESSAGE_IN; + + switch (phase) { + case SCSI_PHASE_DATA_IN: + scsi_device_log("DataIn.\n"); + scsi_bus->state = STATE_DATAIN; + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + scsi_bus->data = dev->sc->temp_buffer[scsi_bus->data_pos++]; + + scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(scsi_bus->data) | BUS_DBP; + break; + case SCSI_PHASE_DATA_OUT: + if (scsi_bus->bus_phase & BUS_IDLE) { + scsi_device_log("Bus Idle.\n"); + scsi_bus->state = STATE_IDLE; + scsi_bus->bus_out &= ~BUS_BSY; + scsi_bus->timer(scsi_bus->priv, 0.0); + } else { + scsi_device_log("DataOut.\n"); + scsi_bus->state = STATE_DATAOUT; + } + break; + case SCSI_PHASE_STATUS: + scsi_device_log("Status.\n"); + scsi_bus->bus_out |= BUS_REQ; + scsi_bus->state = STATE_STATUS; + scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; + break; + case SCSI_PHASE_MESSAGE_IN: + scsi_device_log("Message In.\n"); + scsi_bus->state = STATE_MESSAGEIN; + scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; + break; + case SCSI_PHASE_MESSAGE_OUT: + scsi_device_log("Message Out.\n"); + scsi_bus->bus_out |= BUS_REQ; + scsi_bus->state = STATE_MESSAGEOUT; + scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(scsi_bus->target_id >> 5) | BUS_DBP; + break; + default: + break; + } + } + } + + if (scsi_bus->wait_complete) { + scsi_bus->wait_complete--; + if (!scsi_bus->wait_complete) + scsi_bus->bus_out |= BUS_REQ; + } + + return scsi_bus->bus_out; +} + +void +scsi_bus_update(scsi_bus_t *scsi_bus, int bus) +{ + scsi_device_t *dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id]; + double p; + uint8_t sel_data; + int msglen; + + /*Start the SCSI command layer, which will also make the timings*/ + if (bus & BUS_ARB) + scsi_bus->state = STATE_IDLE; + + scsi_device_log("State = %i\n", scsi_bus->state); + + switch (scsi_bus->state) { + case STATE_IDLE: + scsi_bus->clear_req = scsi_bus->wait_data = scsi_bus->wait_complete = 0; + if ((bus & BUS_SEL) && !(bus & BUS_BSY)) { + sel_data = BUS_GETDATA(bus); + + scsi_bus->target_id = scsi_device_get_id(sel_data); + + /*Once the device has been found and selected, mark it as busy*/ + if ((scsi_bus->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id])) { + scsi_bus->bus_out |= BUS_BSY; + scsi_bus->state = STATE_SELECT; + scsi_device_log("Select - target ID = %i, moving to state = %d.\n", scsi_bus->target_id, scsi_bus->state); + } else { + scsi_device_log("Device not found at ID %i, Current Bus BSY=%02x\n", scsi_bus->target_id, scsi_bus->bus_out); + scsi_bus->bus_out = 0; + } + } + break; + case STATE_SELECT: + if (!(bus & BUS_SEL)) { + if (!(bus & BUS_ATN)) { + if ((scsi_bus->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id])) { + scsi_device_log("Device found at ID %i, Current Bus BSY=%02x\n", scsi_bus->target_id, scsi_bus->bus_out); + scsi_bus->state = STATE_COMMAND; + scsi_bus->bus_out = BUS_BSY | BUS_REQ; + scsi_bus->command_pos = 0; + SET_BUS_STATE(scsi_bus, SCSI_PHASE_COMMAND); + } else { + scsi_device_log("Device not found at ID %i again.\n", scsi_bus->target_id); + scsi_bus->state = STATE_IDLE; + scsi_bus->bus_out = 0; + } + } else { + scsi_device_log("Set to SCSI Message Out\n"); + scsi_bus->bus_phase = SCSI_PHASE_MESSAGE_OUT; + scsi_bus->wait_data = 4; + scsi_bus->msgout_pos = 0; + scsi_bus->is_msgout = 1; + } + } + break; + case STATE_COMMAND: + if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) { + /*Write command byte to the output data register*/ + scsi_bus->command[scsi_bus->command_pos++] = BUS_GETDATA(bus); + scsi_bus->clear_req = 3; + scsi_bus->bus_phase = scsi_bus->bus_out & SCSI_PHASE_MESSAGE_IN; + scsi_bus->bus_out &= ~BUS_REQ; + + scsi_device_log("Command pos=%i, output data=%02x\n", scsi_bus->command_pos, BUS_GETDATA(bus)); + + if (scsi_bus->command_pos == scsi_command_length[(scsi_bus->command[0] >> 5) & 7]) { + if (scsi_bus->is_msgout) { + scsi_bus->is_msgout = 0; +#if 0 + scsi_bus->command[1] = (scsi_bus->command[1] & 0x1f) | (scsi_bus->msglun << 5); +#endif + } + + /*Reset data position to default*/ + scsi_bus->data_pos = 0; + + dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id]; + + scsi_device_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", scsi_bus->command[0], scsi_bus->target_id, dev->status); + dev->buffer_length = -1; + scsi_device_command_phase0(dev, scsi_bus->command); + scsi_device_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", scsi_bus->target_id, scsi_bus->command[0], dev->buffer_length, dev->phase); + + scsi_bus->period = 1.0; + scsi_bus->wait_data = 4; + scsi_bus->data_wait = 0; + scsi_bus->command_issued = 1; + + if (dev->status == SCSI_STATUS_OK) { + /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ + if (dev->buffer_length && ((dev->phase == SCSI_PHASE_DATA_IN) || (dev->phase == SCSI_PHASE_DATA_OUT))) { + p = scsi_device_get_callback(dev); + scsi_bus->period = (p > 0.0) ? ((p / scsi_bus->divider) * scsi_bus->multi) : (((double) dev->buffer_length) * scsi_bus->speed); + scsi_device_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", scsi_bus->target_id, scsi_bus->command[0], scsi_device_get_callback(dev), scsi_bus->period, dev->buffer_length, scsi_bus->tx_mode); + } + } + scsi_bus->bus_phase = dev->phase; + } + } + break; + case STATE_DATAIN: + dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id]; + if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) { + if (scsi_bus->data_pos >= dev->buffer_length) { + scsi_bus->bus_out &= ~BUS_REQ; + scsi_device_command_phase1(dev); + scsi_bus->bus_phase = SCSI_PHASE_STATUS; + scsi_bus->wait_data = 4; + scsi_bus->wait_complete = 8; + } else { + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + scsi_bus->data = dev->sc->temp_buffer[scsi_bus->data_pos++]; + + scsi_device_log("TXMode DataIn=%x, cmd=%02x.\n", scsi_bus->tx_mode, scsi_bus->command[0]); + scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(scsi_bus->data) | BUS_DBP | BUS_REQ; + if (scsi_bus->tx_mode == PIO_TX_BUS) { /*If a data in command that is not read 6/10 has been issued*/ + scsi_device_log("DMA mode idle IN=%d.\n", scsi_bus->data_pos); + scsi_bus->data_wait |= 1; + scsi_bus->timer(scsi_bus->priv, scsi_bus->period); + } else { + scsi_device_log("DMA mode IN=%d.\n", scsi_bus->data_pos); + scsi_bus->clear_req = 3; + } + scsi_bus->bus_out &= ~BUS_REQ; + scsi_bus->bus_phase = SCSI_PHASE_DATA_IN; + } + } + break; + case STATE_DATAOUT: + dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id]; + if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) { + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + dev->sc->temp_buffer[scsi_bus->data_pos++] = BUS_GETDATA(bus); + + if (scsi_bus->data_pos >= dev->buffer_length) { + scsi_bus->bus_out &= ~BUS_REQ; + scsi_device_command_phase1(dev); + scsi_bus->bus_phase = SCSI_PHASE_STATUS; + scsi_bus->wait_data = 4; + scsi_bus->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + if (scsi_bus->tx_mode == PIO_TX_BUS) { /*If a data in command that is not write 6/10 has been issued*/ + scsi_device_log("DMA mode idle OUT=%d.\n", scsi_bus->data_pos); + scsi_bus->data_wait |= 1; + scsi_bus->timer(scsi_bus->priv, scsi_bus->period); + scsi_bus->bus_out &= ~BUS_REQ; + } else { + scsi_device_log("DMA mode OUT=%d.\n", scsi_bus->data_pos); + scsi_bus->bus_out |= BUS_REQ; + } + } + } + break; + case STATE_STATUS: + if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) { + /*All transfers done, wait until next transfer*/ + scsi_device_identify(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id], SCSI_LUN_USE_CDB); + scsi_bus->bus_out &= ~BUS_REQ; + scsi_bus->bus_phase = SCSI_PHASE_MESSAGE_IN; + scsi_bus->wait_data = 4; + scsi_bus->wait_complete = 8; + scsi_bus->command_issued = 0; + } + break; + case STATE_MESSAGEIN: + if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) { + scsi_bus->bus_out &= ~BUS_REQ; + scsi_bus->bus_phase = BUS_IDLE; + scsi_bus->wait_data = 4; + } + break; + case STATE_MESSAGEOUT: + if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) { + scsi_bus->msgout[scsi_bus->msgout_pos++] = BUS_GETDATA(bus); + msglen = scsi_device_get_msg(scsi_bus->msgout, scsi_bus->msgout_pos); + if (scsi_bus->msgout_pos >= msglen) { + if ((scsi_bus->msgout[0] & (0x80 | 0x20)) == 0x80) + scsi_bus->msglun = scsi_bus->msgout[0] & 7; + + scsi_bus->bus_out &= ~BUS_REQ; + scsi_bus->state = STATE_MESSAGE_ID; + } + } + break; + case STATE_MESSAGE_ID: + if ((scsi_bus->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id])) { + scsi_device_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", scsi_bus->target_id, scsi_bus->bus_out); + scsi_device_identify(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id], scsi_bus->msglun); + scsi_bus->state = STATE_COMMAND; + scsi_bus->bus_out = BUS_BSY | BUS_REQ; + scsi_bus->command_pos = 0; + SET_BUS_STATE(scsi_bus, SCSI_PHASE_COMMAND); + } + break; + + default: + break; + } + + scsi_bus->bus_in = bus; +} + diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index e5dff88f8..60f60473e 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -42,8 +42,6 @@ #include <86box/scsi_device.h> #include <86box/scsi_ncr5380.h> -int ncr5380_cmd_len[8] = { 6, 10, 10, 6, 16, 12, 10, 6 }; - #ifdef ENABLE_NCR5380_LOG int ncr5380_do_log = ENABLE_NCR5380_LOG; @@ -62,8 +60,6 @@ ncr5380_log(const char *fmt, ...) # define ncr5380_log(fmt, ...) #endif -#define SET_BUS_STATE(ncr, state) ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) - void ncr5380_irq(ncr_t *ncr, int set_irq) { @@ -86,45 +82,15 @@ ncr5380_set_irq(ncr_t *ncr, int irq) ncr->irq = irq; } -static int -ncr5380_get_dev_id(uint8_t data) -{ - for (uint8_t c = 0; c < SCSI_ID_MAX; c++) { - if (data & (1 << c)) - return c; - } - - return -1; -} - -static int -ncr5380_getmsglen(uint8_t *msgp, int len) -{ - uint8_t msg = msgp[0]; - if (msg == 0 || (msg >= 0x02 && msg <= 0x1f) || msg >= 0x80) - return 1; - if (msg >= 0x20 && msg <= 0x2f) - return 2; - if (len < 2) - return 3; - return msgp[1]; -} - static void ncr5380_reset(ncr_t *ncr) { - ncr->command_pos = 0; - ncr->data_pos = 0; - ncr->state = STATE_IDLE; - ncr->clear_req = 0; - ncr->cur_bus = 0; - ncr->tx_data = 0; + scsi_bus_t *scsi_bus = &ncr->scsibus; + ncr->output_data = 0; - ncr->data_wait = 0; ncr->mode = 0; ncr->tcr = 0; ncr->icr = 0; - ncr->dma_mode = DMA_IDLE; ncr5380_log("NCR Reset\n"); ncr->timer(ncr->priv, 0.0); @@ -132,6 +98,17 @@ ncr5380_reset(ncr_t *ncr) 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; + scsi_bus->wait_data = 0; + scsi_bus->bus_in = 0; + scsi_bus->bus_out = 0; + scsi_bus->command_pos = 0; + scsi_bus->data_wait = 0; + scsi_bus->data = 0; + scsi_bus->command_issued = 0; + ncr5380_irq(ncr, 0); } @@ -173,280 +150,10 @@ ncr5380_get_bus_host(ncr_t *ncr) return (bus_host | BUS_SETDATA(ncr->output_data)); } -void -ncr5380_bus_read(ncr_t *ncr) -{ - const scsi_device_t *dev; - int phase; - - /*Wait processes to handle bus requests*/ - if (ncr->clear_req) { - ncr->clear_req--; - if (!ncr->clear_req) { - ncr5380_log("Prelude to command data\n"); - SET_BUS_STATE(ncr, ncr->new_phase); - ncr->cur_bus |= BUS_REQ; - } - } - - if (ncr->wait_data) { - ncr->wait_data--; - if (!ncr->wait_data) { - dev = &scsi_devices[ncr->bus][ncr->target_id]; - SET_BUS_STATE(ncr, ncr->new_phase); - phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); - - if (phase == SCSI_PHASE_DATA_IN) { - if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext || (ncr->wait_data_back == 1)) { - ncr5380_log("Phase Data In.\n"); - if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - - ncr->state = STATE_DATAIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; - } - } else if (phase == SCSI_PHASE_DATA_OUT) { - if (ncr->new_phase & BUS_IDLE) { - ncr->state = STATE_IDLE; - ncr->cur_bus &= ~BUS_BSY; - } else { - if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext || (ncr->wait_data_back == 1)) - ncr->state = STATE_DATAOUT; - } - } else if (phase == SCSI_PHASE_STATUS) { - ncr5380_log("Phase Status.\n"); - ncr->wait_data_back = 0; - ncr->cur_bus |= BUS_REQ; - ncr->state = STATE_STATUS; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; - } else if (phase == SCSI_PHASE_MESSAGE_IN) { - ncr5380_log("Phase Message In.\n"); - ncr->state = STATE_MESSAGEIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; - } else if (phase == SCSI_PHASE_MESSAGE_OUT) { - ncr->cur_bus |= BUS_REQ; - ncr->state = STATE_MESSAGEOUT; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->target_id >> 5) | BUS_DBP; - } - } - } - - if (ncr->wait_complete) { - ncr->wait_complete--; - if (!ncr->wait_complete) - ncr->cur_bus |= BUS_REQ; - } -} - -void -ncr5380_bus_update(ncr_t *ncr, int bus) -{ - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; - double p; - uint8_t sel_data; - int msglen; - - /*Start the SCSI command layer, which will also make the timings*/ - if (bus & BUS_ARB) - ncr->state = STATE_IDLE; - - ncr5380_log("State = %i\n", ncr->state); - - switch (ncr->state) { - case STATE_IDLE: - ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; - if ((bus & BUS_SEL) && !(bus & BUS_BSY)) { - ncr5380_log("Selection phase\n"); - sel_data = BUS_GETDATA(bus); - - ncr->target_id = ncr5380_get_dev_id(sel_data); - - ncr5380_log("Select - target ID = %i\n", ncr->target_id); - - /*Once the device has been found and selected, mark it as busy*/ - if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) { - ncr->cur_bus |= BUS_BSY; - ncr->state = STATE_SELECT; - } else { - ncr5380_log("Device not found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - ncr->cur_bus = 0; - } - } - break; - case STATE_SELECT: - if (!(bus & BUS_SEL)) { - if (!(bus & BUS_ATN)) { - if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) { - ncr5380_log("Device found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - ncr5380_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - } else { - ncr->state = STATE_IDLE; - ncr->cur_bus = 0; - } - } else { - ncr5380_log("Set to SCSI Message Out\n"); - ncr->new_phase = SCSI_PHASE_MESSAGE_OUT; - ncr->wait_data = 4; - ncr->msgout_pos = 0; - ncr->is_msgout = 1; - } - } - break; - case STATE_COMMAND: - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - /*Write command byte to the output data register*/ - ncr->command[ncr->command_pos++] = BUS_GETDATA(bus); - ncr->clear_req = 3; - ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; - ncr->cur_bus &= ~BUS_REQ; - - ncr5380_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus)); - - if (ncr->command_pos == ncr5380_cmd_len[(ncr->command[0] >> 5) & 7]) { - if (ncr->is_msgout) { - ncr->is_msgout = 0; -#if 0 - ncr->command[1] = (ncr->command[1] & 0x1f) | (ncr->msglun << 5); -#endif - } - - /*Reset data position to default*/ - ncr->data_pos = 0; - - dev = &scsi_devices[ncr->bus][ncr->target_id]; - - ncr5380_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); - dev->buffer_length = -1; - scsi_device_command_phase0(dev, ncr->command); - ncr5380_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase); - - ncr->period = 1.0; - ncr->wait_data = 4; - ncr->data_wait = 0; - - if (dev->status == SCSI_STATUS_OK) { - /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ - if (dev->buffer_length && ((dev->phase == SCSI_PHASE_DATA_IN) || (dev->phase == SCSI_PHASE_DATA_OUT))) { - p = scsi_device_get_callback(dev); - ncr->period = (p > 0.0) ? p : (((double) dev->buffer_length) * 0.2); - ncr5380_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", ncr->target_id, ncr->command[0], scsi_device_get_callback(dev), ncr->period, dev->buffer_length, ncr->dma_mode); - } - } - ncr->new_phase = dev->phase; - } - } - break; - case STATE_DATAIN: - dev = &scsi_devices[ncr->bus][ncr->target_id]; - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - if (ncr->data_pos >= dev->buffer_length) { - ncr->cur_bus &= ~BUS_REQ; - ncr5380_log("CMD Phase1 DataIn.\n"); - scsi_device_command_phase1(dev); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ - ncr->data_wait |= 1; - ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); - ncr->timer(ncr->priv, ncr->period); - } else { - ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); - ncr->clear_req = 3; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - } - break; - case STATE_DATAOUT: - dev = &scsi_devices[ncr->bus][ncr->target_id]; - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); - - if (ncr->data_pos >= dev->buffer_length) { - ncr->cur_bus &= ~BUS_REQ; - scsi_device_command_phase1(dev); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - if (ncr->dma_mode == DMA_IDLE) { /*If a data out command that is not write 6/10 has been issued*/ - ncr->data_wait |= 1; - ncr5380_log("DMA mode idle out\n"); - ncr->timer(ncr->priv, ncr->period); - } else - ncr->clear_req = 3; - - ncr->cur_bus &= ~BUS_REQ; - ncr5380_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - } - break; - case STATE_STATUS: - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - /*All transfers done, wait until next transfer*/ - scsi_device_identify(&scsi_devices[ncr->bus][ncr->target_id], SCSI_LUN_USE_CDB); - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_MESSAGE_IN; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - break; - case STATE_MESSAGEIN: - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = BUS_IDLE; - ncr->wait_data = 4; - } - break; - case STATE_MESSAGEOUT: - ncr5380_log("Ack on MSGOUT = %02x\n", (bus & BUS_ACK)); - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - ncr->msgout[ncr->msgout_pos++] = BUS_GETDATA(bus); - msglen = ncr5380_getmsglen(ncr->msgout, ncr->msgout_pos); - if (ncr->msgout_pos >= msglen) { - if ((ncr->msgout[0] & (0x80 | 0x20)) == 0x80) - ncr->msglun = ncr->msgout[0] & 7; - ncr->cur_bus &= ~BUS_REQ; - ncr->state = STATE_MESSAGE_ID; - } - } - break; - case STATE_MESSAGE_ID: - if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) { - ncr5380_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - scsi_device_identify(&scsi_devices[ncr->bus][ncr->target_id], ncr->msglun); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - ncr5380_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - } - break; - - default: - break; - } - - ncr->bus_in = bus; -} - void ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) { + scsi_bus_t *scsi_bus = &ncr->scsibus; int bus_host = 0; ncr5380_log("NCR5380 write(%04x,%02x)\n", port & 7, val); @@ -462,8 +169,10 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) if ((val & 0x80) && !(ncr->icr & 0x80)) { ncr5380_log("Resetting the 5380\n"); ncr5380_reset(ncr); + ncr5380_irq(ncr, 1); } ncr->icr = val; + ncr5380_log("ICR WaitData=%d, ClearReq=%d.\n", scsi_bus->wait_data, scsi_bus->clear_req); break; case 2: /* Mode register */ @@ -472,10 +181,8 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) ncr->icr &= ~ICR_ARB_LOST; ncr->icr |= ICR_ARB_IN_PROGRESS; } - ncr->mode = val; - - ncr->dma_mode_ext(ncr, ncr->priv); + ncr->dma_mode_ext(ncr, ncr->priv, val); break; case 3: /* Target Command Register */ @@ -488,17 +195,17 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 5: /* start DMA Send */ - ncr5380_log("Write: start DMA send register\n"); + pclog("Write: start DMA send register\n"); /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ - ncr->dma_mode = DMA_SEND; + scsi_bus->tx_mode = DMA_OUT_TX_BUS; if (ncr->dma_send_ext) ncr->dma_send_ext(ncr, ncr->priv); break; case 7: /* start DMA Initiator Receive */ - ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); + ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, waitdata=%d, clearreq=%d.\n", CS, cpu_state.pc, scsi_bus->wait_data, scsi_bus->clear_req); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ - ncr->dma_mode = DMA_INITIATOR_RECEIVE; + scsi_bus->tx_mode = DMA_IN_TX_BUS; if (ncr->dma_initiator_receive_ext) ncr->dma_initiator_receive_ext(ncr, ncr->priv); break; @@ -509,12 +216,13 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) } bus_host = ncr5380_get_bus_host(ncr); - ncr5380_bus_update(ncr, bus_host); + scsi_bus_update(scsi_bus, bus_host); } uint8_t ncr5380_read(uint16_t port, ncr_t *ncr) { + scsi_bus_t *scsi_bus = &ncr->scsibus; uint8_t ret = 0xff; int bus; int bus_state; @@ -524,12 +232,17 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ncr5380_log("Read: Current SCSI data register\n"); if (ncr->icr & ICR_DBP) { /*Return the data from the output register if on data bus phase from ICR*/ - ret = ncr->output_data; - ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x.\n", CS, cpu_state.pc, ret, ncr->clear_req, ncr->wait_data); + if (scsi_bus->command_issued) { + bus = scsi_bus_read(scsi_bus); + ret = BUS_GETDATA(bus); + } else + ret = ncr->output_data; + + ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x, txmode=%x.\n", CS, cpu_state.pc, ret, scsi_bus->clear_req, scsi_bus->wait_data, scsi_bus->tx_mode); } else { /*Return the data from the SCSI bus*/ - ncr5380_bus_read(ncr); - ret = BUS_GETDATA(ncr->cur_bus); + bus = scsi_bus_read(scsi_bus); + ret = BUS_GETDATA(bus); ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret); } break; @@ -552,15 +265,16 @@ ncr5380_read(uint16_t port, ncr_t *ncr) case 4: /* Current SCSI Bus status */ ncr5380_log("Read: SCSI bus status register\n"); ret = 0; - ncr5380_bus_read(ncr); - ncr5380_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff); - ret |= (ncr->cur_bus & 0xff); + bus = scsi_bus_read(scsi_bus); + ret |= (bus & 0xff); if (ncr->icr & ICR_SEL) ret |= BUS_SEL; if (ncr->icr & ICR_BSY) ret |= BUS_BSY; - // if ((ret & SCSI_PHASE_MESSAGE_IN) == SCSI_PHASE_MESSAGE_IN) - // ret &= ~BUS_REQ; + + /*Note by TC1995: Horrible hack, I know.*/ + (void) scsi_bus_read(scsi_bus); + (void) scsi_bus_read(scsi_bus); break; case 5: /* Bus and Status register */ @@ -571,13 +285,12 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ncr5380_log("Get host from Interrupt\n"); /*Check if the phase in process matches with TCR's*/ - if ((bus & SCSI_PHASE_MESSAGE_IN) == (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) { + if ((bus & SCSI_PHASE_MESSAGE_IN) == (scsi_bus->bus_out & SCSI_PHASE_MESSAGE_IN)) { ncr5380_log("Phase match\n"); ret |= STATUS_PHASE_MATCH; } - ncr5380_bus_read(ncr); - bus = ncr->cur_bus; + bus = scsi_bus_read(scsi_bus); if ((bus & BUS_ACK) || (ncr->icr & ICR_ACK)) ret |= STATUS_ACK; @@ -610,8 +323,8 @@ ncr5380_read(uint16_t port, ncr_t *ncr) case 6: ncr5380_log("Read: Input Data.\n"); - ncr5380_bus_read(ncr); - ret = BUS_GETDATA(ncr->cur_bus); + bus = scsi_bus_read(scsi_bus); + ret = BUS_GETDATA(bus); break; case 7: /* reset Parity/Interrupt */ diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index e028c7b42..a9d07af95 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -121,7 +121,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) { ncr53c400_t *ncr400 = (ncr53c400_t *) priv; ncr_t *ncr = &ncr400->ncr; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; addr &= 0x3fff; @@ -146,16 +147,9 @@ 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 (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0))) - timer_on_auto(&ncr400->timer, ncr->period / 250.0); - else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) { - if (scsi_device_get_callback(dev) > 0.0) - timer_on_auto(&ncr400->timer, 100.0); - else - timer_on_auto(&ncr400->timer, 40.0); - } } - } + } else + ncr53c400_log("No Write.\n"); break; case 0x3980: @@ -173,7 +167,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) break; case 0x3981: /* block counter register */ - ncr53c400_log("Write block counter register: val=%d, dma mode=%x, period=%lf.\n", val, ncr->dma_mode, ncr->period); + ncr53c400_log("Write block counter register: val=%d, dma mode=%x, period=%lf.\n", val, scsi_bus->tx_mode, scsi_bus->period); ncr400->block_count = val; ncr400->block_count_loaded = 1; @@ -186,17 +180,11 @@ 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 (ncr->mode & MODE_MONITOR_BUSY) - timer_on_auto(&ncr400->timer, (ncr->period / 4.0) * 3.0); - else if (scsi_device_get_callback(dev) > 0.0) - timer_on_auto(&ncr400->timer, 40.0); - else - timer_on_auto(&ncr400->timer, ncr->period); - - ncr->wait_data_back = ncr->wait_data; - ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", - ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); - } + timer_on_auto(&ncr400->timer, scsi_bus->period); + 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 + ncr53c400_log("No Timer.\n"); break; default: @@ -216,7 +204,8 @@ ncr53c400_read(uint32_t addr, void *priv) { ncr53c400_t *ncr400 = (ncr53c400_t *) priv; ncr_t *ncr = &ncr400->ncr; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; uint8_t ret = 0xff; addr &= 0x3fff; @@ -240,7 +229,7 @@ ncr53c400_read(uint32_t addr, void *priv) break; case 0x3900: - if (ncr400->buffer_host_pos >= MIN(128, dev->buffer_length) || (!(ncr400->status_ctrl & CTRL_DATA_DIR))) { + if ((ncr400->buffer_host_pos >= MIN(128, dev->buffer_length)) || (!(ncr400->status_ctrl & CTRL_DATA_DIR))) { ret = 0xff; ncr53c400_log("No Read.\n"); } else { @@ -249,15 +238,6 @@ ncr53c400_read(uint32_t addr, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; - ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl); - if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0)) - timer_on_auto(&ncr400->timer, ncr->period / 250.0); - else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) { - if (scsi_device_get_callback(dev) > 0.0) - timer_on_auto(&ncr400->timer, 100.0); - else - timer_on_auto(&ncr400->timer, 40.0); - } } } break; @@ -272,7 +252,7 @@ ncr53c400_read(uint32_t addr, void *priv) 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 = 0; /*Required by RTASPI10.SYS otherwise it won't initialize.*/ + ncr->mode = 0x00; /*Required by RTASPI10.SYS otherwise it won't initialize.*/ } } ncr53c400_log("NCR 53c400 status=%02x.\n", ret); @@ -411,46 +391,47 @@ t130b_in(uint16_t port, void *priv) } static void -ncr53c400_dma_mode_ext(void *priv, void *ext_priv) +ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv), uint8_t val) { - ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; + scsi_bus_t *scsi_bus = &ncr->scsibus; /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - ncr53c400_log("BlockCountLoaded=%d.\n", ncr400->block_count_loaded); - if (!ncr400->block_count_loaded) { - if (!(ncr->mode & MODE_DMA)) { - ncr53c400_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; - } + ncr53c400_log("NCR 53c400: BlockCountLoaded=%d, DMA mode enabled=%02x, valDMA=%02x.\n", ncr400->block_count_loaded, ncr->mode & MODE_DMA, val & MODE_DMA); + if (!(val & MODE_DMA) && (ncr->mode & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + scsi_bus->tx_mode = PIO_TX_BUS; } } static void ncr53c400_callback(void *priv) { - ncr53c400_t *ncr400 = (void *) priv; + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; ncr_t *ncr = &ncr400->ncr; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; int bus; uint8_t c; uint8_t temp; + uint8_t status; - if (ncr->dma_mode != DMA_IDLE) + if (scsi_bus->tx_mode != PIO_TX_BUS) timer_on_auto(&ncr400->timer, 1.0); - if (ncr->data_wait & 1) { - ncr->clear_req = 3; - ncr->data_wait &= ~1; + if (scsi_bus->data_wait & 1) { + scsi_bus->clear_req = 3; + scsi_bus->data_wait &= ~1; } - if (ncr->dma_mode == DMA_IDLE) + if (scsi_bus->tx_mode == PIO_TX_BUS) { + ncr53c400_log("Timer CMD=%02x.\n", scsi_bus->command[0]); return; + } - switch (ncr->dma_mode) { - case DMA_SEND: + switch (scsi_bus->tx_mode) { + case DMA_OUT_TX_BUS: if (ncr400->status_ctrl & CTRL_DATA_DIR) { ncr53c400_log("DMA_SEND with DMA direction set wrong\n"); break; @@ -468,8 +449,8 @@ ncr53c400_callback(void *priv) while (1) { for (c = 0; c < 10; c++) { - ncr5380_bus_read(ncr); - if (ncr->cur_bus & BUS_REQ) + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) break; } /* Data ready. */ @@ -478,8 +459,8 @@ ncr53c400_callback(void *priv) bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; bus |= BUS_SETDATA(temp); - ncr5380_bus_update(ncr, bus | BUS_ACK); - ncr5380_bus_update(ncr, bus & ~BUS_ACK); + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); ncr400->buffer_pos++; ncr53c400_log("NCR 53c400 Buffer pos for writing = %d\n", ncr400->buffer_pos); @@ -492,7 +473,7 @@ ncr53c400_callback(void *priv) ncr400->block_count = (ncr400->block_count - 1) & 0xff; ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count); if (!ncr400->block_count) { - ncr->dma_mode = DMA_IDLE; + scsi_bus->tx_mode = PIO_TX_BUS; ncr400->block_count_loaded = 0; ncr53c400_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -507,7 +488,7 @@ ncr53c400_callback(void *priv) } break; - case DMA_INITIATOR_RECEIVE: + case DMA_IN_TX_BUS: if (!(ncr400->status_ctrl & CTRL_DATA_DIR)) { ncr53c400_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); break; @@ -523,18 +504,18 @@ ncr53c400_callback(void *priv) while (1) { for (c = 0; c < 10; c++) { - ncr5380_bus_read(ncr); - if (ncr->cur_bus & BUS_REQ) + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) break; } /* Data ready. */ - ncr5380_bus_read(ncr); - temp = BUS_GETDATA(ncr->cur_bus); + bus = scsi_bus_read(scsi_bus); + temp = BUS_GETDATA(bus); bus = ncr5380_get_bus_host(ncr); - ncr5380_bus_update(ncr, bus | BUS_ACK); - ncr5380_bus_update(ncr, bus & ~BUS_ACK); + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); ncr400->buffer[ncr400->buffer_pos++] = temp; ncr53c400_log("NCR 53c400 Buffer pos for reading = %d\n", ncr400->buffer_pos); @@ -546,7 +527,7 @@ 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) { - ncr->dma_mode = DMA_IDLE; + 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; @@ -564,13 +545,12 @@ ncr53c400_callback(void *priv) break; } - ncr53c400_log("Bus Read.\n"); - ncr5380_bus_read(ncr); + status = scsi_bus_read(scsi_bus); - if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + if (!(status & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { ncr53c400_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; - ncr->dma_mode = DMA_IDLE; + scsi_bus->tx_mode = PIO_TX_BUS; ncr400->block_count_loaded = 0; } } @@ -643,6 +623,7 @@ ncr53c400_init(const device_t *info) const char *fn; ncr53c400_t *ncr400; ncr_t *ncr; + scsi_bus_t *scsi_bus; ncr400 = malloc(sizeof(ncr53c400_t)); memset(ncr400, 0x00, sizeof(ncr53c400_t)); @@ -651,6 +632,7 @@ ncr53c400_init(const device_t *info) ncr400->type = info->local; ncr->bus = scsi_get_bus(); + scsi_bus = &ncr->scsibus; switch (ncr400->type) { case ROM_LCS6821N: /* Longshine LCS6821N */ @@ -734,11 +716,17 @@ ncr53c400_init(const device_t *info) ncr->dma_send_ext = NULL; ncr->dma_initiator_receive_ext = NULL; ncr->timer = ncr53c400_timer_on_auto; + scsi_bus->bus_device = ncr->bus; + scsi_bus->timer = ncr->timer; + scsi_bus->priv = ncr->priv; ncr400->status_ctrl = STATUS_BUFFER_NOT_READY; ncr400->buffer_host_pos = 128; timer_add(&ncr400->timer, ncr53c400_callback, ncr400, 0); scsi_bus_set_speed(ncr->bus, 5000000.0); + scsi_bus->speed = 0.2; + scsi_bus->divider = 2.0; + scsi_bus->multi = 1.750; return ncr400; } diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index c878bbb91..0d653469a 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -69,7 +69,8 @@ t128_write(uint32_t addr, uint8_t val, void *priv) { t128_t *t128 = (t128_t *) priv; ncr_t *ncr = &t128->ncr; - const scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + const scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; addr &= 0x3fff; if ((addr >= 0x1800) && (addr < 0x1880)) @@ -84,7 +85,7 @@ t128_write(uint32_t addr, uint8_t val, void *priv) ncr5380_write((addr - 0x1d00) >> 5, val, ncr); else if ((addr >= 0x1e00) && (addr < 0x2000)) { if ((t128->host_pos < MIN(512, dev->buffer_length)) && - (ncr->dma_mode == DMA_SEND)) { + (scsi_bus->tx_mode == DMA_OUT_TX_BUS)) { t128->buffer[t128->host_pos] = val; t128->host_pos++; @@ -106,7 +107,8 @@ t128_read(uint32_t addr, void *priv) { t128_t *t128 = (t128_t *) priv; ncr_t *ncr = &t128->ncr; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; uint8_t ret = 0xff; addr &= 0x3fff; @@ -124,7 +126,7 @@ t128_read(uint32_t addr, void *priv) ret = ncr5380_read((addr - 0x1d00) >> 5, ncr); else if (addr >= 0x1e00 && addr < 0x2000) { if ((t128->host_pos >= MIN(512, dev->buffer_length)) || - (ncr->dma_mode != DMA_INITIATOR_RECEIVE)) + (scsi_bus->tx_mode != DMA_IN_TX_BUS)) ret = 0xff; else { ret = t128->buffer[t128->host_pos++]; @@ -135,8 +137,8 @@ t128_read(uint32_t addr, void *priv) if (t128->host_pos == MIN(512, dev->buffer_length)) { t128->status &= ~0x04; t128_log("T128 Transfer busy read, status = %02x, period = %lf\n", - t128->status, ncr->period); - if ((ncr->period == 0.2) || (ncr->period == 0.02)) + t128->status, scsi_bus->period); + if ((scsi_bus->period == 0.2) || (scsi_bus->period == 0.02)) timer_on_auto(&t128->timer, 40.2); } else if ((t128->host_pos < MIN(512, dev->buffer_length)) && (scsi_device_get_callback(dev) > 100.0)) @@ -148,15 +150,16 @@ t128_read(uint32_t addr, void *priv) } static void -t128_dma_mode_ext(void *priv, void *ext_priv) +t128_dma_mode_ext(void *priv, void *ext_priv, UNUSED(uint8_t val)) { t128_t *t128 = (t128_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; + scsi_bus_t *scsi_bus = &ncr->scsibus; /*Don't stop the timer until it finishes the transfer*/ if (t128->block_loaded && (ncr->mode & MODE_DMA)) { t128_log("Continuing DMA mode\n"); - timer_on_auto(&t128->timer, ncr->period + 1.0); + timer_on_auto(&t128->timer, scsi_bus->period + 1.0); } /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ @@ -164,7 +167,7 @@ t128_dma_mode_ext(void *priv, void *ext_priv) t128_log("No DMA mode\n"); ncr->tcr &= ~TCR_LAST_BYTE_SENT; ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; + scsi_bus->tx_mode = PIO_TX_BUS; } } @@ -173,7 +176,8 @@ t128_dma_send_ext(void *priv, void *ext_priv) { t128_t *t128 = (t128_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { memset(t128->buffer, 0, MIN(512, dev->buffer_length)); @@ -194,7 +198,8 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) { t128_t *t128 = (t128_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { memset(t128->buffer, 0, MIN(512, dev->buffer_length)); @@ -227,27 +232,29 @@ t128_callback(void *priv) { t128_t *t128 = (void *) priv; ncr_t *ncr = &t128->ncr; - scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; - int bus; - uint8_t c; - uint8_t temp; + scsi_bus_t *scsi_bus = &ncr->scsibus; + scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; + int bus; + uint8_t c; + uint8_t temp; + uint8_t status; - if ((ncr->dma_mode != DMA_IDLE) && (ncr->mode & MODE_DMA) && t128->block_loaded) { + if ((scsi_bus->tx_mode != PIO_TX_BUS) && (ncr->mode & MODE_DMA) && t128->block_loaded) { if ((t128->host_pos == MIN(512, dev->buffer_length)) && t128->block_count) t128->status |= 0x04; - timer_on_auto(&t128->timer, ncr->period / 55.0); + timer_on_auto(&t128->timer, scsi_bus->period / 55.0); } - if (ncr->data_wait & 1) { - ncr->clear_req = 3; - ncr->data_wait &= ~1; - if (ncr->dma_mode == DMA_IDLE) + if (scsi_bus->data_wait & 1) { + scsi_bus->clear_req = 3; + scsi_bus->data_wait &= ~1; + if (scsi_bus->tx_mode == PIO_TX_BUS) return; } - switch (ncr->dma_mode) { - case DMA_SEND: + switch (scsi_bus->tx_mode) { + case DMA_OUT_TX_BUS: if (!(t128->status & 0x04)) { t128_log("Write status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); break; @@ -263,8 +270,8 @@ t128_callback(void *priv) write_again: for (c = 0; c < 10; c++) { - ncr5380_bus_read(ncr); - if (ncr->cur_bus & BUS_REQ) + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) break; } @@ -274,8 +281,8 @@ write_again: bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; bus |= BUS_SETDATA(temp); - ncr5380_bus_update(ncr, bus | BUS_ACK); - ncr5380_bus_update(ncr, bus & ~BUS_ACK); + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); t128->pos++; t128_log("T128 Buffer pos for writing = %d\n", t128->pos); @@ -302,7 +309,7 @@ write_again: goto write_again; break; - case DMA_INITIATOR_RECEIVE: + case DMA_IN_TX_BUS: if (!(t128->status & 0x04)) { t128_log("Read status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); break; @@ -318,19 +325,19 @@ write_again: read_again: for (c = 0; c < 10; c++) { - ncr5380_bus_read(ncr); - if (ncr->cur_bus & BUS_REQ) + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) break; } /* Data ready. */ - ncr5380_bus_read(ncr); - temp = BUS_GETDATA(ncr->cur_bus); + bus = scsi_bus_read(scsi_bus); + temp = BUS_GETDATA(bus); bus = ncr5380_get_bus_host(ncr); - ncr5380_bus_update(ncr, bus | BUS_ACK); - ncr5380_bus_update(ncr, bus & ~BUS_ACK); + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); t128->buffer[t128->pos++] = temp; t128_log("T128 Buffer pos for reading=%d, temp=%02x, len=%d.\n", t128->pos, temp, dev->buffer_length); @@ -360,12 +367,12 @@ read_again: break; } - ncr5380_bus_read(ncr); + status = scsi_bus_read(scsi_bus); - if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + if (!(status & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { t128_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; - ncr->dma_mode = DMA_IDLE; + scsi_bus->tx_mode = PIO_TX_BUS; timer_on_auto(&t128->timer, 10.0); } } @@ -467,12 +474,14 @@ t128_init(const device_t *info) { t128_t *t128; ncr_t *ncr; + scsi_bus_t *scsi_bus; t128 = malloc(sizeof(t128_t)); memset(t128, 0x00, sizeof(t128_t)); ncr = &t128->ncr; ncr->bus = scsi_get_bus(); + scsi_bus = &ncr->scsibus; if (info->flags & DEVICE_MCA) { rom_init(&t128->bios_rom, T128_ROM, @@ -504,6 +513,9 @@ t128_init(const device_t *info) ncr->dma_send_ext = t128_dma_send_ext; ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext; ncr->timer = t128_timer_on_auto; + scsi_bus->bus_device = ncr->bus; + scsi_bus->timer = ncr->timer; + scsi_bus->priv = ncr->priv; t128->status = 0x00 /*0x04*/; t128->host_pos = 512; if (!t128->bios_enabled && !(info->flags & DEVICE_MCA)) @@ -516,6 +528,9 @@ t128_init(const device_t *info) timer_add(&t128->timer, t128_callback, t128, 0); scsi_bus_set_speed(ncr->bus, 5000000.0); + scsi_bus->speed = 0.2; + scsi_bus->divider = 1.0; + scsi_bus->multi = 1.0; return t128; } diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index ed82afebf..110ee95c9 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -86,7 +86,7 @@ * Copyright 2008-2024 Sarah Walker. * Copyright 2024 Miran Grca. */ -#define _USE_MATH_DEFINES +#define _USE_MATH_DEFINES #include #include #include @@ -706,6 +706,7 @@ static uint8_t pas16_in(uint16_t port, void *priv) { pas16_t *pas16 = (pas16_t *) priv; + scsi_bus_t *scsi_bus = NULL; uint8_t ret = 0xff; port -= pas16->base; @@ -784,9 +785,11 @@ pas16_in(uint16_t port, void *priv) ret = t128_read(0x1e00, pas16->scsi); break; case 0x5c01: - if (pas16->has_scsi) + if (pas16->has_scsi) { + scsi_bus = &pas16->scsi->ncr.scsibus; /* Bits 0-6 must absolutely be set for SCSI hard disk drivers to work. */ - ret = (((pas16->scsi->ncr.dma_mode != DMA_IDLE) && (pas16->scsi->status & 0x04)) << 7) | 0x7f; + ret = (((scsi_bus->tx_mode != PIO_TX_BUS) && (pas16->scsi->status & 0x04)) << 7) | 0x7f; + } break; case 0x5c03: if (pas16->has_scsi) @@ -1183,10 +1186,11 @@ pas16_scsi_callback(void *priv) { pas16_t * pas16 = (pas16_t *) priv; t128_t * dev = pas16->scsi; + scsi_bus_t * scsi_bus = &dev->ncr.scsibus; t128_callback(pas16->scsi); - if ((dev->ncr.dma_mode != DMA_IDLE) && (dev->status & 0x04)) { + if ((scsi_bus->tx_mode != PIO_TX_BUS) && (dev->status & 0x04)) { timer_stop(&pas16->scsi_timer); pas16->timeout_status &= 0x7f; } From 714eadfc3a0b3325060cef21f14faa9b90929ec4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 23 Jan 2025 10:31:31 +0100 Subject: [PATCH 0150/1190] NVR: Get/set time functions now take a void pointer, so nvr.h can be included without requiring time.h. --- src/include/86box/nvr.h | 4 ++-- src/nvr.c | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 85e0954f0..c6dc08a12 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -114,8 +114,8 @@ extern int nvr_save(void); extern int nvr_is_leap(int year); extern int nvr_get_days(int month, int year); extern void nvr_time_sync(void); -extern void nvr_time_get(struct tm *); -extern void nvr_time_set(struct tm *); +extern void nvr_time_get(void *priv); +extern void nvr_time_set(void *priv); extern void nvr_reg_write(uint16_t reg, uint8_t val, void *priv); extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); diff --git a/src/nvr.c b/src/nvr.c index d833618d0..d0b05b93a 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -326,14 +326,15 @@ nvr_time_sync(void) /* Get current time from internal clock. */ void -nvr_time_get(struct tm *tm) +nvr_time_get(void *priv) { - uint8_t dom; - uint8_t mon; - uint8_t sum; - uint8_t wd; - uint16_t cent; - uint16_t yr; + struct tm *tm = (struct tm *) priv; + uint8_t dom; + uint8_t mon; + uint8_t sum; + uint8_t wd; + uint16_t cent; + uint16_t yr; tm->tm_sec = intclk.tm_sec; tm->tm_min = intclk.tm_min; @@ -352,8 +353,10 @@ nvr_time_get(struct tm *tm) /* Set internal clock time. */ void -nvr_time_set(struct tm *tm) +nvr_time_set(void *priv) { + struct tm *tm = (struct tm *) priv; + intclk.tm_sec = tm->tm_sec; intclk.tm_min = tm->tm_min; intclk.tm_hour = tm->tm_hour; From fbd1a16eeb39e5f0385322b8c66aedfc19069d2d Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Sat, 25 Jan 2025 00:22:59 +0300 Subject: [PATCH 0151/1190] Add the AT&T Globalyst 330 (Pentium/Socket 4) --- src/include/86box/machine.h | 1 + src/machine/m_at_socket4.c | 31 ++++++++++++++++++++++++++++ src/machine/machine_table.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0cd3564ee..b0365314e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -637,6 +637,7 @@ extern int machine_at_m5pi_init(const machine_t *); extern int machine_at_excalibur_init(const machine_t *); +extern int machine_at_globalyst330_p5_init(const machine_t *); extern int machine_at_p5vl_init(const machine_t *); extern int machine_at_excaliburpci2_init(const machine_t *); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index c3213f1ac..78df5b0cb 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -384,6 +384,37 @@ machine_at_m5pi_init(const machine_t *model) return ret; } +int +machine_at_globalyst330_p5_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/globalyst330_p5/MiTAC_PB5500C_v1.02_120794_ATT.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 5, 6, 7, 8); + pci_register_slot(0x13, PCI_CARD_NORMAL, 9, 10, 11, 12); + pci_register_slot(0x14, PCI_CARD_NORMAL, 13, 14, 15, 16); + + device_add(&opti5x7_pci_device); + device_add(&opti822_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_excalibur_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f2fb53a6f..2a50159e9 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9582,6 +9582,46 @@ const machine_t machines[] = { }, /* OPTi 596/597/822 */ + /* Has a VIA VT82C42N KBC with AMI 'F' firmware */ + { + .name = "[OPTi 597] AT&T Globalyst 330 (Pentium)", + .internal_name = "globalyst330_p5", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_globalyst330_p5_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM, + .ram = { + .min = 8192, + .max = 65536, + .step = 8192 + }, + .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 + }, /* This has AMIKey 'F' KBC firmware. */ { .name = "[OPTi 597] Supermicro P5VL-PCI", From e61f3c8a5d4b3b70de7c1f684f871d39e3fb1513 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 26 Jan 2025 14:25:35 +0100 Subject: [PATCH 0152/1190] Video changes of the day (January 26th, 2025) XGA: 1. Added a proper poll so to have its timings independent of the SVGA core and changes its renderer accordingly, mainly a blank render one. 2. Workaround the Ctrl-Alt-Del reset of Windows 2.x so that it switches back to VGA text mode correctly when using the 0xA000 64K aperture (in vid_svga.c). SVGA core: Re-organized the way the different timers are organized so that the XGA and 8514/A pollers can coexist with the SVGA timer without conflicts. ATI Mach32: Reworked the true color renderer and made it a Mach32 exclusive due to its differences from the standard one. Fixes wrong rendered colors in NT using the 32bpp renderer in RGB mode. --- src/include/86box/vid_svga.h | 12 +- src/include/86box/vid_xga.h | 2 - src/video/vid_8514a.c | 12 +- src/video/vid_ati_mach8.c | 102 ++++++++++- src/video/vid_svga.c | 204 +++++++++++++++++---- src/video/vid_xga.c | 340 +++++++++++++++++++---------------- 6 files changed, 466 insertions(+), 206 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 2b26df2f3..3be4ee9e5 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -189,6 +189,7 @@ typedef struct svga_t { void (*render)(struct svga_t *svga); void (*render8514)(struct svga_t *svga); + void (*render_xga)(struct svga_t *svga); void (*recalctimings_ex)(struct svga_t *svga); void (*video_out)(uint16_t addr, uint8_t val, void *priv); @@ -306,6 +307,7 @@ typedef struct svga_t { void * xga; } svga_t; +extern void ibm8514_set_poll(svga_t *svga); extern void ibm8514_poll(void *priv); extern void ibm8514_recalctimings(svga_t *svga); extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv); @@ -328,10 +330,11 @@ extern void ati8514_mca_write(int port, uint8_t val, void *priv); extern void ati8514_pos_write(uint16_t port, uint8_t val, void *priv); extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); -extern void xga_write_test(uint32_t addr, uint8_t val, void *priv); -extern uint8_t xga_read_test(uint32_t addr, void *priv); -extern void xga_poll(void *priv); -extern void xga_recalctimings(svga_t *svga); +extern void xga_write_test(uint32_t addr, uint8_t val, void *priv); +extern uint8_t xga_read_test(uint32_t addr, void *priv); +extern void xga_set_poll(svga_t *svga); +extern void xga_poll(void *priv); +extern void xga_recalctimings(svga_t *svga); extern uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write); @@ -376,6 +379,7 @@ uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); void svga_doblit(int wx, int wy, svga_t *svga); +void svga_set_poll(svga_t *svga); void svga_poll(void *priv); enum { diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index b90b53978..b2001dba9 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -240,8 +240,6 @@ typedef struct xga_t { uint16_t px_map_height[4]; uint32_t px_map_base[4]; } accel; - - int big_endian_linear; } xga_t; #endif /*VIDEO_XGA_H*/ diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 0e51feae4..d2e7efd8b 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -301,7 +301,7 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in if ((cmd >= 2) && (dev->accel.cmd & 0x1000)) val = (val >> 8) | (val << 8); } - if ((cmd <= 2) || (cmd == 4) || ((cmd == 6))) { + if ((cmd <= 2) || (cmd == 4) || (cmd == 6)) { if ((dev->accel.cmd & 0x08) && (cmd >= 2)) monoxfer = val; else { @@ -3605,6 +3605,12 @@ ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) buffer32->line[dev->displine + svga->y_add][svga->x_add + dev->h_disp + i] = svga->overscan_color; } +void +ibm8514_set_poll(svga_t *svga) +{ + timer_set_callback(&svga->timer, ibm8514_poll); +} + void ibm8514_poll(void *priv) { @@ -3614,7 +3620,7 @@ ibm8514_poll(void *priv) int wx; int wy; - ibm8514_log("IBM 8514/A poll.\n"); + ibm8514_log("IBM 8514/A poll=%x.\n", dev->on); if (dev->on) { ibm8514_log("ON!\n"); if (!dev->linepos) { @@ -3857,7 +3863,7 @@ ibm8514_mca_reset(void *priv) else ibm8514_mca_write(0x102, 0, svga); - timer_set_callback(&svga->timer, svga_poll); + svga_set_poll(svga); } static void * diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index d294f61e9..812885559 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2503,6 +2503,96 @@ ati8514_in(uint16_t addr, void *priv) return temp; } +static void +ati_render_24bpp(svga_t *svga) +{ + mach_t *mach = (mach_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/ + for (int x = 0; x <= dev->h_disp; x += 4) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dev->ma += 12; + } + } else { /*RGB, Red-(23:16), Green-(15:8), Blue-(7:0)*/ + for (int x = 0; x <= dev->h_disp; x += 4) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[x] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + p[x + 1] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + p[x + 2] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + p[x + 3] = dat & 0xffffff; + + dev->ma += 12; + } + } + dev->ma &= dev->vram_mask; + } +} + +static void +ati_render_32bpp(svga_t *svga) +{ + mach_t *mach = (mach_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/ + for (x = 0; x <= dev->h_disp; x++) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + *p++ = ((dat & 0x00ff0000) >> 16) | (dat & 0x0000ff00) | ((dat & 0x000000ff) << 16); + } + } else { /*RGB, Red-(31:24), Green-(23:16), Blue-(15:8)*/ + for (x = 0; x <= dev->h_disp; x++) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + *p++ = ((dat & 0xffffff00) >> 8); + } + } + dev->ma += (x * 4); + dev->ma &= dev->vram_mask; + } +} + void ati8514_recalctimings(svga_t *svga) { @@ -2711,17 +2801,11 @@ mach_recalctimings(svga_t *svga) break; case 24: mach_log("GEConfig24bpp: %03x.\n", mach->accel.ext_ge_config & 0x600); - if (mach->accel.ext_ge_config & 0x400) - svga->render8514 = ibm8514_render_BGR; - else - svga->render8514 = ibm8514_render_24bpp; + svga->render8514 = ati_render_24bpp; break; case 32: mach_log("GEConfig32bpp: %03x.\n", mach->accel.ext_ge_config & 0x600); - if (mach->accel.ext_ge_config & 0x400) - svga->render8514 = ibm8514_render_ABGR8888; - else - svga->render8514 = ibm8514_render_32bpp; + svga->render8514 = ati_render_32bpp; break; default: @@ -5776,7 +5860,7 @@ mach_mca_reset(void *priv) mach_log("MCA reset.\n"); dev->on = 0; mach_mca_write(0x102, 0, mach); - timer_set_callback(&svga->timer, svga_poll); + svga_set_poll(svga); } uint8_t diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index e6201e4bf..4db2737ca 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -83,26 +83,76 @@ svga_get_pri(void) return svga_pri; } +void +svga_set_poll(svga_t *svga) +{ + svga_log("SVGA Timer activated, enabled?=%x.\n", timer_is_enabled(&svga->timer)); + timer_set_callback(&svga->timer, svga_poll); + if (!timer_is_enabled(&svga->timer)) + timer_enable(&svga->timer); +} + void svga_set_override(svga_t *svga, int val) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret_poll = 0; if (svga->override && !val) svga->fullchange = svga->monitor->mon_changeframecount; + svga->override = val; svga_log("Override=%x.\n", val); - if (ibm8514_active && (svga->dev8514 != NULL)) { - if (dev->on) { - if (svga->override) - timer_set_callback(&svga->timer, svga_poll); - else - timer_set_callback(&svga->timer, ibm8514_poll); - } else - timer_set_callback(&svga->timer, svga_poll); - } else - timer_set_callback(&svga->timer, svga_poll); + if (ibm8514_active && (svga->dev8514 != NULL)) + ret_poll |= 1; + + if (xga_active && (svga->xga != NULL)) + ret_poll |= 2; + + if (svga->override) + svga_set_poll(svga); + else { + switch (ret_poll) { + case 0: + default: + svga_set_poll(svga); + break; + + case 1: + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on) + ibm8514_set_poll(svga); + else + svga_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 2: + if (xga_active && (svga->xga != NULL)) { + if (xga->on) + xga_set_poll(svga); + else + svga_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 3: + if (ibm8514_active && (svga->dev8514 != NULL) && xga_active && (svga->xga != NULL)) { + if (dev->on) + ibm8514_set_poll(svga); + else if (xga->on) + xga_set_poll(svga); + else + svga_set_poll(svga); + } else + svga_set_poll(svga); + break; + } + } #ifdef OVERRIDE_OVERSCAN if (!val) { @@ -241,7 +291,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) if (ibm8514_active && dev) dev->on = (val & 0x01) ? 0 : 1; - svga_log("Write Port 3C3.\n"); + svga_log("Write Port 3C3=%x.\n", val & 0x01); svga_recalctimings(svga); break; case 0x3c4: @@ -612,6 +662,8 @@ void svga_recalctimings(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; + uint8_t set_timer = 0; double crtcconst; double _dispontime; double _dispofftime; @@ -620,6 +672,10 @@ svga_recalctimings(svga_t *svga) double _dispontime8514 = 0.0; double _dispofftime8514 = 0.0; double disptime8514 = 0.0; + double crtcconst_xga = 0.0; + double _dispontime_xga = 0.0; + double _dispofftime_xga = 0.0; + double disptime_xga = 0.0; #ifdef ENABLE_SVGA_LOG int vsyncend; int vblankend; @@ -709,6 +765,12 @@ svga_recalctimings(svga_t *svga) } else svga->render = svga_render_text_80; + if (xga_active && (svga->xga != NULL)) { + if (xga->on) { + if ((svga->mapping.base == 0xb8000) && (xga->aperture_cntl == 1)) /*Some operating systems reset themselves with ctrl-alt-del by going into text mode.*/ + xga->on = 0; + } + } svga->hdisp_old = svga->hdisp; } else { svga->hdisp_old = svga->hdisp; @@ -904,6 +966,10 @@ svga_recalctimings(svga_t *svga) if (dev->on) crtcconst8514 = svga->clock8514; } + if (xga_active && (svga->xga != NULL)) { + if (xga->on) + crtcconst_xga = svga->clock_xga; + } #ifdef ENABLE_SVGA_LOG vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); @@ -952,6 +1018,13 @@ svga_recalctimings(svga_t *svga) } } + if (xga_active && (svga->xga != NULL)) { + if (xga->on) { + disptime_xga = xga->h_total ? xga->h_total : TIMER_USEC; + _dispontime_xga = xga->h_disp; + } + } + if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; @@ -968,25 +1041,84 @@ svga_recalctimings(svga_t *svga) if (svga->dispofftime < TIMER_USEC) svga->dispofftime = TIMER_USEC; - if (ibm8514_active && (svga->dev8514 != NULL)) { - if (dev->on) { - _dispofftime8514 = disptime8514 - _dispontime8514; - _dispontime8514 *= crtcconst8514; - _dispofftime8514 *= crtcconst8514; + if (ibm8514_active && (svga->dev8514 != NULL)) + set_timer |= 1; - dev->dispontime = (uint64_t) (_dispontime8514); - dev->dispofftime = (uint64_t) (_dispofftime8514); - if (dev->dispontime < TIMER_USEC) - dev->dispontime = TIMER_USEC; - if (dev->dispofftime < TIMER_USEC) - dev->dispofftime = TIMER_USEC; + if (xga_active && (svga->xga != NULL)) + set_timer |= 2; - svga_log("IBM 8514/A poll.\n"); - timer_set_callback(&svga->timer, ibm8514_poll); - } else { - svga_log("SVGA poll enabled.\n"); - timer_set_callback(&svga->timer, svga_poll); - } + switch (set_timer) { + default: + case 0: /*VGA only*/ + svga_set_poll(svga); + break; + + case 1: /*Plus 8514/A*/ + if (dev->on) { + _dispofftime8514 = disptime8514 - _dispontime8514; + _dispontime8514 *= crtcconst8514; + _dispofftime8514 *= crtcconst8514; + + dev->dispontime = (uint64_t) (_dispontime8514); + dev->dispofftime = (uint64_t) (_dispofftime8514); + if (dev->dispontime < TIMER_USEC) + dev->dispontime = TIMER_USEC; + if (dev->dispofftime < TIMER_USEC) + dev->dispofftime = TIMER_USEC; + + ibm8514_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 2: /*Plus XGA*/ + if (xga->on) { + _dispofftime_xga = disptime_xga - _dispontime_xga; + _dispontime_xga *= crtcconst_xga; + _dispofftime_xga *= crtcconst_xga; + + xga->dispontime = (uint64_t) (_dispontime_xga); + xga->dispofftime = (uint64_t) (_dispofftime_xga); + if (xga->dispontime < TIMER_USEC) + xga->dispontime = TIMER_USEC; + if (xga->dispofftime < TIMER_USEC) + xga->dispofftime = TIMER_USEC; + + xga_set_poll(svga); + } else + svga_set_poll(svga); + break; + + case 3: /*Plus 8514/A and XGA*/ + if (dev->on) { + _dispofftime8514 = disptime8514 - _dispontime8514; + _dispontime8514 *= crtcconst8514; + _dispofftime8514 *= crtcconst8514; + + dev->dispontime = (uint64_t) (_dispontime8514); + dev->dispofftime = (uint64_t) (_dispofftime8514); + if (dev->dispontime < TIMER_USEC) + dev->dispontime = TIMER_USEC; + if (dev->dispofftime < TIMER_USEC) + dev->dispofftime = TIMER_USEC; + + ibm8514_set_poll(svga); + } else if (xga->on) { + _dispofftime_xga = disptime_xga - _dispontime_xga; + _dispontime_xga *= crtcconst_xga; + _dispofftime_xga *= crtcconst_xga; + + xga->dispontime = (uint64_t) (_dispontime_xga); + xga->dispofftime = (uint64_t) (_dispofftime_xga); + if (xga->dispontime < TIMER_USEC) + xga->dispontime = TIMER_USEC; + if (xga->dispofftime < TIMER_USEC) + xga->dispofftime = TIMER_USEC; + + xga_set_poll(svga); + } else + svga_set_poll(svga); + break; } if (!svga->force_old_addr) @@ -1064,7 +1196,6 @@ void svga_poll(void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint32_t x; uint32_t blink_delay; int wx; @@ -1072,15 +1203,6 @@ svga_poll(void *priv) int ret; int old_ma; - if (!svga->override) { - if (xga_active && xga && xga->on) { - if ((xga->disp_cntl_2 & 7) >= 2) { - xga_poll(svga); - return; - } - } - } - svga_log("SVGA Poll.\n"); if (!svga->linepos) { if (svga->displine == ((svga->hwcursor_latch.y < 0) ? 0 : svga->hwcursor_latch.y) && svga->hwcursor_latch.ena) { @@ -2070,6 +2192,8 @@ svga_readw_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_w; if (!linear) { + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); addr = svga_decode_addr(svga, addr, 0); if (addr == 0xffffffff) return 0xffff; @@ -2116,6 +2240,10 @@ svga_readl_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_l; if (!linear) { + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); + (void) xga_read_test(addr + 2, svga); + (void) xga_read_test(addr + 3, svga); addr = svga_decode_addr(svga, addr, 0); if (addr == 0xffffffff) return 0xffffffff; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 852ff6273..8bdc72fc6 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -243,6 +243,26 @@ xga_updatemapping(svga_t *svga) } } +static void +xga_render_blank(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (xga->firstline_draw == 2000) + xga->firstline_draw = xga->displine; + + xga->lastline_draw = xga->displine; + + uint32_t *line_ptr = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + uint32_t line_width = (uint32_t)(xga->h_disp) * sizeof(uint32_t); + + if (xga->h_disp > 0) + memset(line_ptr, 0, line_width); +} + void xga_recalctimings(svga_t *svga) { @@ -272,26 +292,43 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; + xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x, dispcntl2=%02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80, xga->disp_cntl_2 & 0xc0); switch ((xga->clk_sel_1 >> 2) & 3) { case 0: xga_log("HDISP VGA0 = %d, XGA = %d.\n", svga->hdisp, xga->h_disp); if (xga->clk_sel_2 & 0x80) - svga->clock = (cpuclock * (double) (1ULL << 32)) / 41539000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 41539000.0; else - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 25175000.0; break; case 1: xga_log("HDISP VGA1 = %d, XGA = %d.\n", svga->hdisp, xga->h_disp); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 28322000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 28322000.0; break; case 3: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + svga->clock_xga = (cpuclock * (double) (1ULL << 32)) / 44900000.0; break; default: break; } + + switch (xga->disp_cntl_2 & 7) { + case 2: + svga->render_xga = xga_render_4bpp; + break; + case 3: + svga->render_xga = xga_render_8bpp; + break; + case 4: + svga->render_xga = xga_render_16bpp; + break; + + default: + svga->render_xga = xga_render_blank; + break; + } } } @@ -2717,8 +2754,10 @@ xga_write_test(uint32_t addr, uint8_t val, void *priv) xga->vram[addr & xga->vram_mask] = val; xga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x, a5test=%d.\n", val, addr, svga->banked_mask, xga->a5_test); } - } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) + } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) { xga->on = 0; + xga_log("OFF XGA write.\n"); + } } } @@ -2824,8 +2863,10 @@ xga_read_test(uint32_t addr, void *priv) addr += xga->read_bank; return xga->vram[addr & xga->vram_mask]; } - } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) + } else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000))) { xga->on = 0; + xga_log("OFF XGA read.\n"); + } } return ret; } @@ -3029,6 +3070,12 @@ xga_readl_linear(uint32_t addr, void *priv) return ret; } +void +xga_set_poll(svga_t *svga) +{ + timer_set_callback(&svga->timer, xga_poll); +} + void xga_poll(void *priv) { @@ -3038,166 +3085,158 @@ xga_poll(void *priv) int wx; int wy; - if (!xga->linepos) { - if (xga->displine == xga->hwcursor_latch.y && xga->hwcursor_latch.ena) { - xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 32 : 0); - xga->hwcursor_oddeven = 0; - } - - if (xga->displine == (xga->hwcursor_latch.y + 1) && xga->hwcursor_latch.ena && xga->interlace) { - xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 33 : 1); - xga->hwcursor_oddeven = 1; - } - - timer_advance_u64(&svga->timer, svga->dispofftime); - svga->cgastat |= 1; - xga->linepos = 1; - - if (xga->dispon) { - xga->h_disp_on = 1; - - xga->ma &= xga->vram_mask; - - if (xga->firstline == 2000) { - xga->firstline = xga->displine; - video_wait_for_buffer_monitor(svga->monitor_index); + xga_log("XGA Poll=%d.\n", xga->on); + if (xga->on) { + if (!xga->linepos) { + if (xga->displine == xga->hwcursor_latch.y && xga->hwcursor_latch.ena) { + xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 32 : 0); + xga->hwcursor_oddeven = 0; } - if (xga->hwcursor_on) - xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; - - switch (xga->disp_cntl_2 & 7) { - case 2: - xga_render_4bpp(svga); - break; - case 3: - xga_render_8bpp(svga); - break; - case 4: - xga_render_16bpp(svga); - break; - default: - break; + if (xga->displine == (xga->hwcursor_latch.y + 1) && xga->hwcursor_latch.ena && xga->interlace) { + xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - ((xga->hwcursor_latch.yoff & 0x20) ? 33 : 1); + xga->hwcursor_oddeven = 1; } - svga->x_add = (overscan_x >> 1); - xga_render_overscan_left(xga, svga); - xga_render_overscan_right(xga, svga); - svga->x_add = (overscan_x >> 1); + timer_advance_u64(&svga->timer, xga->dispofftime); + svga->cgastat |= 1; + xga->linepos = 1; - if (xga->hwcursor_on) { - xga_hwcursor_draw(svga, xga->displine + svga->y_add); - xga->hwcursor_on--; - if (xga->hwcursor_on && xga->interlace) + if (xga->dispon) { + xga->h_disp_on = 1; + + xga->ma &= xga->vram_mask; + + if (xga->firstline == 2000) { + xga->firstline = xga->displine; + video_wait_for_buffer_monitor(svga->monitor_index); + } + + if (xga->hwcursor_on) + xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; + + svga->render_xga(svga); + + svga->x_add = (overscan_x >> 1); + xga_render_overscan_left(xga, svga); + xga_render_overscan_right(xga, svga); + svga->x_add = (overscan_x >> 1); + + if (xga->hwcursor_on) { + xga_hwcursor_draw(svga, xga->displine + svga->y_add); xga->hwcursor_on--; + if (xga->hwcursor_on && xga->interlace) + xga->hwcursor_on--; + } + + if (xga->lastline < xga->displine) + xga->lastline = xga->displine; } - if (xga->lastline < xga->displine) - xga->lastline = xga->displine; - } - - xga->displine++; - if (xga->interlace) xga->displine++; - if ((svga->cgastat & 8) && ((xga->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) - svga->cgastat &= ~8; - if (xga->displine > 1500) - xga->displine = 0; - } else { - timer_advance_u64(&svga->timer, svga->dispontime); - if (xga->dispon) - svga->cgastat &= ~1; + if (xga->interlace) + xga->displine++; + if ((svga->cgastat & 8) && ((xga->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) + svga->cgastat &= ~8; + if (xga->displine > 1500) + xga->displine = 0; + } else { + timer_advance_u64(&svga->timer, xga->dispontime); + if (xga->dispon) + svga->cgastat &= ~1; - xga->h_disp_on = 0; + xga->h_disp_on = 0; - xga->linepos = 0; - if (xga->dispon) { - if (xga->sc == xga->rowcount) { - xga->sc = 0; + xga->linepos = 0; + if (xga->dispon) { + if (xga->sc == xga->rowcount) { + xga->sc = 0; - xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); - xga->maback += (xga->rowoffset << 3); - if (xga->interlace) + xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); xga->maback += (xga->rowoffset << 3); + if (xga->interlace) + xga->maback += (xga->rowoffset << 3); - xga->maback &= xga->vram_mask; - xga->ma = xga->maback; - } else { - xga->sc++; - xga->sc &= 0x1f; - xga->ma = xga->maback; + xga->maback &= xga->vram_mask; + xga->ma = xga->maback; + } else { + xga->sc++; + xga->sc &= 0x1f; + xga->ma = xga->maback; + } + } + + xga->vc++; + xga->vc &= 0x7ff; + + if (xga->vc == xga->split) { + if (xga->interlace && xga->oddeven) + xga->ma = xga->maback = (xga->rowoffset << 1); + else + xga->ma = xga->maback = 0; + + xga->ma = (xga->ma << 2); + xga->maback = (xga->maback << 2); + + xga->sc = 0; + } + if (xga->vc == xga->dispend) { + xga->dispon = 0; + + for (x = 0; x < ((xga->vram_mask + 1) >> 12); x++) { + if (xga->changedvram[x]) + xga->changedvram[x]--; + } + if (svga->fullchange) + svga->fullchange--; + } + if (xga->vc == xga->v_syncstart) { + xga->dispon = 0; + svga->cgastat |= 8; + x = xga->h_disp; + + if (xga->interlace && !xga->oddeven) + xga->lastline++; + if (xga->interlace && xga->oddeven) + xga->firstline--; + + wx = x; + + wy = xga->lastline - xga->firstline; + svga_doblit(wx, wy, svga); + + xga->firstline = 2000; + xga->lastline = 0; + + xga->firstline_draw = 2000; + xga->lastline_draw = 0; + + xga->oddeven ^= 1; + + svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; + + if (xga->interlace && xga->oddeven) + xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); + else + xga->ma = xga->maback = xga->ma_latch; + + xga->ma = (xga->ma << 2); + xga->maback = (xga->maback << 2); + } + if (xga->vc == xga->v_total) { + xga->vc = 0; + xga->sc = 0; + xga->dispon = 1; + xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; + + svga->x_add = (overscan_x >> 1); + + xga->hwcursor_on = 0; + xga->hwcursor_latch = xga->hwcursor; } } - - xga->vc++; - xga->vc &= 0x7ff; - - if (xga->vc == xga->split) { - if (xga->interlace && xga->oddeven) - xga->ma = xga->maback = (xga->rowoffset << 1); - else - xga->ma = xga->maback = 0; - - xga->ma = (xga->ma << 2); - xga->maback = (xga->maback << 2); - - xga->sc = 0; - } - if (xga->vc == xga->dispend) { - xga->dispon = 0; - - for (x = 0; x < ((xga->vram_mask + 1) >> 12); x++) { - if (xga->changedvram[x]) - xga->changedvram[x]--; - } - if (svga->fullchange) - svga->fullchange--; - } - if (xga->vc == xga->v_syncstart) { - xga->dispon = 0; - svga->cgastat |= 8; - x = xga->h_disp; - - if (xga->interlace && !xga->oddeven) - xga->lastline++; - if (xga->interlace && xga->oddeven) - xga->firstline--; - - wx = x; - - wy = xga->lastline - xga->firstline; - svga_doblit(wx, wy, svga); - - xga->firstline = 2000; - xga->lastline = 0; - - xga->firstline_draw = 2000; - xga->lastline_draw = 0; - - xga->oddeven ^= 1; - - svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; - - if (xga->interlace && xga->oddeven) - xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); - else - xga->ma = xga->maback = xga->ma_latch; - - xga->ma = (xga->ma << 2); - xga->maback = (xga->maback << 2); - } - if (xga->vc == xga->v_total) { - xga->vc = 0; - xga->sc = 0; - xga->dispon = 1; - xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; - - svga->x_add = (overscan_x >> 1); - - xga->hwcursor_on = 0; - xga->hwcursor_latch = xga->hwcursor; - } - } + } else + svga_recalctimings(svga); } static uint8_t @@ -3285,6 +3324,7 @@ xga_reset(void *priv) xga->on = 0; xga->a5_test = 0; mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel); + svga_set_poll(svga); } static uint8_t From 9af10bdac39b4c36bb619bb922da253d6ecbce0a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 26 Jan 2025 15:42:03 +0100 Subject: [PATCH 0153/1190] More changes to the 5380 chips (January 26th, 2025) Apparently the Trantor T130B SCSI controllers has a different way of calculating the timings and removed the scsi_bus_read() calls from the Current SCSI bus status port (Read Port+4). Fixes NT using said controller as well as CD swapping while maintaining the correct accurate CD speed. --- src/include/86box/scsi_ncr5380.h | 1 + src/scsi/scsi_ncr5380.c | 9 +++------ src/scsi/scsi_ncr53c400.c | 30 ++++++++++++++++++++---------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 0b8a4efd8..5a43ba76a 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -74,6 +74,7 @@ typedef struct ncr_t { uint8_t output_data; uint8_t tx_data; uint8_t irq_state; + uint8_t isr_reg; uint8_t bus; diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 60f60473e..048194a96 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -195,7 +195,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 5: /* start DMA Send */ - pclog("Write: start DMA send register\n"); + ncr5380_log("Write: start DMA send register\n"); /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ scsi_bus->tx_mode = DMA_OUT_TX_BUS; if (ncr->dma_send_ext) @@ -238,7 +238,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr) } else ret = ncr->output_data; - ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x, txmode=%x.\n", CS, cpu_state.pc, ret, scsi_bus->clear_req, scsi_bus->wait_data, scsi_bus->tx_mode); + ncr5380_log("[%04X:%08X]: Data Bus Phase, CMDissued=%d, ret=%02x, clearreq=%d, waitdata=%x, txmode=%x.\n", CS, cpu_state.pc, scsi_bus->command_issued, ret, scsi_bus->clear_req, scsi_bus->wait_data, scsi_bus->tx_mode); } else { /*Return the data from the SCSI bus*/ bus = scsi_bus_read(scsi_bus); @@ -271,10 +271,6 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ret |= BUS_SEL; if (ncr->icr & ICR_BSY) ret |= BUS_BSY; - - /*Note by TC1995: Horrible hack, I know.*/ - (void) scsi_bus_read(scsi_bus); - (void) scsi_bus_read(scsi_bus); break; case 5: /* Bus and Status register */ @@ -319,6 +315,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ret |= STATUS_BUSY_ERROR; } ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); + ncr->isr_reg = ret; break; case 6: diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index a9d07af95..fcfda69e4 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -180,7 +180,10 @@ 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)); - timer_on_auto(&ncr400->timer, scsi_bus->period); + if (ncr400->type == ROM_T130B) + timer_on_auto(&ncr400->timer, 10.0); + else + timer_on_auto(&ncr400->timer, scsi_bus->period); 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 @@ -391,17 +394,20 @@ t130b_in(uint16_t port, void *priv) } static void -ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv), uint8_t val) +ncr53c400_dma_mode_ext(void *priv, void *ext_priv, uint8_t val) { + ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; scsi_bus_t *scsi_bus = &ncr->scsibus; /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - ncr53c400_log("NCR 53c400: BlockCountLoaded=%d, DMA mode enabled=%02x, valDMA=%02x.\n", ncr400->block_count_loaded, ncr->mode & MODE_DMA, val & MODE_DMA); - if (!(val & MODE_DMA) && (ncr->mode & MODE_DMA)) { - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - scsi_bus->tx_mode = PIO_TX_BUS; + ncr53c400_log("NCR 53c400: Loaded?=%d, DMA mode enabled=%02x, valDMA=%02x.\n", ncr400->block_count_loaded, ncr->mode & MODE_DMA, val & MODE_DMA); + if (!ncr400->block_count_loaded) { + if (!(val & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + scsi_bus->tx_mode = PIO_TX_BUS; + } } } @@ -417,8 +423,13 @@ ncr53c400_callback(void *priv) uint8_t temp; uint8_t status; - if (scsi_bus->tx_mode != PIO_TX_BUS) - timer_on_auto(&ncr400->timer, 1.0); + if (scsi_bus->tx_mode != PIO_TX_BUS) { + if (ncr400->type == ROM_T130B) { + ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 200.0); + timer_on_auto(&ncr400->timer, scsi_bus->period / 200.0); + } else + timer_on_auto(&ncr400->timer, 1.0); + } if (scsi_bus->data_wait & 1) { scsi_bus->clear_req = 3; @@ -727,7 +738,6 @@ ncr53c400_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 2.0; scsi_bus->multi = 1.750; - return ncr400; } From b141967a31fe929b60b3e92534fd7d27e05ffd19 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 26 Jan 2025 17:57:39 +0100 Subject: [PATCH 0154/1190] 8514/A and S3 minor change (January 26th, 2025) 1. Cosmetic changes. 2. Revert the position of the starting coordinates of the Short Stroke command, fixes some glitches in NT and elsewhere. --- src/video/vid_8514a.c | 18 +++++++++--------- src/video/vid_s3.c | 13 ++++++++----- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index d2e7efd8b..470642884 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -432,6 +432,14 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 2) { dev->accel.short_stroke = val; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; + if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); @@ -1139,16 +1147,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat the NOP command)*/ switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (dev->accel.ssv_state == 0) { - dev->accel.cx = dev->accel.cur_x; - if (dev->accel.cur_x >= 0x600) - dev->accel.cx |= ~0x5ff; - - dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_y >= 0x600) - dev->accel.cy |= ~0x5ff; + if (dev->accel.ssv_state == 0) break; - } if (dev->accel.cmd & 0x08) { while (count-- && dev->accel.ssv_len >= 0) { diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index bb5c283ad..7839a602a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -923,6 +923,9 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cmd & 0x1000) { s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); @@ -1785,6 +1788,9 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) s3->accel.short_stroke = val; s3->accel.ssv_state = 1; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cmd & 0x1000) { s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); @@ -7861,7 +7867,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi uint32_t srcbase; uint32_t dstbase; - if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (s3->accel.cmd & (1 << 11))) + if (((s3->chip >= S3_TRIO64) || (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) && (s3->accel.cmd & (1 << 11))) cmd |= 0x08; // SRC-BASE/DST-BASE @@ -7970,11 +7976,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (s3->accel.ssv_state == 0) { - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.ssv_state == 0) break; - } if (s3->accel.cmd & 0x08) { /*Radial*/ while (count-- && s3->accel.ssv_len >= 0) { From 8f5cf293bddd1fdba845806ff014780bdde3ef4b Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 27 Jan 2025 01:20:37 +0100 Subject: [PATCH 0155/1190] Assorted fixes, including warning message box for unavailable devices and translation fixes. --- src/device.c | 17 ++++++++++++++++- src/include/86box/nvr.h | 7 +++++-- src/include/86box/plat.h | 4 +--- src/include/86box/version.h.in | 4 ++++ src/qt/languages/86box.pot | 5 ++++- src/qt/languages/ca-ES.po | 15 ++++++++++++--- src/qt/languages/cs-CZ.po | 13 +++++++++++-- src/qt/languages/de-DE.po | 13 +++++++++++-- src/qt/languages/es-ES.po | 13 +++++++++++-- src/qt/languages/fi-FI.po | 17 +++++++++++++---- src/qt/languages/fr-FR.po | 13 +++++++++++-- src/qt/languages/hr-HR.po | 13 +++++++++++-- src/qt/languages/hu-HU.po | 13 +++++++++++-- src/qt/languages/it-IT.po | 12 ++++++++++++ src/qt/languages/ja-JP.po | 13 +++++++++++-- src/qt/languages/ko-KR.po | 13 +++++++++++-- src/qt/languages/nl-NL.po | 13 +++++-------- src/qt/languages/pl-PL.po | 25 +++++++++++++++++-------- src/qt/languages/pt-BR.po | 13 +++++-------- src/qt/languages/pt-PT.po | 13 +++++++++++-- src/qt/languages/ru-RU.po | 7 +++++-- src/qt/languages/sk-SK.po | 13 +++++++++++-- src/qt/languages/sl-SI.po | 15 ++++++++++++--- src/qt/languages/tr-TR.po | 13 +++++++++++-- src/qt/languages/uk-UA.po | 13 +++++++++++-- src/qt/languages/vi-VN.po | 13 +++++++++++-- src/qt/languages/zh-CN.po | 13 +++++++++++-- src/qt/languages/zh-TW.po | 13 +++++++++++-- src/qt/qt_platform.cpp | 3 ++- src/timer.c | 6 ++++-- 30 files changed, 282 insertions(+), 76 deletions(-) diff --git a/src/device.c b/src/device.c index 5b733df46..55552ead4 100644 --- a/src/device.c +++ b/src/device.c @@ -45,6 +45,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/ini.h> @@ -52,8 +53,10 @@ #include <86box/device.h> #include <86box/machine.h> #include <86box/mem.h> +#include <86box/plat.h> #include <86box/rom.h> #include <86box/sound.h> +#include <86box/ui.h> #define DEVICE_MAX 256 /* max # of devices */ @@ -155,6 +158,17 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) void *priv = NULL; int16_t c; + if (!device_available(dev)) { + wchar_t temp[512] = { 0 }; + swprintf(temp, sizeof_w(temp), + plat_get_string(STRING_HW_NOT_AVAILABLE_DEVICE), + dev->name); + ui_msgbox_header(MBX_INFO, + plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), + temp); + return ((void *) dev->name); + } + if (params != NULL) { init_dev = calloc(1, sizeof(device_t)); memcpy(init_dev, dev, sizeof(device_t)); @@ -171,7 +185,8 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) break; } if (c >= DEVICE_MAX) { - fatal("DEVICE: too many devices\n"); + fatal("Attempting to initialize more than the maximum " + "limit of %i devices\n", DEVICE_MAX); return NULL; } diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index c6dc08a12..0f7d22172 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -60,6 +60,7 @@ #define TIME_SYNC_ENABLED 1 #define TIME_SYNC_UTC 2 +#ifdef _TIMER_H_ /* Define a generic RTC/NVRAM device. */ typedef struct _nvr_ { char *fn; /* pathname of image file */ @@ -104,8 +105,6 @@ extern const device_t elt_nvr_device; extern void rtc_tick(void); extern void nvr_init(nvr_t *); -extern char *nvr_path(char *str); -extern FILE *nvr_fopen(char *str, char *mode); extern int nvr_load(void); extern void nvr_close(void); extern void nvr_set_ven_save(void (*ven_save)(void)); @@ -132,5 +131,9 @@ extern void nvr_irq_set(int irq, nvr_t *nvr); extern void nvr_smi_enable(int enable, nvr_t *nvr); extern uint8_t nvr_smi_status(nvr_t *nvr); extern void nvr_smi_status_clear(nvr_t *nvr); +#endif + +extern char *nvr_path(char *str); +extern FILE *nvr_fopen(char *str, char *mode); #endif /*EMU_NVR_H*/ diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 225c45ae1..f39f6ba51 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -47,6 +47,7 @@ enum { STRING_HW_NOT_AVAILABLE_MACHINE, /* "Machine \"%hs\" is not available..." */ STRING_HW_NOT_AVAILABLE_VIDEO, /* "Video card \"%hs\" is not available..." */ STRING_HW_NOT_AVAILABLE_VIDEO2, /* "Video card #2 \"%hs\" is not available..." */ + STRING_HW_NOT_AVAILABLE_DEVICE, /* "Device \"%hs\" is not available..." */ STRING_MONITOR_SLEEP, /* "Monitor in sleep mode" */ STRING_GHOSTPCL_ERROR_TITLE, /* "Unable to initialize GhostPCL" */ STRING_GHOSTPCL_ERROR_DESC /* "gpcl6dll32.dll/gpcl6dll64.dll/libgpcl6 is required..." */ @@ -187,9 +188,6 @@ extern void zip_reload(uint8_t id); extern void mo_eject(uint8_t id); extern void mo_mount(uint8_t id, char *fn, uint8_t wp); extern void mo_reload(uint8_t id); -extern int ioctl_open(uint8_t id, char d); -extern void ioctl_reset(uint8_t id); -extern void ioctl_close(uint8_t id); /* Other stuff. */ extern void startblit(void); diff --git a/src/include/86box/version.h.in b/src/include/86box/version.h.in index 5ebf7dba9..17c5b3068 100644 --- a/src/include/86box/version.h.in +++ b/src/include/86box/version.h.in @@ -14,6 +14,8 @@ * * Copyright 2020 Miran Grca. */ +#ifndef EMU_VERSION_H +#define EMU_VERSION_H #define _LSTR(s) L ## s #define LSTR(s) _LSTR(s) @@ -58,3 +60,5 @@ # define EMU_DOCS_URL "https://86box.readthedocs.io" #endif #define EMU_DOCS_URL_W LSTR(EMU_DOCS_URL) + +#endif /*EMU_VERSION_H*/ diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index c427d1300..ac2db7d07 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -687,7 +687,10 @@ msgstr "" msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "" -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "" + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." msgstr "" msgid "Machine" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index cf0556c36..e49ab3223 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -376,7 +376,7 @@ msgid "Time synchronization" msgstr "Sincronització horària" msgid "Disabled" -msgstr "Desactuvat" +msgstr "Deshabilitat" msgid "Enabled (local time)" msgstr "Activat (hora local)" @@ -687,8 +687,11 @@ msgstr "La màquina \"%hs\" no està disponible perquè falten ROM al directori msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "La targeta de vídeo \"%hs\" no està disponible perquè falten ROM al directori roms/video. Canvi a una targeta de vídeo disponible." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "La targeta de vídeo 2 \"%hs\" no està disponible perquè falten ROM al directori roms/video. Canvi a una targeta de vídeo disponible." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "La targeta de vídeo 2 \"%hs\" no està disponible perquè falten ROM al directori roms/video. Deshabilitant la segona targeta de vídeo." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "El dispositiu \"%hs\" no està disponible perquè falten ROM. Ignorant el dispositiu." msgid "Machine" msgstr "Màquina" @@ -2120,3 +2123,9 @@ msgstr "Clon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Frabricant" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Expansió de memòria genèrica PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Expansió de memòria genèrica PC/AT" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 070c8a0df..cafadd63b 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -687,8 +687,11 @@ msgstr "Počítač \"%hs\" není dostupný, jelikož chybí obraz jeho paměti R msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Video adaptér \"%hs\" není dostupný, jelikož chybí obraz jeho paměti ROM ve složce \"roms/video\". Konfigurace se přepne na jiný dostupný adaptér." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Video adaptér 2 \"%hs\" není dostupný, jelikož chybí obraz jeho paměti ROM ve složce \"roms/video\". Konfigurace se přepne na jiný dostupný adaptér." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Video adaptér 2 \"%hs\" není dostupný, jelikož chybí obraz jeho paměti ROM ve složce \"roms/video\". Druhá grafická karta se zakáže." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Zařízení \"%hs\" není dostupné, jelikož chybí obraz jeho paměti ROM. Zařízení je ignorováno." msgid "Machine" msgstr "Počítač" @@ -2120,3 +2123,9 @@ msgstr "Klon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Výrobce" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Obecné rozšíření paměti PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Obecné rozšíření paměti PC/AT" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index e94b8ebf4..aa666cc48 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -687,8 +687,11 @@ msgstr "Das System \"%hs\" ist aufgrund von fehlenden ROMs im Verzeichnis roms/m msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Die Videokarte \"%hs\" ist aufgrund von fehlenden ROMs im Verzeichnis roms/video nicht verfügbar. Es wird auf eine verfügbare Videokarte gewechselt." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Die Videokarte 2 \"%hs\" ist aufgrund von fehlenden ROMs im Verzeichnis roms/video nicht verfügbar. Es wird auf eine verfügbare Videokarte gewechselt." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Das Gerät \"%hs\" ist aufgrund von fehlenden ROMs nicht verfügbar. Es wird ignoriert." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Die Videokarte 2 \"%hs\" ist aufgrund von fehlenden ROMs im Verzeichnis roms/video nicht verfügbar. Es wird deaktiviert." msgid "Machine" msgstr "System" @@ -2123,3 +2126,9 @@ msgstr "IBM 8514/A-Klon (ISA)" msgid "Vendor" msgstr "Hersteller" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Generische PC/XT-Speichererweiterung" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Generische PC/AT-Speichererweiterung" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 7a457b225..5cac8968f 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -687,8 +687,11 @@ msgstr "La máquina \"%hs\" no está disponible debido a ROMs faltantes en el di msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "La tarjeta de vídeo \"%hs\" no está disponible debido a ROMs faltantes en el directorio roms/machines. Cambiando a una tarjeta de vídeo disponible." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "La tarjeta de vídeo 2 \"%hs\" no está disponible debido a ROMs faltantes en el directorio roms/machines. Cambiando a una tarjeta de vídeo disponible." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "La tarjeta de vídeo 2 \"%hs\" no está disponible debido a ROMs faltantes en el directorio roms/machines. Deshabilitanto la segunda tarjeta de vídeo." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "El dispositivo \"%hs\" no está disponible debido a ROMs faltantes. Ignorando el dispositivo." msgid "Machine" msgstr "Máquina" @@ -2119,3 +2122,9 @@ msgstr "Clon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Fabricante" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Expansión de Memoria Generica PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Expansión de Memoria Generica PC/AT" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 6aa71a867..21dcfd1bc 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -682,13 +682,16 @@ msgid "Surface images" msgstr "Pintalevykuvat" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "Konetta \"%hs\" ei voi käyttää puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen koneeseen." +msgstr "Konetta \"%hs\" ei voi käyttää, koska roms/machines-hakemistosta puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen koneeseen." msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Näytönohjainta \"%hs\" ei voi käyttää puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen näytönohjaimeen." +msgstr "Näytönohjainta \"%hs\" ei voi käyttää, koska roms/machines-hakemistosta puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen näytönohjaimeen." -msgid "Video card 2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Näytönohjainta 2 \"%hs\" ei voi käyttää puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen näytönohjaimeen." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgstr "Näytönohjainta 2 \"%hs\" ei voi käyttää, koska roms/machines-hakemistosta puuttuvien ROM-tiedostojen vuoksi. Toisen näytönohjaimen poistaminen käytöstä." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Laite \"%hs\" ei voi käyttää puuttuvien ROM-tiedostojen vuoksi. Laitteen huomiotta jättäminen." msgid "Machine" msgstr "Tietokone" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A-klooni (ISA)" msgid "Vendor" msgstr "Valmistaja" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Yleinen PC/XT-muistilaajennus" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Yleinen PC/AT-muistilaajennus" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index c8e4aa6cd..ff8a5168f 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -687,8 +687,11 @@ msgstr "La machine \"%hs\" n'est pas disponible en raison de l'absence de ROMs d msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "La carte vidéo \"%hs\" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/video. Basculer vers une carte vidéo disponible." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "La carte vidéo 2 \"%hs\" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/video. Basculer vers une carte vidéo disponible." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "La carte vidéo 2 \"%hs\" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/video. Désactiver la deuxième carte vidéo." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Le dispositif \"%hs\" n'est pas disponible en raison de l'absence de ROMs. Ignorer le dispositif." msgid "Machine" msgstr "Machine" @@ -2120,3 +2123,9 @@ msgstr "Clon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Fabricant" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Expansion de la mémoire générique PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Expansion de la mémoire générique PC/AT" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index c1c76f468..9d242f8e0 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -687,8 +687,11 @@ msgstr "Sistem \"%hs\" nije dostupan jer ne postoje potrebni ROM-ovi u mapu roms msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Video kartica \"%hs\" nije dostupna jer ne postoje potrebni ROM-ovi u mapu roms/video. Prebacivanje na dostupnu video karticu." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Video kartica 2 \"%hs\" nije dostupna jer ne postoje potrebni ROM-ovi u mapu roms/video. Prebacivanje na dostupnu video karticu." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Video kartica 2 \"%hs\" nije dostupna jer ne postoje potrebni ROM-ovi u mapu roms/video. Isključivanje druge video karice." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Uređaj \"%hs\" nije dostupan jer ne postoje potrebni ROM-ovi. Ignoriranje uređaja." msgid "Machine" msgstr "Sistem" @@ -2120,3 +2123,9 @@ msgstr "Klon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Proizvođać" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Generičko proširenje memorije PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Generičko proširenje memorije PC/AT" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 732a75df7..2b5adacf4 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -687,8 +687,11 @@ msgstr "A számítógép \"%hs\" nem elérhető a \"roms/machines\" mappából h msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "A videokártya \"%hs\" nem elérhető a \"roms/video\" mappából hiányzó ROM-képek miatt. Ehelyett egy másik kártya kerül futtatásra." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "A videokártya 2 \"%hs\" nem elérhető a \"roms/video\" mappából hiányzó ROM-képek miatt. Ehelyett egy másik kártya kerül futtatásra." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "A videokártya 2 \"%hs\" nem elérhető a \"roms/video\" mappából hiányzó ROM-képek miatt. A második videokártya kerül letiltásra." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Az eszköz \"%hs\" nem elérhető a hiányzó ROM-képek miatt. Az eszköz figyelmen kívül marad." msgid "Machine" msgstr "Számítógép" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A klón (ISA)" msgid "Vendor" msgstr "Gyártó" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Általános PC/XT memóriabővítők" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Általános PC/AT memóriabővítők" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 088b625af..c9af80127 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -687,6 +687,12 @@ msgstr "La macchina \"%hs\" non è disponibile a causa di immagini ROM mancanti msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "La scheda video \"%hs\" non è disponibile a causa di immagini ROM mancanti nella directory roms/video. Cambiando ad una scheda video disponibile." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "La scheda video 2 \"%hs\" non è disponibile a causa di immagini ROM mancanti nella directory roms/video. Disabilitando la seconda scheda video." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Il dispositivo \"%hs\" non è disponibile a causa di immagini ROM mancanti. Ignorando il dispositivo." + msgid "Machine" msgstr "Piastra madre" @@ -2117,3 +2123,9 @@ msgstr "Clone IBM 8514/A(ISA)" msgid "Vendor" msgstr "Fabricante" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Espansione di memoria generica PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Espansione di memoria generica PC/AT" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 8ad510745..9a3289b51 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -687,8 +687,11 @@ msgstr "roms/machines ディレクトリにROMがないため、マシン「%hs msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "roms/video ディレクトリにROMがないため、ビデオ カード「%hs」は使用できません。使用可能なビデオカードに切り替えます。" -msgid "Video card 2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "roms/video ディレクトリにROMがないため、ビデオ カード2「%hs」は使用できません。使用可能なビデオカードに切り替えます。" +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "roms/video ディレクトリにROMがないため、ビデオ カード2「%hs」は使用できません。2枚目のビデオカードを無効にします。" + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "ROMがないため、デバイス「%hs」は使用できません。装置を無視する。" msgid "Machine" msgstr "マシン" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A クローン(ISA)" msgid "Vendor" msgstr "業者" + +msgid "Generic PC/XT Memory Expansion" +msgstr "汎用PC/XTメモリ拡張カード" + +msgid "Generic PC/AT Memory Expansion" +msgstr "汎用PC/ATメモリ拡張カード" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 485789f56..c6928ad43 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -687,8 +687,11 @@ msgstr "roms/machines 디렉토리에 필요한 롬파일이 없어 기종 \"%hs msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "roms/video 디렉토리에 필요한 롬파일이 없어 비디오 카드 \"%hs\"을(를) 사용할 수 없습니다. 사용 가능한 기종으로 변경합니다." -msgid "Video card 2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "roms/video 디렉토리에 필요한 롬파일이 없어 비디오 카드 2 \"%hs\"을(를) 사용할 수 없습니다. 사용 가능한 기종으로 변경합니다." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "roms/video 디렉토리에 필요한 롬파일이 없어 비디오 카드 2 \"%hs\"을(를) 사용할 수 없습니다. 두 번째 비디오 카드를 비활성화합니다." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "필요한 롬파일이 없어 장치 \"%hs\"을(를) 사용할 수 없습니다. 장치를 무시합니다." msgid "Machine" msgstr "기종" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A 클론(ISA)" msgid "Vendor" msgstr "제조사" + +msgid "Generic PC/XT Memory Expansion" +msgstr "일반 PC/XT 메모리 확장 카드" + +msgid "Generic PC/AT Memory Expansion" +msgstr "일반 PC/AT 메모리 확장 카드" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index b54bc1cb0..27870db90 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -687,8 +687,11 @@ msgstr "Machine \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Videokaart \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Overschakel over naar een beschikbare videokaart." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Videokaart #2 \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Overschakel over naar een beschikbare videokaart." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Videokaart #2 \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Uitschakel de tweede videokaart." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Het apparaat \"%hs\" is niet beschikbaar door ontbrekende ROMs. Negeer het apparaat." msgid "Machine" msgstr "Machine" @@ -2121,12 +2124,6 @@ msgstr "IBM 8514/A-kloon (ISA)" msgid "Vendor" msgstr "Verkoper" -msgid "30 Hz (JMP2 = 1)" -msgstr "30 Hz (JMP2 = 1)" - -msgid "60 Hz (JMP2 = 2)" -msgstr "60 Hz (JMP2 = 2)" - msgid "Generic PC/XT Memory Expansion" msgstr "Generieke PC/XT geheugenuitbreiding" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 9fa67bf9e..e42904458 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -687,8 +687,11 @@ msgstr "Maszyna \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w kat msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Karta wideo \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Przełączanie na dostępną kartę wideo." -msgid "Video card 2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Karta wideo 2 \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Przełączanie na dostępną kartę wideo." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Karta wideo 2 \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Wyłączenie drugiej karty graficznej." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Urządzenie \"%hs\" nie jest dostępne, ponieważ brakuje obrazów ROM. Ignorowanie urządzenia." msgid "Machine" msgstr "Maszyna" @@ -871,10 +874,10 @@ msgid "Invalid configuration" msgstr "Nieprawidłowa konfiguracja" msgid "%1 is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -msgstr "%1 jest wymagany do automatycznej konwersji plików PostScript do PDF.\n\nDokumenty wysłane do ogólnej drukarki PostScript zostaną zapisane jako pliki PostScript (.ps)." +msgstr "%1 jest wymagany do automatycznej konwersji plików PostScript do PDF.\n\nDokumenty wysłane do generycznej drukarki PostScript zostaną zapisane jako pliki PostScript (.ps)." msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." -msgstr "%1 jest wymagany do automatycznej konwersji plików PCL do PDF.\n\nDokumenty wysłane do ogólnej drukarki PCL zostaną zapisane jako pliki Printer Command Language (.pcl)." +msgstr "%1 jest wymagany do automatycznej konwersji plików PCL do PDF.\n\nDokumenty wysłane do generycznej drukarki PCL zostaną zapisane jako pliki Printer Command Language (.pcl)." msgid "Entering fullscreen mode" msgstr "Przechodzenie do trybu pełnoekranowego" @@ -1942,7 +1945,7 @@ msgid "New" msgstr "Nowość" msgid "Color (generic)" -msgstr "Kolor (ogólny)" +msgstr "Kolor (generyczny)" msgid "Green Monochrome" msgstr "Zielony monochromatyczny" @@ -2056,16 +2059,16 @@ msgid "Stereo LPT DAC" msgstr "Stereofoniczny przetwornik cyfrowo-analogowy LPT" msgid "Generic Text Printer" -msgstr "Ogólna drukarka tekstowa" +msgstr "Generyczna drukarka tekstowa" msgid "Generic ESC/P Dot-Matrix Printer" msgstr "Generyczna drukarka igłowa ESC/P" msgid "Generic PostScript Printer" -msgstr "Ogólna drukarka PostScript" +msgstr "Generyczna drukarka PostScript" msgid "Generic PCL5e Printer" -msgstr "Drukarka PCL5e" +msgstr "Generyczna drukarka PCL5e" msgid "Parallel Line Internet Protocol" msgstr "Protokół internetowy linii równoległej" @@ -2120,3 +2123,9 @@ msgstr "Klon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Producent" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Generyczne rozszerzenie pamięci PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Generyczne rozszerzenie pamięci PC/AT" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index c9ff9615b..de1bcd544 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -687,8 +687,11 @@ msgstr "A máquina \"%hs\" não está disponível devido à falta de ROMs no dir msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "A placa de vídeo \"%hs\" não está disponível devido à falta de ROMs no diretório roms/video. Mudando para uma placa de vídeo disponível." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "A placa de vídeo 2 \"%hs\" não está disponível devido à falta de ROMs no diretório roms/video. Mudando para uma placa de vídeo disponível." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "A placa de vídeo 2 \"%hs\" não está disponível devido à falta de ROMs no diretório roms/video. Desativando a segunda placa vídeo." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "O dispositivo \"%hs\" não está disponível devido à falta de ROMs. Ignorando o dispositivo." msgid "Machine" msgstr "Máquina" @@ -2121,12 +2124,6 @@ msgstr "Clone IBM 8514/A (ISA)" msgid "Vendor" msgstr "Fabricante" -msgid "30 Hz (JMP2 = 1)" -msgstr "30 Hz (JMP2 = 1)" - -msgid "60 Hz (JMP2 = 2)" -msgstr "60 Hz (JMP2 = 2)" - msgid "Generic PC/XT Memory Expansion" msgstr "Expansão de memória genérica PC/XT" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 1494ce1dc..d4c8bf170 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -687,8 +687,11 @@ msgstr "A máquina \"%hs\" não está disponível devido à falta de ROMs na pas msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "A placa vídeo \"%hs\" não está disponível devido à falta de ROMs na pasta roms/video. A mudar para uma placa vídeo disponível." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "A placa vídeo 2 \"%hs\" não está disponível devido à falta de ROMs na pasta roms/video. A mudar para uma placa vídeo disponível." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "A placa vídeo 2 \"%hs\" não está disponível devido à falta de ROMs na pasta roms/video. A desativar a segunda placa vídeo." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "O dispositivo \"%hs\" não está disponível devido à falta de ROMs A ignorar o dispositivo." msgid "Machine" msgstr "Máquina" @@ -2120,3 +2123,9 @@ msgstr "Clone IBM 8514/A (ISA)" msgid "Vendor" msgstr "Fabricante" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Expansão de memória genérica PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Expansão de memória genérica PC/AT" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 8476090d1..e6405ab79 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -687,8 +687,11 @@ msgstr "Системная плата \"%hs\" недоступна из-за о msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Видеокарта \"%hs\" недоступна из-за отсутствия файла её ПЗУ в каталоге roms/video. Переключение на доступную видеокарту." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Видеокарта 2 \"%hs\" недоступна из-за отсутствия файла её ПЗУ в каталоге roms/video. Переключение на доступную видеокарту." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Видеокарта 2 \"%hs\" недоступна из-за отсутствия файла её ПЗУ в каталоге roms/video. Отключение второй видеокарты." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Устройство \"%hs\" недоступно из-за отсутствия файла его ПЗУ. Игнорирование устройства." msgid "Machine" msgstr "Компьютер" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 708c24dd8..6b2074d47 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -687,8 +687,11 @@ msgstr "Počítač \"%hs\" ie je dostupný, pretože chýba obraz jeho pamäte R msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Video adaptér \"%hs\" nie je dostupný, pretože chýba obraz jeho pamäte ROM v zložke \"roms/video\". Konfigurácia sa prepne na iný dostupný adaptér." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Video adaptér 2 \"%hs\" nie je dostupný, pretože chýba obraz jeho pamäte ROM v zložke \"roms/video\". Konfigurácia sa prepne na iný dostupný adaptér." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Video adaptér 2 \"%hs\" nie je dostupný, pretože chýba obraz jeho pamäte ROM v zložke \"roms/video\". Druhá grafická karta sa zakáže." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Zariadenie \"%hs\" nie je dostupné, pretože chýba obraz jeho pamäte ROM. Zariadenie sa ignoruje." msgid "Machine" msgstr "Počítač" @@ -2120,3 +2123,9 @@ msgstr "Klon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Výrobca" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Všeobecné rozšírenie pamäte PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Všeobecné rozšírenie pamäte PC/AT" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index c9c99d6b2..9d8ccaaf9 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -685,10 +685,13 @@ msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines msgstr "Sistem \"%hs\" ni na voljo zaradi manjkajočih ROM-ov v mapi roms/machines. Preklapljam na drug sistem, ki je na voljo." msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Grafična kartica \"%hs\" ni na voljo zaradi manjkajočih ROM-ov v mapi roms/video. Preklapljam na drugo grafično kartico, ki je na voljo.." +msgstr "Grafična kartica \"%hs\" ni na voljo zaradi manjkajočih ROM-ov v mapi roms/video. Preklapljam na drugo grafično kartico, ki je na voljo." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Grafična kartica 2 \"%hs\" ni na voljo zaradi manjkajočih ROM-ov v mapi roms/video. Preklapljam na drugo grafično kartico, ki je na voljo.." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Grafična kartica 2 \"%hs\" ni na voljo zaradi manjkajočih ROM-ov v mapi roms/video. Onemogočam drugo grafično kartico." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Naprava \"%hs\" ni na voljo zaradi manjkajočih ROM-ov. Preziram napravo." msgid "Machine" msgstr "Sistem" @@ -2120,3 +2123,9 @@ msgstr "Klon IBM 8514/A (ISA)" msgid "Vendor" msgstr "Proizvajalec" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Generična razširitev pomnilnika PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Generična razširitev pomnilnika PC/AT" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 3a0cc2b96..288412154 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -687,8 +687,11 @@ msgstr "\"%hs\" makinesi roms/machines klasöründe gerekli ROM imajlarının me msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "\"%hs\" ekran kartı roms/video klasöründe gerekli ROM imajlarının mevcut olmaması nedeniyle kullanılamıyor. Bundan dolayı kullanılabilen bir ekran kartına geçiş yapılacaktır." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "\"%hs\" ikinci ekran kartı roms/video klasöründe gerekli ROM imajlarının mevcut olmaması nedeniyle kullanılamıyor. Bundan dolayı kullanılabilen bir ekran kartına geçiş yapılacaktır." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "\"%hs\" ikinci ekran kartı roms/video klasöründe gerekli ROM imajlarının mevcut olmaması nedeniyle kullanılamıyor. İkinci ekran kartı devre dışı bırakılır." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "\"%hs\" cihazı gerekli ROM imajlarının mevcut olmaması nedeniyle kullanılamıyor. Cihaz yok sayılıyor." msgid "Machine" msgstr "Makine" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A klonu (ISA)" msgid "Vendor" msgstr "Üretici" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Sıradan PC/XT bellek artırma" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Sıradan PC/AT bellek artırma" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 6cef7c294..5ce59be01 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -687,8 +687,11 @@ msgstr "Системна плата \"%hs\" недоступна через ві msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Відеокарта \"%hs\" недоступна через відсутність файлу її ПЗУ в каталозі roms/video. Переключення на доступну відеокарту." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Відеокарта 2 \"%hs\" недоступна через відсутність файлу її ПЗУ в каталозі roms/video. Переключення на доступну відеокарту." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Відеокарта 2 \"%hs\" недоступна через відсутність файлу її ПЗУ в каталозі roms/video. Відключення другої відеокарти." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Пристрій \"%hs\" недоступний через відсутність файлу його ПЗУ. Ігнорування пристрою." msgid "Machine" msgstr "Комп'ютер" @@ -2126,3 +2129,9 @@ msgstr "30 Гц (JMP2 = 1)" msgid "60 Hz (JMP2 = 2)" msgstr "60 Гц (JMP2 = 2)" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Загальне розширення пам'яті PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Загальне розширення пам'яті PC/AT" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 15802fc2d..707c7ae7f 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -687,8 +687,11 @@ msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tươ msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Vô hiệu hóa card đồ họa thứ hai." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Thiết bị \"%hs\" không giả lập được do thiếu file ROM. Bỏ qua thiết bị." msgid "Machine" msgstr "Mẫu máy" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A dòng vô tính (ISA)" msgid "Vendor" msgstr "Nhà sản xuất" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Chung mở rộng bộ nhớ qua PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Chung mở rộng bộ nhớ qua PC/AT" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 6b659b504..81451b2b3 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -687,8 +687,11 @@ msgstr "由于 roms/machines 文件夹中缺少合适的 ROM,机型 \"%hs\" msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "由于 roms/video 文件夹中缺少合适的 ROM,显卡 \"%hs\" 不可用。将切换到其他可用显卡。" -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "由于 roms/video 文件夹中缺少合适的 ROM,显卡 2 \"%hs\" 不可用。将切换到其他可用显卡。" +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "由于 roms/video 文件夹中缺少合适的 ROM,显卡 2 \"%hs\" 不可用。禁用第二块显卡。" + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "由于缺少合适的 ROM,设备 \"%hs\" 不可用。忽略设备。" msgid "Machine" msgstr "机型" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A 克隆 (ISA)" msgid "Vendor" msgstr "制造商" + +msgid "Generic PC/XT Memory Expansion" +msgstr "通用 PC/XT 内存扩展" + +msgid "Generic PC/AT Memory Expansion" +msgstr "通用 PC/AT 内存扩展" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index f9e917d98..9bf8edfc6 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -687,8 +687,11 @@ msgstr "由於 roms/machines 資料夾中缺少合適的 ROM,機型 \"%hs\" msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "由於 roms/video 資料夾中缺少合適的 ROM,顯示卡 \"%hs\" 不可用。將切換到其他可用顯示卡。" -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "由於 roms/video 資料夾中缺少合適的 ROM,顯示卡 2 \"%hs\" 不可用。將切換到其他可用顯示卡。" +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "由於 roms/video 資料夾中缺少合適的 ROM,顯示卡 2 \"%hs\" 不可用。禁用第二块显卡。" + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "由於缺少合適的 ROM,裝置 \"%hs\" 不可用。忽略设备。" msgid "Machine" msgstr "機型" @@ -2120,3 +2123,9 @@ msgstr "IBM 8514/A 克隆 (ISA)" msgid "Vendor" msgstr "製造商" + +msgid "Generic PC/XT Memory Expansion" +msgstr "通用 PC/XT 記憶體擴充" + +msgid "Generic PC/AT Memory Expansion" +msgstr "通用 PC/AT 記憶體擴充" diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 6b8b44405..a0ef86533 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -632,7 +632,8 @@ ProgSettings::reloadStrings() translatedstrings[STRING_GHOSTPCL_ERROR_DESC] = QCoreApplication::translate("", "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files.").arg(LIB_NAME_GPCL).toStdWString(); translatedstrings[STRING_HW_NOT_AVAILABLE_MACHINE] = QCoreApplication::translate("", "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.").toStdWString(); translatedstrings[STRING_HW_NOT_AVAILABLE_VIDEO] = QCoreApplication::translate("", "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card.").toStdWString(); - translatedstrings[STRING_HW_NOT_AVAILABLE_VIDEO2] = QCoreApplication::translate("", "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.").toStdWString(); + translatedstrings[STRING_HW_NOT_AVAILABLE_VIDEO2] = QCoreApplication::translate("", "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.").toStdWString(); + translatedstrings[STRING_HW_NOT_AVAILABLE_DEVICE] = QCoreApplication::translate("", "Device \"%hs\" is not available due to missing ROMs. Ignoring the device.").toStdWString(); translatedstrings[STRING_HW_NOT_AVAILABLE_TITLE] = QCoreApplication::translate("", "Hardware not available").toStdWString(); translatedstrings[STRING_MONITOR_SLEEP] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString(); translatedstrings[STRING_NET_ERROR] = QCoreApplication::translate("", "Failed to initialize network driver").toStdWString(); diff --git a/src/timer.c b/src/timer.c index a3a7c9efb..9fed37511 100644 --- a/src/timer.c +++ b/src/timer.c @@ -31,7 +31,8 @@ timer_enable(pc_timer_t *timer) timer_disable(timer); if (timer->next || timer->prev) - fatal("timer_enable - timer->next\n"); + fatal("timer_disable(): Attempting to enable a non-isolated " + "timer incorrectly marked as disabled\n"); /*List currently empty - add to head*/ if (!timer_head) { @@ -92,7 +93,8 @@ timer_disable(pc_timer_t *timer) return; if (!timer->next && !timer->prev && timer != timer_head) - fatal("timer_disable - !timer->next\n"); + fatal("timer_disable(): Attempting to disable an isolated " + "non-head timer incorrectly marked as enabled\n"); timer->flags &= ~TIMER_ENABLED; timer->in_callback = 0; From f85e7debde395043d3e8389f71d5a1218c50a8fb Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 27 Jan 2025 01:48:14 +0100 Subject: [PATCH 0156/1190] Russian translation fixes by lemondrops. --- src/qt/languages/ru-RU.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index e6405ab79..a2e352faa 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -688,10 +688,10 @@ msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video msgstr "Видеокарта \"%hs\" недоступна из-за отсутствия файла её ПЗУ в каталоге roms/video. Переключение на доступную видеокарту." msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." -msgstr "Видеокарта 2 \"%hs\" недоступна из-за отсутствия файла её ПЗУ в каталоге roms/video. Отключение второй видеокарты." +msgstr "Видеокарта 2 \"%hs\" недоступна из-за отсутствия файла её ПЗУ в каталоге roms/video. Вторая видеокарта отключена." msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." -msgstr "Устройство \"%hs\" недоступно из-за отсутствия файла его ПЗУ. Игнорирование устройства." +msgstr "Устройство \"%hs\" недоступно из-за отсутствия файла его ПЗУ. Устройство проигнорировано." msgid "Machine" msgstr "Компьютер" From 2753a8e4bfc20ff9adb2c4924c8b5eb2236fcef4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 27 Jan 2025 09:54:39 +0100 Subject: [PATCH 0157/1190] Radisys EPC-2102: Move it to among the 430HX machines, where it should be. --- 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 2a50159e9..8ea850610 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11791,6 +11791,46 @@ const machine_t machines[] = { .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, + /* Unknown PS/2 KBC. */ + { + .name = "[i430HX] Radisys EPC-2102", + .internal_name = "epc2102", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_epc2102_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 83333333, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .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 + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . @@ -12448,46 +12488,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Unknown PS/2 KBC. */ - { - .name = "[i430HX] Radisys EPC-2102", - .internal_name = "epc2102", - .type = MACHINE_TYPE_SOCKET7, - .chipset = MACHINE_CHIPSET_INTEL_430HX, - .init = machine_at_epc2102_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 83333333, - .min_voltage = 2500, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 3.0 - }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, - .ram = { - .min = 8192, - .max = 262144, - .step = 8192 - }, - .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 - }, /* This has a Holtek KBC and the BIOS does not send a single non-standard KBC command, so it must be an ASIC that clones the standard IBM PS/2 KBC. */ { From f78403ffe537d02b2a4a79d29d1edc1fe0ed5a56 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Mon, 27 Jan 2025 12:01:23 +0300 Subject: [PATCH 0158/1190] Add the PC Partner VIA809DS (Socket 7 D.V./VIA VP3) --- src/include/86box/machine.h | 1 + src/machine/m_at_socket7.c | 32 +++++++++++++++++++++++++++ src/machine/machine_table.c | 43 ++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b0365314e..f4f3f8834 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -746,6 +746,7 @@ extern int machine_at_tomahawk_init(const machine_t *); extern int machine_at_ficva502_init(const machine_t *); extern int machine_at_ficpa2012_init(const machine_t *); +extern int machine_at_via809ds_init(const machine_t *); extern int machine_at_r534f_init(const machine_t *); extern int machine_at_ms5146_init(const machine_t *); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 2dbb83684..14b641540 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1271,6 +1271,38 @@ machine_at_ficpa2012_init(const machine_t *model) return ret; } +int +machine_at_via809ds_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/via809ds/v30422sg.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); /* assumed */ + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + + device_add(&via_vp3_device); + device_add(&via_vt82c586b_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c669_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 512); + + return ret; +} + int machine_at_r534f_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8ea850610..bad86a786 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13063,7 +13063,48 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ + { + .name = "[VIA VP3] PC Partner VIA809DS", + .internal_name = "via809ds", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_VP3, + .init = machine_at_via809ds_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2100, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .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 + }, + /* SiS 5571 */ /* Has the SiS 5571 chipset with on-chip KBC. */ { From 90e1190c9262bef735ee0dbfb3827242dab4ad53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 16:26:28 +0100 Subject: [PATCH 0159/1190] The great CD-ROM clean-up and rewrite, fixes #5134. --- src/cdrom/CMakeLists.txt | 4 +- src/cdrom/cdrom.c | 3556 +++++++++++++---------- src/cdrom/cdrom_image.c | 2176 ++++++++++++-- src/cdrom/cdrom_image_backend.c | 1499 ---------- src/cdrom/cdrom_image_viso.c | 138 +- src/cdrom/cdrom_ioctl.c | 267 -- src/cdrom/cdrom_mitsumi.c | 8 - src/config.c | 128 +- src/disk/hdc_esdi_at.c | 2 +- src/disk/hdc_esdi_mca.c | 2 +- src/disk/hdc_ide.c | 32 +- src/disk/hdc_ide_sff8038i.c | 11 +- src/disk/hdc_st506_at.c | 2 +- src/disk/hdc_st506_xt.c | 2 +- src/disk/hdc_xta.c | 2 +- src/disk/hdd.c | 2 +- src/disk/mo.c | 1551 +++++----- src/disk/zip.c | 1758 +++++------ src/include/86box/cdrom.h | 554 ++-- src/include/86box/cdrom_image.h | 40 +- src/include/86box/cdrom_image_backend.h | 119 - src/include/86box/cdrom_image_viso.h | 26 + src/include/86box/cdrom_interface.h | 14 +- src/include/86box/cdrom_ioctl.h | 32 - src/include/86box/hdc.h | 5 - src/include/86box/hdc_ide.h | 15 +- src/include/86box/hdd.h | 2 +- src/include/86box/log.h | 23 +- src/include/86box/mo.h | 122 +- src/include/86box/plat_cdrom.h | 73 - src/include/86box/plat_cdrom_ioctl.h | 34 + src/include/86box/scsi.h | 18 +- src/include/86box/scsi_cdrom.h | 67 +- src/include/86box/scsi_device.h | 183 +- src/include/86box/scsi_disk.h | 54 +- src/include/86box/zip.h | 107 +- src/log.c | 353 ++- src/machine/m_ps1_hdc.c | 2 +- src/qt/dummy_cdrom_ioctl.c | 292 +- src/qt/qt_machinestatus.cpp | 4 +- src/qt/qt_mediamenu.cpp | 27 +- src/qt/qt_settingsfloppycdrom.cpp | 43 +- src/qt/qt_settingsharddisks.cpp | 24 +- src/qt/win_cdrom_ioctl.c | 952 +++--- src/scsi/scsi_cdrom.c | 3214 +++++++++----------- src/scsi/scsi_disk.c | 1040 +++---- src/sound/snd_sb.c | 4 +- src/unix/dummy_cdrom_ioctl.c | 292 +- 48 files changed, 9486 insertions(+), 9389 deletions(-) delete mode 100644 src/cdrom/cdrom_image_backend.c delete mode 100644 src/cdrom/cdrom_ioctl.c delete mode 100644 src/include/86box/cdrom_image_backend.h create mode 100644 src/include/86box/cdrom_image_viso.h delete mode 100644 src/include/86box/cdrom_ioctl.h delete mode 100644 src/include/86box/plat_cdrom.h create mode 100644 src/include/86box/plat_cdrom_ioctl.h diff --git a/src/cdrom/CMakeLists.txt b/src/cdrom/CMakeLists.txt index 2f0f1cd23..621b069b0 100644 --- a/src/cdrom/CMakeLists.txt +++ b/src/cdrom/CMakeLists.txt @@ -21,10 +21,8 @@ pkg_check_modules(SNDFILE REQUIRED IMPORTED_TARGET sndfile) add_library(cdrom OBJECT cdrom.c - cdrom_image_backend.c - cdrom_image_viso.c cdrom_image.c - cdrom_ioctl.c + cdrom_image_viso.c ) target_link_libraries(86Box PkgConfig::SNDFILE) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 6d993f24a..5ddd788cb 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -15,105 +15,90 @@ * Copyright 2018-2021 Miran Grca. */ #include +#ifdef ENABLE_CDROM_LOG #include +#endif #include #include #include #include -#include -#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/config.h> #include <86box/cdrom.h> #include <86box/cdrom_image.h> #include <86box/cdrom_interface.h> -#include <86box/cdrom_mitsumi.h> +#include <86box/log.h> #include <86box/plat.h> +#include <86box/plat_cdrom_ioctl.h> #include <86box/scsi.h> #include <86box/scsi_device.h> +#include <86box/scsi_cdrom.h> #include <86box/sound.h> - -/* 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. */ -#undef MSFtoLBA -#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) +#include <86box/ui.h> #define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 #define MIN_SEEK 2000 #define MAX_SEEK 333333 -#pragma pack(push, 1) -typedef struct { - uint8_t user_data[2048], - ecc[288]; -} m1_data_t; - -typedef struct { - uint8_t sub_header[8], - user_data[2328]; -} m2_data_t; - -typedef union { - m1_data_t m1_data; - m2_data_t m2_data; - uint8_t raw_data[2336]; -} sector_data_t; - -typedef struct { - uint8_t sync[12]; - uint8_t header[4]; - sector_data_t data; -} sector_raw_data_t; - -typedef union { - sector_raw_data_t sector_data; - uint8_t raw_data[2352]; -} sector_t; - -typedef struct { - sector_t sector; - uint8_t c2[296]; - uint8_t subchannel_raw[96]; - uint8_t subchannel_q[16]; - uint8_t subchannel_rw[96]; -} cdrom_sector_t; - -typedef union { - cdrom_sector_t cdrom_sector; - uint8_t buffer[2856]; -} sector_buffer_t; -#pragma pack(pop) - static int cdrom_sector_size; -static uint8_t raw_buffer[2856]; /* Needs to be the same size as sector_buffer_t in the structs. */ +/* Needs some extra breathing space in case of overflows. */ +static uint8_t raw_buffer[4096]; static uint8_t extra_buffer[296]; -cdrom_t cdrom[CDROM_NUM]; +cdrom_t cdrom[CDROM_NUM] = { 0 }; int cdrom_interface_current; #ifdef ENABLE_CDROM_LOG int cdrom_do_log = ENABLE_CDROM_LOG; -void -cdrom_log(const char *fmt, ...) +static void +cdrom_log(void *priv, const char *fmt, ...) { - va_list ap; - if (cdrom_do_log) { + va_list ap; va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define cdrom_log(fmt, ...) +# define cdrom_log(priv, fmt, ...) #endif +static void process_mode1(const cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b); +static void process_mode2_non_xa(const cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b); +static void process_mode2_xa_form1(const cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b); +static void process_mode2_xa_form2(const cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b); + +typedef void (*cdrom_process_data_t)(const cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b); + +static cdrom_process_data_t cdrom_process_data[4] = { process_mode1, process_mode2_non_xa, + process_mode2_xa_form1, process_mode2_xa_form2 }; +#ifdef ENABLE_CDROM_LOG +static char * cdrom_req_modes[14] = { "Any", "Audio", "Mode 1", "Mode 2", + "CD-I/XA Mode 2 Form 1", "CD-I/XA Mode 2 Form 2", "Unk", "Unk", + "Any Data", "Any Data - 4", + "CD-I/XA Mode 2 Form 1", "CD-I/XA Mode 2 Form 1 - 4", + "Any CD-I/XA Data", "Any CD-I/XA Data - 4" }; +static char * cdrom_modes[4] = { "Mode 1", "Mode 2", "CD-I/XA Mode 2 Form 1", "CD-I/XA Mode 2 Form 2" }; +#endif +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 int mult = 1; +static int part = 0; +static int ecc_diff = 288; + static const device_t cdrom_interface_none_device = { .name = "None", .internal_name = "none", @@ -137,146 +122,57 @@ static const struct { // clang-format on }; -/* Reset the CD-ROM Interface, whichever one that is. */ -void -cdrom_interface_reset(void) +/* Private functions. */ +static void +cdrom_generate_name(const int type, char *name, const int internal) { - cdrom_log("CD-ROM Interface: reset(current=%d)\n", - cdrom_interface_current); + char elements[3][2048] = { 0 }; - /* If we have a valid controller, add its device. */ - if ((cdrom_interface_current > 0) && controllers[cdrom_interface_current].device) - device_add(controllers[cdrom_interface_current].device); -} + memcpy(elements[0], cdrom_drive_types[type].vendor, + strlen(cdrom_drive_types[type].vendor) + 1); + if (internal) for (int i = 0; i < strlen(elements[0]); i++) + if (elements[0][i] == ' ') + elements[0][i] = '_'; -const char * -cdrom_interface_get_internal_name(int cdinterface) -{ - return device_get_internal_name(controllers[cdinterface].device); -} + if (internal) { + int j = 0; + for (int i = 0; i <= strlen(cdrom_drive_types[type].model); i++) + if (cdrom_drive_types[type].model[i] != ':') + elements[1][j++] = cdrom_drive_types[type].model[i]; + } else + memcpy(elements[1], cdrom_drive_types[type].model, + strlen(cdrom_drive_types[type].model) + 1); + char *s = strstr(elements[1], " "); + if (s != NULL) + s[0] = 0x00; + if (internal) for (int i = 0; i < strlen(elements[1]); i++) + if (elements[1][i] == ' ') + elements[1][i] = '_'; -int -cdrom_interface_get_from_internal_name(char *s) -{ - int c = 0; + memcpy(elements[2], cdrom_drive_types[type].revision, + strlen(cdrom_drive_types[type].revision) + 1); + s = strstr(elements[2], " "); + if (s != NULL) + s[0] = 0x00; + if (internal) for (int i = 0; i < strlen(elements[2]); i++) + if (elements[2][i] == ' ') + elements[2][i] = '_'; - while (controllers[c].device != NULL) { - if (!strcmp(controllers[c].device->internal_name, s)) - return c; - c++; - } - - return 0; -} - -const device_t * -cdrom_interface_get_device(int cdinterface) -{ - return (controllers[cdinterface].device); -} - -int -cdrom_interface_has_config(int cdinterface) -{ - const device_t *dev = cdrom_interface_get_device(cdinterface); - - if (dev == NULL) - return 0; - - if (!device_has_config(dev)) - return 0; - - return 1; -} - -int -cdrom_interface_get_flags(int cdinterface) -{ - return (controllers[cdinterface].device->flags); -} - -int -cdrom_interface_available(int cdinterface) -{ - return (device_available(controllers[cdinterface].device)); -} - -char * -cdrom_getname(int type) -{ - return (char *) cdrom_drive_types[type].name; -} - -char * -cdrom_get_internal_name(int type) -{ - return (char *) cdrom_drive_types[type].internal_name; -} - -int -cdrom_get_from_internal_name(char *s) -{ - int c = 0; - - while (strlen(cdrom_drive_types[c].internal_name)) { - if (!strcmp((char *) cdrom_drive_types[c].internal_name, s)) - return c; - c++; - } - - return 0; -} - -void -cdrom_set_type(int model, int type) -{ - cdrom[model].type = type; -} - -int -cdrom_get_type(int model) -{ - return cdrom[model].type; -} - -static __inline int -bin2bcd(int x) -{ - return (x % 10) | ((x / 10) << 4); -} - -static __inline int -bcd2bin(int x) -{ - return (x >> 4) * 10 + (x & 0x0f); -} - -int -cdrom_lba_to_msf_accurate(int lba) -{ - int pos; - int m; - int s; - int f; - - pos = lba + 150; - f = pos % 75; - pos -= f; - pos /= 75; - s = pos % 60; - pos -= s; - pos /= 60; - m = pos; - - return ((m << 16) | (s << 8) | f); + if (internal) + sprintf(name, "%s_%s_%s", elements[0], elements[1], elements[2]); + else if (cdrom_drive_types[type].speed == -1) + sprintf(name, "%s %s %s", elements[0], elements[1], elements[2]); + else + sprintf(name, "%s %s %s (%ix)", elements[0], elements[1], + elements[2], cdrom_drive_types[type].speed); } static double -cdrom_get_short_seek(cdrom_t *dev) +cdrom_get_short_seek(const cdrom_t *dev) { switch (dev->cur_speed) { case 0: - fatal("CD-ROM %i: 0x speed\n", dev->id); + log_fatal(dev->log, "0x speed\n"); return 0.0; case 1: return 240.0; @@ -324,11 +220,11 @@ cdrom_get_short_seek(cdrom_t *dev) } static double -cdrom_get_long_seek(cdrom_t *dev) +cdrom_get_long_seek(const cdrom_t *dev) { switch (dev->cur_speed) { case 0: - fatal("CD-ROM %i: 0x speed\n", dev->id); + log_fatal(dev->log, "0x speed\n"); return 0.0; case 1: return 1446.0; @@ -375,113 +271,6 @@ cdrom_get_long_seek(cdrom_t *dev) } } -double -cdrom_seek_time(cdrom_t *dev) -{ - uint32_t diff = dev->seek_diff; - double sd = (double) (MAX_SEEK - MIN_SEEK); - - if (diff < MIN_SEEK) - return 0.0; - if (diff > MAX_SEEK) - diff = MAX_SEEK; - - diff -= MIN_SEEK; - - return cdrom_get_short_seek(dev) + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd); -} - -void -cdrom_stop(cdrom_t *dev) -{ - if (dev->cd_status > CD_STATUS_DATA_ONLY) - dev->cd_status = CD_STATUS_STOPPED; -} - -void -cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type) -{ - int m; - int s; - int f; - - if (!dev) - return; - - cdrom_log("CD-ROM %i: Seek to LBA %08X, vendor type = %02x.\n", dev->id, pos, vendor_type); - - switch (vendor_type) { - case 0x40: - m = bcd2bin((pos >> 24) & 0xff); - s = bcd2bin((pos >> 16) & 0xff); - f = bcd2bin((pos >> 8) & 0xff); - pos = MSFtoLBA(m, s, f) - 150; - break; - case 0x80: - pos = bcd2bin((pos >> 24) & 0xff); - break; - default: - break; - } - - dev->seek_pos = pos; - cdrom_stop(dev); -} - -int -cdrom_is_pre(cdrom_t *dev, uint32_t lba) -{ - if (dev->ops && dev->ops->is_track_pre) - return dev->ops->is_track_pre(dev, lba); - - return 0; -} - -int -cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) -{ - int ret = 1; - - if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING) || dev->audio_muted_soft) { - // cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id); - 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, (uint8_t *) &(dev->cd_buffer[dev->cd_buflen]), dev->seek_pos)) { - cdrom_log("CD-ROM %i: Read LBA %08X successful\n", dev->id, dev->seek_pos); - memcpy(dev->subch_buffer, ((uint8_t *) &(dev->cd_buffer[dev->cd_buflen])) + 2352, 96); - dev->seek_pos++; - dev->cd_buflen += (RAW_SECTOR_SIZE / 2); - ret = 1; - } else { - cdrom_log("CD-ROM %i: Read LBA %08X failed\n", dev->id, dev->seek_pos); - memset(&(dev->cd_buffer[dev->cd_buflen]), 0x00, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_status = CD_STATUS_STOPPED; - dev->cd_buflen = len; - ret = 0; - } - } else { - cdrom_log("CD-ROM %i: Playing completed\n", dev->id); - memset(&dev->cd_buffer[dev->cd_buflen], 0x00, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_status = CD_STATUS_PLAYING_COMPLETED; - dev->cd_buflen = len; - ret = 0; - } - } - - memcpy(output, dev->cd_buffer, len * 2); - memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); - dev->cd_buflen -= len; - - cdrom_log("CD-ROM %i: Audio callback returning %i\n", dev->id, ret); - return ret; -} - static void msf_from_bcd(int *m, int *s, int *f) { @@ -498,386 +287,1359 @@ msf_to_bcd(int *m, int *s, int *f) *f = bin2bcd(*f); } -uint8_t -cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf) +static int +read_data(const cdrom_t *dev, const uint32_t lba) { - track_info_t ti; - int m = 0; - int s = 0; - int f = 0; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - cdrom_log("CD-ROM %i: Play audio - %08X %08X %i\n", dev->id, pos, len, ismsf); - if (ismsf & 0x100) { - /* Track-relative audio play. */ - dev->ops->get_track_info(dev, ismsf & 0xff, 0, &ti); - pos += MSFtoLBA(ti.m, ti.s, ti.f) - 150; - } else if ((ismsf == 2) || (ismsf == 3)) { - dev->ops->get_track_info(dev, pos, 0, &ti); - pos = 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. */ - dev->ops->get_track_info(dev, len, 1, &ti); - len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; - } - } else if (ismsf == 1) { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - - /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) /*NEC*/ - msf_from_bcd(&m, &s, &f); - - if (pos == 0xffffff) { - cdrom_log("CD-ROM %i: Playing from current position (MSF)\n", dev->id); - pos = dev->seek_pos; - } else - pos = MSFtoLBA(m, s, f) - 150; - - m = (len >> 16) & 0xff; - s = (len >> 8) & 0xff; - f = len & 0xff; - - /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) /*NEC*/ - msf_from_bcd(&m, &s, &f); - - len = MSFtoLBA(m, s, f) - 150; - - cdrom_log("CD-ROM %i: MSF - pos = %08X len = %08X\n", dev->id, pos, len); - } else if (ismsf == 0) { - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: Playing from current position\n", dev->id); - pos = dev->seek_pos; - } - len += pos; - } - - 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->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; - } - - dev->seek_pos = pos; - dev->cd_end = len; - dev->cd_status = CD_STATUS_PLAYING; - dev->cd_buflen = 0; - return 1; -} - -uint8_t -cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit) -{ - int m = 0; - int s = 0; - int f = 0; - uint32_t pos2 = 0; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - cdrom_log("Audio Track Search: MSF = %06x, type = %02x, playbit = %02x\n", pos, type, playbit); - switch (type) { - case 0x00: - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: (type 0) Search from current position\n", dev->id); - pos = dev->seek_pos; - } - dev->seek_pos = pos; - break; - case 0x40: - m = bcd2bin((pos >> 24) & 0xff); - s = bcd2bin((pos >> 16) & 0xff); - f = bcd2bin((pos >> 8) & 0xff); - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: (type 1) Search from current position\n", dev->id); - pos = dev->seek_pos; - } else - pos = MSFtoLBA(m, s, f) - 150; - - dev->seek_pos = pos; - break; - case 0x80: - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: (type 2) Search from current position\n", dev->id); - pos = dev->seek_pos; - } - dev->seek_pos = (pos >> 24) & 0xff; - break; - default: - break; - } - - pos2 = pos - 1; - if (pos2 == 0xffffffff) - pos2 = pos + 1; - - /* 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->track_type(dev, pos2) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: Track Search: LBA %08X not on an audio track\n", dev->id, pos); - dev->audio_muted_soft = 1; - if (dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO) - dev->audio_muted_soft = 0; - } else - dev->audio_muted_soft = 0; - - cdrom_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; - return 1; -} - -uint8_t -cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit) -{ - int m = 0; - int s = 0; - int f = 0; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - f = bcd2bin((pos >> 24) & 0xff); - s = bcd2bin((pos >> 16) & 0xff); - m = bcd2bin((pos >> 8) & 0xff); - if (pos == 0xffffffff) { - pos = dev->seek_pos; - } else - pos = MSFtoLBA(m, s, f) - 150; - - dev->seek_pos = pos; - - 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->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; - } - - dev->cd_buflen = 0; - dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; - return 1; -} - -uint8_t -cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos) -{ - int m = 0; - int s = 0; - int f = 0; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - f = bcd2bin((pos >> 24) & 0xff); - s = bcd2bin((pos >> 16) & 0xff); - m = bcd2bin((pos >> 8) & 0xff); - pos = MSFtoLBA(m, s, f) - 150; - dev->cd_end = pos; - - dev->audio_muted_soft = 0; - dev->cd_buflen = 0; - dev->cd_status = CD_STATUS_PLAYING; - return 1; -} - -uint8_t -cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type) -{ - int m = 0; - int s = 0; - int f = 0; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - /*Preliminary support, revert if too incomplete*/ - switch (type) { - case 0x00: - dev->cd_end = pos; - break; - case 0x40: - m = bcd2bin((pos >> 24) & 0xff); - s = bcd2bin((pos >> 16) & 0xff); - f = bcd2bin((pos >> 8) & 0xff); - pos = MSFtoLBA(m, s, f) - 150; - dev->cd_end = pos; - break; - case 0x80: - dev->cd_end = (pos >> 24) & 0xff; - break; - case 0xc0: - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: Playing from current position\n", dev->id); - pos = dev->cd_end; - } - dev->cd_end = pos; - break; - default: - break; - } - - cdrom_log("Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos); - dev->cd_buflen = 0; - dev->cd_status = CD_STATUS_PLAYING; - return 1; -} - -uint8_t -cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type) -{ - int m = 0; - int s = 0; - int f = 0; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - cdrom_log("Audio Scan: MSF = %06x, type = %02x\n", pos, type); - switch (type) { - case 0x00: - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: (type 0) Search from current position\n", dev->id); - pos = dev->seek_pos; - } - dev->seek_pos = pos; - break; - case 0x40: - m = bcd2bin((pos >> 24) & 0xff); - s = bcd2bin((pos >> 16) & 0xff); - f = bcd2bin((pos >> 8) & 0xff); - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: (type 1) Search from current position\n", dev->id); - pos = dev->seek_pos; - } else - pos = MSFtoLBA(m, s, f) - 150; - - dev->seek_pos = pos; - break; - case 0x80: - dev->seek_pos = (pos >> 24) & 0xff; - break; - default: - break; - } - - 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->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; - } - - dev->cd_buflen = 0; - return 1; -} - -void -cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume) -{ - if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) - dev->cd_status = (dev->cd_status & 0xfe) | (resume & 0x01); + return dev->ops->read_sector(dev->local, raw_buffer, lba); } static void -cdrom_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc, int cooked) +cdrom_get_subchannel(const cdrom_t *dev, const uint32_t lba, + subchannel_t *subc, const int cooked) { - uint8_t *scb = dev->subch_buffer; - uint8_t q[16] = { 0 }; + const uint8_t *scb; + uint32_t scb_offs = 0; + uint8_t q[16] = { 0 }; - if ((lba == dev->seek_pos) && (dev->cd_status == CD_STATUS_PLAYING)) { - for (int i = 0; i < 12; i++) - for (int j = 0; j < 8; j++) - q[i] |= ((scb[(i << 3) + j] >> 6) & 0x01) << (7 - j); + 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 *) raw_buffer; + scb_offs = 2352; - if (cooked) { - uint8_t temp = (q[0] >> 4) | ((q[0] & 0xf) << 4); - q[0] = temp; + memset(raw_buffer, 0, 2448); - for (int i = 1; i < 10; i++) { - temp = bcd2bin(q[i]); - q[i] = temp; - } + (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); + + if (cooked) { + uint8_t temp = (q[0] >> 4) | ((q[0] & 0xf) << 4); + q[0] = temp; + + for (int i = 1; i < 10; i++) { + temp = bcd2bin(q[i]); + q[i] = temp; } + } - subc->attr = q[0]; - subc->track = q[1]; - subc->index = q[2]; - subc->rel_m = q[3]; - subc->rel_s = q[4]; - subc->rel_f = q[5]; - subc->abs_m = q[7]; - subc->abs_s = q[8]; - subc->abs_f = q[9]; - } else if ((dev->ops != NULL) && (dev->ops->get_subchannel != NULL)) { - dev->ops->get_subchannel(dev, lba, subc); + subc->attr = q[0]; + subc->track = q[1]; + subc->index = q[2]; + subc->rel_m = q[3]; + subc->rel_s = q[4]; + subc->rel_f = q[5]; + subc->abs_m = q[7]; + subc->abs_s = q[8]; + subc->abs_f = q[9]; +} - if (!cooked) { - uint8_t temp = (q[0] >> 4) | ((q[0] & 0xf) << 4); - q[0] = temp; +static void +read_toc_identify_sessions(const raw_track_info_t *rti, const int num, unsigned char *b) +{ + /* Bytes 2 and 3 = Number of first and last sessions */ + b[2] = 0xff; + b[3] = 0x00; - subc->attr = (subc->attr >> 4) | ((subc->attr & 0xf) << 4); - subc->track = bin2bcd(subc->track); - subc->index = bin2bcd(subc->index); - subc->rel_m = bin2bcd(subc->rel_m); - subc->rel_s = bin2bcd(subc->rel_s); - subc->rel_f = bin2bcd(subc->rel_f); - subc->abs_m = bin2bcd(subc->abs_m); - subc->abs_s = bin2bcd(subc->abs_s); - subc->abs_f = bin2bcd(subc->abs_f); - } + for (int i = (num - 1); i >= 0; i--) { + if (rti[i].session < b[2]) + b[2] = rti[i].session; + } + + for (int i = 0; i < num; i++) { + if (rti[i].session > b[3]) + b[3] = rti[i].session; } } -uint8_t -cdrom_get_current_status(cdrom_t *dev) +static int +find_track(const raw_track_info_t *trti, const int num, const int first) { - uint8_t ret; + int ret = -1; - if (dev->cd_status == CD_STATUS_DATA_ONLY) - ret = 0x15; - else { - if (dev->cd_status == CD_STATUS_PLAYING) - ret = 0x11; - else if (dev->cd_status == CD_STATUS_PAUSED) - ret = 0x12; + if (first) { + for (int i = 0; i < num; i++) + if ((trti[i].point >= 1) && (trti[i].point <= 99)) { + ret = i; + break; + } + } else { + for (int i = (num - 1); i >= 0; i--) + if ((trti[i].point >= 1) && (trti[i].point <= 99)) { + ret = i; + break; + } + } + + return ret; +} + +static int +find_last_lead_out(const raw_track_info_t *trti, const int num) +{ + int ret = -1; + + for (int i = (num - 1); i >= 0; i--) + if (trti[i].point == 0xa2) { + ret = i; + break; + } + + return ret; +} + +static int +find_specific_track(const raw_track_info_t *trti, const int num, const int track) +{ + int ret = -1; + + if ((track >= 1) && (track <= 99)) { + for (int i = (num - 1); i >= 0; i--) + if (trti[i].point == track) { + ret = i; + break; + } + } + + return ret; +} + +static int +read_toc_normal(const cdrom_t *dev, unsigned char *b, + const unsigned char start_track, const int msf, + const int sony) +{ + uint8_t rti[65536] = { 0 }; + uint8_t prti[65536] = { 0 }; + const raw_track_info_t *trti = (raw_track_info_t *) rti; + raw_track_info_t * tprti = (raw_track_info_t *) prti; + int num = 0; + int len = 4; + int t = -1; + + cdrom_log(dev->log, "read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i)\n", + (uintptr_t) dev, (uintptr_t) b, start_track, msf, sony); + + dev->ops->get_raw_track_info(dev->local, &num, rti); + + if (num > 0) { + int j = 0; + for (int i = 0; i < num; i++) { + if ((trti[i].point >= 0x01) && (trti[i].point <= 0x63)) { + tprti[j] = trti[i]; + if ((t == -1) && (tprti[j].point >= start_track)) + t = j; + cdrom_log(dev->log, "Sorted %03i = Unsorted %03i\n", j, i); + j++; + } + } + + /* Bytes 2 and 3 = Number of first and last tracks found before lead out */ + b[2] = tprti[0].point; + b[3] = tprti[j - 1].point; + + for (int i = (num - 1); i >= 0; i--) { + if (trti[i].point == 0xa2) { + tprti[j] = trti[i]; + tprti[j].point = 0xaa; + if ((t == -1) && (tprti[j].point >= start_track)) + t = j; + cdrom_log(dev->log, "Sorted %03i = Unsorted %03i\n", j, i); + j++; + break; + } + } + + if (t != -1) for (int i = t; i < j; i++) { +#ifdef ENABLE_CDROM_LOG + uint8_t *c = &(b[len]); +#endif + + if (!sony) + b[len++] = 0; /* Reserved */ + b[len++] = tprti[i].adr_ctl; /* ADR/CTL */ + b[len++] = tprti[i].point; /* Track number */ + if (!sony) + b[len++] = 0; /* Reserved */ + + if (msf) { + b[len++] = 0; + + /* NEC CDR-260 speaks BCD. */ + if (dev->is_early) { + int m = tprti[i].pm; + int s = tprti[i].ps; + int f = tprti[i].pf; + msf_to_bcd(&m, &s, &f); + b[len++] = m; + b[len++] = s; + b[len++] = f; + } else { + b[len++] = tprti[i].pm; + b[len++] = tprti[i].ps; + b[len++] = tprti[i].pf; + } + } else { + const uint32_t temp = MSFtoLBA(tprti[i].pm, tprti[i].ps, + tprti[i].pf) - 150; + + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + +#ifdef ENABLE_CDROM_LOG + cdrom_log(dev->log, "Track %02X: %02X %02X %02X %02X %02X %02X %02X %02X\n", + i, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); +#endif + } + } else + b[2] = b[3] = 0; + + return len; +} + +static int +read_toc_session(const cdrom_t *dev, unsigned char *b, const int msf) +{ + uint8_t rti[65536] = { 0 }; + const raw_track_info_t *t = (raw_track_info_t *) rti; + const raw_track_info_t *first = NULL; + int num = 0; + int len = 4; + + dev->ops->get_raw_track_info(dev->local, &num, rti); + + /* Bytes 2 and 3 = Number of first and last sessions */ + read_toc_identify_sessions((raw_track_info_t *) rti, num, b); + + cdrom_log(dev->log, "read_toc_session(%016" PRIXPTR ", %016" PRIXPTR ", %i)\n", + (uintptr_t) dev, (uintptr_t) b, msf); + + if (num != 0) { + for (int i = 0; i < num; i++) { + if ((t[i].session == b[3]) && (t[i].point >= 0x01) && (t[i].point <= 0x63)) { + first = &(t[i]); + break; + } + } + if (first != NULL) { + b[len++] = 0x00; + b[len++] = first->adr_ctl; + b[len++] = first->point; + b[len++] = 0x00; + + if (msf) { + b[len++] = 0x00; + + /* NEC CDR-260 speaks BCD. */ + if (dev->is_early) { + int m = first->pm; + int s = first->ps; + int f = first->pf; + + msf_to_bcd(&m, &s, &f); + + b[len++] = m; + b[len++] = s; + b[len++] = f; + } else { + b[len++] = first->pm; + b[len++] = first->ps; + b[len++] = first->pf; + } + } else { + const uint32_t temp = MSFtoLBA(first->pm, first->ps, + first->pf) - 150; + + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + } + } + + if (len == 4) + memset(&(b[len += 8]), 0x00, 8); + + return len; +} + +static int +read_toc_raw(const cdrom_t *dev, unsigned char *b, const unsigned char start_track) +{ + uint8_t rti[65536] = { 0 }; + const raw_track_info_t *t = (raw_track_info_t *) rti; + int num = 0; + int len = 4; + + /* Bytes 2 and 3 = Number of first and last sessions */ + read_toc_identify_sessions((raw_track_info_t *) rti, num, b); + + cdrom_log(dev->log, "read_toc_raw(%016" PRIXPTR ", %016" PRIXPTR ", %02X)\n", + (uintptr_t) dev, (uintptr_t) b, start_track); + + dev->ops->get_raw_track_info(dev->local, &num, rti); + + if (num != 0) for (int i = 0; i < num; i++) + if (t[i].session >= start_track) { + memcpy(&(b[len]), &(t[i]), 11); + len += 11; + } + + return len; +} + +static int +track_type_is_valid(const cdrom_t *dev, const int type, const int flags, const int audio, + const int mode2) +{ + if (!(flags & 0x70) && (flags & 0xf8)) { /* 0x08/0x80/0x88 are illegal modes */ + cdrom_log(dev->log, "[Any Mode] 0x08/0x80/0x88 are illegal modes\n"); + return 0; + } + + if ((type != 1) && !audio) { + if ((flags & 0x06) == 0x06) { + cdrom_log(dev->log, "[Any Data Mode] Invalid error flags\n"); + return 0; + } + + if (((flags & 0x700) == 0x300) || ((flags & 0x700) > 0x400)) { + cdrom_log(dev->log, "[Any Data Mode] Invalid subchannel data flags (%02X)\n", + flags & 0x700); + return 0; + } + + if ((flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ + cdrom_log(dev->log, "[Any Data Mode] EDC/ECC without user data is an " + "illegal mode\n"); + return 0; + } + + if (((flags & 0xf0) == 0x90) || ((flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ + cdrom_log(dev->log, "[Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n"); + return 0; + } + + if (((type > 3) && (type != 8)) || (mode2 && (mode2 & 0x03))) { + if ((flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ + cdrom_log(dev->log, "[Any XA Mode 2] 0x30/0x38 are illegal modes\n"); + return 0; + } + if (((flags & 0xf0) == 0xb0) || ((flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ + cdrom_log(dev->log, "[Any XA Mode 2] 0xBx and 0xDx are illegal modes\n"); + return 0; + } + } + } + + return 1; +} + +static int +read_audio(const cdrom_t *dev, const uint32_t lba, uint8_t *b) +{ + const int ret = dev->ops->read_sector(dev->local, raw_buffer, lba); + + memcpy(b, raw_buffer, 2352); + + cdrom_sector_size = 2352; + + return ret; +} + + +static void +process_mode1(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +{ + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log(dev->log, "[Mode 1] Sync\n"); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log(dev->log, "[Mode 1] Header\n"); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + if (!(cdrom_sector_flags & 0x10)) { + /* No user data */ + cdrom_log(dev->log, "[Mode 1] Sub-header\n"); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + } + + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log(dev->log, "[Mode 1] User data\n"); + if (mult > 1) { + memcpy(b, raw_buffer + 16 + (part * dev->sector_size), dev->sector_size); + cdrom_sector_size += dev->sector_size; + b += dev->sector_size; + } else { + memcpy(b, raw_buffer + 16, 2048); + cdrom_sector_size += 2048; + b += 2048; + } + } + + if (cdrom_sector_flags & 0x08) { + /* EDC/ECC */ + cdrom_log(dev->log, "[Mode 1] EDC/ECC\n"); + memcpy(b, raw_buffer + 2064, (288 - ecc_diff)); + cdrom_sector_size += (288 - ecc_diff); + } +} + +static void +process_mode2_non_xa(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +{ + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log(dev->log, "[Mode 2 Formless] Sync\n"); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log(dev->log, "[Mode 2 Formless] Header\n"); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + /* Mode 1 sector, expected type is 1 type. */ + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + cdrom_log(dev->log, "[Mode 2 Formless] Sub-header\n"); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log(dev->log, "[Mode 2 Formless] User data\n"); + memcpy(b, raw_buffer + 24, (2336 - ecc_diff)); + cdrom_sector_size += (2336 - ecc_diff); + } +} + +static void +process_mode2_xa_form1(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +{ + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log(dev->log, "[XA Mode 2 Form 1] Sync\n"); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log(dev->log, "[XA Mode 2 Form 1] Header\n"); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + cdrom_log(dev->log, "[XA Mode 2 Form 1] Sub-header\n"); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log(dev->log, "[XA Mode 2 Form 1] User data\n"); + if (mult > 1) { + memcpy(b, raw_buffer + 24 + (part * dev->sector_size), dev->sector_size); + cdrom_sector_size += dev->sector_size; + b += dev->sector_size; + } else { + memcpy(b, raw_buffer + 24, 2048); + cdrom_sector_size += 2048; + b += 2048; + } + } + + if (cdrom_sector_flags & 0x08) { + /* EDC/ECC */ + cdrom_log(dev->log, "[XA Mode 2 Form 1] EDC/ECC\n"); + memcpy(b, raw_buffer + 2072, (280 - ecc_diff)); + cdrom_sector_size += (280 - ecc_diff); + } +} + +static void +process_mode2_xa_form2(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +{ + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log(dev->log, "[XA Mode 2 Form 2] Sync\n"); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log(dev->log, "[XA Mode 2 Form 2] Header\n"); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + cdrom_log(dev->log, "[XA Mode 2 Form 2] Sub-header\n"); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log(dev->log, "[XA Mode 2 Form 2] User data\n"); + memcpy(b, raw_buffer + 24, (2328 - ecc_diff)); + cdrom_sector_size += (2328 - ecc_diff); + } +} + +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; + + if (cdrom_drive_types[dev->type].speed == -1) + dev->real_speed = dev->speed; + else + dev->real_speed = cdrom_drive_types[dev->type].speed; +} + +static void +cdrom_unload(cdrom_t *dev) +{ + cdrom_log(dev->log, "CDROM: cdrom_unload(%s)\n", dev->image_path); + + dev->cd_status = CD_STATUS_EMPTY; + + if (dev->local != NULL) { + dev->ops->close(dev->local); + dev->local = NULL; + } + + dev->ops = NULL; +} + +/* Reset the CD-ROM Interface, whichever one that is. */ +void +cdrom_interface_reset(void) +{ + /* If we have a valid controller, add its device. */ + if ((cdrom_interface_current > 0) && + controllers[cdrom_interface_current].device) + device_add(controllers[cdrom_interface_current].device); +} + +const char * +cdrom_interface_get_internal_name(const int cdinterface) +{ + return device_get_internal_name(controllers[cdinterface].device); +} + +int +cdrom_interface_get_from_internal_name(const char *s) +{ + int c = 0; + + while (controllers[c].device != NULL) { + if (!strcmp(controllers[c].device->internal_name, s)) + return c; + c++; + } + + return 0; +} + +const device_t * +cdrom_interface_get_device(const int cdinterface) +{ + return (controllers[cdinterface].device); +} + +int +cdrom_interface_has_config(const int cdinterface) +{ + const device_t *dev = cdrom_interface_get_device(cdinterface); + + if (dev == NULL) + return 0; + + if (!device_has_config(dev)) + return 0; + + return 1; +} + +int +cdrom_interface_get_flags(const int cdinterface) +{ + return (controllers[cdinterface].device->flags); +} + +int +cdrom_interface_available(const int cdinterface) +{ + return (device_available(controllers[cdinterface].device)); +} + +char * +cdrom_get_vendor(const int type) +{ + return (char *) cdrom_drive_types[type].vendor; +} + +void +cdrom_get_model(const int type, char *name, const int id) +{ + if (!strcmp(cdrom_drive_types[type].vendor, EMU_NAME)) + sprintf(name, "%s%02i", cdrom_drive_types[type].model, id); + else + sprintf(name, "%s", cdrom_drive_types[type].model); +} + +char * +cdrom_get_revision(const int type) +{ + return (char *) cdrom_drive_types[type].revision; +} + +int +cdrom_get_scsi_std(const int type) +{ + return cdrom_drive_types[type].scsi_std; +} + +int +cdrom_is_early(const int type) +{ + return (cdrom_drive_types[type].scsi_std == 1); +} + +int +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) +{ + return cdrom_drive_types[type].caddy; +} + +int +cdrom_get_speed(const int type) +{ + return cdrom_drive_types[type].speed; +} + +int +cdrom_get_inquiry_len(const int type) +{ + return cdrom_drive_types[type].inquiry_len; +} + +int +cdrom_get_transfer_max(const int type, const int mode) +{ + return cdrom_drive_types[type].transfer_max[mode]; +} + +int +cdrom_has_dma(const int type) +{ + return (cdrom_drive_types[type].transfer_max[2] != -1); +} + +int +cdrom_get_type_count(void) +{ + int count = 0; + + while (1) { + if (strlen(cdrom_drive_types[count].vendor) == 0) + break; else - ret = 0x13; + count++; + } + + return count; +} + +void +cdrom_get_identify_model(const int type, char *name, const int id) +{ + char elements[2][2048] = { 0 }; + + memcpy(elements[0], cdrom_drive_types[type].vendor, + strlen(cdrom_drive_types[type].vendor) + 1); + + memcpy(elements[1], cdrom_drive_types[type].model, + strlen(cdrom_drive_types[type].model) + 1); + + char *s = strstr(elements[1], " "); + + if (s != NULL) + s[0] = 0x00; + + if (!strcmp(cdrom_drive_types[type].vendor, EMU_NAME)) + sprintf(name, "%s%02i", elements[1], id); + else if (!strcmp(cdrom_drive_types[type].vendor, "ASUS")) + sprintf(name, "%s %s", elements[0], elements[1]); + else if (!strcmp(cdrom_drive_types[type].vendor, "NEC")) + sprintf(name, "%s %s", elements[0], elements[1]); + else if (!strcmp(cdrom_drive_types[type].vendor, "LITE-ON")) + sprintf(name, "%s", elements[1]); + else + sprintf(name, "%s %s", elements[0], elements[1]); +} + +void +cdrom_get_name(const int type, char *name) +{ + char n[2048] = { 0 }; + + cdrom_generate_name(type, n, 0); + + if (cdrom_drive_types[type].bus_type == BUS_TYPE_SCSI) + sprintf(name, "[SCSI-%i] %s", cdrom_drive_types[type].scsi_std, n); + else + sprintf(name, "%s", n); +} + +char * +cdrom_get_internal_name(const int type) +{ + return (char *) cdrom_drive_types[type].internal_name; +} + +int +cdrom_get_from_internal_name(const char *s) +{ + int c = 0; + int found = 0; + + while (strlen(cdrom_drive_types[c].internal_name) > 0) { + if (!strcmp((char *) cdrom_drive_types[c].internal_name, s)) { + found = 1; + break; + } + c++; + } + + if (!found) + c = -1; + + return c; +} + +/* TODO: Configuration migration, remove when no longer needed. */ +int +cdrom_get_from_name(const char *s) +{ + int c = 0; + int found = 0; + char n[2048] = { 0 }; + + if (strcmp(s, "none")) { + while (strlen(cdrom_drive_types[c].internal_name) > 0) { + memset(n, 0x00, 2048); + cdrom_generate_name(c, n, 1); + /* Special case some names. */ + if ((!strcmp(s, "86BOX_CD-ROM_1.00") && !strcmp(n, "86Box_86B_CD_3.50")) || + (!strcmp(s, "TEAC_CD_532E_2.0A") && !strcmp(n, "TEAC_CD-532E_2.0A")) || + !strcmp(n, s)) { + found = 1; + break; + } + c++; + } + } + + if (!found) { + if (strcmp(s, "none")) { + 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); + ui_msgbox_header(MBX_INFO, + plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), + tempmsg); + } + c = -1; + } + + return c; +} + +void +cdrom_set_type(const int model, const int type) +{ + cdrom[model].type = type; +} + +int +cdrom_get_type(const int model) +{ + return cdrom[model].type; +} + +int +cdrom_lba_to_msf_accurate(const int lba) +{ + int pos = lba + 150; + const int f = pos % 75; + pos -= f; + pos /= 75; + const int s = pos % 60; + pos -= s; + pos /= 60; + const int m = pos; + + return ((m << 16) | (s << 8) | f); +} + +double +cdrom_seek_time(const cdrom_t *dev) +{ + uint32_t diff = dev->seek_diff; + const double sd = (double) (MAX_SEEK - MIN_SEEK); + + if (diff < MIN_SEEK) + return 0.0; + if (diff > MAX_SEEK) + diff = MAX_SEEK; + + diff -= MIN_SEEK; + + return cdrom_get_short_seek(dev) + + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd); +} + +void +cdrom_stop(cdrom_t *dev) +{ + if (dev->cd_status > CD_STATUS_DVD) + dev->cd_status = CD_STATUS_STOPPED; +} + +void +cdrom_seek(cdrom_t *dev, const uint32_t pos, const uint8_t vendor_type) +{ + int m; + int s; + int f; + uint32_t real_pos = pos; + + if (dev == NULL) + return; + + cdrom_log(dev->log, "Seek to LBA %08X, vendor type = %02x.\n", pos, vendor_type); + + switch (vendor_type) { + case 0x40: + m = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + f = bcd2bin((pos >> 8) & 0xff); + real_pos = MSFtoLBA(m, s, f) - 150; + break; + case 0x80: + real_pos = bcd2bin((pos >> 24) & 0xff); + break; + default: + break; + } + + dev->seek_pos = real_pos; + cdrom_stop(dev); +} + +int +cdrom_is_pre(const cdrom_t *dev, const uint32_t lba) +{ + if (dev->ops && dev->ops->is_track_pre) + return dev->ops->is_track_pre(dev->local, lba); + + return 0; +} + +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)) { + 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->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); + 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); + dev->cd_status = CD_STATUS_PLAYING_COMPLETED; + dev->cd_buflen = len; + ret = 0; + } + } + + memcpy(output, dev->cd_buffer, len * 2); + memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); + dev->cd_buflen -= len; + + cdrom_log(dev->log, "Audio callback returning %i\n", ret); + return ret; +} + +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; + + 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. */ + ret = dev->ops->get_track_info(dev->local, ismsf & 0xff, 0, &ti); + if (ret) + pos2 += 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); + } + } else if ((ismsf == 2) || (ismsf == 3)) { + 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 (ret) + len2 = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + else { + cdrom_log(dev->log, "Unable to get the ending position for " + "track %08X\n", pos2); + cdrom_stop(dev); + } + } + } else { + cdrom_log(dev->log, "Unable to get the starting position for " + "track %08X\n", pos2); + cdrom_stop(dev); + } + } else if (ismsf == 1) { + int m = (pos >> 16) & 0xff; + int s = (pos >> 8) & 0xff; + int f = pos & 0xff; + + /* NEC CDR-260 speaks BCD. */ + if (dev->is_early) + msf_from_bcd(&m, &s, &f); + + if (pos == 0xffffff) { + cdrom_log(dev->log, "Playing from current position (MSF)\n"); + pos2 = dev->seek_pos; + } else + pos2 = MSFtoLBA(m, s, f) - 150; + + m = (len >> 16) & 0xff; + s = (len >> 8) & 0xff; + f = len & 0xff; + + /* NEC CDR-260 speaks BCD. */ + if (dev->is_early) + msf_from_bcd(&m, &s, &f); + + len2 = MSFtoLBA(m, s, f) - 150; + + ret = 1; + + cdrom_log(dev->log, "MSF - pos = %08X len = %08X\n", pos2, len); + } else if (ismsf == 0) { + if (pos == 0xffffffff) { + cdrom_log(dev->log, "Playing from current position\n"); + pos2 = dev->seek_pos; + } + len2 += pos2; + + ret = 1; + } + } + + 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. + */ + 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; + } else { + cdrom_log(dev->log, "LBA %08X not on an audio track\n", pos); + cdrom_stop(dev); + } + } + + return ret; +} + +uint8_t +cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos, + const int type, const uint8_t playbit) +{ + uint32_t pos2 = pos; + uint8_t ret = 0; + + if (dev->cd_status & CD_STATUS_HAS_AUDIO) { + cdrom_log(dev->log, "Audio Track Search: MSF = %06x, type = %02x, " + "playbit = %02x\n", pos, type, playbit); + + 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: + if (pos == 0xffffffff) { + cdrom_log(dev->log, "(Type 2) Search from current position\n"); + pos2 = dev->seek_pos; + } + dev->seek_pos = (pos2 >> 24) & 0xff; + break; + default: + break; + } + + 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: 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; +} + +uint8_t +cdrom_audio_track_search_pioneer(cdrom_t *dev, const uint32_t pos, const uint8_t playbit) +{ + uint8_t ret = 0; + + if (dev->cd_status &= CD_STATUS_HAS_AUDIO) { + const int f = bcd2bin((pos >> 24) & 0xff); + const int s = bcd2bin((pos >> 16) & 0xff); + const int m = bcd2bin((pos >> 8) & 0xff); + uint32_t pos2; + + if (pos == 0xffffffff) + pos2 = dev->seek_pos; + else + pos2 = MSFtoLBA(m, s, f) - 150; + + 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_buflen = 0; + dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; + + ret = 1; + } else { + cdrom_log(dev->log, "LBA %08X not on an audio track\n", pos); + cdrom_stop(dev); + } + } + + return ret; +} + +uint8_t +cdrom_audio_play_pioneer(cdrom_t *dev, const uint32_t pos) +{ + uint8_t ret = 0; + + if (dev->cd_status & CD_STATUS_HAS_AUDIO) { + const int f = bcd2bin((pos >> 24) & 0xff); + const int s = bcd2bin((pos >> 16) & 0xff); + const int m = bcd2bin((pos >> 8) & 0xff); + 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; + + ret = 1; + } + + return ret; +} + +uint8_t +cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) +{ + uint32_t pos2 = pos; + uint8_t ret = 0; + + if (dev->cd_status & CD_STATUS_HAS_AUDIO) { + /* Preliminary support, revert if too incomplete. */ + switch (type) { + case 0x00: + dev->cd_end = 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); + pos2 = MSFtoLBA(m, s, f) - 150; + dev->cd_end = pos2; + break; + case 0x80: + dev->cd_end = (pos2 >> 24) & 0xff; + break; + case 0xc0: + if (pos == 0xffffffff) { + cdrom_log(dev->log, "Playing from current position\n"); + pos2 = dev->cd_end; + } + dev->cd_end = pos2; + break; + default: + break; + } + + cdrom_log(dev->log, "Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", + dev->audio_muted_soft, pos2); + dev->cd_buflen = 0; + + dev->cd_status = CD_STATUS_PLAYING; + + ret = 1; + } + + return ret; +} + +uint8_t +cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type) +{ + 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; + } + + 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) { + dev->cd_buflen = 0; + ret = 1; + } else { + cdrom_log(dev->log, "LBA %08X not on an audio track\n", pos); + cdrom_stop(dev); + } } return ret; } void -cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) +cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume) +{ + if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) + dev->cd_status = (dev->cd_status & 0xfe) | (resume & 0x01); +} + +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]; + + return ret; +} + +void +cdrom_get_current_subchannel(const cdrom_t *dev, uint8_t *b, const int msf) { subchannel_t subc; - uint32_t dat; cdrom_get_subchannel(dev, dev->seek_pos, &subc, 1); - cdrom_log("CD-ROM %i: Returned subchannel absolute at %02i:%02i.%02i, " + cdrom_log(dev->log, "Returned subchannel absolute at %02i:%02i.%02i, " "relative at %02i:%02i.%02i, seek pos = %08x, cd_end = %08x.\n", - dev->id, subc.abs_m, subc.abs_s, subc.abs_f, subc.rel_m, subc.rel_s, subc.rel_f, + subc.abs_m, subc.abs_s, subc.abs_f, subc.rel_m, subc.rel_s, subc.rel_f, dev->seek_pos, dev->cd_end); /* Format code. */ switch (b[0]) { - /* 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. */ + /* + 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 0x01: /* Current position. */ b[1] = subc.attr; @@ -888,8 +1650,7 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) b[4] = b[8] = 0x00; /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { - /* NEC */ + if (dev->is_early) { b[5] = bin2bcd(subc.abs_m); b[6] = bin2bcd(subc.abs_s); b[7] = bin2bcd(subc.abs_f); @@ -907,7 +1668,7 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) b[11] = subc.rel_f; } } else { - dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; + uint32_t dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; b[4] = (dat >> 24) & 0xff; b[5] = (dat >> 16) & 0xff; b[6] = (dat >> 8) & 0xff; @@ -925,8 +1686,7 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) memset(&(b[1]), 0x00, 19); memset(&(b[5]), 0x30, 13); /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) - /* NEC */ + if (dev->is_early) b[19] = bin2bcd(subc.abs_f); else b[19] = subc.abs_f; @@ -936,27 +1696,27 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) memset(&(b[1]), 0x00, 19); memset(&(b[5]), 0x30, 12); /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) - /* NEC */ + if (dev->is_early) b[18] = bin2bcd(subc.abs_f); else b[18] = subc.abs_f; break; default: - cdrom_log("b[0] = %02X\n", b[0]); + cdrom_log(dev->log, "b[0] = %02X\n", b[0]); break; } } void -cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf) +cdrom_get_current_subchannel_sony(const cdrom_t *dev, uint8_t *b, const int msf) { subchannel_t subc; - uint32_t dat; cdrom_get_subchannel(dev, dev->seek_pos, &subc, 1); - cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i, seek pos = %08x, cd_end = %08x, msf = %x.\n", dev->id, subc.abs_m, subc.abs_s, subc.abs_f, dev->seek_pos, dev->cd_end, msf); + cdrom_log(dev->log, "Returned subchannel at %02i:%02i.%02i, seek pos = %08x, " + "cd_end = %08x, msf = %x.\n", + subc.abs_m, subc.abs_s, subc.abs_f, dev->seek_pos, dev->cd_end, msf); b[0] = subc.attr; b[1] = subc.track; @@ -970,7 +1730,7 @@ cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf) b[7] = subc.abs_s; b[8] = subc.abs_f; } else { - dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f); + uint32_t dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f); b[3] = (dat >> 16) & 0xff; b[4] = (dat >> 8) & 0xff; b[5] = dat & 0xff; @@ -982,23 +1742,22 @@ cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf) } uint8_t -cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b) +cdrom_get_audio_status_pioneer(const cdrom_t *dev, uint8_t *b) { uint8_t ret; subchannel_t subc; cdrom_get_subchannel(dev, dev->seek_pos, &subc, 0); - if (dev->cd_status == CD_STATUS_DATA_ONLY) - ret = 0x05; - else { + if (dev->cd_status & CD_STATUS_HAS_AUDIO) { if (dev->cd_status == CD_STATUS_PLAYING) ret = dev->sound_on ? 0x00 : 0x02; else if (dev->cd_status == CD_STATUS_PAUSED) ret = 0x01; else ret = 0x03; - } + } else + ret = 0x05; b[0] = 0; b[1] = subc.abs_m; @@ -1009,24 +1768,22 @@ cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b) } uint8_t -cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf) +cdrom_get_audio_status_sony(const cdrom_t *dev, uint8_t *b, const int msf) { uint8_t ret; subchannel_t subc; - uint32_t dat; cdrom_get_subchannel(dev, dev->seek_pos, &subc, 1); - if (dev->cd_status == CD_STATUS_DATA_ONLY) - ret = 0x05; - else { + if (dev->cd_status & CD_STATUS_HAS_AUDIO) { if (dev->cd_status == CD_STATUS_PLAYING) ret = dev->sound_on ? 0x00 : 0x02; else if (dev->cd_status == CD_STATUS_PAUSED) ret = 0x01; else ret = 0x03; - } + } else + ret = 0x05; if (msf) { b[0] = 0; @@ -1034,7 +1791,7 @@ cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf) b[2] = subc.abs_s; b[3] = subc.abs_f; } else { - dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; + const uint32_t dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; b[0] = (dat >> 24) & 0xff; b[1] = (dat >> 16) & 0xff; b[2] = (dat >> 8) & 0xff; @@ -1045,7 +1802,7 @@ cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf) } void -cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b) +cdrom_get_current_subcodeq(const cdrom_t *dev, uint8_t *b) { subchannel_t subc; @@ -1070,6 +1827,7 @@ 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; @@ -1077,268 +1835,17 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op; /*If a valid audio track is detected with audio on, unmute it.*/ - if (dev->ops->track_type(dev, dev->seek_pos) & CD_TRACK_AUDIO) + if (dev->ops->get_track_type(dev->local, dev->seek_pos) & CD_TRACK_AUDIO) dev->audio_muted_soft = 0; - cdrom_log("SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d.\n", + 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); return ret; } -static void -read_toc_identify_sessions(raw_track_info_t *rti, int num, unsigned char *b) -{ - /* Bytes 2 and 3 = Number of first and last sessions */ - b[2] = 0xff; - b[3] = 0x00; - - for (int i = (num - 1); i >= 0; i--) { - if (rti[i].session < b[2]) - b[2] = rti[i].session; - } - - for (int i = 0; i < num; i++) { - if (rti[i].session > b[3]) - b[3] = rti[i].session; - } -} - -static int -find_track(raw_track_info_t *trti, int num, int first) -{ - int ret = -1; - - if (first) { - for (int i = 0; i < num; i++) - if ((trti[i].point >= 1) && (trti[i].point <= 99)) { - ret = i; - break; - } - } else { - for (int i = (num - 1); i >= 0; i--) - if ((trti[i].point >= 1) && (trti[i].point <= 99)) { - ret = i; - break; - } - } - - return ret; -} - -static int -find_last_lead_out(raw_track_info_t *trti, int num) -{ - int ret = -1; - - for (int i = (num - 1); i >= 0; i--) - if (trti[i].point == 0xa2) { - ret = i; - break; - } - - return ret; -} - -static int -find_specific_track(raw_track_info_t *trti, int num, int track) -{ - int ret = -1; - - if ((track >= 1) && (track <= 99)) { - for (int i = (num - 1); i >= 0; i--) - if (trti[i].point == track) { - ret = i; - break; - } - } - - return ret; -} - -static int -read_toc_normal(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int sony) -{ - uint8_t rti[65536] = { 0 }; - uint8_t prti[65536] = { 0 }; - raw_track_info_t *trti = (raw_track_info_t *) rti; - raw_track_info_t *tprti = (raw_track_info_t *) prti; - int num = 0; - int len = 4; - int s = -1; - - cdrom_log("read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i)\n", - (uintptr_t) dev, (uintptr_t) b, start_track, msf, sony); - - dev->ops->get_raw_track_info(dev, &num, (raw_track_info_t *) rti); - - if (num > 0) { - int j = 0; - for (int i = 0; i < num; i++) { - if ((trti[i].point >= 0x01) && (trti[i].point <= 0x63)) { - tprti[j] = trti[i]; - if ((s == -1) && (tprti[j].point >= start_track)) - s = j; - cdrom_log("Sorted %03i = Unsorted %03i (s = %03i)\n", j, i, s); - j++; - } - } - - /* Bytes 2 and 3 = Number of first and last tracks found before lead out */ - b[2] = tprti[0].point; - b[3] = tprti[j - 1].point; - - for (int i = (num - 1); i >= 0; i--) { - if (trti[i].point == 0xa2) { - tprti[j] = trti[i]; - tprti[j].point = 0xaa; - if ((s == -1) && (tprti[j].point >= start_track)) - s = j; - cdrom_log("Sorted %03i = Unsorted %03i (s = %03i)\n", j, i, s); - j++; - break; - } - } - - if (s != -1) for (int i = s; i < j; i++) { -#ifdef ENABLE_CDROM_LOG - uint8_t *c = &(b[len]); -#endif - - if (!sony) - b[len++] = 0; /* Reserved */ - b[len++] = tprti[i].adr_ctl; /* ADR/CTL */ - b[len++] = tprti[i].point; /* Track number */ - if (!sony) - b[len++] = 0; /* Reserved */ - - if (msf) { - b[len++] = 0; - - /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { - int m = tprti[i].pm; - int s = tprti[i].ps; - int f = tprti[i].pf; - msf_to_bcd(&m, &s, &f); - b[len++] = m; - b[len++] = s; - b[len++] = f; - } else { - b[len++] = tprti[i].pm; - b[len++] = tprti[i].ps; - b[len++] = tprti[i].pf; - } - } else { - uint32_t temp = MSFtoLBA(tprti[i].pm, tprti[i].ps, tprti[i].pf) - 150; - - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - -#ifdef ENABLE_CDROM_LOG - cdrom_log("Track %02X: %02X %02X %02X %02X %02X %02X %02X %02X\n", - i, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); -#endif - } - } else - b[2] = b[3] = 0; - - return len; -} - -static int -read_toc_session(cdrom_t *dev, unsigned char *b, int msf) -{ - uint8_t rti[65536] = { 0 }; - raw_track_info_t *t = (raw_track_info_t *) rti; - raw_track_info_t *first = NULL; - int num = 0; - int len = 4; - - dev->ops->get_raw_track_info(dev, &num, (raw_track_info_t *) rti); - - /* Bytes 2 and 3 = Number of first and last sessions */ - read_toc_identify_sessions((raw_track_info_t *) rti, num, b); - - cdrom_log("read_toc_session(%016" PRIXPTR ", %016" PRIXPTR ", %i)\n", - (uintptr_t) dev, (uintptr_t) b, msf); - - if (num != 0) { - for (int i = 0; i < num; i++) if ((t[i].session == b[3]) && (t[i].point >= 0x01) && (t[i].point <= 0x63)) { - first = &(t[i]); - break; - } - if (first != NULL) { - b[len++] = 0x00; - b[len++] = first->adr_ctl; - b[len++] = first->point; - b[len++] = 0x00; - - if (msf) { - b[len++] = 0x00; - - /* NEC CDR-260 speaks BCD. */ - if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { /*NEC*/ - int m = first->pm; - int s = first->ps; - int f = first->pf; - - msf_to_bcd(&m, &s, &f); - - b[len++] = m; - b[len++] = s; - b[len++] = f; - } else { - b[len++] = first->pm; - b[len++] = first->ps; - b[len++] = first->pf; - } - } else { - uint32_t temp = MSFtoLBA(first->pm, first->ps, first->pf) - 150; - - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - } - } - - if (len == 4) - memset(&(b[len += 8]), 0x00, 8); - - return len; -} - -static int -read_toc_raw(cdrom_t *dev, unsigned char *b, unsigned char start_track) -{ - uint8_t rti[65536] = { 0 }; - raw_track_info_t *t = (raw_track_info_t *) rti; - int num = 0; - int len = 4; - - /* Bytes 2 and 3 = Number of first and last sessions */ - read_toc_identify_sessions((raw_track_info_t *) rti, num, b); - - cdrom_log("read_toc_raw(%016" PRIXPTR ", %016" PRIXPTR ", %02X)\n", - (uintptr_t) dev, (uintptr_t) b, start_track); - - dev->ops->get_raw_track_info(dev, &num, (raw_track_info_t *) rti); - - if (num != 0) for (int i = 0; i < num; i++) - if (t[i].session >= start_track) { - memcpy(&(b[len]), &(t[i]), 11); - len += 11; - } - - return len; -} - int -cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_track, int msf, int max_len) +cdrom_read_toc(const cdrom_t *dev, uint8_t *b, const int type, + const uint8_t start_track, const int msf, const int max_len) { int len; @@ -1353,7 +1860,7 @@ cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_tra len = read_toc_raw(dev, b, start_track); break; default: - cdrom_log("CD-ROM %i: Unknown TOC read type: %i\n", dev->id, type); + cdrom_log(dev->log, "Unknown TOC read type: %i\n", type); return 0; } @@ -1366,11 +1873,10 @@ cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_tra } int -cdrom_read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int max_len) +cdrom_read_toc_sony(const cdrom_t *dev, uint8_t *b, const uint8_t start_track, + const int msf, const int max_len) { - int len; - - len = read_toc_normal(dev, b, start_track, msf, 1); + int len = read_toc_normal(dev, b, start_track, msf, 1); len = MIN(len, max_len); @@ -1392,7 +1898,7 @@ cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf) int last = -1; if (dev != NULL) - dev->ops->get_raw_track_info(dev, &num, (raw_track_info_t *) rti); + dev->ops->get_raw_track_info(dev->local, &num, rti); if (num > 0) { first = find_track(trti, num, 1); @@ -1437,68 +1943,86 @@ uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len) { track_info_t ti; + int ret = 0; - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; + if (dev->cd_status & CD_STATUS_HAS_AUDIO) { + cdrom_log(dev->log, "Play Mitsumi audio - %08X %08X\n", pos, len); - cdrom_log("CD-ROM 0: Play Mitsumi audio - %08X %08X\n", pos, len); - dev->ops->get_track_info(dev, pos, 0, &ti); - pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; - dev->ops->get_track_info(dev, len, 1, &ti); - len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + ret = dev->ops->get_track_info(dev->local, pos, 0, &ti); - /* 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->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; + if (ret) { + pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + ret = dev->ops->get_track_info(dev->local, len, 1, &ti); + + if (ret) { + len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + + /* + Do this at this point, since it's at this point that we know the + actual LBA position to start playing from. + */ + ret = (dev->ops->get_track_type(dev->local, pos) == CD_TRACK_AUDIO); + + if (ret) { + dev->seek_pos = pos; + dev->cd_end = len; + 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); + } + } else { + cdrom_log(dev->log, "Unable to get the ending position for track %08X\n", + len); + cdrom_stop(dev); + } + } else { + cdrom_log(dev->log, "Unable to get the starting position for track %08X\n", pos); + cdrom_stop(dev); + } } - dev->seek_pos = pos; - dev->cd_end = len; - dev->cd_status = CD_STATUS_PLAYING; - dev->cd_buflen = 0; - - return 1; + return ret; } #endif uint8_t -cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type) +cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, + const uint8_t track, const int type) { - uint8_t rti[65536] = { 0 }; - raw_track_info_t *trti = (raw_track_info_t *) rti; - int num = 0; - int first = -1; - int last = -1; - int t = -1; - uint32_t temp; - uint8_t ret = 1; + uint8_t rti[65536] = { 0 }; + const raw_track_info_t *trti = (raw_track_info_t *) rti; + int num = 0; + int first = -1; + int t = -1; + uint8_t ret = 1; + uint32_t temp; - if (dev != NULL) - dev->ops->get_raw_track_info(dev, &num, (raw_track_info_t *) rti); + cdrom_log(dev->log, "Read DISC Info TOC Type = %d, track = %d\n", type, track); - cdrom_log("Read DISC Info TOC Type = %d, track = %d\n", type, track); + dev->inv_field = track; + dev->ops->get_raw_track_info(dev->local, &num, rti); switch (type) { case 0: if (num > 0) { first = find_track(trti, num, 1); - last = find_track(trti, num, 0); - } + const int last = find_track(trti, num, 0); - if ((first == -1) || (last == -1)) + if ((first == -1) || (last == -1)) + ret = 0; + else { + b[0] = bin2bcd(first); + b[1] = bin2bcd(last); + b[2] = 0x00; + b[3] = 0x00; + + cdrom_log(dev->log, "Returned Toshiba/NEC disc information (type 0) " + "at %02i:%02i\n", b[0], b[1]); + } + } else ret = 0; - else { - b[0] = bin2bcd(first); - b[1] = bin2bcd(last); - b[2] = 0x00; - b[3] = 0x00; - - cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 0) at %02i:%02i\n", - dev->id, b[0], b[1]); - } break; case 1: if (num > 0) @@ -1512,8 +2036,8 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in b[2] = bin2bcd(trti[t].pf); b[3] = 0x00; - cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 1) at %02i:%02i.%02i\n", - dev->id, b[0], b[1], b[2]); + cdrom_log(dev->log, "Returned Toshiba/NEC disc information (type 1) at " + "%02i:%02i.%02i\n", b[0], b[1], b[2]); } break; case 2: @@ -1528,49 +2052,41 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in b[2] = bin2bcd(trti[t].pf); b[3] = trti[t].adr_ctl; - cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 2) at " - "%02i:%02i.%02i, track=%d, attr=%02x.\n", dev->id, b[0], b[1], b[2], bcd2bin(track), b[3]); + cdrom_log(dev->log, "Returned Toshiba/NEC disc information (type 2) at " + "%02i:%02i.%02i, track=%d, attr=%02x.\n", b[0], b[1], + b[2], bcd2bin(track), b[3]); } break; case 3: /* Undocumented on NEC CD-ROM's, from information based on sr_vendor.c from the Linux kernel */ - switch (dev->type) { - case CDROM_TYPE_NEC_25_10a: - case CDROM_TYPE_NEC_38_103: - case CDROM_TYPE_NEC_75_103: - case CDROM_TYPE_NEC_77_106: - case CDROM_TYPE_NEC_211_100: - case CDROM_TYPE_NEC_464_105: - b[0x0e] = 0x00; + if (dev->is_nec) { + b[0x0e] = 0x00; - if (num > 0) - first = find_track(trti, num, 1); + if (num > 0) + first = find_track(trti, num, 1); - if (first == -1) - ret = 0; - else { - temp = MSFtoLBA(trti[first].pm, trti[first].ps, trti[first].pf) - 150; - b[0x0f] = temp >> 24; - b[0x10] = temp >> 16; - b[0x11] = temp >> 8; - b[0x12] = temp; - } - break; + if (first == -1) + ret = 0; + else { + temp = MSFtoLBA(trti[first].pm, trti[first].ps, trti[first].pf) - 150; + b[0x0f] = temp >> 24; + b[0x10] = temp >> 16; + b[0x11] = temp >> 8; + b[0x12] = temp; + } + } else { + b[0] = 0x00; /* Audio or CDROM disc. */ - default: - b[0] = 0x00; /* Audio or CDROM disc. */ + if (num > 0) + first = find_track(trti, num, 1); - if (num > 0) - first = find_track(trti, num, 1); - - if (first == -1) - ret = 0; - else { - temp = MSFtoLBA(trti[first].pm, trti[first].ps, trti[first].pf) - 150; - b[0x1] = temp >> 24; - b[0x2] = temp >> 16; - b[0x3] = temp >> 8; - } - break; + if (first == -1) + ret = 0; + else { + temp = MSFtoLBA(trti[first].pm, trti[first].ps, trti[first].pf) - 150; + b[0x1] = temp >> 24; + b[0x2] = temp >> 16; + b[0x3] = temp >> 8; + } } break; default: @@ -1580,307 +2096,57 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in return ret; } -static int -track_type_is_valid(UNUSED(uint8_t id), int type, int flags, int audio, int mode2) -{ - if (!(flags & 0x70) && (flags & 0xf8)) { /* 0x08/0x80/0x88 are illegal modes */ - cdrom_log("CD-ROM %i: [Any Mode] 0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } - - if ((type != 1) && !audio) { - if ((flags & 0x06) == 0x06) { - cdrom_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); - return 0; - } - - if (((flags & 0x700) == 0x300) || ((flags & 0x700) > 0x400)) { - cdrom_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, flags & 0x700); - return 0; - } - - if ((flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ - cdrom_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); - return 0; - } - - if (((flags & 0xf0) == 0x90) || ((flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ - cdrom_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); - return 0; - } - - if (((type > 3) && (type != 8)) || (mode2 && (mode2 & 0x03))) { - if ((flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ - cdrom_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); - return 0; - } - if (((flags & 0xf0) == 0xb0) || ((flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ - cdrom_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); - return 0; - } - } - } - - return 1; -} - -static int -read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b) -{ - int ret = dev->ops->read_sector(dev, raw_buffer, lba); - - memcpy(b, raw_buffer, 2352); - - cdrom_sector_size = 2352; - - return ret; -} - -static void -process_mode1(cdrom_t *dev, int cdrom_sector_flags, uint8_t *b) -{ - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { - /* Sync */ - cdrom_log("CD-ROM %i: [Mode 1] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; - } - - if (cdrom_sector_flags & 0x20) { - /* Header */ - cdrom_log("CD-ROM %i: [Mode 1] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; - } - - if (cdrom_sector_flags & 0x40) { - /* Sub-header */ - if (!(cdrom_sector_flags & 0x10)) { - /* No user data */ - cdrom_log("CD-ROM %i: [Mode 1] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; - } - } - - if (cdrom_sector_flags & 0x10) { - /* User data */ - cdrom_log("CD-ROM %i: [Mode 1] User data\n", dev->id); - memcpy(b, raw_buffer + 16, 2048); - cdrom_sector_size += 2048; - b += 2048; - } - - if (cdrom_sector_flags & 0x08) { - /* EDC/ECC */ - cdrom_log("CD-ROM %i: [Mode 1] EDC/ECC\n", dev->id); - memcpy(b, raw_buffer + 2064, 288); - cdrom_sector_size += 288; - b += 288; - } -} - -static int -read_data(cdrom_t *dev, uint32_t lba) -{ - return dev->ops->read_sector(dev, raw_buffer, lba); -} - -static int -read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint8_t *b) -{ - int ret = read_data(dev, lba); - - process_mode1(dev, cdrom_sector_flags, b); - - return ret; -} - -static int -read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint8_t *b) -{ - int ret = dev->ops->read_sector(dev, raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { - /* Sync */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; - } - - if (cdrom_sector_flags & 0x20) { - /* Header */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; - } - - /* Mode 1 sector, expected type is 1 type. */ - if (cdrom_sector_flags & 0x40) { - /* Sub-header */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; - } - - if (cdrom_sector_flags & 0x10) { - /* User data */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] User data\n", dev->id); - memcpy(b, raw_buffer + 24, 2336); - cdrom_sector_size += 2336; - b += 2336; - } - - return ret; -} - -static void -process_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint8_t *b) -{ - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { - /* Sync */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; - } - - if (cdrom_sector_flags & 0x20) { - /* Header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; - } - - if (cdrom_sector_flags & 0x40) { - /* Sub-header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; - } - - if (cdrom_sector_flags & 0x10) { - /* User data */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", dev->id); - memcpy(b, raw_buffer + 24, 2048); - cdrom_sector_size += 2048; - b += 2048; - } - - if (cdrom_sector_flags & 0x08) { - /* EDC/ECC */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", dev->id); - memcpy(b, raw_buffer + 2072, 280); - cdrom_sector_size += 280; - b += 280; - } -} - -static int -read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint8_t *b) -{ - int ret = read_data(dev, lba); - - process_mode2_xa_form1(dev, cdrom_sector_flags, b); - - return ret; -} - -static int -read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint8_t *b) -{ - int ret = dev->ops->read_sector(dev, raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { - /* Sync */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; - } - - if (cdrom_sector_flags & 0x20) { - /* Header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; - } - - if (cdrom_sector_flags & 0x40) { - /* Sub-header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; - } - - if (cdrom_sector_flags & 0x10) { - /* User data */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", dev->id); - memcpy(b, raw_buffer + 24, 2328); - cdrom_sector_size += 2328; - b += 2328; - } - - return ret; -} - int -cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, - int cdrom_sector_flags, int *len, uint8_t vendor_type) +cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, + int cdrom_sector_type, const int cdrom_sector_flags, + int *len, const uint8_t vendor_type) { - uint8_t *b; uint8_t *temp_b; uint32_t lba; int audio = 0; int mode2 = 0; - int unk = 0; - int ret = 0; + int pos = sector; + int ret; + + if ((cdrom_sector_type & 0x0f) >= 0x08) { + mult = cdrom_sector_type >> 4; + cdrom_sector_type &= 0x0f; + part = pos % mult; + pos /= mult; + ecc_diff = (cdrom_sector_type & 0x01) ? 4 : 0; + } else { + mult = 1; + part = 0; + ecc_diff = 0; + } if (dev->cd_status == CD_STATUS_EMPTY) return 0; - b = temp_b = buffer; + uint8_t *b = temp_b = buffer; *len = 0; if (ismsf) { - int m = (sector >> 16) & 0xff; - int s = (sector >> 8) & 0xff; - int f = sector & 0xff; + const int m = (pos >> 16) & 0xff; + const int s = (pos >> 8) & 0xff; + const int f = pos & 0xff; lba = MSFtoLBA(m, s, f) - 150; } else { switch (vendor_type) { case 0x00: - lba = sector; + lba = pos; break; case 0x40: { - int m = bcd2bin((sector >> 24) & 0xff); - int s = bcd2bin((sector >> 16) & 0xff); - int f = bcd2bin((sector >> 8) & 0xff); + const int m = bcd2bin((pos >> 24) & 0xff); + const int s = bcd2bin((pos >> 16) & 0xff); + const int f = bcd2bin((pos >> 8) & 0xff); lba = MSFtoLBA(m, s, f) - 150; break; } case 0x80: - lba = bcd2bin((sector >> 24) & 0xff); + lba = bcd2bin((pos >> 24) & 0xff); break; /* Never used values but the compiler complains. */ default: @@ -1888,127 +2154,111 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c } } - if (dev->ops->track_type) - audio = dev->ops->track_type(dev, lba); + if (dev->ops->get_track_type) + audio = dev->ops->get_track_type(dev->local, lba); - mode2 = audio & CD_TRACK_MODE2; - unk = audio & CD_TRACK_UNK_DATA; - audio &= CD_TRACK_AUDIO; + int dm = audio & CD_TRACK_MODE_MASK; + audio &= CD_TRACK_AUDIO; + + if (dm != CD_TRACK_NORMAL) + mode2 = 1; memset(raw_buffer, 0, 2448); memset(extra_buffer, 0, 296); if ((cdrom_sector_flags & 0xf8) == 0x08) { /* 0x08 is an illegal mode */ - cdrom_log("CD-ROM %i: [Mode 1] 0x08 is an illegal mode\n", dev->id); + cdrom_log(dev->log, "[Mode 1] 0x08 is an illegal mode\n"); return 0; } - if (!track_type_is_valid(dev->id, cdrom_sector_type, cdrom_sector_flags, audio, mode2)) + if ((cdrom_sector_type > 5) && (cdrom_sector_type < 8)) { + cdrom_log(dev->log, "Attempting to read an unrecognized sector " + "type from an image\n"); return 0; - - if ((cdrom_sector_type > 5) && (cdrom_sector_type != 8)) { - cdrom_log("CD-ROM %i: Attempting to read an unrecognized sector type from an image\n", dev->id); - return 0; - } else if (cdrom_sector_type == 1) { - if (!audio || (dev->cd_status == CD_STATUS_DATA_ONLY)) { - cdrom_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", dev->id); + } else { + if ((cdrom_sector_type > 1) && audio && (dev->cd_status & CD_STATUS_HAS_AUDIO)) { + cdrom_log(dev->log, "[%s] Attempting to read a data sector " + "from an audio track\n", cdrom_req_modes[cdrom_sector_type]); + return 0; + } else if ((cdrom_sector_type == 1) && + (!audio || !(dev->cd_status & CD_STATUS_HAS_AUDIO))) { + cdrom_log(dev->log, "[Audio] Attempting to read an audio sector " + "from a data track\n"); return 0; } - ret = read_audio(dev, lba, temp_b); - } else if (cdrom_sector_type == 2) { - if (audio || mode2) { - cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id); - return 0; - } - - ret = read_mode1(dev, cdrom_sector_flags, lba, temp_b); - } else if (cdrom_sector_type == 3) { - if (audio || !mode2 || (mode2 & 0x03)) { - cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id); - return 0; - } - - ret = read_mode2_non_xa(dev, cdrom_sector_flags, lba, temp_b); - } else if (cdrom_sector_type == 4) { - if (audio || !mode2 || ((mode2 & 0x03) != 1)) { - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id); - return 0; - } - - read_mode2_xa_form1(dev, cdrom_sector_flags, lba, temp_b); - } else if (cdrom_sector_type == 5) { - if (audio || !mode2 || ((mode2 & 0x03) != 2)) { - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", dev->id); - return 0; - } - - ret = read_mode2_xa_form2(dev, cdrom_sector_flags, lba, temp_b); - } else if (cdrom_sector_type == 8) { if (audio) { - cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id); - return 0; - } + if (!track_type_is_valid(dev, cdrom_sector_type, cdrom_sector_flags, 1, 0x00)) + ret = 0; + else + ret = read_audio(dev, lba, temp_b); + } else { + int form = 0; - if (unk) { - /* This is needed to correctly read Mode 2 XA Form 1 sectors over IOCTL. */ ret = read_data(dev, lba); - if (raw_buffer[0x000f] == 0x02) { - cdrom_log("CD-ROM %i: [Any Data] Unknown data type determined to be XA Mode 2 Form 1\n", dev->id); - process_mode2_xa_form1(dev, cdrom_sector_flags, temp_b); - } else { - cdrom_log("CD-ROM %i: [Any Data] Unknown data type determined to be Mode 1\n", dev->id); - process_mode1(dev, cdrom_sector_flags, temp_b); + if ((raw_buffer[0x000f] == 0x00) || (raw_buffer[0x000f] > 0x02)) { + cdrom_log(dev->log, "[%s] Unknown mode: %02X\n", + cdrom_req_modes[cdrom_sector_type], raw_buffer[0x000f]); + return 0; + } + + if (mode2) { + if (raw_buffer[0x000f] == 0x01) + log_fatal(dev->log, "Mode 1 sector on CD-I/XA disc\n"); + else if (raw_buffer[0x0012] != raw_buffer[0x0016]) { + cdrom_log(dev->log, "[%s] XA Mode 2 sector with malformed " + "sub-header\n", cdrom_req_modes[cdrom_sector_type], + raw_buffer[0x000f]); + return 0; + } else + form = ((raw_buffer[0x0012] & 0x20) >> 5) + 1; + } else if (raw_buffer[0x000f] == 0x02) + mode2 = 1; + + const int mode_id = mode2 + form; + + cdrom_log(dev->log, "[%s] %s detected\n", cdrom_req_modes[cdrom_sector_type], + cdrom_modes[mode_id]); + + if (!track_type_is_valid(dev, cdrom_sector_type, cdrom_sector_flags, 0, + (mode2 << 2) + form)) + return 0; + + /* It just so happens that only modes with even ID's have a sector user data size of 2048. */ + if (cdrom_mode_masks[cdrom_sector_type] & (1 << mode_id)) + cdrom_process_data[mode_id](dev, cdrom_sector_flags, temp_b); + else { + cdrom_log(dev->log, "[%s] Attempting to read a %s sector\n", + cdrom_req_modes[cdrom_sector_type], cdrom_modes[mode_id]); + return 0; } - } else if (mode2 && ((mode2 & 0x03) == 1)) - ret = read_mode2_xa_form1(dev, cdrom_sector_flags, lba, temp_b); - else if (!mode2) - ret = read_mode1(dev, cdrom_sector_flags, lba, temp_b); - else { - cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size " - "is not 2048 bytes\n", dev->id); - return 0; - } - } else { - if (mode2) { - if ((mode2 & 0x03) == 0x01) - ret = read_mode2_xa_form1(dev, cdrom_sector_flags, lba, temp_b); - else if ((mode2 & 0x03) == 0x02) - ret = read_mode2_xa_form2(dev, cdrom_sector_flags, lba, temp_b); - else - ret = read_mode2_non_xa(dev, cdrom_sector_flags, lba, temp_b); - } else { - if (audio) - ret = read_audio(dev, lba, temp_b); - else - ret = read_mode1(dev, cdrom_sector_flags, lba, temp_b); } } if ((cdrom_sector_flags & 0x06) == 0x02) { /* Add error flags. */ - cdrom_log("CD-ROM %i: Error flags\n", dev->id); + cdrom_log(dev->log, "Error flags\n"); memcpy(b + cdrom_sector_size, extra_buffer, 294); cdrom_sector_size += 294; } else if ((cdrom_sector_flags & 0x06) == 0x04) { /* Add error flags. */ - cdrom_log("CD-ROM %i: Full error flags\n", dev->id); + cdrom_log(dev->log, "Full error flags\n"); memcpy(b + cdrom_sector_size, extra_buffer, 296); cdrom_sector_size += 296; } if ((cdrom_sector_flags & 0x700) == 0x100) { - cdrom_log("CD-ROM %i: Raw subchannel data\n", dev->id); + cdrom_log(dev->log, "Raw subchannel data\n"); memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); cdrom_sector_size += 96; } else if ((cdrom_sector_flags & 0x700) == 0x200) { - cdrom_log("CD-ROM %i: Q subchannel data\n", dev->id); + cdrom_log(dev->log, "Q subchannel data\n"); memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); cdrom_sector_size += 16; } else if ((cdrom_sector_flags & 0x700) == 0x400) { - cdrom_log("CD-ROM %i: R/W subchannel data\n", dev->id); + cdrom_log(dev->log, "R/W subchannel data\n"); memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); cdrom_sector_size += 96; } @@ -2018,22 +2268,381 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c return ret; } -/* Peform a master init on the entire module. */ -void -cdrom_global_init(void) +/* + Read DVD Structure + + Yes, +2 instead of +4 is correct, I have verified this via Windows IOCTL, and it also matches + the MMC specification. + */ +int +cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_t layer, const uint8_t format, + uint8_t *buffer, uint32_t *info) { - /* Clear the global data. */ - memset(cdrom, 0x00, sizeof(cdrom)); + int max_layer = 0; + int ret = 0; + uint64_t total_sectors; + + if (format < 0xc0) { + if (dev->cd_status != CD_STATUS_DVD) { + *info = format; + ret = -(SENSE_ILLEGAL_REQUEST << 16) | (ASC_INCOMPATIBLE_FORMAT << 8); + } else if ((dev->ops != NULL) && (dev->ops->read_dvd_structure != NULL)) + ret = dev->ops->read_dvd_structure(dev->local, layer, format, buffer, info); + } + + if (ret == 0) switch (format) { + case 0x00: /* Physical format information */ + total_sectors = (uint64_t) dev->cdrom_capacity; + + if (total_sectors > DVD_LAYER_0_SECTORS) + max_layer++; + + if (layer > max_layer) { + *info = layer; + ret = -(SENSE_ILLEGAL_REQUEST << 16) | (ASC_INV_FIELD_IN_CMD_PACKET << 8); + } else { + if (total_sectors == 0) { + *info = 0x00000000; + ret = -(SENSE_NOT_READY << 16) | (ASC_MEDIUM_NOT_PRESENT << 8); + } else { + buffer[4] = 0x01; /* DVD-ROM, part version 1. */ + buffer[5] = 0x0f; /* 120mm disc, minimum rate unspecified .*/ + if (max_layer == 1) + /* Two layers, OTP track path, read-only (per MMC-2 spec). */ + buffer[6] = 0x31; + else + /* One layer, read-only (per MMC-2 spec). */ + buffer[6] = 0x01; + buffer[7] = 0x10; /* Default densities. */ + + /* Start sector. */ + buffer[8] = 0x00; + buffer[9] = (0x030000 >> 16) & 0xff; + buffer[10] = (0x030000 >> 8) & 0xff; + buffer[11] = 0x030000 & 0xff; + + /* End sector. */ + buffer[12] = 0x00; + if (layer == 1) { + buffer[13] = ((total_sectors - DVD_LAYER_0_SECTORS) >> 16) & 0xff; + buffer[14] = ((total_sectors - DVD_LAYER_0_SECTORS) >> 8) & 0xff; + buffer[15] = (total_sectors - DVD_LAYER_0_SECTORS) & 0xff; + } else if (max_layer == 1) { + buffer[13] = (DVD_LAYER_0_SECTORS >> 16) & 0xff; + buffer[14] = (DVD_LAYER_0_SECTORS >> 8) & 0xff; + buffer[15] = DVD_LAYER_0_SECTORS & 0xff; + } else { + buffer[13] = (total_sectors >> 16) & 0xff; + buffer[14] = (total_sectors >> 8) & 0xff; + buffer[15] = total_sectors & 0xff; + } + + /* Layer 0 end sector. */ + buffer[16] = 0x00; + buffer[17] = (total_sectors >> 16) & 0xff; + buffer[18] = (total_sectors >> 8) & 0xff; + buffer[19] = total_sectors & 0xff; + + buffer[20] = 0x00; /* No BCA */ + + /* 2048 bytes of data + 2 byte header */ + ret = (2048 + 2); + } + } + break; + + case 0x01: /* DVD copyright information */ + buffer[4] = 0; /* No copyright data. */ + buffer[5] = 0; /* No region restrictions. */ + + /* 4 bytes of data + 2 byte header. */ + ret = (4 + 2); + break; + + case 0x04: /* DVD disc manufacturing information. */ + /* 2048 bytes of data + 2 byte header */ + ret = (2048 + 2); + break; + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buffer[4] = 0x00; /* Physical format */ + buffer[5] = 0x40; /* Not writable, is readable */ + buffer[6] = ((2048 + 4) >> 8) & 0xff; + buffer[7] = (2048 + 4) & 0xff; + + buffer[8] = 0x01; /* Copyright info */ + buffer[9] = 0x40; /* Not writable, is readable */ + buffer[10] = ((4 + 2) >> 8) & 0xff; + buffer[11] = (4 + 2) & 0xff; + + buffer[12] = 0x03; /* BCA info */ + buffer[13] = 0x40; /* Not writable, is readable */ + buffer[14] = ((188 + 2) >> 8) & 0xff; + buffer[15] = (188 + 2) & 0xff; + + buffer[16] = 0x04; /* Manufacturing info */ + buffer[17] = 0x40; /* Not writable, is readable */ + buffer[18] = ((2048 + 2) >> 8) & 0xff; + buffer[19] = (2048 + 2) & 0xff; + + /* data written + 4 byte header */ + ret = (16 + 2); + break; + + default: + *info = format; + ret = -(SENSE_ILLEGAL_REQUEST << 16) | (ASC_INV_FIELD_IN_CMD_PACKET << 8); + break; + } + + return ret; } -static void -cdrom_drive_reset(cdrom_t *dev) +void +cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer) { - dev->priv = NULL; - dev->insert = NULL; - dev->close = NULL; - dev->get_volume = NULL; - dev->get_channel = NULL; + uint8_t rti[65536] = { 0 }; + raw_track_info_t *t = (raw_track_info_t *) rti; + int num = 0; + int first = 0; + int sessions = 0; + int ls_first = 0; + int ls_last = 0; + int t_b0 = -1; + + dev->ops->get_raw_track_info(dev->local, &num, rti); + + for (int i = 0; i < num; i++) + if (t[i].session > sessions) + sessions = t[i].session; + else if ((first == 0) && (t[i].point >= 1) && (t[i].point <= 99)) + first = t[i].point; + + for (int i = 0; i < num; i++) + if ((t[i].session == sessions) && (t[i].point >= 1) && (t[i].point <= 99)) { + ls_first = t[i].point; + break; + } + + for (int i = (num - 1); i >= 0; i--) + if ((t[i].session == sessions) && (t[i].point >= 1) && (t[i].point <= 99)) { + ls_last = t[i].point; + break; + } + + for (int i = (num - 1); i >= 0; i--) + if (t[i].point == 0xb0) { + t_b0 = i; + break; + } + + memset(buffer, 0x00, 34); + + buffer[ 0] = 0x00; /* Disc Information Length (MSB) */ + buffer[ 1] = 0x20; /* Disc Information Lenght (LSB) */ + buffer[ 2] = 0x0e; /* Last session complete, disc finalized */ + buffer[ 3] = first; /* Number of First Track on Disc */ + buffer[ 4] = sessions; /* Number of Sessions (LSB) */ + buffer[ 5] = ls_first; /* First Track Number in Last Session (LSB) */ + buffer[ 5] = ls_last; /* Last Track Number in Last Session (LSB) */ + buffer[ 7] = 0x20; /* Unrestricted use */ + buffer[ 8] = t[0].ps; /* Disc Type */ + buffer[ 9] = 0x00; /* Number Of Sessions (MSB) */ + buffer[10] = 0x00; /* First Track Number in Last Session (MSB) */ + buffer[11] = 0x00; /* Last Track Number in Last Session (MSB) */ + + if (t_b0 == -1) { + /* Single-session disc. */ + + /* Last Session Lead-in Start Time MSF is 00:00:00 */ + + /* Last Possible Start Time for Start of Lead-out */ + buffer[20] = t[2].pm; + buffer[21] = t[2].ps; + buffer[22] = t[2].pf; + } else { + /* Multi-session disc. */ + + /* Last Session Lead-in Start Time MSF */ + buffer[17] = t[t_b0].m; + buffer[18] = t[t_b0].s; + buffer[19] = t[t_b0].f; + + /* Last Possible Start Time for Start of Lead-out */ + buffer[20] = t[t_b0].pm; + buffer[21] = t[t_b0].ps; + buffer[22] = t[t_b0].pf; + } +} + +int +cdrom_read_track_information(const cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer) +{ + uint8_t rti[65536] = { 0 }; + const raw_track_info_t *t = (raw_track_info_t *) rti; + const raw_track_info_t *track = NULL; + const raw_track_info_t lead_in = { 0 }; + const uint32_t pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + uint32_t real_pos = pos; + int num = 0; + int ret; + + dev->ops->get_raw_track_info(dev->local, &num, rti); + + switch (cdb[1] & 0x03) { + default: + ret = -cdb[1]; + break; + case 0x00: + if (num < 4) + ret = -pos; + else { + for (int i = 0; i < num; i++) { + const raw_track_info_t *ct = &(t[i]); + const uint32_t start = ((ct->pm * 60 * 75) + (ct->ps * 75) + + ct->pf) - 150; + if (pos > start) { + track = ct; + break; + } + } + + if (track == NULL) + ret = -cdb[1]; + else + ret = 36; + } + break; + case 0x01: + switch (pos) { + default: + /* + TODO: Does READ TRACK INFORMATION use track AAh + or the raw A0h, A1h, and A2h? + */ + if (pos == 0xaa) + real_pos = 0xa2; + + for (int i = 0; i < num; i++) { + const raw_track_info_t *ct = &(t[i]); + if (ct->point == real_pos) { + track = ct; + break; + } + } + + if (track == NULL) + ret = -pos; + else + ret = 36; + break; + case 0x00: + track = &lead_in; + ret = 36; + break; + case 0xff: + ret = -pos; + break; + } + break; + case 0x02: + for (int i = 0; i < num; i++) { + const raw_track_info_t *ct = &(t[i]); + if ((ct->session == pos) && (ct->point >= 1) && (ct->point <= 99)) { + track = ct; + break; + } + } + + if (track == NULL) + ret = -pos; + else + ret = 36; + break; + } + + if (ret == 36) { + uint32_t start = ((track->pm * 60 * 75) + (track->ps * 75) + + track->pf) - 150; + uint32_t len = 0x00000000; + uint8_t mode = 0xf; + + memset(buffer, 0, 36); + buffer[0] = 0x00; + buffer[1] = 0x22; + buffer[2] = track->point; /* Track number (LSB). */ + buffer[3] = track->session; /* Session number (LSB). */ + /* Not damaged, primary copy. */ + buffer[5] = track->adr_ctl & 0x04; + + if ((track->point >= 1) && (track->point >= 99)) { + for (int i = 0; i < num; i++) { + const raw_track_info_t *ct = &(t[i]); + const uint32_t ts = ((ct->pm * 60 * 75) + (ct->ps * 75) + + ct->pf) - 150; + if ((ts > start) && ((ct->point == 0xa2) || ((ct->point >= 1) && + (ct->point <= 99)))) { + len = ts - start; + break; + } + } + + if (track->adr_ctl & 0x04) { + ret = read_data(dev, start); + mode = raw_buffer[3]; + } + } else if (track->point != 0xa2) + start = 0x00000000; + + /* Not reserved track, not blank, not packet writing, not fixed packet. */ + buffer[ 6] = mode << 0; + /* Last recorded address not valid, next recordable address not valid. */ + buffer[ 7] = 0x00; + + buffer[ 8] = (start >> 24) & 0xff; + buffer[ 9] = (start >> 16) & 0xff; + buffer[10] = (start >> 8) & 0xff; + buffer[11] = start & 0xff; + + buffer[24] = (len >> 24) & 0xff; + buffer[25] = (len >> 16) & 0xff; + buffer[26] = (len >> 8) & 0xff; + buffer[27] = len & 0xff; + } + + return ret; +} + +int +cdrom_ext_medium_changed(const cdrom_t *dev) +{ + int ret = 0; + + if (dev && dev->ops && dev->ops->ext_medium_changed && + (dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED)) + ret = dev->ops->ext_medium_changed(dev->local); + + return ret; +} + +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; } #ifdef ENABLE_CDROM_LOG @@ -2047,7 +2656,7 @@ cdrom_toc_dump(cdrom_t *dev) fwrite(b, 1, len, f); fflush(f); fclose(f); - pclog("Written TOC of %i bytes to %s\n", len, fn2); + 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); @@ -2056,7 +2665,7 @@ cdrom_toc_dump(cdrom_t *dev) fwrite(b, 1, len, f); fflush(f); fclose(f); - pclog("Written cooked TOC of %i bytes to %s\n", len, fn2); + 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); @@ -2065,24 +2674,96 @@ cdrom_toc_dump(cdrom_t *dev) fwrite(b, 1, len, f); fflush(f); fclose(f); - pclog("Written session TOC of %i bytes to %s\n", len, fn2); + cdrom_log(dev->log, "Written session TOC of %i bytes to %s\n", len, fn2); } #endif +int +cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert) +{ + const int was_empty = cdrom_is_empty(dev->id); + int ret = 0; + + /* Make sure to not STRCPY if the two are pointing + at the same place. */ + if (fn != dev->image_path) + strcpy(dev->image_path, fn); + + /* Open the target. */ + if ((strlen(dev->image_path) != 0) && + (strstr(dev->image_path, "ioctl://") == dev->image_path)) + dev->local = ioctl_open(dev, dev->image_path); + else + dev->local = image_open(dev, dev->image_path); + + if (dev->local == NULL) { + dev->ops = NULL; + dev->image_path[0] = 0; + + ret = 1; + } else { + /* All good, reset state. */ + dev->seek_pos = 0; + dev->cd_buflen = 0; + + 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 : + CD_STATUS_DATA_ONLY; + + dev->cdrom_capacity = dev->ops->get_last_block(dev->local); + + cdrom_log(dev->log, "CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", + dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL); + } + +#ifdef ENABLE_CDROM_LOG + cdrom_toc_dump(dev); +#endif + + if (!skip_insert) { + /* Signal media change to the emulated machine. */ + cdrom_insert(dev->id); + + /* The drive was previously empty, transition directly to UNIT ATTENTION. */ + if (was_empty) + cdrom_insert(dev->id); + } + + return ret; +} + +/* Peform a master init on the entire module. */ +void +cdrom_global_init(void) +{ + /* Clear the global data. */ + memset(cdrom, 0x00, sizeof(cdrom)); +} + void cdrom_hard_reset(void) { - cdrom_t *dev; - for (uint8_t i = 0; i < CDROM_NUM; i++) { - dev = &cdrom[i]; - if (dev->bus_type) { - cdrom_log("CD-ROM %i: Hard reset\n", i); + cdrom_t *dev = &cdrom[i]; - dev->id = i; + if (dev->bus_type) { + cdrom_log(dev->log, "Hard reset\n"); + + 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"); cdrom_drive_reset(dev); + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i ", i + 1); + dev->log = log_open(n); + switch (dev->bus_type) { case CDROM_BUS_ATAPI: case CDROM_BUS_SCSI: @@ -2105,18 +2786,7 @@ cdrom_hard_reset(void) dev->image_path[strlen(dev->image_path) - 1] = '/'; #endif - if ((strlen(dev->image_path) != 0) && (strstr(dev->image_path, "ioctl://") == dev->image_path)) - cdrom_ioctl_open(dev, dev->image_path); - else - cdrom_image_open(dev, dev->image_path); - - cdrom_insert(i); - cdrom_insert(i); - -#ifdef ENABLE_CDROM_LOG - if (i == 0) - cdrom_toc_dump(dev); -#endif + cdrom_load(dev, dev->image_path, 0); } } } @@ -2127,10 +2797,8 @@ cdrom_hard_reset(void) void cdrom_close(void) { - cdrom_t *dev; - for (uint8_t i = 0; i < CDROM_NUM; i++) { - dev = &cdrom[i]; + cdrom_t *dev = &cdrom[i]; if (dev->bus_type == CDROM_BUS_SCSI) memset(&scsi_devices[dev->scsi_device_id], 0x00, sizeof(scsi_device_t)); @@ -2138,92 +2806,79 @@ cdrom_close(void) if (dev->close) dev->close(dev->priv); - if (dev->ops && dev->ops->exit) - dev->ops->exit(dev); + cdrom_unload(dev); dev->ops = NULL; dev->priv = NULL; cdrom_drive_reset(dev); + + if (dev->log != NULL) { + cdrom_log(dev->log, "Log closed\n"); + + log_close(dev->log); + dev->log = NULL; + } } } /* Signal disc change to the emulated machine. */ void -cdrom_insert(uint8_t id) +cdrom_insert(const uint8_t id) { - cdrom_t *dev = &cdrom[id]; + const cdrom_t *dev = &cdrom[id]; if (dev->bus_type && dev->insert) dev->insert(dev->priv); } void -cdrom_exit(uint8_t id) +cdrom_exit(const uint8_t id) { cdrom_t *dev = &cdrom[id]; strcpy(dev->prev_image_path, dev->image_path); if (dev->ops) { - if (dev->ops->exit) - dev->ops->exit(dev); + cdrom_unload(dev); dev->ops = NULL; } memset(dev->image_path, 0, sizeof(dev->image_path)); - cdrom_log("cdrom_exit(%i): cdrom_insert(%i)\n", id, id); + cdrom_log(dev->log, "cdrom_exit(): cdrom_insert()\n"); cdrom_insert(id); } -int -cdrom_is_empty(uint8_t id) -{ - 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(uint8_t id) +cdrom_eject(const uint8_t id) { - cdrom_t *dev = &cdrom[id]; + const cdrom_t *dev = &cdrom[id]; - /* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */ - if (strlen(dev->image_path) == 0) - /* Switch from empty to empty. Do nothing. */ - return; + if (strlen(dev->image_path) != 0) { + cdrom_exit(id); - cdrom_exit(id); + plat_cdrom_ui_update(id, 0); - plat_cdrom_ui_update(id, 0); - - config_save(); + config_save(); + } } /* The mechanics of re-loading a CD-ROM drive. */ void -cdrom_reload(uint8_t id) +cdrom_reload(const uint8_t id) { - cdrom_t *dev = &cdrom[id]; - int was_empty = cdrom_is_empty(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)) { /* Switch from empty to empty. Do nothing. */ return; } - if (dev->ops && dev->ops->exit) - dev->ops->exit(dev); + cdrom_unload(dev); + dev->ops = NULL; memset(dev->image_path, 0, sizeof(dev->image_path)); @@ -2242,22 +2897,7 @@ cdrom_reload(uint8_t id) dev->image_path[strlen(dev->image_path) - 1] = '/'; #endif - if ((strlen(dev->image_path) != 0) && (strstr(dev->image_path, "ioctl://") == dev->image_path)) - cdrom_ioctl_open(dev, dev->image_path); - else - cdrom_image_open(dev, dev->image_path); - -#ifdef ENABLE_CDROM_LOG - cdrom_toc_dump(dev); -#endif - - /* Signal media change to the emulated machine. */ - cdrom_log("cdrom_reload(%i): cdrom_insert(%i)\n", id, id); - cdrom_insert(id); - - /* The drive was previously empty, transition directly to UNIT ATTENTION. */ - if (was_empty) - cdrom_insert(id); + cdrom_load(dev, dev->image_path, 0); } plat_cdrom_ui_update(id, 1); diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 0c7870902..e4a425c78 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -6,63 +6,1705 @@ * * This file is part of the 86Box distribution. * - * CD-ROM image support. + * CD-ROM image file handling module. * + * Authors: Miran Grca, + * RichardG, + * Cacodemon345 * - * - * Authors: RichardG867, - * Miran Grca, - * bit, - * - * Copyright 2015-2019 Richardg867. - * Copyright 2015-2019 Miran Grca. - * Copyright 2017-2019 bit. + * Copyright 2016-2025 Miran Grca. + * Copyright 2016-2025 RichardG. + * Copyright 2024-2025 Cacodemon345. */ +#define __STDC_FORMAT_MACROS +#include #include +#ifdef ENABLE_IMAGE_LOG #include -#include +#endif #include -#include +#include #include -#include -#define HAVE_STDARG_H +#include +#include +#ifndef _WIN32 +# include +#endif #include <86box/86box.h> -#include <86box/config.h> +#include <86box/log.h> #include <86box/path.h> #include <86box/plat.h> -#include <86box/scsi_device.h> -#include <86box/cdrom_image_backend.h> #include <86box/cdrom.h> #include <86box/cdrom_image.h> +#include <86box/cdrom_image_viso.h> -#ifdef ENABLE_CDROM_IMAGE_LOG -int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; +#include + +#define MAX_LINE_LENGTH 512 +#define MAX_FILENAME_LENGTH 256 +#define CROSS_LEN 512 + +static char temp_keyword[1024]; + +#define INDEX_SPECIAL -2 /* Track A0h onwards. */ +#define INDEX_NONE -1 /* Empty block. */ +#define INDEX_ZERO 0 /* Block not in the file, return all 0x00's. */ +#define INDEX_NORMAL 1 /* Block in the file. */ + +typedef struct track_index_t { + /* + Is the current block in the file? If not, return all 0x00's. -1 means not + yet loaded. + */ + int32_t type; + /* The amount of bytes to skip at the beginning of each sector. */ + int32_t skip; + /* + Starting and ending sector LBA - negative in order to accomodate LBA -150 to -1 + to read the pregap of track 1. + */ + uint64_t start; + uint64_t length; + uint64_t file_start; + uint64_t file_length; + track_file_t *file; +} track_index_t; + +typedef struct track_t { + uint8_t session; + uint8_t attr; + uint8_t tno; + uint8_t point; + uint8_t extra[4]; + uint8_t mode; + uint8_t form; + uint8_t subch_type; + uint8_t skip; + uint32_t sector_size; + track_index_t idx[3]; +} track_t; + +typedef struct cd_image_t { + cdrom_t *dev; + void *log; + int is_dvd; + int has_audio; + int32_t tracks_num; + uint32_t bad_sectors_num; + track_t *tracks; + uint32_t *bad_sectors; +} cd_image_t; + +#ifdef ENABLE_IMAGE_LOG +int image_do_log = ENABLE_IMAGE_LOG; void -cdrom_image_log(const char *fmt, ...) +image_log(void *priv, const char *fmt, ...) { va_list ap; - if (cdrom_image_do_log) { + if (image_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } + +static char *cit[4] = { "SPECIAL", "NONE", "ZERO", "NORMAL" }; #else -# define cdrom_image_log(fmt, ...) +# define image_log(priv, fmt, ...) #endif -/* 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) +typedef struct audio_file_t { + SNDFILE *file; + SF_INFO info; +} audio_file_t; + +/* Audio file functions */ +static int +audio_read(void *priv, uint8_t *buffer, const uint64_t seek, const size_t count) +{ + const track_file_t *tf = (track_file_t *) priv; + const audio_file_t *audio = (audio_file_t *) tf->priv; + const uint64_t samples_seek = seek / 4; + const uint64_t samples_count = count / 4; + + if ((seek & 3) || (count & 3)) { + image_log(tf->log, "CD Audio file: Reading on non-4-aligned boundaries.\n"); + } + + const sf_count_t res = sf_seek(audio->file, samples_seek, SEEK_SET); + + if (res == -1) + return 0; + + return !!sf_readf_short(audio->file, (short *) buffer, samples_count); +} + +static uint64_t +audio_get_length(void *priv) +{ + const track_file_t *tf = (track_file_t *) priv; + const audio_file_t *audio = (audio_file_t *) tf->priv; + + /* Assume 16-bit audio, 2 channel. */ + return audio->info.frames * 4ull; +} static void -image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) +audio_close(void *priv) { - cd_img_t *img = (cd_img_t *) dev->local; - track_t *ct = NULL; + track_file_t *tf = (track_file_t *) priv; + audio_file_t *audio = (audio_file_t *) tf->priv; + + memset(tf->fn, 0x00, sizeof(tf->fn)); + if (audio && audio->file) + sf_close(audio->file); + free(audio); + free(tf); +} + +static track_file_t * +audio_init(const uint8_t id, const char *filename, int *error) +{ + track_file_t *tf = (track_file_t *) calloc(sizeof(track_file_t), 1); + audio_file_t *audio = (audio_file_t *) calloc(sizeof(audio_file_t), 1); +#ifdef _WIN32 + wchar_t filename_w[4096]; +#endif + + if (tf == NULL || audio == NULL) { + goto cleanup_error; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + strncpy(tf->fn, filename, sizeof(tf->fn) - 1); +#ifdef _WIN32 + mbstowcs(filename_w, filename, 4096); + audio->file = sf_wchar_open(filename_w, SFM_READ, &audio->info); +#else + audio->file = sf_open(filename, SFM_READ, &audio->info); +#endif + + if (audio->file == NULL) { + image_log(tf->log, "Audio file open error!"); + goto cleanup_error; + } + + if (audio->info.channels != 2 || audio->info.samplerate != 44100 || !audio->info.seekable) { + image_log(tf->log, "Audio file not seekable or in non-CD format!"); + sf_close(audio->file); + goto cleanup_error; + } + + *error = 0; + + tf->priv = audio; + tf->fp = NULL; + tf->close = audio_close; + tf->get_length = audio_get_length; + tf->read = audio_read; + + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i Audio", id + 1); + tf->log = log_open(n); + + return tf; +cleanup_error: + free(tf); + free(audio); + *error = 1; + return NULL; +} + +/* Binary file functions. */ +static int +bin_read(void *priv, uint8_t *buffer, const uint64_t seek, const size_t count) +{ + const track_file_t *tf = (track_file_t *) priv; + + if (tf->fp == NULL) + return 0; + + image_log(tf->log, "binary_read(%08lx, pos=%" PRIu64 " count=%lu)\n", + tf->fp, seek, count); + + if (fseeko64(tf->fp, seek, SEEK_SET) == -1) { + image_log(tf->log, "binary_read failed during seek!\n"); + + return -1; + } + + if (fread(buffer, count, 1, tf->fp) != 1) { + image_log(tf->log, "binary_read failed during read!\n"); + + return -1; + } + + if (UNLIKELY(tf->motorola)) { + for (uint64_t i = 0; i < count; i += 2) { + const uint8_t buffer0 = buffer[i]; + const uint8_t buffer1 = buffer[i + 1]; + buffer[i] = buffer1; + buffer[i + 1] = buffer0; + } + } + + return 1; +} + +static uint64_t +bin_get_length(void *priv) +{ + const track_file_t *tf = (track_file_t *) priv; + + if (tf->fp == NULL) + return 0; + + fseeko64(tf->fp, 0, SEEK_END); + const off64_t len = ftello64(tf->fp); + image_log(tf->log, "binary_length(%08lx) = %" PRIu64 "\n", tf->fp, len); + + return len; +} + +static void +bin_close(void *priv) +{ + track_file_t *tf = (track_file_t *) priv; + + if (tf == NULL) + return; + + if (tf->fp != NULL) { + fclose(tf->fp); + tf->fp = NULL; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + + free(priv); +} + +static track_file_t * +bin_init(const uint8_t id, const char *filename, int *error) +{ + track_file_t *tf = (track_file_t *) calloc(1, sizeof(track_file_t)); + struct stat stats; + + if (tf == NULL) { + *error = 1; + return NULL; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + strncpy(tf->fn, filename, sizeof(tf->fn) - 1); + tf->fp = plat_fopen64(tf->fn, "rb"); + image_log(tf->log, "binary_open(%s) = %08lx\n", tf->fn, tf->fp); + + if (stat(tf->fn, &stats) != 0) { + /* Use a blank structure if stat failed. */ + memset(&stats, 0, sizeof(struct stat)); + } + *error = ((tf->fp == NULL) || ((stats.st_mode & S_IFMT) == S_IFDIR)); + + /* Set the function pointers. */ + if (!*error) { + tf->read = bin_read; + tf->get_length = bin_get_length; + tf->close = bin_close; + + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i Bin ", id + 1); + tf->log = log_open(n); + } else { + /* From the check above, error may still be non-zero if opening a directory. + * The error is set for viso to try and open the directory following this function. + * However, we need to make sure the descriptor is closed. */ + if ((tf->fp != NULL) && ((stats.st_mode & S_IFMT) == S_IFDIR)) { + /* tf is freed by bin_close */ + bin_close(tf); + } else + free(tf); + tf = NULL; + } + + return tf; +} + +static track_file_t * +index_file_init(const uint8_t id, const char *filename, int *error, int *is_viso) +{ + track_file_t *tf = NULL; + + *is_viso = 0; + + /* Current we only support .BIN files, either combined or one per + track. In the future, more is planned. */ + tf = bin_init(id, filename, error); + + if (*error) { + if ((tf != NULL) && (tf->close != NULL)) { + tf->close(tf); + tf = NULL; + } + + tf = viso_init(id, filename, error); + + if (!*error) + *is_viso = 1; + } + + return tf; +} + +static void +index_file_close(track_index_t *idx) +{ + if ((idx == NULL) || (idx->file == NULL) || + (idx->file->close == NULL)) + return; + + idx->file->close(idx->file); + + image_log(idx->file->log, "Log closed\n"); + + if (idx->file->log != NULL) { + log_close(idx->file->log); + idx->file->log = NULL; + } + + idx->file = NULL; +} + +/* Internal functions. */ +static int +image_get_track(const cd_image_t *img, const uint32_t sector) +{ + int ret = -1; + + for (int i = 0; i < img->tracks_num; i++) { + track_t *ct = &(img->tracks[i]); + for (int j = 0; j < 3; j++) { + const 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))) { + ret = i; + break; + } + } + } + + return ret; +} + +static void +image_get_track_and_index(const cd_image_t *img, const uint32_t sector, + int *track, int *index) +{ + *track = -1; + *index = -1; + + for (int i = 0; i < img->tracks_num; i++) { + track_t *ct = &(img->tracks[i]); + 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))) { + *track = i; + *index = j; + break; + } + } + } +} + +static int +image_is_sector_bad(const cd_image_t *img, const uint32_t sector) +{ + int ret = 0; + + if (img->bad_sectors_num > 0) for (int i = 0; i < img->bad_sectors_num; i++) + if (img->bad_sectors[i] == sector) { + ret = 1; + break; + } + + return ret; +} + +static int +image_is_track_audio(const cd_image_t *img, const uint32_t pos) +{ + int ret = 0; + + if (img->has_audio) { + const int track = image_get_track(img, pos); + + if (track >= 0) { + const track_t *trk = &(img->tracks[track]); + + ret = (trk->mode == 0); + } + } + + return ret; +} + +static int +image_can_read_pvd(track_file_t *file, const uint64_t start, + const uint64_t sector_size, const int xa) +{ + uint8_t buf[2448] = { 0 }; + /* First VD is located at sector 16. */ + uint64_t seek = start + (16ULL * sector_size); + uint8_t *pvd = (uint8_t *) buf; + + if (sector_size >= RAW_SECTOR_SIZE) { + if (xa) + pvd = &(buf[24]); + else + pvd = &(buf[16]); + } else if (sector_size >= 2332) { + if (xa) + pvd = &(buf[8]); + } + + file->read(file, buf, seek, sector_size); + + int ret = (((pvd[0] == 1) && + !strncmp((char *) &(pvd[1]), "CD001", 5) && + (pvd[6] == 1)) || + ((pvd[8] == 1) && + !strncmp((char *) &(pvd[9]), "CDROM", 5) && + (pvd[14] == 1))); + + if (ret) { + if (sector_size >= RAW_SECTOR_SIZE) { + if (xa) + /* Mode 2 XA, Form from the sub-header. */ + ret = 0x20 | (((buf[18] & 0x20) >> 5) + 1); + else + /* Mode from header. */ + ret = buf[15] << 4; + } else if (sector_size >= 2332) { + if (xa) + /* Mode 2 XA, Form from the sub-header. */ + ret = 0x20 | (((buf[2] & 0x20) >> 5) + 1); + else + /* Mode 2 non-XA. */ + ret = 0x20; + } else if (sector_size >= 2324) + /* Mode 2 XA Form 2. */ + ret = 0x22; + else if (!strncmp((char *) &(pvd[0x400]), "CD-XA001", 8)) + /* Mode 2 XA Form 1. */ + ret = 0x21; + else + /* Mode 1. */ + ret = 0x10; + } + + return ret; +} + +static int +image_cue_get_buffer(char *str, char **line, const int up) +{ + char *s = *line; + char *p = str; + int quote = 0; + int done = 0; + int space = 1; + + /* Copy to local buffer until we have end of string or whitespace. */ + while (!done) { + switch (*s) { + case '\0': + if (quote) { + /* Ouch, unterminated string.. */ + return 0; + } + done = 1; + break; + + case '\"': + quote ^= 1; + break; + + case ' ': + case '\t': + if (space) + break; + + if (!quote) { + done = 1; + break; + } + fallthrough; + + default: + if (up && islower((int) *s)) + *p++ = toupper((int) *s); + else + *p++ = *s; + space = 0; + break; + } + + if (!done) + s++; + } + *p = '\0'; + + *line = s; + + return 1; +} + +static int +image_cue_get_keyword(char **dest, char **line) +{ + int success = image_cue_get_buffer(temp_keyword, line, 1); + + if (success) + *dest = temp_keyword; + + return success; +} + +/* Get a string from the input line, handling quotes properly. */ +static uint64_t +image_cue_get_number(char **line) +{ + char temp[128]; + uint64_t num; + + if (!image_cue_get_buffer(temp, line, 0)) + return 0; + + if (sscanf(temp, "%" PRIu64, &num) != 1) + return 0; + + return num; +} + +static int +image_cue_get_frame(uint64_t *frames, char **line) +{ + char temp[128]; + int min = 0; + int sec = 0; + int fr = 0; + + int success = image_cue_get_buffer(temp, line, 0); + if (!success) + return 0; + + success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; + if (!success) + return 0; + + *frames = MSF_TO_FRAMES(min, sec, fr); + + return 1; +} + +static int +image_cue_get_flags(track_t *cur, char **line) +{ + char temp[128]; + char temp2[128]; + + int success = image_cue_get_buffer(temp, line, 0); + if (!success) + return 0; + + memset(temp2, 0x00, sizeof(temp2)); + success = sscanf(temp, "%s", temp2) == 1; + if (!success) + return 0; + + if (strstr(temp2, "PRE") != NULL) + cur->attr |= 0x01; + if (strstr(temp2, "DCP") != NULL) + cur->attr |= 0x02; + if (strstr(temp2, "4CH") != NULL) + cur->attr |= 0x08; + + return 1; +} + +static track_t * +image_insert_track(cd_image_t *img, const uint8_t session, const uint8_t point) +{ + track_t *ct = NULL; + + img->tracks_num++; + if (img->tracks == NULL) { + img->tracks = calloc(1, sizeof(track_t)); + ct = &(img->tracks[0]); + } else { + img->tracks = realloc(img->tracks, img->tracks_num * sizeof(track_t)); + ct = &(img->tracks[img->tracks_num - 1]); + } + + image_log(img->log, " [TRACK ] Insert %02X: img->tracks[%2i]\n", + point, img->tracks_num - 1); + + memset(ct, 0x00, sizeof(track_t)); + + ct->session = session; + ct->point = point; + + for (int i = 0; i < 3; i++) + ct->idx[i].type = (point > 99) ? INDEX_SPECIAL : INDEX_NONE; + + if (point >= 0xb0) + ct->attr = 0x50; + + return ct; +} + +static void +image_process(cd_image_t *img) +{ + track_t *ct = NULL; + track_t *lt = NULL; + track_index_t *ci = NULL; + track_file_t *tf = NULL; + uint64_t tf_len = 0ULL; + uint64_t cur_pos = 0ULL; + int pos = 0; + int ls = 0; + int map[256] = { 0 }; + int lead[3] = { 0 }; + uint64_t spg[256] = { 0ULL }; + track_t *lo[256] = { 0 }; + + /* + Pass 2 - adjusting pre-gaps of the first track of every session and creating the + map so we can map from <01-99> to <01-99> + so that their times and length can be adjusted correctly in the third and fourth + passes - especially important for multi-session Cue files. + + We have to do that because Cue sheets do not explicitly indicate those pre-gaps + but they are required so we have the correct frames - the first track of each + session always has a pre-gap of at least 0:02:00. We do not adjust it if it is + already present. + */ + image_log(img->log, "Pass 2 (adjusting pre-gaps and preparing map)...\n"); + + /* Pre-gap of the first track of the first session. */ + ct = &(img->tracks[3]); + ci = &(ct->idx[0]); + + if (ci->type == INDEX_NONE) { + ci->type = INDEX_ZERO; + ci->start = 0ULL; + ci->length = 150ULL; + } + + image_log(img->log, " [PREGAP ] Adjusted pre-gap of track %02X (first in " + "session %i)\n", ct->point, ct->session); + + /* The other pre-gaps and the preparation of the map. */ + for (int i = 0; i < img->tracks_num; i++) { + ct = &(img->tracks[i]); + if (((ct->point >= 1) && (ct->point <= 99)) || (ct->point >= 0xb0)) { + if (ct->point == 0xb0) { + /* The first track of a session always has a pre-gap of at least 0:02:00. */ + track_t *ft = &(img->tracks[i + (ct->session == 1) + 4]); + ci = &(ft->idx[0]); + + if (ci->type == INDEX_NONE) { + if (ft->idx[1].type == INDEX_NORMAL) { + ci->type = INDEX_NORMAL; + ci->file_start = ft->idx[1].file_start - 150ULL; + } else { + ci->type = INDEX_ZERO; + ci->start = 0ULL; + ci->length = 150ULL; + } + } + + image_log(img->log, " [PREGAP ] Adjusted pre-gap of track %02X " + "(first in session %i)\n", ft->point, ct->session); + + /* Point B0h found, add the previous three lead tracks. */ + for (int j = 0; j < 3; j++) { + map[pos] = lead[j]; + image_log(img->log, " [REMAP ] Remap %3i to %3i (%02X)\n", pos, + map[pos], 0xa0 + j); + pos++; + } + } + + /* Add the current track. */ + map[pos] = i; + image_log(img->log, " [NORMAL ] Remap %3i to %3i\n", pos, map[pos]); + pos++; + } else if ((ct->point >= 0xa0) && (ct->point <= 0xa2)) { + /* + Collect lead track (A0 = first track in session, A1 = last track in session, + A2 = lead out). + */ + lead[ct->point & 0x03] = i; + + image_log(img->log, " [LEAD ] Lead %i = %3i (%02X)\n", ct->point & 0x03, i, + ct->point); + } + } + + /* Add the last three lead tracks. */ + for (int i = 0; i < 3; i++) { + map[pos] = lead[i]; + image_log(img->log, " [REMAP ] Remap %3i to %3i (%02X)\n", pos, map[pos], + 0xa0 + i); + pos++; + } + + /* + If these two mismatch, it is a fatal condition since it means something + has gone wrong enough that the Cue sheet processing has been messed up. + */ + if (pos != img->tracks_num) + log_fatal(img->log, "Something has gone wrong and we have remappped %3i tracks " + "instead of the expected %3i\n", pos, img->tracks_num); + + /* + Pass 3 - adjusting the time lengths of each index of track according to the + files. + + We have to do that because Cue sheets do not explicitly indicate the lengths + of track, so we have to deduce them from what the combination of the Cue sheet + and the various files give us. + */ + image_log(img->log, "Pass 3 (adjusting track file lengths according to the files)...\n"); + for (int i = (img->tracks_num - 1); i >= 0; i--) { + ct = &(img->tracks[map[i]]); + if (ct->idx[1].type != INDEX_SPECIAL) { + for (int j = 2; j >= 0; j--) { + ci = &(ct->idx[j]); + + /* + If the file is not NULL and is different from the previous file, + open it and read its length. + */ + if ((ci->file != NULL) && (ci->file != tf)) { + tf = ci->file; + if (tf != NULL) { + tf_len = tf->get_length(tf) / ct->sector_size; + image_log(img->log, " [FILE ] File length: %016" + PRIX64 " sectors\n", tf_len); + } + } + + if ((ci->type < INDEX_SPECIAL) || (ci->type > INDEX_NORMAL)) { + image_log(img->log, " [TRACK ] %02X, INDEX %02X, ATTR %02X,\n", + ci->type, j, + ct->attr); + log_fatal(img->log, " Unrecognized index type during " + "Pass 3: %2i\n", + ci->type); + } else if (ci->type == INDEX_NORMAL) { + /* Index was in the cue sheet and is present in the file. */ + ci->file_length = tf_len - ci->file_start; + tf_len -= ci->file_length; + } else { + /* Index was not in the cue sheet or is not present in the file, + keep its length at zero. */ + ci->file_start = tf_len; + } + + image_log(img->log, " [TRACK ] %02X/%02X, INDEX %02X, ATTR %02X, " + "MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, j, + ct->attr, + ct->mode, ct->form, + cit[ci->type + 2]); + image_log(img->log, " file_start = %016" + PRIX64 " (%2i:%02i:%02i),\n", + ci->file_start, + (int) ((ci->file_start / 75) / 60), + (int) ((ci->file_start / 75) % 60), + (int) (ci->file_start % 75)); + image_log(img->log, " file_length = %016" + PRIX64 " (%2i:%02i:%02i),\n", + ci->file_length, + (int) ((ci->file_length / 75) / 60), + (int) ((ci->file_length / 75) % 60), + (int) (ci->file_length % 75)); + image_log(img->log, " remaining = %016" + PRIX64 " (%2i:%02i:%02i)\n", + tf_len, + (int) ((tf_len / 75) / 60), + (int) ((tf_len / 75) % 60), + (int) (tf_len % 75)); + } + } + } + + /* + Pass 4 - calculating the actual track starts and lengths for the TOC. + */ + image_log(img->log, "Pass 4 (calculating the actual track starts " + "and lengths for the TOC)...\n"); + for (int i = 0; i < img->tracks_num; i++) { + ct = &(img->tracks[map[i]]); + if (ct->idx[1].type != INDEX_SPECIAL) { + int session_changed = 0; + + /* + If the session has changed, store the last session + and mark that it has changed. + */ + if (ct->session != ls) { + ls = ct->session; + session_changed = 1; + } + + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + + if ((ci->type < INDEX_SPECIAL) || (ci->type > INDEX_NORMAL)) { + image_log(img->log, " [TRACK ] %02X, INDEX %02X, ATTR %02X,\n", + ci->type, j, + ct->attr); + log_fatal(img->log, " Unrecognized index type during " + "Pass 4: %2i\n", + ci->type); + } else if (ci->type <= INDEX_NONE) + /* Index was not in the cue sheet, keep its length at zero. */ + ci->start = cur_pos; + else if (ci->type == INDEX_ZERO) { + /* Index was in the cue sheet and is not present in the file. */ + ci->start = cur_pos; + cur_pos += ci->length; + } else if (ci->type == INDEX_NORMAL) { + /* Index was in the cue sheet and is present in the file. */ + ci->start = cur_pos; + ci->length = ci->file_length; + cur_pos += ci->file_length; + } + + image_log(img->log, " [TRACK ] %02X/%02X, INDEX %02X, ATTR %02X, " + "MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, j, + ct->attr, + ct->mode, ct->form, + cit[ci->type + 2]); + image_log(img->log, " start = %016" + PRIX64 " (%2i:%02i:%02i),\n", + ci->start, + (int) ((ci->start / 75) / 60), + (int) ((ci->start / 75) % 60), + (int) (ci->start % 75)); + image_log(img->log, " length = %016" + PRIX64 " (%2i:%02i:%02i),\n", + ci->length, + (int) ((ci->length / 75) / 60), + (int) ((ci->length / 75) % 60), + (int) (ci->length % 75)); + image_log(img->log, " cur_pos = %016" + PRIX64 " (%2i:%02i:%02i)\n", + cur_pos, + (int) ((cur_pos / 75) / 60), + (int) ((cur_pos / 75) % 60), + (int) (cur_pos % 75)); + + /* Set the pre-gap of the first track of this session. */ + if (session_changed) + spg[ct->session] = ct->idx[0].start; + } + } + } + + /* + Pass 5 - setting the lead out starts for all sessions. + */ + image_log(img->log, "Pass 5 (setting the lead out starts for all sessions)...\n"); + for (int i = 0; i <= ls; i++) { + lo[i] = NULL; + for (int j = (img->tracks_num - 1); j >= 0; j--) { + const track_t *jt = &(img->tracks[j]); + if ((jt->session == i) && (jt->point >= 1) && (jt->point <= 99)) { + lo[i] = &(img->tracks[j]); + image_log(img->log, " [TRACK ] %02X/%02X, INDEX %02X, ATTR %02X, " + "MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, j, + ct->attr, + ct->mode, ct->form, + cit[ci->type + 2]); + image_log(img->log, " using to calculate the start of session " + "%02X lead out\n", + ct->session); + break; + } + } + } + + /* + Pass 6 - refinining modes and forms, and finalizing all the special tracks. + */ + image_log(img->log, "Pass 6 (refinining modes and forms, and finalizing " + "all the special tracks)...\n"); + for (int i = 0; i < img->tracks_num; i++) { + ct = &(img->tracks[i]); + lt = NULL; + switch (ct->point) { + default: + break; + case 1 ... 99: + ci = &(ct->idx[1]); + + if ((ci->type == INDEX_NORMAL) && (ct->mode >= 1)) { + image_log(img->log, " [TRACK ] %02X/01, INDEX %02X, ATTR %02X, " + "MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, + ct->attr, + ct->mode, ct->form, + cit[ct->idx[1].type + 2]); + + /* Override the loaded modes with that we determine here. */ + int can_read_pvd = image_can_read_pvd(ci->file, + ci->file_start * ct->sector_size, + ct->sector_size, 0); + ct->skip = 0; + if (can_read_pvd) { + ct->mode = can_read_pvd >> 4; + ct->form = can_read_pvd & 0xf; + if (((ct->sector_size == 2332) || (ct->sector_size == 2336)) && + (ct->form >= 1)) + ct->skip = 8; + } else if (ct->sector_size >= 2332) { + can_read_pvd = image_can_read_pvd(ci->file, + ci->file_start * ct->sector_size, + ct->sector_size, 1); + if (can_read_pvd) { + ct->mode = can_read_pvd >> 4; + ct->form = can_read_pvd & 0xf; + if (((ct->sector_size == 2332) || (ct->sector_size == 2336)) && + (ct->form >= 1)) + ct->skip = 8; + } + } + + image_log(img->log, " NEW MODE: %02X/%02X\n", + ct->mode, ct->form); + } + break; + case 0xa0: + for (int j = 0; j < img->tracks_num; j++) { + track_t *jt = &(img->tracks[j]); + if ((jt->session == ct->session) && + (jt->point >= 1) && (jt->point <= 99)) { + lt = jt; + break; + } + } + + if (lt != NULL) { + int disc_type = 0x00; + + ct->attr = lt->attr; + + ct->mode = lt->mode; + ct->form = lt->form; + + if (lt->mode == 2) + disc_type = 0x20; + + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + ci->type = INDEX_ZERO; + ci->start = (lt->point * 60 * 75) + (disc_type * 75); + ci->length = 0; + + image_log(img->log, " [TRACK ] %02X/%02X, INDEX %02X, " + "ATTR %02X, MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, j, + ct->attr, + ct->mode, ct->form, + cit[ci->type + 2]); + image_log(img->log, " first track = %02X, " + "disc type = %02X\n", + lt->point, disc_type); + } + } + break; + case 0xa1: + for (int j = (img->tracks_num - 1); j >= 0; j--) { + track_t *jt = &(img->tracks[j]); + if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { + lt = jt; + break; + } + } + + if (lt != NULL) { + ct->attr = lt->attr; + + ct->mode = lt->mode; + ct->form = lt->form; + + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + ci->type = INDEX_ZERO; + ci->start = (lt->point * 60 * 75); + ci->length = 0; + + image_log(img->log, " [TRACK ] %02X/%02X, INDEX %02X, " + "ATTR %02X, MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, j, + ct->attr, + ct->mode, ct->form, + cit[ci->type + 2]); + image_log(img->log, " last track = %02X\n", + lt->point); + } + } + break; + case 0xa2: + if (lo[ct->session] != NULL) { + /* + We have a track to use for the calculation, first adjust the track's + attribute (ADR/Ctrl), mode, and form to match the last non-special track. + */ + lt = lo[ct->session]; + + ct->attr = lt->attr; + + ct->mode = lt->mode; + ct->form = lt->form; + + if (ct->idx[1].type != INDEX_NORMAL) { + /* + Index not normal, therefore, this is not a lead out track from a + second or afterwards session of a multi-session Cue sheet, calculate + the starting time and update all the indexes accordingly. + */ + const track_index_t *li = &(lt->idx[2]); + + for (int j = 0; j < 3; j++) { + image_log(img->log, " [TRACK ] %02X/%02X, INDEX %02X, " + "ATTR %02X, MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, j, + ct->attr, + ct->mode, ct->form, + cit[ci->type + 2]); + + ci = &(ct->idx[j]); + ci->type = INDEX_ZERO; + ci->start = li->start + li->length; + ci->length = 0; + + image_log(img->log, " start = %016" PRIX64 + " (%2i:%02i:%02i)\n", + ci->start, + (int) ((ci->start / 75) / 60), + (int) ((ci->start / 75) % 60), + (int) (ci->start % 75)); + } + } +#ifdef ENABLE_IMAGE_LOG + else + image_log(img->log, " no start calculation done, " + "already specified\n"); +#endif + } +#ifdef ENABLE_IMAGE_LOG + else + image_log(img->log, " nothing done, no suitable last track " + "found\n"); +#endif + break; + case 0xb0: + /* + B0: MSF points to the beginning of the pre-gap + of the following session's first track. + */ + ct->extra[0] = (spg[ct->session + 1] / 75) / 60; + ct->extra[1] = (spg[ct->session + 1] / 75) % 60; + ct->extra[2] = spg[ct->session + 1] % 75; + + image_log(img->log, " [TRACK ] %02X/%02X, INDEX 01, " + "ATTR %02X, MODE %02X/%02X, %8s,\n", + ct->session, + ct->point, + ct->attr, + ct->mode, ct->form, + cit[ct->idx[1].type + 2]); + image_log(img->log, " %02X:%02X:%02X, %02X,\n", + ct->extra[0], ct->extra[1], ct->extra[2], ct->extra[3]); + + /* + B0 PMSF points to the start of the lead out track + of the last session. + */ + if (lo[ls] != NULL) { + lt = lo[ls]; + const track_index_t *li = &(lt->idx[2]); + + ct->idx[1].start = li->start + li->length; + + image_log(img->log, " start = %016" PRIX64 + " (%2i:%02i:%02i)\n", + ct->idx[1].start, + (int) ((ct->idx[1].start / 75) / 60), + (int) ((ct->idx[1].start / 75) % 60), + (int) (ct->idx[1].start % 75)); + } +#ifdef ENABLE_IMAGE_LOG + else + image_log(img->log, " no start calculation done, " + "no suitable last track found\n"); +#endif + break; + } + } + +#ifdef ENABLE_IMAGE_LOG + image_log(img->log, "Final tracks list:\n"); + for (int i = 0; i < img->tracks_num; i++) { + ct = &(img->tracks[i]); + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + image_log(img->log, " [TRACK ] %02X INDEX %02X: [%8s, %016" PRIX64 "]\n", + ct->point, j, + cit[ci->type + 2], ci->file_start * ct->sector_size); + image_log(img->log, " TOC data: %02X %02X %02X " + "%%02X %02X %02X %02X 02X %02X %02X %02X\n", + ct->session, ct->attr, ct->tno, ct->point, + ct->extra[0], ct->extra[1], ct->extra[2], ct->extra[3], + (uint32_t) ((ci->start / 75) / 60), + (uint32_t) ((ci->start / 75) % 60), + (uint32_t) (ci->start % 75)); + } + } +#endif +} + +static void +image_set_track_subch_type(track_t *ct) +{ + if (ct->sector_size == 2448) + ct->subch_type = 0x08; + else if (ct->sector_size == 2368) + ct->subch_type = 0x10; + else + ct->subch_type = 0x00; +} + +static int +image_load_iso(cd_image_t *img, const char *filename) +{ + track_t *ct = NULL; + track_index_t *ci = NULL; + track_file_t *tf = NULL; + int success = 1; + int error = 1; + int is_viso = 0; + int sector_sizes[8] = { 2448, 2368, RAW_SECTOR_SIZE, 2336, + 2332, 2328, 2324, COOKED_SECTOR_SIZE }; + + img->tracks = NULL; + /* + Pass 1 - loading the ISO image. + */ + image_log(img->log, "Pass 1 (loading the ISO image)...\n"); + img->tracks_num = 0; + + image_insert_track(img, 1, 0xa0); + image_insert_track(img, 1, 0xa1); + image_insert_track(img, 1, 0xa2); + + /* Data track (shouldn't there be a lead in track?). */ + tf = index_file_init(img->dev->id, filename, &error, &is_viso); + + if (error) { + if (tf != NULL) { + tf->close(tf); + tf = NULL; + } + + success = 0; + } else if (is_viso) + success = 3; + + if (success) { + ct = image_insert_track(img, 1, 1); + ci = &(ct->idx[1]); + + ct->form = 0; + ct->mode = 0; + + for (int i = 0; i < 3; i++) + ct->idx[i].type = INDEX_NONE; + + ct->attr = DATA_TRACK; + + /* Try to detect ISO type. */ + ct->mode = 1; + ct->form = 0; + + ci->type = INDEX_NORMAL; + ci->file_start = 0ULL; + + ci->file = tf; + + for (int i = 0; i < 8; i++) { + ct->sector_size = sector_sizes[i]; + int can_read_pvd = image_can_read_pvd(ci->file, 0, ct->sector_size, 0); + if (can_read_pvd) { + ct->mode = can_read_pvd >> 4; + ct->form = can_read_pvd & 0xf; + if (((ct->sector_size == 2332) || (ct->sector_size == 2336)) && + (ct->form >= 1)) + ct->skip = 8; + break; + } else if (ct->sector_size >= 2332) { + can_read_pvd = image_can_read_pvd(ci->file, 0, ct->sector_size, 1); + if (can_read_pvd) { + ct->mode = can_read_pvd >> 4; + ct->form = can_read_pvd & 0xf; + if (((ct->sector_size == 2332) || (ct->sector_size == 2336)) && + (ct->form >= 1)) + ct->skip = 8; + break; + } + } + } + + image_set_track_subch_type(ct); + + image_log(img->log, " [TRACK ] %02X/%02X, ATTR %02X, MODE %02X/%02X,\n", + ct->session, + ct->point, + ct->attr, + ct->mode, ct->form); + image_log(img->log, " %02X:%02X:%02X, %02X, %i\n", + ct->sector_size); + } + + if (success) for (int i = 2; i >= 0; i--) { + if (ct->idx[i].file == NULL) + ct->idx[i].file = tf; + else + break; + } + + tf = NULL; + + if (success) + image_process(img); + else { + image_log(img->log, " [ISO ] Unable to open image or folder \"%s\"\n", + filename); + return 0; + } + + return success; +} + +static int +image_load_cue(cd_image_t *img, const char *cuefile) +{ + track_t *ct = NULL; + track_index_t *ci = NULL; + track_file_t *tf = NULL; + uint64_t frame = 0ULL; + uint64_t last = 0ULL; + uint8_t session = 1; + int last_t = -1; + int is_viso = 0; + int lead[3] = { 0 }; + int error; + char pathname[MAX_FILENAME_LENGTH]; + char buf[MAX_LINE_LENGTH]; + char *line; + char *command; + char *type; + char temp; + + img->tracks = NULL; + img->tracks_num = 0; + + /* Get a copy of the filename into pathname, we need it later. */ + memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(char)); + path_get_dirname(pathname, cuefile); + + /* Open the file. */ + FILE *fp = plat_fopen(cuefile, "r"); + if (fp == NULL) + return 0; + + int success = 0; + + /* + Pass 1 - loading the Cue sheet. + */ + image_log(img->log, "Pass 1 (loading the Cue sheet)...\n"); + img->tracks_num = 0; + + for (int i = 0; i < 3; i++) { + lead[i] = img->tracks_num; + (void) image_insert_track(img, session, 0xa0 + i); + } + + while (1) { + line = buf; + + /* Read a line from the cuesheet file. */ + if (feof(fp) || (fgets(buf, sizeof(buf), fp) == NULL) || ferror(fp)) + break; + + /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, + but do checks to make sure we're not nuking other bytes. */ + for (uint8_t i = 0; i < 2; i++) { + if (strlen(buf) > 0) { + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + /* nuke trailing newline */ + else if (buf[strlen(buf) - 1] == '\r') + buf[strlen(buf) - 1] = '\0'; + /* nuke trailing newline */ + } + } + image_log(img->log, " [LINE ] \"%s\"\n", line); + + (void) image_cue_get_keyword(&command, &line); + + if (!strcmp(command, "FILE")) { + /* The file for the track. */ + char filename[MAX_FILENAME_LENGTH]; + char ansi[MAX_FILENAME_LENGTH]; + + tf = NULL; + + memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); + memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(char)); + + success = image_cue_get_buffer(ansi, &line, 0); + if (!success) + break; + success = image_cue_get_keyword(&type, &line); + if (!success) + break; + + error = 1; + is_viso = 0; + + if (!strcmp(type, "BINARY") || !strcmp(type, "MOTOROLA")) { + if (!path_abs(ansi)) + path_append_filename(filename, pathname, ansi); + else + strcpy(filename, ansi); + + tf = index_file_init(img->dev->id, filename, &error, &is_viso); + + if (tf) + tf->motorola = !strcmp(type, "MOTOROLA"); + } else if (!strcmp(type, "WAVE") || !strcmp(type, "AIFF") || + !strcmp(type, "MP3")) { + if (!path_abs(ansi)) + path_append_filename(filename, pathname, ansi); + else + strcpy(filename, ansi); + tf = audio_init(img->dev->id, filename, &error); + } + if (error) { + if (tf != NULL) { + tf->close(tf); + tf = NULL; + } + success = 0; + } else if (is_viso) + success = 3; + +#ifdef ENABLE_IMAGE_LOG + if (!success) + image_log(img->log, " [FILE ] Unable to open file \"%s\" " + "specified in cue sheet\n", filename); +#endif + } else if (!strcmp(command, "TRACK")) { + int t = image_cue_get_number(&line); + success = image_cue_get_keyword(&type, &line); + + if (!success) + break; + + if (last_t != -1) { + /* + Important: This has to be done like this because pointers + change due to realloc. + */ + ct = &(img->tracks[t]); + + for (int i = 2; i >= 0; i--) { + if (ct->idx[i].file == NULL) + ct->idx[i].file = tf; + else + break; + } + } + + last_t = t; + ct = image_insert_track(img, session, t); + + ct->form = 0; + ct->mode = 0; + + if (!strcmp(type, "AUDIO")) { + ct->sector_size = RAW_SECTOR_SIZE; + ct->attr = AUDIO_TRACK; + } else if (!memcmp(type, "MODE", 4)) { + uint32_t mode; + ct->attr = DATA_TRACK; + sscanf(type, "MODE%" PRIu32 "/%" PRIu32, + &mode, &(ct->sector_size)); + ct->mode = mode; + if (ct->mode == 2) switch(ct->sector_size) { + default: + break; + case 2324: case 2328: + ct->form = 2; + break; + case 2048: case 2332: case 2336: case 2352: case 2368: case 2448: + ct->form = 1; + break; + } + if (((ct->sector_size == 2336) || (ct->sector_size == 2332)) && (ct->mode == 2) && (ct->form == 1)) + ct->skip = 8; + } else if (!memcmp(type, "CD", 2)) { + ct->attr = DATA_TRACK; + ct->mode = 2; + sscanf(type, "CD%c/%i", &temp, &(ct->sector_size)); + } else + success = 0; + + if (success) { + image_set_track_subch_type(ct); + + last = ct->sector_size; + + image_log(img->log, " [TRACK ] %02X/%02X, ATTR %02X, MODE %02X/%02X,\n", + ct->session, + ct->point, + ct->attr, + ct->mode, ct->form); + image_log(img->log, " %i\n", + ct->sector_size); + } +#ifdef ENABLE_IMAGE_LOG + else + image_log(img->log, " [TRACK ] Unable to initialize track %02X " + "specified in Cue sheet\n", t); +#endif + } else if (!strcmp(command, "INDEX")) { + int t = image_cue_get_number(&line); + ci = &(ct->idx[t]); + + ci->type = INDEX_NORMAL; + ci->file = tf; + success = image_cue_get_frame(&frame, &line); + ci->file_start = frame; + + image_log(img->log, " [INDEX ] %02X (%8s): Initialization %s\n", + t, cit[ci->type + 2], success ? "successful" : "failed"); + } else if (!strcmp(command, "PREGAP")) { + ci = &(ct->idx[0]); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = image_cue_get_frame(&frame, &line); + ci->length = frame; + + image_log(img->log, " [INDEX ] 00 (%8s): Initialization %s\n", + cit[ci->type + 2], success ? "successful" : "failed"); + } else if (!strcmp(command, "PAUSE") || !strcmp(command, "ZERO")) { + ci = &(ct->idx[1]); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = image_cue_get_frame(&frame, &line); + ci->length = frame; + + image_log(img->log, " [INDEX ] 01 (%8s): Initialization %s\n", + cit[ci->type + 2], success ? "successful" : "failed"); + } else if (!strcmp(command, "POSTGAP")) { + ci = &(ct->idx[2]); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = image_cue_get_frame(&frame, &line); + ci->length = frame; + + image_log(img->log, " [INDEX ] 02 (%8s): Initialization %s\n", + cit[ci->type + 2], success ? "successful" : "failed"); + } else if (!strcmp(command, "FLAGS")) { + success = image_cue_get_flags(ct, &line); + + image_log(img->log, " [FLAGS ] Initialization %s\n", + success ? "successful" : "failed"); + } else if (!strcmp(command, "REM")) { + success = 1; + char *space = strstr(line, " "); + if (space != NULL) { + space++; + if (space < (line + strlen(line))) { + (void) image_cue_get_keyword(&command, &space); + if (!strcmp(command, "LEAD-OUT")) { + ct = &(img->tracks[lead[2]]); + /* + Mark it this way so file pointers on it are not + going to be adjusted. + */ + last_t = -1; + ct->sector_size = last; + ci = &(ct->idx[1]); + ci->type = INDEX_NORMAL; + ci->file = tf; + success = image_cue_get_frame(&frame, &space); + ci->file_start = frame; + + image_log(img->log, " [LEAD-OUT] Initialization %s\n", + success ? "successful" : "failed"); + } else if (!strcmp(command, "SESSION")) { + session = image_cue_get_number(&space); + + if (session > 1) { + ct = image_insert_track(img, session - 1, 0xb0); + /* + Mark it this way so file pointers on it are not + going to be adjusted. + */ + last_t = -1; + ci = &(ct->idx[1]); + ci->start = (0x40 * 60 * 75) + (0x02 * 75); + + if (session == 2) { + ct->extra[3] = 0x02; + + /* + 00:00:00 on Wembley, C0:00:00 in the spec. + And what's in PMSF? + */ + ct = image_insert_track(img, session - 1, 0xc0); + /* + Mark it this way so file pointers on it are not + going to be adjusted. + */ + last_t = -1; + ci = &(ct->idx[1]); + /* Queen - Live at Wembley '86 CD 1. */ + ci->start = (0x5f * 75 * 60); + /* Optimum recording power. */ + ct->extra[0] = 0x00; + } else + ct->extra[3] = 0x01; + + for (int i = 0; i < 3; i++) { + lead[i] = img->tracks_num; + (void) image_insert_track(img, session, 0xa0 + i); + } + } + + image_log(img->log, " [SESSION ] Initialization successful\n"); + } + } + } + } else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || + !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || + !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || + !strcmp(command, "")) { + /* Ignored commands. */ + image_log(img->log, " [CUE ] Ignored command \"%s\" in Cue sheet\n", + command); + success = 1; + } else { + image_log(img->log, " [CUE ] Unsupported command \"%s\" in Cue sheet\n", + command); + success = 0; + } + + if (!success) + break; + } + + if (success && (ct != NULL)) for (int i = 2; i >= 0; i--) { + if (ct->idx[i].file == NULL) + ct->idx[i].file = tf; + else + break; + } + + tf = NULL; + + fclose(fp); + + if (success) + image_process(img); + else { + image_log(img->log, " [CUE ] Unable to open Cue sheet \"%s\"\n", cuefile); + return 0; + } + + return success; +} + +/* Root functions. */ +static void +image_clear_tracks(cd_image_t *img) +{ + const track_file_t *last = NULL; + track_t *cur = NULL; + track_index_t *idx = NULL; + + if ((img->tracks != NULL) && (img->tracks_num > 0)) { + for (int i = 0; i < img->tracks_num; i++) { + cur = &img->tracks[i]; + + if (((cur->point >= 1) && (cur->point <= 99)) || + (cur->point == 0xa2)) for (int j = 0; j < 3; j++) { + idx = &(cur->idx[j]); + /* Make sure we do not attempt to close a NULL file. */ + if ((idx->file != NULL) && (idx->type == INDEX_NORMAL)) { + if (idx->file != last) { + last = idx->file; + index_file_close(idx); + } else + idx->file = NULL; + } + } + } + + /* Now free the array. */ + free(img->tracks); + img->tracks = NULL; + + /* Mark that there's no tracks. */ + img->tracks_num = 0; + } +} + +/* Shared functions. */ +static int +image_get_track_info(const void *local, const uint32_t track, + const int end, track_info_t *ti) +{ + const cd_image_t *img = (const cd_image_t *) local; + const track_t *ct = NULL; + int ret = 0; for (int i = 0; i < img->tracks_num; i++) { ct = &(img->tracks[i]); @@ -70,238 +1712,328 @@ image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) break; } - ti->number = ct->point; + if (ct != NULL) { + const uint32_t pos = end ? ct->idx[1].start : + (ct->idx[1].start + ct->idx[1].length); - if (ct == NULL) { - ti->attr = 0x14; - ti->m = 0; - ti->s = 2; - ti->f = 0; - } else { - uint32_t pos = end ? ct->idx[1].start : (ct->idx[1].start + ct->idx[1].length); - ti->attr = ct->attr; - ti->m = (pos / 75) / 60; - ti->s = (pos / 75) % 60; - ti->f = pos % 75; + ti->number = ct->point; + ti->attr = ct->attr; + ti->m = (pos / 75) / 60; + ti->s = (pos / 75) % 60; + ti->f = pos % 75; + + ret = 1; } + + return ret; } static void -image_get_raw_track_info(cdrom_t *dev, int *num, raw_track_info_t *rti) +image_get_raw_track_info(const void *local, int *num, uint8_t *buffer) { - cdi_get_raw_track_info((cd_img_t *) dev->local, num, (uint8_t *) rti); -} + const cd_image_t *img = (const cd_image_t *) local; + int len = 0; -static void -image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) -{ - cd_img_t *img = (cd_img_t *) dev->local; - TMSF rel_pos; - TMSF abs_pos; + image_log(img->log, "img->tracks_num = %i\n", img->tracks_num); - cdi_get_audio_sub(img, lba, &subc->attr, &subc->track, &subc->index, - &rel_pos, &abs_pos); + for (int i = 0; i < img->tracks_num; i++) { + const track_t *ct = &(img->tracks[i]); +#ifdef ENABLE_IMAGE_LOG + int old_len = len; +#endif + buffer[len++] = ct->session; /* Session number. */ + buffer[len++] = ct->attr; /* Track ADR and Control. */ + buffer[len++] = ct->tno; /* TNO (always 0). */ + buffer[len++] = ct->point; /* Point (track number). */ + for (int j = 0; j < 4; j++) + buffer[len++] = ct->extra[j]; + buffer[len++] = (ct->idx[1].start / 75) / 60; + buffer[len++] = (ct->idx[1].start / 75) % 60; + buffer[len++] = ct->idx[1].start % 75; + image_log(img->log, "%i: %02X %02X %02X %02X %02X %02X %02X\n", i, + buffer[old_len], buffer[old_len + 1], + buffer[old_len + 2], buffer[old_len + 3], + buffer[old_len + 8], buffer[old_len + 9], + buffer[old_len + 10]); + } - subc->abs_m = abs_pos.min; - subc->abs_s = abs_pos.sec; - subc->abs_f = abs_pos.fr; - - subc->rel_m = rel_pos.min; - subc->rel_s = rel_pos.sec; - subc->rel_f = rel_pos.fr; - - cdrom_image_log("image_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", - subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f, - subc->rel_m, subc->rel_s, subc->rel_f); + *num = img->tracks_num; } static int -image_get_capacity(cdrom_t *dev) +image_is_track_pre(const void *local, const uint32_t sector) { - cd_img_t *img = (cd_img_t *) dev->local; - uint32_t lb = 0; - track_t *lo = NULL; + const cd_image_t *img = (const cd_image_t *) local; + int ret = 0; - if (!img) - return 0; + if (img->has_audio) { + const int track = image_get_track(img, sector); - for (int i = (img->tracks_num - 1); i >= 0; i--) { - if (img->tracks[i].point == 0xa2) { - lo = &(img->tracks[i]); - break; + if (track >= 0) { + const track_t *trk = &(img->tracks[track]); + + ret = !!(trk->attr & 0x01); } } - if (lo != NULL) - lb = lo->idx[1].start - 1; + return ret; +} + +static int +image_read_sector(const void *local, uint8_t *buffer, + const uint32_t sector) +{ + const cd_image_t *img = (const cd_image_t *) local; + int m = 0; + int s = 0; + int f = 0; + int ret = 0; + uint32_t lba = sector; + int track; + int index; + uint8_t q[16] = { 0x00 }; + + if (sector == 0xffffffff) + lba = img->dev->seek_pos; + + const uint64_t sect = (uint64_t) lba; + + image_get_track_and_index(img, lba, &track, &index); + + const track_t *trk = &(img->tracks[track]); + const track_index_t *idx = &(trk->idx[index]); + const int track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || + (trk->sector_size == 2448)); + const uint64_t seek = ((sect + 150 - idx->start + idx->file_start) * + trk->sector_size) + trk->skip; + + if (track >= 0) { + /* Signal CIRC error to the guest if sector is bad. */ + ret = image_is_sector_bad(img, lba) ? -1 : 1; + + if (ret > 0) { + uint64_t offset = 0ULL; + + image_log(img->log, "cdrom_read_sector(%08X): track %02X, index %02X, %016" + PRIX64 ", %i, %i, %i, %i\n", + lba, track, index, idx->start, trk->sector_size, track_is_raw, + trk->mode, trk->form); + + memset(buffer, 0x00, 2448); + + if ((trk->attr & 0x04) && ((idx->type < INDEX_NORMAL) || !track_is_raw)) { + offset += 16ULL; + + /* Construct the header. */ + memset(buffer + 1, 0xff, 10); + buffer += 12; + FRAMES_TO_MSF(sector + 150, &m, &s, &f); + /* These have to be BCD. */ + buffer[0] = bin2bcd(m & 0xff); + buffer[1] = bin2bcd(s & 0xff); + buffer[2] = bin2bcd(f & 0xff); + /* Data, should reflect the actual sector type. */ + buffer[3] = trk->mode; + buffer += 4; + if (trk->form >= 1) { + offset += 8ULL; + + /* Construct the CD-I/XA sub-header. */ + buffer[2] = buffer[6] = (trk->form - 1) << 5; + buffer += 8; + } + } + + if (idx->type >= INDEX_NORMAL) { + /* Read the data from the file. */ + ret = idx->file->read(idx->file, buffer, seek, trk->sector_size); + } else + /* Index is not in the file, no read to fail here. */ + ret = 1; + + if ((ret > 0) && ((idx->type < INDEX_NORMAL) || (trk->subch_type != 0x08))) { + buffer -= offset; + + if (trk->subch_type == 0x10) + memcpy(q, &(buffer[2352]), 12); + else { + /* Construct Q. */ + q[0] = (trk->attr >> 4) | ((trk->attr & 0xf) << 4); + q[1] = bin2bcd(trk->point); + q[2] = index; + if (index == 0) { + /* + Pre-gap sector relative frame addresses count from + 00:01:74 downwards. + */ + FRAMES_TO_MSF((int32_t) (149 - (lba + 150 - idx->start)), &m, &s, &f); + } else { + FRAMES_TO_MSF((int32_t) (lba + 150 - idx->start), &m, &s, &f); + } + q[3] = bin2bcd(m & 0xff); + q[4] = bin2bcd(s & 0xff); + q[5] = bin2bcd(f & 0xff); + FRAMES_TO_MSF(lba + 150, &m, &s, &f); + q[7] = bin2bcd(m & 0xff); + q[8] = bin2bcd(s & 0xff); + q[9] = bin2bcd(f & 0xff); + } + + /* Construct raw subchannel data from Q only. */ + for (int i = 0; i < 12; i++) + for (int j = 0; j < 8; j++) + buffer[2352 + (i << 3) + j] = ((q[i] >> (7 - j)) & 0x01) << 6; + } + } + } + + return ret; +} + +static uint8_t +image_get_track_type(const void *local, const uint32_t sector) +{ + const cd_image_t *img = (cd_image_t *) local; + const int track = image_get_track(img, sector); + const track_t * trk = &(img->tracks[track]); + int ret = 0x00; + + if (image_is_track_audio(img, sector)) + ret = CD_TRACK_AUDIO; + else if (track >= 0) for (int i = 0; i < img->tracks_num; i++) { + const track_t *ct = &(img->tracks[i]); + const track_t *nt = &(img->tracks[i + 1]); + + if (ct->point == 0xa0) { + uint8_t first = (ct->idx[1].start / 75 / 60); + uint8_t last = (nt->idx[1].start / 75 / 60); + + if ((trk->point >= first) && (trk->point <= last)) { + ret = (ct->idx[1].start / 75) % 60; + break; + } + } + } + + return ret; +} + +static uint32_t +image_get_last_block(const void *local) +{ + const cd_image_t *img = (const cd_image_t *) local; + uint32_t lb = 0x00000000; + + if (img != NULL) { + const track_t *lo = NULL; + + for (int i = (img->tracks_num - 1); i >= 0; i--) { + if (img->tracks[i].point == 0xa2) { + lo = &(img->tracks[i]); + break; + } + } + + if (lo != NULL) + lb = lo->idx[1].start - 1; + } return lb; } static int -image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) -{ - cd_img_t *img = (cd_img_t *) dev->local; - int m; - int s; - int f; - - if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY)) - return 0; - - if (ismsf) { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - pos = MSFtoLBA(m, s, f) - 150; - } - - return cdi_is_audio(img, pos); -} - -static int -image_is_track_pre(cdrom_t *dev, uint32_t lba) -{ - cd_img_t *img = (cd_img_t *) dev->local; - - if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY)) - return 0; - - return cdi_is_pre(img, lba); -} - -static int -image_sector_size(struct cdrom *dev, uint32_t lba) -{ - cd_img_t *img = (cd_img_t *) dev->local; - - return cdi_get_sector_size(img, lba); -} - -static int -image_read_sector(struct cdrom *dev, uint8_t *b, uint32_t lba) -{ - cd_img_t *img = (cd_img_t *) dev->local; - - if (cdi_get_sector_size(img, lba) <= 2352) - return cdi_read_sector(img, b, 1, lba); - else - return cdi_read_sector_sub(img, b, lba); -} - -static int -image_track_type(cdrom_t *dev, uint32_t lba) -{ - cd_img_t *img = (cd_img_t *) dev->local; - - if (img) { - if (image_is_track_audio(dev, lba, 0)) - return CD_TRACK_AUDIO; - else if (cdi_is_mode2(img, lba)) - return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba); - } - - return 0; -} - -static int -image_ext_medium_changed(cdrom_t *dev) +image_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t format, + uint8_t *buffer, uint32_t *info) { return 0; } +static int +image_is_dvd(const void *local) +{ + const cd_image_t *img = (const cd_image_t *) local; + + return img->is_dvd; +} + +static int +image_has_audio(const void *local) +{ + const cd_image_t *img = (const cd_image_t *) local; + + return img->has_audio; +} + static void -image_exit(cdrom_t *dev) +image_close(void *local) { - cd_img_t *img = (cd_img_t *) dev->local; + cd_image_t *img = (cd_image_t *) local; - cdrom_image_log("CDROM: image_exit(%s)\n", dev->image_path); - dev->cd_status = CD_STATUS_EMPTY; + if (img != NULL) { + image_clear_tracks(img); - if (img) { - cdi_close(img); - dev->local = NULL; + image_log(img->log, "Log closed\n"); + + log_close(img->log); + img->log = NULL; + + free(img); } - - dev->ops = NULL; } -static const cdrom_ops_t cdrom_image_ops = { +static const cdrom_ops_t image_ops = { image_get_track_info, image_get_raw_track_info, - image_get_subchannel, image_is_track_pre, - image_sector_size, image_read_sector, - image_track_type, - image_ext_medium_changed, - image_exit + image_get_track_type, + image_get_last_block, + image_read_dvd_structure, + image_is_dvd, + image_has_audio, + NULL, + image_close }; -static int -image_open_abort(cdrom_t *dev) +/* Public functions. */ +void * +image_open(cdrom_t *dev, const char *path) { - cdrom_image_close(dev); - dev->ops = NULL; - dev->image_path[0] = 0; - return 1; -} - -int -cdrom_image_open(cdrom_t *dev, const char *fn) -{ - cd_img_t *img; - - /* Make sure to not STRCPY if the two are pointing - at the same place. */ - if (fn != dev->image_path) - strcpy(dev->image_path, fn); - - /* Create new instance of the CDROM_Image class. */ - img = (cd_img_t *) calloc(1, sizeof(cd_img_t)); - - /* This guarantees that if ops is not NULL, then - neither is the image pointer. */ - if (img == NULL) - return image_open_abort(dev); - - dev->local = img; - - /* Open the image. */ - int i = cdi_set_device(img, fn); - if (!i) - return image_open_abort(dev); - - /* All good, reset state. */ - if (i >= 2) - dev->cd_status = CD_STATUS_DATA_ONLY; - else - dev->cd_status = CD_STATUS_STOPPED; - dev->seek_pos = 0; - dev->cd_buflen = 0; - dev->cdrom_capacity = image_get_capacity(dev); - cdrom_image_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", dev->cdrom_capacity, - ((uint64_t) dev->cdrom_capacity) << 11ULL); -#ifdef ENABLE_CDROM_IMAGE_LOG - int cm, cs, cf; - cf = dev->cdrom_capacity % 75; - cs = (dev->cdrom_capacity / 75) % 60; - cm = (dev->cdrom_capacity / 75) / 60; - cdrom_image_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes) (time: %02i:%02i:%02i)\n", - dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity - 150ULL) * 2352ULL, cm, cs, cf); -#endif - - /* Attach this handler to the drive. */ - dev->ops = &cdrom_image_ops; - - return 0; -} - -void -cdrom_image_close(cdrom_t *dev) -{ - cdrom_image_log("CDROM: image_close(%s)\n", dev->image_path); - - if (dev && dev->ops && dev->ops->exit) - dev->ops->exit(dev); + const uintptr_t ext = path + strlen(path) - strrchr(path, '.'); + cd_image_t *img = (cd_image_t *) calloc(1, sizeof(cd_image_t)); + + if (img != NULL) { + int ret; + const int is_cue = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE")); + + if (is_cue) { + ret = image_load_cue(img, path); + + if (ret >= 2) + img->has_audio = 0; + else if (ret) + img->has_audio = 1; + } else { + ret = image_load_iso(img, path); + + if (!ret) { + image_close(img); + img = NULL; + } else + img->has_audio = 0; + } + + if (ret) { + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i Image", dev->id + 1); + img->log = log_open(n); + + img->dev = dev; + + dev->ops = &image_ops; + } + } + + return img; } diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c deleted file mode 100644 index 9d065a0cb..000000000 --- a/src/cdrom/cdrom_image_backend.c +++ /dev/null @@ -1,1499 +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. - * - * CD-ROM image file handling module. - * - * Authors: Miran Grca, - * RichardG, - * Cacodemon345 - * - * Copyright 2016-2025 Miran Grca. - * Copyright 2016-2025 Miran Grca. - * Copyright 2024-2025 Cacodemon345. - */ -#define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -# include -# include -#else -# include -#endif -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/path.h> -#include <86box/plat.h> -#include <86box/cdrom_image_backend.h> - -#include - -#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) - -#define MAX_LINE_LENGTH 512 -#define MAX_FILENAME_LENGTH 256 -#define CROSS_LEN 512 - -static char temp_keyword[1024]; - -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG -int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; - -void -cdrom_image_backend_log(const char *fmt, ...) -{ - va_list ap; - - if (cdrom_image_backend_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define cdrom_image_backend_log(fmt, ...) -#endif - -typedef struct audio_file_t { - SNDFILE *file; - SF_INFO info; -} audio_file_t; - -/* Audio file functions */ -static int -audio_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) -{ - track_file_t *tf = (track_file_t *) priv; - audio_file_t *audio = (audio_file_t *) tf->priv; - uint64_t samples_seek = seek / 4; - uint64_t samples_count = count / 4; - - if ((seek & 3) || (count & 3)) { - cdrom_image_backend_log("CD Audio file: Reading on non-4-aligned boundaries.\n"); - } - - sf_count_t res = sf_seek(audio->file, samples_seek, SEEK_SET); - - if (res == -1) - return 0; - - return !!sf_readf_short(audio->file, (short *) buffer, samples_count); -} - -static uint64_t -audio_get_length(void *priv) -{ - track_file_t *tf = (track_file_t *) priv; - audio_file_t *audio = (audio_file_t *) tf->priv; - - /* Assume 16-bit audio, 2 channel. */ - return audio->info.frames * 4ull; -} - -static void -audio_close(void *priv) -{ - track_file_t *tf = (track_file_t *) priv; - audio_file_t *audio = (audio_file_t *) tf->priv; - - memset(tf->fn, 0x00, sizeof(tf->fn)); - if (audio && audio->file) - sf_close(audio->file); - free(audio); - free(tf); -} - -static track_file_t * -audio_init(const char *filename, int *error) -{ - track_file_t *tf = (track_file_t *) calloc(sizeof(track_file_t), 1); - audio_file_t *audio = (audio_file_t *) calloc(sizeof(audio_file_t), 1); -#ifdef _WIN32 - wchar_t filename_w[4096]; -#endif - - if (tf == NULL || audio == NULL) { - goto cleanup_error; - } - - memset(tf->fn, 0x00, sizeof(tf->fn)); - strncpy(tf->fn, filename, sizeof(tf->fn) - 1); -#ifdef _WIN32 - mbstowcs(filename_w, filename, 4096); - audio->file = sf_wchar_open(filename_w, SFM_READ, &audio->info); -#else - audio->file = sf_open(filename, SFM_READ, &audio->info); -#endif - - if (!audio->file) { - cdrom_image_backend_log("Audio file open error!"); - goto cleanup_error; - } - - if (audio->info.channels != 2 || audio->info.samplerate != 44100 || !audio->info.seekable) { - cdrom_image_backend_log("Audio file not seekable or in non-CD format!"); - sf_close(audio->file); - goto cleanup_error; - } - - *error = 0; - tf->priv = audio; - tf->fp = NULL; - tf->close = audio_close; - tf->get_length = audio_get_length; - tf->read = audio_read; - return tf; -cleanup_error: - free(tf); - free(audio); - *error = 1; - return NULL; -} - -/* Binary file functions. */ -static int -bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) -{ - track_file_t *tf = NULL; - - if ((tf = (track_file_t *) priv)->fp == NULL) - return 0; - - cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu)\n", - tf->fp, seek, count); - - if (fseeko64(tf->fp, seek, SEEK_SET) == -1) { - cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); - - return -1; - } - - if (fread(buffer, count, 1, tf->fp) != 1) { - cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); - - return -1; - } - - if (UNLIKELY(tf->motorola)) { - for (uint64_t i = 0; i < count; i += 2) { - uint8_t buffer0 = buffer[i]; - uint8_t buffer1 = buffer[i + 1]; - buffer[i] = buffer1; - buffer[i + 1] = buffer0; - } - } - - return 1; -} - -static uint64_t -bin_get_length(void *priv) -{ - track_file_t *tf = NULL; - - if ((tf = (track_file_t *) priv)->fp == NULL) - return 0; - - fseeko64(tf->fp, 0, SEEK_END); - const off64_t len = ftello64(tf->fp); - cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->fp, len); - - return len; -} - -static void -bin_close(void *priv) -{ - track_file_t *tf = (track_file_t *) priv; - - if (tf == NULL) - return; - - if (tf->fp != NULL) { - fclose(tf->fp); - tf->fp = NULL; - } - - memset(tf->fn, 0x00, sizeof(tf->fn)); - - free(priv); -} - -static track_file_t * -bin_init(const char *filename, int *error) -{ - track_file_t *tf = (track_file_t *) calloc(1, sizeof(track_file_t)); - struct stat stats; - - if (tf == NULL) { - *error = 1; - return NULL; - } - - memset(tf->fn, 0x00, sizeof(tf->fn)); - strncpy(tf->fn, filename, sizeof(tf->fn) - 1); - tf->fp = plat_fopen64(tf->fn, "rb"); - cdrom_image_backend_log("CDROM: binary_open(%s) = %08lx\n", tf->fn, tf->fp); - - if (stat(tf->fn, &stats) != 0) { - /* Use a blank structure if stat failed. */ - memset(&stats, 0, sizeof(struct stat)); - } - *error = ((tf->fp == NULL) || ((stats.st_mode & S_IFMT) == S_IFDIR)); - - /* Set the function pointers. */ - if (!*error) { - tf->read = bin_read; - tf->get_length = bin_get_length; - tf->close = bin_close; - } else { - /* From the check above, error may still be non-zero if opening a directory. - * The error is set for viso to try and open the directory following this function. - * However, we need to make sure the descriptor is closed. */ - if ((tf->fp != NULL) && ((stats.st_mode & S_IFMT) == S_IFDIR)) { - /* tf is freed by bin_close */ - bin_close(tf); - } else - free(tf); - tf = NULL; - } - - return tf; -} - -static track_file_t * -track_file_init(const char *filename, int *error, int *is_viso) -{ - track_file_t *tf; - - *is_viso = 0; - - /* Current we only support .BIN files, either combined or one per - track. In the future, more is planned. */ - tf = bin_init(filename, error); - - if (*error) { - if ((tf != NULL) && (tf->close != NULL)) { - tf->close(tf); - tf = NULL; - } - - tf = viso_init(filename, error); - - if (!*error) - *is_viso = 1; - } - - return tf; -} - -static void -index_file_close(track_index_t *idx) -{ - if (idx == NULL) - return; - - if (idx->file == NULL) - return; - - if (idx->file->close == NULL) - return; - - idx->file->close(idx->file); - idx->file = NULL; -} - -void -cdi_get_raw_track_info(cd_img_t *cdi, int *num, uint8_t *buffer) -{ - int len = 0; - - cdrom_image_backend_log("cdi->tracks_num = %i\n", cdi->tracks_num); - - for (int i = 0; i < cdi->tracks_num; i++) { - track_t *ct = &(cdi->tracks[i]); -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - int old_len = len; -#endif - buffer[len++] = ct->session; /* Session number */ - buffer[len++] = ct->attr; /* Track ADR and Control */ - buffer[len++] = ct->tno; /* TNO (always 0) */ - buffer[len++] = ct->point; /* Point (for track points - track number) */ - for (int j = 0; j < 4; j++) - buffer[len++] = ct->extra[j]; - buffer[len++] = (ct->idx[1].start / 75) / 60; - buffer[len++] = (ct->idx[1].start / 75) % 60; - buffer[len++] = ct->idx[1].start % 75; - cdrom_image_backend_log("%i: %02X %02X %02X %02X %02X %02X %02X\n", i, - buffer[old_len], buffer[old_len + 1], buffer[old_len + 2], buffer[old_len + 3], - buffer[old_len + 8], buffer[old_len + 9], buffer[old_len + 10]); - } - - *num = cdi->tracks_num; -} - -static int -cdi_get_track(cd_img_t *cdi, uint32_t sector) -{ - int ret = -1; - - for (int i = 0; i < cdi->tracks_num; i++) { - track_t *ct = &(cdi->tracks[i]); - for (int j = 0; j < 3; j++) { - track_index_t *ci = &(ct->idx[j]); - if (((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) { - ret = i; - break; - } - } - } - - return ret; -} - -static void -cdi_get_track_and_index(cd_img_t *cdi, uint32_t sector, int *track, int *index) -{ - *track = -1; - *index = -1; - - for (int i = 0; i < cdi->tracks_num; i++) { - track_t *ct = &(cdi->tracks[i]); - for (int j = 0; j < 3; j++) { - track_index_t *ci = &(ct->idx[j]); - if (((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) { - *track = i; - *index = j; - break; - } - } - } -} - -/* TODO: See if track start is adjusted by 150 or not. */ -int -cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) -{ - int cur_track = cdi_get_track(cdi, sector); - - if (cur_track < 1) - return 0; - - *track = (uint8_t) cur_track; - const track_t *trk = &cdi->tracks[*track]; - *attr = trk->attr; - *index = 1; - - /* Absolute position should be adjusted by 150, not the relative ones. */ - FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); - - /* Relative position is relative Index 1 start - pre-gap values will be negative. */ - FRAMES_TO_MSF((int32_t) (sector + 150 - trk->idx[1].start), &rel_pos->min, &rel_pos->sec, &rel_pos->fr); - - return 1; -} - -static __inline int -bin2bcd(int x) -{ - return (x % 10) | ((x / 10) << 4); -} - -int -cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) -{ - const uint64_t sect = (uint64_t) sector; - int m = 0; - int s = 0; - int f = 0; - int ret = 0; - uint64_t offset = 0ULL; - int track; - int index; - int raw_size; - int cooked_size; - uint8_t q[16] = { 0x00 }; - - cdi_get_track_and_index(cdi, sector, &track, &index); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - const track_index_t *idx = &(trk->idx[index]); - const int track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); - const uint64_t seek = (sect + 150 - idx->start + idx->file_start) * trk->sector_size; - - cdrom_image_backend_log("cdrom_read_sector(%08X): track %02X, index %02X, %016" PRIX64 ", %016" PRIX64 ", %i\n", - sector, track, index, idx->start, trk->sector_size); - - if (track_is_raw) - raw_size = trk->sector_size; - else - raw_size = 2448; - - if ((trk->mode == 2) && (trk->form != 1)) { - if (trk->form == 2) - cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ - else - cooked_size = 2336; - } else - cooked_size = COOKED_SECTOR_SIZE; - - if ((trk->mode == 2) && (trk->form >= 1)) - offset = 24ULL; - else - offset = 16ULL; - - if (idx->type < INDEX_NORMAL) { - memset(buffer, 0x00, 2448); - if (trk->attr & 0x04) { - /* Construct the rest of the raw sector. */ - memset(buffer + 1, 0xff, 10); - buffer += 12; - FRAMES_TO_MSF(sector + 150, &m, &s, &f); - /* These have to be BCD. */ - buffer[0] = CDROM_BCD(m & 0xff); - buffer[1] = CDROM_BCD(s & 0xff); - buffer[2] = CDROM_BCD(f & 0xff); - /* Data, should reflect the actual sector type. */ - buffer[3] = trk->mode; - ret = 1; - } - } else if (raw && !track_is_raw) { - memset(buffer, 0x00, 2448); - /* We are doing a raw read but the track is cooked, length should be cooked size. */ - const int temp = idx->file->read(idx->file, buffer + offset, seek, cooked_size); - if (temp <= 0) - return temp; - if (trk->attr & 0x04) { - /* Construct the rest of the raw sector. */ - memset(buffer + 1, 0xff, 10); - buffer += 12; - FRAMES_TO_MSF(sector + 150, &m, &s, &f); - /* These have to be BCD. */ - buffer[0] = CDROM_BCD(m & 0xff); - buffer[1] = CDROM_BCD(s & 0xff); - buffer[2] = CDROM_BCD(f & 0xff); - /* Data, should reflect the actual sector type. */ - buffer[3] = trk->mode; - ret = 1; - } - } else if (!raw && track_is_raw) - /* The track is raw but we are doing a cooked read, length should be cooked size. */ - return idx->file->read(idx->file, buffer, seek + offset, cooked_size); - else { - /* The track is raw and we are doing a raw read, length should be raw size. */ - ret = idx->file->read(idx->file, buffer, seek, raw_size); - if (raw && (raw_size == 2448)) - return ret; - } - - /* Construct Q. */ - q[0] = (trk->attr >> 4) | ((trk->attr & 0xf) << 4); - q[1] = bin2bcd(trk->point); - q[2] = index; - if (index == 0) { - /* Pre-gap sector relative frame addresses count from 00:01:74 downwards. */ - FRAMES_TO_MSF((int32_t) (149 - (sector + 150 - idx->start)), &m, &s, &f); - } else { - FRAMES_TO_MSF((int32_t) (sector + 150 - idx->start), &m, &s, &f); - } - q[3] = bin2bcd(m); - q[4] = bin2bcd(s); - q[5] = bin2bcd(f); - FRAMES_TO_MSF(sector + 150, &m, &s, &f); - q[7] = bin2bcd(m); - q[8] = bin2bcd(s); - q[9] = bin2bcd(f); - - /* Construct raw subchannel data from Q only. */ - for (int i = 0; i < 12; i++) - for (int j = 0; j < 8; j++) - buffer[2352 + (i << 3) + j] = ((q[i] >> (7 - j)) & 0x01) << 6; - - return ret; -} - -/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ -int -cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) -{ - int track; - int index; - - cdi_get_track_and_index(cdi, sector, &track, &index); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - const track_index_t *idx = &(trk->idx[index]); - - const uint64_t seek = (((uint64_t) sector + 150 - idx->start + idx->file_start) * trk->sector_size); - - if ((idx->type < INDEX_NORMAL) && (trk->sector_size != 2448)) - return 0; - - return idx->file->read(idx->file, buffer, seek, 2448); -} - -int -cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - - return trk->sector_size; -} - -int -cdi_is_audio(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - - return !!(trk->mode == 0); -} - -int -cdi_is_pre(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - - return !!(trk->attr & 0x01); -} - -int -cdi_is_mode2(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - - return !!(trk->mode == 2); -} - -int -cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector); - - if (track < 0) - return 0; - - const track_t *trk = &(cdi->tracks[track]); - - return trk->form; -} - -static int -cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) -{ - uint8_t pvd[COOKED_SECTOR_SIZE]; - uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ - - if (sector_size == RAW_SECTOR_SIZE) { - if (mode2 && (form > 0)) - seek += 24; - else - seek += 16; - } else if (form > 0) - seek += 8; - - file->read(file, pvd, seek, COOKED_SECTOR_SIZE); - - return ((pvd[0] == 1 && !strncmp((char *) (&pvd[1]), "CD001", 5) && pvd[6] == 1) || (pvd[8] == 1 && !strncmp((char *) (&pvd[9]), "CDROM", 5) && pvd[14] == 1)); -} - -static int -cdi_cue_get_buffer(char *str, char **line, int up) -{ - char *s = *line; - char *p = str; - int quote = 0; - int done = 0; - int space = 1; - - /* Copy to local buffer until we have end of string or whitespace. */ - while (!done) { - switch (*s) { - case '\0': - if (quote) { - /* Ouch, unterminated string.. */ - return 0; - } - done = 1; - break; - - case '\"': - quote ^= 1; - break; - - case ' ': - case '\t': - if (space) - break; - - if (!quote) { - done = 1; - break; - } - fallthrough; - - default: - if (up && islower((int) *s)) - *p++ = toupper((int) *s); - else - *p++ = *s; - space = 0; - break; - } - - if (!done) - s++; - } - *p = '\0'; - - *line = s; - - return 1; -} - -static int -cdi_cue_get_keyword(char **dest, char **line) -{ - int success; - - success = cdi_cue_get_buffer(temp_keyword, line, 1); - if (success) - *dest = temp_keyword; - - return success; -} - -/* Get a string from the input line, handling quotes properly. */ -static uint64_t -cdi_cue_get_number(char **line) -{ - char temp[128]; - uint64_t num; - - if (!cdi_cue_get_buffer(temp, line, 0)) - return 0; - - if (sscanf(temp, "%" PRIu64, &num) != 1) - return 0; - - return num; -} - -static int -cdi_cue_get_frame(uint64_t *frames, char **line) -{ - char temp[128]; - int min = 0; - int sec = 0; - int fr = 0; - int success; - - success = cdi_cue_get_buffer(temp, line, 0); - if (!success) - return 0; - - success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; - if (!success) - return 0; - - *frames = MSF_TO_FRAMES(min, sec, fr); - - return 1; -} - -static int -cdi_cue_get_flags(track_t *cur, char **line) -{ - char temp[128]; - char temp2[128]; - int success; - - success = cdi_cue_get_buffer(temp, line, 0); - if (!success) - return 0; - - memset(temp2, 0x00, sizeof(temp2)); - success = sscanf(temp, "%s", temp2) == 1; - if (!success) - return 0; - - if (strstr(temp2, "PRE") != NULL) - cur->attr |= 0x01; - if (strstr(temp2, "DCP") != NULL) - cur->attr |= 0x02; - if (strstr(temp2, "4CH") != NULL) - cur->attr |= 0x08; - - return 1; -} - -static track_t * -cdi_insert_track(cd_img_t *cdi, uint8_t session, uint8_t point) -{ - track_t *ct = NULL; - - cdi->tracks_num++; - if (cdi->tracks == NULL) { - cdi->tracks = calloc(1, sizeof(track_t)); - ct = &(cdi->tracks[0]); - } else { - cdi->tracks = realloc(cdi->tracks, cdi->tracks_num * sizeof(track_t)); - ct = &(cdi->tracks[cdi->tracks_num - 1]); - } - cdrom_image_backend_log("%02X: cdi->tracks[%2i] = %016" PRIX64 "\n", point, cdi->tracks_num - 1, (uint64_t) ct); - - memset(ct, 0x00, sizeof(track_t)); - - ct->session = session; - ct->point = point; - - for (int i = 0; i < 3; i++) - ct->idx[i].type = (point > 99) ? INDEX_SPECIAL : INDEX_NONE; - - return ct; -} - -static void -cdi_last_3_passes(cd_img_t *cdi) -{ - track_t *ct = NULL; - track_t *lt = NULL; - track_index_t *ci = NULL; - track_file_t *tf = NULL; - uint64_t tf_len = 0ULL; - uint64_t cur_pos = 0ULL; - int map[256] = { 0 }; - int lead[3] = { 0 }; - int pos = 0; - int ls = 0; - uint64_t spg[256] = { 0ULL }; - track_t *lo[256] = { 0 }; - - cdrom_image_backend_log("A2 = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[2])); - - for (int i = 0; i < cdi->tracks_num; i++) { - ct = &(cdi->tracks[i]); - if (((ct->point >= 1) && (ct->point <= 99)) || (ct->point >= 0xb0)) { - if (ct->point == 0xb0) { - /* Point B0h found, add the previous three lead tracks. */ - for (int j = 0; j < 3; j++) { - map[pos] = lead[j]; - pos++; - } - } - - map[pos] = i; - pos++; - } else if ((ct->point >= 0xa0) && (ct->point <= 0xa2)) - lead[ct->point & 0x03] = i; - } - - /* The last lead tracks. */ - for (int i = 0; i < 3; i++) { - map[pos] = lead[i]; - pos++; - } -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - cdrom_image_backend_log("pos = %i, cdi->tracks_num = %i\n", pos, cdi->tracks_num); - for (int i = 0; i < pos; i++) - cdrom_image_backend_log("map[%02i] = %02X\n", i, map[i]); -#endif - - cdrom_image_backend_log("Second pass:\n"); - for (int i = (cdi->tracks_num - 1); i >= 0; i--) { - ct = &(cdi->tracks[map[i]]); - if (ct->idx[1].type != INDEX_SPECIAL) { - for (int j = 2; j >= 0; j--) { - ci = &(ct->idx[j]); - - if ((ci->type >= INDEX_ZERO) && (ci->file != tf)) { - tf = ci->file; - if (tf != NULL) { - tf_len = tf->get_length(tf) / ct->sector_size; - cdrom_image_backend_log(" File length: %016" PRIX64 " sectors\n", tf_len); - } - } - - if (ci->type == INDEX_NONE) { - /* Index was not in the cue sheet, keep its length at zero. */ - ci->file_start = tf_len; - } else if (ci->type == INDEX_NORMAL) { - /* Index was in the cue sheet and is present in the file. */ - ci->file_length = tf_len - ci->file_start; - tf_len -= ci->file_length; - } - - cdrom_image_backend_log(" TRACK %2i (%2i), ATTR %02X, INDEX %i: %2i, file_start = %016" - PRIX64 " (%2i:%02i:%02i), file_length = %016" PRIX64 " (%2i:%02i:%02i)\n", - i, map[i], - ct->attr, - j, ci->type, - ci->file_start, - (int) ((ci->file_start / 75) / 60), - (int) ((ci->file_start / 75) % 60), - (int) (ci->file_start % 75), - ci->file_length, - (int) ((ci->file_length / 75) / 60), - (int) ((ci->file_length / 75) % 60), - (int) (ci->file_length % 75)); - } - } - } - - cdrom_image_backend_log("Third pass:\n"); - for (int i = 0; i < cdi->tracks_num; i++) { - int session_changed = 0; - - ct = &(cdi->tracks[map[i]]); - if (ct->idx[1].type != INDEX_SPECIAL) { - if (ct->session != ls) { - /* The first track of a session always has a pre-gap of at least 0:02:00. */ - ci = &(ct->idx[0]); - if (ci->type == INDEX_NONE) { - ci->type = INDEX_ZERO; - ci->start = 0ULL; - ci->length = 150ULL; - } - - session_changed = 1; - ls = ct->session; - } - - for (int j = 0; j < 3; j++) { - ci = &(ct->idx[j]); - - if (ci->type == INDEX_NONE) - /* Index was not in the cue sheet, keep its length at zero. */ - ci->start = cur_pos; - else if (ci->type == INDEX_ZERO) { - /* Index was in the cue sheet and is not present in the file. */ - ci->start = cur_pos; - cur_pos += ci->length; - } else if (ci->type == INDEX_NORMAL) { - /* Index was in the cue sheet and is present in the file. */ - ci->start = cur_pos; - ci->length = ci->file_length; - cur_pos += ci->file_length; - } - - cdrom_image_backend_log(" TRACK %2i (%2i) (%2i), ATTR %02X, MODE %i, INDEX %i: %2i, " - "start = %016" PRIX64 " (%2i:%02i:%02i), length = %016" PRIX64 - " (%2i:%02i:%02i)\n", - i, map[i], - ct->point, ct->attr, - ct->mode, - j, ci->type, - ci->start, - (int) ((ci->start / 75) / 60), - (int) ((ci->start / 75) % 60), - (int) (ci->start % 75), - ci->length, - (int) ((ci->length / 75) / 60), - (int) ((ci->length / 75) % 60), - (int) (ci->length % 75)); - - /* Set the pre-gap of the first track of this session. */ - if (session_changed) - spg[ct->session] = ct->idx[0].start; - } - } - } - - /* Set the lead out starts for all sessions. */ - for (int i = 0; i <= ls; i++) { - lo[i] = NULL; - for (int j = (cdi->tracks_num - 1); j >= 0; j--) { - track_t *jt = &(cdi->tracks[j]); - if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { - lo[i] = &(cdi->tracks[j]); - break; - } - } - } - - cdrom_image_backend_log("Fourth pass:\n"); - for (int i = 0; i < cdi->tracks_num; i++) { - ct = &(cdi->tracks[i]); - lt = NULL; - switch (ct->point) { - case 0xa0: - for (int j = 0; j < cdi->tracks_num; j++) { - track_t *jt = &(cdi->tracks[j]); - if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { - lt = &(cdi->tracks[j]); - break; - } - } - if (lt != NULL) { - int disc_type = 0x00; - - ct->attr = lt->attr; - - ct->mode = lt->mode; - ct->form = lt->form; - - if (lt->mode == 2) - disc_type = (lt->form > 0) ? 0x20 : 0x10; - for (int j = 0; j < 3; j++) { - ci = &(ct->idx[j]); - ci->type = INDEX_ZERO; - ci->start = (lt->point * 60 * 75) + (disc_type * 75); - ci->length = 0; - } - } - break; - case 0xa1: - for (int j = (cdi->tracks_num - 1); j >= 0; j--) { - track_t *jt = &(cdi->tracks[j]); - if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { - lt = &(cdi->tracks[j]); - break; - } - } - if (lt != NULL) { - ct->attr = lt->attr; - - ct->mode = lt->mode; - ct->form = lt->form; - - for (int j = 0; j < 3; j++) { - ci = &(ct->idx[j]); - ci->type = INDEX_ZERO; - ci->start = (lt->point * 60 * 75); - ci->length = 0; - } - } - break; - case 0xa2: - if (lo[ct->session] != NULL) { - lt = lo[ct->session]; - - ct->attr = lt->attr; - - ct->mode = lt->mode; - ct->form = lt->form; - - if (ct->idx[1].type != INDEX_NORMAL) { - track_index_t *li = &(lt->idx[2]); - - for (int j = 0; j < 3; j++) { - ci = &(ct->idx[j]); - ci->type = INDEX_ZERO; - ci->start = li->start + li->length; - ci->length = 0; - } - } - } - break; - case 0xb0: - /* - B0 MSF (*NOT* PMSF) points to the beginning of the pre-gap - of the corresponding session's first track. - */ - ct->extra[0] = (spg[ct->session] / 75) / 60; - ct->extra[1] = (spg[ct->session] / 75) % 60; - ct->extra[2] = spg[ct->session] % 75; - - /* - B0 PMSF points to the start of the lead out track - of the last session. - */ - if (lo[ls] != NULL) { - lt = lo[ls]; - track_index_t *li = &(lt->idx[2]); - - ct->idx[1].start = li->start + li->length; - } - break; - } - -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - if ((ct->point >= 0xa0) && (ct->point <= 0xa2)) - cdrom_image_backend_log(" TRACK %02X, SESSION %i: start = %016" PRIX64 " (%2i:%02i:%02i)\n", - ct->point, ct->session, - ct->idx[1].start, - (int) ((ct->idx[1].start / 75) / 60), - (int) ((ct->idx[1].start / 75) % 60), - (int) (ct->idx[1].start % 75)); -#endif - } -} - -int -cdi_load_iso(cd_img_t *cdi, const char *filename) -{ - track_t *ct = NULL; - track_index_t *ci = NULL; - track_file_t *tf = NULL; - int success; - int error = 1; - int is_viso = 0; - - cdi->tracks = NULL; - success = 1; - - cdrom_image_backend_log("First pass:\n"); - cdi->tracks_num = 0; - - cdi_insert_track(cdi, 1, 0xa0); - cdi_insert_track(cdi, 1, 0xa1); - cdi_insert_track(cdi, 1, 0xa2); - - /* Data track (shouldn't there be a lead in track?). */ - tf = track_file_init(filename, &error, &is_viso); - - if (error) { - cdrom_image_backend_log("ISO: cannot open file '%s'!\n", filename); - - if (tf != NULL) { - tf->close(tf); - tf = NULL; - } - success = 0; - } else if (is_viso) - success = 3; - - if (success) { - ct = cdi_insert_track(cdi, 1, 1); - ci = &(ct->idx[1]); - - ct->form = 0; - ct->mode = 0; - - for (int i = 0; i < 3; i++) - ct->idx[i].type = INDEX_NONE; - - ct->attr = DATA_TRACK; - - /* Try to detect ISO type. */ - ct->mode = 1; - ct->form = 0; - - ci->type = INDEX_NORMAL; - ci->file_start = 0ULL; - - ci->file = tf; - - /* For Mode 2 XA, skip the first 8 bytes in every sector when sector size = 2336. */ - if (cdi_can_read_pvd(ci->file, RAW_SECTOR_SIZE, 0, 0)) - ct->sector_size = RAW_SECTOR_SIZE; - else if (cdi_can_read_pvd(ci->file, 2336, 1, 0)) { - ct->sector_size = 2336; - ct->mode = 2; - } else if (cdi_can_read_pvd(ci->file, 2324, 1, 2)) { - ct->sector_size = 2324; - ct->mode = 2; - ct->form = 2; - } else if (cdi_can_read_pvd(ci->file, 2328, 1, 2)) { - ct->sector_size = 2328; - ct->mode = 2; - ct->form = 2; - } else if (cdi_can_read_pvd(ci->file, 2336, 1, 1)) { - ct->sector_size = 2336; - ct->mode = 2; - ct->form = 1; - ct->skip = 8; - } else if (cdi_can_read_pvd(ci->file, RAW_SECTOR_SIZE, 1, 0)) { - ct->sector_size = RAW_SECTOR_SIZE; - ct->mode = 2; - } else if (cdi_can_read_pvd(ci->file, RAW_SECTOR_SIZE, 1, 1)) { - ct->sector_size = RAW_SECTOR_SIZE; - ct->mode = 2; - ct->form = 1; - } else { - /* We use 2048 mode 1 as the default. */ - ct->sector_size = COOKED_SECTOR_SIZE; - } - - cdrom_image_backend_log("TRACK 1: Mode = %i, Form = %i, Sector size = %08X\n", - ct->mode, ct->form, ct->sector_size); - } - - tf = NULL; - - if (!success) - return 0; - - cdi_last_3_passes(cdi); - - return success; -} - -int -cdi_load_cue(cd_img_t *cdi, const char *cuefile) -{ - track_t *ct = NULL; - track_index_t *ci = NULL; - track_file_t *tf = NULL; - uint64_t frame = 0ULL; - uint64_t last = 0ULL; - uint8_t session = 1; - int success; - int error; - int is_viso = 0; - int lead[3] = { 0 }; - char pathname[MAX_FILENAME_LENGTH]; - char buf[MAX_LINE_LENGTH]; - FILE *fp; - char *line; - char *command; - char *type; - char temp; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - /* Get a copy of the filename into pathname, we need it later. */ - memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(char)); - path_get_dirname(pathname, cuefile); - - /* Open the file. */ - fp = plat_fopen(cuefile, "r"); - if (fp == NULL) - return 0; - - success = 0; - - cdrom_image_backend_log("First pass:\n"); - cdi->tracks_num = 0; - - for (int i = 0; i < 3; i++) { - lead[i] = cdi->tracks_num; - (void *) cdi_insert_track(cdi, session, 0xa0 + i); - } - cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); - - while (1) { - line = buf; - - /* Read a line from the cuesheet file. */ - if (feof(fp) || (fgets(buf, sizeof(buf), fp) == NULL) || ferror(fp)) - break; - - /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, - but do checks to make sure we're not nuking other bytes. */ - for (uint8_t i = 0; i < 2; i++) { - if (strlen(buf) > 0) { - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; - /* nuke trailing newline */ - else if (buf[strlen(buf) - 1] == '\r') - buf[strlen(buf) - 1] = '\0'; - /* nuke trailing newline */ - } - } - cdrom_image_backend_log(" line = %s\n", line); - - (void) cdi_cue_get_keyword(&command, &line); - - if (!strcmp(command, "FILE")) { - /* The file for the track. */ - char filename[MAX_FILENAME_LENGTH]; - char ansi[MAX_FILENAME_LENGTH]; - - tf = NULL; - - memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); - memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(char)); - - success = cdi_cue_get_buffer(ansi, &line, 0); - if (!success) - break; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; - - error = 1; - is_viso = 0; - - if (!strcmp(type, "BINARY") || !strcmp(type, "MOTOROLA")) { - if (!path_abs(ansi)) - path_append_filename(filename, pathname, ansi); - else - strcpy(filename, ansi); - - tf = track_file_init(filename, &error, &is_viso); - - if (tf) - tf->motorola = !strcmp(type, "MOTOROLA"); - } else if (!strcmp(type, "WAVE") || !strcmp(type, "AIFF") || !strcmp(type, "MP3")) { - if (!path_abs(ansi)) - path_append_filename(filename, pathname, ansi); - else - strcpy(filename, ansi); - tf = audio_init(filename, &error); - } - if (error) { - cdrom_image_backend_log("CUE: cannot open file '%s' in cue sheet!\n", - filename); - - if (tf != NULL) { - tf->close(tf); - tf = NULL; - } - success = 0; - } else if (is_viso) - success = 3; - } else if (!strcmp(command, "TRACK")) { - int t = cdi_cue_get_number(&line); - success = cdi_cue_get_keyword(&type, &line); - - if (!success) - break; - - ct = cdi_insert_track(cdi, session, t); - - cdrom_image_backend_log(" TRACK %i\n", t); - - ct->form = 0; - ct->mode = 0; - - if (!strcmp(type, "AUDIO")) { - ct->sector_size = RAW_SECTOR_SIZE; - ct->attr = AUDIO_TRACK; - } else if (!memcmp(type, "MODE", 4)) { - uint32_t mode; - ct->attr = DATA_TRACK; - sscanf(type, "MODE%" PRIu32 "/%" PRIu32, &mode, &(ct->sector_size)); - ct->mode = mode; - if (ct->mode == 2) switch(ct->sector_size) { - case 2324: case 2328: - ct->form = 2; - break; - case 2048: case 2336: case 2352: case 2448: - ct->form = 1; - break; - } - if ((ct->sector_size == 2336) && (ct->mode == 2) && (ct->form == 1)) - ct->skip = 8; - } else if (!memcmp(type, "CD", 2)) { - ct->attr = DATA_TRACK; - ct->mode = 2; - sscanf(type, "CD%c/%i", &temp, &(ct->sector_size)); - } else - success = 0; - - if (success) - last = ct->sector_size; - } else if (!strcmp(command, "INDEX")) { - int t = cdi_cue_get_number(&line); - ci = &(ct->idx[t]); - - cdrom_image_backend_log(" INDEX %i (1)\n", t); - - ci->type = INDEX_NORMAL; - ci->file = tf; - success = cdi_cue_get_frame(&frame, &line); - ci->file_start = frame; - } else if (!strcmp(command, "PREGAP")) { - ci = &(ct->idx[0]); - cdrom_image_backend_log(" INDEX 0 (0)\n"); - - ci->type = INDEX_ZERO; - ci->file = tf; - success = cdi_cue_get_frame(&frame, &line); - ci->length = frame; - } else if (!strcmp(command, "PAUSE")) { - ci = &(ct->idx[1]); - cdrom_image_backend_log(" INDEX 1 (0)\n"); - - ci->type = INDEX_ZERO; - ci->file = tf; - success = cdi_cue_get_frame(&frame, &line); - ci->length = frame; - } else if (!strcmp(command, "POSTGAP")) { - ci = &(ct->idx[2]); - cdrom_image_backend_log(" INDEX 2 (0)\n"); - - ci->type = INDEX_ZERO; - ci->file = tf; - success = cdi_cue_get_frame(&frame, &line); - ci->length = frame; - } else if (!strcmp(command, "ZERO")) { - ci = &(ct->idx[1]); - cdrom_image_backend_log(" INDEX 1 (0)\n"); - - ci->type = INDEX_ZERO; - ci->file = tf; - success = cdi_cue_get_frame(&frame, &line); - ci->length = frame; - } else if (!strcmp(command, "FLAGS")) - success = cdi_cue_get_flags(ct, &line); - else if (!strcmp(command, "REM")) { - success = 1; - char *space = strstr(line, " "); - if (space != NULL) { - space++; - if (space < (line + strlen(line))) { - (void) cdi_cue_get_keyword(&command, &space); - if (!strcmp(command, "LEAD-OUT")) { - ct = &(cdi->tracks[lead[2]]); - cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) ct); - ct->sector_size = last; - ci = &(ct->idx[1]); - ci->type = INDEX_NORMAL; - ci->file = tf; - success = cdi_cue_get_frame(&frame, &space); - ci->file_start = frame; - - cdrom_image_backend_log(" LEAD-OUT\n"); - } else if (!strcmp(command, "SESSION")) { - session = cdi_cue_get_number(&space); - - if (session > 1) { - ct = cdi_insert_track(cdi, session - 1, 0xb0); - ci = &(ct->idx[1]); - ci->start = (0x40 * 60 * 75) + (0x02 * 75); - - if (session == 2) { - ct->extra[3] = 0x02; - - /* 5F:00:00 on Wembley, C0:00:00 in the spec. And what's in PMSF? */ - ct = cdi_insert_track(cdi, session - 1, 0xc0); - ci = &(ct->idx[1]); - ct->extra[0] = 0x5f; /* Optimum recording power. */ - } else - ct->extra[3] = 0x01; - - for (int i = 0; i < 3; i++) { - lead[i] = cdi->tracks_num; - (void *) cdi_insert_track(cdi, session, 0xa0 + i); - } - cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", - (uint64_t) &(cdi->tracks[lead[2]])); - } - - cdrom_image_backend_log(" SESSION %i\n", session); - } - } - } - } else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || - !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || - !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || - !strcmp(command, "")) - /* Ignored commands. */ - success = 1; - else { - cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command); - - success = 0; - } - - if (!success) - break; - } - - tf = NULL; - - fclose(fp); - - if (!success) - return 0; - - cdi_last_3_passes(cdi); - - return success; -} - -/* Root functions. */ -static void -cdi_clear_tracks(cd_img_t *cdi) -{ - track_file_t *last = NULL; - track_t *cur = NULL; - track_index_t *idx = NULL; - - if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) - return; - - for (int i = 0; i < cdi->tracks_num; i++) { - cur = &cdi->tracks[i]; - - if ((cur->point >= 1) && (cur->point <= 99)) for (int j = 0; j < 3; j++) { - idx = &(cur->idx[j]); - - /* Make sure we do not attempt to close a NULL file. */ - if (idx->file != NULL) { - if (idx->file != last) { - last = idx->file; - index_file_close(idx); - } else - idx->file = NULL; - } - } - } - - /* Now free the array. */ - free(cdi->tracks); - cdi->tracks = NULL; - - /* Mark that there's no tracks. */ - cdi->tracks_num = 0; -} - -void -cdi_close(cd_img_t *cdi) -{ - cdi_clear_tracks(cdi); - free(cdi); -} - -int -cdi_set_device(cd_img_t *cdi, const char *path) -{ - uintptr_t ext = path + strlen(path) - strrchr(path, '.'); - int ret; - - cdrom_image_backend_log("cdi_set_device(): %" PRIu64 ", %lli, %s\n", - ext, strlen(path), path + strlen(path) - ext + 1); - - if ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE")) { - if ((ret = cdi_load_cue(cdi, path))) - return ret; - - cdi_clear_tracks(cdi); - } - - if ((ret = cdi_load_iso(cdi, path))) - return ret; - - cdi_close(cdi); - - return 0; -} diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index 24f60836d..52657e38d 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -21,7 +21,9 @@ #define __STDC_FORMAT_MACROS #include #include +#ifdef IMAGE_VISO_LOG #include +#endif #include #include #include @@ -29,15 +31,16 @@ #include #include #include -#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/bswap.h> -#include <86box/cdrom_image_backend.h> +#include <86box/cdrom.h> +#include <86box/cdrom_image.h> +#include <86box/cdrom_image_viso.h> +#include <86box/log.h> #include <86box/path.h> #include <86box/plat.h> #include <86box/plat_dir.h> #include <86box/version.h> -#include <86box/timer.h> #include <86box/nvr.h> #ifndef S_ISDIR @@ -136,29 +139,30 @@ static const char rr_eid[] = "RRIP_1991A"; /* identifiers used in ER field for static const char rr_edesc[] = "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS."; static int8_t tz_offset = 0; -#ifdef ENABLE_CDROM_IMAGE_VISO_LOG -int cdrom_image_viso_do_log = ENABLE_CDROM_IMAGE_VISO_LOG; +#ifdef IMAGE_VISO_LOG +int image_viso_do_log = IMAGE_VISO_LOG; void -cdrom_image_viso_log(const char *fmt, ...) +image_viso_log(void *priv, const char *fmt, ...) { va_list ap; - if (cdrom_image_viso_do_log) { + if (image_viso_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define cdrom_image_viso_log(fmt, ...) +# define image_viso_log(priv, fmt, ...) #endif static size_t -viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp) +viso_pread(void *ptr, const uint64_t offset, const size_t size, + const size_t count, FILE *fp) { - uint64_t cur_pos = ftello64(fp); - size_t ret = 0; + const uint64_t cur_pos = ftello64(fp); + size_t ret = 0; if (fseeko64(fp, offset, SEEK_SET) != -1) ret = fread(ptr, size, count, fp); fseeko64(fp, cur_pos, SEEK_SET); @@ -166,10 +170,11 @@ viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp) } static size_t -viso_pwrite(const void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp) +viso_pwrite(const void *ptr, const uint64_t offset, const size_t size, + const size_t count, FILE *fp) { - uint64_t cur_pos = ftello64(fp); - size_t ret = 0; + const uint64_t cur_pos = ftello64(fp); + size_t ret = 0; if (fseeko64(fp, offset, SEEK_SET) != -1) ret = fwrite(ptr, size, count, fp); fseeko64(fp, cur_pos, SEEK_SET); @@ -691,22 +696,22 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) /* Close any existing FIFO entry's file. */ viso_entry_t *other_entry = viso->file_fifo[viso->file_fifo_pos]; if (other_entry && other_entry->file) { - cdrom_image_viso_log("VISO: Closing [%s]", other_entry->path); + image_viso_log(viso->tf.log, "Closing [%s]...\n", other_entry->path); fclose(other_entry->file); other_entry->file = NULL; - cdrom_image_viso_log("\n"); + image_viso_log(viso->tf.log, "Done\n"); } /* Open file. */ - cdrom_image_viso_log("VISO: Opening [%s]", entry->path); + image_viso_log(viso->tf.log, "Opening [%s]...\n", entry->path); if ((entry->file = fopen(entry->path, "rb"))) { - cdrom_image_viso_log("\n"); + image_viso_log(viso->tf.log, "Done\n"); /* Add this entry to the FIFO. */ viso->file_fifo[viso->file_fifo_pos++] = entry; viso->file_fifo_pos &= (sizeof(viso->file_fifo) / sizeof(viso->file_fifo[0])) - 1; } else { - cdrom_image_viso_log(" => failed\n"); + image_viso_log(viso->tf.log, "Failed\n"); /* Clear any existing FIFO entry. */ viso->file_fifo[viso->file_fifo_pos] = NULL; @@ -753,12 +758,12 @@ viso_close(void *priv) if (viso == NULL) return; - cdrom_image_viso_log("VISO: close()\n"); + image_viso_log(viso->tf.log, "close()\n"); /* De-allocate everything. */ if (tf->fp) fclose(tf->fp); -#ifndef ENABLE_CDROM_IMAGE_VISO_LOG +#ifndef ENABLE_IMAGE_VISO_LOG remove(nvr_path(viso->tf.fn)); #endif @@ -777,21 +782,32 @@ viso_close(void *priv) if (viso->entry_map) free(viso->entry_map); + if (tf->log != NULL) { + + } + free(viso); } track_file_t * -viso_init(const char *dirname, int *error) +viso_init(const uint8_t id, const char *dirname, int *error) { - cdrom_image_viso_log("VISO: init()\n"); - /* Initialize our data structure. */ viso_t *viso = (viso_t *) calloc(1, sizeof(viso_t)); uint8_t *data = NULL; uint8_t *p; *error = 1; + if (viso == NULL) goto end; + + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i VISO ", id + 1); + viso->tf.log = log_open(n); + + image_viso_log(viso->tf.log, "init()\n"); + viso->sector_size = VISO_SECTOR_SIZE; viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR; viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */ @@ -802,7 +818,7 @@ viso_init(const char *dirname, int *error) goto end; /* Open temporary file. */ -#ifdef ENABLE_CDROM_IMAGE_VISO_LOG +#ifdef ENABLE_IMAGE_VISO_LOG strcpy(viso->tf.fn, "viso-debug.iso"); #else plat_tempfile(viso->tf.fn, "viso", ".tmp"); @@ -812,7 +828,7 @@ viso_init(const char *dirname, int *error) goto end; /* Set up directory traversal. */ - cdrom_image_viso_log("VISO: Traversing directories:\n"); + image_viso_log(viso->tf.log, "Traversing directories:\n"); viso_entry_t *entry; viso_entry_t *last_entry; viso_entry_t *dir; @@ -839,7 +855,7 @@ viso_init(const char *dirname, int *error) if (!S_ISDIR(dir->stats.st_mode)) /* root is not a directory */ goto end; dir->parent = dir; /* for the root's path table and .. entries */ - cdrom_image_viso_log("[%08X] %s => [root]\n", dir, dir->path); + image_viso_log(viso->tf.log, "[%08X] %s => [root]\n", dir, dir->path); /* Traverse directories, starting with the root. */ viso_entry_t **dir_entries = NULL; @@ -889,7 +905,8 @@ viso_init(const char *dirname, int *error) /* Set basename. */ strcpy(entry->name_short, children_count ? ".." : "."); - cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path, entry->name_short); + image_viso_log(viso->tf.log, "[%08X] %s => %s\n", entry, + dir->path, entry->name_short); } /* Iterate through this directory's children again, making the entries. */ @@ -897,12 +914,16 @@ viso_init(const char *dirname, int *error) rewinddir(dirp); while ((readdir_entry = readdir(dirp))) { /* Ignore . and .. pseudo-directories. */ - if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.'))) + if ((readdir_entry->d_name[0] == '.') && + ((readdir_entry->d_name[1] == '\0') || + (*((uint16_t *) &readdir_entry->d_name[1]) == '.'))) continue; /* Add and fill entry. */ - entry = dir_entries[children_count++] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + strlen(readdir_entry->d_name) + 2); - if (!entry) + entry = dir_entries[children_count++] = + (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + + dir_path_len + strlen(readdir_entry->d_name) + 2); + if (entry == NULL) break; entry->parent = dir; strcpy(entry->path, dir->path); @@ -972,10 +993,12 @@ have_eltorito_entry: continue; } - cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", entry, dir->path, entry->name_short, entry->basename); + image_viso_log(viso->tf.log, "[%08X] %s => [%-12s] %s\n", entry, + dir->path, entry->name_short, entry->basename); } } else { - cdrom_image_viso_log("VISO: Failed to enumerate [%s], will be empty\n", dir->path); + image_viso_log(viso->tf.log, "Failed to enumerate [%s], will be empty\n", + dir->path); } /* Add terminator. */ @@ -1129,13 +1152,17 @@ next_dir: /* Write El Torito boot descriptor. This is an awkward spot for that, but the spec requires it to be the second descriptor. */ if (!i && eltorito_entry) { - cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry); + image_viso_log(viso->tf.log, "Writing El Torito boot descriptor for " + "entry [%08X]\n", eltorito_entry); p = data; if (!(viso->format & VISO_FORMAT_ISO)) - VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); /* sector offset (HSF only) */ - *p++ = 0; /* type */ - memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ + /* Sector offset (HSF only). */ + VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); + /* Type. */ + *p++ = 0; + /* Standard ID. */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); p += 5; *p++ = 1; /* version */ @@ -1236,7 +1263,7 @@ next_dir: /* Write each path table. */ for (int i = 0; i <= ((max_vd << 1) | 1); i++) { - cdrom_image_viso_log("VISO: Generating path table #%d:\n", i); + image_viso_log(viso->tf.log, "Generating path table #%d:\n", i); /* Save this path table's start offset. */ uint64_t pt_start = ftello64(viso->tf.fp); @@ -1257,7 +1284,9 @@ next_dir: continue; } - cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename : dir->name_short); + image_viso_log(viso->tf.log, "[%08X] %s => %s\n", dir, + dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename : + dir->name_short); /* Save this directory's path table index and offset. */ dir->pt_idx = pt_idx; @@ -1325,7 +1354,7 @@ next_dir: /* Write directory records for each type. */ int dir_type = VISO_DIR_CURRENT_ROOT; for (int i = 0; i <= max_vd; i++) { - cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i); + image_viso_log(viso->tf.log, "Generating directory record set #%d:\n", i); /* Go through directories. */ dir = viso->root_dir; @@ -1368,8 +1397,10 @@ next_dir: if ((entry == eltorito_entry) || (entry == eltorito_dir)) goto next_entry; - cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path, - ((dir_type == VISO_DIR_PARENT) ? ".." : ((dir_type < VISO_DIR_PARENT) ? "." : (i ? entry->basename : entry->name_short)))); + image_viso_log(viso->tf.log, "[%08X] %s => %s\n", entry, dir->path, + ((dir_type == VISO_DIR_PARENT) ? ".." : + ((dir_type < VISO_DIR_PARENT) ? "." : + (i ? entry->basename : entry->name_short)))); /* Fill directory record. */ viso_fill_dir_record(data, entry, viso, dir_type); @@ -1436,7 +1467,8 @@ next_entry: /* Allocate entry map for sector->file lookups. */ size_t orig_sector_size = viso->sector_size; while (1) { - cdrom_image_viso_log("VISO: Allocating entry map for %zu %zu-byte sectors\n", viso->entry_map_size, viso->sector_size); + image_viso_log(viso->tf.log, "Allocating entry map for %zu %zu-byte sectors\n", + viso->entry_map_size, viso->sector_size); viso->entry_map = (viso_entry_t **) calloc(viso->entry_map_size, sizeof(viso_entry_t *)); if (viso->entry_map) { /* Successfully allocated. */ @@ -1477,7 +1509,7 @@ next_entry: viso->all_sectors = viso->metadata_sectors; /* Go through files, assigning sectors to them. */ - cdrom_image_viso_log("VISO: Assigning sectors to files:\n"); + image_viso_log(viso->tf.log, "Assigning sectors to files:\n"); size_t base_factor = viso->sector_size / orig_sector_size; viso_entry_t *prev_entry = viso->root_dir; viso_entry_t **entry_map_p = viso->entry_map; @@ -1522,7 +1554,8 @@ next_entry: size_t size = entry->stats.st_size / viso->sector_size; if (entry->stats.st_size % viso->sector_size) size++; /* round up to the next sector */ - cdrom_image_viso_log("[%08X] %s => %zu + %zu sectors\n", entry, entry->path, viso->all_sectors, size); + image_viso_log(viso->tf.log, "[%08X] %s => %zu + %zu sectors\n", entry, + entry->path, viso->all_sectors, size); /* Allocate sectors to this file. */ viso->all_sectors += size; @@ -1541,9 +1574,10 @@ next_entry: viso_pwrite(data, viso->vol_size_offsets[i], 8, 1, viso->tf.fp); /* Metadata processing is finished, read it back to memory. */ - cdrom_image_viso_log("VISO: Reading back %zu %zu-byte sectors of metadata\n", viso->metadata_sectors, viso->sector_size); + image_viso_log(viso->tf.log, "Reading back %zu %zu-byte sectors of metadata\n", + viso->metadata_sectors, viso->sector_size); viso->metadata = (uint8_t *) calloc(viso->metadata_sectors, viso->sector_size); - if (!viso->metadata) + if (viso->metadata == NULL) goto end; fseeko64(viso->tf.fp, 0, SEEK_SET); size_t metadata_size = viso->metadata_sectors * viso->sector_size; @@ -1554,7 +1588,7 @@ next_entry: /* We no longer need the temporary file; close and delete it. */ fclose(viso->tf.fp); viso->tf.fp = NULL; -#ifndef ENABLE_CDROM_IMAGE_VISO_LOG +#ifndef ENABLE_IMAGE_VISO_LOG remove(nvr_path(viso->tf.fn)); #endif @@ -1565,13 +1599,15 @@ end: /* Set the function pointers. */ viso->tf.priv = viso; if (!*error) { - cdrom_image_viso_log("VISO: Initialized\n"); + image_viso_log(viso->tf.log, "Initialized\n"); + viso->tf.read = viso_read; viso->tf.get_length = viso_get_length; viso->tf.close = viso_close; + return &viso->tf; } else { - cdrom_image_viso_log("VISO: Initialization failed\n"); + image_viso_log(viso->tf.log, "Initialization failed\n"); if (data) free(data); viso_close(&viso->tf); diff --git a/src/cdrom/cdrom_ioctl.c b/src/cdrom/cdrom_ioctl.c deleted file mode 100644 index 2bb691f30..000000000 --- a/src/cdrom/cdrom_ioctl.c +++ /dev/null @@ -1,267 +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. - * - * CD-ROM passthrough support. - * - * - * - * Authors: TheCollector1995, , - * Miran Grca, - * - * Copyright 2023 TheCollector1995. - * Copyright 2023 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/path.h> -#include <86box/plat.h> -#include <86box/scsi_device.h> -#include <86box/cdrom.h> -#include <86box/plat_cdrom.h> - -#ifdef ENABLE_CDROM_IOCTL_LOG -int cdrom_ioctl_do_log = ENABLE_CDROM_IOCTL_LOG; - -void -cdrom_ioctl_log(const char *fmt, ...) -{ - va_list ap; - - if (cdrom_ioctl_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define cdrom_ioctl_log(fmt, ...) -#endif - -/* 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 void -ioctl_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) -{ - TMSF tmsf; - - plat_cdrom_get_audio_track_info(dev->local, end, track, &ti->number, &tmsf, &ti->attr); - - ti->m = tmsf.min; - ti->s = tmsf.sec; - ti->f = tmsf.fr; -} - -static void -ioctl_get_raw_track_info(cdrom_t *dev, int *num, raw_track_info_t *rti) -{ - plat_cdrom_get_raw_track_info(dev->local, num, rti); -} - -static void -ioctl_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) -{ - TMSF rel_pos; - TMSF abs_pos; - - if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) { - const uint32_t trk = plat_cdrom_get_track_start(dev->local, lba, &subc->attr, &subc->track); - - FRAMES_TO_MSF(lba + 150, &abs_pos.min, &abs_pos.sec, &abs_pos.fr); - - /* Absolute position should be adjusted by 150, not the relative ones. */ - FRAMES_TO_MSF(lba - trk, &rel_pos.min, &rel_pos.sec, &rel_pos.fr); - - subc->index = 1; - } else - plat_cdrom_get_audio_sub(dev->local, lba, &subc->attr, &subc->track, &subc->index, - &rel_pos, &abs_pos); - - subc->abs_m = abs_pos.min; - subc->abs_s = abs_pos.sec; - subc->abs_f = abs_pos.fr; - - subc->rel_m = rel_pos.min; - subc->rel_s = rel_pos.sec; - subc->rel_f = rel_pos.fr; - - cdrom_ioctl_log("ioctl_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", - subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f, - subc->rel_m, subc->rel_s, subc->rel_f); -} - -static int -ioctl_get_capacity(cdrom_t *dev) -{ - int ret; - - ret = plat_cdrom_get_last_block(dev->local); - cdrom_ioctl_log("GetCapacity=%x.\n", ret); - return ret; -} - -static int -ioctl_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) -{ - int m; - int s; - int f; - - if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - - if (ismsf) { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - pos = MSFtoLBA(m, s, f) - 150; - } - - /* GetTrack requires LBA. */ - return plat_cdrom_is_track_audio(dev->local, pos); -} - -static int -ioctl_is_track_pre(cdrom_t *dev, uint32_t lba) -{ - return plat_cdrom_is_track_pre(dev->local, lba); -} - -static int -ioctl_sector_size(cdrom_t *dev, uint32_t lba) -{ - cdrom_ioctl_log("LBA=%x.\n", lba); - return plat_cdrom_get_sector_size(dev->local, lba); -} - -static int -ioctl_read_sector(cdrom_t *dev, uint8_t *b, uint32_t lba) -{ - cdrom_ioctl_log("cdrom_ioctl_read_sector(): Raw.\n"); - return plat_cdrom_read_sector(dev->local, b, lba); -} - -static int -ioctl_track_type(cdrom_t *dev, uint32_t lba) -{ - int ret = CD_TRACK_UNK_DATA; - - if (ioctl_is_track_audio(dev, lba, 0)) - ret = CD_TRACK_AUDIO; - - cdrom_ioctl_log("cdrom_ioctl_track_type(): %i\n", ret); - - return ret; -} - -static int -ioctl_ext_medium_changed(cdrom_t *dev) -{ - int ret; - - if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) - ret = 0; - else - ret = plat_cdrom_ext_medium_changed(dev->local); - - if (ret == 1) { - dev->cd_status = CD_STATUS_STOPPED; - dev->cdrom_capacity = ioctl_get_capacity(dev); - } else if (ret == -1) - dev->cd_status = CD_STATUS_EMPTY; - - return ret; -} - -static void -ioctl_exit(cdrom_t *dev) -{ - cdrom_ioctl_log("CDROM: ioctl_exit(%s)\n", dev->image_path); - dev->cd_status = CD_STATUS_EMPTY; - - plat_cdrom_close(dev->local); - dev->local = NULL; - - dev->ops = NULL; -} - -static const cdrom_ops_t cdrom_ioctl_ops = { - ioctl_get_track_info, - ioctl_get_raw_track_info, - ioctl_get_subchannel, - ioctl_is_track_pre, - ioctl_sector_size, - ioctl_read_sector, - ioctl_track_type, - ioctl_ext_medium_changed, - ioctl_exit -}; - -static int -cdrom_ioctl_open_abort(cdrom_t *dev) -{ - cdrom_ioctl_close(dev); - dev->ops = NULL; - dev->image_path[0] = 0; - return 1; -} - -int -cdrom_ioctl_open(cdrom_t *dev, const char *drv) -{ - const char *actual_drv = &(drv[8]); - int local_size = plat_cdrom_get_local_size(); - - /* Make sure to not STRCPY if the two are pointing - at the same place. */ - if (drv != dev->image_path) - strcpy(dev->image_path, drv); - - /* Open the image. */ - if (strstr(drv, "ioctl://") != drv) - return cdrom_ioctl_open_abort(dev); - cdrom_ioctl_log("actual_drv = %s\n", actual_drv); - if (dev->local == NULL) - dev->local = calloc(1, local_size); - int i = plat_cdrom_set_drive(dev->local, actual_drv); - if (!i) - return cdrom_ioctl_open_abort(dev); - - /* All good, reset state. */ - dev->cd_status = CD_STATUS_STOPPED; - dev->seek_pos = 0; - dev->cd_buflen = 0; - dev->cdrom_capacity = ioctl_get_capacity(dev); - cdrom_ioctl_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", - dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL); - - /* Attach this handler to the drive. */ - dev->ops = &cdrom_ioctl_ops; - - return 0; -} - -void -cdrom_ioctl_close(cdrom_t *dev) -{ - cdrom_ioctl_log("CDROM: ioctl_close(%s)\n", dev->image_path); - - if (dev && dev->ops && dev->ops->exit) - dev->ops->exit(dev); -} - diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c index c3c362b1b..19fa06e23 100644 --- a/src/cdrom/cdrom_mitsumi.c +++ b/src/cdrom/cdrom_mitsumi.c @@ -118,14 +118,6 @@ typedef struct mcd_t { int newstat; } mcd_t; -/* 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. */ -#ifdef MSFtoLBA -#undef MSFtoLBA -#endif -#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) - #define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4)) #define CD_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f)) diff --git a/src/config.c b/src/config.c index 24efcf264..83b010eb2 100644 --- a/src/config.c +++ b/src/config.c @@ -29,12 +29,13 @@ */ #include +#ifdef ENABLE_CONFIG_LOG #include +#endif #include #include #include #include -#include #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" @@ -53,10 +54,8 @@ #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/fdd.h> -#include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/gameport.h> -#include <86box/serial.h> #include <86box/serial_passthrough.h> #include <86box/machine.h> #include <86box/mouse.h> @@ -300,7 +299,7 @@ load_machine(void) /* Only copy if a file with the new name doesn't already exist. */ FILE *g = nvr_fopen(new_fn, "rb"); - if (!g) { + if (g == NULL) { FILE *f = nvr_fopen(entry->d_name, "rb"); g = nvr_fopen(new_fn, "wb"); @@ -361,7 +360,7 @@ load_machine(void) while (!cpu_family_is_eligible(&cpu_families[c], machine)) { if (cpu_families[c++].package == 0) { /* End of list. */ - fatal("No eligible CPU families for the selected machine\n"); + fatal("Configuration: No eligible CPU families for the selected machine\n"); return; } } @@ -441,7 +440,6 @@ load_video(void) if (free_p) { free(p); p = NULL; - free_p = 0; } } @@ -618,7 +616,7 @@ load_sound(void) memset(temp, '\0', sizeof(temp)); p = ini_section_get_string(cat, "sound_type", "float"); if (strlen(p) > 511) - fatal("load_sound(): strlen(p) > 511\n"); + fatal("Configuration: Length of sound_type is more than 511\n"); else strncpy(temp, p, 511); if (!strcmp(temp, "float") || !strcmp(temp, "1")) @@ -847,7 +845,6 @@ load_storage_controllers(void) if (free_p) { free(p); p = NULL; - free_p = 0; } ide_ter_enabled = !!ini_section_get_int(cat, "ide_ter", 0); @@ -866,7 +863,7 @@ load_storage_controllers(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511 (cassette_fname)\n"); + fatal("Configuration: Length of cassette_file is more than 511\n"); else strncpy(cassette_fname, p, 511); } else @@ -876,7 +873,7 @@ load_storage_controllers(void) p = ini_section_get_string(cat, "cassette_mode", "load"); if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511\n"); + fatal("Configuration: Length of cassette_mode is more than 511\n"); else strncpy(cassette_mode, p, 511); @@ -887,8 +884,8 @@ load_storage_controllers(void) if (p) { if (path_abs(p)) { if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) - fatal("load_storage_controllers(): strlen(p) > 2047 " - "(cassette_image_history[%i])\n", i); + fatal("Configuration: Length of cassette_image_history_%02i is more " + "than %i\n", i + 1, MAX_IMAGE_PATH_LEN - 1); else snprintf(cassette_image_history[i], MAX_IMAGE_PATH_LEN, "%s", p); } else @@ -937,7 +934,8 @@ load_storage_controllers(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511 (cart_fns[%i])\n", c); + fatal("Configuration: Length of cartridge_%02i_fn is more than 511\n", + c + 1); else strncpy(cart_fns[c], p, 511); } else @@ -952,8 +950,8 @@ load_storage_controllers(void) if (p) { if (path_abs(p)) { if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) - fatal("load_storage_controllers(): strlen(p) > 2047 " - "(cart_image_history[%i][%i])\n", c, i); + fatal("Configuration: Length of cartridge_%02i_image_history_%02i " + "is more than %i\n", c + 1, i + 1, MAX_IMAGE_PATH_LEN - 1); else snprintf(cart_image_history[c][i], MAX_IMAGE_PATH_LEN, "%s", p); } else @@ -992,8 +990,8 @@ load_hard_disks(void) sscanf(p, "%u, %u, %u, %i, %s", &hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, (int *) &hdd[c].wp, s); - hdd[c].bus = hdd_string_to_bus(s, 0); - switch (hdd[c].bus) { + hdd[c].bus_type = hdd_string_to_bus(s, 0); + switch (hdd[c].bus_type) { default: case HDD_BUS_DISABLED: max_spt = max_hpc = max_tracks = 0; @@ -1039,7 +1037,7 @@ load_hard_disks(void) hdd[c].tracks = max_tracks; sprintf(temp, "hdd_%02i_speed", c + 1); - switch (hdd[c].bus) { + switch (hdd[c].bus_type) { case HDD_BUS_IDE: case HDD_BUS_ESDI: case HDD_BUS_ATAPI: @@ -1055,28 +1053,28 @@ load_hard_disks(void) /* MFM/RLL */ sprintf(temp, "hdd_%02i_mfm_channel", c + 1); - if (hdd[c].bus == HDD_BUS_MFM) + if (hdd[c].bus_type == HDD_BUS_MFM) hdd[c].mfm_channel = !!ini_section_get_int(cat, temp, c & 1); else ini_section_delete_var(cat, temp); /* XTA */ sprintf(temp, "hdd_%02i_xta_channel", c + 1); - if (hdd[c].bus == HDD_BUS_XTA) + if (hdd[c].bus_type == HDD_BUS_XTA) hdd[c].xta_channel = !!ini_section_get_int(cat, temp, c & 1); else ini_section_delete_var(cat, temp); /* ESDI */ sprintf(temp, "hdd_%02i_esdi_channel", c + 1); - if (hdd[c].bus == HDD_BUS_ESDI) + if (hdd[c].bus_type == HDD_BUS_ESDI) hdd[c].esdi_channel = !!ini_section_get_int(cat, temp, c & 1); else ini_section_delete_var(cat, temp); /* IDE */ sprintf(temp, "hdd_%02i_ide_channel", c + 1); - if ((hdd[c].bus == HDD_BUS_IDE) || (hdd[c].bus == HDD_BUS_ATAPI)) { + if ((hdd[c].bus_type == HDD_BUS_IDE) || (hdd[c].bus_type == HDD_BUS_ATAPI)) { sprintf(tmp2, "%01u:%01u", c >> 1, c & 1); p = ini_section_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1090,7 +1088,7 @@ load_hard_disks(void) ini_section_delete_var(cat, temp); /* SCSI */ - if (hdd[c].bus == HDD_BUS_SCSI) { + if (hdd[c].bus_type == HDD_BUS_SCSI) { sprintf(temp, "hdd_%02i_scsi_location", c + 1); sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c + 2); p = ini_section_get_string(cat, temp, tmp2); @@ -1130,7 +1128,8 @@ load_hard_disks(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_hard_disks(): strlen(p) > 511 (hdd[%i].fn)\n", c); + fatal("Configuration: Length of hdd_%02i_fn is more " + "than 511\n", c + 1); else strncpy(hdd[c].fn, p, 511); } else @@ -1179,12 +1178,12 @@ load_floppy_and_cdrom_drives(void) char temp[512]; char tmp2[512]; char *p; - char *def_type; char s[512]; unsigned int board = 0; unsigned int dev = 0; int c; int d = 0; + int count = cdrom_get_type_count(); memset(temp, 0x00, sizeof(temp)); for (c = 0; c < FDD_NUM; c++) { @@ -1203,7 +1202,7 @@ load_floppy_and_cdrom_drives(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_floppy_and_cdrom_drives(): strlen(p) > 511 (floppyfns[%i])\n", c); + fatal("Configuration: Length of fdd_%02i_fn is more than 511\n", c + 1); else strncpy(floppyfns[c], p, 511); } else @@ -1251,8 +1250,8 @@ load_floppy_and_cdrom_drives(void) if (p) { if (path_abs(p)) { if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) - fatal("load_floppy_and_cdrom_drives(): strlen(p) > 2047 " - "(fdd_image_history[%i][%i])\n", c, i); + fatal("Configuration: Length of fdd_%02i_image_history_%02i is more " + "than %i\n", c + 1, i + 1, MAX_IMAGE_PATH_LEN - 1); else snprintf(fdd_image_history[c][i], MAX_IMAGE_PATH_LEN, "%s", p); } else @@ -1284,12 +1283,20 @@ load_floppy_and_cdrom_drives(void) cdrom[c].speed = ini_section_get_int(cat, temp, 8); sprintf(temp, "cdrom_%02i_type", c + 1); - def_type = (c == 1) ? "86BOX_CD-ROM_1.00" : "none"; - p = ini_section_get_string(cat, temp, def_type); - cdrom_set_type(c, cdrom_get_from_internal_name(p)); - if (cdrom_get_type(c) > KNOWN_CDROM_DRIVE_TYPES) - cdrom_set_type(c, KNOWN_CDROM_DRIVE_TYPES); - if (!strcmp(p, def_type)) + p = ini_section_get_string(cat, temp, "86cd"); + /* TODO: Configuration migration, remove when no longer needed. */ + int cdrom_type = cdrom_get_from_internal_name(p); + if (cdrom_type == -1) { + cdrom_type = cdrom_get_from_name(p); + if (cdrom_type == -1) + cdrom_set_type(c, cdrom_get_from_internal_name("86cd")); + else + cdrom_set_type(c, cdrom_type); + } else + cdrom_set_type(c, cdrom_type); + if (cdrom_get_type(c) >= count) + cdrom_set_type(c, count - 1); + if (!strcmp(p, "86cd")) ini_section_delete_var(cat, temp); /* Default values, needed for proper operation of the Settings dialog. */ @@ -1347,7 +1354,7 @@ load_floppy_and_cdrom_drives(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_floppy_and_cdrom_drives(): strlen(p) > 511 (cdrom[%i].image_path)\n", c); + fatal("Configuration: Length of cdrom_%02i_image_path is more than 511\n", c + 1); else strncpy(cdrom[c].image_path, p, 511); } else @@ -1362,8 +1369,8 @@ load_floppy_and_cdrom_drives(void) if (p) { if (path_abs(p)) { if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) - fatal("load_floppy_and_cdrom_drives(): strlen(p) > 2047 " - "(cdrom[%i].image_history[%i])\n", c, i); + fatal("Configuration: Length of cdrom_%02i_image_history_%02i is more " + "than %i\n", c + 1, i + 1, MAX_IMAGE_PATH_LEN - 1); else snprintf(cdrom[c].image_history[i], MAX_IMAGE_PATH_LEN, "%s", p); } else @@ -1378,6 +1385,12 @@ load_floppy_and_cdrom_drives(void) sprintf(temp, "cdrom_%02i_parameters", c + 1); ini_section_delete_var(cat, temp); + sprintf(temp, "cdrom_%02i_speed", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_type", c + 1); + ini_section_delete_var(cat, temp); + sprintf(temp, "cdrom_%02i_ide_channel", c + 1); ini_section_delete_var(cat, temp); @@ -1476,8 +1489,7 @@ load_other_removable_devices(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_other_removable_devices(): strlen(p) > 511 (zip_drives[%i].image_path)\n", - c); + fatal("Configuration: Length of zip_%02i_image_path is more than 511\n", c + 1); else strncpy(zip_drives[c].image_path, p, 511); } else @@ -1492,8 +1504,8 @@ load_other_removable_devices(void) if (p) { if (path_abs(p)) { if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) - fatal("load_other_removable_devices(): strlen(p) > 2047 " - "(zip_drives[%i].image_history[%i])\n", c, i); + fatal("Configuration: Length of zip_%02i_image_history_%02i is more than %i\n", + c + 1, i + 1, MAX_IMAGE_PATH_LEN - 1); else snprintf(zip_drives[c].image_history[i], MAX_IMAGE_PATH_LEN, "%s", p); } else @@ -1589,8 +1601,7 @@ load_other_removable_devices(void) if (p[0] != 0x00) { if (path_abs(p)) { if (strlen(p) > 511) - fatal("load_other_removable_devices(): strlen(p) > 511 (mo_drives[%i].image_path)\n", - c); + fatal("Configuration: Length of mo_%02i_image_path is more than 511\n", c + 1); else strncpy(mo_drives[c].image_path, p, 511); } else @@ -1605,8 +1616,8 @@ load_other_removable_devices(void) if (p) { if (path_abs(p)) { if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) - fatal("load_other_removable_devices(): strlen(p) > 2047 " - "(mo_drives[%i].image_history[%i])\n", c, i); + fatal("Configuration: Length of mo_%02i_image_history_%02i is more than %i\n", + c + 1, i + 1, MAX_IMAGE_PATH_LEN - 1); else snprintf(mo_drives[c].image_history[i], MAX_IMAGE_PATH_LEN, "%s", p); } else @@ -1698,7 +1709,7 @@ config_load(void) config = ini_read(cfg_path); - if (!config) { + if (config == NULL) { config = ini_new(); config_changed = 1; @@ -2574,7 +2585,7 @@ save_hard_disks(void) for (uint8_t c = 0; c < HDD_NUM; c++) { sprintf(temp, "hdd_%02i_parameters", c + 1); if (hdd_is_valid(c)) { - p = hdd_bus_to_string(hdd[c].bus, 0); + p = hdd_bus_to_string(hdd[c].bus_type, 0); sprintf(tmp2, "%u, %u, %u, %i, %s", hdd[c].spt, hdd[c].hpc, hdd[c].tracks, hdd[c].wp, p); ini_section_set_string(cat, temp, tmp2); @@ -2582,25 +2593,26 @@ save_hard_disks(void) ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_mfm_channel", c + 1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_MFM)) + if (hdd_is_valid(c) && (hdd[c].bus_type == HDD_BUS_MFM)) ini_section_set_int(cat, temp, hdd[c].mfm_channel); else ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_xta_channel", c + 1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_XTA)) + if (hdd_is_valid(c) && (hdd[c].bus_type == HDD_BUS_XTA)) ini_section_set_int(cat, temp, hdd[c].xta_channel); else ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_esdi_channel", c + 1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_ESDI)) + if (hdd_is_valid(c) && (hdd[c].bus_type == HDD_BUS_ESDI)) ini_section_set_int(cat, temp, hdd[c].esdi_channel); else ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_ide_channel", c + 1); - if (!hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE) && (hdd[c].bus != HDD_BUS_ATAPI))) + if (!hdd_is_valid(c) || ((hdd[c].bus_type != HDD_BUS_IDE) && + (hdd[c].bus_type != HDD_BUS_ATAPI))) ini_section_delete_var(cat, temp); else { sprintf(tmp2, "%01u:%01u", hdd[c].ide_channel >> 1, hdd[c].ide_channel & 1); @@ -2611,7 +2623,7 @@ save_hard_disks(void) ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_scsi_location", c + 1); - if (hdd[c].bus != HDD_BUS_SCSI) + if (hdd[c].bus_type != HDD_BUS_SCSI) ini_section_delete_var(cat, temp); else { sprintf(tmp2, "%01u:%02u", hdd[c].scsi_id >> 4, @@ -2643,8 +2655,9 @@ save_hard_disks(void) ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_speed", c + 1); - if (!hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_ESDI) && (hdd[c].bus != HDD_BUS_IDE) && - (hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_ATAPI))) + if (!hdd_is_valid(c) || + ((hdd[c].bus_type != HDD_BUS_ESDI) && (hdd[c].bus_type != HDD_BUS_IDE) && + (hdd[c].bus_type != HDD_BUS_SCSI) && (hdd[c].bus_type != HDD_BUS_ATAPI))) ini_section_delete_var(cat, temp); else ini_section_set_string(cat, temp, hdd_preset_get_internal_name(hdd[c].speed_preset)); @@ -2729,11 +2742,12 @@ save_floppy_and_cdrom_drives(void) ini_section_set_int(cat, temp, cdrom[c].speed); sprintf(temp, "cdrom_%02i_type", c + 1); - if ((cdrom[c].bus_type == 0) || (cdrom[c].bus_type == CDROM_BUS_MITSUMI)) + char *tn = cdrom_get_internal_name(cdrom_get_type(c)); + if ((cdrom[c].bus_type == 0) || (cdrom[c].bus_type == CDROM_BUS_MITSUMI) || + !strcmp(tn, "86cd")) ini_section_delete_var(cat, temp); else - ini_section_set_string(cat, temp, - cdrom_get_internal_name(cdrom_get_type(c))); + ini_section_set_string(cat, temp, tn); sprintf(temp, "cdrom_%02i_parameters", c + 1); if (cdrom[c].bus_type == 0) diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index 7228cba62..82314e6db 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -925,7 +925,7 @@ wd1007vse1_init(UNUSED(const device_t *info)) c = 0; for (uint8_t d = 0; d < HDD_NUM; d++) { - if ((hdd[d].bus == HDD_BUS_ESDI) && (hdd[d].esdi_channel < ESDI_NUM)) { + if ((hdd[d].bus_type == HDD_BUS_ESDI) && (hdd[d].esdi_channel < ESDI_NUM)) { loadhd(esdi, hdd[d].esdi_channel, d, hdd[d].fn); if (++c >= ESDI_NUM) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index c63c80721..539684b81 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1265,7 +1265,7 @@ esdi_init(UNUSED(const device_t *info)) dev->drives[0].present = dev->drives[1].present = 0; for (c = 0, i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_ESDI) && (hdd[i].esdi_channel < ESDI_NUM)) { + if ((hdd[i].bus_type == HDD_BUS_ESDI) && (hdd[i].esdi_channel < ESDI_NUM)) { /* This is an ESDI drive. */ drive = &dev->drives[hdd[i].esdi_channel]; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index a212361dc..3af561989 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -486,7 +486,7 @@ ide_get_max(const ide_t *ide, const int type) int ret; if (ide->type == IDE_ATAPI) - ret = ide->get_max(!IDE_ATAPI_IS_EARLY && ata_4, type); + ret = ide->get_max(ide, !IDE_ATAPI_IS_EARLY && ata_4, type); else ret = max[ata_4][type]; @@ -501,7 +501,7 @@ ide_get_timings(const ide_t *ide, const int type) int ret; if (ide->type == IDE_ATAPI) - ret = ide->get_timings(!IDE_ATAPI_IS_EARLY && ata_4, type); + ret = ide->get_timings(ide, !IDE_ATAPI_IS_EARLY && ata_4, type); else ret = timings[ata_4][type]; @@ -643,7 +643,7 @@ ide_identify(ide_t *ide) memset(ide->buffer, 0, 512); if (ide->type == IDE_ATAPI) - ide->identify(ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL)); + ide->identify((const ide_t *) ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL)); else if (ide->type == IDE_HDD) ide_hd_identify(ide); else { @@ -973,7 +973,7 @@ ide_atapi_attach(ide_t *ide) ide->type = IDE_ATAPI; ide_allocate_buffer(ide); ide_set_signature(ide); - ide->mdma_mode = (1 << ide->get_max(!IDE_ATAPI_IS_EARLY && + ide->mdma_mode = (1 << ide->get_max((const ide_t *) ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL), TYPE_PIO)); ide->tf->error = 1; ide->cfg_spt = ide->cfg_hpc = 0; @@ -1655,7 +1655,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->sc->callback = 200.0 * IDE_TIME; if (ide->type == IDE_HDD) { - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); uint32_t sec_count; double wait_time; if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { @@ -1697,7 +1697,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->blockcount = 0; /* Turn on the activity indicator *here* so that it gets turned on less times. */ - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); fallthrough; case WIN_WRITE: @@ -1885,7 +1885,7 @@ ide_read_data(ide_t *ide) ide_set_callback(ide, seek_us + xfer_us); } } else - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } } } @@ -2238,7 +2238,7 @@ ide_callback(void *priv) ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } break; @@ -2277,7 +2277,7 @@ ide_callback(void *priv) ide->tf->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } else { /* Bus master DMAS error, abort the command. */ ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); @@ -2346,10 +2346,10 @@ ide_callback(void *priv) ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide->tf->pos = 0; ide_next_sector(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } else { ide->tf->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } if (ret < 0) err = UNC_ERR; @@ -2391,7 +2391,7 @@ ide_callback(void *priv) err = UNC_ERR; ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } else { /* Bus master DMA error, abort the command. */ ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); @@ -2429,7 +2429,7 @@ ide_callback(void *priv) ide_next_sector(ide); } else { ide->tf->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } if (ret < 0) err = UNC_ERR; @@ -2446,7 +2446,7 @@ ide_callback(void *priv) ide->tf->pos = 0; ide->tf->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } break; @@ -2463,7 +2463,7 @@ ide_callback(void *priv) err = UNC_ERR; ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } break; @@ -2759,7 +2759,7 @@ ide_board_setup(const int board) c = 0; for (d = 0; d < HDD_NUM; d++) { - const int is_ide = (hdd[d].bus == HDD_BUS_IDE); + const int is_ide = (hdd[d].bus_type == HDD_BUS_IDE); const int ch = hdd[d].ide_channel; const int valid_ch = ((ch >= min_ch) && (ch <= max_ch)); diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 631afa931..3b8da3f2e 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -475,19 +475,22 @@ sff_reset(void *priv) #endif for (uint8_t i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_ATAPI) && (hdd[i].ide_channel < 4) && hdd[i].priv) + if ((hdd[i].bus_type == HDD_BUS_ATAPI) && (hdd[i].ide_channel < 4) && hdd[i].priv) scsi_disk_reset((scsi_common_t *) hdd[i].priv); } for (uint8_t i = 0; i < CDROM_NUM; i++) { - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv) + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && + cdrom[i].priv) scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); } for (uint8_t i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel < 4) && + zip_drives[i].priv) zip_reset((scsi_common_t *) zip_drives[i].priv); } for (uint8_t i = 0; i < MO_NUM; i++) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) && mo_drives[i].priv) + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) && + mo_drives[i].priv) mo_reset((scsi_common_t *) mo_drives[i].priv); } diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index 9e5b82336..8cc5fe20a 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -749,7 +749,7 @@ mfm_init(UNUSED(const device_t *info)) c = 0; for (uint8_t d = 0; d < HDD_NUM; d++) { - if ((hdd[d].bus == HDD_BUS_MFM) && (hdd[d].mfm_channel < MFM_NUM)) { + if ((hdd[d].bus_type == HDD_BUS_MFM) && (hdd[d].mfm_channel < MFM_NUM)) { loadhd(mfm, hdd[d].mfm_channel, d, hdd[d].fn); st506_at_log("WD1003(%d): (%s) geometry %d/%d/%d\n", c, hdd[d].fn, diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 766b28086..5d310e96b 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1799,7 +1799,7 @@ st506_init(const device_t *info) st506_xt_log("ST506: looking for disks...\n"); #endif for (c = 0, i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) { + if ((hdd[i].bus_type == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) { st506_xt_log("ST506: disk '%s' on channel %i\n", hdd[i].fn, hdd[i].mfm_channel); loadhd(dev, hdd[i].mfm_channel, i, hdd[i].fn); diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index a65ab5c69..91bdd709d 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1038,7 +1038,7 @@ xta_init(const device_t *info) /* Load any disks for this device class. */ c = 0; for (uint8_t i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < max)) { + if ((hdd[i].bus_type == HDD_BUS_XTA) && (hdd[i].xta_channel < max)) { drive = &dev->drives[hdd[i].xta_channel]; if (!hdd_image_load(i)) { diff --git a/src/disk/hdd.c b/src/disk/hdd.c index c17f64863..25257e878 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -123,7 +123,7 @@ hdd_bus_to_string(int bus, UNUSED(int cdrom)) int hdd_is_valid(int c) { - if (hdd[c].bus == HDD_BUS_DISABLED) + if (hdd[c].bus_type == HDD_BUS_DISABLED) return 0; if (strlen(hdd[c].fn) == 0) diff --git a/src/disk/mo.c b/src/disk/mo.c index 5f757c8af..7528806c7 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -9,35 +9,31 @@ * Implementation of a generic Magneto-Optical Disk drive * commands, for both ATAPI and SCSI usage. * - * - * * Authors: Natalia Portillo * Miran Grca, * Fred N. van Kempen, * - * Copyright 2020-2021 Natalia Portillo. - * Copyright 2020-2021 Miran Grca. - * Copyright 2020-2021 Fred N. van Kempen + * Copyright 2020-2025 Natalia Portillo. + * Copyright 2020-2025 Miran Grca. + * Copyright 2020-2025 Fred N. van Kempen */ -#include -#include -#include -#include +#ifdef ENABLE_MO_LOG #include -#include -#define HAVE_STDARG_H +#endif +#include +#include +#include +#include #include <86box/86box.h> #include <86box/timer.h> -#include <86box/config.h> -#include <86box/timer.h> #include <86box/device.h> +#include <86box/log.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/nvr.h> #include <86box/path.h> #include <86box/plat.h> #include <86box/ui.h> -#include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/mo.h> #include <86box/version.h> @@ -53,235 +49,50 @@ mo_drive_t mo_drives[MO_NUM]; -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +// clang-format off +/* + Table of all SCSI commands and their flags, needed for the new disc change / + not ready handler. + */ const uint8_t mo_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ - 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ - 0, 0, - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2C */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ - 0, - IMPLEMENTED | CHECK_READY | NONDATA, /* 0xAC */ - 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + [0x00] = IMPLEMENTED | CHECK_READY, + [0x01] = IMPLEMENTED | ALLOW_UA | SCSI_ONLY, + [0x03] = IMPLEMENTED | ALLOW_UA, + [0x04] = IMPLEMENTED | CHECK_READY | ALLOW_UA | SCSI_ONLY, + [0x08] = IMPLEMENTED | CHECK_READY, + [0x0a] = IMPLEMENTED | CHECK_READY, + [0x0b] = IMPLEMENTED | CHECK_READY, + [0x12] = IMPLEMENTED | ALLOW_UA, + [0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x15] = IMPLEMENTED, + [0x16] = IMPLEMENTED | SCSI_ONLY, + [0x17] = IMPLEMENTED | SCSI_ONLY, + [0x1a] = IMPLEMENTED, + [0x1b] = IMPLEMENTED | CHECK_READY, + [0x1d] = IMPLEMENTED, + [0x1e] = IMPLEMENTED | CHECK_READY, + [0x25] = IMPLEMENTED | CHECK_READY, + [0x28] = IMPLEMENTED | CHECK_READY, + [0x2a ... 0x2c] = IMPLEMENTED | CHECK_READY, + [0x2e] = IMPLEMENTED | CHECK_READY, + [0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x41] = IMPLEMENTED | CHECK_READY, + [0x55] = IMPLEMENTED, + [0x5a] = IMPLEMENTED, + [0xa8] = IMPLEMENTED | CHECK_READY, + [0xaa] = IMPLEMENTED | CHECK_READY, + [0xac] = IMPLEMENTED | CHECK_READY, + [0xae] = IMPLEMENTED | CHECK_READY, + [0xaf] = IMPLEMENTED | CHECK_READY | SCSI_ONLY }; static uint64_t mo_mode_sense_page_flags = GPMODEP_ALL_PAGES; -static const mode_sense_pages_t mo_mode_sense_pages_default = - // clang-format off -{ { - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 } -} }; -// clang-format on +static const mode_sense_pages_t mo_mode_sense_pages_default = { 0 }; -static const mode_sense_pages_t mo_mode_sense_pages_default_scsi = - // clang-format off -{ { - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 } -} }; -// clang-format on +static const mode_sense_pages_t mo_mode_sense_pages_default_scsi = { 0 }; -static const mode_sense_pages_t mo_mode_sense_pages_changeable = - // clang-format off -{ { - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 } -} }; +static const mode_sense_pages_t mo_mode_sense_pages_changeable = { 0 }; // clang-format on static void mo_command_complete(mo_t *dev); @@ -291,32 +102,22 @@ static void mo_init(mo_t *dev); int mo_do_log = ENABLE_MO_LOG; static void -mo_log(const char *fmt, ...) +mo_log(void *priv, const char *fmt, ...) { va_list ap; if (mo_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define mo_log(fmt, ...) +# define mo_log(priv, fmt, ...) #endif -int -find_mo_for_channel(uint8_t channel) -{ - for (uint8_t i = 0; i < MO_NUM; i++) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel == channel)) - return i; - } - return 0xff; -} - static int -mo_load_abort(mo_t *dev) +mo_load_abort(const mo_t *dev) { if (dev->drv->fp) fclose(dev->drv->fp); @@ -330,105 +131,125 @@ mo_load_abort(mo_t *dev) int image_is_mdi(const char *s) { - if (!strcasecmp(path_get_extension((char *) s), "MDI")) - return 1; - else - return 0; + return !strcasecmp(path_get_extension((char *) s), "MDI"); } int -mo_load(mo_t *dev, char *fn) +mo_is_empty(const uint8_t id) { - int is_mdi; - uint32_t size = 0; - unsigned int found = 0; + const mo_t *dev = (const mo_t *) mo_drives[id].priv; + int ret = 0; - if (!dev->drv) { + if ((dev->drv == NULL) || (dev->drv->fp == NULL)) + ret = 1; + + return ret; +} + +void +mo_load(const mo_t *dev, const char *fn, const int skip_insert) +{ + const int was_empty = mo_is_empty(dev->id); + int ret = 0; + + if (dev->drv == NULL) mo_eject(dev->id); - return 0; - } + else { + const int is_mdi = image_is_mdi(fn); - is_mdi = image_is_mdi(fn); + dev->drv->fp = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); + ret = 1; - dev->drv->fp = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); - if (!dev->drv->fp) { - if (!dev->drv->read_only) { - dev->drv->fp = plat_fopen(fn, "rb"); - if (dev->drv->fp) - dev->drv->read_only = 1; - else - return mo_load_abort(dev); - } else - return mo_load_abort(dev); - } + if (dev->drv->fp == NULL) { + if (!dev->drv->read_only) { + dev->drv->fp = plat_fopen(fn, "rb"); + if (dev->drv->fp == NULL) + ret = mo_load_abort(dev); + else + dev->drv->read_only = 1; + } else + ret = mo_load_abort(dev); + } - fseek(dev->drv->fp, 0, SEEK_END); - size = (uint32_t) ftell(dev->drv->fp); + if (ret) { + fseek(dev->drv->fp, 0, SEEK_END); - if (is_mdi) { - /* This is a MDI image. */ - size -= 0x1000LL; - dev->drv->base = 0x1000; - } + uint32_t size = (uint32_t) ftell(dev->drv->fp); + unsigned int found = 0; - for (uint8_t i = 0; i < KNOWN_MO_TYPES; i++) { - if (size == (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; - break; + if (is_mdi) { + /* This is a MDI image. */ + size -= 0x1000LL; + dev->drv->base = 0x1000; + } else + 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)) { + found = 1; + dev->drv->medium_size = mo_types[i].sectors; + dev->drv->sector_size = mo_types[i].bytes_per_sector; + break; + } + } + + if (found) { + if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) + log_fatal(dev->log, "mo_load(): Error seeking to the beginning of " + "the file\n"); + + strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); + + ret = 1; + } else + ret = mo_load_abort(dev); } } - if (!found) - return mo_load_abort(dev); + if (ret && !skip_insert) { + /* Signal media change to the emulated machine. */ + mo_insert((mo_t *) dev); - if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) - fatal("mo_load(): Error seeking to the beginning of the file\n"); - - strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); - - return 1; + /* The drive was previously empty, transition directly to UNIT ATTENTION. */ + if (was_empty) + mo_insert((mo_t *) dev); + } } void -mo_disk_reload(mo_t *dev) +mo_disk_reload(const mo_t *dev) { - int ret = 0; - - if (strlen(dev->drv->prev_image_path) == 0) - return; - else - ret = mo_load(dev, dev->drv->prev_image_path); - - if (ret) - dev->unit_attention = 1; + if (strlen(dev->drv->prev_image_path) != 0) + (void) mo_load(dev, dev->drv->prev_image_path, 0); } -void -mo_disk_unload(mo_t *dev) +static void +mo_disk_unload(const mo_t *dev) { - if (dev->drv && dev->drv->fp) { + if ((dev->drv != NULL) && (dev->drv->fp != NULL)) { fclose(dev->drv->fp); dev->drv->fp = NULL; } } void -mo_disk_close(mo_t *dev) +mo_disk_close(const mo_t *dev) { - if (dev->drv && dev->drv->fp) { + if ((dev->drv != NULL) && (dev->drv->fp != NULL)) { mo_disk_unload(dev); - memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); + memcpy(dev->drv->prev_image_path, dev->drv->image_path, + sizeof(dev->drv->prev_image_path)); memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); dev->drv->medium_size = 0; + + mo_insert((mo_t *) dev); } } static void -mo_set_callback(mo_t *dev) +mo_set_callback(const mo_t *dev) { if (dev->drv->bus_type != MO_BUS_SCSI) ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); @@ -437,55 +258,55 @@ mo_set_callback(mo_t *dev) static void mo_init(mo_t *dev) { - if (dev->id >= MO_NUM) - return; - - dev->requested_blocks = 1; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - dev->drv->bus_mode = 0; - if (dev->drv->bus_type >= MO_BUS_ATAPI) - dev->drv->bus_mode |= 2; - if (dev->drv->bus_type < MO_BUS_SCSI) - dev->drv->bus_mode |= 1; - mo_log("MO %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); - if (dev->drv->bus_type < MO_BUS_SCSI) { - dev->tf->phase = 1; - dev->tf->request_length = 0xEB14; + if (dev->id < MO_NUM) { + dev->requested_blocks = 1; + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= MO_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < MO_BUS_SCSI) + dev->drv->bus_mode |= 1; + mo_log(dev->log, "Bus type %i, bus mode %i\n", dev->drv->bus_type, dev->drv->bus_mode); + if (dev->drv->bus_type < MO_BUS_SCSI) { + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + } + dev->tf->status = READY_STAT | DSC_STAT; + dev->tf->pos = 0; + dev->packet_status = PHASE_NONE; + mo_sense_key = mo_asc = mo_ascq = dev->unit_attention = dev->transition = 0; + mo_info = 0x00000000; } - dev->tf->status = READY_STAT | DSC_STAT; - dev->tf->pos = 0; - dev->packet_status = PHASE_NONE; - mo_sense_key = mo_asc = mo_ascq = dev->unit_attention = 0; } static int -mo_supports_pio(mo_t *dev) +mo_supports_pio(const mo_t *dev) { return (dev->drv->bus_mode & 1); } static int -mo_supports_dma(mo_t *dev) +mo_supports_dma(const mo_t *dev) { return (dev->drv->bus_mode & 2); } /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int -mo_current_mode(mo_t *dev) +mo_current_mode(const mo_t *dev) { if (!mo_supports_pio(dev) && !mo_supports_dma(dev)) return 0; if (mo_supports_pio(dev) && !mo_supports_dma(dev)) { - mo_log("MO %i: Drive does not support DMA, setting to PIO\n", dev->id); + mo_log(dev->log, "Drive does not support DMA, setting to PIO\n"); return 1; } if (!mo_supports_pio(dev) && mo_supports_dma(dev)) return 2; if (mo_supports_pio(dev) && mo_supports_dma(dev)) { - mo_log("MO %i: Drive supports both, setting to %s\n", dev->id, - (dev->tf->features & 1) ? "DMA" : "PIO"); + mo_log(dev->log, "Drive supports both, setting to %s\n", (dev->tf->features & 1) ? + "DMA" : "PIO"); return (dev->tf->features & 1) ? 2 : 1; } @@ -495,21 +316,21 @@ mo_current_mode(mo_t *dev) static void mo_mode_sense_load(mo_t *dev) { - FILE *fp; - char fn[512]; + char fn[512] = { 0 }; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); if (mo_drives[dev->id].bus_type == MO_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default_scsi, + sizeof(mode_sense_pages_t)); else - memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default, + sizeof(mode_sense_pages_t)); - memset(fn, 0, 512); if (dev->drv->bus_type == MO_BUS_SCSI) sprintf(fn, "scsi_mo_%02i_mode_sense_bin", dev->id); else sprintf(fn, "mo_%02i_mode_sense_bin", dev->id); - fp = plat_fopen(nvr_path(fn), "rb"); + FILE *fp = plat_fopen(nvr_path(fn), "rb"); if (fp) { /* Nothing to read, not used by MO. */ fclose(fp); @@ -517,28 +338,27 @@ mo_mode_sense_load(mo_t *dev) } static void -mo_mode_sense_save(mo_t *dev) +mo_mode_sense_save(const mo_t *dev) { - FILE *fp; - char fn[512]; + char fn[512] = { 0 }; - memset(fn, 0, 512); if (dev->drv->bus_type == MO_BUS_SCSI) sprintf(fn, "scsi_mo_%02i_mode_sense_bin", dev->id); else sprintf(fn, "mo_%02i_mode_sense_bin", dev->id); - fp = plat_fopen(nvr_path(fn), "wb"); + FILE *fp = plat_fopen(nvr_path(fn), "wb"); if (fp) { /* Nothing to write, not used by MO. */ fclose(fp); } } -/*SCSI Mode Sense 6/10*/ +/* SCSI Mode Sense 6/10. */ static uint8_t -mo_mode_sense_read(mo_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +mo_mode_sense_read(const mo_t *dev, const uint8_t pgctl, + const uint8_t page, const uint8_t pos) { - switch (page_control) { + switch (pgctl) { case 0: case 3: return dev->ms_pages_saved.pages[page][pos]; @@ -558,14 +378,11 @@ mo_mode_sense_read(mo_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) } static uint32_t -mo_mode_sense(mo_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +mo_mode_sense(const mo_t *dev, uint8_t *buf, uint32_t pos, + uint8_t page, const uint8_t block_descriptor_len) { - uint64_t pf; - uint8_t page_control = (page >> 6) & 3; - - pf = mo_mode_sense_page_flags; - - uint8_t msplen; + const uint64_t pf = mo_mode_sense_page_flags; + const uint8_t pgctl = (page >> 6) & 3; page &= 0x3f; @@ -583,12 +400,12 @@ mo_mode_sense(mo_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { if (pf & (1LL << ((uint64_t) page))) { - buf[pos++] = mo_mode_sense_read(dev, page_control, i, 0); - msplen = mo_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - mo_log("MO %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + const uint8_t msplen = mo_mode_sense_read(dev, pgctl, i, 1); + buf[pos++] = mo_mode_sense_read(dev, pgctl, i, 0); + buf[pos++] = msplen; + mo_log(dev->log, "MODE SENSE: Page [%02X] length %i\n", i, msplen); for (uint8_t j = 0; j < msplen; j++) - buf[pos++] = mo_mode_sense_read(dev, page_control, i, 2 + j); + buf[pos++] = mo_mode_sense_read(dev, pgctl, i, 2 + j); } } } @@ -604,7 +421,10 @@ mo_update_request_length(mo_t *dev, int len, int block_len) dev->max_transfer_len = dev->tf->request_length; - /* For media access commands, make sure the requested DRQ length matches the block length. */ + /* + For media access commands, make sure the requested DRQ length + matches the block length. + */ switch (dev->current_cdb[0]) { case 0x08: case 0x0a: @@ -615,8 +435,10 @@ mo_update_request_length(mo_t *dev, int len, int block_len) /* Round it to the nearest 2048 bytes. */ dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ + /* + Make sure total length is not bigger than sum of the lengths of + all the requested blocks. + */ bt = (dev->requested_blocks * block_len); if (len > bt) len = bt; @@ -641,7 +463,10 @@ mo_update_request_length(mo_t *dev, int len, int block_len) /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) dev->max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + /* + If the DRQ length is smaller or equal in size to the total remaining length, + set it to that. + */ if (!dev->max_transfer_len) dev->max_transfer_len = 65534; @@ -649,8 +474,6 @@ mo_update_request_length(mo_t *dev, int len, int block_len) dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) dev->tf->request_length = dev->max_transfer_len; - - return; } static double @@ -676,23 +499,22 @@ mo_bus_speed(mo_t *dev) static void mo_command_common(mo_t *dev) { - double bytes_per_second; - double period; - dev->tf->status = BUSY_STAT; dev->tf->phase = 1; 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); - period = 1000000.0 / bytes_per_second; - dev->callback = period * (double) (dev->packet_len); + const double period = 1000000.0 / bytes_per_second; + dev->callback = period * (double) (dev->packet_len); } mo_set_callback(dev); @@ -733,16 +555,20 @@ mo_command_write_dma(mo_t *dev) mo_command_common(dev); } -/* id = Current MO device ID; +/* + dev = Pointer to current MO device; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; - direction = Transfer direction (0 = read from host, 1 = write to host). */ + direction = Transfer direction (0 = read from host, 1 = write to host). + */ static void -mo_data_command_finish(mo_t *dev, int len, int block_len, int alloc_len, int direction) +mo_data_command_finish(mo_t *dev, int len, const int block_len, + const int alloc_len, const int direction) { - mo_log("MO %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); + mo_log(dev->log, "Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->current_cdb[0], len, block_len, alloc_len, + direction, dev->tf->request_length); dev->tf->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) @@ -771,27 +597,26 @@ mo_data_command_finish(mo_t *dev, int len, int block_len, int alloc_len, int dir } } - mo_log("MO %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, - dev->tf->phase); + mo_log(dev->log, "Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->packet_status, dev->tf->request_length, dev->packet_len, + dev->tf->pos, dev->tf->phase); } static void mo_sense_clear(mo_t *dev, UNUSED(int command)) { mo_sense_key = mo_asc = mo_ascq = 0; + mo_info = 0x00000000; } static void -mo_set_phase(mo_t *dev, uint8_t phase) +mo_set_phase(const mo_t *dev, const uint8_t phase) { - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + const uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; - if (dev->drv->bus_type != MO_BUS_SCSI) - return; - - scsi_devices[scsi_bus][scsi_id].phase = phase; + if (dev->drv->bus_type == MO_BUS_SCSI) + scsi_devices[scsi_bus][scsi_id].phase = phase; } static void @@ -799,8 +624,6 @@ mo_cmd_error(mo_t *dev) { mo_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = ((mo_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; dev->tf->pos = 0; @@ -808,31 +631,30 @@ mo_cmd_error(mo_t *dev) dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); - mo_log("MO %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], mo_sense_key, mo_asc, mo_ascq); + mo_log(dev->log, "[%02X] ERROR: %02X/%02X/%02X\n", dev->current_cdb[0], mo_sense_key, + mo_asc, mo_ascq); } static void mo_unit_attention(mo_t *dev) { mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->tf->error |= MCR_ERR; - dev->tf->status = READY_STAT | ERR_STAT; - dev->tf->phase = 3; - dev->tf->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * MO_TIME; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); - mo_log("MO %i: UNIT ATTENTION\n", dev->id); + mo_log(dev->log, "UNIT ATTENTION\n"); } static void mo_buf_alloc(mo_t *dev, uint32_t len) { - mo_log("MO %i: Allocated buffer length: %i\n", dev->id, len); - if (!dev->buffer) + mo_log(dev->log, "Allocated buffer length: %i\n", len); + if (dev->buffer == NULL) dev->buffer = (uint8_t *) malloc(len); } @@ -840,7 +662,7 @@ static void mo_buf_free(mo_t *dev) { if (dev->buffer) { - mo_log("MO %i: Freeing buffer...\n", dev->id); + mo_log(dev->log, "Freeing buffer...\n"); free(dev->buffer); dev->buffer = NULL; } @@ -853,6 +675,10 @@ mo_bus_master_error(scsi_common_t *sc) mo_buf_free(dev); mo_sense_key = mo_asc = mo_ascq = 0; + mo_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); mo_cmd_error(dev); } @@ -862,6 +688,7 @@ mo_not_ready(mo_t *dev) mo_sense_key = SENSE_NOT_READY; mo_asc = ASC_MEDIUM_NOT_PRESENT; mo_ascq = 0; + mo_info = 0x00000000; mo_cmd_error(dev); } @@ -871,6 +698,10 @@ mo_write_protected(mo_t *dev) mo_sense_key = SENSE_UNIT_ATTENTION; mo_asc = ASC_WRITE_PROTECTED; mo_ascq = 0; + mo_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); mo_cmd_error(dev); } @@ -880,6 +711,10 @@ mo_write_error(mo_t *dev) mo_sense_key = SENSE_MEDIUM_ERROR; mo_asc = ASC_WRITE_ERROR; mo_ascq = 0; + mo_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); mo_cmd_error(dev); } @@ -889,24 +724,30 @@ mo_read_error(mo_t *dev) mo_sense_key = SENSE_MEDIUM_ERROR; mo_asc = ASC_UNRECOVERED_READ_ERROR; mo_ascq = 0; + mo_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); mo_cmd_error(dev); } static void -mo_invalid_lun(mo_t *dev) +mo_invalid_lun(mo_t *dev, const uint8_t lun) { mo_sense_key = SENSE_ILLEGAL_REQUEST; mo_asc = ASC_INV_LUN; mo_ascq = 0; + mo_info = lun << 24; mo_cmd_error(dev); } static void -mo_illegal_opcode(mo_t *dev) +mo_illegal_opcode(mo_t *dev, const uint8_t opcode) { mo_sense_key = SENSE_ILLEGAL_REQUEST; mo_asc = ASC_ILLEGAL_OPCODE; mo_ascq = 0; + mo_info = opcode << 24; mo_cmd_error(dev); } @@ -916,140 +757,171 @@ mo_lba_out_of_range(mo_t *dev) mo_sense_key = SENSE_ILLEGAL_REQUEST; mo_asc = ASC_LBA_OUT_OF_RANGE; mo_ascq = 0; + mo_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); mo_cmd_error(dev); } static void -mo_invalid_field(mo_t *dev) +mo_invalid_field(mo_t *dev, const uint32_t field) { mo_sense_key = SENSE_ILLEGAL_REQUEST; mo_asc = ASC_INV_FIELD_IN_CMD_PACKET; mo_ascq = 0; + mo_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); mo_cmd_error(dev); dev->tf->status = 0x53; } static void -mo_invalid_field_pl(mo_t *dev) +mo_invalid_field_pl(mo_t *dev, const uint32_t field) { mo_sense_key = SENSE_ILLEGAL_REQUEST; mo_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; mo_ascq = 0; + mo_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); mo_cmd_error(dev); dev->tf->status = 0x53; } static int -mo_blocks(mo_t *dev, int32_t *len, UNUSED(int first_batch), int out) +mo_blocks(mo_t *dev, int32_t *len, int out) { - *len = 0; + int ret = 0; - if (!dev->sector_len) { + *len = 0; + + if (!dev->sector_len) mo_command_complete(dev); - return 0; - } + else { + mo_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", + dev->requested_blocks, dev->sector_pos); - mo_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("MO %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); - mo_lba_out_of_range(dev); - return 0; - } - - *len = dev->requested_blocks * dev->drv->sector_size; - - 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 (out) - mo_write_error(dev); - else - mo_read_error(dev); - return -1; - } - - 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) { - mo_log("mo_blocks(): Error writing data\n"); - mo_write_error(dev); - return -1; - } - - fflush(dev->drv->fp); + 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); } else { - if (fread(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) { - mo_log("mo_blocks(): Error reading data\n"); - mo_read_error(dev); - return -1; + *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 (out) + mo_write_error(dev); + else + mo_read_error(dev); + + ret = -1; + } else { + 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) { + 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; + } + } + } + + if (ret == -1) + break; + + dev->sector_pos++; + } + + if (ret == 1) { + mo_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + + dev->sector_len -= dev->requested_blocks; } } } - mo_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); - - dev->sector_pos += dev->requested_blocks; - dev->sector_len -= dev->requested_blocks; - - return 1; + return ret; } void mo_insert(mo_t *dev) { - dev->unit_attention = 1; + if ((dev != NULL) && (dev->drv != NULL)) { + if (dev->drv->fp == NULL) { + dev->unit_attention = 0; + dev->transition = 0; + mo_log(dev->log, "Media removal\n"); + } else if (dev->transition) { + dev->unit_attention = 1; + /* Turn off the medium changed status. */ + dev->transition = 0; + mo_log(dev->log, "Media insert\n"); + } else { + dev->unit_attention = 0; + dev->transition = 1; + mo_log(dev->log, "Media transition\n"); + } + } } void mo_format(mo_t *dev) { - long size; int ret; int fd; - mo_log("MO %i: Formatting media...\n", dev->id); + mo_log(dev->log, "Formatting media...\n"); fseek(dev->drv->fp, 0, SEEK_END); - size = ftell(dev->drv->fp); + long size = ftell(dev->drv->fp); #ifdef _WIN32 - HANDLE fh; LARGE_INTEGER liSize; - fd = _fileno(dev->drv->fp); - fh = (HANDLE) _get_osfhandle(fd); + fd = _fileno(dev->drv->fp); + const HANDLE fh = (HANDLE) _get_osfhandle(fd); liSize.QuadPart = 0; ret = (int) SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); - if (!ret) { - mo_log("MO %i: Failed seek to start of image file\n", dev->id); - return; - } + if (ret) { + ret = (int) SetEndOfFile(fh); - ret = (int) SetEndOfFile(fh); + if (ret) { + liSize.QuadPart = size; + ret = (int) SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); - if (!ret) { - mo_log("MO %i: Failed to truncate image file to 0\n", dev->id); - return; - } + if (ret) { + ret = (int) SetEndOfFile(fh); - liSize.QuadPart = size; - ret = (int) SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); - - if (!ret) { - mo_log("MO %i: Failed seek to end of image file\n", dev->id); - return; - } - - ret = (int) SetEndOfFile(fh); - - if (!ret) { - mo_log("MO %i: Failed to truncate image file to %llu\n", dev->id, size); - return; + if (!ret) { + mo_log(dev->log, "Failed to truncate image file to %llu\n", size); + } + } else { + mo_log(dev->log, "Failed seek to end of image file\n"); + } + } else { + mo_log(dev->log, "Failed to truncate image file to 0\n"); + } + } else { + mo_log(dev->log, "Failed seek to start of image file\n"); } #else fd = fileno(dev->drv->fp); @@ -1057,15 +929,13 @@ mo_format(mo_t *dev) ret = ftruncate(fd, 0); if (ret) { - mo_log("MO %i: Failed to truncate image file to 0\n", dev->id); - return; - } + mo_log(dev->log, "Failed to truncate image file to 0\n"); + } else { + ret = ftruncate(fd, size); - ret = ftruncate(fd, size); - - if (ret) { - mo_log("MO %i: Failed to truncate image file to %llu", dev->id, size); - return; + if (ret) { + mo_log(dev->log, "Failed to truncate image file to %llu", size); + } } #endif } @@ -1080,10 +950,11 @@ mo_erase(mo_t *dev) return -1; } - mo_log("MO %i: Erasing %i blocks starting from %i...\n", dev->id, dev->sector_len, dev->sector_pos); + 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) { - mo_log("MO %i: Trying to erase beyond the end of disk\n", dev->id); + mo_log(dev->log, "Trying to erase beyond the end of disk\n"); mo_lba_out_of_range(dev); return 0; } @@ -1091,7 +962,8 @@ 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); + fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size), + SEEK_SET); for (i = 0; i < dev->requested_blocks; i++) { if (feof(dev->drv->fp)) @@ -1102,7 +974,7 @@ mo_erase(mo_t *dev) fflush(dev->drv->fp); - mo_log("MO %i: Erased %i bytes of blocks...\n", dev->id, i * dev->drv->sector_size); + mo_log(dev->log, "Erased %i bytes of blocks...\n", i * dev->drv->sector_size); dev->sector_pos += i; dev->sector_len -= i; @@ -1110,96 +982,110 @@ mo_erase(mo_t *dev) return 1; } -/*SCSI Sense Initialization*/ -void -mo_sense_code_ok(mo_t *dev) -{ - mo_sense_key = SENSE_NONE; - mo_asc = 0; - mo_ascq = 0; -} - static int -mo_pre_execution_check(mo_t *dev, uint8_t *cdb) +mo_pre_execution_check(mo_t *dev, const uint8_t *cdb) { - int ready = 0; + int ready; - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - mo_log("MO %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && + (cdb[1] & 0xe0)) { + mo_log(dev->log, "Attempting to execute a unknown command targeted at SCSI LUN %i\n", ((dev->tf->request_length >> 5) & 7)); - mo_invalid_lun(dev); + mo_invalid_lun(dev, cdb[1] >> 5); return 0; } if (!(mo_command_flags[cdb[0]] & IMPLEMENTED)) { - mo_log("MO %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == MO_BUS_SCSI) ? "SCSI" : "ATAPI"); + mo_log(dev->log, "Attempting to execute unknown command %02X over %s\n", + cdb[0], (dev->drv->bus_type == MO_BUS_SCSI) ? + "SCSI" : "ATAPI"); - mo_illegal_opcode(dev); + mo_illegal_opcode(dev, cdb[0]); return 0; } - if ((dev->drv->bus_type < MO_BUS_SCSI) && (mo_command_flags[cdb[0]] & SCSI_ONLY)) { - mo_log("MO %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - mo_illegal_opcode(dev); + if ((dev->drv->bus_type < MO_BUS_SCSI) && + (mo_command_flags[cdb[0]] & SCSI_ONLY)) { + mo_log(dev->log, "Attempting to execute SCSI-only command %02X " + "over ATAPI\n", cdb[0]); + mo_illegal_opcode(dev, cdb[0]); return 0; } - if ((dev->drv->bus_type == MO_BUS_SCSI) && (mo_command_flags[cdb[0]] & ATAPI_ONLY)) { - mo_log("MO %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - mo_illegal_opcode(dev); + if ((dev->drv->bus_type == MO_BUS_SCSI) && + (mo_command_flags[cdb[0]] & ATAPI_ONLY)) { + mo_log(dev->log, "Attempting to execute ATAPI-only command %02X " + "over SCSI\n", cdb[0]); + mo_illegal_opcode(dev, cdb[0]); return 0; } - ready = (dev->drv->fp != NULL); + if (dev->transition) { + if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE)) + ready = 0; + else { + if (!(mo_command_flags[cdb[0]] & ALLOW_UA)) { + mo_log(dev->log, "(ext_medium_changed != 0): mo_insert()\n"); + mo_insert((void *) dev); + } - /* If the drive is not ready, there is no reason to keep the + ready = (dev->drv->fp != NULL); + } + } else + ready = (dev->drv->fp != NULL); + + /* + If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - if (!ready && dev->unit_attention) + disc changes. + */ + if (!ready && (dev->unit_attention > 0)) dev->unit_attention = 0; - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ + /* + If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. + */ if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ + /* + Only increment the unit attention phase if the command can + not pass through it. + */ if (!(mo_command_flags[cdb[0]] & ALLOW_UA)) { - /* mo_log("MO %i: Unit attention now 2\n", dev->id); */ - dev->unit_attention = 2; - mo_log("MO %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + mo_log(dev->log, "Unit attention now 2\n"); + dev->unit_attention++; + mo_log(dev->log, "UNIT ATTENTION: Command %02X not allowed to " + "pass through\n", cdb[0]); mo_unit_attention(dev); return 0; } } else if (dev->unit_attention == 2) { if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* mo_log("MO %i: Unit attention now 0\n", dev->id); */ + mo_log(dev->log, "MO %i: Unit attention now 0\n"); dev->unit_attention = 0; } } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ + /* + Unless the command is REQUEST SENSE, clear the sense. This will *NOT* clear + the UNIT ATTENTION condition if it's set. + */ if (cdb[0] != GPCMD_REQUEST_SENSE) mo_sense_clear(dev, cdb[0]); - /* Next it's time for NOT READY. */ - if ((mo_command_flags[cdb[0]] & CHECK_READY) && !ready) { - mo_log("MO %i: Not ready (%02X)\n", dev->id, cdb[0]); + if (!ready && (mo_command_flags[cdb[0]] & CHECK_READY)) { + mo_log(dev->log, "Not ready (%02X)\n", cdb[0]); mo_not_ready(dev); return 0; } - mo_log("MO %i: Continuing with command %02X\n", dev->id, cdb[0]); - + mo_log(dev->log, "Continuing with command %02X\n", cdb[0]); return 1; } static void mo_seek(mo_t *dev, uint32_t pos) { -#if 0 - mo_log("MO %i: Seek %08X\n", dev->id, pos); -#endif dev->sector_pos = pos; } @@ -1220,28 +1106,30 @@ mo_reset(scsi_common_t *sc) dev->callback = 0.0; mo_set_callback(dev); dev->tf->phase = 1; - dev->tf->request_length = 0xEB14; + dev->tf->request_length = 0xeb14; dev->packet_status = PHASE_NONE; - dev->unit_attention = 0; dev->cur_lun = SCSI_LUN_USE_CDB; + mo_sense_key = mo_asc = mo_ascq = dev->unit_attention = dev->transition = 0; + mo_info = 0x00000000; } static void -mo_request_sense(mo_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) +mo_request_sense(mo_t *dev, uint8_t *buffer, const uint8_t alloc_length, const int desc) { - /*Will return 18 bytes of 0*/ + /* Will return 18 bytes of 0. */ if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, dev->sense, alloc_length); - else { + memset(buffer, 0x00, alloc_length); + if (desc) { buffer[1] = mo_sense_key; buffer[2] = mo_asc; buffer[3] = mo_ascq; - } + } else + memcpy(buffer, dev->sense, alloc_length); } - buffer[0] = desc ? 0x72 : 0x70; + buffer[0] = desc ? 0x72 : 0xf0; + if (!desc) + buffer[7] = 10; if (dev->unit_attention && (mo_sense_key == 0)) { buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; @@ -1249,25 +1137,27 @@ mo_request_sense(mo_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) buffer[desc ? 3 : 13] = 0; } - mo_log("MO %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + mo_log(dev->log, "Reporting sense: %02X %02X %02X\n", buffer[2], buffer[12], buffer[13]); if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ + /* If the last remaining sense is unit attention, clear that condition. */ dev->unit_attention = 0; } /* Clear the sense stuff as per the spec. */ mo_sense_clear(dev, GPCMD_REQUEST_SENSE); + + if (dev->transition) { + mo_log(dev->log, "MO_TRANSITION: mo_insert()\n"); + mo_insert((void *) dev); + } } static void mo_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { - mo_t *dev = (mo_t *) sc; - int ready = 0; - - ready = (dev->drv->fp != NULL); + mo_t *dev = (mo_t *) sc; + const int ready = (dev->drv->fp != NULL); if (!ready && dev->unit_attention) { /* If the drive is not ready, there is no reason to keep the @@ -1277,12 +1167,11 @@ mo_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_leng } /* Do *NOT* advance the unit attention phase. */ - mo_request_sense(dev, buffer, alloc_length, 0); } static void -mo_set_buf_len(mo_t *dev, int32_t *BufLen, int32_t *src_len) +mo_set_buf_len(const mo_t *dev, int32_t *BufLen, int32_t *src_len) { if (dev->drv->bus_type == MO_BUS_SCSI) { if (*BufLen == -1) @@ -1291,29 +1180,28 @@ mo_set_buf_len(mo_t *dev, int32_t *BufLen, int32_t *src_len) *BufLen = MIN(*src_len, *BufLen); *src_len = *BufLen; } - mo_log("MO %i: Actual transfer length: %i\n", dev->id, *BufLen); + mo_log(dev->log, "Actual transfer length: %i\n", *BufLen); } } static void -mo_command(scsi_common_t *sc, uint8_t *cdb) +mo_command(scsi_common_t *sc, const uint8_t *cdb) { - mo_t *dev = (mo_t *) sc; - int pos = 0; - int block_desc = 0; - int ret; - int32_t len; - int32_t max_len; - int32_t alloc_length; - int size_idx; - int idx = 0; - unsigned preamble_len; - char device_identify[9] = { '8', '6', 'B', '_', 'M', 'O', '0', '0', 0 }; - int32_t blen = 0; - int32_t *BufLen; - uint32_t previous_pos = 0; - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + mo_t * dev = (mo_t *) sc; + char device_identify[9] = { '8', '6', 'B', '_', 'M', 'O', '0', '0', 0 }; + uint32_t previous_pos = 0; + int32_t blen = 0; + const uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + int pos = 0; + int idx = 0; + int32_t len; + int32_t max_len; + int32_t alloc_length; + unsigned preamble_len; + int block_desc; + int size_idx; + int32_t * BufLen; if (dev->drv->bus_type == MO_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; @@ -1331,11 +1219,13 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - mo_log("MO %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], mo_sense_key, mo_asc, mo_ascq, dev->unit_attention); - mo_log("MO %i: Request length: %04X\n", dev->id, dev->tf->request_length); + mo_log(dev->log, "Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, " + "Unit attention: %i\n", + cdb[0], mo_sense_key, mo_asc, mo_ascq, dev->unit_attention); + mo_log(dev->log, "Request length: %04X\n", dev->tf->request_length); - mo_log("MO %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + mo_log(dev->log, "CDB: %02X %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X\n", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); } @@ -1344,14 +1234,17 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) mo_set_phase(dev, SCSI_PHASE_STATUS); - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + /* + This handles the Not Ready/Unit Attention check if it has to be + handled at this point. + */ if (mo_pre_execution_check(dev, cdb) == 0) return; switch (cdb[0]) { case GPCMD_SEND_DIAGNOSTIC: if (!(cdb[1] & (1 << 2))) { - mo_invalid_field(dev); + mo_invalid_field(dev, cdb[1]); return; } fallthrough; @@ -1380,8 +1273,6 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ mo_set_phase(dev, SCSI_PHASE_DATA_IN); max_len = cdb[4]; @@ -1422,158 +1313,187 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) switch (cdb[0]) { case GPCMD_READ_6: dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); if (dev->sector_len == 0) dev->sector_len = 256; - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + mo_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_READ_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + mo_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + mo_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; default: break; } - if (!dev->sector_len) { + if (dev->sector_len) { + max_len = dev->sector_len; + dev->requested_blocks = max_len; + + dev->packet_len = max_len * alloc_length; + mo_buf_alloc(dev, dev->packet_len); + + const int ret = mo_blocks(dev, &alloc_length, 0); + + if (ret > 0) { + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + mo_data_command_finish(dev, alloc_length, dev->drv->sector_size, alloc_length, 0); + + if (dev->packet_status != PHASE_COMPLETE) + ui_sb_update_icon(SB_MO | dev->id, 1); + else + ui_sb_update_icon(SB_MO | dev->id, 0); + } else { + mo_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; + dev->callback = 20.0 * MO_TIME; + mo_set_callback(dev); + mo_buf_free(dev); + } + } else { mo_set_phase(dev, SCSI_PHASE_STATUS); - /* mo_log("MO %i: All done - callback set\n", dev->id); */ + /* mo_log(dev->log, "All done - callback set\n"); */ dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * MO_TIME; mo_set_callback(dev); - break; } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - mo_buf_alloc(dev, dev->packet_len); - - ret = mo_blocks(dev, &alloc_length, 1, 0); - if (ret <= 0) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; - dev->callback = 20.0 * MO_TIME; - mo_set_callback(dev); - mo_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - mo_data_command_finish(dev, alloc_length, dev->drv->sector_size, alloc_length, 0); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_MO | dev->id, 1); - else - ui_sb_update_icon(SB_MO | dev->id, 0); - return; + break; case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: case GPCMD_VERIFY_12: - /* Data and blank verification cannot be set at the same time */ - if ((cdb[1] & 2) && (cdb[1] & 4)) { - mo_invalid_field(dev); - return; - } - if (!(cdb[1] & 2) || (cdb[1] & 4)) { + if (!(cdb[1] & 2)) { mo_set_phase(dev, SCSI_PHASE_STATUS); mo_command_complete(dev); break; } - /*TODO: Implement*/ - mo_invalid_field(dev); - return; - + fallthrough; case GPCMD_WRITE_6: case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: mo_set_phase(dev, SCSI_PHASE_DATA_OUT); - alloc_length = dev->drv->sector_size; - - if (dev->drv->read_only) { - mo_write_protected(dev); - return; - } + alloc_length = 512; switch (cdb[0]) { case GPCMD_VERIFY_6: case GPCMD_WRITE_6: dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + mo_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_10: case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + mo_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; default: break; } - if ((dev->sector_pos >= dev->drv->medium_size) /* || - ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/ - ) { + if (dev->sector_pos > (mo_types[dev->drv->type].sectors - 1)) mo_lba_out_of_range(dev); - return; + else { + if (dev->sector_len) { + max_len = dev->sector_len; + dev->requested_blocks = max_len; + + dev->packet_len = max_len * alloc_length; + mo_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; + + mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + mo_data_command_finish(dev, dev->packet_len, 512, + dev->packet_len, 1); + + ui_sb_update_icon(SB_MO | dev->id, + dev->packet_status != PHASE_COMPLETE); + } else { + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_log(dev->log, "All done - callback set\n"); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + mo_set_callback(dev); + } } + break; - if (!dev->sector_len) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - /* mo_log("MO %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * MO_TIME; - mo_set_callback(dev); - break; + case GPCMD_WRITE_SAME_10: + alloc_length = 512; + + if ((cdb[1] & 6) == 6) + mo_invalid_field(dev, cdb[1]); + else { + 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)) + mo_lba_out_of_range(dev); + else if (dev->sector_len) { + mo_buf_alloc(dev, alloc_length); + mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + dev->requested_blocks = 1; + dev->packet_len = alloc_length; + + mo_set_phase(dev, SCSI_PHASE_DATA_OUT); + + mo_data_command_finish(dev, 512, 512, + alloc_length, 1); + + ui_sb_update_icon(SB_MO | dev->id, + dev->packet_status != PHASE_COMPLETE); + } else { + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_log(dev->log, "All done - callback set\n"); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + mo_set_callback(dev); + } } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - mo_buf_alloc(dev, dev->packet_len); - - dev->requested_blocks = max_len; - dev->packet_len = max_len << 9; - - mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size, dev->packet_len, 1); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_MO | dev->id, 1); - else - ui_sb_update_icon(SB_MO | dev->id, 0); - return; + break; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: @@ -1593,7 +1513,7 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) } if (!(mo_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { - mo_invalid_field(dev); + mo_invalid_field(dev, cdb[2]); mo_buf_free(dev); return; } @@ -1602,14 +1522,16 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) alloc_length = len; if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = mo_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); + len = mo_mode_sense(dev, dev->buffer, 4, + cdb[2], block_desc); len = MIN(len, alloc_length); dev->buffer[0] = len - 1; dev->buffer[1] = 0; if (block_desc) dev->buffer[3] = 8; } else { - len = mo_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); + len = mo_mode_sense(dev, dev->buffer, 8, + cdb[2], block_desc); len = MIN(len, alloc_length); dev->buffer[0] = (len - 2) >> 8; dev->buffer[1] = (len - 2) & 255; @@ -1622,7 +1544,7 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) mo_set_buf_len(dev, BufLen, &len); - mo_log("MO %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + mo_log(dev->log, "Reading mode page: %02X...\n", cdb[2]); mo_data_command_finish(dev, len, len, alloc_length, 0); return; @@ -1682,7 +1604,7 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) preamble_len = 4; size_idx = 3; - dev->buffer[idx++] = 7; /*Optical disk*/ + dev->buffer[idx++] = 7; /* Optical disk */ dev->buffer[idx++] = cdb[2]; dev->buffer[idx++] = 0; @@ -1693,14 +1615,15 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[idx++] = 0x00; dev->buffer[idx++] = 0x80; break; - case 0x80: /*Unit serial number page*/ + case 0x80: /*Unit serial number page*/ dev->buffer[idx++] = strlen("VCM!10") + 1; - ide_padstr8(dev->buffer + idx, 20, "VCM!10"); /* Serial */ + /* Serial */ + ide_padstr8(dev->buffer + idx, 20, "VCM!10"); idx += strlen("VCM!10"); break; default: - mo_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - mo_invalid_field(dev); + mo_log(dev->log, "INQUIRY: Invalid page: %02X\n", cdb[2]); + mo_invalid_field(dev, cdb[2]); mo_buf_free(dev); return; } @@ -1710,30 +1633,34 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) memset(dev->buffer, 0, 8); if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) - dev->buffer[0] = 0x7f; /*No physical device on this LUN*/ + dev->buffer[0] = 0x7f; /* No physical device on this LUN */ else - dev->buffer[0] = 0x07; /*Optical disk*/ - dev->buffer[1] = 0x80; /*Removable*/ - dev->buffer[2] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + dev->buffer[0] = 0x07; /* Optical disk */ + dev->buffer[1] = 0x80; /* Removable */ + /* SCSI-2 compliant */ + dev->buffer[2] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x00; dev->buffer[3] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x21; -#if 0 - dev->buffer[4] = 31; -#endif dev->buffer[4] = 0; if (dev->drv->bus_type == MO_BUS_SCSI) { - dev->buffer[6] = 1; /* 16-bit transfers supported */ - dev->buffer[7] = 0x20; /* Wide bus supported */ + dev->buffer[6] = 1; /* 16-bit transfers supported */ + dev->buffer[7] = 0x20; /* Wide bus supported */ } dev->buffer[7] |= 0x02; if (dev->drv->type > 0) { - ide_padstr8(dev->buffer + 8, 8, mo_drive_types[dev->drv->type].vendor); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, mo_drive_types[dev->drv->type].model); /* Product */ - ide_padstr8(dev->buffer + 32, 4, mo_drive_types[dev->drv->type].revision); /* Revision */ + ide_padstr8(dev->buffer + 8, 8, + mo_drive_types[dev->drv->type].vendor); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, + mo_drive_types[dev->drv->type].model); /* Product */ + ide_padstr8(dev->buffer + 32, 4, + mo_drive_types[dev->drv->type].revision); /* Revision */ } else { - ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */ + ide_padstr8(dev->buffer + 8, 8, + EMU_NAME); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, + device_identify); /* Product */ + ide_padstr8(dev->buffer + 32, 4, + EMU_VERSION_EX); /* Revision */ } idx = 36; @@ -1784,7 +1711,8 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) mo_buf_alloc(dev, 8); - max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + /* IMPORTANT: What's returned is the last LBA block. */ + max_len = dev->drv->medium_size - 1; memset(dev->buffer, 0, 8); dev->buffer[0] = (max_len >> 24) & 0xff; dev->buffer[1] = (max_len >> 16) & 0xff; @@ -1801,7 +1729,7 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_ERASE_10: case GPCMD_ERASE_12: - /*Relative address*/ + /* Relative address. */ if (cdb[1] & 1) previous_pos = dev->sector_pos; @@ -1810,18 +1738,20 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) dev->sector_len = (cdb[7] << 8) | cdb[8]; break; case GPCMD_ERASE_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); break; default: break; } - /*Erase all remaining sectors*/ + /* Erase all remaining sectors. */ if (cdb[1] & 4) { - /* Cannot have a sector number when erase all*/ + /* Cannot have a sector number when erase all. */ if (dev->sector_len) { - mo_invalid_field(dev); + mo_invalid_field(dev, dev->sector_len); return; } mo_format(dev); @@ -1832,10 +1762,13 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) switch (cdb[0]) { case GPCMD_ERASE_10: - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; break; case GPCMD_ERASE_12: - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; default: @@ -1849,7 +1782,10 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) mo_command_complete(dev); break; - /*Never seen media that supports generations but it's interesting to know if any implementation calls this commmand*/ + /* + Never seen media that supports generations but it's interesting to know if any + implementation calls this commmand. + */ case GPCMD_READ_GENERATION: mo_set_phase(dev, SCSI_PHASE_DATA_IN); @@ -1866,12 +1802,13 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) break; default: - mo_illegal_opcode(dev); + mo_illegal_opcode(dev, cdb[0]); break; } #if 0 - mo_log("MO %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length); + mo_log(dev->log, "Phase: %02X, request length: %i\n", + dev->tf->phase, dev->tf->request_length); #endif if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) @@ -1891,22 +1828,16 @@ mo_command_stop(scsi_common_t *sc) static uint8_t mo_phase_data_out(scsi_common_t *sc) { - mo_t *dev = (mo_t *) sc; - - uint16_t block_desc_len; - uint16_t pos; - uint16_t param_list_len; - - uint8_t error = 0; - uint8_t page; - uint8_t page_len; - - uint8_t hdr_len; - uint8_t val; - uint8_t old_val; - uint8_t ch; - - int len = 0; + mo_t * dev = (mo_t *) sc; + const uint32_t last_sector = mo_types[dev->drv->type].sectors - 1; + int len = 0; + uint8_t error = 0; + uint32_t last_to_write; + uint16_t block_desc_len; + uint16_t pos; + uint16_t param_list_len; + uint8_t hdr_len; + uint8_t val; switch (dev->current_cdb[0]) { case GPCMD_VERIFY_6: @@ -1919,7 +1850,40 @@ mo_phase_data_out(scsi_common_t *sc) case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: if (dev->requested_blocks > 0) - mo_blocks(dev, &len, 1, 1); + mo_blocks(dev, &len, 1); + break; + case GPCMD_WRITE_SAME_10: + if (!dev->current_cdb[7] && !dev->current_cdb[8]) + last_to_write = last_sector; + else + last_to_write = dev->sector_pos + dev->sector_len - 1; + + for (int i = dev->sector_pos; i <= (int) last_to_write; i++) { + if (dev->current_cdb[1] & 2) { + dev->buffer[0] = (i >> 24) & 0xff; + dev->buffer[1] = (i >> 16) & 0xff; + dev->buffer[2] = (i >> 8) & 0xff; + dev->buffer[3] = i & 0xff; + } else if (dev->current_cdb[1] & 4) { + uint32_t s = (i % 63); + uint32_t h = ((i - s) / 63) % 16; + uint32_t c = ((i - s) / 63) / 16; + dev->buffer[0] = (c >> 16) & 0xff; + dev->buffer[1] = (c >> 8) & 0xff; + dev->buffer[2] = c & 0xff; + dev->buffer[3] = h & 0xff; + dev->buffer[4] = (s >> 24) & 0xff; + dev->buffer[5] = (s >> 16) & 0xff; + dev->buffer[6] = (s >> 8) & 0xff; + dev->buffer[7] = s & 0xff; + } + if (fseek(dev->drv->fp, (i * dev->drv->sector_size), SEEK_SET) == -1) + mo_write_error(dev); + if (feof(dev->drv->fp)) + break; + if (fwrite(dev->buffer, 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) + mo_write_error(dev); + } break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: @@ -1950,27 +1914,27 @@ mo_phase_data_out(scsi_common_t *sc) while (1) { if (pos >= param_list_len) { - mo_log("MO %i: Buffer has only block descriptor\n", dev->id); + mo_log(dev->log, "Buffer has only block descriptor\n"); break; } - page = dev->buffer[pos] & 0x3F; - page_len = dev->buffer[pos + 1]; + const uint8_t page = dev->buffer[pos] & 0x3F; + const uint8_t page_len = dev->buffer[pos + 1]; pos += 2; if (!(mo_mode_sense_page_flags & (1LL << ((uint64_t) page)))) error |= 1; - else { - for (uint8_t i = 0; i < page_len; i++) { - ch = mo_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; + else for (uint8_t i = 0; i < page_len; i++) { + const uint8_t ch = mo_mode_sense_pages_changeable.pages[page][i + 2]; + const uint8_t old_val = dev->ms_pages_saved.pages[page][i + 2]; + val = dev->buffer[pos + i]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + error |= 1; + mo_invalid_field_pl(dev, val); } } } @@ -1990,7 +1954,6 @@ mo_phase_data_out(scsi_common_t *sc) if (error) { mo_buf_free(dev); - mo_invalid_field_pl(dev); return 0; } break; @@ -2012,7 +1975,7 @@ mo_global_init(void) } static int -mo_get_max(int ide_has_dma, int type) +mo_get_max(const ide_t *ide, const int ide_has_dma, const int type) { int ret; @@ -2036,7 +1999,7 @@ mo_get_max(int ide_has_dma, int type) } static int -mo_get_timings(int ide_has_dma, int type) +mo_get_timings(const ide_t *ide, const int ide_has_dma, const int type) { int ret; @@ -2059,7 +2022,7 @@ mo_get_timings(int ide_has_dma, int type) } static void -mo_do_identify(ide_t *ide, int ide_has_dma) +mo_do_identify(const ide_t *ide, const int ide_has_dma) { char model[40]; @@ -2068,56 +2031,65 @@ mo_do_identify(ide_t *ide, int ide_has_dma) memset(model, 0, 40); if (mo_drives[mo->id].type > 0) { - snprintf(model, 40, "%s %s", mo_drive_types[mo_drives[mo->id].type].vendor, mo_drive_types[mo_drives[mo->id].type].model); - ide_padstr((char *) (ide->buffer + 23), mo_drive_types[mo_drives[mo->id].type].revision, 8); /* Firmware */ + snprintf(model, 40, "%s %s", mo_drive_types[mo_drives[mo->id].type].vendor, + mo_drive_types[mo_drives[mo->id].type].model); + /* Firmware */ + ide_padstr((char *) (ide->buffer + 23), + mo_drive_types[mo_drives[mo->id].type].revision, 8); ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ } else { snprintf(model, 40, "%s %s%02i", EMU_NAME, "86B_MO", mo->id); - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ } if (ide_has_dma) { - ide->buffer[80] = 0x70; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6*/ - ide->buffer[81] = 0x19; /*Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a*/ + /* Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6 */ + ide->buffer[80] = 0x70; + /* Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a */ + ide->buffer[81] = 0x19; } } static void -mo_identify(ide_t *ide, int ide_has_dma) +mo_identify(const ide_t *ide, const int ide_has_dma) { - ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + /* ATAPI device, direct-access device, removable media, interrupt DRQ */ + ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5); + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide->buffer[49] = 0x200; /* LBA supported */ + /* Interpret zero byte count limit as maximum length */ + ide->buffer[126] = 0xfffe; mo_do_identify(ide, ide_has_dma); } static void -mo_drive_reset(int c) +mo_drive_reset(const int c) { - mo_t *dev; - scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; + const uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; - if (!mo_drives[c].priv) { - mo_drives[c].priv = (mo_t *) malloc(sizeof(mo_t)); - memset(mo_drives[c].priv, 0, sizeof(mo_t)); + if (mo_drives[c].priv == NULL) { + mo_drives[c].priv = (mo_t *) calloc(1, sizeof(mo_t)); + mo_t *dev = (mo_t *) mo_drives[c].priv; + + char n[1024] = { 0 }; + + sprintf(n, "MO %i", c + 1); + dev->log = log_open(n); } - dev = (mo_t *) mo_drives[c].priv; + mo_t *dev = (mo_t *) mo_drives[c].priv; dev->id = c; dev->cur_lun = SCSI_LUN_USE_CDB; if (mo_drives[c].bus_type == MO_BUS_SCSI) { - if (!dev->tf) + if (dev->tf == NULL) dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); /* SCSI MO, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + scsi_device_t *sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = mo_command; @@ -2128,7 +2100,7 @@ mo_drive_reset(int c) sd->type = SCSI_REMOVABLE_DISK; } else if (mo_drives[c].bus_type == MO_BUS_ATAPI) { /* ATAPI MO, attach to the IDE bus. */ - id = ide_get_drive(mo_drives[c].ide_channel); + ide_t *id = ide_get_drive(mo_drives[c].ide_channel); /* If the IDE channel is initialized, we attach to it, otherwise, we do nothing - it's going to be a drive that's not attached to anything. */ @@ -2155,17 +2127,11 @@ mo_drive_reset(int c) void mo_hard_reset(void) { - mo_t *dev; - uint8_t scsi_id; - uint8_t scsi_bus; - for (uint8_t c = 0; c < MO_NUM; c++) { if ((mo_drives[c].bus_type == MO_BUS_ATAPI) || (mo_drives[c].bus_type == MO_BUS_SCSI)) { - mo_log("MO hard_reset drive=%d\n", c); - if (mo_drives[c].bus_type == MO_BUS_SCSI) { - scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = mo_drives[c].scsi_device_id & 0x0f; + const uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; /* Make sure to ignore any SCSI MO drive that has an out of range SCSI Bus. */ if (scsi_bus >= SCSI_BUS_MAX) @@ -2182,7 +2148,9 @@ mo_hard_reset(void) mo_drive_reset(c); - dev = (mo_t *) mo_drives[c].priv; + mo_t *dev = (mo_t *) mo_drives[c].priv; + + mo_log(dev->log, "MO hard_reset drive=%d\n", c); if (dev->tf == NULL) continue; @@ -2193,14 +2161,16 @@ mo_hard_reset(void) mo_init(dev); if (strlen(mo_drives[c].image_path)) - mo_load(dev, mo_drives[c].image_path); + mo_load(dev, mo_drives[c].image_path, 0); mo_mode_sense_load(dev); if (mo_drives[c].bus_type == MO_BUS_SCSI) - mo_log("SCSI MO drive %i attached to SCSI ID %i\n", c, mo_drives[c].scsi_device_id); + mo_log(dev->log, "SCSI MO drive %i attached to SCSI ID %i\n", + c, mo_drives[c].scsi_device_id); else if (mo_drives[c].bus_type == MO_BUS_ATAPI) - mo_log("ATAPI MO drive %i attached to IDE channel %i\n", c, mo_drives[c].ide_channel); + mo_log(dev->log, "ATAPI MO drive %i attached to IDE channel %i\n", + c, mo_drives[c].ide_channel); } } } @@ -2208,19 +2178,15 @@ mo_hard_reset(void) void mo_close(void) { - mo_t *dev; - uint8_t scsi_id; - uint8_t scsi_bus; - for (uint8_t c = 0; c < MO_NUM; c++) { if (mo_drives[c].bus_type == MO_BUS_SCSI) { - scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = mo_drives[c].scsi_device_id & 0x0f; + const uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); } - dev = (mo_t *) mo_drives[c].priv; + mo_t *dev = (mo_t *) mo_drives[c].priv; if (dev) { mo_disk_unload(dev); @@ -2228,6 +2194,13 @@ mo_close(void) if (dev->tf) free(dev->tf); + if (dev->log != NULL) { + mo_log(dev->log, "Log closed\n"); + + log_close(dev->log); + dev->log = NULL; + } + free(dev); mo_drives[c].priv = NULL; } diff --git a/src/disk/zip.c b/src/disk/zip.c index 4a5a9b968..fd261b4dd 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -9,30 +9,27 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * - * * Authors: Miran Grca, * - * Copyright 2018-2019 Miran Grca. + * Copyright 2018-2025 Miran Grca. */ -#include -#include -#include -#include +#ifdef ENABLE_ZIP_LOG #include -#include -#define HAVE_STDARG_H +#endif +#include +#include +#include +#include #include <86box/86box.h> #include <86box/timer.h> -#include <86box/config.h> -#include <86box/timer.h> #include <86box/device.h> +#include <86box/log.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/nvr.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/ui.h> -#include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/zip.h> @@ -40,402 +37,107 @@ zip_drive_t zip_drives[ZIP_NUM]; -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +// clang-format off +/* + Table of all SCSI commands and their flags, needed for the new disc change / + not ready handler. + */ const uint8_t zip_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ - 0, - IMPLEMENTED, /* 0x06 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - IMPLEMENTED, /* 0x0C */ - IMPLEMENTED | ATAPI_ONLY, /* 0x0D */ - 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ - 0, 0, - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, 0, - IMPLEMENTED | ATAPI_ONLY, /* 0x23 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - IMPLEMENTED | CHECK_READY, /* 0x41 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ - 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0xBD */ - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + [0x00] = IMPLEMENTED | CHECK_READY, + [0x01] = IMPLEMENTED | ALLOW_UA | SCSI_ONLY, + [0x03] = IMPLEMENTED | ALLOW_UA, + [0x04] = IMPLEMENTED | CHECK_READY | ALLOW_UA | SCSI_ONLY, + [0x06] = IMPLEMENTED, + [0x08] = IMPLEMENTED | CHECK_READY, + [0x0a ... 0x0b] = IMPLEMENTED | CHECK_READY, + [0x0c] = IMPLEMENTED, + [0x0d] = IMPLEMENTED | ATAPI_ONLY, + [0x12] = IMPLEMENTED | ALLOW_UA, + [0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x15] = IMPLEMENTED, + [0x16 ... 0x17] = IMPLEMENTED | SCSI_ONLY, + [0x1a] = IMPLEMENTED, + [0x1b] = IMPLEMENTED | CHECK_READY, + [0x1d] = IMPLEMENTED, + [0x1e] = IMPLEMENTED | CHECK_READY, + [0x23] = IMPLEMENTED | ATAPI_ONLY, + [0x25] = IMPLEMENTED | CHECK_READY, + [0x28] = IMPLEMENTED | CHECK_READY, + [0x2a ... 0x2b] = IMPLEMENTED | CHECK_READY, + [0x2e] = IMPLEMENTED | CHECK_READY, + [0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x41] = IMPLEMENTED | CHECK_READY, + [0x55] = IMPLEMENTED, + [0x5a] = IMPLEMENTED, + [0xa8] = IMPLEMENTED | CHECK_READY, + [0xaa] = IMPLEMENTED | CHECK_READY, + [0xae] = IMPLEMENTED | CHECK_READY, + [0xaf] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xbd] = IMPLEMENTED }; -static uint64_t zip_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); -static uint64_t zip_250_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_FLEXIBLE_DISK_PAGE | GPMODEP_CACHING_PAGE | GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); +static uint64_t zip_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | + GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); +static uint64_t zip_250_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_FLEXIBLE_DISK_PAGE | + GPMODEP_CACHING_PAGE | GPMODEP_IOMEGA_PAGE | + GPMODEP_ALL_PAGES); -static const mode_sense_pages_t zip_mode_sense_pages_default = - // clang-format off -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; -// clang-format on +static const mode_sense_pages_t zip_mode_sense_pages_default = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x50, 0x20 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2f] = { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } } +}; -static const mode_sense_pages_t zip_250_mode_sense_pages_default = - // clang-format off -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - {GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CACHING_PAGE, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; -// clang-format on +static const mode_sense_pages_t zip_250_mode_sense_pages_default = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0x00, 0x00, 0x00, 0x00 }, + [0x05] = { GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0x80, 0x00, 0x40, 0x20, 0x02, 0x00, + 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x7d, 0x00, 0x00 }, + [0x08] = { GPMODE_CACHING_PAGE, 0x0a, 0x04, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff }, + [0x2f] = { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } } +}; -static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = - // clang-format off -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; -// clang-format on +static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x50, 0x20 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2f] = { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } } +}; -static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = - // clang-format off -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - {GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CACHING_PAGE, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; -// clang-format on +static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0x00, 0x00, 0x00, 0x00 }, + [0x05] = { GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0x80, 0x00, 0x40, 0x20, 0x02, 0x00, + 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x7d, 0x00, 0x00 }, + [0x08] = { GPMODE_CACHING_PAGE, 0x0a, 0x04, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff }, + [0x2f] = { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } } +}; -static const mode_sense_pages_t zip_mode_sense_pages_changeable = - // clang-format off -{ { - { 0, 0 }, +static const mode_sense_pages_t zip_mode_sense_pages_changeable = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x5a, 0xff, 0xff, 0xff }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2f] = { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } } +}; - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xFF, 0xFF, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } -} }; -// clang-format on - -static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = - // clang-format off -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xFF, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - {GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CACHING_PAGE, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } -} }; +static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x05] = { GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }, + [0x08] = { GPMODE_CACHING_PAGE, 0x0a, 0x04, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff }, + [0x2f] = { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } } +}; // clang-format on static void zip_command_complete(zip_t *dev); @@ -445,32 +147,22 @@ static void zip_init(zip_t *dev); int zip_do_log = ENABLE_ZIP_LOG; static void -zip_log(const char *fmt, ...) +zip_log(void *priv, const char *fmt, ...) { va_list ap; if (zip_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define zip_log(fmt, ...) +# define zip_log(priv, fmt, ...) #endif -int -find_zip_for_channel(uint8_t channel) -{ - for (uint8_t i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel == channel)) - return i; - } - return 0xff; -} - static int -zip_load_abort(zip_t *dev) +zip_load_abort(const zip_t *dev) { if (dev->drv->fp) fclose(dev->drv->fp); @@ -481,104 +173,140 @@ zip_load_abort(zip_t *dev) } int -zip_load(zip_t *dev, char *fn) +image_is_zdi(const char *s) { - int size = 0; + return !strcasecmp(path_get_extension((char *) s), "ZDI"); +} - if (!dev->drv) { +int +zip_is_empty(const uint8_t id) +{ + const zip_t *dev = (const zip_t *) zip_drives[id].priv; + int ret = 0; + + if ((dev->drv == NULL) || (dev->drv->fp == NULL)) + ret = 1; + + return ret; +} + +void +zip_load(const zip_t *dev, const char *fn, const int skip_insert) +{ + const int was_empty = zip_is_empty(dev->id); + int ret = 0; + + if (dev->drv == NULL) zip_eject(dev->id); - return 0; - } + else { + const int is_zdi = image_is_zdi(fn); - dev->drv->fp = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); - if (!dev->drv->fp) { - if (!dev->drv->read_only) { - dev->drv->fp = plat_fopen(fn, "rb"); - if (dev->drv->fp) - dev->drv->read_only = 1; - else - return zip_load_abort(dev); - } else - return zip_load_abort(dev); - } + dev->drv->fp = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); + ret = 1; - fseek(dev->drv->fp, 0, SEEK_END); - size = ftell(dev->drv->fp); - - if ((size == ((ZIP_250_SECTORS << 9) + 0x1000)) || (size == ((ZIP_SECTORS << 9) + 0x1000))) { - /* This is a ZDI image. */ - size -= 0x1000; - dev->drv->base = 0x1000; - } else - dev->drv->base = 0; - - if (dev->drv->is_250) { - if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", - ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); - return zip_load_abort(dev); + if (dev->drv->fp == NULL) { + if (!dev->drv->read_only) { + dev->drv->fp = plat_fopen(fn, "rb"); + if (dev->drv->fp == NULL) + ret = zip_load_abort(dev); + else + dev->drv->read_only = 1; + } else + ret = zip_load_abort(dev); } - } else { - if (size != (ZIP_SECTORS << 9)) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", - ZIP_SECTORS << 9); - return zip_load_abort(dev); + + if (ret) { + fseek(dev->drv->fp, 0, SEEK_END); + int size = ftell(dev->drv->fp); + + if (is_zdi) { + /* This is a ZDI image. */ + size -= 0x1000; + dev->drv->base = 0x1000; + } else + dev->drv->base = 0; + + if (dev->drv->is_250) { + if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { + zip_log(dev->log, "File is incorrect size for a ZIP image\n"); + zip_log(dev->log, "Must be exactly %i or %i bytes\n", + ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); + ret = zip_load_abort(dev); + } + } else if (size != (ZIP_SECTORS << 9)) { + zip_log(dev->log, "File is incorrect size for a ZIP image\n"); + zip_log(dev->log, "Must be exactly %i bytes\n", ZIP_SECTORS << 9); + ret = zip_load_abort(dev); + } + + if (ret) + dev->drv->medium_size = size >> 9; + } + + if (ret) { + if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) + log_fatal(dev->log, "zip_load(): Error seeking to the beginning of " + "the file\n"); + + strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); + /* + After using strncpy, dev->drv->image_path needs to be explicitly null + terminated to make gcc happy. + In the event strlen(dev->drv->image_path) == sizeof(dev->drv->image_path) + (no null terminator) it is placed at the very end. Otherwise, it is placed + right after the string. + */ + const size_t term = strlen(dev->drv->image_path) == + sizeof(dev->drv->image_path) ? sizeof(dev->drv->image_path) - 1 : + strlen(dev->drv->image_path); + dev->drv->image_path[term] = '\0'; } } - dev->drv->medium_size = size >> 9; + if (ret && !skip_insert) { + /* Signal media change to the emulated machine. */ + zip_insert((zip_t *) dev); - if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) - fatal("zip_load(): Error seeking to the beginning of the file\n"); - - strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); - // After using strncpy, dev->drv->image_path needs to be explicitly null terminated to make gcc happy. - // In the event strlen(dev->drv->image_path) == sizeof(dev->drv->image_path) (no null terminator) - // it is placed at the very end. Otherwise, it is placed right after the string. - const size_t term = strlen(dev->drv->image_path) == sizeof(dev->drv->image_path) ? sizeof(dev->drv->image_path) - 1 : strlen(dev->drv->image_path); - dev->drv->image_path[term] = '\0'; - - return 1; + /* The drive was previously empty, transition directly to UNIT ATTENTION. */ + if (was_empty) + zip_insert((zip_t *) dev); + } } void -zip_disk_reload(zip_t *dev) +zip_disk_reload(const zip_t *dev) { - int ret = 0; - - if (strlen(dev->drv->prev_image_path) == 0) - return; - else - ret = zip_load(dev, dev->drv->prev_image_path); - - if (ret) - dev->unit_attention = 1; + if (strlen(dev->drv->prev_image_path) != 0) + (void) zip_load(dev, dev->drv->prev_image_path, 0); } -void -zip_disk_unload(zip_t *dev) +static void +zip_disk_unload(const zip_t *dev) { - if (dev->drv && dev->drv->fp) { + if ((dev->drv != NULL) && (dev->drv->fp != NULL)) { fclose(dev->drv->fp); dev->drv->fp = NULL; } } void -zip_disk_close(zip_t *dev) +zip_disk_close(const zip_t *dev) { - if (dev->drv && dev->drv->fp) { + if ((dev->drv != NULL) && (dev->drv->fp != NULL)) { zip_disk_unload(dev); - memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); + memcpy(dev->drv->prev_image_path, dev->drv->image_path, + sizeof(dev->drv->prev_image_path)); memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); dev->drv->medium_size = 0; + + zip_insert((zip_t *) dev); } } static void -zip_set_callback(zip_t *dev) +zip_set_callback(const zip_t *dev) { if (dev->drv->bus_type != ZIP_BUS_SCSI) ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); @@ -587,54 +315,54 @@ zip_set_callback(zip_t *dev) static void zip_init(zip_t *dev) { - if (dev->id >= ZIP_NUM) - return; - - dev->requested_blocks = 1; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - dev->drv->bus_mode = 0; - if (dev->drv->bus_type >= ZIP_BUS_ATAPI) - dev->drv->bus_mode |= 2; - if (dev->drv->bus_type < ZIP_BUS_SCSI) - dev->drv->bus_mode |= 1; - zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); - if (dev->drv->bus_type < ZIP_BUS_SCSI) { - dev->tf->phase = 1; - dev->tf->request_length = 0xEB14; + if (dev->id < ZIP_NUM) { + dev->requested_blocks = 1; + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= ZIP_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < ZIP_BUS_SCSI) + dev->drv->bus_mode |= 1; + zip_log(dev->log, "Bus type %i, bus mode %i\n", dev->drv->bus_type, dev->drv->bus_mode); + if (dev->drv->bus_type < ZIP_BUS_SCSI) { + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + } + dev->tf->status = READY_STAT | DSC_STAT; + dev->tf->pos = 0; + dev->packet_status = PHASE_NONE; + zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = dev->transition = 0; + zip_info = 0x00000000; } - dev->tf->status = READY_STAT | DSC_STAT; - dev->tf->pos = 0; - dev->packet_status = PHASE_NONE; - zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0; } static int -zip_supports_pio(zip_t *dev) +zip_supports_pio(const zip_t *dev) { return (dev->drv->bus_mode & 1); } static int -zip_supports_dma(zip_t *dev) +zip_supports_dma(const zip_t *dev) { return (dev->drv->bus_mode & 2); } /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int -zip_current_mode(zip_t *dev) +zip_current_mode(const zip_t *dev) { if (!zip_supports_pio(dev) && !zip_supports_dma(dev)) return 0; if (zip_supports_pio(dev) && !zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); + zip_log(dev->log, "Drive does not support DMA, setting to PIO\n"); return 1; } if (!zip_supports_pio(dev) && zip_supports_dma(dev)) return 2; if (zip_supports_pio(dev) && zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, + zip_log(dev->log, "Drive supports both, setting to %s\n", (dev->tf->features & 1) ? "DMA" : "PIO"); return (dev->tf->features & 1) ? 2 : 1; } @@ -645,8 +373,7 @@ zip_current_mode(zip_t *dev) static void zip_mode_sense_load(zip_t *dev) { - FILE *fp; - char fn[512]; + char fn[512] = { 0 }; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); if (dev->drv->is_250) { @@ -661,12 +388,11 @@ zip_mode_sense_load(zip_t *dev) memcpy(&dev->ms_pages_saved, &zip_mode_sense_pages_default, sizeof(mode_sense_pages_t)); } - memset(fn, 0, 512); if (dev->drv->bus_type == ZIP_BUS_SCSI) sprintf(fn, "scsi_zip_%02i_mode_sense_bin", dev->id); else sprintf(fn, "zip_%02i_mode_sense_bin", dev->id); - fp = plat_fopen(nvr_path(fn), "rb"); + FILE *fp = plat_fopen(nvr_path(fn), "rb"); if (fp) { /* Nothing to read, not used by ZIP. */ fclose(fp); @@ -674,31 +400,31 @@ zip_mode_sense_load(zip_t *dev) } static void -zip_mode_sense_save(zip_t *dev) +zip_mode_sense_save(const zip_t *dev) { - FILE *fp; - char fn[512]; + char fn[512] = { 0 }; - memset(fn, 0, 512); if (dev->drv->bus_type == ZIP_BUS_SCSI) sprintf(fn, "scsi_zip_%02i_mode_sense_bin", dev->id); else sprintf(fn, "zip_%02i_mode_sense_bin", dev->id); - fp = plat_fopen(nvr_path(fn), "wb"); + FILE *fp = plat_fopen(nvr_path(fn), "wb"); if (fp) { /* Nothing to write, not used by ZIP. */ fclose(fp); } } -/*SCSI Mode Sense 6/10*/ +/* SCSI Mode Sense 6/10. */ static uint8_t -zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +zip_mode_sense_read(const zip_t *dev, const uint8_t pgctl, + const uint8_t page, const uint8_t pos) { - switch (page_control) { + switch (pgctl) { case 0: case 3: - if (dev->drv->is_250 && (page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) + if (dev->drv->is_250 && (page == 5) && (pos == 9) && + (dev->drv->medium_size == ZIP_SECTORS)) return 0x60; return dev->ms_pages_saved.pages[page][pos]; case 1: @@ -729,18 +455,17 @@ zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) } static uint32_t -zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +zip_mode_sense(const zip_t *dev, uint8_t *buf, uint32_t pos, + uint8_t page, const uint8_t block_descriptor_len) { - uint64_t pf; - uint8_t page_control = (page >> 6) & 3; + uint64_t pf; + const uint8_t pgctl = (page >> 6) & 3; if (dev->drv->is_250) pf = zip_250_mode_sense_page_flags; else pf = zip_mode_sense_page_flags; - uint8_t msplen; - page &= 0x3f; if (block_descriptor_len) { @@ -757,12 +482,12 @@ zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t blo for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { if (pf & (1LL << ((uint64_t) page))) { - buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0); - msplen = zip_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + const uint8_t msplen = zip_mode_sense_read(dev, pgctl, i, 1); + buf[pos++] = zip_mode_sense_read(dev, pgctl, i, 0); + buf[pos++] = msplen; + zip_log(dev->log, "MODE SENSE: Page [%02X] length %i\n", i, msplen); for (uint8_t j = 0; j < msplen; j++) - buf[pos++] = zip_mode_sense_read(dev, page_control, i, 2 + j); + buf[pos++] = zip_mode_sense_read(dev, pgctl, i, 2 + j); } } } @@ -778,7 +503,10 @@ zip_update_request_length(zip_t *dev, int len, int block_len) dev->max_transfer_len = dev->tf->request_length; - /* For media access commands, make sure the requested DRQ length matches the block length. */ + /* + For media access commands, make sure the requested DRQ length matches the + block length. + */ switch (dev->current_cdb[0]) { case 0x08: case 0x0a: @@ -789,8 +517,10 @@ zip_update_request_length(zip_t *dev, int len, int block_len) /* Round it to the nearest 2048 bytes. */ dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ + /* + Make sure total length is not bigger than sum of the lengths of + all the requested blocks. + */ bt = (dev->requested_blocks * block_len); if (len > bt) len = bt; @@ -812,10 +542,16 @@ zip_update_request_length(zip_t *dev, int len, int block_len) dev->packet_len = len; break; } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + /* + If the DRQ length is odd, and the total remaining length is bigger, + make sure it's even. + */ if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) dev->max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + /* + If the DRQ length is smaller or equal in size to the total remaining length, + set it to that. + */ if (!dev->max_transfer_len) dev->max_transfer_len = 65534; @@ -850,23 +586,22 @@ zip_bus_speed(zip_t *dev) static void zip_command_common(zip_t *dev) { - double bytes_per_second; - double period; - dev->tf->status = BUSY_STAT; dev->tf->phase = 1; 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); - period = 1000000.0 / bytes_per_second; - dev->callback = period * (double) (dev->packet_len); + double period = 1000000.0 / bytes_per_second; + dev->callback = period * (double) (dev->packet_len); } zip_set_callback(dev); @@ -907,16 +642,20 @@ zip_command_write_dma(zip_t *dev) zip_command_common(dev); } -/* id = Current ZIP device ID; +/* + dev = Pointer to current ZIP device; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; - direction = Transfer direction (0 = read from host, 1 = write to host). */ + direction = Transfer direction (0 = read from host, 1 = write to host). + */ static void -zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction) +zip_data_command_finish(zip_t *dev, int len, const int block_len, + const int alloc_len, const int direction) { - zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); + zip_log(dev->log, "Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->current_cdb[0], len, block_len, alloc_len, + direction, dev->tf->request_length); dev->tf->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) @@ -945,27 +684,26 @@ zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int d } } - zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, - dev->tf->phase); + zip_log(dev->log, "Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->packet_status, dev->tf->request_length, dev->packet_len, + dev->tf->pos, dev->tf->phase); } static void zip_sense_clear(zip_t *dev, UNUSED(int command)) { zip_sense_key = zip_asc = zip_ascq = 0; + zip_info = 0x00000000; } static void -zip_set_phase(zip_t *dev, uint8_t phase) +zip_set_phase(const zip_t *dev, const uint8_t phase) { - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + const uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; - if (dev->drv->bus_type != ZIP_BUS_SCSI) - return; - - scsi_devices[scsi_bus][scsi_id].phase = phase; + if (dev->drv->bus_type == ZIP_BUS_SCSI) + scsi_devices[scsi_bus][scsi_id].phase = phase; } static void @@ -973,8 +711,6 @@ zip_cmd_error(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; dev->tf->pos = 0; @@ -982,7 +718,8 @@ zip_cmd_error(zip_t *dev) dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); ui_sb_update_icon(SB_ZIP | dev->id, 0); - zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); + zip_log(dev->log, "[%02X] ERROR: %02X/%02X/%02X\n", dev->current_cdb[0], zip_sense_key, + zip_asc, zip_ascq); } static void @@ -990,8 +727,6 @@ zip_unit_attention(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; dev->tf->pos = 0; @@ -999,22 +734,22 @@ zip_unit_attention(zip_t *dev) dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); ui_sb_update_icon(SB_ZIP | dev->id, 0); - zip_log("ZIP %i: UNIT ATTENTION\n", dev->id); + zip_log(dev->log, "UNIT ATTENTION\n", dev->id); } static void -zip_buf_alloc(zip_t *dev, uint32_t len) +zip_buf_alloc(zip_t *dev, const uint32_t len) { - zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len); - if (!dev->buffer) + zip_log(dev->log, "Allocated buffer length: %i\n", len); + if (dev->buffer == NULL) dev->buffer = (uint8_t *) malloc(len); } static void zip_buf_free(zip_t *dev) { - if (dev->buffer) { - zip_log("ZIP %i: Freeing buffer...\n", dev->id); + if (dev->buffer != NULL) { + zip_log(dev->log, "ZIP %i: Freeing buffer...\n"); free(dev->buffer); dev->buffer = NULL; } @@ -1027,6 +762,10 @@ zip_bus_master_error(scsi_common_t *sc) zip_buf_free(dev); zip_sense_key = zip_asc = zip_ascq = 0; + zip_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); zip_cmd_error(dev); } @@ -1036,6 +775,7 @@ zip_not_ready(zip_t *dev) zip_sense_key = SENSE_NOT_READY; zip_asc = ASC_MEDIUM_NOT_PRESENT; zip_ascq = 0; + zip_info = 0x00000000; zip_cmd_error(dev); } @@ -1045,6 +785,10 @@ zip_write_protected(zip_t *dev) zip_sense_key = SENSE_UNIT_ATTENTION; zip_asc = ASC_WRITE_PROTECTED; zip_ascq = 0; + zip_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); zip_cmd_error(dev); } @@ -1054,6 +798,10 @@ zip_write_error(zip_t *dev) zip_sense_key = SENSE_MEDIUM_ERROR; zip_asc = ASC_WRITE_ERROR; zip_ascq = 0; + zip_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); zip_cmd_error(dev); } @@ -1063,24 +811,30 @@ zip_read_error(zip_t *dev) zip_sense_key = SENSE_MEDIUM_ERROR; zip_asc = ASC_UNRECOVERED_READ_ERROR; zip_ascq = 0; + zip_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); zip_cmd_error(dev); } static void -zip_invalid_lun(zip_t *dev) +zip_invalid_lun(zip_t *dev, const uint8_t lun) { zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_INV_LUN; zip_ascq = 0; + zip_info = lun << 24; zip_cmd_error(dev); } static void -zip_illegal_opcode(zip_t *dev) +zip_illegal_opcode(zip_t *dev, const uint8_t opcode) { zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_ILLEGAL_OPCODE; zip_ascq = 0; + zip_info = opcode << 24; zip_cmd_error(dev); } @@ -1090,191 +844,244 @@ zip_lba_out_of_range(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_LBA_OUT_OF_RANGE; zip_ascq = 0; + zip_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); zip_cmd_error(dev); } static void -zip_invalid_field(zip_t *dev) +zip_invalid_field(zip_t *dev, const uint32_t field) { zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; zip_ascq = 0; + zip_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); zip_cmd_error(dev); dev->tf->status = 0x53; } static void -zip_invalid_field_pl(zip_t *dev) +zip_invalid_field_pl(zip_t *dev, const uint32_t field) { zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; zip_ascq = 0; + zip_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); zip_cmd_error(dev); dev->tf->status = 0x53; } static void -zip_data_phase_error(zip_t *dev) +zip_data_phase_error(zip_t *dev, const uint32_t info) { zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_DATA_PHASE_ERROR; zip_ascq = 0; + zip_info = (info >> 24) | + ((info >> 16) << 8) | + ((info >> 8) << 16) | + ( info << 24); zip_cmd_error(dev); } static int -zip_blocks(zip_t *dev, int32_t *len, UNUSED(int first_batch), int out) +zip_blocks(zip_t *dev, int32_t *len, const int out) { - *len = 0; + int ret = 1; + *len = 0; - if (!dev->sector_len) { + if (!dev->sector_len) zip_command_complete(dev); - return 0; - } + else { + zip_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", + dev->requested_blocks, dev->sector_pos); - zip_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) { - zip_log("ZIP %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); - zip_lba_out_of_range(dev); - return 0; - } - - *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 (out) - zip_write_error(dev); - else - zip_read_error(dev); - return -1; - } - - if (feof(dev->drv->fp)) - break; - - if (out) { - if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) { - zip_log("zip_blocks(): Error writing data\n"); - zip_write_error(dev); - return -1; - } - - fflush(dev->drv->fp); + if (dev->sector_pos >= dev->drv->medium_size) { + zip_log(dev->log, "Trying to %s beyond the end of disk\n", + out ? "write" : "read"); + zip_lba_out_of_range(dev); } else { - if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) { - zip_log("zip_blocks(): Error reading data\n"); - zip_read_error(dev); - return -1; + *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 (out) + zip_write_error(dev); + else + zip_read_error(dev); + ret = -1; + } else { + if (feof(dev->drv->fp)) + break; + + if (out) { + if (fwrite(dev->buffer + (i << 9), 1, + 512, dev->drv->fp) != 512) { + zip_log(dev->log, "zip_blocks(): Error writing data\n"); + zip_write_error(dev); + ret = -1; + } else + fflush(dev->drv->fp); + } else if (fread(dev->buffer + (i << 9), 1, + 512, dev->drv->fp) != 512) { + zip_log(dev->log, "zip_blocks(): Error reading data\n"); + zip_read_error(dev); + ret = -1; + } + } + + if (ret == -1) + break; + + dev->sector_pos++; + } + + if (ret == 1) { + zip_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" : + "Read", *len); + + dev->sector_len -= dev->requested_blocks; } } } - zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); - - dev->sector_pos += dev->requested_blocks; - dev->sector_len -= dev->requested_blocks; - - return 1; + return ret; } void zip_insert(zip_t *dev) { - dev->unit_attention = 1; -} - -/*SCSI Sense Initialization*/ -void -zip_sense_code_ok(zip_t *dev) -{ - zip_sense_key = SENSE_NONE; - zip_asc = 0; - zip_ascq = 0; + if ((dev != NULL) && (dev->drv != NULL)) { + if (dev->drv->fp == NULL) { + dev->unit_attention = 0; + dev->transition = 0; + zip_log(dev->log, "Media removal\n"); + } else if (dev->transition) { + dev->unit_attention = 1; + /* Turn off the medium changed status. */ + dev->transition = 0; + zip_log(dev->log, "Media insert\n"); + } else { + dev->unit_attention = 0; + dev->transition = 1; + zip_log(dev->log, "Media transition\n"); + } + } } static int -zip_pre_execution_check(zip_t *dev, uint8_t *cdb) +zip_pre_execution_check(zip_t *dev, const uint8_t *cdb) { - int ready = 0; + int ready; - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && + (cdb[1] & 0xe0)) { + zip_log(dev->log, "Attempting to execute a unknown command targeted at SCSI LUN %i\n", ((dev->tf->request_length >> 5) & 7)); - zip_invalid_lun(dev); + zip_invalid_lun(dev, cdb[1] >> 5); return 0; } if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { - zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == ZIP_BUS_SCSI) ? "SCSI" : "ATAPI"); + zip_log(dev->log, "Attempting to execute unknown command %02X over %s\n", + cdb[0], (dev->drv->bus_type == ZIP_BUS_SCSI) ? + "SCSI" : "ATAPI"); - zip_illegal_opcode(dev); + zip_illegal_opcode(dev, cdb[0]); return 0; } - if ((dev->drv->bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { - zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - zip_illegal_opcode(dev); + if ((dev->drv->bus_type < ZIP_BUS_SCSI) && + (zip_command_flags[cdb[0]] & SCSI_ONLY)) { + zip_log(dev->log, "Attempting to execute SCSI-only command %02X " + "over ATAPI\n", cdb[0]); + zip_illegal_opcode(dev, cdb[0]); return 0; } - if ((dev->drv->bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { - zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - zip_illegal_opcode(dev); + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && + (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { + zip_log(dev->log, "Attempting to execute ATAPI-only command %02X " + "over SCSI\n", cdb[0]); + zip_illegal_opcode(dev, cdb[0]); return 0; } - ready = (dev->drv->fp != NULL); + if (dev->transition) { + if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE)) + ready = 0; + else { + if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { + zip_log(dev->log, "(ext_medium_changed != 0): zip_insert()\n"); + zip_insert((void *) dev); + } - /* If the drive is not ready, there is no reason to keep the + ready = (dev->drv->fp != NULL); + } + } else + ready = (dev->drv->fp != NULL); + + /* + If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - if (!ready && dev->unit_attention) + disc changes. + */ + if (!ready && (dev->unit_attention > 0)) dev->unit_attention = 0; - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ + /* + If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. + */ if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ + /* + Only increment the unit attention phase if the command can + not pass through it. + */ if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { - /* zip_log("ZIP %i: Unit attention now 2\n", dev->id); */ - dev->unit_attention = 2; - zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + zip_log(dev->log, "Unit attention now 2\n"); + dev->unit_attention++; + zip_log(dev->log, "UNIT ATTENTION: Command %02X not allowed to pass through\n", + cdb[0]); zip_unit_attention(dev); return 0; } } else if (dev->unit_attention == 2) { if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* zip_log("ZIP %i: Unit attention now 0\n", dev->id); */ + zip_log(dev->log, "Unit attention now 0\n"); dev->unit_attention = 0; } } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ + /* + Unless the command is REQUEST SENSE, clear the sense. This will *NOT* clear + the UNIT ATTENTION condition if it's set. + */ if (cdb[0] != GPCMD_REQUEST_SENSE) zip_sense_clear(dev, cdb[0]); - /* Next it's time for NOT READY. */ - if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { - zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); + if (!ready && (zip_command_flags[cdb[0]] & CHECK_READY)) { + zip_log(dev->log, "Not ready (%02X)\n", cdb[0]); zip_not_ready(dev); return 0; } - zip_log("ZIP %i: Continuing with command %02X\n", dev->id, cdb[0]); - + zip_log(dev->log, "Continuing with command %02X\n", cdb[0]); return 1; } static void -zip_seek(zip_t *dev, uint32_t pos) +zip_seek(zip_t *dev, const uint32_t pos) { -#if 0 - zip_log("ZIP %i: Seek %08X\n", dev->id, pos); -#endif dev->sector_pos = pos; } @@ -1299,10 +1106,12 @@ zip_reset(scsi_common_t *sc) dev->packet_status = PHASE_NONE; dev->unit_attention = 0; dev->cur_lun = SCSI_LUN_USE_CDB; + zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = dev->transition = 0; + zip_info = 0x00000000; } static void -zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) +zip_request_sense(zip_t *dev, uint8_t *buffer, const uint8_t alloc_length, const int desc) { /*Will return 18 bytes of 0*/ if (alloc_length != 0) { @@ -1316,7 +1125,9 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) } } - buffer[0] = desc ? 0x72 : 0x70; + buffer[0] = desc ? 0x72 : 0xf0; + if (!desc) + buffer[7] = 10; if (dev->unit_attention && (zip_sense_key == 0)) { buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; @@ -1324,7 +1135,8 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) buffer[desc ? 3 : 13] = 0; } - zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + zip_log(dev->log, "Reporting sense: %02X %02X %02X\n", buffer[2], + buffer[12], buffer[13]); if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { /* If the last remaining sense is unit attention, clear @@ -1334,30 +1146,33 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) /* Clear the sense stuff as per the spec. */ zip_sense_clear(dev, GPCMD_REQUEST_SENSE); + + if (dev->transition) { + zip_log(dev->log, "ZIP_TRANSITION: zip_insert()\n"); + zip_insert((void *) dev); + } } static void -zip_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) +zip_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, const uint8_t alloc_length) { - zip_t *dev = (zip_t *) sc; - int ready = 0; - - ready = (dev->drv->fp != NULL); + zip_t *dev = (zip_t *) sc; + const int ready = (dev->drv->fp != NULL); if (!ready && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ + /* + If the drive is not ready, there is no reason to keep the UNIT ATTENTION + condition present, as we only use it to mark disc changes. + */ dev->unit_attention = 0; } /* Do *NOT* advance the unit attention phase. */ - zip_request_sense(dev, buffer, alloc_length, 0); } static void -zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len) +zip_set_buf_len(const zip_t *dev, int32_t *BufLen, int32_t *src_len) { if (dev->drv->bus_type == ZIP_BUS_SCSI) { if (*BufLen == -1) @@ -1366,28 +1181,27 @@ zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len) *BufLen = MIN(*src_len, *BufLen); *src_len = *BufLen; } - zip_log("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); + zip_log(dev->log, "Actual transfer length: %i\n", *BufLen); } } static void -zip_command(scsi_common_t *sc, uint8_t *cdb) +zip_command(scsi_common_t *sc, const uint8_t *cdb) { - zip_t *dev = (zip_t *) sc; - int pos = 0; - int block_desc = 0; - int ret; - int32_t len; - int32_t max_len; - int32_t alloc_length; - uint32_t i = 0; - int size_idx; - int idx = 0; - unsigned preamble_len; - int32_t blen = 0; - int32_t *BufLen; - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + zip_t *dev = (zip_t *) sc; + const uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + int pos = 0; + int idx = 0; + int32_t blen = 0; + uint32_t i; + unsigned preamble_len; + int32_t len; + int32_t max_len; + int32_t alloc_length; + int block_desc; + int size_idx; + int32_t * BufLen; if (dev->drv->bus_type == ZIP_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; @@ -1403,11 +1217,13 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); - zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->tf->request_length); + zip_log(dev->log, "Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, " + "Unit attention: %i\n", + cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); + zip_log(dev->log, "Request length: %04X\n", dev->tf->request_length); - zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + zip_log(dev->log, "CDB: %02X %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X\n", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); } @@ -1416,14 +1232,17 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_set_phase(dev, SCSI_PHASE_STATUS); - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + /* + This handles the Not Ready/Unit Attention check if it has to be handled at + this point. + */ if (zip_pre_execution_check(dev, cdb) == 0) return; switch (cdb[0]) { case GPCMD_SEND_DIAGNOSTIC: if (!(cdb[1] & (1 << 2))) { - zip_invalid_field(dev); + zip_invalid_field(dev, cdb[1]); return; } fallthrough; @@ -1435,13 +1254,12 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_FORMAT_UNIT: - if (dev->drv->read_only) { + if (dev->drv->read_only) zip_write_protected(dev); - return; + else { + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); } - - zip_set_phase(dev, SCSI_PHASE_STATUS); - zip_command_complete(dev); break; case GPCMD_IOMEGA_SENSE: @@ -1451,8 +1269,10 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_set_buf_len(dev, BufLen, &max_len); memset(dev->buffer, 0, 256); if (cdb[2] == 1) { - /* This page is related to disk health status - setting - this page to 0 makes disk health read as "marginal". */ + /* + This page is related to disk health status - setting + this page to 0 makes disk health read as "marginal". + */ dev->buffer[0] = 0x58; dev->buffer[1] = 0x00; for (i = 0x00; i < 0x58; i++) @@ -1468,7 +1288,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) for (i = 0x00; i < 0x27; i++) dev->buffer[i + 0x16] = 0x00; } else { - zip_invalid_field(dev); + zip_invalid_field(dev, cdb[2]); zip_buf_free(dev); return; } @@ -1482,9 +1302,11 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not - ready, a standalone REQUEST SENSE should forget about the not - ready, and report unit attention straight away. */ + /* + If there's a unit attention condition and there's a buffered not ready, a + standalone REQUEST SENSE should forget about the not ready, and report unit + attention straight away. + */ zip_set_phase(dev, SCSI_PHASE_DATA_IN); max_len = cdb[4]; @@ -1533,17 +1355,20 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) dev->sector_len = 256; dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + zip_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_READ_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + zip_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; @@ -1551,51 +1376,47 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) break; } - if (dev->sector_pos >= dev->drv->medium_size) { + if (dev->sector_pos >= dev->drv->medium_size) zip_lba_out_of_range(dev); - return; - } + else if (dev->sector_len) { + max_len = dev->sector_len; + dev->requested_blocks = max_len; - if (!dev->sector_len) { + 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); + + if (ret > 0) { + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + zip_data_command_finish(dev, alloc_length, 512, + alloc_length, 0); + + ui_sb_update_icon(SB_ZIP | dev->id, + dev->packet_status != PHASE_COMPLETE); + } else { + zip_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + zip_buf_free(dev); + } + } else { zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + /* zip_log(dev->log, "All done - callback set\n"); */ dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * ZIP_TIME; zip_set_callback(dev); break; } - - max_len = dev->sector_len; - /* - If we're reading all blocks in one go for DMA, why not also for - PIO, it should NOT matter anyway, this step should be identical - and only the way the read dat is transferred to the host should - be different. - */ - dev->requested_blocks = max_len; - - dev->packet_len = max_len * alloc_length; - zip_buf_alloc(dev, dev->packet_len); - - ret = zip_blocks(dev, &alloc_length, 1, 0); - if (ret <= 0) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - zip_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - - ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); - return; + break; case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: @@ -1616,7 +1437,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) if (dev->drv->read_only) { zip_write_protected(dev); - return; + break; } switch (cdb[0]) { @@ -1636,15 +1457,19 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + zip_log(dev->log, "Length: %i, LBA: %i\n", + dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; @@ -1652,86 +1477,75 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) break; } - if (dev->sector_pos >= dev->drv->medium_size) { + if (dev->sector_pos >= dev->drv->medium_size) zip_lba_out_of_range(dev); - return; - } + if (dev->sector_len) { + max_len = dev->sector_len; + dev->requested_blocks = max_len; - if (!dev->sector_len) { + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; + + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + zip_data_command_finish(dev, dev->packet_len, 512, + dev->packet_len, 1); + + ui_sb_update_icon(SB_ZIP | dev->id, + dev->packet_status != PHASE_COMPLETE); + } else { zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + /* zip_log(dev->log, "All done - callback set\n"); */ dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * ZIP_TIME; zip_set_callback(dev); - break; } - - max_len = dev->sector_len; - /* - If we're writing all blocks in one go for DMA, why not also for - PIO, it should NOT matter anyway, this step should be identical - and only the way the read dat is transferred to the host should - be different. - */ - dev->requested_blocks = max_len; - - dev->packet_len = max_len * alloc_length; - zip_buf_alloc(dev, dev->packet_len); - - dev->requested_blocks = max_len; - dev->packet_len = max_len << 9; - - zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - - ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); - return; + break; case GPCMD_WRITE_SAME_10: alloc_length = 512; - if ((cdb[1] & 6) == 6) { - zip_invalid_field(dev); - return; + if ((cdb[1] & 6) == 6) + zip_invalid_field(dev, cdb[1]); + else { + if (dev->drv->read_only) + zip_write_protected(dev); + else { + 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 >= dev->drv->medium_size) + zip_lba_out_of_range(dev); + else if (dev->sector_len) { + zip_buf_alloc(dev, alloc_length); + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + max_len = 1; + dev->requested_blocks = 1; + + dev->packet_len = alloc_length; + + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + + zip_data_command_finish(dev, 512, 512, + alloc_length, 1); + + ui_sb_update_icon(SB_ZIP | dev->id, + dev->packet_status != PHASE_COMPLETE); + } else { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log(dev->log, "All done - callback set\n"); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + } + } } - - if (dev->drv->read_only) { - zip_write_protected(dev); - return; - } - - 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 >= dev->drv->medium_size) { - zip_lba_out_of_range(dev); - return; - } - - if (!dev->sector_len) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - break; - } - - zip_buf_alloc(dev, alloc_length); - zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - max_len = 1; - dev->requested_blocks = 1; - - dev->packet_len = alloc_length; - - zip_set_phase(dev, SCSI_PHASE_DATA_OUT); - - zip_data_command_finish(dev, 512, 512, alloc_length, 1); - - ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); - return; + break; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: @@ -1750,40 +1564,41 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_buf_alloc(dev, 65536); } - if (!(zip_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { - zip_invalid_field(dev); - zip_buf_free(dev); - return; - } + if (zip_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f))) { + memset(dev->buffer, 0, len); + alloc_length = len; - memset(dev->buffer, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = zip_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0] = len - 1; - dev->buffer[1] = 0; - if (block_desc) - dev->buffer[3] = 8; - } else { - len = zip_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0] = (len - 2) >> 8; - dev->buffer[1] = (len - 2) & 255; - dev->buffer[2] = 0; - if (block_desc) { - dev->buffer[6] = 0; - dev->buffer[7] = 8; + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = zip_mode_sense(dev, dev->buffer, 4, cdb[2], + block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = len - 1; + dev->buffer[1] = 0; + if (block_desc) + dev->buffer[3] = 8; + } else { + len = zip_mode_sense(dev, dev->buffer, 8, cdb[2], + block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = (len - 2) >> 8; + dev->buffer[1] = (len - 2) & 255; + dev->buffer[2] = 0; + if (block_desc) { + dev->buffer[6] = 0; + dev->buffer[7] = 8; + } } + + zip_set_buf_len(dev, BufLen, &len); + + zip_log(dev->log, "Reading mode page: %02X...\n", cdb[2]); + + zip_data_command_finish(dev, len, len, alloc_length, 0); + } else { + zip_invalid_field(dev, cdb[2]); + zip_buf_free(dev); } - - zip_set_buf_len(dev, BufLen, &len); - - zip_log("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - - zip_data_command_finish(dev, len, len, alloc_length, 0); - return; + break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: @@ -1856,7 +1671,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) break; case 0x83: if (idx + 24 > max_len) { - zip_data_phase_error(dev); + zip_data_phase_error(dev, cdb[2]); zip_buf_free(dev); return; } @@ -1874,19 +1689,21 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[idx++] = 0x01; dev->buffer[idx++] = 0x00; dev->buffer[idx++] = 68; - ide_padstr8(dev->buffer + idx, 8, "IOMEGA "); /* Vendor */ + /* Vendor */ + ide_padstr8(dev->buffer + idx, 8, "IOMEGA "); idx += 8; + /* Product */ if (dev->drv->is_250) - ide_padstr8(dev->buffer + idx, 40, "ZIP 250 "); /* Product */ + ide_padstr8(dev->buffer + idx, 40, "ZIP 250 "); else - ide_padstr8(dev->buffer + idx, 40, "ZIP 100 "); /* Product */ + ide_padstr8(dev->buffer + idx, 40, "ZIP 100 "); idx += 40; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */ + ide_padstr8(dev->buffer + idx, 20, "53R141"); idx += 20; break; default: - zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - zip_invalid_field(dev); + zip_log(dev->log, "INQUIRY: Invalid page: %02X\n", cdb[2]); + zip_invalid_field(dev, cdb[2]); zip_buf_free(dev); return; } @@ -1896,33 +1713,39 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) memset(dev->buffer, 0, 8); if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) - dev->buffer[0] = 0x7f; /*No physical device on this LUN*/ + dev->buffer[0] = 0x7f; /* No physical device on this LUN */ else - dev->buffer[0] = 0x00; /*Hard disk*/ - dev->buffer[1] = 0x80; /*Removable*/ - dev->buffer[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + dev->buffer[0] = 0x00; /* Hard disk */ + dev->buffer[1] = 0x80; /* Removable */ + /* SCSI-2 compliant */ + dev->buffer[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; dev->buffer[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; #if 0 dev->buffer[4] = 31; #endif dev->buffer[4] = 0; if (dev->drv->bus_type == ZIP_BUS_SCSI) { - dev->buffer[6] = 1; /* 16-bit transfers supported */ - dev->buffer[7] = 0x20; /* Wide bus supported */ + dev->buffer[6] = 1; /* 16-bit transfers supported */ + dev->buffer[7] = 0x20; /* Wide bus supported */ } dev->buffer[7] |= 0x02; - ide_padstr8(dev->buffer + 8, 8, "IOMEGA "); /* Vendor */ + ide_padstr8(dev->buffer + 8, 8, "IOMEGA "); /* Vendor */ if (dev->drv->is_250) { - ide_padstr8(dev->buffer + 16, 16, "ZIP 250 "); /* Product */ - ide_padstr8(dev->buffer + 32, 4, "42.S"); /* Revision */ + /* Product */ + ide_padstr8(dev->buffer + 16, 16, "ZIP 250 "); + /* Revision */ + ide_padstr8(dev->buffer + 32, 4, "42.S"); + /* Date? */ if (max_len >= 44) - ide_padstr8(dev->buffer + 36, 8, "08/08/01"); /* Date? */ + ide_padstr8(dev->buffer + 36, 8, "08/08/01"); if (max_len >= 122) ide_padstr8(dev->buffer + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ } else { - ide_padstr8(dev->buffer + 16, 16, "ZIP 100 "); /* Product */ - ide_padstr8(dev->buffer + 32, 4, "E.08"); /* Revision */ + /* Product */ + ide_padstr8(dev->buffer + 16, 16, "ZIP 100 "); + /* Revision */ + ide_padstr8(dev->buffer + 32, 4, "E.08"); } idx = 36; @@ -1974,7 +1797,8 @@ atapi_out: zip_buf_alloc(dev, 8); - max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + /* IMPORTANT: What's returned is the last LBA block. */ + max_len = dev->drv->medium_size - 1; memset(dev->buffer, 0, 8); dev->buffer[0] = (max_len >> 24) & 0xff; dev->buffer[1] = (max_len >> 16) & 0xff; @@ -2063,12 +1887,13 @@ atapi_out: break; default: - zip_illegal_opcode(dev); + zip_illegal_opcode(dev, cdb[0]); break; } #if 0 - zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length); + zip_log(dev->log, "Phase: %02X, request length: %i\n", + dev->tf->phase, dev->tf->request_length); #endif if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) @@ -2088,29 +1913,16 @@ zip_command_stop(scsi_common_t *sc) static uint8_t zip_phase_data_out(scsi_common_t *sc) { - zip_t *dev = (zip_t *) sc; - + zip_t *dev = (zip_t *) sc; + int len = 0; + uint8_t error = 0; + uint32_t last_to_write; + uint32_t i; uint16_t block_desc_len; uint16_t pos; uint16_t param_list_len; - - uint8_t error = 0; - uint8_t page; - uint8_t page_len; - - uint32_t i = 0; - - uint8_t hdr_len; - uint8_t val; - uint8_t old_val; - uint8_t ch; - - uint32_t last_to_write = 0; - uint32_t c; - uint32_t h; - uint32_t s; - - int len = 0; + uint8_t hdr_len; + uint8_t val; switch (dev->current_cdb[0]) { case GPCMD_VERIFY_6: @@ -2123,7 +1935,7 @@ zip_phase_data_out(scsi_common_t *sc) case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: if (dev->requested_blocks > 0) - zip_blocks(dev, &len, 1, 1); + zip_blocks(dev, &len, 1); break; case GPCMD_WRITE_SAME_10: if (!dev->current_cdb[7] && !dev->current_cdb[8]) { @@ -2139,22 +1951,23 @@ zip_phase_data_out(scsi_common_t *sc) dev->buffer[3] = i & 0xff; } else if (dev->current_cdb[1] & 4) { /* CHS are 96, 1, 2048 (ZIP 100) and 239, 1, 2048 (ZIP 250) */ - s = (i % 2048); - h = ((i - s) / 2048) % 1; - c = ((i - s) / 2048) / 1; - dev->buffer[0] = (c >> 16) & 0xff; - dev->buffer[1] = (c >> 8) & 0xff; - dev->buffer[2] = c & 0xff; - dev->buffer[3] = h & 0xff; - dev->buffer[4] = (s >> 24) & 0xff; - dev->buffer[5] = (s >> 16) & 0xff; - dev->buffer[6] = (s >> 8) & 0xff; - dev->buffer[7] = s & 0xff; + const uint32_t s = (i % 2048); + const uint32_t h = ((i - s) / 2048) % 1; + const uint32_t c = ((i - s) / 2048) / 1; + dev->buffer[0] = (c >> 16) & 0xff; + dev->buffer[1] = (c >> 8) & 0xff; + dev->buffer[2] = c & 0xff; + dev->buffer[3] = h & 0xff; + dev->buffer[4] = (s >> 24) & 0xff; + dev->buffer[5] = (s >> 16) & 0xff; + dev->buffer[6] = (s >> 8) & 0xff; + dev->buffer[7] = s & 0xff; } - if (fseek(dev->drv->fp, dev->drv->base + (i << 9), SEEK_SET) == -1) - fatal("zip_phase_data_out(): Error seeking\n"); + if (fseek(dev->drv->fp, dev->drv->base + (i << 9), + SEEK_SET) == -1) + log_fatal(dev->log, "zip_phase_data_out(): Error seeking\n"); if (fwrite(dev->buffer, 1, 512, dev->drv->fp) != 512) - fatal("zip_phase_data_out(): Error writing data\n"); + log_fatal(dev->log, "zip_phase_data_out(): Error writing data\n"); } fflush(dev->drv->fp); @@ -2188,27 +2001,27 @@ zip_phase_data_out(scsi_common_t *sc) while (1) { if (pos >= param_list_len) { - zip_log("ZIP %i: Buffer has only block descriptor\n", dev->id); + zip_log(dev->log, "Buffer has only block descriptor\n"); break; } - page = dev->buffer[pos] & 0x3F; - page_len = dev->buffer[pos + 1]; + const uint8_t page = dev->buffer[pos] & 0x3f; + const uint8_t page_len = dev->buffer[pos + 1]; pos += 2; if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; + else for (i = 0; i < page_len; i++) { + const uint8_t old_val = dev->ms_pages_saved.pages[page][i + 2]; + const uint8_t ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; + val = dev->buffer[pos + i]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + error |= 1; + zip_invalid_field_pl(dev, val); } } } @@ -2228,7 +2041,6 @@ zip_phase_data_out(scsi_common_t *sc) if (error) { zip_buf_free(dev); - zip_invalid_field_pl(dev); return 0; } break; @@ -2250,7 +2062,7 @@ zip_global_init(void) } static int -zip_get_max(int ide_has_dma, int type) +zip_get_max(const ide_t *ide, const int ide_has_dma, const int type) { int ret; @@ -2274,7 +2086,7 @@ zip_get_max(int ide_has_dma, int type) } static int -zip_get_timings(int ide_has_dma, int type) +zip_get_timings(const ide_t *ide, const int ide_has_dma, const int type) { int ret; @@ -2297,39 +2109,43 @@ zip_get_timings(int ide_has_dma, int type) } static void -zip_100_identify(ide_t *ide) +zip_100_identify(const ide_t *ide) { ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ } static void -zip_250_identify(ide_t *ide, int ide_has_dma) +zip_250_identify(const ide_t *ide, const int ide_has_dma) { - ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ + /* Firmware */ + ide_padstr((char *) (ide->buffer + 23), "42.S", 8); + /* Model */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); if (ide_has_dma) { - ide->buffer[80] = 0x70; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6*/ - ide->buffer[81] = 0x19; /*Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a*/ + ide->buffer[80] = 0x70; /* Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6 */ + /* Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a */ + ide->buffer[81] = 0x19; } } static void -zip_identify(ide_t *ide, int ide_has_dma) +zip_identify(const ide_t *ide, const int ide_has_dma) { - const zip_t *zip; + const zip_t *zip = (zip_t *) ide->sc; - zip = (zip_t *) ide->sc; - - /* ATAPI device, direct-access device, removable media, interrupt DRQ: + /* + ATAPI device, direct-access device, removable media, interrupt DRQ: Using (2 << 5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive - as a LS-120. */ + as a LS-120. + */ ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5); - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide->buffer[49] = 0x200; /* LBA supported */ + /* Interpret zero byte count limit as maximum length */ + ide->buffer[126] = 0xfffe; if (zip_drives[zip->id].is_250) zip_250_identify(ide, ide_has_dma); @@ -2338,30 +2154,32 @@ zip_identify(ide_t *ide, int ide_has_dma) } static void -zip_drive_reset(int c) +zip_drive_reset(const int c) { - zip_t *dev; - scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; + const uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; - if (!zip_drives[c].priv) { - zip_drives[c].priv = (zip_t *) malloc(sizeof(zip_t)); - memset(zip_drives[c].priv, 0, sizeof(zip_t)); + if (zip_drives[c].priv == NULL) { + zip_drives[c].priv = (zip_t *) calloc(1, sizeof(zip_t)); + zip_t *dev = (zip_t *) zip_drives[c].priv; + + char n[1024] = { 0 }; + + sprintf(n, "ZIP %i", c + 1); + dev->log = log_open(n); } - dev = (zip_t *) zip_drives[c].priv; + zip_t *dev = (zip_t *) zip_drives[c].priv; dev->id = c; dev->cur_lun = SCSI_LUN_USE_CDB; if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - if (!dev->tf) + if (dev->tf == NULL) dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); /* SCSI ZIP, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + scsi_device_t *sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = zip_command; @@ -2372,7 +2190,7 @@ zip_drive_reset(int c) sd->type = SCSI_REMOVABLE_DISK; } else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { /* ATAPI CD-ROM, attach to the IDE bus. */ - id = ide_get_drive(zip_drives[c].ide_channel); + ide_t *id = ide_get_drive(zip_drives[c].ide_channel); /* If the IDE channel is initialized, we attach to it, otherwise, we do nothing - it's going to be a drive that's not attached to anything. */ @@ -2399,17 +2217,12 @@ zip_drive_reset(int c) void zip_hard_reset(void) { - zip_t *dev; - uint8_t scsi_id; - uint8_t scsi_bus; - for (uint8_t c = 0; c < ZIP_NUM; c++) { if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) || (zip_drives[c].bus_type == ZIP_BUS_SCSI)) { - zip_log("ZIP hard_reset drive=%d\n", c); if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = zip_drives[c].scsi_device_id & 0x0f; + const uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; /* Make sure to ignore any SCSI ZIP drive that has an out of range SCSI bus. */ if (scsi_bus >= SCSI_BUS_MAX) @@ -2426,7 +2239,9 @@ zip_hard_reset(void) zip_drive_reset(c); - dev = (zip_t *) zip_drives[c].priv; + zip_t *dev = (zip_t *) zip_drives[c].priv; + + zip_log(dev->log, "ZIP hard_reset drive=%d\n", c); if (dev->tf == NULL) continue; @@ -2437,14 +2252,16 @@ zip_hard_reset(void) zip_init(dev); if (strlen(zip_drives[c].image_path)) - zip_load(dev, zip_drives[c].image_path); + zip_load(dev, zip_drives[c].image_path, 0); zip_mode_sense_load(dev); if (zip_drives[c].bus_type == ZIP_BUS_SCSI) - zip_log("SCSI ZIP drive %i attached to SCSI ID %i\n", c, zip_drives[c].scsi_device_id); + zip_log(dev->log, "SCSI ZIP drive %i attached to SCSI ID %i\n", + c, zip_drives[c].scsi_device_id); else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) - zip_log("ATAPI ZIP drive %i attached to IDE channel %i\n", c, zip_drives[c].ide_channel); + zip_log(dev->log, "ATAPI ZIP drive %i attached to IDE channel %i\n", + c, zip_drives[c].ide_channel); } } } @@ -2452,19 +2269,15 @@ zip_hard_reset(void) void zip_close(void) { - zip_t *dev; - uint8_t scsi_bus; - uint8_t scsi_id; - for (uint8_t c = 0; c < ZIP_NUM; c++) { if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = zip_drives[c].scsi_device_id & 0x0f; + const uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); } - dev = (zip_t *) zip_drives[c].priv; + zip_t *dev = (zip_t *) zip_drives[c].priv; if (dev) { zip_disk_unload(dev); @@ -2472,6 +2285,13 @@ zip_close(void) if (dev->tf) free(dev->tf); + if (dev->log != NULL) { + zip_log(dev->log, "Log closed\n"); + + log_close(dev->log); + dev->log = NULL; + } + free(dev); zip_drives[c].priv = NULL; } diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index f28bba517..b9dbccb4b 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -15,26 +15,34 @@ #ifndef EMU_CDROM_H #define EMU_CDROM_H +#ifndef EMU_VERSION_H +#include <86box/version.h> +#endif + #define CDROM_NUM 8 #define CD_STATUS_EMPTY 0 #define CD_STATUS_DATA_ONLY 1 -#define CD_STATUS_PAUSED 2 -#define CD_STATUS_PLAYING 3 -#define CD_STATUS_STOPPED 4 -#define CD_STATUS_PLAYING_COMPLETED 5 +#define CD_STATUS_DVD 2 +#define CD_STATUS_PAUSED 4 +#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 /* Medium changed flag. */ #define CD_STATUS_TRANSITION 0x40 #define CD_STATUS_MEDIUM_CHANGED 0x80 -#define CD_TRACK_UNK_DATA 0x10 +#define CD_TRACK_UNK_DATA 0x04 +#define CD_TRACK_NORMAL 0x00 #define CD_TRACK_AUDIO 0x08 +#define CD_TRACK_CDI 0x10 +#define CD_TRACK_XA 0x20 +#define CD_TRACK_MODE_MASK 0x30 #define CD_TRACK_MODE2 0x04 - -#define CD_READ_DATA 0 -#define CD_READ_AUDIO 1 -#define CD_READ_RAW 2 +#define CD_TRACK_MODE2_MASK 0x07 #define CD_TOC_NORMAL 0 #define CD_TOC_SESSION 1 @@ -48,7 +56,34 @@ /* This is so that if/when this is changed to something else, changing this one define will be enough. */ -#define CDROM_EMPTY !dev->host_drive +#define CDROM_EMPTY !dev->host_drive + +#define DVD_LAYER_0_SECTORS 0x00210558ULL + +#define RAW_SECTOR_SIZE 2352 +#define COOKED_SECTOR_SIZE 2048 + +#define DATA_TRACK 0x14 +#define AUDIO_TRACK 0x10 + +#define CD_FPS 75 + +#define FRAMES_TO_MSF(f, M, S, F) \ + { \ + uint64_t value = f; \ + *(F) = (value % CD_FPS) & 0xff; \ + value /= CD_FPS; \ + *(S) = (value % 60) & 0xff; \ + value /= 60; \ + *(M) = value & 0xff; \ + } +#define MSF_TO_FRAMES(M, S, F) ((M) *60 * CD_FPS + (S) *CD_FPS + (F)) + +typedef struct SMSF { + uint16_t min; + uint8_t sec; + uint8_t fr; +} TMSF; #ifdef __cplusplus extern "C" { @@ -62,161 +97,126 @@ enum { CDROM_BUS_USB = 8 }; -enum -{ - CDROM_TYPE_86BOX_100, - CDROM_TYPE_ASUS_CDS500_141, - CDROM_TYPE_ASUS_CDS520_132, - CDROM_TYPE_AZT_CDA46802I_115, - CDROM_TYPE_BTC_BCD36XH_U10, - CDROM_TYPE_GOLDSTAR_CRD_8160B_314, - CDROM_TYPE_HITACHI_CDR_8130_0020, - CDROM_TYPE_HITACHI_GD7500_A1, - CDROM_TYPE_HLDTST_GCR8526B_101, - CDROM_TYPE_HLDTST_GSA4160_A302, - CDROM_TYPE_KENWOOD_UCR_421_208E, - CDROM_TYPE_LG_CRN8245B_130, - CDROM_TYPE_LG_CRD8322B_106, - CDROM_TYPE_LTN48125S_1S07, - CDROM_TYPE_LTN526D_YSR5, - CDROM_TYPE_MATSHITA_583_107, - CDROM_TYPE_MATSHITA_585_Z18P, - CDROM_TYPE_MATSHITA_587_7S13, - CDROM_TYPE_MATSHITA_588_LS15, - CDROM_TYPE_MATSHITA_571_10e, - CDROM_TYPE_MATSHITA_572_10j, - CDROM_TYPE_MITSUMI_FX4820T_D02A, - CDROM_TYPE_NEC_260_100, - CDROM_TYPE_NEC_260_101, - CDROM_TYPE_NEC_273_420, - CDROM_TYPE_NEC_280_105, - CDROM_TYPE_NEC_280_308, - CDROM_TYPE_NEC_CDR_1900A_100, - CDROM_TYPE_PHILIPS_PCA403CD_U31P, - CDROM_TYPE_SONY_CDU76_10i, - CDROM_TYPE_SONY_CDU311_30h, - CDROM_TYPE_SONY_CDU5225_NYS4, - CDROM_TYPE_TEAC_CD516E_10G, - CDROM_TYPE_TEAC_CD524EA_30D, - CDROM_TYPE_TEAC_CD532E_20A, - CDROM_TYPE_TOSHIBA_5302TA_0305, - CDROM_TYPE_TOSHIBA_5702B_TA70, - CDROM_TYPE_TOSHIBA_6202B_1512, - CDROM_TYPE_TOSHIBA_6402B_1008, - CDROM_TYPE_TOSHIBA_6702B_1007, - CDROM_TYPE_TOSHIBA_M1802_1051, - CDROM_TYPE_CHINON_CDS431_H42, - CDROM_TYPE_CHINON_CDX435_M62, - CDROM_TYPE_DEC_RRD45_0436, - CDROM_TYPE_MATSHITA_501_10b, - CDROM_TYPE_NEC_25_10a, - CDROM_TYPE_NEC_38_103, - CDROM_TYPE_NEC_75_103, - CDROM_TYPE_NEC_77_106, - CDROM_TYPE_NEC_211_100, - CDROM_TYPE_NEC_464_105, - CDROM_TYPE_ShinaKen_DM3x1S_104, - CDROM_TYPE_SONY_CDU541_10i, - CDROM_TYPE_SONY_CDU561_18k, - CDROM_TYPE_SONY_CDU76S_100, - CDROM_TYPE_PHILIPS_CDD2600_107, - CDROM_TYPE_PIONEER_DRM604X_2403, - CDROM_TYPE_PLEXTOR_PX32TS_103, - CDROM_TYPE_TEAC_CD50_100, - CDROM_TYPE_TEAC_R55S_10R, - CDROM_TYPE_TEXEL_DM3024_100, - CDROM_TYPE_TEXEL_DM3028_106, - CDROM_TYPE_TOSHIBA_XM_3433, - CDROM_TYPE_TOSHIBA_XM3201B_3232, - CDROM_TYPE_TOSHIBA_XM3301TA_0272, - CDROM_TYPE_TOSHIBA_XM5701TA_3136, - CDROM_TYPE_TOSHIBA_SDM1401_1008, - CDROM_TYPES_NUM -}; - -#define KNOWN_CDROM_DRIVE_TYPES CDROM_TYPES_NUM #define BUS_TYPE_IDE CDROM_BUS_ATAPI #define BUS_TYPE_SCSI CDROM_BUS_SCSI #define BUS_TYPE_BOTH -2 #define BUS_TYPE_NONE -1 +#define CDV EMU_VERSION_EX + static const struct { - const char vendor[9]; - const char model[17]; - const char revision[5]; - const char *name; - const char *internal_name; - const int bus_type; + const char vendor[9]; + const char model[17]; + const char revision[5]; + const char * internal_name; + const int bus_type; + /* SCSI standard for SCSI (or both) devices, early for IDE. */ + const int scsi_std; + const int speed; + const int inquiry_len; + const int caddy; + const int transfer_max[4]; } cdrom_drive_types[] = { - { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, - { "ASUS", "CD-S500/A", "1.41", "ASUS CD-S500/A 1.41", "ASUS_CD-S500A_1.41", BUS_TYPE_IDE }, - { "ASUS", "CD-S520/A4", "1.32", "ASUS CD-S520/A4 1.32", "ASUS_CD-S520A4_1.32", BUS_TYPE_IDE }, - { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, - { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, - { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, - { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, - { "HITACHI", "GD-7500", "A1 ", "HITACHI GD-7500 A1", "HITACHI_GD-7500_A1", BUS_TYPE_IDE }, - { "HL-DT-ST", "CD-ROM GCR-8526B", "1.01", "HL-DT-ST CD-ROM GCR-8526B 1.01", "HL-DT-ST_CD-ROM_GCR-8526B_1.01", BUS_TYPE_IDE }, - { "HL-DT-ST", "DVDRAM GSA-4160", "A302", "HL-DT-ST DVDRAM GSA-4160 A302", "HL-DT-ST_DVDRAM_GSA-4160_A302", BUS_TYPE_IDE }, - { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, - { "LG", "CD-ROM CRN-8245B", "1.30", "LG CD-ROM CRN-8245B 1.30", "LG_CD-ROM_CRN-8245B_1.30", BUS_TYPE_IDE }, - { "LG", "CD-ROM CRD-8322B", "1.06", "LG CD-ROM CRD-8322B 1.06", "LG_CD-ROM_CRD-8322B_1.06", BUS_TYPE_IDE }, - { "LITE-ON", "LTN48125S", "1S07", "LITE-ON LTN48125S 1S07", "LITE-ON_LTN48125S_1S07", BUS_TYPE_IDE }, - { "LITE-ON", "LTN526D", "YSR5", "LITE-ON LTN526D YSR5", "LITE-ON_LTN526D_YSR5", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-583", "1.07", "MATSHITA CD-ROM CR-583 1.07", "MATSHITA_CD-ROM_CR-583_1.07", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-585", "Z18P", "MATSHITA CD-ROM CR-585 Z18P", "MATSHITA_CD-ROM_CR-585_Z18P", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, - { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, - { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, - { "MATSHITA", "CR-572", "1.0j", "MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE }, - { "MITSUMI", "CRMC-FX4820T", "D02A", "MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:260", "1.00", "NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:260", "1.01", "NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, - { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, - { "NEC", "CDR-1900A", "1.00", "NEC CDR-1900A 1.00", "NEC_CDR-1900A_1.00", BUS_TYPE_IDE }, - { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, - { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, - { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, - { "SONY", "CD-ROM CDU5225", "NYS4", "SONY CD-ROM CDU5225 NYS4", "SONY_CD-ROM_CDU5225_NYS4", BUS_TYPE_IDE }, - { "TEAC", "CD-516E", "1.0G", "TEAC CD-516E 1.0G", "TEAC_CD-516E_1.0G", BUS_TYPE_IDE }, - { "TEAC", "CD-524EA", "3.0D", "TEAC CD-524EA 3.0D", "TEAC_CD-524EA_3.0D", BUS_TYPE_IDE }, - { "TEAC", "CD-532E", "2.0A", "TEAC CD-532E 2.0A", "TEAC_CD_532E_2.0A", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6202B", "1512", "TOSHIBA CD-ROM XM-6202B 1512", "TOSHIBA_CD-ROM_XM-6202B_1512", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6402B", "1008", "TOSHIBA CD-ROM XM-6402B 1008", "TOSHIBA_CD-ROM_XM-6402B_1008", BUS_TYPE_IDE }, - { "TOSHIBA", "CD-ROM XM-6702B", "1007", "TOSHIBA CD-ROM XM-6702B 1007", "TOSHIBA_CD-ROM_XM-6702B_1007", BUS_TYPE_IDE }, - { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "TOSHIBA DVD-ROM SD-M1802 1051", "TOSHIBA_DVD-ROM_SD-M1802_1051", BUS_TYPE_IDE }, - { "CHINON", "CD-ROM CDS-431", "H42 ", "[SCSI-1] CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, - { "CHINON", "CD-ROM CDX-435", "M62 ", "[SCSI-1] CHINON CD-ROM CDX-435 M62", "CHINON_CD-ROM_CDX-435_M62", BUS_TYPE_SCSI }, - { "DEC", "RRD45 (C) DEC", "0436", "[SCSI-1] DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, - { "MATSHITA", "CD-ROM CR-501", "1.0b", "[SCSI-1] MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI }, - { "NEC", "CD-ROM DRIVE:25", "1.0a", "[SCSI-1] NEC CD-ROM DRIVE:25 1.0a", "NEC_CD-ROM_DRIVE25_1.0a", BUS_TYPE_SCSI }, - { "NEC", "CD-ROM DRIVE:38", "1.00", "[SCSI-2] NEC CD-ROM DRIVE:38 1.00", "NEC_CD-ROM_DRIVE38_1.00", BUS_TYPE_SCSI }, - { "NEC", "CD-ROM DRIVE:75", "1.03", "[SCSI-1] NEC CD-ROM DRIVE:75 1.03", "NEC_CD-ROM_DRIVE75_1.03", BUS_TYPE_SCSI }, - { "NEC", "CD-ROM DRIVE:77", "1.06", "[SCSI-1] NEC CD-ROM DRIVE:77 1.06", "NEC_CD-ROM_DRIVE77_1.06", BUS_TYPE_SCSI }, - { "NEC", "CD-ROM DRIVE:211", "1.00", "[SCSI-2] NEC CD-ROM DRIVE:211 1.00", "NEC_CD-ROM_DRIVE211_1.00", BUS_TYPE_SCSI }, - { "NEC", "CD-ROM DRIVE:464", "1.05", "[SCSI-2] NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI }, - { "ShinaKen", "CD-ROM DM-3x1S", "1.04", "[SCSI-1] ShinaKen CD-ROM DM-3x1S 1.04", "ShinaKen_CD-ROM_DM-3x1S_1.04", BUS_TYPE_SCSI }, - { "SONY", "CD-ROM CDU-541", "1.0i", "[SCSI-1] SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI }, - { "SONY", "CD-ROM CDU-561", "1.8k", "[SCSI-2] SONY CD-ROM CDU-561 1.8k", "SONY_CD-ROM_CDU-561_1.8k", BUS_TYPE_SCSI }, - { "SONY", "CD-ROM CDU-76S", "1.00", "[SCSI-2] SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI }, - { "PHILIPS", "CDD2600", "1.07", "[SCSI-2] PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI }, - { "PIONEER", "CD-ROM DRM-604X", "2403", "[SCSI-2] PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI }, - { "PLEXTOR", "CD-ROM PX-32TS", "1.03", "[SCSI-2] PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI }, - { "TEAC", "CD 50", "1.00", "[SCSI-2] TEAC CD 50 1.00", "TEAC_CD_50_1.00", BUS_TYPE_SCSI }, - { "TEAC", "CD-ROM R55S", "1.0R", "[SCSI-2] TEAC CD-ROM R55S 1.0R", "TEAC_CD-ROM_R55S_1.0R", BUS_TYPE_SCSI }, - { "TEXEL", "CD-ROM DM-3024", "1.00", "[SCSI-1] TEXEL CD-ROM DM-3024 1.00", "TEXEL_CD-ROM_DM-3024_1.00", BUS_TYPE_SCSI }, - { "TEXEL", "CD-ROM DM-3028", "1.06", "[SCSI-2] TEXEL CD-ROM DM-3028 1.06", "TEXEL_CD-ROM_DM-3028_1.06", BUS_TYPE_SCSI }, - { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "[SCSI-2] TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI }, - { "TOSHIBA", "CD-ROM XM-3201B", "3232", "[SCSI-1] TOSHIBA CD-ROM XM-3201B 3232", "TOSHIBA_CD-ROM_XM-3201B_3232", BUS_TYPE_SCSI }, - { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "[SCSI-2] TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI }, - { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "[SCSI-2] TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI }, - { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "[SCSI-2] TOSHIBA DVD-ROM SD-M1401 1008", "TOSHIBA_DVD-ROM_SD-M1401_1008", BUS_TYPE_SCSI }, - { "", "", "", "", "", BUS_TYPE_NONE }, + { EMU_NAME, "86B_CD", CDV, "86cd", BUS_TYPE_BOTH, 2, -1, 36, 0, { 4, 2, 2, 5 } }, + /* SCSI-1 / early ATAPI generic - second on purpose so the later variant is the default. */ + { EMU_NAME, "86B_CD", "1.00", "86cd100", BUS_TYPE_BOTH, 1, -1, 36, 1, { 0, -1, -1, -1 } }, + /* No difference from 86BOX CD-ROM, other than name - but enough people have requested such a name to warrant it. */ + { EMU_NAME, "86B_DVD", "4.30", "86dvd", BUS_TYPE_BOTH, 2, -1, 36, 0, { 4, 2, 2, 5 } }, + { "ASUS", "CD-S500/A", "1.41", "asus_500", BUS_TYPE_IDE, 0, 50, 36, 0, { 4, 2, 2, 2 } }, + { "ASUS", "CD-S520/A4", "1.32", "asus_520", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 2 } }, + { "AZT", "CDA46802I", "1.15", "azt_cda", BUS_TYPE_IDE, 0, 4, 36, 0, { 3, 0, 0, 0 } }, + { "BTC", "CD-ROM BCD36XH", "U1.0", "btc_36xh", BUS_TYPE_IDE, 0, 36, 36, 0, { 4, 2, 2, -1 } }, + { "GOLDSTAR", "CRD-8160B", "3.14", "goldstar", BUS_TYPE_IDE, 0, 16, 36, 0, { 4, 2, 2, -1 } }, + /* TODO: Find an IDENTIFY and/or INQUIRY dump. */ + { "GOLDSTAR", "GCD-R560B", "1.00", "goldstar", BUS_TYPE_IDE, 0, 6, 36, 0, { 4, 2, 2, -1 } }, + { "HITACHI", "CDR-8130", "0020", "hitachi_r8130", BUS_TYPE_IDE, 0, 16, 36, 0, { 4, 2, 2, -1 } }, + { "HITACHI", "GD-7500", "A1 ", "hitachi_7500", BUS_TYPE_IDE, 0, 40, 36, 0, { 4, 2, 2, 2 } }, /* DVD. */ + { "HL-DT-ST", "CD-ROM GCR-8526B", "1.01", "hldtst_8526b", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 2 } }, + { "HL-DT-ST", "DVDRAM GSA-4160", "A302", "hldtst_4160", BUS_TYPE_IDE, 0, 40, 36, 0, { 4, 2, 2, 2 } }, + { "KENWOOD", "CD-ROM UCR-421", "208E", "kenwood_421", BUS_TYPE_IDE, 0, 72, 36, 0, { 4, 2, 2, 4 } }, + /* + This is a laptop/notebook drive, as is also evident from the name: + CRN = Notebook, CRD = Desktop. + */ + { "LG", "CD-ROM CRN-8245B", "1.30", "lg_8245b", BUS_TYPE_IDE, 0, 24, 36, 0, { 4, 2, 2, -1 } }, + { "LG", "CD-ROM CRD-8322B", "1.06", "lg_8322b", BUS_TYPE_IDE, 0, 32, 36, 0, { 4, 2, 2, -1 } }, + /* Nothing on Google, deduced 48x from the name. */ + { "LITE-ON", "LTN48125S", "1S07", "liteon_48125s", BUS_TYPE_IDE, 0, 48, 36, 0, { 4, 2, 2, 2 } }, + /* Confirmed to be 52x, was the basis for deducing the other one's speed. */ + { "LITE-ON", "LTN526D", "YSR5", "liteon_526d", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 2 } }, + { "MATSHITA", "CD-ROM CR-583", "1.07", "matshita_583", BUS_TYPE_IDE, 0, 8, 36, 0, { 4, 2, 2, -1 } }, + { "MATSHITA", "CD-ROM CR-585", "Z18P", "matshita_585", BUS_TYPE_IDE, 0, 24, 36, 0, { 4, 2, 2, -1 } }, + { "MATSHITA", "CD-ROM CR-587", "7S13", "matshita_587", BUS_TYPE_IDE, 0, 24, 36, 0, { 4, 2, 2, -1 } }, + { "MATSHITA", "CD-ROM CR-588", "LS15", "matshita_588", BUS_TYPE_IDE, 0, 32, 36, 0, { 4, 2, 2, -1 } }, + { "MATSHITA", "CR-571", "1.0e", "matshita_571", BUS_TYPE_IDE, 0, 2, 36, 0, { 0, -1, -1, -1 } }, + { "MATSHITA", "CR-572", "1.0j", "matshita_572", BUS_TYPE_IDE, 0, 4, 36, 0, { 0, -1, -1, -1 } }, + { "MITSUMI", "CRMC-FX4820T", "D02A", "mitsumi_4820t", BUS_TYPE_IDE, 0, 48, 36, 0, { 4, 2, 2, 2 } }, + /* TODO: Find an IDENTIFY and/or INQUIRY dump. */ + { "MITSUMI", "CRMC-FX810T4", "????", "mitsumi_810t4", BUS_TYPE_IDE, 0, 8, 36, 0, { 4, 2, 2, -1 } }, + { "NEC", "CD-ROM DRIVE:260", "1.00", "nec_260_early", BUS_TYPE_IDE, 1, 2, 36, 1, { 0, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:260", "1.01", "nec_260", BUS_TYPE_IDE, 1, 4, 36, 1, { 0, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:273", "4.20", "nec_273", BUS_TYPE_IDE, 0, 4, 36, 0, { 0, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:280", "1.05", "nec_280_early", BUS_TYPE_IDE, 0, 6, 36, 1, { 4, 2, 2, -1 } }, + { "NEC", "CD-ROM DRIVE:280", "3.08", "nec_280", BUS_TYPE_IDE, 0, 8, 36, 1, { 4, 2, 2, -1 } }, + { "NEC", "CDR-1300A", "1.05", "nec_1300a", BUS_TYPE_IDE, 0, 6, 36, 0, { 4, 2, 2, -1 } }, + { "NEC", "CDR-1900A", "1.00", "nec_1900a", BUS_TYPE_IDE, 0, 32, 36, 0, { 4, 2, 2, -1 } }, + { "PHILIPS", "CD-ROM PCA403CD", "U31P", "philips_403", BUS_TYPE_IDE, 0, 40, 36, 0, { 4, 2, 2, -1 } }, + { "SONY", "CD-ROM CDU76", "1.0i", "sony_76", BUS_TYPE_IDE, 0, 4, 36, 0, { 2, -1, -1, -1 } }, + { "SONY", "CD-ROM CDU311", "3.0h", "sony_311", BUS_TYPE_IDE, 0, 8, 36, 0, { 3, 2, 1, -1 } }, + { "SONY", "CD-ROM CDU5225", "NYS4", "sony_5225", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 4 } }, + { "TEAC", "CD-516E", "1.0G", "teac_516e", BUS_TYPE_IDE, 0, 16, 36, 0, { 3, 2, 2, -1 } }, + { "TEAC", "CD-524EA", "3.0D", "teac_524ea", BUS_TYPE_IDE, 0, 24, 36, 0, { 3, 2, 2, -1 } }, + { "TEAC", "CD-532E", "2.0A", "teac_532e", BUS_TYPE_IDE, 0, 32, 36, 0, { 3, 2, 2, -1 } }, + { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "toshiba_5302ta", BUS_TYPE_IDE, 0, 4, 96, 0, { 0, -1, -1, -1 } }, + { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "toshiba_5702b", BUS_TYPE_IDE, 0, 12, 96, 0, { 3, 2, 1, -1 } }, + { "TOSHIBA", "CD-ROM XM-6202B", "1512", "toshiba_6202b", BUS_TYPE_IDE, 0, 32, 96, 0, { 4, 2, 2, -1 } }, + { "TOSHIBA", "CD-ROM XM-6402B", "1008", "toshiba_6402b", BUS_TYPE_IDE, 0, 32, 96, 0, { 4, 2, 2, 2 } }, + { "TOSHIBA", "CD-ROM XM-6702B", "1007", "toshiba_6720b", BUS_TYPE_IDE, 0, 48, 96, 0, { 4, 2, 2, 2 } }, + { "TOSHIBA", "DVD-ROM SD-M1802", "1051", "toshiba_m1802", BUS_TYPE_IDE, 0, 48, 96, 0, { 4, 2, 2, 2 } }, + { "CHINON", "CD-ROM CDS-431", "H42 ", "chinon_431", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } }, + { "CHINON", "CD-ROM CDX-435", "M62 ", "chinon_435", BUS_TYPE_SCSI, 1, 2, 36, 1, { -1, -1, -1, -1 } }, + { "DEC", "RRD45 (C) DEC", "0436", "dec_45", BUS_TYPE_SCSI, 1, 4, 36, 0, { -1, -1, -1, -1 } }, + { "MATSHITA", "CD-ROM CR-501", "1.0b", "matshita_501", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:25", "1.0a", "nec_25", BUS_TYPE_SCSI, 1, 2, 36, 0, { -1, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:38", "1.00", "nec_38", BUS_TYPE_SCSI, 2, 1, 36, 0, { -1, -1, -1, -1 } }, + /* The speed of the following two is guesswork based on the CDR-74. */ + { "NEC", "CD-ROM DRIVE:75", "1.03", "nec_75", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:77", "1.06", "nec_77", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } }, + { "NEC", "CD-ROM DRIVE:211", "1.00", "nec_211", BUS_TYPE_SCSI, 2, 3, 36, 0, { -1, -1, -1, -1 } }, + /* The speed of the following two is guesswork based on the CDR-400. */ + { "NEC", "CD-ROM DRIVE:464", "1.05", "nec_464", BUS_TYPE_SCSI, 2, 3, 36, 0, { -1, -1, -1, -1 } }, + /* The speed of the following two is guesswork based on the name. */ + { "ShinaKen", "CD-ROM DM-3x1S", "1.04", "shinaken_3x1s", BUS_TYPE_SCSI, 1, 3, 36, 0, { -1, -1, -1, -1 } }, + { "SONY", "CD-ROM CDU-541", "1.0i", "sony_541", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } }, + { "SONY", "CD-ROM CDU-561", "1.8k", "sony_561", BUS_TYPE_SCSI, 2, 2, 36, 1, { -1, -1, -1, -1 } }, + { "SONY", "CD-ROM CDU-76S", "1.00", "sony_76s", BUS_TYPE_SCSI, 2, 4, 36, 0, { -1, -1, -1, -1 } }, + { "PHILIPS", "CDD2600", "1.07", "philips_2600", BUS_TYPE_SCSI, 2, 6, 36, 0, { -1, -1, -1, -1 } }, + /* NOTE: The real thing is a CD changer drive! */ + { "PIONEER", "CD-ROM DRM-604X", "2403", "pioneer_604x", BUS_TYPE_SCSI, 2, 4, 47, 0, { -1, -1, -1, -1 } }, + { "PLEXTOR", "CD-ROM PX-32TS", "1.03", "plextor_32ts", BUS_TYPE_SCSI, 2, 32, 36, 0, { -1, -1, -1, -1 } }, + /* The speed of the following two is guesswork based on the R55S. */ + { "TEAC", "CD 50", "1.00", "teac_50", BUS_TYPE_SCSI, 2, 4, 36, 1, { -1, -1, -1, -1 } }, + { "TEAC", "CD-ROM R55S", "1.0R", "teac_55s", BUS_TYPE_SCSI, 2, 4, 36, 0, { -1, -1, -1, -1 } }, + /* Texel is Plextor according to Plextor's own EU website. */ + { "TEXEL", "CD-ROM DM-3024", "1.00", "texel_3024", BUS_TYPE_SCSI, 2, 2, 36, 1, { -1, -1, -1, -1 } }, + /* + Unusual 2.23x according to Google, I'm rounding it upwards to 3x. + Assumed caddy based on the DM-3024. + */ + { "TEXEL", "CD-ROM DM-3028", "1.06", "texel_3028", BUS_TYPE_SCSI, 2, 3, 36, 1 }, /* Caddy. */ + /* + The characteristics are a complete guesswork because I can't find + this one on Google. + + Also, INQUIRY length is always 96 on these Toshiba drives. + */ + { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "toshiba_xm", BUS_TYPE_SCSI, 2, 2, 96, 0 }, /* Tray. */ + { "TOSHIBA", "CD-ROM XM-3201B", "3232", "toshiba_3201b", BUS_TYPE_SCSI, 1, 1, 96, 1 }, /* Caddy. */ + { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "toshiba_3301ta", BUS_TYPE_SCSI, 2, 2, 96, 0 }, /* Tray. */ + { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "toshiba_5701a", BUS_TYPE_SCSI, 2, 12, 96, 0 }, /* Tray. */ + { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "toshiba_m1401", BUS_TYPE_SCSI, 2, 40, 96, 0 }, /* Tray. */ + { "", "", "", "", BUS_TYPE_NONE, 0, -1, 0, 0 } }; /* To shut up the GCC compilers. */ @@ -258,133 +258,177 @@ typedef struct raw_track_info_t { /* Define the various CD-ROM drive operations (ops). */ typedef struct cdrom_ops_t { - void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti); - void (*get_raw_track_info)(struct cdrom *dev, int *num, raw_track_info_t *rti); - void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc); - int (*is_track_pre)(struct cdrom *dev, uint32_t lba); - int (*sector_size)(struct cdrom *dev, uint32_t lba); - int (*read_sector)(struct cdrom *dev, uint8_t *b, uint32_t lba); - int (*track_type)(struct cdrom *dev, uint32_t lba); - int (*ext_medium_changed)(struct cdrom *dev); - void (*exit)(struct cdrom *dev); + int (*get_track_info)(const void *local, const uint32_t track, + const int end, track_info_t *ti); + void (*get_raw_track_info)(const void *local, int *num, + uint8_t *rti); + int (*is_track_pre)(const void *local, const uint32_t sector); + int (*read_sector)(const void *local, uint8_t *buffer, + const uint32_t sector); + uint8_t (*get_track_type)(const void *local, const uint32_t sector); + uint32_t (*get_last_block)(const void *local); + int (*read_dvd_structure)(const void *local, const uint8_t layer, + const uint8_t format, uint8_t *buffer, + uint32_t *info); + int (*is_dvd)(const void *local); + int (*has_audio)(const void *local); + int (*ext_medium_changed)(void *local); + void (*close)(void *local); } cdrom_ops_t; typedef struct cdrom { - uint8_t id; + uint8_t id; union { - uint8_t res; - uint8_t res0; /* Reserved for other ID's. */ - uint8_t res1; - uint8_t ide_channel; - uint8_t scsi_device_id; + uint8_t res; + uint8_t res0; /* Reserved for other ID's. */ + uint8_t res1; + uint8_t ide_channel; + uint8_t scsi_device_id; }; - uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - uint8_t cd_status; /* Struct variable reserved for - media status. */ - uint8_t speed; - uint8_t cur_speed; + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t cd_status; /* Struct variable reserved for + media status. */ + uint8_t speed; + uint8_t cur_speed; - void *priv; + void * priv; - char image_path[1024]; - char prev_image_path[1024]; + char image_path[1024]; + char prev_image_path[1024]; - char *image_history[CD_IMAGE_HISTORY]; + char * image_history[CD_IMAGE_HISTORY]; - uint32_t sound_on; - uint32_t cdrom_capacity; - uint32_t seek_pos; - uint32_t seek_diff; - uint32_t cd_end; - uint32_t type; - uint32_t sector_size; + uint32_t sound_on; + uint32_t cdrom_capacity; + uint32_t seek_pos; + uint32_t seek_diff; + uint32_t cd_end; + uint32_t type; + uint32_t sector_size; - int cd_buflen; - int audio_op; - int audio_muted_soft; - int sony_msf; + 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; const cdrom_ops_t *ops; - void *local; + void * local; + void * log; - void (*insert)(void *priv); - void (*close)(void *priv); - uint32_t (*get_volume)(void *p, int channel); - uint32_t (*get_channel)(void *p, int channel); + void (*insert)(void *priv); + void (*close)(void *priv); + 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[BUF_SIZE]; - uint8_t subch_buffer[96]; + uint8_t subch_buffer[96]; } cdrom_t; extern cdrom_t cdrom[CDROM_NUM]; -extern char *cdrom_getname(int type); +/* 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) -extern char *cdrom_get_internal_name(int type); -extern int cdrom_get_from_internal_name(char *s); -extern void cdrom_set_type(int model, int type); -extern int cdrom_get_type(int model); +static __inline int +bin2bcd(int x) +{ + return (x % 10) | ((x / 10) << 4); +} -extern int cdrom_lba_to_msf_accurate(int lba); -extern double cdrom_seek_time(cdrom_t *dev); -extern void cdrom_stop(cdrom_t *dev); -extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba); -extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len); -extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf); -extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit); -extern uint8_t cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit); -extern uint8_t cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos); -extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type); -extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume); -extern uint8_t cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type); -extern uint8_t cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b); -extern uint8_t cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf); -extern uint8_t cdrom_get_current_status(cdrom_t *dev); -extern void cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf); -extern void cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf); -extern void cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b); -extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b); -extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, - unsigned char start_track, int msf, int max_len); -extern int cdrom_read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int max_len); -extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf); -extern void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode); -extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len); -extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, - int cdrom_sector_type, int cdrom_sector_flags, int *len, uint8_t vendor_type); -extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type); +static __inline int +bcd2bin(int x) +{ + return (x >> 4) * 10 + (x & 0x0f); +} -extern void cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type); +extern char *cdrom_get_vendor(const int type); +extern void cdrom_get_model(const int type, char *name, const int id); +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); +extern int cdrom_has_dma(const int type); +extern int cdrom_get_transfer_max(const int type, const int mode); +extern int cdrom_get_type_count(void); +extern void cdrom_get_identify_model(const int type, char *name, const int id); +extern void cdrom_get_name(const int type, char *name); +extern char *cdrom_get_internal_name(const int type); +extern int cdrom_get_from_internal_name(const char *s); +/* TODO: Configuration migration, remove when no longer needed. */ +extern int cdrom_get_from_name(const char *s); +extern void cdrom_set_type(const int model, const int type); +extern int cdrom_get_type(const int model); -extern void cdrom_close_handler(uint8_t id); -extern void cdrom_insert(uint8_t id); -extern void cdrom_exit(uint8_t id); -extern int cdrom_is_empty(uint8_t id); -extern void cdrom_eject(uint8_t id); -extern void cdrom_reload(uint8_t id); +extern int cdrom_lba_to_msf_accurate(const int lba); +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); +extern int cdrom_is_pre(const cdrom_t *dev, const uint32_t lba); -extern int cdrom_image_open(cdrom_t *dev, const char *fn); -extern void cdrom_image_close(cdrom_t *dev); +extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, const int len); +extern uint8_t cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int ismsf); +extern uint8_t cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos, + const int type, const uint8_t playbit); +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 void cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume); -extern int cdrom_ioctl_open(cdrom_t *dev, const char *drv); -extern void cdrom_ioctl_close(cdrom_t *dev); +extern uint8_t cdrom_get_current_status(const cdrom_t *dev); +extern void cdrom_get_current_subchannel(const cdrom_t *dev, uint8_t *b, const int msf); +extern void cdrom_get_current_subchannel_sony(const cdrom_t *dev, uint8_t *b, const int msf); +extern uint8_t cdrom_get_audio_status_pioneer(const cdrom_t *dev, uint8_t *b); +extern uint8_t cdrom_get_audio_status_sony(const cdrom_t *dev, uint8_t *b, const int msf); +extern void cdrom_get_current_subcodeq(const cdrom_t *dev, uint8_t *b); +extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b); +extern int cdrom_read_toc(const cdrom_t *dev, uint8_t *b, const int type, + const uint8_t start_track, const int msf, const int max_len); +extern int cdrom_read_toc_sony(const cdrom_t *dev, uint8_t *b, const uint8_t start_track, + const int msf, const int max_len); +#ifdef USE_CDROM_MITSUMI +extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf); +extern void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode); +extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len); +#endif +extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, + const uint8_t track, const int type); +extern int cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, + int cdrom_sector_type, const int cdrom_sector_flags, + int *len, const uint8_t vendor_type); +extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_t layer, const uint8_t format, + 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(const cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer); +extern int cdrom_ext_medium_changed(const cdrom_t *dev); +extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert); -extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, - int number_of_blocks); - -extern int find_cdrom_for_scsi_id(uint8_t scsi_id); - -extern void cdrom_close(void); -extern void cdrom_global_init(void); -extern void cdrom_global_reset(void); -extern void cdrom_hard_reset(void); -extern void scsi_cdrom_drive_reset(int c); +extern void cdrom_global_init(void); +extern void cdrom_hard_reset(void); +extern void cdrom_close(void); +extern void cdrom_insert(const uint8_t id); +extern void cdrom_exit(const uint8_t id); +extern int cdrom_is_empty(const uint8_t id); +extern void cdrom_eject(const uint8_t id); +extern void cdrom_reload(const uint8_t id); #ifdef __cplusplus } diff --git a/src/include/86box/cdrom_image.h b/src/include/86box/cdrom_image.h index c848af50d..84dd66f37 100644 --- a/src/include/86box/cdrom_image.h +++ b/src/include/86box/cdrom_image.h @@ -6,35 +6,33 @@ * * This file is part of the 86Box distribution. * - * CD-ROM image file handling module header, translated to C - * from cdrom_dosbox.h. + * CD-ROM image file handling module header. * - * Authors: RichardG, - * Miran Grca, + * Authors: Miran Grca, + * RichardG, + * Cacodemon345 * - * Copyright 2016-2022 RichardG. - * Copyright 2016-2022 Miran Grca. + * Copyright 2016-2025 Miran Grca. + * Copyright 2016-2025 RichardG. + * Copyright 2024-2025 Cacodemon345. */ #ifndef CDROM_IMAGE_H #define CDROM_IMAGE_H -/* this header file lists the functions provided by - various platform specific cdrom-ioctl files */ +/* Track file struct. */ +typedef struct track_file_t { + int (*read)(void *priv, uint8_t *buffer, uint64_t seek, size_t count); + uint64_t (*get_length)(void *priv); + void (*close)(void *priv); -#ifdef __cplusplus -extern "C" { -#endif + char fn[260]; + FILE *fp; + void *priv; + void *log; -extern int image_open(uint8_t id, wchar_t *fn); -extern void image_reset(uint8_t id); + int motorola; +} track_file_t; -extern void image_close(uint8_t id); - -void update_status_bar_icon_state(int tag, int state); -extern void cdrom_set_null_handler(uint8_t id); - -#ifdef __cplusplus -} -#endif +extern void * image_open(cdrom_t *dev, const char *path); #endif /*CDROM_IMAGE_H*/ diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h deleted file mode 100644 index 64ce88d83..000000000 --- a/src/include/86box/cdrom_image_backend.h +++ /dev/null @@ -1,119 +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. - * - * CD-ROM image file handling module header. - * - * Authors: Miran Grca, - * RichardG, - * Cacodemon345 - * - * Copyright 2016-2025 Miran Grca. - * Copyright 2016-2025 Miran Grca. - * Copyright 2024-2025 Cacodemon345. - */ -#ifndef CDROM_IMAGE_BACKEND_H -#define CDROM_IMAGE_BACKEND_H - -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 - -#define DATA_TRACK 0x14 -#define AUDIO_TRACK 0x10 - -#define CD_FPS 75 -#define FRAMES_TO_MSF(f, M, S, F) \ - { \ - uint64_t value = f; \ - *(F) = (value % CD_FPS) & 0xff; \ - value /= CD_FPS; \ - *(S) = (value % 60) & 0xff; \ - value /= 60; \ - *(M) = value & 0xff; \ - } -#define MSF_TO_FRAMES(M, S, F) ((M) *60 * CD_FPS + (S) *CD_FPS + (F)) - -typedef struct SMSF { - uint16_t min; - uint8_t sec; - uint8_t fr; -} TMSF; - -/* Track file struct. */ -typedef struct track_file_t { - int (*read)(void *priv, uint8_t *buffer, uint64_t seek, size_t count); - uint64_t (*get_length)(void *priv); - void (*close)(void *priv); - - char fn[260]; - FILE *fp; - void *priv; - - int motorola; -} track_file_t; - -#define INDEX_SPECIAL -2 /* Track A0h onwards. */ -#define INDEX_NONE -1 /* Empty block. */ -#define INDEX_ZERO 0 /* Block not in the file, return all 0x00's. */ -#define INDEX_NORMAL 1 /* Block in the file. */ - -typedef struct track_index_t { - /* Is the current block in the file? If not, return all 0x00's. -1 means not yet loaded. */ - int32_t type; - /* The amount of bytes to skip at the beginning of each sector. */ - int32_t skip; - /* Starting and ending sector LBA - negative in order to accomodate LBA -150 to -1 - to read the pregap of track 1. */ - uint64_t start; - uint64_t length; - uint64_t file_start; - uint64_t file_length; - track_file_t *file; -} track_index_t; - -typedef struct track_t { - uint8_t session; - uint8_t attr; - uint8_t tno; - uint8_t point; - uint8_t extra[4]; - uint8_t mode; - uint8_t form; - uint8_t pad; - uint8_t skip; - uint32_t sector_size; - track_index_t idx[3]; -} track_t; - -typedef struct cd_img_t { - int32_t tracks_num; - track_t *tracks; -} cd_img_t; - -/* Binary file functions. */ -extern void cdi_get_raw_track_info(cd_img_t *cdi, int *num, uint8_t *buffer); -extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, - uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); -extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector); -extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector); -extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector); -extern int cdi_is_audio(cd_img_t *cdi, uint32_t sector); -extern int cdi_is_pre(cd_img_t *cdi, uint32_t sector); -extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector); -extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector); -extern int cdi_load_iso(cd_img_t *cdi, const char *filename); -extern int cdi_load_cue(cd_img_t *cdi, const char *cuefile); -extern void cdi_close(cd_img_t *cdi); -extern int cdi_set_device(cd_img_t *cdi, const char *path); - -/* Virtual ISO functions. */ -extern int viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count); -extern uint64_t viso_get_length(void *priv); -extern void viso_close(void *priv); -extern track_file_t *viso_init(const char *dirname, int *error); - -#endif /*CDROM_IMAGE_BACKEND_H*/ diff --git a/src/include/86box/cdrom_image_viso.h b/src/include/86box/cdrom_image_viso.h new file mode 100644 index 000000000..19f0e1de0 --- /dev/null +++ b/src/include/86box/cdrom_image_viso.h @@ -0,0 +1,26 @@ +/* + * 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. + * + * CD-ROM image file handling module header. + * + * Authors: RichardG, + * Miran Grca, + * + * Copyright 2016-2025 RichardG. + * Copyright 2016-2025 Miran Grca. + */ +#ifndef CDROM_IMAGE_VISO_H +#define CDROM_IMAGE_VISO_H + +/* Virtual ISO functions. */ +extern int viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count); +extern uint64_t viso_get_length(void *priv); +extern void viso_close(void *priv); +extern track_file_t *viso_init(const uint8_t id, const char *dirname, int *error); + +#endif /*CDROM_IMAGE_VISO_H*/ diff --git a/src/include/86box/cdrom_interface.h b/src/include/86box/cdrom_interface.h index 081f758f6..ba4d0581b 100644 --- a/src/include/86box/cdrom_interface.h +++ b/src/include/86box/cdrom_interface.h @@ -21,11 +21,13 @@ extern int cdrom_interface_current; extern void cdrom_interface_reset(void); -extern const char *cdrom_interface_get_internal_name(int cdinterface); -extern int cdrom_interface_get_from_internal_name(char *s); -extern int cdrom_interface_has_config(int cdinterface); -extern const device_t *cdrom_interface_get_device(int cdinterface); -extern int cdrom_interface_get_flags(int cdinterface); -extern int cdrom_interface_available(int cdinterface); +const char *cdrom_interface_get_internal_name(const int cdinterface); +extern int cdrom_interface_get_from_internal_name(const char *s); +#ifdef EMU_DEVICE_H +extern const device_t *cdrom_interface_get_device(const int cdinterface); +#endif +extern int cdrom_interface_has_config(const int cdinterface); +extern int cdrom_interface_get_flags(const int cdinterface); +extern int cdrom_interface_available(const int cdinterface); #endif /*EMU_CDROM_INTERFACE_H*/ diff --git a/src/include/86box/cdrom_ioctl.h b/src/include/86box/cdrom_ioctl.h deleted file mode 100644 index 5fc157615..000000000 --- a/src/include/86box/cdrom_ioctl.h +++ /dev/null @@ -1,32 +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. - * - * CD-ROM image file handling module header, translated to C - * from cdrom_dosbox.h. - * - * Authors: RichardG, - * Miran Grca, - * - * Copyright 2016-2022 RichardG. - * Copyright 2016-2022 Miran Grca. - */ -#ifndef CDROM_IOCTL_H -#define CDROM_IOCTL_H - -/* this header file lists the functions provided by - various platform specific cdrom-ioctl files */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /*CDROM_IOCTL_H*/ diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index a3b667e2e..110804244 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -22,11 +22,6 @@ #define MFM_NUM 2 /* 2 drives per controller supported */ #define ESDI_NUM 2 /* 2 drives per controller supported */ #define XTA_NUM 2 /* 2 drives per controller supported */ -#define IDE_NUM 10 /* 8 drives per AT IDE + 2 for XT IDE */ -#define ATAPI_NUM 8 /* 8 drives per AT IDE */ -#define SCSI_NUM 16 /* theoretically the controller can have at \ - * least 7 devices, with each device being \ - * able to support 8 units, but hey... */ /* Controller types. */ #define HDC_NONE 0 diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 9094f7f00..0280cf301 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -19,6 +19,9 @@ #ifndef EMU_IDE_H #define EMU_IDE_H +#define IDE_NUM 10 /* 8 drives per AT IDE + 2 for XT IDE */ +#define ATAPI_NUM 10 /* 8 drives per AT IDE + 2 for XT IDE */ + #define IDE_BUS_MAX 4 #define IDE_CHAN_MAX 2 @@ -121,11 +124,11 @@ typedef struct ide_s { double pending_delay; #ifdef SCSI_DEVICE_H - int (*get_max)(int ide_has_dma, int type); - int (*get_timings)(int ide_has_dma, int type); - void (*identify)(struct ide_s *ide, int ide_has_dma); - void (*stop)(scsi_common_t *sc); - void (*packet_command)(scsi_common_t *sc, uint8_t *cdb); + int (*get_max)(const struct ide_s *ide, const int ide_has_dma, const int type); + int (*get_timings)(const struct ide_s *ide, const int ide_has_dma, const int type); + void (*identify)(const struct ide_s *ide, const int ide_has_dma); + void (*stop)(const scsi_common_t *sc); + void (*packet_command)(scsi_common_t *sc, const uint8_t *cdb); void (*device_reset)(scsi_common_t *sc); uint8_t (*phase_data_out)(scsi_common_t *sc); void (*command_stop)(scsi_common_t *sc); @@ -142,10 +145,8 @@ typedef struct ide_s { #endif } ide_t; -#ifdef EMU_HDC_H extern ide_t *ide_drives[IDE_NUM]; #endif -#endif /* Type: 0 = PIO, diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index a4bded58f..b80c21c13 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -148,7 +148,7 @@ typedef struct hard_disk_t { uint8_t ide_channel; uint8_t scsi_id; }; - uint8_t bus; + 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 */ diff --git a/src/include/86box/log.h b/src/include/86box/log.h index 7f0b96d60..a37bdec4f 100644 --- a/src/include/86box/log.h +++ b/src/include/86box/log.h @@ -6,24 +6,20 @@ * * This file is part of the 86Box distribution. * - * Main include file for the application. - * - * + * New logging system handler header. * * Authors: Miran Grca, * Fred N. van Kempen, - * Connor Hyde + * Connor Hyde, * - * Copyright 2021 Miran Grca. - * Copyright 2021 Fred N. van Kempen. + * Copyright 2021-25 Miran Grca. + * Copyright 2021-25 Fred N. van Kempen. * Copyright 2025 Connor Hyde. */ #ifndef EMU_LOG_H #define EMU_LOG_H -#ifndef RELEASE_BUILD - # ifdef __cplusplus extern "C" { # endif @@ -35,20 +31,17 @@ extern "C" { /* Function prototypes. */ extern void log_set_suppr_seen(void *priv, int suppr_seen); extern void log_set_dev_name(void *priv, char *dev_name); -# ifdef HAVE_STDARG_H +#ifndef RELEASE_BUILD 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, ...); -# endif -extern void *log_open(char *dev_name); +extern void *log_open(const char *dev_name); +extern void *log_open_cyclic(const char *dev_name); extern void log_close(void *priv); # ifdef __cplusplus } # endif -#else -# define log_fatal(priv, fmt, ...) fatal(fmt, ...) -#endif /*RELEASE_BUILD*/ - #endif /*EMU_LOG_H*/ diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index 4ab567aca..0b494952c 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -9,13 +9,13 @@ * Implementation of a generic Magneto-Optical Disk drive * commands, for both ATAPI and SCSI usage. * - * - * * Authors: Natalia Portillo - * Fred N. van Kempen, * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2020 Miran Grca. + * Copyright 2020-2025 Natalia Portillo. + * Copyright 2020-2025 Miran Grca. + * Copyright 2020-2025 Fred N. van Kempen */ #ifndef EMU_MO_H @@ -91,88 +91,87 @@ enum { }; typedef struct mo_drive_t { - uint8_t id; + uint8_t id; union { - uint8_t res; - uint8_t res0; /* Reserved for other ID's. */ - uint8_t res1; - uint8_t ide_channel; - uint8_t scsi_device_id; + uint8_t res; + /* Reserved for other ID's. */ + uint8_t res0; + uint8_t res1; + uint8_t ide_channel; + uint8_t scsi_device_id; }; - uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - uint8_t read_only; /* Struct variable reserved for - media status. */ - uint8_t pad; - uint8_t pad0; + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t read_only; /* Struct variable reserved for + media status. */ + uint8_t pad; + uint8_t pad0; - FILE *fp; - void *priv; + FILE * fp; + void * priv; - char image_path[1024]; - char prev_image_path[1024]; + char image_path[1024]; + char prev_image_path[1024]; - char *image_history[MO_IMAGE_HISTORY]; + char * image_history[MO_IMAGE_HISTORY]; - uint32_t type; - uint32_t medium_size; - uint32_t base; - uint16_t sector_size; + uint32_t type; + uint32_t medium_size; + uint32_t base; + uint16_t sector_size; } mo_drive_t; typedef struct mo_t { mode_sense_pages_t ms_pages_saved; - mo_drive_t *drv; + mo_drive_t * drv; #ifdef EMU_IDE_H - ide_tf_t * tf; + ide_tf_t * tf; #else - void * tf; + void * tf; #endif - uint8_t *buffer; - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - uint8_t sense[256]; + void * log; - uint8_t id; - uint8_t cur_lun; - uint8_t pad0; - uint8_t pad1; + uint8_t * buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint16_t max_transfer_len; - uint16_t pad2; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks; - int packet_status; - int total_length; - int do_page_save; - int unit_attention; - int request_pos; - int old_len; - int pad3; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t packet_len; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int transition; - double callback; + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; - uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); + double callback; + + uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); } mo_t; -extern mo_t *mo[MO_NUM]; -extern mo_drive_t mo_drives[MO_NUM]; -#if 0 -extern uint8_t atapi_mo_drives[8]; -extern uint8_t scsi_mo_drives[16]; -#endif +extern mo_drive_t mo_drives[MO_NUM]; #define mo_sense_error dev->sense[0] #define mo_sense_key dev->sense[2] +#define mo_info *(uint32_t *) &(dev->sense[3]) #define mo_asc dev->sense[12] #define mo_ascq dev->sense[13] @@ -180,15 +179,16 @@ extern uint8_t scsi_mo_drives[16]; extern "C" { #endif -extern void mo_disk_close(mo_t *dev); -extern void mo_disk_reload(mo_t *dev); +extern void mo_disk_close(const mo_t *dev); +extern void mo_disk_reload(const mo_t *dev); extern void mo_insert(mo_t *dev); extern void mo_global_init(void); extern void mo_hard_reset(void); extern void mo_reset(scsi_common_t *sc); -extern int mo_load(mo_t *dev, char *fn); +extern int mo_is_empty(const uint8_t id); +extern void mo_load(const mo_t *dev, const char *fn, const int skip_insert); extern void mo_close(void); #ifdef __cplusplus diff --git a/src/include/86box/plat_cdrom.h b/src/include/86box/plat_cdrom.h deleted file mode 100644 index 643013a08..000000000 --- a/src/include/86box/plat_cdrom.h +++ /dev/null @@ -1,73 +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. - * - * Definitions for platform specific serial to host passthrough. - * - * - * Authors: Andreas J. Reichel , - * Jasmine Iwanek - * - * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. - */ - -#ifndef PLAT_CDROM_H -#define PLAT_CDROM_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 - -#define DATA_TRACK 0x14 -#define AUDIO_TRACK 0x10 - -#define CD_FPS 75 -#define FRAMES_TO_MSF(f, M, S, F) \ - { \ - uint64_t value = f; \ - *(F) = (value % CD_FPS) & 0xff; \ - value /= CD_FPS; \ - *(S) = (value % 60) & 0xff; \ - value /= 60; \ - *(M) = value & 0xff; \ - } -#define MSF_TO_FRAMES(M, S, F) ((M) *60 * CD_FPS + (S) *CD_FPS + (F)) - -typedef struct SMSF { - uint16_t min; - uint8_t sec; - uint8_t fr; -} TMSF; - -extern void plat_cdrom_get_raw_track_info(void *local, int *num, raw_track_info_t *rti); -extern int plat_cdrom_is_track_audio(void *local, uint32_t sector); -extern int plat_cdrom_is_track_pre(void *local, uint32_t sector); -extern uint32_t plat_cdrom_get_last_block(void *local); -extern int plat_cdrom_get_audio_track_info(void *local, int end, int track, int *track_num, TMSF *start, - uint8_t *attr); -extern int plat_cdrom_get_audio_sub(void *local, uint32_t sector, uint8_t *attr, uint8_t *track, - uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); -extern int plat_cdrom_get_sector_size(void *local, uint32_t sector); -extern int plat_cdrom_read_sector(void *local, uint8_t *buffer, uint32_t sector); -extern void plat_cdrom_eject(void *local); -extern void plat_cdrom_close(void *local); -extern int plat_cdrom_set_drive(void *local, const char *drv); -extern int plat_cdrom_ext_medium_changed(void *local); -extern uint32_t plat_cdrom_get_track_start(void *local, uint32_t sector, uint8_t *attr, uint8_t *track); -extern int plat_cdrom_get_local_size(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/include/86box/plat_cdrom_ioctl.h b/src/include/86box/plat_cdrom_ioctl.h new file mode 100644 index 000000000..471222134 --- /dev/null +++ b/src/include/86box/plat_cdrom_ioctl.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 platform specific serial to host passthrough. + * + * + * Authors: Andreas J. Reichel , + * Jasmine Iwanek + * + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. + */ + +#ifndef PLAT_CDROM_IOCTL_H +#define PLAT_CDROM_IOCTL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void * ioctl_open(cdrom_t *dev, const char *drv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/86box/scsi.h b/src/include/86box/scsi.h index 32ad1f912..84a4a608e 100644 --- a/src/include/86box/scsi.h +++ b/src/include/86box/scsi.h @@ -29,15 +29,21 @@ #define SCSI_ID_MAX 16 /* 16 on wide buses */ #define SCSI_LUN_MAX 8 /* always 8 */ -extern int scsi_card_current[SCSI_CARD_MAX]; +extern int scsi_card_current[SCSI_CARD_MAX]; -extern int scsi_card_available(int card); +extern void scsi_reset(void); +extern uint8_t scsi_get_bus(void); + +extern int scsi_card_available(int card); #ifdef EMU_DEVICE_H extern const device_t *scsi_card_getdevice(int card); #endif -extern int scsi_card_has_config(int card); -extern const char *scsi_card_get_internal_name(int card); -extern int scsi_card_get_from_internal_name(char *s); -extern void scsi_card_init(void); +extern int scsi_card_has_config(int card); +extern const char *scsi_card_get_internal_name(int card); +extern int scsi_card_get_from_internal_name(char *s); +extern void scsi_card_init(void); + +extern void scsi_bus_set_speed(uint8_t bus, double speed); +extern double scsi_bus_get_speed(uint8_t bus); #endif /*EMU_SCSI_H*/ diff --git a/src/include/86box/scsi_cdrom.h b/src/include/86box/scsi_cdrom.h index 684a9d589..bc2d4c8bd 100644 --- a/src/include/86box/scsi_cdrom.h +++ b/src/include/86box/scsi_cdrom.h @@ -26,47 +26,56 @@ typedef struct scsi_cdrom_t { /* Common block. */ mode_sense_pages_t ms_pages_saved; - cdrom_t * drv; + cdrom_t * drv; #ifdef EMU_IDE_H - ide_tf_t *tf; + ide_tf_t * tf; #else - void * tf; + void * tf; #endif - uint8_t *buffer; - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - uint8_t sense[256]; + void * log; - uint8_t id; - uint8_t cur_lun; - uint8_t early; - uint8_t pad1; + uint8_t * buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint16_t max_transfer_len; - uint16_t pad2; + uint8_t id; + uint8_t cur_lun; + uint8_t early; + uint8_t sector_type; - int requested_blocks; - int packet_status; - int total_length; - int do_page_save; - int unit_attention; - int request_pos; - int old_len; - int media_status; + uint16_t max_transfer_len; + uint16_t sector_flags; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t packet_len; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int media_status; - double callback; + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; - uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); + double callback; - int sony_vendor; + int is_sony; + int use_cdb_9; + + uint8_t ven_cmd_is_data[256]; - mode_sense_pages_t ms_pages_saved_sony; mode_sense_pages_t ms_drive_status_pages_saved; + + uint64_t ms_page_flags; + + 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 @@ -74,10 +83,12 @@ extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM]; #define scsi_cdrom_sense_error dev->sense[0] #define scsi_cdrom_sense_key dev->sense[2] +#define scsi_cdrom_info *(uint32_t *) &(dev->sense[3]) #define scsi_cdrom_asc dev->sense[12] #define scsi_cdrom_ascq dev->sense[13] #define scsi_cdrom_drive cdrom_drives[id].host_drive extern void scsi_cdrom_reset(scsi_common_t *sc); +extern void scsi_cdrom_drive_reset(const int c); #endif /*EMU_SCSI_CDROM_H*/ diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 538a96fac..84abee066 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -21,6 +21,7 @@ #define SCSI_DEVICE_H /* Configuration. */ +#define SCSI_NUM (SCSI_BUS_MAX * SCSI_ID_MAX) #define SCSI_LUN_USE_CDB 0xff @@ -53,8 +54,8 @@ #define GPCMD_SEEK_6 0x0b #define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c #define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ -#define GPCMD_NO_OPERATION_TOSHIBA 0x0d /* Toshiba Vendor Unique command */ -#define GPCMD_NO_OPERATION_NEC 0x0d /* NEC Vendor Unique command */ +#define GPCMD_NO_OPERATION_TOSHIBA 0x0d /* Toshiba Vendor Unique command. */ +#define GPCMD_NO_OPERATION_NEC 0x0d /* NEC Vendor Unique command. */ #define GPCMD_INQUIRY 0x12 #define GPCMD_VERIFY_6 0x13 #define GPCMD_MODE_SELECT_6 0x15 @@ -66,7 +67,7 @@ #define GPCMD_PREVENT_REMOVAL 0x1e #define GPCMD_READ_FORMAT_CAPACITIES 0x23 #define GPCMD_READ_CDROM_CAPACITY 0x25 -#define GPCMD_UNKNOWN_CHINON 0x26 /*Chinon Vendor Unique command*/ +#define GPCMD_UNKNOWN_CHINON 0x26 /* Chinon Vendor Unique command. */ #define GPCMD_READ_10 0x28 #define GPCMD_READ_GENERATION 0x29 #define GPCMD_WRITE_10 0x2a @@ -233,16 +234,12 @@ #define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 #define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13 -/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw). - Not that it means anything */ -#define CDROM_SPEED 706 /* 0x2C2 */ - -#define BUFFER_SIZE (256 * 1024) - -#define RW_DELAY (TIMER_USEC * 500) - /* Some generally useful CD-ROM information */ +#ifdef CONSERVATIVE_MAXIMUM #define CD_MINS 90 /* max. minutes per CD */ +#else +#define CD_MINS 100 /* max. minutes per CD - yes, 100-minute CD's in fact existed */ +#endif #define CD_SECS 60 /* seconds per minute */ #define CD_FRAMES 75 /* frames per second */ #define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ @@ -276,6 +273,10 @@ /* Profile list from MMC-6 revision 1 table 91 */ #define MMC_PROFILE_NONE 0x0000 +#define MMC_PROFILE_REMOVABLE_DISK 0x0002 +#define MMC_PROFILE_MO 0x0003 +#define MMC_PROFILE_MO_WORM 0x0004 +#define MMC_PROFILE_AS_MO 0x0005 #define MMC_PROFILE_CD_ROM 0x0008 #define MMC_PROFILE_CD_R 0x0009 #define MMC_PROFILE_CD_RW 0x000A @@ -304,7 +305,6 @@ #define MMC_PROFILE_HDDVD_RW_DL 0x005A #define MMC_PROFILE_INVALID 0xFFFF -#define EARLY_ONLY 64 #define SCSI_ONLY 32 #define ATAPI_ONLY 16 #define IMPLEMENTED 8 @@ -312,8 +312,6 @@ #define CHECK_READY 2 #define ALLOW_UA 1 -#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) - #define MSG_COMMAND_COMPLETE 0x00 #define BUS_DBP 0x01 @@ -371,7 +369,7 @@ #define MODE_SELECT_PHASE_PAGE 4 typedef struct mode_sense_pages_t { - uint8_t pages[0x40][0x40]; + uint8_t pages[0x40][0x40]; } mode_sense_pages_t; /* This is so we can access the common elements to all SCSI device structs @@ -379,89 +377,105 @@ typedef struct mode_sense_pages_t { typedef struct scsi_common_s { mode_sense_pages_t ms_pages_saved; - void * priv; + void * priv; #ifdef EMU_IDE_H - ide_tf_t *tf; + ide_tf_t * tf; #else - void * tf; + void * tf; #endif - uint8_t *temp_buffer; - uint8_t atapi_cdb[16]; /* This is atapi_cdb in ATAPI-supporting devices, - and pad in SCSI-only devices. */ - uint8_t current_cdb[16]; - uint8_t sense[256]; + void * log; - uint8_t id; - uint8_t cur_lun; - uint8_t pad0; - uint8_t pad1; + uint8_t * temp_buffer; + /* + This is atapi_cdb in ATAPI-supporting devices, + and pad in SCSI-only devices. + */ + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint16_t max_transfer_len; - uint16_t pad2; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks; - int packet_status; - int total_length; - int do_page_save; - int unit_attention; - int request_pos; - int old_len; - int media_status; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t packet_len; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int media_status; - double callback; + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; - uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); + double callback; + + uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); } scsi_common_t; typedef struct scsi_device_t { - int32_t buffer_length; + int32_t buffer_length; - uint8_t status; - uint8_t phase; - uint16_t type; + uint8_t status; + uint8_t phase; - scsi_common_t *sc; + uint16_t type; - void (*command)(scsi_common_t *sc, uint8_t *cdb); - void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length); - void (*reset)(scsi_common_t *sc); - uint8_t (*phase_data_out)(scsi_common_t *sc); - void (*command_stop)(scsi_common_t *sc); + scsi_common_t * sc; + + void (*command)(scsi_common_t *sc, const uint8_t *cdb); + void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, + uint8_t alloc_length); + void (*reset)(scsi_common_t *sc); + uint8_t (*phase_data_out)(scsi_common_t *sc); + void (*command_stop)(scsi_common_t *sc); } scsi_device_t; typedef struct scsi_bus_t { - int tx_mode; - int clear_req; - int wait_data; - int wait_complete; - int bus_out; - int bus_in; - int command_pos; - int command_issued; - int data_pos; - int msgout_pos; - int is_msgout; - int state; - int dma_on_pio_enabled; - uint8_t data; - uint8_t msglun; - uint8_t data_wait; - uint8_t command[16]; - uint8_t msgout[4]; - uint8_t target_id; - uint8_t bus_device; - uint32_t bus_phase; - double period; - double speed; - double divider; - double multi; - void *priv; - void (*timer)(void *priv, double period); + uint8_t data; + uint8_t msglun; + uint8_t data_wait; + uint8_t target_id; + uint8_t bus_device; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + + uint8_t command[16]; + uint8_t msgout[4]; + uint8_t pad2[4]; + + int tx_mode; + int clear_req; + int wait_data; + int wait_complete; + int bus_out; + int bus_in; + int command_pos; + int command_issued; + int data_pos; + int msgout_pos; + int is_msgout; + int state; + int dma_on_pio_enabled; + + uint32_t bus_phase; + + double period; + double speed; + double divider; + double multi; + + void *priv; + void (*timer)(void *priv, double period); } scsi_bus_t; /* These are based on the INQUIRY values. */ @@ -474,15 +488,8 @@ typedef struct scsi_bus_t { extern scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; #endif /* EMU_SCSI_H */ -extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); -extern int cdrom_LBAtoMSF_accurate(void); - -extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); -extern int mode_select_terminate(int force); -extern int mode_select_write(uint8_t val); - -extern uint8_t *scsi_device_sense(scsi_device_t *dev); extern double scsi_device_get_callback(scsi_device_t *dev); +extern uint8_t *scsi_device_sense(scsi_device_t *dev); extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length); extern void scsi_device_reset(scsi_device_t *dev); @@ -490,8 +497,8 @@ extern int scsi_device_present(scsi_device_t *dev); extern int scsi_device_valid(scsi_device_t *dev); extern int scsi_device_cdb_length(scsi_device_t *dev); extern void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb); -extern void scsi_device_command_phase1(scsi_device_t *dev); extern void scsi_device_command_stop(scsi_device_t *dev); +extern void scsi_device_command_phase1(scsi_device_t *dev); extern void scsi_device_identify(scsi_device_t *dev, uint8_t lun); extern void scsi_device_close_all(void); extern void scsi_device_init(void); diff --git a/src/include/86box/scsi_disk.h b/src/include/86box/scsi_disk.h index 8c7e045fb..7099b836a 100644 --- a/src/include/86box/scsi_disk.h +++ b/src/include/86box/scsi_disk.h @@ -19,42 +19,44 @@ typedef struct scsi_disk_t { mode_sense_pages_t ms_pages_saved; - hard_disk_t *drv; + hard_disk_t * drv; #ifdef EMU_IDE_H - ide_tf_t * tf; + ide_tf_t * tf; #else - void * tf; + void * tf; #endif - uint8_t *temp_buffer; - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - uint8_t sense[256]; + void * log; - uint8_t id; - uint8_t cur_lun; - uint8_t pad0; - uint8_t pad1; + uint8_t * temp_buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint16_t max_transfer_len; - uint16_t pad2; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks; - int packet_status; - int total_length; - int do_page_save; - int unit_attention; - int request_pos; - int pad6; - int pad7; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t packet_len; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int pad6; + int pad7; - double callback; + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; - uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); + double callback; + + uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); } scsi_disk_t; extern scsi_disk_t *scsi_disk[HDD_NUM]; diff --git a/src/include/86box/zip.h b/src/include/86box/zip.h index 739ba388b..59b78b64e 100644 --- a/src/include/86box/zip.h +++ b/src/include/86box/zip.h @@ -13,7 +13,7 @@ * * Authors: Miran Grca, * - * Copyright 2018-2019 Miran Grca. + * Copyright 2018-2025 Miran Grca. */ #ifndef EMU_ZIP_H @@ -39,76 +39,79 @@ enum { }; typedef struct zip_drive_t { - uint8_t id; + uint8_t id; union { - uint8_t res; - uint8_t res0; /* Reserved for other ID's. */ - uint8_t res1; - uint8_t ide_channel; - uint8_t scsi_device_id; + uint8_t res; + /* Reserved for other ID's. */ + uint8_t res0; + uint8_t res1; + uint8_t ide_channel; + uint8_t scsi_device_id; }; - uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - uint8_t read_only; /* Struct variable reserved for - media status. */ - uint8_t pad; - uint8_t pad0; + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t read_only; /* Struct variable reserved for + media status. */ + uint8_t pad; + uint8_t pad0; - FILE *fp; - void *priv; + FILE * fp; + void * priv; - char image_path[1024]; - char prev_image_path[1024]; + char image_path[1024]; + char prev_image_path[1024]; - char *image_history[ZIP_IMAGE_HISTORY]; + char * image_history[ZIP_IMAGE_HISTORY]; - uint32_t is_250; - uint32_t medium_size; - uint32_t base; + uint32_t is_250; + uint32_t medium_size; + uint32_t base; } zip_drive_t; typedef struct zip_t { mode_sense_pages_t ms_pages_saved; - zip_drive_t *drv; + zip_drive_t * drv; #ifdef EMU_IDE_H - ide_tf_t * tf; + ide_tf_t * tf; #else - void * tf; + void * tf; #endif - uint8_t *buffer; - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - uint8_t sense[256]; + void * log; - uint8_t id; - uint8_t cur_lun; - uint8_t pad0; - uint8_t pad1; + uint8_t * buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint16_t max_transfer_len; - uint16_t pad2; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks; - int packet_status; - int total_length; - int do_page_save; - int unit_attention; - int request_pos; - int old_len; - int pad3; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t packet_len; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int transition; - double callback; + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; - uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); + double callback; + + uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen); } zip_t; extern zip_t *zip[ZIP_NUM]; @@ -118,6 +121,7 @@ extern uint8_t scsi_zip_drives[16]; #define zip_sense_error dev->sense[0] #define zip_sense_key dev->sense[2] +#define zip_info *(uint32_t *) &(dev->sense[3]) #define zip_asc dev->sense[12] #define zip_ascq dev->sense[13] @@ -125,15 +129,16 @@ extern uint8_t scsi_zip_drives[16]; extern "C" { #endif -extern void zip_disk_close(zip_t *dev); -extern void zip_disk_reload(zip_t *dev); +extern void zip_disk_close(const zip_t *dev); +extern void zip_disk_reload(const zip_t *dev); extern void zip_insert(zip_t *dev); extern void zip_global_init(void); extern void zip_hard_reset(void); extern void zip_reset(scsi_common_t *sc); -extern int zip_load(zip_t *dev, char *fn); +extern int zip_is_empty(const uint8_t id); +extern void zip_load(const zip_t *dev, const char *fn, const int skip_insert); extern void zip_close(void); #ifdef __cplusplus diff --git a/src/log.c b/src/log.c index a4d84e616..c8dddf62e 100644 --- a/src/log.c +++ b/src/log.c @@ -6,16 +6,14 @@ * * This file is part of the 86Box distribution. * - * The handler of the new logging system. - * - * + * New logging system handler. * * Authors: Miran Grca, * Fred N. van Kempen, - * Connor Hyde + * Connor Hyde, * - * Copyright 2021 Miran Grca. - * Copyright 2021 Fred N. van Kempen. + * Copyright 2021-25 Miran Grca. + * Copyright 2021-25 Fred N. van Kempen. * Copyright 2025 Connor Hyde. */ #include @@ -37,21 +35,44 @@ #include <86box/version.h> #include <86box/log.h> -#ifndef RELEASE_BUILD typedef struct log_t { - char buff[1024]; - char *dev_name; - int seen; - int suppr_seen; - char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; // Cyclical log buffer. This is 32kb, might calloc? - int32_t cyclic_last_line; - int32_t log_cycles; + char buff[1024]; + char dev_name[1024]; + int seen; + int suppr_seen; + /* Cyclical log buffer. */ + char **cyclic_buff; + int32_t cyclic_last_line; + int32_t log_cycles; } log_t; -extern FILE *stdlog; /* file to log output to */ -// Functions only used in this translation unit +/* File to log output to. */ +extern FILE *stdlog; +/* Functions only used in this translation unit. */ void log_ensure_stdlog_open(void); +void +log_set_dev_name(void *priv, char *dev_name) +{ + log_t *log = (log_t *) priv; + + memcpy(log->dev_name, dev_name, strlen(dev_name) + 1); +} + +static void +log_copy(log_t *log, char *dest, const char *src, size_t dest_size) +{ + memset(dest, 0x00, dest_size * sizeof(char)); + + if ((log != NULL) && strcmp(log->dev_name, "")) { + strcat(dest, log->dev_name); + strcat(dest, ": "); + } + + strcat(dest, src); +} + +#ifndef RELEASE_BUILD void log_ensure_stdlog_open(void) { @@ -73,31 +94,12 @@ log_set_suppr_seen(void *priv, int suppr_seen) log->suppr_seen = suppr_seen; } -void -log_set_dev_name(void *priv, char *dev_name) -{ - log_t *log = (log_t *) priv; - - log->dev_name = dev_name; -} - -static void -log_copy(log_t *log, char *dest, const char *src, size_t dest_size) -{ - memset(dest, 0x00, dest_size * sizeof(char)); - if (log && log->dev_name && strcmp(log->dev_name, "")) { - strcat(dest, log->dev_name); - strcat(dest, ": "); - } - strcat(dest, src); -} - /* - * Log something to the logfile or stdout. - * - * To avoid excessively-large logfiles because some - * module repeatedly logs, we keep track of what is - * being logged, and catch repeating entries. + Log something to the logfile or stdout. + + To avoid excessively-large logfiles because some + module repeatedly logs, we keep track of what is + being logged, and catch repeating entries. */ void log_out(void *priv, const char *fmt, va_list ap) @@ -107,154 +109,164 @@ log_out(void *priv, const char *fmt, va_list ap) char fmt2[1024]; if (log == NULL) - return; + pclog("WARNING: Logging called with a NULL log pointer\n"); + else if (fmt == NULL) + pclog("WARNING: Logging called with a NULL format pointer\n"); + else if (fmt[0] != '\0') { + log_ensure_stdlog_open(); - if (strcmp(fmt, "") == 0) - return; - - log_ensure_stdlog_open(); - - vsprintf(temp, fmt, ap); - if (log->suppr_seen && !strcmp(log->buff, temp)) - log->seen++; - else { - if (log->suppr_seen && log->seen) { - log_copy(log, fmt2, "*** %d repeats ***\n", 1024); - fprintf(stdlog, fmt2, log->seen); + vsprintf(temp, fmt, ap); + if (log->suppr_seen && !strcmp(log->buff, temp)) + log->seen++; + else { + if (log->suppr_seen && log->seen) { + log_copy(log, fmt2, "*** %d repeats ***\n", 1024); + fprintf(stdlog, fmt2, log->seen); + } + log->seen = 0; + strcpy(log->buff, temp); + log_copy(log, fmt2, temp, 1024); + fprintf(stdlog, fmt2, ap); } - log->seen = 0; - strcpy(log->buff, temp); - log_copy(log, fmt2, temp, 1024); - fprintf(stdlog, fmt2, ap); - } - fflush(stdlog); + fflush(stdlog); + } } - /* -Starfrost, 7-8 January 2025: + Starfrost, 7-8 January 2025: -For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. + For RIVA 128 emulation I needed a way to suppress logging if a repeated + pattern of the same set of lines were found. -Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm + Implements a version of the Rabin-Karp algorithm: + https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm . */ void log_out_cyclic(void* priv, const char* fmt, va_list ap) { -#ifndef RELEASE_BUILD - // get our new logging system instance. - log_t* log = (log_t*)priv; + /* Get our new logging system instance. */ + log_t* log = (log_t*) priv; - // does the log actually exist? - if (!log) - return; + /* Does the log actually exist? */ + if (log == NULL) + pclog("WARNING: Cyclical logging called with a NULL log pointer\n"); + else if (log->cyclic_buff == NULL) + pclog("WARNING: Cyclical logging called with a non-cyclic log\n"); + else if (fmt == NULL) + pclog("WARNING: Cyclical logging called with a NULL format pointer\n"); + /* Is the string empty? */ + else if (fmt[0] != '\0') { + /* Ensure stdlog is open. */ + log_ensure_stdlog_open(); - // is the string empty? - if (fmt[0] == '\0') - return; - - // ensure stdlog is open - log_ensure_stdlog_open(); + char temp[LOG_SIZE_BUFFER] = {0}; - char temp[LOG_SIZE_BUFFER] = {0}; + log->cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; - log->cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; + vsprintf(temp, fmt, ap); - vsprintf(temp, fmt, ap); + log_copy(log, log->cyclic_buff[log->cyclic_last_line], temp, + LOG_SIZE_BUFFER); - log_copy(log, log->cyclic_buff[log->cyclic_last_line], temp, LOG_SIZE_BUFFER); + uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; - uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; + /* Random numbers. */ + uint32_t base = 257; + uint32_t mod = 1000000007; - // Random numbers - uint32_t base = 257; - uint32_t mod = 1000000007; + uint32_t repeat_order = 0; + bool is_cycle = false; - uint32_t repeat_order = 0; - bool is_cycle = false; + /* Compute the set of hashes for the current log buffer. */ + for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; + log_line++) { + if (log->cyclic_buff[log_line][0] == '\0') + continue; /* Skip. */ - // compute the set of hashes for the current log buffer - for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) - { - if (log->cyclic_buff[log_line][0] == '\0') - continue; // skip - - for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) - { - hashes[log_line] = hashes[log_line] * base + log->cyclic_buff[log_line][log_line_char] % mod; + for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; + log_line_char++) + hashes[log_line] = hashes[log_line] * base + + log->cyclic_buff[log_line][log_line_char] % mod; } - } - - // Now see if there are real cycles... - // We implement a minimum repeat size. - for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) - { - //TODO: Log what we need for cycle 1. - //TODO: Command line option that lets us turn off this behaviour. - for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) - { - if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) - { - repeat_order = check_size; - break; + /* + Now see if there are real cycles. + We implement a minimum repeat size. + */ + for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; + check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) { + /* + TODO: Log what we need for cycle 1. + TODO: Command line option that lets us turn off this behaviour. + */ + for (int32_t log_line_to_check = 0; log_line_to_check < check_size; + log_line_to_check++) { + if (hashes[log_line_to_check] == + hashes[(log_line_to_check + check_size) % + LOG_SIZE_BUFFER_CYCLIC_LINES]) { + repeat_order = check_size; + break; + } } + + is_cycle = (repeat_order != 0); + + /* If there still is a cycle, break. */ + if (is_cycle) + break; + } - is_cycle = (repeat_order != 0); + if (is_cycle) { + if (log->cyclic_last_line % repeat_order == 0) { + log->log_cycles++; - // if there still is a cycle.. - if (is_cycle) - break; - - } + if (log->log_cycles == 1) { + /* + 'Replay' the last few log entries so they actually + show up. - if (is_cycle) - { - if (log->cyclic_last_line % repeat_order == 0) - { - log->log_cycles++; + TODO: Is this right? + */ - if (log->log_cycles == 1) - { - // 'Replay' the last few log entries so they actually show up - // Todo: is this right? + for (uint32_t index = log->cyclic_last_line - 1; + index > (log->cyclic_last_line - repeat_order); + index--) { + /* *Very important* to prevent out of bounds index. */ + uint32_t real_index = index % + LOG_SIZE_BUFFER_CYCLIC_LINES; + log_copy(log, temp, log->cyclic_buff[real_index], + LOG_SIZE_BUFFER); - for (uint32_t index = log->cyclic_last_line - 1; index > (log->cyclic_last_line - repeat_order); index--) - { - // *very important* to prevent out of bounds index - uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; - log_copy(log, temp, log->cyclic_buff[real_index], LOG_SIZE_BUFFER); - - fprintf(stdlog, "%s", log->cyclic_buff[real_index]); + fprintf(stdlog, "%s", log->cyclic_buff[real_index]); + } + /* Restore the original line. */ + log_copy(log, temp, + log->cyclic_buff[log->cyclic_last_line], + LOG_SIZE_BUFFER); + + /* Allow normal logging. */ + fprintf(stdlog, "%s", temp); } - // restore the original line - log_copy(log, temp, log->cyclic_buff[log->cyclic_last_line], LOG_SIZE_BUFFER); - - fprintf(stdlog, "%s", temp); // allow normal logging + if (log->log_cycles > 1 && log->log_cycles < 100) + fprintf(stdlog, "***** Cyclical Log Repeat of Order %d " + "#%d *****\n", repeat_order, log->log_cycles); + else if (log->log_cycles == 100) + fprintf(stdlog, "Logged the same cycle 100 times... " + "Silence until something interesting happens\n"); } - - - if (log->log_cycles > 1 && log->log_cycles < 100) - fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log->log_cycles); - else if (log->log_cycles == 100) - fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); + } else { + log->log_cycles = 0; + fprintf(stdlog, "%s", temp); } - } - else - { - log->log_cycles = 0; - fprintf(stdlog, "%s", temp); - } - - log->cyclic_last_line++; - -#endif + log->cyclic_last_line++; + } } +#endif void log_fatal(void *priv, const char *fmt, ...) @@ -267,6 +279,13 @@ log_fatal(void *priv, const char *fmt, ...) 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); @@ -275,21 +294,42 @@ log_fatal(void *priv, const char *fmt, ...) exit(-1); } -void * -log_open(char *dev_name) +static void * +log_open_common(const char *dev_name, const int cyclic) { - log_t *log = malloc(sizeof(log_t)); + log_t *log = calloc(1, sizeof(log_t)); - memset(log, 0, sizeof(log_t)); - - log->dev_name = dev_name; + memcpy(log->dev_name, dev_name, strlen(dev_name) + 1); log->suppr_seen = 1; log->cyclic_last_line = 0; log->log_cycles = 0; + if (cyclic) { + log->cyclic_buff = calloc(LOG_SIZE_BUFFER_CYCLIC_LINES, + sizeof(char *)); + for (int i = 0; i < LOG_SIZE_BUFFER_CYCLIC_LINES; i++) + log->cyclic_buff[i] = calloc(LOG_SIZE_BUFFER, sizeof(char)); + } + return (void *) log; } +void * +log_open(const char *dev_name) +{ + return log_open_common(dev_name, 0); +} + +/* + This is so that not all logs get the 32k cyclical buffer + they may not need. + */ +void * +log_open_cyclic(const char *dev_name) +{ + return log_open_common(dev_name, 1); +} + void log_close(void *priv) { @@ -297,4 +337,3 @@ log_close(void *priv) free(log); } -#endif diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index e1bacad6c..e3f6428a7 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -1311,7 +1311,7 @@ ps1_hdc_init(UNUSED(const device_t *info)) /* Load any disks for this device class. */ c = 0; for (uint8_t i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < 1)) { + if ((hdd[i].bus_type == HDD_BUS_XTA) && (hdd[i].xta_channel < 1)) { drive = &dev->drives[hdd[i].xta_channel]; if (!hdd_image_load(i)) { diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index fb0224bc6..c85628e01 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -17,16 +17,18 @@ * Copyright 2023 Miran Grca. */ #include +#ifdef ENABLE_IOCTL_LOG #include +#endif #include #include #include #include #include #define HAVE_STDARG_H -#include <86box/86box.h> #include <86box/scsi_device.h> #include <86box/cdrom.h> +#include <86box/log.h> #include <86box/plat_unused.h> #include <86box/plat_cdrom.h> @@ -35,223 +37,203 @@ 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) -typedef struct dummy_cdrom_ioctl_t { +typedef struct ioctl_t { + cdrom_t *dev; + void *log; int toc_valid; -} dummy_cdrom_ioctl_t; +} ioctl_t; -#ifdef ENABLE_DUMMY_CDROM_IOCTL_LOG -int dummy_cdrom_ioctl_do_log = ENABLE_DUMMY_CDROM_IOCTL_LOG; +#ifdef ENABLE_IOCTL_LOG +int ioctl_do_log = ENABLE_IOCTL_LOG; void -dummy_cdrom_ioctl_log(const char *fmt, ...) +ioctl_log(void *priv, const char *fmt, ...) { - va_list ap; - - if (dummy_cdrom_ioctl_do_log) { + if (ioctl_do_log) { + va_list ap; va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define dummy_cdrom_ioctl_log(fmt, ...) +# define ioctl_log(priv, fmt, ...) #endif -static int -plat_cdrom_open(void *local) +/* Internal functions. */ +static void +ioctl_close_handle(UNUSED(const ioctl_t *ioctl)) { return 0; } static int -plat_cdrom_load(void *local) +ioctl_open_handle(UNUSED(ioctl_t *ioctl)) { return 0; } static void -plat_cdrom_read_toc(void *local) +ioctl_read_toc(ioctl_t *ioctl) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + if (!ioctl->toc_valid) { + ioctl->toc_valid = 1; + } +} + +/* Shared functions. */ +static int +ioctl_get_track_info(UNUSED(const void *local), UNUSED(const uint32_t track), + UNUSED(int end), UNUSED(track_info_t *ti)) +{ + return 0; +} + +static void +ioctl_get_raw_track_info(const void *local, UNUSED(int *num), UNUSED(uint8_t *rti)) +{ + ioctl_t *ioctl = (ioctl_t *) local; if (!ioctl->toc_valid) ioctl->toc_valid = 1; } -void -plat_cdrom_get_raw_track_info(UNUSED(void *local), int *num, raw_track_info_t *rti) +static void +ioctl_get_raw_track_info(UNUSED(const void *local), int *num, uint8_t *rti) { *num = 1; memset(rti, 0x00, 11); } -int -plat_cdrom_is_track_audio(void *local, uint32_t sector) +static int +ioctl_is_track_pre(const void *local, const uint32_t sector) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - const int ret = 0; - - dummy_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); - - return ret; -} - -int -plat_cdrom_is_track_pre(void *local, uint32_t sector) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + ioctl_t *ioctl = (ioctl_t *) local; plat_cdrom_read_toc(ioctl); const int ret = 0; - dummy_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); + ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); return ret; } -uint32_t -plat_cdrom_get_track_start(void *local, uint32_t sector, uint8_t *attr, uint8_t *track) +static int +ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - return 0x00000000; -} - -uint32_t -plat_cdrom_get_last_block(void *local) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - return 0x00000000; -} - -int -plat_cdrom_ext_medium_changed(UNUSED(void *local)) -{ -#if 0 - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); -#endif - - int ret = 0; - - dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); - - return ret; -} - -/* This replaces both Info and EndInfo, they are specified by a variable. */ -int -plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - if ((track < 1) || (track == 0xaa)) { - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i)\n", track); - return 0; - } - - start->min = 0; - start->sec = 0; - start->fr = 2; - - *track_num = 1; - *attr = 0x14; - - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n", - track, start->min, start->sec, start->fr, *track_num, *attr); - - return 1; -} - -/* TODO: See if track start is adjusted by 150 or not. */ -int -plat_cdrom_get_audio_sub(UNUSED(void *local), UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track, uint8_t *index, - TMSF *rel_pos, TMSF *abs_pos) -{ - *track = 1; - *attr = 0x14; - *index = 1; - - rel_pos->min = 0; - rel_pos->sec = 0; - rel_pos->fr = 0; - abs_pos->min = 0; - abs_pos->sec = 0; - abs_pos->fr = 2; - - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_sub(): %02i, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", - *track, *attr, *index, rel_pos->min, rel_pos->sec, rel_pos->fr, abs_pos->min, abs_pos->sec, abs_pos->fr); - - return 1; -} - -int -plat_cdrom_get_sector_size(UNUSED(void *local), UNUSED(uint32_t sector)) -{ - dummy_cdrom_ioctl_log("BytesPerSector=2048\n"); - - return 2048; -} - -int -plat_cdrom_read_sector(void *local, uint8_t *buffer, uint32_t sector) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + ioctl_t *ioctl = (ioctl_t *) local; plat_cdrom_open(ioctl); /* Raw */ - dummy_cdrom_ioctl_log("Raw\n"); + ioctl_log("Raw\n"); plat_cdrom_close(ioctl); - dummy_cdrom_ioctl_log("ReadSector sector=%d.\n", sector); + ioctl_log("ReadSector sector=%d.\n", sector); return 0; } -void -plat_cdrom_eject(void *local) +static uint8_t +ioctl_get_track_type(UNUSED(const void *local), UNUSED(const uint32_t sector)) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_open(ioctl); - plat_cdrom_close(ioctl); + return 0x00; } -void -plat_cdrom_close(UNUSED(void *local)) +static uint32_t +ioctl_get_last_block(const void *local) { + ioctl_t *ioctl = (ioctl_t *) local; + + ioctl_read_toc(ioctl); + + return 0x00000000; } -int -plat_cdrom_set_drive(void *local, const char *drv) +static int +ioctl_read_dvd_structure(UNUSED(const void *local), UNUSED(const uint8_t layer), UNUSED(const uint8_t format), + UNUSED(uint8_t *buffer), UNUSED(uint32_t *info)) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_close(ioctl); - - ioctl->toc_valid = 0; - - plat_cdrom_load(ioctl); - - return 1; + return -0x00052100; } -int -plat_cdrom_get_local_size(void) +static int +ioctl_is_dvd(UNUSED(const void *local)) { - return sizeof(dummy_cdrom_ioctl_t); + return 0; +} + +static int +ioctl_has_audio(UNUSED(const void *local)) +{ + return 0; +} + +static int +ioctl_ext_medium_changed(UNUSED(void *local)) +{ +#if 0 + ioctl_t *ioctl = (ioctl_t *) local; +#endif + int ret = 0; + + ioctl_log("ioctl_ext_medium_changed(): %i\n", ret); + + return ret; +} + +static void +ioctl_close(void *local) +{ + ioctl_t *ioctl = (ioctl_t *) local; + + ioctl_close_handle(ioctl); + ioctl->handle = NULL; + + ioctl_log(ioctl->log, "Log closed\n"); + + log_close(ioctl->log); + ioctl->log = NULL; +} + +static const cdrom_ops_t ioctl_ops = { + ioctl_get_track_info, + ioctl_get_raw_track_info, + ioctl_is_track_pre, + ioctl_read_sector, + ioctl_get_track_type, + ioctl_get_last_block, + ioctl_read_dvd_structure, + ioctl_is_dvd, + ioctl_has_audio, + ioctl_ext_medium_changed, + ioctl_close +}; + +/* Public functions. */ +void * +ioctl_open(cdrom_t *dev, const char *drv) +{ + ioctl_t *ioctl = (ioctl_t *) calloc(1, sizeof(ioctl_t)); + + if (ioctl != NULL) { + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i IOCtl", dev->id + 1); + ioctl->log = log_open(n); + + memset(ioctl->path, 0x00, sizeof(ioctl->path)); + + wsprintf(ioctl->path, L"%S", &(drv[8])); + ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); + + ioctl->dev = dev; + ioctl->toc_valid = 0; + + dev->ops = &ioctl_ops; + } + + return ioctl; } diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index ebc18e198..d1335873c 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -369,12 +369,12 @@ MachineStatus::iterateNIC(const std::function &cb) } static int -hdd_count(int bus) +hdd_count(const int bus_type) { int c = 0; for (uint8_t i = 0; i < HDD_NUM; i++) { - if (hdd[i].bus == bus) { + if (hdd[i].bus_type == bus_type) { c++; } } diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 902ca10d6..fdea16c2a 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -537,10 +537,7 @@ MediaMenu::cdromMount(int i, const QString &filename) if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '\\')) fn.data()[strlen(fn.data()) - 1] = '/'; #endif - if ((fn.data() != nullptr) && fn.contains("ioctl://")) - cdrom_ioctl_open(&(cdrom[i]), fn.data()); - else - cdrom_image_open(&(cdrom[i]), fn.data()); + cdrom_load(&(cdrom[i]), fn.data(), 1); /* Signal media change to the emulated machine. */ if (cdrom[i].insert) { @@ -806,14 +803,21 @@ MediaMenu::zipSelectImage(int i, bool wp) void MediaMenu::zipMount(int i, const QString &filename, bool wp) { - const auto dev = static_cast(zip_drives[i].priv); + const auto dev = static_cast(zip_drives[i].priv); + int was_empty = zip_is_empty(i); zip_disk_close(dev); zip_drives[i].read_only = wp; if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); - zip_load(dev, filenameBytes.data()); + zip_load(dev, filenameBytes.data(), 1); + + /* Signal media change to the emulated machine. */ zip_insert(dev); + + /* The drive was previously empty, transition directly to UNIT ATTENTION. */ + if (was_empty) + zip_insert(dev); } mhm.addImageToHistory(i, ui::MediaType::Zip, zip_drives[i].prev_image_path, zip_drives[i].image_path); @@ -935,14 +939,21 @@ MediaMenu::moSelectImage(int i, bool wp) void MediaMenu::moMount(int i, const QString &filename, bool wp) { - const auto dev = static_cast(mo_drives[i].priv); + const auto dev = static_cast(mo_drives[i].priv); + int was_empty = mo_is_empty(i); mo_disk_close(dev); mo_drives[i].read_only = wp; if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); - mo_load(dev, filenameBytes.data()); + mo_load(dev, filenameBytes.data(), 1); + + /* Signal media change to the emulated machine. */ mo_insert(dev); + + /* The drive was previously empty, transition directly to UNIT ATTENTION. */ + if (was_empty) + mo_insert(dev); } mhm.addImageToHistory(i, ui::MediaType::Mo, mo_drives[i].prev_image_path, mo_drives[i].image_path); diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index db54315e4..cc58d3cde 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -90,6 +90,14 @@ setCDROMSpeed(QAbstractItemModel *model, const QModelIndex &idx, uint8_t speed) model->setData(i, speed, Qt::UserRole); } +static QString +CDROMName(int type) +{ + char temp[512]; + cdrom_get_name(type, temp); + return QObject::tr((const char *) temp); +} + static void setCDROMType(QAbstractItemModel *model, const QModelIndex &idx, int type) { @@ -97,7 +105,7 @@ setCDROMType(QAbstractItemModel *model, const QModelIndex &idx, int type) if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == CDROM_BUS_DISABLED) model->setData(i, QCoreApplication::translate("", "None")); else if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() != CDROM_BUS_MITSUMI) - model->setData(i, QObject::tr(cdrom_getname(type))); + model->setData(i, CDROMName(type)); model->setData(i, type, Qt::UserRole); } @@ -156,8 +164,12 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) auto idx = model->index(i, 0); int type = cdrom_get_type(i); setCDROMBus(model, idx, cdrom[i].bus_type, cdrom[i].res); - setCDROMSpeed(model, idx.siblingAtColumn(1), cdrom[i].speed); setCDROMType(model, idx.siblingAtColumn(2), type); + int speed = cdrom_get_speed(type); + if (speed == -1) + setCDROMSpeed(model, idx.siblingAtColumn(1), cdrom[i].speed); + else + setCDROMSpeed(model, idx.siblingAtColumn(1), speed); if (cdrom[i].bus_type == CDROM_BUS_ATAPI) Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, cdrom[i].ide_channel); else if (cdrom[i].bus_type == CDROM_BUS_SCSI) @@ -186,7 +198,7 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) if (((bus_type == CDROM_BUS_ATAPI) || (bus_type == CDROM_BUS_SCSI)) && ((cdrom_drive_types[j].bus_type == bus_type) || (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { - QString name = tr(cdrom_getname(j)); + QString name = CDROMName(j); Models::AddEntry(modelType, name, j); if ((cdrom[cdromIdx].bus_type == bus_type) && (cdrom[cdromIdx].type == j)) selectedTypeRow = eligibleRows; @@ -246,7 +258,6 @@ SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) { uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); - uint8_t speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); int type = current.siblingAtColumn(2).data(Qt::UserRole).toInt(); ui->comboBoxBus->setCurrentIndex(-1); @@ -260,7 +271,14 @@ SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) if (!match.isEmpty()) ui->comboBoxChannel->setCurrentIndex(match.first().row()); + int speed = cdrom_get_speed(type); + if (speed == -1) { + speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); + ui->comboBoxSpeed->setEnabled(true); + } else + ui->comboBoxSpeed->setEnabled(false); ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1); + ui->comboBoxCDROMType->setCurrentIndex(type); enableCurrentlySelectedChannel(); } @@ -351,7 +369,7 @@ SettingsFloppyCDROM::on_comboBoxBus_activated(int) if (((bus_type == CDROM_BUS_ATAPI) || (bus_type == CDROM_BUS_SCSI)) && ((cdrom_drive_types[j].bus_type == bus_type) || (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { - QString name = tr(cdrom_getname(j)); + QString name = CDROMName(j); Models::AddEntry(modelType, name, j); if ((cdrom[cdromIdx].bus_type == bus_type) && (cdrom[cdromIdx].type == j)) selectedTypeRow = eligibleRows; @@ -401,9 +419,22 @@ SettingsFloppyCDROM::on_comboBoxChannel_activated(int) void SettingsFloppyCDROM::on_comboBoxCDROMType_activated(int) { + int type = ui->comboBoxCDROMType->currentData().toUInt(); + setCDROMType(ui->tableViewCDROM->model(), ui->tableViewCDROM->selectionModel()->currentIndex(), - ui->comboBoxCDROMType->currentData().toUInt()); + type); ui->tableViewCDROM->resizeColumnsToContents(); ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + + int speed = cdrom_get_speed(type); + if (speed == -1) { + speed = ui->comboBoxSpeed->currentData().toUInt(); + ui->comboBoxSpeed->setEnabled(true); + } else + ui->comboBoxSpeed->setEnabled(false); + ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1); + + auto idx = ui->tableViewCDROM->selectionModel()->currentIndex(); + setCDROMSpeed(ui->tableViewCDROM->model(), idx.siblingAtColumn(1), speed); } diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index 4f6811ff1..e679dafa5 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -55,7 +55,7 @@ normalize_hd_list() memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); for (uint8_t i = 0; i < HDD_NUM; i++) { - if (temp_hdd[i].bus != HDD_BUS_DISABLED) { + if (temp_hdd[i].bus_type != HDD_BUS_DISABLED) { memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); j++; } @@ -79,14 +79,14 @@ addRow(QAbstractItemModel *model, hard_disk_t *hd) int row = model->rowCount(); model->insertRow(row); - QString busName = Harddrives::BusChannelName(hd->bus, hd->channel); + 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), hd->bus, DataBus); - model->setData(model->index(row, ColumnBus), hd->bus, DataBusPrevious); + 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); model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannelPrevious); - Harddrives::busTrackClass->device_track(1, DEV_HDD, hd->bus, hd->channel); + Harddrives::busTrackClass->device_track(1, DEV_HDD, hd->bus_type, hd->channel); QString fileName = hd->fn; if (fileName.startsWith(userPath, Qt::CaseInsensitive)) { model->setData(model->index(row, ColumnFilename), fileName.mid(userPath.size())); @@ -120,7 +120,7 @@ SettingsHarddisks::SettingsHarddisks(QWidget *parent) ui->tableView->setModel(model); for (int i = 0; i < HDD_NUM; i++) { - if (hdd[i].bus > 0) { + if (hdd[i].bus_type > 0) { addRow(model, &hdd[i]); } } @@ -153,7 +153,7 @@ SettingsHarddisks::save() int rows = model->rowCount(); for (int i = 0; i < rows; ++i) { auto idx = model->index(i, ColumnBus); - hdd[i].bus = idx.data(DataBus).toUInt(); + hdd[i].bus_type = idx.data(DataBus).toUInt(); hdd[i].channel = idx.data(DataBusChannel).toUInt(); hdd[i].tracks = idx.siblingAtColumn(ColumnCylinders).data().toUInt(); hdd[i].hpc = idx.siblingAtColumn(ColumnHeads).data().toUInt(); @@ -313,11 +313,11 @@ addDriveFromDialog(Ui::SettingsHarddisks *ui, const HarddiskDialog &dlg) hard_disk_t hd; memset(&hd, 0, sizeof(hd)); - hd.bus = dlg.bus(); - hd.channel = dlg.channel(); - hd.tracks = dlg.cylinders(); - hd.hpc = dlg.heads(); - hd.spt = dlg.sectors(); + hd.bus_type = dlg.bus(); + hd.channel = dlg.channel(); + hd.tracks = dlg.cylinders(); + hd.hpc = dlg.heads(); + hd.spt = dlg.sectors(); strncpy(hd.fn, fn.data(), sizeof(hd.fn) - 1); hd.speed_preset = dlg.speed(); diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 9d82d68cc..271f7226f 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -19,32 +19,28 @@ #define UNICODE #define BITMAP WINDOWS_BITMAP #include -#include #undef BITMAP #include -#include #include "ntddcdrm.h" #include "ntddscsi.h" +#ifdef ENABLE_IOCTL_LOG #include -#include +#endif #include #include #include #include #include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/scsi_device.h> #include <86box/cdrom.h> -#include <86box/plat_unused.h> -#include <86box/plat_cdrom.h> +#include <86box/log.h> +#include <86box/plat_cdrom_ioctl.h> -/* 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) - -typedef struct win_cdrom_ioctl_t { +typedef struct ioctl_t { + cdrom_t *dev; + void *log; + int is_dvd; + int has_audio; + int32_t tracks_num; int toc_valid; uint8_t cur_toc[65536]; CDROM_READ_TOC_EX cur_read_toc_ex; @@ -52,109 +48,112 @@ typedef struct win_cdrom_ioctl_t { uint8_t cur_rti[65536]; HANDLE handle; WCHAR path[256]; - WCHAR old_path[256]; -} win_cdrom_ioctl_t; +} ioctl_t; -#ifdef ENABLE_WIN_CDROM_IOCTL_LOG -int win_cdrom_ioctl_do_log = ENABLE_WIN_CDROM_IOCTL_LOG; +static void ioctl_read_toc(ioctl_t *ioctl); +static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format, + uint8_t *buffer, uint32_t *info); + +#ifdef ENABLE_IOCTL_LOG +int ioctl_do_log = ENABLE_IOCTL_LOG; void -win_cdrom_ioctl_log(const char *fmt, ...) +ioctl_log(void *priv, const char *fmt, ...) { - va_list ap; - - if (win_cdrom_ioctl_do_log) { + if (ioctl_do_log) { + va_list ap; va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define win_cdrom_ioctl_log(fmt, ...) +# define ioctl_log(priv, fmt, ...) #endif +/* Internal functions. */ static void -plat_cdrom_close_handle(win_cdrom_ioctl_t *ioctl) +ioctl_close_handle(const ioctl_t *ioctl) { if (ioctl->handle != NULL) CloseHandle(ioctl->handle); } static int -plat_cdrom_open(void *local) +ioctl_open_handle(ioctl_t *ioctl) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - - plat_cdrom_close_handle(local); - + ioctl_log(ioctl->log, "ioctl->path = \"%ls\"\n", ioctl->path); ioctl->handle = CreateFileW((LPCWSTR) ioctl->path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - win_cdrom_ioctl_log("handle=%p, error=%x\n", ioctl->handle, (unsigned int) GetLastError()); + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, NULL); + + ioctl_log(ioctl->log, "handle=%p, error=%x\n", + ioctl->handle, (unsigned int) GetLastError()); return (ioctl->handle != INVALID_HANDLE_VALUE); } static int -plat_cdrom_load(void *local) +ioctl_load(ioctl_t *ioctl) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; + int ret = 0; - plat_cdrom_close(local); - - ioctl->handle = CreateFileW((LPCWSTR) ioctl->path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - win_cdrom_ioctl_log("handle=%p, error=%x\n", ioctl->handle, (unsigned int) GetLastError()); - if (ioctl->handle != INVALID_HANDLE_VALUE) { + if (ioctl_open_handle(ioctl)) { long size; - DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, (LPDWORD) &size, NULL); - return 1; + DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA, + NULL, 0, NULL, 0, + (LPDWORD) &size, NULL); + ret = 1; + ioctl_close_handle(ioctl); + + ioctl_read_toc(ioctl); } - return 0; + + return ret; } static int -plat_cdrom_read_normal_toc(win_cdrom_ioctl_t *ioctl, uint8_t *toc_buf) +ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) { long size = 0; PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; + ioctl->tracks_num = 0; memset(toc_buf, 0x00, 65536); cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536); - if (ioctl->blocks_num != 0) { - memset(ioctl->cur_rti, 0x00, ioctl->blocks_num * 11); - ioctl->blocks_num = 0; - } ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC; - win_cdrom_ioctl_log("cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format); + 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 = 0; + ioctl->cur_read_toc_ex.SessionTrack = 1; - plat_cdrom_open(ioctl); - int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535, - cur_full_toc, 65535, (LPDWORD) &size, NULL); - plat_cdrom_close(ioctl); - win_cdrom_ioctl_log("temp = %i\n", temp); + 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) { - int length = ((cur_full_toc->Length[0] << 8) | cur_full_toc->Length[1]) + 2; + 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; } free(cur_full_toc); -#ifdef ENABLE_WIN_CDROM_IOCTL_LOG +#ifdef ENABLE_IOCTL_LOG PCDROM_TOC toc = (PCDROM_TOC) toc_buf; - const int tracks_num = (((toc->Length[0] << 8) | toc->Length[1]) - 2) / 8; - win_cdrom_ioctl_log("%i tracks: %02X %02X %02X %02X\n", - tracks_num, toc_buf[0], toc_buf[1], toc_buf[2], toc_buf[3]); + 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]); - for (int i = 0; i < tracks_num; i++) { - uint8_t *t = (uint8_t *) &toc->TrackData[i]; - win_cdrom_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]); + for (int i = 0; i < ioctl->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]); } #endif @@ -162,427 +161,626 @@ plat_cdrom_read_normal_toc(win_cdrom_ioctl_t *ioctl, uint8_t *toc_buf) } static void -plat_cdrom_read_raw_toc(win_cdrom_ioctl_t *ioctl) +ioctl_read_raw_toc(ioctl_t *ioctl) { - long size = 0; - PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; + 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); + ioctl->is_dvd = (ioctl_read_dvd_structure(ioctl, 0, 0, buffer, NULL) > 0); + free(buffer); + + ioctl->has_audio = 0; + ioctl->blocks_num = 0; memset(ioctl->cur_rti, 0x00, 65536); cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536); - if (ioctl->blocks_num != 0) { - memset(ioctl->cur_rti, 0x00, ioctl->blocks_num * 11); - ioctl->blocks_num = 0; - } ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC; - win_cdrom_ioctl_log("cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format); + 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 = 0; + ioctl->cur_read_toc_ex.SessionTrack = 1; - plat_cdrom_open(ioctl); - int status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535, - cur_full_toc, 65535, (LPDWORD) &size, NULL); - plat_cdrom_close(ioctl); - win_cdrom_ioctl_log("status = %i\n", status); + 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->blocks_num = (((cur_full_toc->Length[0] << 8) | cur_full_toc->Length[1]) - 2) / 11; + if ((status == 0) && (ioctl->tracks_num >= 1)) { + /* + This is needed because in some circumstances (eg. a DVD .MDS + mounted in Daemon Tools), reading the raw TOC fails but + 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]); + + rti[0].adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf); + rti[0].point = 0xa0; + rti[0].pm = toc->FirstTrack; + + rti[1].adr_ctl = rti[0].adr_ctl; + rti[1].point = 0xa1; + rti[1].pm = toc->LastTrack; + + 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]; + + ioctl->blocks_num = 3; + + for (int i = 0; i < (ioctl->tracks_num - 1); i++) { + raw_track_info_t *crt = &(rti[ioctl->blocks_num]); + + ct = &(toc->TrackData[i]); + + 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) { + 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); } -#ifdef ENABLE_WIN_CDROM_IOCTL_LOG - uint8_t *u = (uint8_t *) cur_full_toc; + if (ioctl->blocks_num) for (int i = 0; i < ioctl->tracks_num; i++) { + const raw_track_info_t *crt = &(rti[i]); - win_cdrom_ioctl_log("%i blocks: %02X %02X %02X %02X\n", - ioctl->blocks_num, u[0], u[1], u[2], u[3]); + if ((crt->point >= 1) && (crt->point <= 99) && !(crt->adr_ctl & 0x04)) { + ioctl->has_audio = 1; + break; + } + } + +#ifdef ENABLE_IOCTL_LOG + uint8_t *u = (uint8_t *) cur_full_toc; + + ioctl_log(ioctl->log, "%i blocks: %02X %02X %02X %02X\n", + ioctl->blocks_num, u[0], u[1], u[2], u[3]); - raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; for (int i = 0; i < ioctl->blocks_num; i++) { uint8_t *t = (uint8_t *) &rti[i]; - win_cdrom_ioctl_log("Block %03i: %02X %02X %02X %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], t[8], t[9], t[10]); + ioctl_log(ioctl->log, "Block %03i: %02X %02X %02X %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], t[8], + t[9], t[10]); } #endif free(cur_full_toc); } -void -plat_cdrom_get_raw_track_info(void *local, int *num, raw_track_info_t *rti) +static void +ioctl_read_toc(ioctl_t *ioctl) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; + if (!ioctl->toc_valid) { + ioctl->toc_valid = 1; + (void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc); + 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; + int track = -1; + + for (int i = (ioctl->blocks_num - 1); i >= 0; i--) { + const raw_track_info_t *ct = &(rti[i]); + const uint32_t start = (ct->pm * 60 * 75) + (ct->ps * 75) + ct->pf - 150; + + ioctl_log(ioctl->log, "ioctl_get_track(): ct: %02X, %08X\n", + ct->point, start); + + if ((ct->point >= 1) && (ct->point <= 99) && (sector >= start)) { + track = i; + ioctl_log(ioctl->log, "ioctl_get_track(): found track: %i\n", i); + break; + } + } + + return track; +} + +static int +ioctl_is_track_audio(const ioctl_t *ioctl, const uint32_t pos) +{ + const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; + int ret = 0; + + ioctl_read_toc((ioctl_t *) ioctl); + + if (ioctl->has_audio && !ioctl->is_dvd) { + const int track = ioctl_get_track(ioctl, pos); + const int control = rti[track].adr_ctl; + + ret = !(control & 0x04); + + ioctl_log(ioctl->log, "ioctl_is_track_audio(%08X, %02X): %i\n", pos, track, ret); + } + + return ret; +} + +/* Shared functions. */ +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; + + ioctl_read_toc((ioctl_t *) ioctl); + + if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 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 = 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); + + 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); + } + + return ret; +} + +static void +ioctl_get_raw_track_info(const void *local, int *num, uint8_t *rti) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; *num = ioctl->blocks_num; memcpy(rti, ioctl->cur_rti, ioctl->blocks_num * 11); } -static void -plat_cdrom_read_toc(win_cdrom_ioctl_t *ioctl) +static int +ioctl_is_track_pre(const void *local, const uint32_t sector) { - if (!ioctl->toc_valid) { - ioctl->toc_valid = 1; - (void) plat_cdrom_read_normal_toc(ioctl, ioctl->cur_toc); - plat_cdrom_read_raw_toc(ioctl); + const ioctl_t *ioctl = (const ioctl_t *) local; + const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; + int ret = 0; + + ioctl_read_toc((ioctl_t *) ioctl); + + if (ioctl->has_audio && !ioctl->is_dvd) { + const int track = ioctl_get_track(ioctl, sector); + const int control = rti[track].adr_ctl; + + ret = control & 0x01; + + ioctl_log(ioctl->log, "ioctl_is_track_pre(%08X, %02X): %i\n", sector, track, ret); } -} - -int -plat_cdrom_is_track_audio(void *local, uint32_t sector) -{ - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - int control = 0; - uint32_t cur_addr = 0; - uint32_t next_addr = 0; - - plat_cdrom_read_toc(ioctl); - - for (int c = 0; toc->TrackData[c].TrackNumber != 0xaa; c++) { - PTRACK_DATA cur_td = &toc->TrackData[c]; - PTRACK_DATA next_td = &toc->TrackData[c + 1]; - - cur_addr = MSFtoLBA(cur_td->Address[1], cur_td->Address[2], cur_td->Address[3]) - 150; - next_addr = MSFtoLBA(next_td->Address[1], next_td->Address[2], next_td->Address[3]) - 150; - - win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, A: %08X, S: %08X\n", - toc->FirstTrack, toc->LastTrack, cur_td->TrackNumber, c, - cur_td->Control, cur_addr, sector); - - if ((cur_td->TrackNumber >= toc->FirstTrack) && (cur_td->TrackNumber <= toc->LastTrack) && - (sector >= cur_addr) && (sector < next_addr)) { - control = cur_td->Control; - break; - } - } - - const int ret = !(control & 0x04); - - win_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); return ret; } -int -plat_cdrom_is_track_pre(void *local, uint32_t sector) +static int +ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - int control = 0; - uint32_t cur_addr = 0; - uint32_t next_addr = 0; + typedef struct SCSI_PASS_THROUGH_DIRECT_BUF { + SCSI_PASS_THROUGH_DIRECT spt; + ULONG Filler; + UCHAR SenseBuf[64]; + } SCSI_PASS_THROUGH_DIRECT_BUF; - plat_cdrom_read_toc(ioctl); + const ioctl_t * ioctl = (const ioctl_t *) local; + const raw_track_info_t * rti = (raw_track_info_t *) ioctl->cur_rti; + unsigned long int unused = 0; + const int sc_offs = (sector == 0xffffffff) ? 0 : 2352; + int len = (sector == 0xffffffff) ? 16 : 2368; + int m = 0; + int s = 0; + int f = 0; + uint32_t lba = sector; + int ret; + SCSI_PASS_THROUGH_DIRECT_BUF req; - for (int c = 0; toc->TrackData[c].TrackNumber != 0xaa; c++) { - PTRACK_DATA cur_td = &toc->TrackData[c]; - PTRACK_DATA next_td = &toc->TrackData[c + 1]; + ioctl_open_handle((ioctl_t *) ioctl); - cur_addr = MSFtoLBA(cur_td->Address[1], cur_td->Address[2], cur_td->Address[3]) - 150; - next_addr = MSFtoLBA(next_td->Address[1], next_td->Address[2], next_td->Address[3]) - 150; + if (ioctl->is_dvd) { + int track; - win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, A: %08X, S: %08X\n", - toc->FirstTrack, toc->LastTrack, cur_td->TrackNumber, c, - cur_td->Control, cur_addr, sector); + req.spt.DataTransferLength = 0; + ret = 0; - if ((cur_td->TrackNumber >= toc->FirstTrack) && (cur_td->TrackNumber <= toc->LastTrack) && - (sector >= cur_addr) && (sector < next_addr)) { - control = cur_td->Control; - break; + if (lba == 0xffffffff) { + lba = ioctl->dev->seek_pos; + track = ioctl_get_track(ioctl, lba); + + if (track != -1) { + req.spt.DataTransferLength = len; + ret = 1; + } + } else { + len = COOKED_SECTOR_SIZE; + track = ioctl_get_track(ioctl, lba); + + if (track != -1) { + DWORD newPos = SetFilePointer(ioctl->handle, (long) lba * COOKED_SECTOR_SIZE, + 0, FILE_BEGIN); + + if (newPos != 0xffffffff) + ret = ReadFile(ioctl->handle, &(buffer[16]), + COOKED_SECTOR_SIZE, (LPDWORD) &req.spt.DataTransferLength, + NULL); + } } + + if (ret && (req.spt.DataTransferLength >= len) && (track != -1)) { + const raw_track_info_t *ct = &(rti[track]); + const uint32_t start = (ct->pm * 60 * 75) + (ct->ps * 75) + ct->pf; + + m = s = f = 0; + + /* Construct sector header and sub-header. */ + if (sector != 0xffffffff) { + /* Sync bytes. */ + buffer[0] = 0x00; + memset(&(buffer[1]), 0xff, 10); + buffer[11] = 0x00; + + /* Sector header. */ + FRAMES_TO_MSF(lba + 150, &m, &s, &f); + buffer[12] = bin2bcd(m); + buffer[13] = bin2bcd(s); + buffer[14] = bin2bcd(f); + + /* Mode 1 data. */ + buffer[15] = 0x01; + } + + /* Construct Q. */ + buffer[sc_offs + 0] = (ct->adr_ctl >> 4) | ((ct->adr_ctl & 0xf) << 4); + buffer[sc_offs + 1] = bin2bcd(ct->point); + buffer[sc_offs + 2] = 1; + FRAMES_TO_MSF((int32_t) (lba + 150 - start), &m, &s, &f); + buffer[sc_offs + 3] = bin2bcd(m); + buffer[sc_offs + 4] = bin2bcd(s); + buffer[sc_offs + 5] = bin2bcd(f); + FRAMES_TO_MSF(lba + 150, &m, &s, &f); + buffer[sc_offs + 7] = bin2bcd(m); + buffer[sc_offs + 8] = bin2bcd(s); + buffer[sc_offs + 9] = bin2bcd(f); + } + } else { + memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF)); + req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); + req.spt.PathId = 0; + req.spt.TargetId = 1; + req.spt.Lun = 0; + req.spt.CdbLength = 12; + req.spt.DataIn = SCSI_IOCTL_DATA_IN; + req.spt.SenseInfoLength = sizeof(req.SenseBuf); + req.spt.DataTransferLength = len; + req.spt.TimeOutValue = 6; + req.spt.DataBuffer = buffer; + req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf); + + /* Fill in the CDB. */ + req.spt.Cdb[0] = 0xbe; /* READ CD */ + req.spt.Cdb[1] = 0x00; + req.spt.Cdb[2] = (sector >> 24) & 0xff; + req.spt.Cdb[3] = (sector >> 16) & 0xff; + req.spt.Cdb[4] = (sector >> 8) & 0xff; + req.spt.Cdb[5] = sector & 0xff; /* Starting Logical Block Address. */ + req.spt.Cdb[6] = 0x00; + req.spt.Cdb[7] = 0x00; + req.spt.Cdb[8] = 0x01; /* Transfer Length. */ + /* If sector is FFFFFFFF, only return the subchannel. */ + req.spt.Cdb[9] = (sector == 0xffffffff) ? 0x00 : 0xf8; + req.spt.Cdb[10] = 0x02; + req.spt.Cdb[11] = 0x00; + DWORD length = sizeof(SCSI_PASS_THROUGH_DIRECT_BUF); + +#ifdef ENABLE_IOCTL_LOG + uint8_t *cdb = (uint8_t *) req.spt.Cdb; + ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X\n", + ioctl->dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); +#endif + + ret = DeviceIoControl(ioctl->handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, + &req, length, + &req, length, &unused, NULL); } - const int ret = (control & 0x01); + ioctl_log(ioctl->log, "ioctl_read_sector: ret = %d, req.spt.DataTransferLength = %lu\n", + ret, req.spt.DataTransferLength); + ioctl_log(ioctl->log, "Sense: %08X, %08X\n", req.spt.SenseInfoLength, req.spt.SenseInfoOffset); + if (req.spt.SenseInfoLength >= 16) { + uint8_t *cdb = (uint8_t *) req.SenseBuf; + if ((cdb[2] == 0x03) && (cdb[12] == 0x11)) + /* Treat this as an error to corectly indicate CIRC error to the guest. */ + ret = 0; + ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[ 2], cdb[ 3], cdb[ 4], cdb[ 5], cdb[ 6], cdb[ 7]); + ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]); + } - win_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); + ret = (!!ret > 0) ? (req.spt.DataTransferLength >= len) : -1; + ioctl_log(ioctl->log, "iocl_read_sector: final ret = %i\n", ret); + + /* Construct raw subchannel data from Q only. */ + if ((ret > 0) && (req.spt.DataTransferLength >= len)) + for (int i = 11; i >= 0; i--) + 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; } -uint32_t -plat_cdrom_get_track_start(void *local, uint32_t sector, uint8_t *attr, uint8_t *track) +static uint8_t +ioctl_get_track_type(const void *local, const uint32_t sector) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - uint32_t cur_addr = 0; - uint32_t next_addr = 0; + ioctl_t * ioctl = (ioctl_t *) local; + int track = ioctl_get_track(ioctl, sector); + raw_track_info_t * rti = (raw_track_info_t *) ioctl->cur_rti; + const raw_track_info_t *trk = &(rti[track]); + uint8_t ret = 0x00; - plat_cdrom_read_toc(ioctl); + if (ioctl_is_track_audio(ioctl, sector)) + ret = CD_TRACK_AUDIO; + else if (track != -1) for (int i = 0; i < ioctl->blocks_num; i++) { + const raw_track_info_t *ct = &(rti[i]); + const raw_track_info_t *nt = &(rti[i + 1]); - for (int c = 0; toc->TrackData[c].TrackNumber != 0xaa; c++) { - PTRACK_DATA cur_td = &toc->TrackData[c]; - PTRACK_DATA next_td = &toc->TrackData[c + 1]; + if (ct->point == 0xa0) { + uint8_t first = ct->pm; + uint8_t last = nt->pm; - cur_addr = MSFtoLBA(cur_td->Address[1], cur_td->Address[2], cur_td->Address[3]) - 150; - next_addr = MSFtoLBA(next_td->Address[1], next_td->Address[2], next_td->Address[3]) - 150; - - win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, a: %02X, A: %08X, S: %08X\n", - toc->FirstTrack, toc->LastTrack, cur_td->TrackNumber, c, - cur_td->Control, cur_td->Adr, cur_addr, sector); - - if ((cur_td->TrackNumber >= toc->FirstTrack) && (cur_td->TrackNumber <= toc->LastTrack) && - (sector >= cur_addr) && (sector < next_addr)) { - *track = cur_td->TrackNumber; - *attr = cur_td->Control; - *attr |= ((cur_td->Adr << 4) & 0xf0); - break; + if ((trk->point >= first) && (trk->point <= last)) { + ret = ct->ps; + break; + } } } - win_cdrom_ioctl_log("plat_cdrom_get_track_start(%08X): %i\n", sector, cur_addr); - - return cur_addr; + return ret; } -uint32_t -plat_cdrom_get_last_block(void *local) +static uint32_t +ioctl_get_last_block(const void *local) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - uint32_t lb = 0; - uint32_t address = 0; + const ioctl_t *ioctl = (const ioctl_t *) local; + const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc; + uint32_t lb = 0; - plat_cdrom_read_toc(ioctl); + ioctl_read_toc((ioctl_t *) ioctl); for (int c = 0; c <= toc->LastTrack; c++) { - PTRACK_DATA td = &toc->TrackData[c]; - - address = MSFtoLBA(td->Address[1], td->Address[2], td->Address[3]) - 150; + 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; } - win_cdrom_ioctl_log("LBCapacity=%d\n", lb); + ioctl_log(ioctl->log, "LBCapacity=%d\n", lb); return lb; } -int -plat_cdrom_ext_medium_changed(void *local) -{ - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - uint8_t new_toc_buf[65536] = { 0 }; - PCDROM_TOC new_toc = (PCDROM_TOC) new_toc_buf; - int ret = 0; - int temp = plat_cdrom_read_normal_toc(ioctl, new_toc_buf); - PTRACK_DATA cur_ltd = &toc->TrackData[toc->LastTrack]; - - if (temp != 0) - plat_cdrom_read_raw_toc(ioctl); - - PTRACK_DATA new_ltd = &new_toc->TrackData[new_toc->LastTrack]; - - if (temp == 0) - /* There has been some kind of error - not a medium change, but a not ready - condition. */ - ret = -1; - else if (!ioctl->toc_valid || (memcmp(ioctl->path, ioctl->old_path, sizeof(ioctl->path)) != 0)) { - /* Changed to a different host drive - we already detect such medium changes. */ - ioctl->toc_valid = 1; - memcpy(toc, new_toc, 65535); - if (memcmp(ioctl->path, ioctl->old_path, sizeof(ioctl->path)) != 0) - memcpy(ioctl->old_path, ioctl->path, sizeof(ioctl->path)); - } else if (memcmp(&(new_ltd->Address[1]), &(cur_ltd->Address[1]), 3)) { - /* The TOC has changed. */ - ioctl->toc_valid = 1; - memcpy(toc, new_toc, 65535); - if (memcmp(ioctl->path, ioctl->old_path, sizeof(ioctl->path)) != 0) - memcpy(ioctl->old_path, ioctl->path, sizeof(ioctl->path)); - ret = 1; - } - - win_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); - - return ret; -} - -/* This replaces both Info and EndInfo, they are specified by a variable. */ -int -plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) -{ - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - - plat_cdrom_read_toc(ioctl); - - if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 1))) { - win_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i)\n", track); - return 0; - } - - PTRACK_DATA td = &toc->TrackData[track - 1]; - - start->min = td->Address[1]; - start->sec = td->Address[2]; - start->fr = td->Address[3]; - - *track_num = td->TrackNumber; - *attr = td->Control; - *attr |= ((td->Adr << 4) & 0xf0); - - win_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n", - track, start->min, start->sec, start->fr, *track_num, *attr); - - return 1; -} - -/* TODO: See if track start is adjusted by 150 or not. */ -int -plat_cdrom_get_audio_sub(void *local, UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track, uint8_t *index, - TMSF *rel_pos, TMSF *abs_pos) -{ - win_cdrom_ioctl_t * ioctl = (win_cdrom_ioctl_t *) local; - CDROM_SUB_Q_DATA_FORMAT insub; - SUB_Q_CHANNEL_DATA sub; - long size = 0; - - insub.Format = IOCTL_CDROM_CURRENT_POSITION; - - plat_cdrom_open(ioctl); - DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), &sub, sizeof(sub), - (LPDWORD) &size, NULL); - plat_cdrom_close(ioctl); - - if (sub.CurrentPosition.TrackNumber < 1) - return 0; - - *track = sub.CurrentPosition.TrackNumber; - *attr = sub.CurrentPosition.Control; - *attr |= ((sub.CurrentPosition.ADR << 4) & 0xf0); - *index = sub.CurrentPosition.IndexNumber; - - rel_pos->min = sub.CurrentPosition.TrackRelativeAddress[1]; - rel_pos->sec = sub.CurrentPosition.TrackRelativeAddress[2]; - rel_pos->fr = sub.CurrentPosition.TrackRelativeAddress[3]; - abs_pos->min = sub.CurrentPosition.AbsoluteAddress[1]; - abs_pos->sec = sub.CurrentPosition.AbsoluteAddress[2]; - abs_pos->fr = sub.CurrentPosition.AbsoluteAddress[3]; - - win_cdrom_ioctl_log("plat_cdrom_get_audio_sub(): %02i, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", - *track, *attr, *index, rel_pos->min, rel_pos->sec, rel_pos->fr, abs_pos->min, abs_pos->sec, - abs_pos->fr); - - return 1; -} - -int -plat_cdrom_get_sector_size(void *local, UNUSED(uint32_t sector)) -{ - win_cdrom_ioctl_t * ioctl = (win_cdrom_ioctl_t *) local; - long size; - DISK_GEOMETRY dgCDROM; - - plat_cdrom_open(ioctl); - DeviceIoControl(ioctl->handle, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &dgCDROM, sizeof(dgCDROM), - (LPDWORD) &size, NULL); - plat_cdrom_close(ioctl); - - win_cdrom_ioctl_log("BytesPerSector=%d\n", dgCDROM.BytesPerSector); - return dgCDROM.BytesPerSector; -} - -int -plat_cdrom_read_sector(void *local, uint8_t *buffer, uint32_t sector) +static int +ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t format, + uint8_t *buffer, uint32_t *info) { typedef struct SCSI_PASS_THROUGH_DIRECT_BUF { SCSI_PASS_THROUGH_DIRECT spt; ULONG Filler; - UCHAR SenseBuf[32]; + UCHAR SenseBuf[64]; } SCSI_PASS_THROUGH_DIRECT_BUF; - win_cdrom_ioctl_t * ioctl = (win_cdrom_ioctl_t *) local; - int sc_offs = (sector == 0xffffffff) ? 0 : 2352; + const ioctl_t * ioctl = (const ioctl_t *) local; unsigned long int unused = 0; - int ret; + const int len = 2052; SCSI_PASS_THROUGH_DIRECT_BUF req; - memset(&req, 0x00, sizeof(req)); - req.Filler = 0; + 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; + req.spt.TargetId = 1; + req.spt.Lun = 0; req.spt.CdbLength = 12; req.spt.DataIn = SCSI_IOCTL_DATA_IN; - req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf); req.spt.SenseInfoLength = sizeof(req.SenseBuf); + req.spt.DataTransferLength = len; req.spt.TimeOutValue = 6; - req.spt.DataTransferLength = 2368; req.spt.DataBuffer = buffer; + req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf); /* Fill in the CDB. */ - req.spt.Cdb[0] = 0xbe; /* READ CD */ - req.spt.Cdb[1] = 0x00; /* DAP = 0, Any Sector Type. */ - req.spt.Cdb[2] = (sector >> 24) & 0xff; - req.spt.Cdb[3] = (sector >> 16) & 0xff; - req.spt.Cdb[4] = (sector >> 8) & 0xff; - req.spt.Cdb[5] = sector & 0xff; /* Starting Logical Block Address. */ - req.spt.Cdb[6] = 0x00; - req.spt.Cdb[7] = 0x00; - req.spt.Cdb[8] = 0x01; /* Transfer Length. */ - /* If sector is FFFFFFFF, only return the subchannel. */ - req.spt.Cdb[9] = (sector == 0xffffffff) ? 0x00 : 0xf8; - req.spt.Cdb[10] = 0x02; + req.spt.Cdb[0] = 0xad; + req.spt.Cdb[1] = 0x00; + req.spt.Cdb[2] = 0x00; + req.spt.Cdb[3] = 0x00; + req.spt.Cdb[4] = 0x00; + req.spt.Cdb[5] = 0x00; + req.spt.Cdb[6] = layer; /* Layer Number */ + req.spt.Cdb[7] = format; /* Format */ + req.spt.Cdb[8] = 0x08; /* Allocation Length */ + req.spt.Cdb[9] = 0x04; + req.spt.Cdb[10] = 0x00; /* AGID */ req.spt.Cdb[11] = 0x00; - plat_cdrom_open(ioctl); - ret = DeviceIoControl(ioctl->handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, &req, sizeof(req), &req, sizeof(req), - &unused, NULL); - plat_cdrom_close(ioctl); + DWORD length = sizeof(SCSI_PASS_THROUGH_DIRECT_BUF); - /* Construct raw subchannel data from Q only. */ - if (ret && (req.spt.DataTransferLength >= 2368)) - for (int i = 11; i >= 0; i--) - for (int j = 7; j >= 0; j--) - buffer[2352 + (i * 8) + j] = ((buffer[sc_offs + i] >> (7 - j)) & 0x01) << 6; +#ifdef ENABLE_IOCTL_LOG + uint8_t *cdb = (uint8_t *) req.spt.Cdb; + ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); +#endif - win_cdrom_ioctl_log("plat_cdrom_read_scsi_direct: ret = %d, req.spt.DataTransferLength = %lu\n", - ret, req.spt.DataTransferLength); - win_cdrom_ioctl_log("Sense: %08X, %08X\n", req.spt.SenseInfoLength, req.spt.SenseInfoOffset); - return ret && (req.spt.DataTransferLength >= 2368); + int ret = DeviceIoControl(ioctl->handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, + &req, length, + &req, length, + &unused, NULL); + + ioctl_log(ioctl->log, "ioctl_read_dvd_structure(): ret = %d, " + "req.spt.DataTransferLength = %lu\n", + ret, req.spt.DataTransferLength); + ioctl_log(ioctl->log, "Sense: %08X, %08X\n", req.spt.SenseInfoLength, + req.spt.SenseInfoOffset); + + if (req.spt.SenseInfoLength >= 16) { + uint8_t *sb = (uint8_t *) req.SenseBuf; + /* Return sense to the host as is. */ + ret = -((sb[2] << 16) | (sb[12] << 8) | sb[13]); + if (info != NULL) + *info = *(uint32_t *) &(sb[3]); + ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n", + sb[0], sb[1], sb[ 2], sb[ 3], sb[ 4], sb[ 5], sb[ 6], sb[ 7]); + ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n", + sb[8], sb[9], sb[10], sb[11], sb[12], sb[13], sb[14], sb[15]); + } else + ret = ret ? (req.spt.DataTransferLength >= len) : 0; + + ioctl_close_handle((ioctl_t *) ioctl); + + return ret; } -void -plat_cdrom_eject(void *local) +static int +ioctl_is_dvd(const void *local) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - long size; + const ioctl_t *ioctl = (const ioctl_t *) local; - plat_cdrom_open(ioctl); - DeviceIoControl(ioctl->handle, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, (LPDWORD) &size, NULL); - plat_cdrom_close(ioctl); + return ioctl->is_dvd; } -void -plat_cdrom_close(void *local) +static int +ioctl_has_audio(const void *local) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; + const ioctl_t *ioctl = (const ioctl_t *) local; - plat_cdrom_close_handle(ioctl); + return ioctl->has_audio; +} + +static int +ioctl_ext_medium_changed(void *local) +{ + ioctl_t * ioctl = (ioctl_t *) local; + const CDROM_TOC *toc = (CDROM_TOC *) ioctl->cur_toc; + const TRACK_DATA *ltd = &toc->TrackData[toc->LastTrack]; + const uint32_t old_addr = *(uint32_t *) ltd->Address; + const int temp = ioctl_read_normal_toc(ioctl, ioctl->cur_toc); + int ret = 0; + + if (temp == 1) { + if (ioctl->toc_valid && ((*(uint32_t *) ltd->Address) != old_addr)) { + /* The TOC has changed. */ + ioctl->toc_valid = 0; + ret = 1; + } + + if (!ioctl->toc_valid) { + ioctl->toc_valid = 1; + ioctl_read_raw_toc(ioctl); + } + } else { + /* There has been some kind of error - not a medium change, but a not ready + condition. */ + ret = -1; + } + + if (ret == 1) { + if (ioctl->is_dvd) + ioctl->dev->cd_status = CD_STATUS_DVD; + else + ioctl->dev->cd_status = ioctl->has_audio ? CD_STATUS_STOPPED : + CD_STATUS_DATA_ONLY; + + ioctl->dev->cdrom_capacity = ioctl_get_last_block(ioctl); + } else if (ret == -1) + ioctl->dev->cd_status = CD_STATUS_EMPTY; + + ioctl_log(ioctl->log, "ioctl_ext_medium_changed(): %i\n", ret); + + return ret; +} + +static void +ioctl_close(void *local) +{ + ioctl_t *ioctl = (ioctl_t *) local; + + ioctl_close_handle(ioctl); ioctl->handle = NULL; + + ioctl_log(ioctl->log, "Log closed\n"); + + log_close(ioctl->log); + ioctl->log = NULL; } -int -plat_cdrom_set_drive(void *local, const char *drv) +static const cdrom_ops_t ioctl_ops = { + ioctl_get_track_info, + ioctl_get_raw_track_info, + ioctl_is_track_pre, + ioctl_read_sector, + ioctl_get_track_type, + ioctl_get_last_block, + ioctl_read_dvd_structure, + ioctl_is_dvd, + ioctl_has_audio, + ioctl_ext_medium_changed, + ioctl_close +}; + +/* Public functions. */ +void * +ioctl_open(cdrom_t *dev, const char *drv) { - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; + ioctl_t *ioctl = (ioctl_t *) calloc(1, sizeof(ioctl_t)); - plat_cdrom_close(ioctl); + if (ioctl != NULL) { + char n[1024] = { 0 }; - memcpy(ioctl->old_path, ioctl->path, sizeof(ioctl->path)); - memset(ioctl->path, 0x00, sizeof(ioctl->path)); + sprintf(n, "CD-ROM %i IOCtl", dev->id + 1); + ioctl->log = log_open(n); - wsprintf(ioctl->path, L"%S", drv); - win_cdrom_ioctl_log("Path is %S\n", ioctl->path); + memset(ioctl->path, 0x00, sizeof(ioctl->path)); - ioctl->toc_valid = 0; + wsprintf(ioctl->path, L"%S", &(drv[8])); + ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); - plat_cdrom_load(ioctl); + ioctl->dev = dev; + ioctl->toc_valid = 0; - return 1; -} - -int -plat_cdrom_get_local_size(void) -{ - return sizeof(win_cdrom_ioctl_t); + dev->ops = &ioctl_ops; + + ioctl_load(ioctl); + } + + return ioctl; } diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 91773c62c..65604758d 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -9,46 +9,41 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * - * * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ -#include #include #include +#ifdef ENABLE_SCSI_CDROM_LOG +#include +#endif #include #include #include #include -#include -#define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/config.h> #include <86box/timer.h> +#include <86box/cdrom.h> #include <86box/device.h> -#include <86box/scsi.h> -#include <86box/scsi_device.h> +#include <86box/log.h> #include <86box/machine.h> #include <86box/nvr.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/sound.h> #include <86box/plat.h> -#include <86box/ui.h> -#include <86box/cdrom.h> +#include <86box/scsi.h> +#include <86box/scsi_device.h> +#include <86box/hdc_ide.h> #include <86box/scsi_cdrom.h> -#include <86box/version.h> +#include <86box/ui.h> #define IDE_ATAPI_IS_EARLY id->sc->pad0 #pragma pack(push, 1) typedef struct gesn_cdb_t { - uint8_t opcode; - uint8_t polled; - uint8_t reserved2[2]; - uint8_t class; + uint8_t opcode; + uint8_t polled; + uint8_t reserved2[2]; + uint8_t class; uint8_t reserved3[2]; uint16_t len; uint8_t control; @@ -61,411 +56,192 @@ typedef struct gesn_event_header_t { } gesn_event_header_t; #pragma pack(pop) -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +// clang-format off +/* + Table of all SCSI commands and their flags, needed for the new disc change / + not ready handler. + */ uint8_t scsi_cdrom_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, /* 0x02 */ - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - 0, 0, 0, 0, /* 0x04-0x07 */ - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, 0, /* 0x09-0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - 0, /* 0x0C */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0x0D */ - 0, 0, 0, 0, /* 0x0E-0x11 */ - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, /* 0x14 */ - IMPLEMENTED, /* 0x15 */ - 0, 0, 0, 0, /* 0x16-0x19 */ - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, 0, /* 0x1C-0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, /* 0x1F-0x21*/ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0x22*/ - 0, 0, /* 0x23-0x24 */ - IMPLEMENTED | CHECK_READY, /* 0x25 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0x26 */ - 0, /* 0x27 */ - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, 0, /* 0x29-0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - 0, 0, 0, /* 0x2C-0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ - 0, 0, /* 0x40-0x41 */ - IMPLEMENTED | CHECK_READY, /* 0x42 */ - IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS - NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ - IMPLEMENTED | CHECK_READY, /* 0x44 */ - IMPLEMENTED | CHECK_READY, /* 0x45 */ - IMPLEMENTED | ALLOW_UA, /* 0x46 */ - IMPLEMENTED | CHECK_READY, /* 0x47 */ - IMPLEMENTED | CHECK_READY, /* 0x48 */ - IMPLEMENTED | CHECK_READY, /* 0x49 */ - IMPLEMENTED | ALLOW_UA, /* 0x4A */ - IMPLEMENTED | CHECK_READY, /* 0x4B */ - 0, 0, /* 0x4C-0x4D */ - IMPLEMENTED | CHECK_READY, /* 0x4E */ - 0, 0, /* 0x4F-0x50 */ - IMPLEMENTED | CHECK_READY, /* 0x51 */ - IMPLEMENTED | CHECK_READY, /* 0x52 */ - 0, 0, /* 0x53-0x54 */ - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, /* 0x56-0x59 */ - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, /* 0x5B-0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ - 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ - IMPLEMENTED | CHECK_READY, /* 0xA5 */ - 0, 0, /* 0xA6-0xA7 */ - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - IMPLEMENTED | CHECK_READY, /* 0xA9 */ - 0, 0, 0, /* 0xAA-0xAC */ - IMPLEMENTED | CHECK_READY, /* 0xAD */ - 0, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, /* 0xB0-0xB3 */ - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ - 0, 0, 0, /* 0xB5-0xB7 */ - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ - IMPLEMENTED | CHECK_READY, /* 0xB9 */ - IMPLEMENTED | CHECK_READY, /* 0xBA */ - IMPLEMENTED, /* 0xBB */ - IMPLEMENTED | CHECK_READY, /* 0xBC */ - IMPLEMENTED, /* 0xBD */ - IMPLEMENTED | CHECK_READY, /* 0xBE */ - IMPLEMENTED | CHECK_READY, /* 0xBF */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC0 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC1 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC3 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC4 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC5 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC6 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC7 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC8 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC9 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCA */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCB */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCC */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD7 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xD8 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xD9 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDA */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDB */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDC */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDD */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDE */ - 0, /* 0xDF */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE0 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE1 */ - 0, /* 0xE2 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE3 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE4 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE5 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE6 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE7 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE8 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE9 */ - 0, /* 0xEA */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xEB */ - 0, /* 0xEC */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xED */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xEE */ - 0, /* 0xEF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ + [0x00] = IMPLEMENTED | CHECK_READY, + [0x01] = IMPLEMENTED | ALLOW_UA | SCSI_ONLY, + [0x03] = IMPLEMENTED | ALLOW_UA, + [0x08] = IMPLEMENTED | CHECK_READY, + [0x0b] = IMPLEMENTED | CHECK_READY, + [0x0d] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x12] = IMPLEMENTED | ALLOW_UA, + [0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x15] = IMPLEMENTED, + [0x1a] = IMPLEMENTED, + [0x1b] = IMPLEMENTED | CHECK_READY, + [0x1e] = IMPLEMENTED | CHECK_READY, + [0x22] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x25] = IMPLEMENTED | CHECK_READY, + [0x26] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x28] = IMPLEMENTED | CHECK_READY, + [0x2b] = IMPLEMENTED | CHECK_READY, + [0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x42] = IMPLEMENTED | CHECK_READY, + /* + Read TOC/PMA/ATIP - can get through UNIT_ATTENTION, per VIDE-CDD.SYS. + + NOTE: The ATAPI reference says otherwise, but I think this is a question of + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. + */ + [0x43 ... 0x45] = IMPLEMENTED | CHECK_READY, + [0x46] IMPLEMENTED | ALLOW_UA, + [0x47 ... 0x49] = IMPLEMENTED | CHECK_READY, + [0x4a] = IMPLEMENTED | ALLOW_UA, + [0x4b] = IMPLEMENTED | CHECK_READY, + [0x4e] = IMPLEMENTED | CHECK_READY, + [0x51 ... 0x52] = IMPLEMENTED | CHECK_READY, + [0x55] = IMPLEMENTED, + [0x5a] = IMPLEMENTED, + [0xa5] = IMPLEMENTED | CHECK_READY, + [0xa8 ... 0xa9] = IMPLEMENTED | CHECK_READY, + [0xad] = IMPLEMENTED, + [0xaf] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xb4] = IMPLEMENTED | CHECK_READY | ATAPI_ONLY, + [0xb8] = IMPLEMENTED | CHECK_READY | ATAPI_ONLY, + [0xb9 ... 0xba] = IMPLEMENTED | CHECK_READY, + [0xbb] = IMPLEMENTED, + [0xbc] = IMPLEMENTED | CHECK_READY, + [0xbd] = IMPLEMENTED, + [0xbe ... 0xbf] = IMPLEMENTED | CHECK_READY, + [0xc0 ... 0xcd] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xd8 ... 0xde] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xe0 ... 0xe1] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xe3 ... 0xe9] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xeb] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xed ... 0xee] = IMPLEMENTED | CHECK_READY | SCSI_ONLY }; -static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_UNIT_ATN_PAGE | GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_FORMAT_DEVICE_PAGE | GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); -static uint64_t scsi_cdrom_mode_sense_page_flags_sony = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_CDROM_PAGE_SONY | GPMODEP_CDROM_AUDIO_PAGE_SONY | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); -static uint64_t scsi_cdrom_drive_status_page_flags = ((1ULL << 0x01ULL) | (1ULL << 0x02ULL) | (1ULL << 0x0fULL) | GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_ms_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_CDROM_PAGE | + GPMODEP_CDROM_AUDIO_PAGE | (1ULL << 0x0fULL) | + GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_ms_page_flags_scsi = (GPMODEP_UNIT_ATN_PAGE | GPMODEP_R_W_ERROR_PAGE | + GPMODEP_DISCONNECT_PAGE | GPMODEP_FORMAT_DEVICE_PAGE | + GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | + (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | + GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_ms_page_flags_sony_scsi = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | + GPMODEP_CDROM_PAGE_SONY | GPMODEP_CDROM_AUDIO_PAGE_SONY | + (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | + GPMODEP_ALL_PAGES); + +static uint64_t scsi_cdrom_drive_status_page_flags = ((1ULL << 0x01ULL) | (1ULL << 0x02ULL) | + (1ULL << 0x0fULL) | GPMODEP_ALL_PAGES); static const mode_sense_pages_t scsi_cdrom_drive_status_pages = { - {{ 0, 0 }, - { 0x01, 0, 2, 0x0f, 0xbf }, /*Drive Status Data Format*/ - { 0x02, 0, 1, 0 }, /*Audio Play Status Format*/ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }} + { [0x01] = { 0x01, 0x00, 0x02, 0x0f, 0xbf }, /* Drive Status Data Format */ + [0x02] = { 0x02, 0x00, 0x01, 0x00 } } /* Audio Play Status Format */ }; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = { - {{ 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 7, 0, 0x3f, 1, 0x0d, 3, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} +static const mode_sense_pages_t scsi_cdrom_ms_pages_default = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00 }, + [0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x4b }, + [0x0e] = { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0x0e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, + 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x0f] = { 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0x07, 0x00, 0x7f, 0x01, 0x0d, 0x03, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x02, 0xc2, + 0x00, 0x00, 0x00, 0x00 } } }; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { - {{ GPMODE_UNIT_ATN_PAGE, 6, 0, 0, 0, 0, 0, 0 }, /*Guess-work*/ - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 5, 4, 0, 128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 7, 0, 0x3f, 1, 0x0d, 3, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} +static const mode_sense_pages_t scsi_cdrom_ms_pages_default_scsi = { + { [0x00] = { GPMODE_UNIT_ATN_PAGE, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Guesswork */ + [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x03] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x4b }, + [0x0e] = { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0x0e, 0x05, 0x04, 0x00, 0x80, 0x00, 0x4b, + 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x0f] = { 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0x07, 0x00, 0x7f, 0x01, 0x0d, 0x03, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x02, 0xc2, + 0x00, 0x00, 0x00, 0x00 } } }; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_sony_scsi = { - {{ 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE_SONY, 2, 0, 5 }, - { GPMODE_CDROM_AUDIO_PAGE_SONY | 0x80, 0xE, 5, 0, 0, 0, 0, 0, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 5, 4, 0, 128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 7, 0, 0x3f, 1, 0x0d, 3, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} +static const mode_sense_pages_t scsi_cdrom_ms_pages_default_sony_scsi = { + { { 0, 0 }, + [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x08] = { GPMODE_CDROM_PAGE_SONY, 0x02, 0x00, 0x05 }, + [0x09] = { GPMODE_CDROM_AUDIO_PAGE_SONY | 0x80, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x4b }, + [0x0e] = { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0x0e, 0x05, 0x04, 0x00, 0x80, 0x00, 0x4b, + 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x0f] = { 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0x07, 0x00, 0x7f, 0x01, 0x0d, 0x03, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x02, 0xc2, + 0x00, 0x00, 0x00, 0x00 } } }; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { - {{ GPMODE_UNIT_ATN_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, /*Guess-work*/ - { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, - { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} +static const mode_sense_pages_t scsi_cdrom_ms_pages_changeable = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0e] = { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0f] = { 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 } } }; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable_sony = { - {{ 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE_SONY, 2, 0xFF, 0xFF }, - { GPMODE_CDROM_AUDIO_PAGE_SONY | 0x80, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} +static const mode_sense_pages_t scsi_cdrom_ms_pages_changeable_scsi = { + { [0x00] = { GPMODE_UNIT_ATN_PAGE, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, /* Guesswork */ + [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x03] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0e] = { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0f] = { 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 } } }; +static const mode_sense_pages_t scsi_cdrom_ms_pages_changeable_sony_scsi = { + { [0x01] = { GPMODE_R_W_ERROR_PAGE, 0x06, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x02] = { GPMODE_DISCONNECT_PAGE, 0x0e, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, + [0x08] = { GPMODE_CDROM_PAGE_SONY, 0x02, 0xff, 0xff }, + [0x09] = { GPMODE_CDROM_AUDIO_PAGE_SONY | 0x80, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0d] = { GPMODE_CDROM_PAGE, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0e] = { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + [0x0f] = { 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x2a] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } } +}; +// clang-format on + static gesn_cdb_t *gesn_cdb; static gesn_event_header_t *gesn_event_header; @@ -480,22 +256,21 @@ static void scsi_cdrom_init(scsi_cdrom_t *dev); int scsi_cdrom_do_log = ENABLE_SCSI_CDROM_LOG; static void -scsi_cdrom_log(const char *format, ...) +scsi_cdrom_log(void *priv, const char *format, ...) { - va_list ap; - if (scsi_cdrom_do_log) { + va_list ap; va_start(ap, format); - pclog_ex(format, ap); + log_out(priv, format, ap); va_end(ap); } } #else -# define scsi_cdrom_log(format, ...) +# define scsi_cdrom_log(priv, format, ...) #endif static void -scsi_cdrom_set_callback(scsi_cdrom_t *dev) +scsi_cdrom_set_callback(const scsi_cdrom_t *dev) { if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI)) ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); @@ -504,47 +279,51 @@ scsi_cdrom_set_callback(scsi_cdrom_t *dev) static void scsi_cdrom_init(scsi_cdrom_t *dev) { - if (!dev) - return; + if (dev != NULL) { + /* Do a reset (which will also rezero it). */ + scsi_cdrom_reset((scsi_common_t *) dev); - /* Do a reset (which will also rezero it). */ - scsi_cdrom_reset((scsi_common_t *) dev); + /* Configure the drive. */ + dev->requested_blocks = 1; - /* Configure the drive. */ - dev->requested_blocks = 1; + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= CDROM_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < CDROM_BUS_SCSI) + dev->drv->bus_mode |= 1; + scsi_cdrom_log(dev->log, "Bus type %i, bus mode %i\n", + dev->drv->bus_type, dev->drv->bus_mode); - dev->drv->bus_mode = 0; - if (dev->drv->bus_type >= CDROM_BUS_ATAPI) - dev->drv->bus_mode |= 2; - if (dev->drv->bus_type < CDROM_BUS_SCSI) - dev->drv->bus_mode |= 1; - scsi_cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", - dev->id, dev->drv->bus_type, dev->drv->bus_mode); + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + /* NEC only */ + if (dev->drv->is_early) + dev->tf->status = READY_STAT | DSC_STAT; + else + 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_info = 0x00000000; + dev->drv->cd_status &= ~CD_STATUS_TRANSITION; + dev->drv->cur_speed = dev->drv->real_speed; + scsi_cdrom_mode_sense_load(dev); - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - /* NEC only */ - if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) - dev->tf->status = READY_STAT | DSC_STAT; - else - 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; - dev->drv->cur_speed = dev->drv->speed; - scsi_cdrom_mode_sense_load(dev); - if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) - scsi_cdrom_drive_status_load(dev); + const char *vendor = cdrom_get_vendor(dev->drv->type); + + if ((dev->drv->bus_type == CDROM_BUS_SCSI) && !strcmp(vendor, "PIONEER")) + scsi_cdrom_drive_status_load(dev); + } } /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int -scsi_cdrom_current_mode(scsi_cdrom_t *dev) +scsi_cdrom_current_mode(const scsi_cdrom_t *dev) { if (dev->drv->bus_type == CDROM_BUS_SCSI) return 2; else if (dev->drv->bus_type == CDROM_BUS_ATAPI) { - scsi_cdrom_log("CD-ROM %i: ATAPI drive, setting to %s\n", dev->id, + scsi_cdrom_log(dev->log, "ATAPI drive, setting to %s\n", (dev->tf->features & 1) ? "DMA" : "PIO", dev->id); return (dev->tf->features & 1) ? 2 : 1; @@ -554,50 +333,25 @@ scsi_cdrom_current_mode(scsi_cdrom_t *dev) } static uint32_t -scsi_cdrom_get_channel(void *priv, int channel) +scsi_cdrom_get_channel(void *priv, const int channel) { const scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; - uint32_t ret; + uint32_t ret = channel + 1; - if (!dev) - return channel + 1; - - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - ret = dev->ms_pages_saved_sony.pages[dev->sony_vendor ? - GPMODE_CDROM_AUDIO_PAGE_SONY : GPMODE_CDROM_AUDIO_PAGE] - [channel ? 10 : 8]; - break; - default: - ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; - break; - } + if (dev != NULL) + ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; return ret; } static uint32_t -scsi_cdrom_get_volume(void *priv, int channel) +scsi_cdrom_get_volume(void *priv, const int channel) { const scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; - uint32_t ret; + uint32_t ret = 255; - if (!dev) - return 255; - - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - ret = dev->ms_pages_saved_sony.pages[dev->sony_vendor ? GPMODE_CDROM_AUDIO_PAGE_SONY : - GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; - break; - default: - ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; - break; - } + if (dev != NULL) + ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; return ret; } @@ -605,129 +359,90 @@ scsi_cdrom_get_volume(void *priv, int channel) static void scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) { - FILE *fp; - char file_name[512]; + char file_name[512] = { 0 }; - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - memset(&dev->ms_pages_saved_sony, 0, sizeof(mode_sense_pages_t)); - memcpy(&dev->ms_pages_saved_sony, &scsi_cdrom_mode_sense_pages_default_sony_scsi, - sizeof(mode_sense_pages_t)); + memset(&dev->ms_pages_saved, 0x00, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &dev->ms_pages_default, + sizeof(mode_sense_pages_t)); - memset(file_name, 0, 512); - sprintf(file_name, "scsi_cdrom_%02i_mode_sense_sony_bin", dev->id); - fp = plat_fopen(nvr_path(file_name), "rb"); - if (fp) { - if (fread(dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, - 0x10, fp) != 0x10) - fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); - fclose(fp); - } - break; - default: - memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default_scsi, - sizeof(mode_sense_pages_t)); - else - memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default, - sizeof(mode_sense_pages_t)); - - memset(file_name, 0, 512); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); - else - sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); - fp = plat_fopen(nvr_path(file_name), "rb"); - if (fp) { - if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp) != 0x10) - fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); - fclose(fp); - } - break; + if (dev->drv->bus_type == CDROM_BUS_SCSI) + sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); + FILE *fp = plat_fopen(nvr_path(file_name), "rb"); + if (fp) { + if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp) != 0x10) + log_fatal(dev->log, "scsi_cdrom_mode_sense_load(): Error reading data\n"); + (void) fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, + 0x10, fp); + fclose(fp); } } static void -scsi_cdrom_mode_sense_save(scsi_cdrom_t *dev) +scsi_cdrom_mode_sense_save(const scsi_cdrom_t *dev) { - FILE *fp; - char file_name[512]; + char file_name[512] = { 0 }; - memset(file_name, 0, 512); - - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - sprintf(file_name, "scsi_cdrom_%02i_mode_sense_sony_bin", dev->id); - fp = plat_fopen(nvr_path(file_name), "wb"); - if (fp) { - fwrite(dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, 0x10, fp); - fclose(fp); - } - break; - default: - if (dev->drv->bus_type == CDROM_BUS_SCSI) - sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); - else - sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); - fp = plat_fopen(nvr_path(file_name), "wb"); - if (fp) { - fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp); - fclose(fp); - } - break; + if (dev->drv->bus_type == CDROM_BUS_SCSI) + sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); + FILE *fp = plat_fopen(nvr_path(file_name), "wb"); + if (fp) { + fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp); + fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, 0x10, fp); + fclose(fp); } } -/*SCSI Drive Status (Pioneer only)*/ +/* SCSI Drive Status (Pioneer only). */ static void scsi_cdrom_drive_status_load(scsi_cdrom_t *dev) { - memset(&dev->ms_drive_status_pages_saved, 0, sizeof(mode_sense_pages_t)); - memcpy(&dev->ms_drive_status_pages_saved, &scsi_cdrom_drive_status_pages, sizeof(mode_sense_pages_t)); + memset(&dev->ms_drive_status_pages_saved, 0x00, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_drive_status_pages_saved, &scsi_cdrom_drive_status_pages, + sizeof(mode_sense_pages_t)); } static uint8_t -scsi_cdrom_drive_status_read(scsi_cdrom_t *dev, UNUSED(uint8_t page_control), uint8_t page, uint8_t pos) +scsi_cdrom_drive_status_read(const scsi_cdrom_t *dev, const uint8_t page, + const uint8_t pos) { return dev->ms_drive_status_pages_saved.pages[page][pos]; } static uint32_t -scsi_cdrom_drive_status(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t page) +scsi_cdrom_drive_status(const scsi_cdrom_t *dev, uint8_t *buf, uint8_t page) { - uint8_t page_control = (page >> 6) & 3; - uint16_t msplen; + uint32_t pos = 0; page &= 0x3f; for (uint8_t i = 0; i < 0x40; i++) { - if (page == i) { - if (scsi_cdrom_drive_status_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { - buf[pos++] = scsi_cdrom_drive_status_read(dev, page_control, i, 0); - msplen = (scsi_cdrom_drive_status_read(dev, page_control, i, 1) << 8); - msplen |= scsi_cdrom_drive_status_read(dev, page_control, i, 2); - buf[pos++] = (msplen >> 8) & 0xff; - buf[pos++] = msplen & 0xff; - scsi_cdrom_log("CD-ROM %i: DRIVE STATUS: Page [%02X] length %i\n", dev->id, i, msplen); - for (uint16_t j = 0; j < msplen; j++) { - if (i == 0x01) { - buf[pos++] = scsi_cdrom_drive_status_read(dev, page_control, i, 3 + j); - if (!(j & 1)) { /*MSB of Drive Status*/ - if (dev->drv->ops) /*Bit 11 of Drive Status, */ - buf[pos] &= ~0x08; /*Disc is present*/ - else - buf[pos] |= 0x08; /*Disc not present*/ - } - } else if ((i == 0x02) && (j == 0)) { - buf[pos++] = ((dev->drv->cd_status == CD_STATUS_PLAYING) ? 0x01 : 0x00); - } else - buf[pos++] = scsi_cdrom_drive_status_read(dev, page_control, i, 3 + j); - } + if ((page == i) && (scsi_cdrom_drive_status_page_flags & + (1LL << ((uint64_t) (page & 0x3f))))) { + buf[pos++] = scsi_cdrom_drive_status_read(dev, i, 0); + uint16_t len = (scsi_cdrom_drive_status_read(dev, i, 1) << 8); + len |= scsi_cdrom_drive_status_read(dev, i, 2); + buf[pos++] = (len >> 8) & 0xff; + buf[pos++] = len & 0xff; + scsi_cdrom_log(dev->log, "CD-ROM %i: DRIVE STATUS: Page [%02X] length %i\n", + i, len); + for (uint16_t j = 0; j < len; j++) { + if (i == 0x01) { + buf[pos++] = scsi_cdrom_drive_status_read(dev, i, 3 + j); + if (!(j & 1)) { /* MSB of Drive Status. */ + if (dev->drv->ops) /* Bit 11 of Drive Status, */ + buf[pos] &= ~0x08; /* Disc is present. */ + else + buf[pos] |= 0x08; /* Disc not present. */ + } + } else if ((i == 0x02) && (j == 0)) + buf[pos++] = ((dev->drv->cd_status == CD_STATUS_PLAYING) ? + 0x01 : 0x00); + else + buf[pos++] = scsi_cdrom_drive_status_read(dev, i, 3 + j); } } } @@ -737,52 +452,36 @@ scsi_cdrom_drive_status(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t p /*SCSI Mode Sense 6/10*/ static uint8_t -scsi_cdrom_mode_sense_read(scsi_cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +scsi_cdrom_mode_sense_read(const scsi_cdrom_t *dev, const uint8_t pgctl, + const uint8_t page, const uint8_t pos) { - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved_sony.pages[page][pos]; - case 1: - return scsi_cdrom_mode_sense_pages_changeable_sony.pages[page][pos]; - case 2: - return scsi_cdrom_mode_sense_pages_default_sony_scsi.pages[page][pos]; + uint8_t ret = 0; - default: - break; - } + switch (pgctl) { + case 0: case 3: + ret = dev->ms_pages_saved.pages[page][pos]; break; + + case 1: + ret = dev->ms_pages_changeable.pages[page][pos]; + break; + + case 2: + ret = dev->ms_pages_default.pages[page][pos]; + break; + default: - switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved.pages[page][pos]; - case 1: - return scsi_cdrom_mode_sense_pages_changeable.pages[page][pos]; - case 2: - if (dev->drv->bus_type == CDROM_BUS_SCSI) - return scsi_cdrom_mode_sense_pages_default_scsi.pages[page][pos]; - else - return scsi_cdrom_mode_sense_pages_default.pages[page][pos]; + break; + } - default: - break; - } - break; - } - - return 0; + return ret; } static uint32_t -scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +scsi_cdrom_mode_sense(const scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, + uint8_t page, const uint8_t block_descriptor_len) { - uint8_t page_control = (page >> 6) & 3; - uint8_t msplen; + const uint8_t pgctl = (page >> 6) & 3; page &= 0x3f; @@ -799,45 +498,45 @@ scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t pag for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { - if (scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { - buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 0); - msplen = scsi_cdrom_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - scsi_cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + if (dev->ms_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { + const uint8_t msplen = scsi_cdrom_mode_sense_read(dev, pgctl, i, 1); + + buf[pos++] = scsi_cdrom_mode_sense_read(dev, pgctl, i, 0); + buf[pos++] = msplen; + + scsi_cdrom_log(dev->log, "MODE SENSE: Page [%02X] length %i\n", + i, msplen); + for (uint8_t j = 0; j < msplen; j++) { - /* If we are returning changeable values, always return them from the page, - so they are all correctly. */ - if (page_control == 1) - buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j); + /* + If we are returning changeable values, always return + them from the page, so they are all correct. + */ + if (pgctl == 1) + buf[pos++] = scsi_cdrom_mode_sense_read(dev, pgctl, i, 2 + j); else { if ((i == GPMODE_CAPABILITIES_PAGE) && (j == 4)) { - buf[pos] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j) & 0x1f; - /* The early CD-ROM drives we emulate (NEC CDR-260 for ATAPI and - early vendor SCSI CD-ROM models) are caddy drives, the later - ones are tray drives. */ - if (dev->drv->bus_type == CDROM_BUS_SCSI) - buf[pos++] |= ((dev->drv->type == CDROM_TYPE_86BOX_100) ? 0x20 : 0x00); - else - buf[pos++] |= ((dev->drv->type == CDROM_TYPE_NEC_260_100) || - ((dev->drv->type == CDROM_TYPE_NEC_260_101)) ? 0x00 : 0x20); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { + buf[pos] = scsi_cdrom_mode_sense_read(dev, pgctl, i, 2 + j) & 0x1f; + buf[pos++] |= (cdrom_is_caddy(dev->drv->type) ? 0x00 : 0x20); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && + (j <= 7)) { if (j & 1) - buf[pos++] = ((dev->drv->speed * 176) & 0xff); + buf[pos++] = ((dev->drv->real_speed * 176) & 0xff); else - buf[pos++] = ((dev->drv->speed * 176) >> 8); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 8) && (j <= 9) && - (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403)) { - if (j & 1) - buf[pos++] = ((dev->drv->speed * 176) & 0xff); - else - buf[pos++] = ((dev->drv->speed * 176) >> 8); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { + buf[pos++] = ((dev->drv->real_speed * 176) >> 8); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && + (j <= 13)) { if (j & 1) buf[pos++] = ((dev->drv->cur_speed * 176) & 0xff); else buf[pos++] = ((dev->drv->cur_speed * 176) >> 8); - } else - buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j); + } else if (dev->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); + else + buf[pos++] = scsi_cdrom_mode_sense_read(dev, pgctl, + i, 2 + j); } } } @@ -848,15 +547,17 @@ scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t pag } static void -scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) +scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, const int block_len) { - int32_t bt; int32_t min_len = 0; - double dlen; + int32_t bt; dev->max_transfer_len = dev->tf->request_length; - /* For media access commands, make sure the requested DRQ length matches the block length. */ + /* + For media access commands, make sure the requested DRQ length + matches the block length. + */ switch (dev->current_cdb[0]) { case 0x08: case 0x28: @@ -865,21 +566,26 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) case 0xbe: /* Round it to the nearest (block length) bytes. */ if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { - /* 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 of a sector. One of the drivers that - relies on the correctness of this behavior is MTMCDAI.SYS (the Mitsumi CD-ROM driver) for DOS - which uses the READ CD command to read data on some CD types. */ + /* + 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 + of a sector. One of the drivers that relies on the correctness of this + behavior is MTMCDAI.SYS (the Mitsumi CD-ROM driver) for DOS which uses + the READ CD command to read data on some CD types. + */ /* Round to sector length. */ - dlen = ((double) dev->max_transfer_len) / ((double) block_len); + const double dlen = ((double) dev->max_transfer_len) / ((double) block_len); dev->max_transfer_len = ((uint16_t) floor(dlen)) * block_len; } else { /* Round it to the nearest 2048 bytes. */ - dev->max_transfer_len = (dev->max_transfer_len >> 11) << 11; + 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 - all the requested blocks. */ + /* + Make sure total length is not bigger than sum of the lengths of + all the requested blocks. + */ bt = (dev->requested_blocks * block_len); if (len > bt) len = bt; @@ -901,10 +607,16 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) dev->packet_len = len; break; } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + /* + If the DRQ length is odd, and the total remaining length is bigger, + make sure it's even. + */ if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) dev->max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + /* + If the DRQ length is smaller or equal in size to the total remaining length, + set it to that. + */ if (!dev->max_transfer_len) dev->max_transfer_len = 65534; @@ -939,8 +651,7 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) static void scsi_cdrom_command_common(scsi_cdrom_t *dev) { - double bytes_per_second = 0.0; - double period; + const uint8_t cmd = dev->current_cdb[0]; /* MAP: BUSY_STAT, no DRQ, phase 1. */ dev->tf->status = BUSY_STAT; @@ -948,19 +659,22 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) dev->tf->pos = 0; dev->callback = 0; - scsi_cdrom_log("CD-ROM %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed); + scsi_cdrom_log(dev->log, "Current speed: %ix\n", dev->drv->cur_speed); if (dev->packet_status == PHASE_COMPLETE) dev->callback = 0; else { - switch (dev->current_cdb[0]) { + 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("CD-ROM %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); + scsi_cdrom_log(dev->log, "Seek period: %" PRIu64 " us\n", + (uint64_t) period); dev->callback += period; scsi_cdrom_set_callback(dev); return; @@ -969,11 +683,12 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) case 0xa8: /* Seek time is in us. */ period = cdrom_seek_time(dev->drv); - scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); - scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us, speed: %" PRIu64 " bytes per second, " - "should be: %" PRIu64 " bytes per second\n", - dev->id, (uint64_t) period, (uint64_t) (1000000.0 / period), + 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; @@ -990,54 +705,17 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; + case 0xc0 ... 0xc3: case 0xc6 ... 0xc7: - switch (dev->drv->type) { - case CDROM_TYPE_TOSHIBA_XM_3433 ... CDROM_TYPE_TOSHIBA_SDM1401_1008: - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - } - case 0xc0: - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - } - case 0xc1: - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_PIONEER_DRM604X_2403: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - } - case 0xc2 ... 0xc3: - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_PIONEER_DRM604X_2403: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - if (dev->current_cdb[0] == 0xc2) - dev->callback += 40.0; - /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - } case 0xdd ... 0xde: - switch (dev->drv->type) { - case CDROM_TYPE_NEC_25_10a ... CDROM_TYPE_NEC_464_105: - /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; + 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: @@ -1050,9 +728,11 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) } period = 1000000.0 / bytes_per_second; - scsi_cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", + (uint64_t) period); period = period * (double) (dev->packet_len); - scsi_cdrom_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", + (uint64_t) period); dev->callback += period; } scsi_cdrom_set_callback(dev); @@ -1096,16 +776,18 @@ scsi_cdrom_command_write_dma(scsi_cdrom_t *dev) scsi_cdrom_command_common(dev); } -/* id = Current CD-ROM device ID; +/* + dev = Pointer to current CD-ROM device; len = Total transfer length; block_len = Length of a single block (it matters because media access commands on ATAPI); alloc_len = Allocated transfer length; - direction = Transfer direction (0 = read from host, 1 = write to host). */ + direction = Transfer direction (0 = read from host, 1 = write to host). + */ static void scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int alloc_len, int direction) { - scsi_cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, + scsi_cdrom_log(dev->log, "Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); dev->tf->pos = 0; if (alloc_len >= 0) { @@ -1135,72 +817,74 @@ scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int al } } - scsi_cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, - dev->tf->phase); + scsi_cdrom_log(dev->log, "Status: %i, cylinder %i, packet length: %i, position: %i, " + "phase: %i\n", dev->packet_status, dev->tf->request_length, dev->packet_len, + dev->tf->pos, dev->tf->phase); } static void scsi_cdrom_sense_clear(scsi_cdrom_t *dev, UNUSED(int command)) { scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = 0; + scsi_cdrom_info = 0x00000000; } static void -scsi_cdrom_set_phase(scsi_cdrom_t *dev, uint8_t phase) +scsi_cdrom_set_phase(const scsi_cdrom_t *dev, const uint8_t phase) { - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + const uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; - if (dev->drv->bus_type != CDROM_BUS_SCSI) - return; - - scsi_devices[scsi_bus][scsi_id].phase = phase; + if (dev->drv->bus_type == CDROM_BUS_SCSI) + scsi_devices[scsi_bus][scsi_id].phase = phase; } static void scsi_cdrom_cmd_error(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->tf->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; - dev->tf->status = READY_STAT | ERR_STAT; - dev->tf->phase = 3; - dev->tf->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * CDROM_TIME; - scsi_cdrom_set_callback(dev); - ui_sb_update_icon(SB_CDROM | dev->id, 0); - scsi_cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq); -} - -static void -scsi_cdrom_unit_attention(scsi_cdrom_t *dev) -{ - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; dev->callback = 50.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); ui_sb_update_icon(SB_CDROM | dev->id, 0); - scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION\n", dev->id); + scsi_cdrom_log(dev->log, "ERROR: %02X/%02X/%02X\n", scsi_cdrom_sense_key, + scsi_cdrom_asc, scsi_cdrom_ascq); } static void -scsi_cdrom_buf_alloc(scsi_cdrom_t *dev, uint32_t len) +scsi_cdrom_unit_attention(scsi_cdrom_t *dev) { - if (!dev->buffer) + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + ui_sb_update_icon(SB_CDROM | dev->id, 0); + scsi_cdrom_log(dev->log, "UNIT ATTENTION\n"); +} + +static void +scsi_cdrom_buf_alloc(scsi_cdrom_t *dev, const uint32_t len) +{ + if (dev->buffer == NULL) dev->buffer = (uint8_t *) malloc(len); - scsi_cdrom_log("CD-ROM %i: Allocated buffer length: %i, buffer = %p\n", dev->id, len, dev->buffer); + + scsi_cdrom_log(dev->log, "Allocated buffer length: %i, buffer = %p\n", + len, dev->buffer); } static void scsi_cdrom_buf_free(scsi_cdrom_t *dev) { if (dev->buffer) { - scsi_cdrom_log("CD-ROM %i: Freeing buffer...\n", dev->id); + scsi_cdrom_log(dev->log, "Freeing buffer...\n"); free(dev->buffer); dev->buffer = NULL; } @@ -1211,179 +895,218 @@ scsi_cdrom_bus_master_error(scsi_common_t *sc) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - scsi_cdrom_log("CD-ROM %i: Bus master error\n", dev->id); + scsi_cdrom_log(dev->log, "Bus master error\n"); scsi_cdrom_buf_free(dev); scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = 0; + scsi_cdrom_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); + scsi_cdrom_cmd_error(dev); +} + +static void +scsi_cdrom_error_common(scsi_cdrom_t *dev, uint8_t sense_key, uint8_t asc, uint8_t ascq, uint32_t info) +{ + scsi_cdrom_log(dev->log, "Medium not present\n"); + scsi_cdrom_sense_key = sense_key; + scsi_cdrom_asc = asc; + scsi_cdrom_ascq = ascq; + scsi_cdrom_info = info; scsi_cdrom_cmd_error(dev); } static void scsi_cdrom_not_ready(scsi_cdrom_t *dev) { - scsi_cdrom_log("CD-ROM %i: Medium not present\n", dev->id); + scsi_cdrom_log(dev->log, "Medium not present\n"); scsi_cdrom_sense_key = SENSE_NOT_READY; scsi_cdrom_asc = ASC_MEDIUM_NOT_PRESENT; scsi_cdrom_ascq = 0; + scsi_cdrom_info = 0x00000000; scsi_cdrom_cmd_error(dev); } static void scsi_cdrom_circ_error(scsi_cdrom_t *dev) { - scsi_cdrom_log("CD-ROM %i: CIRC unrecovered error\n", dev->id); + scsi_cdrom_log(dev->log, "CIRC unrecovered error\n"); scsi_cdrom_sense_key = SENSE_MEDIUM_ERROR; scsi_cdrom_asc = ASC_UNRECOVERED_READ_ERROR; scsi_cdrom_ascq = ASCQ_CIRC_UNRECOVERED_ERROR; + scsi_cdrom_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_cdrom_cmd_error(dev); } static void -scsi_cdrom_invalid_lun(scsi_cdrom_t *dev) +scsi_cdrom_invalid_lun(scsi_cdrom_t *dev, const uint8_t lun) { - scsi_cdrom_log("CD-ROM %i: Invalid LUN\n", dev->id); + scsi_cdrom_log(dev->log, "Invalid LUN\n"); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_INV_LUN; scsi_cdrom_ascq = 0; + scsi_cdrom_info = lun << 24; scsi_cdrom_cmd_error(dev); } static void -scsi_cdrom_illegal_opcode(scsi_cdrom_t *dev) +scsi_cdrom_illegal_opcode(scsi_cdrom_t *dev, const uint8_t opcode) { - scsi_cdrom_log("CD-ROM %i: Illegal opcode\n", dev->id); + scsi_cdrom_log(dev->log, "Illegal opcode\n"); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_ILLEGAL_OPCODE; scsi_cdrom_ascq = 0; + scsi_cdrom_info = opcode << 24; scsi_cdrom_cmd_error(dev); } static void scsi_cdrom_lba_out_of_range(scsi_cdrom_t *dev) { - scsi_cdrom_log("CD-ROM %i: LBA out of range\n", dev->id); + scsi_cdrom_log(dev->log, "LBA out of range\n"); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_LBA_OUT_OF_RANGE; scsi_cdrom_ascq = 0; + scsi_cdrom_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_cdrom_cmd_error(dev); } static void -scsi_cdrom_invalid_field(scsi_cdrom_t *dev) +scsi_cdrom_invalid_field(scsi_cdrom_t *dev, const uint32_t field) { - scsi_cdrom_log("CD-ROM %i: Invalid field in command packet\n", dev->id); + scsi_cdrom_log(dev->log, "Invalid field in command packet\n"); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; scsi_cdrom_ascq = 0; + scsi_cdrom_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); scsi_cdrom_cmd_error(dev); dev->tf->status = 0x53; } static void -scsi_cdrom_invalid_field_pl(scsi_cdrom_t *dev) +scsi_cdrom_invalid_field_pl(scsi_cdrom_t *dev, const uint32_t field) { - scsi_cdrom_log("CD-ROM %i: Invalid field in parameter list\n", dev->id); + scsi_cdrom_log(dev->log, "Invalid field in parameter list\n"); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; scsi_cdrom_ascq = 0; + scsi_cdrom_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); scsi_cdrom_cmd_error(dev); dev->tf->status = 0x53; } +static void +scsi_cdrom_incompatible_format(scsi_cdrom_t *dev, const uint32_t val) +{ + scsi_cdrom_log(dev->log, "Incompatible format\n"); + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_INCOMPATIBLE_FORMAT; + scsi_cdrom_ascq = 2; + scsi_cdrom_info = (val >> 24) | + ((val >> 16) << 8) | + ((val >> 8) << 16) | + ( val << 24); + scsi_cdrom_cmd_error(dev); +} + +static void +scsi_cdrom_data_phase_error(scsi_cdrom_t *dev, const uint32_t info) +{ + scsi_cdrom_log(dev->log, "Data phase error\n"); + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_DATA_PHASE_ERROR; + scsi_cdrom_ascq = 0; + scsi_cdrom_info = (info >> 24) | + ((info >> 16) << 8) | + ((info >> 8) << 16) | + ( info << 24); + scsi_cdrom_cmd_error(dev); +} + static void scsi_cdrom_illegal_mode(scsi_cdrom_t *dev) { - scsi_cdrom_log("CD-ROM %i: Illegal mode for this track\n", dev->id); + scsi_cdrom_log(dev->log, "Illegal mode for this track\n"); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; scsi_cdrom_ascq = 0; - scsi_cdrom_cmd_error(dev); -} - -static void -scsi_cdrom_incompatible_format(scsi_cdrom_t *dev) -{ - scsi_cdrom_log("CD-ROM %i: Incompatible format\n", dev->id); - scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_INCOMPATIBLE_FORMAT; - scsi_cdrom_ascq = 2; - scsi_cdrom_cmd_error(dev); -} - -static void -scsi_cdrom_data_phase_error(scsi_cdrom_t *dev) -{ - scsi_cdrom_log("CD-ROM %i: Data phase error\n", dev->id); - scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_DATA_PHASE_ERROR; - scsi_cdrom_ascq = 0; + scsi_cdrom_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_cdrom_cmd_error(dev); } static int -scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *len, int vendor_type) +scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int flags, + int32_t *len, const int vendor_type) { - int ret = 0; - int data_pos = 0; int temp_len = 0; - uint32_t cdsize = 0; + int ret = 0; - if (dev->drv->cd_status == CD_STATUS_EMPTY) { + if (dev->drv->cd_status == CD_STATUS_EMPTY) scsi_cdrom_not_ready(dev); - return 0; - } + else { + const uint32_t cdsize = dev->drv->cdrom_capacity; - 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); + scsi_cdrom_lba_out_of_range(dev); + ret = -1; + } else { + int data_pos = 0; - if (dev->sector_pos >= cdsize) { - scsi_cdrom_log("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, - dev->sector_pos, cdsize); - scsi_cdrom_lba_out_of_range(dev); - return -1; - } + dev->old_len = 0; + *len = 0; -/* FIXME: Temporarily disabled this because the Triones ATAPI DMA driver seems to - always request a 4-sector read but sets the DMA bus master to transfer less - data than that. */ -#if 0 - if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { - scsi_cdrom_log("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, - (dev->sector_pos + dev->sector_len - 1), cdsize); - scsi_cdrom_lba_out_of_range(dev); - return -1; - } -#endif + ret = 1; - dev->old_len = 0; - *len = 0; + 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); - 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); + data_pos += temp_len; + dev->old_len += temp_len; - data_pos += temp_len; - dev->old_len += temp_len; + *len += temp_len; - *len += temp_len; + if (ret == 0) { + scsi_cdrom_illegal_mode(dev); + break; + } - if (!ret) { - scsi_cdrom_illegal_mode(dev); - return 0; - } else if (ret < 0) { - scsi_cdrom_circ_error(dev); - return -1; + if (ret < 0) { + scsi_cdrom_circ_error(dev); + break; + } + } } } - return 1; + return ret; } static int -scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch, int vendor_type) +scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, const int vendor_type) { - int ret = 0; + int ret = 1; int msf = 0; - int type = 0; - int flags = 0; + int type = dev->sector_type; + int flags = dev->sector_flags; switch (dev->current_cdb[0]) { case GPCMD_READ_CD_MSF_OLD: @@ -1395,152 +1118,40 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch, int ven type = (dev->current_cdb[1] >> 2) & 7; flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); break; + case GPCMD_READ_HEADER: + type = 0x00; + flags = 0x20; + break; default: - type = 8; /* Internal type code indicating both Mode 1 and Mode 2 Form 1 are allowed. */ - flags = (dev->drv->sector_size == 2340) ? 0x78 : 0x10; + if (dev->sector_type == 0xff) { + scsi_cdrom_illegal_mode(dev); + ret = 0; + } break; } - if (!dev->sector_len) { - scsi_cdrom_command_complete(dev); - return -1; + if (ret) { + if (!dev->sector_len) { + scsi_cdrom_command_complete(dev); + return -1; + } + + 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); + + scsi_cdrom_log(dev->log, "Read %i bytes of blocks (ret = %i)...\n", *len, ret); } - scsi_cdrom_log("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); + if ((ret > 0) && (dev->current_cdb[0] != GPCMD_READ_HEADER)) { + dev->sector_pos += dev->requested_blocks; + dev->drv->seek_pos = dev->sector_pos; - ret = scsi_cdrom_read_data(dev, msf, type, flags, len, vendor_type); - - scsi_cdrom_log("Read %i bytes of blocks...\n", *len); - - if (ret == -1) - return ret; - else if (!ret || (!first_batch && (dev->old_len != *len))) { - if (!first_batch && (dev->old_len != *len)) - scsi_cdrom_illegal_mode(dev); - - return 0; + dev->sector_len -= dev->requested_blocks; } - dev->sector_pos += dev->requested_blocks; - dev->drv->seek_pos = dev->sector_pos; - dev->sector_len -= dev->requested_blocks; - return 1; -} - -/*SCSI Read DVD Structure*/ -static int -scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *packet, uint8_t *buf) -{ - int layer = packet[6]; - uint64_t total_sectors = 0; - - switch (format) { - case 0x00: /* Physical format information */ - if (dev->drv->cd_status == CD_STATUS_EMPTY) { - scsi_cdrom_not_ready(dev); - return 0; - } - - total_sectors = (uint64_t) dev->drv->cdrom_capacity; - - if (layer != 0) { - scsi_cdrom_invalid_field(dev); - return 0; - } - - total_sectors >>= 2; - if (total_sectors == 0) { - /* return -ASC_MEDIUM_NOT_PRESENT; */ - scsi_cdrom_not_ready(dev); - return 0; - } - - buf[4] = 18; /* Length of Layer Information */ - buf[5] = 0; - - buf[6] = 1; /* DVD-ROM, part version 1 */ - buf[7] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[8] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[9] = 0; /* default densities */ - - /* FIXME: 0x30000 per spec? */ - buf[10] = 0x00; - buf[11] = 0x03; - buf[12] = buf[13] = 0; /* start sector */ - - buf[14] = 0x00; - buf[15] = (total_sectors >> 16) & 0xff; /* end sector */ - buf[16] = (total_sectors >> 8) & 0xff; - buf[17] = total_sectors & 0xff; - - buf[18] = 0x00; - buf[19] = (total_sectors >> 16) & 0xff; /* l0 end sector */ - buf[20] = (total_sectors >> 8) & 0xff; - buf[21] = total_sectors & 0xff; - - /* 20 bytes of data + 4 byte header */ - return (20 + 4); - - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((4 + 2) >> 8) & 0xff; - buf[1] = (4 + 2) & 0xff; - - /* 4 byte header + 4 byte data */ - return (4 + 4); - - case 0x03: /* BCA information - invalid field for no BCA info */ - scsi_cdrom_invalid_field(dev); - return 0; - - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 + 2) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ - - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((20 + 4) >> 8) & 0xff; - buf[7] = (20 + 4) & 0xff; - - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - buf[10] = ((4 + 4) >> 8) & 0xff; - buf[11] = (4 + 4) & 0xff; - - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - buf[14] = ((188 + 4) >> 8) & 0xff; - buf[15] = (188 + 4) & 0xff; - - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - buf[18] = ((2048 + 4) >> 8) & 0xff; - buf[19] = (2048 + 4) & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[6] = ((16 + 2) >> 8) & 0xff; - buf[7] = (16 + 2) & 0xff; - - /* data written + 4 byte header */ - return (16 + 4); - - default: /* TODO: formats beyond DVD-ROM requires */ - scsi_cdrom_invalid_field(dev); - return 0; - } + return ret; } static void @@ -1554,16 +1165,16 @@ scsi_cdrom_insert(void *priv) if (dev->drv->ops == NULL) { dev->unit_attention = 0; dev->drv->cd_status = CD_STATUS_EMPTY; - scsi_cdrom_log("CD-ROM %i: Media removal\n", dev->id); + scsi_cdrom_log(dev->log, "Media removal\n"); } else if (dev->drv->cd_status & CD_STATUS_TRANSITION) { dev->unit_attention = 1; /* Turn off the medium changed status. */ dev->drv->cd_status &= ~CD_STATUS_TRANSITION; - scsi_cdrom_log("CD-ROM %i: Media insert\n", dev->id); + scsi_cdrom_log(dev->log, "Media insert\n"); } else { dev->unit_attention = 0; dev->drv->cd_status |= CD_STATUS_TRANSITION; - scsi_cdrom_log("CD-ROM %i: Media transition\n", dev->id); + scsi_cdrom_log(dev->log, "Media transition\n"); } } @@ -1578,80 +1189,76 @@ scsi_cdrom_ext_insert(void *priv, int ext_medium_changed) if ((dev->drv->ops == NULL) || (ext_medium_changed == -1)) { dev->unit_attention = 0; dev->drv->cd_status = CD_STATUS_EMPTY; - scsi_cdrom_log("CD-ROM %i: External media removal\n", dev->id); + scsi_cdrom_log(dev->log, "External media removal\n"); } else if (ext_medium_changed == 1) { dev->unit_attention = 0; dev->drv->cd_status |= CD_STATUS_TRANSITION; - scsi_cdrom_log("CD-ROM %i: External media transition\n", dev->id); + scsi_cdrom_log(dev->log, "External media transition\n"); } } static int -scsi_command_check_ready(scsi_cdrom_t *dev, uint8_t *cdb) +scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb) { int ret = 0; if (scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) { - /*Note by TC1995: Some vendor commands from X vendor don't really check for ready status - but they do on Y vendor. Quite confusing I know.*/ - if (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY) switch (dev->drv->type) { - default: - ret = 1; - break; - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - if (cdb[0] == 0xc0) - break; - ret = 1; - break; - } else + /* + Note by TC1995: Some vendor commands from X vendor don't really + check for ready status but they do on Y vendor. + Quite confusing I know. + */ + if (!dev->is_sony || (cdb[0] != 0xc0)) ret = 1; - } + } else if ((cdb[0] == GPCMD_READ_DVD_STRUCTURE) && (cdb[7] < 0xc0)) + ret = 1; return ret; } static int -scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) +scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb) { - int ready = 0; - int ext_medium_changed = 0; + int ready; + const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv); - if (dev->drv && dev->drv->ops && dev->drv->ops->ext_medium_changed) - ext_medium_changed = dev->drv->ops->ext_medium_changed(dev->drv); - - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->tf->request_length >> 5) & 7)); - scsi_cdrom_invalid_lun(dev); + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && + (cdb[1] & 0xe0)) { + scsi_cdrom_log(dev->log, "Attempting to execute a unknown command targeted " + "at SCSI LUN %i\n", ((dev->tf->request_length >> 5) & 7)); + scsi_cdrom_invalid_lun(dev, cdb[1] >> 5); return 0; } if (!(scsi_cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); + scsi_cdrom_log(dev->log, "Attempting to execute unknown command %02X over %s\n", + cdb[0], (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); - scsi_cdrom_illegal_opcode(dev); + scsi_cdrom_illegal_opcode(dev, cdb[0]); return 0; } - if ((dev->drv->bus_type < CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - scsi_cdrom_illegal_opcode(dev); + if ((dev->drv->bus_type < CDROM_BUS_SCSI) && + (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { + scsi_cdrom_log(dev->log, "Attempting to execute SCSI-only command %02X over " + "ATAPI\n", cdb[0]); + scsi_cdrom_illegal_opcode(dev, cdb[0]); return 0; } - if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - scsi_cdrom_illegal_opcode(dev); + if ((dev->drv->bus_type == CDROM_BUS_SCSI) && + (scsi_cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { + scsi_cdrom_log(dev->log, "Attempting to execute ATAPI-only command %02X over " + "SCSI\n", cdb[0]); + scsi_cdrom_illegal_opcode(dev, cdb[0]); return 0; } if (ext_medium_changed != 0) scsi_cdrom_ext_insert((void *) dev, ext_medium_changed); - if ((dev->drv->cd_status == CD_STATUS_PLAYING) || (dev->drv->cd_status == CD_STATUS_PAUSED)) { + if ((dev->drv->cd_status == CD_STATUS_PLAYING) || + (dev->drv->cd_status == CD_STATUS_PAUSED)) { ready = 1; goto skip_ready_check; } @@ -1660,8 +1267,9 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE)) ready = 0; else { - if ((ext_medium_changed != 0) || !(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - scsi_cdrom_log("(ext_medium_changed != 0): scsi_cdrom_insert()\n"); + if ((ext_medium_changed != 0) || + !(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { + scsi_cdrom_log(dev->log, "(ext_medium_changed != 0): scsi_cdrom_insert()\n"); scsi_cdrom_insert((void *) dev); } @@ -1671,33 +1279,42 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) ready = (dev->drv->cd_status != CD_STATUS_EMPTY); skip_ready_check: - /* If the drive is not ready, there is no reason to keep the + /* + If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ + disc changes. + */ if (!ready && (dev->unit_attention > 0)) dev->unit_attention = 0; - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ + /* + If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. + */ if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ + /* + Only increment the unit attention phase if the command can + not pass through it. + */ if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - scsi_cdrom_log("CD-ROM %i: Unit attention now 2\n", dev->id); + scsi_cdrom_log(dev->log, "Unit attention now 2\n"); dev->unit_attention++; - scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", - dev->id, cdb[0]); + scsi_cdrom_log(dev->log, "UNIT ATTENTION: Command %02X not allowed to " + "pass through\n", cdb[0]); scsi_cdrom_unit_attention(dev); return 0; } } else if (dev->unit_attention == 2) { if (cdb[0] != GPCMD_REQUEST_SENSE) { - scsi_cdrom_log("CD-ROM %i: Unit attention now 0\n", dev->id); + scsi_cdrom_log(dev->log, "Unit attention now 0\n"); dev->unit_attention = 0; } } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* clear - the UNIT ATTENTION condition if it's set. */ + /* + Unless the command is REQUEST SENSE, clear the sense. This will *NOT* clear + the UNIT ATTENTION condition if it's set. + */ if (cdb[0] != GPCMD_REQUEST_SENSE) scsi_cdrom_sense_clear(dev, cdb[0]); @@ -1708,12 +1325,12 @@ skip_ready_check: dev->media_status = MEC_MEDIA_REMOVAL; if (!ready && scsi_command_check_ready(dev, cdb)) { - scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); + scsi_cdrom_log(dev->log, "Not ready (%02X)\n", cdb[0]); scsi_cdrom_not_ready(dev); return 0; } - scsi_cdrom_log("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); + scsi_cdrom_log(dev->log, "Continuing with command %02X\n", cdb[0]); return 1; } @@ -1724,41 +1341,103 @@ scsi_cdrom_rezero(scsi_cdrom_t *dev) cdrom_seek(dev->drv, 0, 0); } +static int +scsi_cdrom_update_sector_flags(scsi_cdrom_t *dev) +{ + int ret = 0; + + switch (dev->drv->sector_size) { + default: + dev->sector_type = 0xff; + scsi_cdrom_log(dev->log, "Invalid sector size: %i\n", dev->drv->sector_size); + scsi_cdrom_invalid_field_pl(dev, dev->drv->sector_size); + ret = 1; + break; + case 128: case 256: case 512: case 2048: + /* + Internal type code indicating both Mode 1 and Mode 2 Form 1 are allowed. + Upper 4 bits indicate the divisor. + */ + dev->sector_type = 0x08 | ((2048 / dev->drv->sector_size) << 4); + dev->sector_flags = 0x0010; + break; + case 2056: + dev->sector_type = 0x18; + dev->sector_flags = 0x0050; + break; + case 2324: case 2328: + dev->sector_type = (dev->drv->sector_size == 2328) ? 0x1a : 0x1b; + dev->sector_flags = 0x0018; + break; + case 2332: case 2336: + dev->sector_type = (dev->drv->sector_size == 2336) ? 0x1c : 0x1d; + dev->sector_flags = 0x0058; + break; + case 2340: + dev->sector_type = 0x18; + dev->sector_flags = 0x0078; + break; + case 2352: + dev->sector_type = 0x00; + dev->sector_flags = 0x00f8; + break; + case 2368: + dev->sector_type = 0x00; + dev->sector_flags = 0x01f8; + break; + case 2448: + dev->sector_type = 0x00; + dev->sector_flags = 0x02f8; + break; + } + + return ret; +} + void scsi_cdrom_reset(scsi_common_t *sc) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - if (!dev) - return; + if (dev != NULL) { + scsi_cdrom_rezero(dev); + dev->tf->status = 0; + dev->callback = 0.0; + scsi_cdrom_set_callback(dev); + dev->tf->phase = 1; + dev->tf->request_length = 0xeb14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0xff; + dev->cur_lun = SCSI_LUN_USE_CDB; - scsi_cdrom_rezero(dev); - dev->tf->status = 0; - dev->callback = 0.0; - scsi_cdrom_set_callback(dev); - dev->tf->phase = 1; - dev->tf->request_length = 0xeb14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0xff; - dev->cur_lun = SCSI_LUN_USE_CDB; + 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; + } } static void scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) { - /*Will return 18 bytes of 0*/ + /* Will return 18 bytes of 0x00. */ if (alloc_length != 0) { - memset(buffer, 0, alloc_length); + memset(buffer, 0x00, alloc_length); memcpy(buffer, dev->sense, alloc_length); } - buffer[0] = 0x70; + buffer[0] = 0xf0; + buffer[7] = 0x0a; if ((scsi_cdrom_sense_key > 0) && (dev->drv->cd_status == CD_STATUS_PLAYING_COMPLETED)) { buffer[2] = SENSE_ILLEGAL_REQUEST; buffer[12] = ASC_AUDIO_PLAY_OPERATION; buffer[13] = ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } else if ((scsi_cdrom_sense_key == 0) && ((dev->drv->cd_status == CD_STATUS_PAUSED) || ((dev->drv->cd_status >= CD_STATUS_PLAYING) && (dev->drv->cd_status != CD_STATUS_STOPPED)))) { + } else if ((scsi_cdrom_sense_key == 0) && + ((dev->drv->cd_status == CD_STATUS_PAUSED) || ((dev->drv->cd_status >= CD_STATUS_PLAYING) && + (dev->drv->cd_status != CD_STATUS_STOPPED)))) { buffer[2] = SENSE_ILLEGAL_REQUEST; buffer[12] = ASC_AUDIO_PLAY_OPERATION; buffer[13] = (dev->drv->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; @@ -1768,7 +1447,8 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt buffer[13] = 0; } - scsi_cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + scsi_cdrom_log(dev->log, "Reporting sense: %02X %02X %02X\n", buffer[2], buffer[12], + buffer[13]); if (buffer[2] == SENSE_UNIT_ATTENTION) { /* If the last remaining sense is unit attention, clear @@ -1777,7 +1457,7 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt } if (dev->drv->cd_status & CD_STATUS_TRANSITION) { - scsi_cdrom_log("CD_STATUS_TRANSITION: scsi_cdrom_insert()\n"); + scsi_cdrom_log(dev->log, "CD_STATUS_TRANSITION: scsi_cdrom_insert()\n"); scsi_cdrom_insert((void *) dev); } } @@ -1786,18 +1466,16 @@ void scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int ext_medium_changed = 0; - - if (dev->drv && dev->drv->ops && dev->drv->ops->ext_medium_changed) - ext_medium_changed = dev->drv->ops->ext_medium_changed(dev->drv); + const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv); if (ext_medium_changed != 0) scsi_cdrom_ext_insert((void *) dev, ext_medium_changed); if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ + /* + If the drive is not ready, there is no reason to keep the UNIT ATTENTION + condition present, as we only use it to mark disc changes. + */ dev->unit_attention = 0; } @@ -1806,7 +1484,7 @@ scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t al } static void -scsi_cdrom_set_buf_len(scsi_cdrom_t *dev, int32_t *BufLen, int32_t *src_len) +scsi_cdrom_set_buf_len(const scsi_cdrom_t *dev, int32_t *BufLen, int32_t *src_len) { if (dev->drv->bus_type == CDROM_BUS_SCSI) { if (*BufLen == -1) @@ -1815,44 +1493,45 @@ scsi_cdrom_set_buf_len(scsi_cdrom_t *dev, int32_t *BufLen, int32_t *src_len) *BufLen = MIN(*src_len, *BufLen); *src_len = *BufLen; } - scsi_cdrom_log("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); + scsi_cdrom_log(dev->log, "Actual transfer length: %i\n", *BufLen); } } static void -scsi_cdrom_stop(scsi_common_t *sc) +scsi_cdrom_stop(const scsi_common_t *sc) { - scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; + const scsi_cdrom_t *dev = (const scsi_cdrom_t *) sc; cdrom_stop(dev->drv); } static void -scsi_cdrom_set_speed(scsi_cdrom_t *dev, uint8_t *cdb) +scsi_cdrom_set_speed(scsi_cdrom_t *dev, const uint8_t *cdb) { dev->drv->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; if (dev->drv->cur_speed < 1) dev->drv->cur_speed = 1; - else if (dev->drv->cur_speed > dev->drv->speed) - dev->drv->cur_speed = dev->drv->speed; + else if (dev->drv->cur_speed > dev->drv->real_speed) + dev->drv->cur_speed = dev->drv->real_speed; scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_command_complete(dev); } static uint8_t -scsi_cdrom_command_chinon(void *sc, uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_chinon(void *sc, const uint8_t *cdb, int32_t *BufLen) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; uint8_t cmd_stat = 0x00; switch (cdb[0]) { + default: + break; + case GPCMD_UNKNOWN_CHINON: - if (dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) { - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_stop(sc); - scsi_cdrom_command_complete(dev); - cmd_stat = 0x01; - } + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + scsi_cdrom_command_complete(dev); + cmd_stat = 0x01; break; case GPCMD_EJECT_CHINON: @@ -1875,12 +1554,10 @@ scsi_cdrom_command_chinon(void *sc, uint8_t *cdb, int32_t *BufLen) } static uint8_t -scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) +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 = 0; - int pos = dev->drv->seek_pos; - int ret = 1; + int msf; uint8_t cmd_stat = 0x00; int len; int max_len; @@ -1888,9 +1565,11 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) int real_pos; switch (cdb[0]) { + default: + break; + case GPCMD_SET_ADDRESS_FORMAT_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->sony_vendor = 1; dev->drv->sony_msf = cdb[8] & 1; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; @@ -1899,7 +1578,6 @@ scsi_cdrom_command_dec_sony_texel(void *sc, 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->sony_vendor = 1; max_len = cdb[7]; max_len <<= 8; @@ -1907,14 +1585,14 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_buf_alloc(dev, 65536); - if (!dev->drv->ops) + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); else { len = cdrom_read_toc_sony(dev->drv, dev->buffer, cdb[5], msf, max_len); if (len == -1) /* If the returned length is -1, this means cdrom_read_toc_sony() has encountered an error. */ - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, dev->drv->inv_field); else { scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -1925,15 +1603,14 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_SUBCHANNEL_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - dev->sony_vendor = 1; max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; msf = dev->drv->sony_msf; - scsi_cdrom_log("CD-ROM %i: Getting sub-channel type (%s), code-q = %02x\n", - dev->id, msf ? "MSF" : "LBA", cdb[2] & 0x40); + scsi_cdrom_log(dev->log, "Getting sub-channel type (%s), code-q = %02x\n", + msf ? "MSF" : "LBA", cdb[2] & 0x40); if (cdb[2] & 0x40) { scsi_cdrom_buf_alloc(dev, 9); @@ -1945,7 +1622,7 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_data_command_finish(dev, len, len, len, 0); } else { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: Drive Status All done - callback set\n", dev->id); + scsi_cdrom_log(dev->log, "Drive Status All done - callback set\n"); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -1955,7 +1632,6 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_HEADER_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - dev->sony_vendor = 1; alloc_length = ((cdb[7] << 8) | cdb[8]); scsi_cdrom_buf_alloc(dev, 4); @@ -1979,7 +1655,6 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_PLAYBACK_STATUS_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - dev->sony_vendor = 1; max_len = cdb[7]; max_len <<= 8; @@ -1999,7 +1674,7 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) &dev->buffer[6], msf); dev->buffer[5] = 0x00; - scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[4]); + scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[4]); len = MIN(len, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &len); @@ -2010,7 +1685,6 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_PAUSE_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->sony_vendor = 1; cdrom_audio_pause_resume(dev->drv, !(cdb[1] & 0x10)); scsi_cdrom_command_complete(dev); cmd_stat = 0x01; @@ -2018,19 +1692,19 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_PLAY_TRACK_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->sony_vendor = 1; msf = 3; if ((cdb[5] != 1) || (cdb[8] != 1)) scsi_cdrom_illegal_mode(dev); else { - pos = cdb[4]; + const int pos = cdb[4]; - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) + if ((dev->drv->image_path[0] == 0x00) || + (dev->drv->cd_status <= CD_STATUS_DVD)) scsi_cdrom_illegal_mode(dev); else { /* In this case, len is unused so just pass a fixed value of 1 intead. */ - ret = cdrom_audio_play(dev->drv, pos, 1 /*len*/, msf); + const int ret = cdrom_audio_play(dev->drv, pos, 1, msf); if (ret) scsi_cdrom_command_complete(dev); @@ -2042,27 +1716,29 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) break; case GPCMD_PLAY_MSF_SONY: - cdb[0] = GPCMD_PLAY_AUDIO_MSF; - dev->current_cdb[0] = cdb[0]; - dev->sony_vendor = 1; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_MSF. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_MSF; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_MSF. + */ break; case GPCMD_PLAY_AUDIO_SONY: - cdb[0] = GPCMD_PLAY_AUDIO_10; - dev->current_cdb[0] = cdb[0]; - dev->sony_vendor = 1; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_10. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_10; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_10. + */ break; case GPCMD_PLAYBACK_CONTROL_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); - dev->sony_vendor = 1; len = (cdb[7] << 8) | cdb[8]; if (len == 0) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: PlayBack Control Sony All done - callback set\n", dev->id); + scsi_cdrom_log(dev->log, "PlayBack Control Sony All done - " + "callback set\n"); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -2079,70 +1755,93 @@ scsi_cdrom_command_dec_sony_texel(void *sc, uint8_t *cdb, int32_t *BufLen) } static uint8_t -scsi_cdrom_command_matsushita(void *sc, uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_matsushita(void *sc, const uint8_t *cdb, int32_t *BufLen) { - scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - uint8_t cmd_stat = 0x00; + scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; + const uint8_t cmd_stat = 0x00; switch (cdb[0]) { + default: + break; + case GPCMD_READ_SUBCHANNEL_MATSUSHITA: - cdb[0] = GPCMD_READ_SUBCHANNEL; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_READ_SUBCHANNEL. */ + dev->current_cdb[0] = GPCMD_READ_SUBCHANNEL; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_READ_SUBCHANNEL. + */ break; case GPCMD_READ_TOC_MATSUSHITA: - cdb[0] = GPCMD_READ_TOC_PMA_ATIP; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_READ_TOC_PMA_ATIP. */ + dev->current_cdb[0] = GPCMD_READ_TOC_PMA_ATIP; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_READ_TOC_PMA_ATIP. + */ break; case GPCMD_READ_HEADER_MATSUSHITA: - cdb[0] = GPCMD_READ_HEADER; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_READ_HEADER. */ + dev->current_cdb[0] = GPCMD_READ_HEADER; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_READ_HEADER. + */ break; case GPCMD_PLAY_AUDIO_MATSUSHITA: - cdb[0] = GPCMD_PLAY_AUDIO_10; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_10. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_10; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_10. + */ break; case GPCMD_PLAY_AUDIO_MSF_MATSUSHITA: - cdb[0] = GPCMD_PLAY_AUDIO_MSF; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_MSF. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_MSF; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_MSF. + */ break; case GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA: - cdb[0] = GPCMD_PLAY_AUDIO_TRACK_INDEX; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_TRACK_INDEX. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_TRACK_INDEX; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_TRACK_INDEX. + */ break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA: - cdb[0] = GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10. + */ break; case GPCMD_PAUSE_RESUME_MATSUSHITA: - cdb[0] = GPCMD_PAUSE_RESUME; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PAUSE_RESUME. */ + dev->current_cdb[0] = GPCMD_PAUSE_RESUME; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PAUSE_RESUME. + */ break; case GPCMD_PLAY_AUDIO_12_MATSUSHITA: - cdb[0] = GPCMD_PLAY_AUDIO_12; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_12. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_12; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_12. + */ break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA: - cdb[0] = GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12; - dev->current_cdb[0] = cdb[0]; - /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12. */ + dev->current_cdb[0] = GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12; + /* + Keep cmd_stat at 0x00, therefore, it's going to process it + as GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12. + */ break; } @@ -2150,16 +1849,19 @@ scsi_cdrom_command_matsushita(void *sc, uint8_t *cdb, int32_t *BufLen) } static uint8_t -scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_nec(void *sc, const uint8_t *cdb, int32_t *BufLen) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int pos = dev->drv->seek_pos; - int ret = 1; uint8_t cmd_stat = 0x00; + int pos; + int ret; int len; int alloc_length; switch (cdb[0]) { + default: + break; + case GPCMD_NO_OPERATION_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_command_complete(dev); @@ -2174,7 +1876,7 @@ scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_AUDIO_TRACK_SEARCH_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) + 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]; @@ -2191,7 +1893,7 @@ scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_PLAY_AUDIO_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) + 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]; @@ -2234,11 +1936,11 @@ scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) alloc_length = cdb[1] & 0x1f; len = 10; - if (!dev->drv->ops) + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); else if (alloc_length <= 0) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: Subcode Q All done - callback set\n", dev->id); + scsi_cdrom_log(dev->log, "Subcode Q All done - callback set\n"); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -2248,7 +1950,7 @@ scsi_cdrom_command_nec(void *sc, 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_log("Audio Status = %02x\n", dev->buffer[0]); + scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[0]); scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -2264,17 +1966,14 @@ scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) */ scsi_cdrom_buf_alloc(dev, 22); - if (!dev->drv->ops) - scsi_cdrom_not_ready(dev); - else { - ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); - len = 22; - if (ret) { - scsi_cdrom_set_buf_len(dev, BufLen, &len); - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - } else - scsi_cdrom_invalid_field(dev); - } + ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); + len = 22; + if (ret) { + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + } else + scsi_cdrom_invalid_field(dev, dev->drv->inv_field); + cmd_stat = 0x01; break; } @@ -2283,17 +1982,20 @@ scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) } static uint8_t -scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_pioneer(void *sc, const uint8_t *cdb, int32_t *BufLen) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int pos = dev->drv->seek_pos; - int ret = 1; uint8_t cmd_stat = 0x00; + int pos; + int ret; int len; int max_len; int alloc_length; switch (cdb[0]) { + default: + break; + case GPCMD_MAGAZINE_EJECT_PIONEER: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_stop(sc); @@ -2306,7 +2008,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); scsi_cdrom_buf_alloc(dev, 4); - if (!dev->drv->ops) + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); else { ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); @@ -2316,7 +2018,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } else - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, dev->drv->inv_field); } cmd_stat = 0x01; break; @@ -2327,11 +2029,11 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) alloc_length = cdb[1] & 0x1f; len = 9; - if (!dev->drv->ops) + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); else if (!alloc_length) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: Subcode Q All done - callback set\n", dev->id); + scsi_cdrom_log(dev->log, "Subcode Q All done - callback set\n"); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -2341,7 +2043,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) memset(dev->buffer, 0, len); cdrom_get_current_subcodeq(dev->drv, &dev->buffer[1]); - scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[0]); + scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[0]); scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -2351,7 +2053,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_AUDIO_TRACK_SEARCH_PIONEER: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) + 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]; @@ -2370,7 +2072,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_PLAY_AUDIO_PIONEER: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) + 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]; @@ -2412,7 +2114,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) memset(dev->buffer, 0, 6); dev->buffer[0] = cdrom_get_audio_status_pioneer(dev->drv, &dev->buffer[1]); /*Audio status*/ - scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[4]); + scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[4]); len = MIN(len, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &len); @@ -2428,10 +2130,10 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_buf_alloc(dev, 65536); if (!(scsi_cdrom_drive_status_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, cdb[2]); else if (len <= 0) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: Drive Status All done - callback set\n", dev->id); + scsi_cdrom_log(dev->log, "Drive Status All done - callback set\n"); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -2439,12 +2141,13 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) memset(dev->buffer, 0, len); alloc_length = len; - len = scsi_cdrom_drive_status(dev, dev->buffer, 0, cdb[2]); + len = scsi_cdrom_drive_status(dev, dev->buffer, cdb[2]); len = MIN(len, alloc_length); scsi_cdrom_set_buf_len(dev, BufLen, &len); - scsi_cdrom_log("CD-ROM %i: Reading drive status page: %02X...\n", dev->id, cdb[2]); + scsi_cdrom_log(dev->log, "Reading drive status page: %02X...\n", + cdb[2]); scsi_cdrom_data_command_finish(dev, len, len, alloc_length, 0); } @@ -2456,16 +2159,19 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) } static uint8_t -scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int pos = dev->drv->seek_pos; - int ret = 1; uint8_t cmd_stat = 0x00; + int pos; + int ret; int len; int alloc_length; switch (cdb[0]) { + default: + break; + case GPCMD_NO_OPERATION_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_command_complete(dev); @@ -2474,7 +2180,7 @@ scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DVD)) { scsi_cdrom_illegal_mode(dev); break; } @@ -2492,7 +2198,7 @@ scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) case GPCMD_PLAY_AUDIO_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) + 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]; @@ -2534,11 +2240,11 @@ scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) alloc_length = cdb[1] & 0x1f; len = 10; - if (!dev->drv->ops) + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); else if (alloc_length <= 0) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: Subcode Q All done - callback set\n", dev->id); + scsi_cdrom_log(dev->log, "Subcode Q All done - callback set\n"); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -2548,7 +2254,7 @@ scsi_cdrom_command_toshiba(void *sc, 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_log("Audio Status = %02x\n", dev->buffer[0]); + scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[0]); scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -2560,7 +2266,7 @@ scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); scsi_cdrom_buf_alloc(dev, 4); - if (!dev->drv->ops) + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); else { ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); @@ -2569,7 +2275,7 @@ scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } else - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, dev->drv->inv_field); } cmd_stat = 0x01; break; @@ -2579,22 +2285,19 @@ scsi_cdrom_command_toshiba(void *sc, uint8_t *cdb, int32_t *BufLen) } void -scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) +scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int msf = 0; int pos = dev->drv->seek_pos; int idx = 0; - int block_desc = 0; int ret = 1; - int format = 0; - int track = 0; - char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; int32_t blen = 0; uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + char model[2048] = { 0 }; + int msf; + int block_desc; int len; int max_len; int used_len; @@ -2603,9 +2306,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) uint32_t feature; unsigned preamble_len; int toc_format; - int real_pos; int32_t *BufLen; - uint8_t *b; if (dev->drv->bus_type == CDROM_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; @@ -2618,33 +2319,29 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->packet_len = 0; dev->request_pos = 0; - device_identify[7] = dev->id + 0x30; - - device_identify_ex[7] = dev->id + 0x30; - device_identify_ex[10] = EMU_VERSION_EX[0]; - device_identify_ex[12] = EMU_VERSION_EX[2]; - device_identify_ex[13] = EMU_VERSION_EX[3]; - memcpy(dev->current_cdb, cdb, 12); - dev->sony_vendor = 0; - // if (cdb[0] != 0) { - scsi_cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, - dev->unit_attention); - scsi_cdrom_log("CD-ROM %i: Request length: %04X\n", dev->id, dev->tf->request_length); +#if ENABLE_SCSI_CDROM_LOG == 2 + scsi_cdrom_log(dev->log, "Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, " + "Unit attention: %i\n", cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, + scsi_cdrom_ascq, dev->unit_attention); + scsi_cdrom_log(dev->log, "Request length: %04X\n", dev->tf->request_length); - scsi_cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + scsi_cdrom_log(dev->log, "CDB: %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); - // } +#endif msf = cdb[1] & 2; dev->sector_len = 0; scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + /* + This handles the Not Ready/Unit Attention check if it has to be + handled at this point. + */ if (scsi_cdrom_pre_execution_check(dev, cdb) == 0) return; @@ -2653,7 +2350,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_sense_clear(dev, cdb[0]); } - if ((dev->ven_cmd == NULL) || (dev->ven_cmd(sc, cdb, BufLen) == 0x00)) switch (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); @@ -2668,8 +2365,6 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); max_len = cdb[4]; @@ -2695,7 +2390,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_AUDIO_SCAN: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + if ((dev->drv->image_path[0] == 0x00) || + (dev->drv->cd_status <= CD_STATUS_DVD)) { scsi_cdrom_illegal_mode(dev); break; } @@ -2737,22 +2433,19 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (toc_format == 0) toc_format = (cdb[9] >> 6) & 3; - if (!dev->drv->ops) { + if (dev->drv->ops == NULL) scsi_cdrom_not_ready(dev); - return; - } - - if (toc_format < 3) { + else if (toc_format < 3) { len = cdrom_read_toc(dev->drv, dev->buffer, toc_format, cdb[6], msf, max_len); /* If the returned length is -1, this means cdrom_read_toc() has encountered an error. */ if (len == -1) - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, dev->drv->inv_field); else { scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } } else - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, toc_format); break; case GPCMD_READ_6: @@ -2763,32 +2456,38 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_READ_CD: case GPCMD_READ_CD_MSF: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = 2048; + alloc_length = dev->drv->sector_size; switch (cdb[0]) { case GPCMD_READ_6: dev->sector_len = cdb[4]; - /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sectors. */ + /* + For READ (6) and WRITE (6), a length of 0 indicates a transfer of + 256 sectors. + */ if (dev->sector_len == 0) dev->sector_len = 256; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | - ((uint32_t) cdb[3]); - scsi_cdrom_log("CD-ROM %i: READ (6): Length: %i, LBA: %i\n", dev->id, dev->sector_len, - dev->sector_pos); + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + scsi_cdrom_log(dev->log, "READ (6): Length: %i, LBA: %i\n", + dev->sector_len, dev->sector_pos); break; case GPCMD_READ_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_cdrom_log("CD-ROM %i: READ (10): Length: %i, LBA: %i\n", dev->id, dev->sector_len, - dev->sector_pos); + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + scsi_cdrom_log(dev->log, "READ (10): Length: %i, LBA: %i\n", + dev->sector_len, dev->sector_pos); break; case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - scsi_cdrom_log("CD-ROM %i: READ (12): Length: %i, LBA: %i\n", dev->id, dev->sector_len, - dev->sector_pos); + scsi_cdrom_log(dev->log, "READ (12): Length: %i, LBA: %i\n", + dev->sector_len, dev->sector_pos); break; case GPCMD_READ_CD_MSF_OLD: case GPCMD_READ_CD_MSF: @@ -2806,15 +2505,20 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->sector_len++; } else { dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; } - if (((cdb[9] & 0xf8) == 0x08) || ((cdb[9] == 0x00) && ((cdb[10] & 0x07) != 0x00))) { + if (((cdb[9] & 0xf8) == 0x08) || ((cdb[9] == 0x00) && + ((cdb[10] & 0x07) != 0x00))) { /* Illegal mode */ - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, cdb[9]); ret = 0; } else if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) == 0x00)) - /* If all the flag bits are cleared, then treat it as a non-data command. */ + /* + If all the flag bits are cleared, then treat it as a + non-data command. + */ dev->sector_len = 0; break; @@ -2825,39 +2529,30 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (ret) { if (dev->sector_len > 0) { max_len = dev->sector_len; - dev->requested_blocks = max_len; /* - If we're reading all blocks in one go for DMA, - why not also for PIO, it should NOT matter - anyway, this step should be identical and only - the way the read dat is transferred to the host - should be different. - */ + dev->requested_blocks = max_len; dev->packet_len = max_len * alloc_length; scsi_cdrom_buf_alloc(dev, dev->packet_len); dev->drv->seek_diff = ABS((int) (pos - dev->sector_pos)); + dev->drv->seek_pos = dev->sector_pos; - if ((cdb[0] == GPCMD_READ_10) || (cdb[0] == GPCMD_READ_12)) { - switch (dev->drv->type) { - case CDROM_TYPE_NEC_25_10a ... CDROM_TYPE_NEC_464_105: - case CDROM_TYPE_TOSHIBA_XM_3433 ... CDROM_TYPE_TOSHIBA_SDM1401_1008: - ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, cdb[9] & 0xc0); - break; - default: - ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, 0); - break; - } - } else - ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, 0); + 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); + else + ret = scsi_cdrom_read_blocks(dev, &alloc_length, 0); 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_set_buf_len(dev, BufLen, + (int32_t *) &dev->packet_len); - scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, + scsi_cdrom_data_command_finish(dev, alloc_length, + alloc_length / dev->requested_blocks, alloc_length, 0); if (dev->packet_status != PHASE_COMPLETE) @@ -2872,7 +2567,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } } else { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - /* scsi_cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); */ + /* 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); @@ -2882,39 +2577,80 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_READ_HEADER: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 2352; - alloc_length = ((cdb[7] << 8) | cdb[8]); - scsi_cdrom_buf_alloc(dev, 8); - + len = (cdb[7] << 8) | cdb[8]; dev->sector_len = 1; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - if (msf) - real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); - else - real_pos = dev->sector_pos; - dev->buffer[0] = 1; /*2048 bytes user data*/ - dev->buffer[1] = dev->buffer[2] = dev->buffer[3] = 0; - dev->buffer[4] = (real_pos >> 24); - dev->buffer[5] = ((real_pos >> 16) & 0xff); - dev->buffer[6] = ((real_pos >> 8) & 0xff); - dev->buffer[7] = real_pos & 0xff; + scsi_cdrom_log(dev->log, "READ HEADER: Length: %i, LBA: %i\n", + dev->sector_len, dev->sector_pos); - len = 8; - len = MIN(len, alloc_length); + if (len > 0) { + max_len = 1; + dev->requested_blocks = max_len; - scsi_cdrom_set_buf_len(dev, BufLen, &len); + dev->packet_len = len; + scsi_cdrom_buf_alloc(dev, 2352); - scsi_cdrom_data_command_finish(dev, len, len, len, 0); + dev->drv->seek_diff = ABS((int) (pos - dev->sector_pos)); + dev->drv->seek_pos = dev->sector_pos; + + ret = scsi_cdrom_read_blocks(dev, &alloc_length, 0); + + if (ret > 0) { + uint8_t header[4] = { 0 }; + + memcpy(header, dev->buffer, 4); + + dev->buffer[0] = header[3]; + + if (cdb[1] & 0x02) { + memset(&(dev->buffer[1]), 0x00, 4); + dev->buffer[5] = header[0]; + dev->buffer[6] = header[1]; + dev->buffer[7] = header[2]; + } else { + memset(&(dev->buffer[1]), 0x00, 3); + uint32_t lba = ((header[0] * 60 * 75) + + (header[1] * 75) + + header[2]) - 150; + dev->buffer[4] = (lba >> 24) & 0xff; + dev->buffer[5] = (lba >> 16) & 0xff; + dev->buffer[6] = (lba >> 8) & 0xff; + dev->buffer[7] = lba & 0xff; + } + + len = MIN(8, 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); + } break; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else + if (dev->drv->bus_type == CDROM_BUS_ATAPI) block_desc = 0; + else + block_desc = !((cdb[1] >> 3) & 1); if (cdb[0] == GPCMD_MODE_SENSE_6) { len = cdb[4]; @@ -2924,32 +2660,23 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 65536); } - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - if (!(scsi_cdrom_mode_sense_page_flags_sony & (1LL << (uint64_t) (cdb[2] & 0x3f)))) - ret = 0; - break; - default: - if (!(scsi_cdrom_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) - ret = 0; - break; - } + if (!(dev->ms_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) + ret = 0; if (ret == 1) { memset(dev->buffer, 0, len); alloc_length = len; - /* This determines the media type ID to return - this is - a SCSI/ATAPI-specific thing, so it makes the most sense - to keep this here. - Also, the max_len variable is reused as this command - does otherwise not use it, to avoid having to declare - another variable. */ + /* + This determines the media type ID to return which is a SCSI/ATAPI-specific + thing, so it makes the most sense to keep this here. + + Also, the max_len variable is reused as this command does otherwise not + use it, to avoid having to declare another variable. + */ if (dev->drv->cd_status == CD_STATUS_EMPTY) max_len = 70; /* No media inserted. */ - else if (dev->drv->cdrom_capacity > CD_MAX_SECTORS) + else if (dev->drv->cd_status == CD_STATUS_DVD) max_len = 65; /* DVD. */ else if (dev->drv->cd_status == CD_STATUS_DATA_ONLY) max_len = 1; /* Data CD. */ @@ -2964,7 +2691,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (block_desc) dev->buffer[3] = 8; } else { - len = scsi_cdrom_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); + len = scsi_cdrom_mode_sense(dev, dev->buffer, 8, + cdb[2], block_desc); len = MIN(len, alloc_length); dev->buffer[0] = (len - 2) >> 8; dev->buffer[1] = (len - 2) & 255; @@ -2977,11 +2705,11 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); - scsi_cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + scsi_cdrom_log(dev->log, "Reading mode page: %02X...\n", cdb[2]); scsi_cdrom_data_command_finish(dev, len, len, alloc_length, 0); } else - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, cdb[2]); break; case GPCMD_MODE_SELECT_6: @@ -3014,21 +2742,17 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) /* Only feature 0 is supported */ if ((feature > 3) && (feature != 0x010) && (feature != 0x1d) && (feature != 0x01e) && (feature != 0x01f) && (feature != 0x103)) - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, feature); else { scsi_cdrom_buf_alloc(dev, 65536); memset(dev->buffer, 0, max_len); - alloc_length = 0; - b = dev->buffer; + uint8_t *b = dev->buffer; + + alloc_length = 0; - /* - The number of sectors from the media tells us which profile - to use as current. 0 means there is no media. - */ if (dev->drv->cd_status != CD_STATUS_EMPTY) { - len = dev->drv->cdrom_capacity; - if (len > CD_MAX_SECTORS) { + if (dev->drv->cd_status == CD_STATUS_DVD) { b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; b[7] = MMC_PROFILE_DVD_ROM & 0xff; ret = 1; @@ -3044,7 +2768,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) b += 8; if ((feature == 0) || ((cdb[1] & 3) < 2)) { - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + /* Persistent and current. */ + b[2] = (0 << 2) | 0x02 | 0x01; b[3] = 8; alloc_length += 4; @@ -3062,8 +2787,9 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } } if ((feature == 1) || ((cdb[1] & 3) < 2)) { + /* Persistent and current. */ b[1] = 1; - b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + b[2] = (2 << 2) | 0x02 | 0x01; b[3] = 8; if (dev->drv->bus_type == CDROM_BUS_SCSI) @@ -3086,25 +2812,18 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } if ((feature == 3) || ((cdb[1] & 3) < 2)) { b[1] = 2; - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + /* Persistent and current. */ + b[2] = (0 << 2) | 0x02 | 0x01; b[3] = 4; - b[4] = 0x0d; - - /* The early CD-ROM drives we emulate (NEC CDR-260 for ATAPI and - early vendor SCSI CD-ROM models) are caddy drives, the later - ones are tray drives. */ - if (dev->drv->bus_type == CDROM_BUS_SCSI) - b[4] |= ((dev->drv->type == CDROM_TYPE_86BOX_100) ? 0x20 : 0x00); - else - b[4] |= ((dev->drv->type == CDROM_TYPE_NEC_260_100) || - ((dev->drv->type == CDROM_TYPE_NEC_260_101)) ? 0x00 : 0x20); + b[4] = 0x0d | (cdrom_is_caddy(dev->drv->type) ? 0x00 : 0x20); alloc_length += 8; b += 8; } if ((feature == 0x10) || ((cdb[1] & 3) < 2)) { b[1] = 0x10; - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + /* Persistent and current. */ + b[2] = (0 << 2) | 0x02 | 0x01; b[3] = 8; b[6] = 8; @@ -3115,7 +2834,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } if ((feature == 0x1d) || ((cdb[1] & 3) < 2)) { b[1] = 0x1d; - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + /* Persistent and current. */ + b[2] = (0 << 2) | 0x02 | 0x01; b[3] = 0; alloc_length += 4; @@ -3123,7 +2843,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } if ((feature == 0x1e) || ((cdb[1] & 3) < 2)) { b[1] = 0x1e; - b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + /* Persistent and current. */ + b[2] = (2 << 2) | 0x02 | 0x01; b[3] = 4; b[4] = 0; @@ -3141,14 +2862,14 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if ((feature == 0x103) || ((cdb[1] & 3) < 2)) { b[0] = 1; b[1] = 3; - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + /* Persistent and current. */ + b[2] = (0 << 2) | 0x02 | 0x01; b[3] = 0; b[4] = 7; b[6] = 1; alloc_length += 8; - b += 8; } dev->buffer[0] = ((alloc_length - 4) >> 24) & 0xff; @@ -3160,7 +2881,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); - scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, + alloc_length, 0); } break; @@ -3174,37 +2896,40 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (gesn_cdb->polled & 0x01) { /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. + These are the supported events. + + We currently only support requests of the 'media' type. + Notification class requests and supported event classes are bitmasks, + but they are built from the same values as the "notification class" + field. */ gesn_event_header->supported_events = 1 << GESN_MEDIA; /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. + We use |= below to set the class field; other bits in this byte + are reserved now but this is useful to do if we have to use the + reserved fields later. */ gesn_event_header->notification_class = 0; /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. + Responses to requests are to be based on request priority. The + notification_class_request_type enum above specifies the + priority: upper elements are higher prio than lower ones. */ if (gesn_cdb->class & (1 << GESN_MEDIA)) { gesn_event_header->notification_class |= GESN_MEDIA; - dev->buffer[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ - dev->buffer[5] = 1; /* Power Status (1 = Active) */ + /* Bits 7-4 = Reserved, Bits 4-1 = Media Status. */ + dev->buffer[4] = dev->media_status; + /* Power Status (1 = Active). */ + dev->buffer[5] = 1; dev->buffer[6] = 0; dev->buffer[7] = 0; used_len = 8; } else { - gesn_event_header->notification_class = 0x80; /* No event available */ + /* No event available. */ + gesn_event_header->notification_class = 0x80; used_len = sizeof(*gesn_event_header); } gesn_event_header->len = used_len - sizeof(*gesn_event_header); @@ -3214,14 +2939,12 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_set_buf_len(dev, BufLen, &used_len); scsi_cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); - } else { + } else /* Only polling is supported, asynchronous mode is not. It is fine by the MMC spec to not support async mode operations. */ - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - } + scsi_cdrom_invalid_field(dev, gesn_cdb->polled); break; case GPCMD_READ_DISC_INFORMATION: @@ -3233,16 +2956,9 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 65536); - memset(dev->buffer, 0, 34); - memset(dev->buffer, 1, 9); - dev->buffer[0] = 0; - dev->buffer[1] = 32; - dev->buffer[2] = 0xe; /* last session complete, disc finalized */ - dev->buffer[7] = 0x20; /* unrestricted use */ - dev->buffer[8] = 0x00; /* CD-ROM */ + cdrom_read_disc_information(dev->drv, dev->buffer); - len = 34; - len = MIN(len, max_len); + len = MIN(34, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &len); @@ -3258,32 +2974,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 65536); - track = ((uint32_t) cdb[2]) << 24; - track |= ((uint32_t) cdb[3]) << 16; - track |= ((uint32_t) cdb[4]) << 8; - track |= (uint32_t) cdb[5]; + ret = cdrom_read_track_information(dev->drv, cdb, dev->buffer); - if (((cdb[1] & 0x03) != 1) || (track != 1)) - scsi_cdrom_invalid_field(dev); - else { - len = 36; - - memset(dev->buffer, 0, 36); - dev->buffer[0] = 0; - dev->buffer[1] = 34; - dev->buffer[2] = 1; /* track number (LSB) */ - dev->buffer[3] = 1; /* session number (LSB) */ - dev->buffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - dev->buffer[6] = (0 << 7) | (0 << 6) | (0 << 5) | /* not reserved track, not blank, */ - (0 << 6) | (1 << 0); /* not packet writing, not fixed packet, */ - /* data mode 1 */ - dev->buffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, */ - /* next recordable address not valid */ - - dev->buffer[24] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff; /* track size */ - dev->buffer[25] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff; /* track size */ - dev->buffer[26] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff; /* track size */ - dev->buffer[27] = (dev->drv->cdrom_capacity - 1) & 0xff; /* track size */ + if (ret > 0) { + len = ret; if (len > max_len) { len = max_len; @@ -3293,7 +2987,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); - } + } else + scsi_cdrom_invalid_field(dev, -ret); break; case GPCMD_PLAY_AUDIO_10: @@ -3345,7 +3040,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) break; } - if (ret && (dev->drv->image_path[0] != 0x00) && (dev->drv->cd_status > CD_STATUS_DATA_ONLY)) + 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 ret = 0; @@ -3366,13 +3062,14 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 32); - scsi_cdrom_log("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); + scsi_cdrom_log(dev->log, "Getting page %i (%s)\n", cdb[3], + msf ? "MSF" : "LBA"); - if (cdb[3] > 3) { - /* scsi_cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", dev->id, - cdb[3]); */ - scsi_cdrom_invalid_field(dev); - } else if (max_len <= 0) { + if (cdb[3] > 3) + scsi_cdrom_invalid_field(dev, cdb[3]); + else if ((cdb[3] != 3) && (cdb[6] != 0)) + scsi_cdrom_invalid_field(dev, cdb[6]); + else if (max_len <= 0) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; @@ -3382,7 +3079,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) alloc_length = 4; else switch (cdb[3]) { case 0: - /* SCSI-2: Q-type subchannel, ATAPI: reserved */ + /* SCSI-2: Q-type subchannel, ATAPI: reserved. */ alloc_length = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 48 : 4; break; case 1: @@ -3404,32 +3101,14 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[pos++] = cdb[3]; /* Format code */ if (alloc_length != 4) { - dev->buffer[1] = cdrom_get_current_status(dev->drv); - cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf); dev->buffer[2] = alloc_length - 4; } - switch (dev->drv->cd_status) { - case CD_STATUS_PLAYING: - dev->buffer[1] = 0x11; - break; - case CD_STATUS_PAUSED: - dev->buffer[1] = ((dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) || - (dev->drv->type == CDROM_TYPE_CHINON_CDX435_M62)) ? 0x15 : 0x12; - break; - case CD_STATUS_DATA_ONLY: - dev->buffer[1] = ((dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) || - (dev->drv->type == CDROM_TYPE_CHINON_CDX435_M62)) ? 0x00 : 0x15; - break; - default: - dev->buffer[1] = ((dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) || - (dev->drv->type == CDROM_TYPE_CHINON_CDX435_M62)) ? 0x00 : 0x13; - break; - } + dev->buffer[1] = cdrom_get_current_status(dev->drv); - scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[1]); + scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[1]); len = MIN(len, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &len); @@ -3445,23 +3124,29 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_buf_alloc(dev, alloc_length); - if ((cdb[7] < 0xc0) && (dev->drv->cdrom_capacity <= CD_MAX_SECTORS)) - scsi_cdrom_incompatible_format(dev); + if ((cdb[7] < 0xc0) && (dev->drv->cd_status != CD_STATUS_DVD)) + scsi_cdrom_incompatible_format(dev, cdb[7]); else { memset(dev->buffer, 0, alloc_length); if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { + uint32_t info = 0x00000000; + if (cdb[1] == 0) { - format = cdb[7]; - ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, dev->buffer); - dev->buffer[0] = (ret >> 8); - dev->buffer[1] = (ret & 0xff); - dev->buffer[2] = dev->buffer[3] = 0x00; - if (ret) { + ret = cdrom_read_dvd_structure(dev->drv, cdb[6], cdb[7], dev->buffer, &info); + if (ret > 0) { + dev->buffer[0] = (ret >> 8); + dev->buffer[1] = (ret & 0xff); + dev->buffer[2] = dev->buffer[3] = 0x00; + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); - scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, + scsi_cdrom_data_command_finish(dev, alloc_length, + alloc_length, alloc_length, 0); - } else { + } else if (ret < 0) + scsi_cdrom_error_common(dev, (ret >> 16) & 0xff, + (ret >> 8) & 0xff, ret & 0xff, info); + else { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * CDROM_TIME; @@ -3469,7 +3154,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } } } else - scsi_cdrom_invalid_field(dev); + scsi_cdrom_invalid_field(dev, cdb[7]); } break; @@ -3481,8 +3166,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_stop(sc); break; case 1: /* Start the disc and read the TOC. */ - /* This makes no sense under emulation as this would do - absolutely nothing, so just break. */ + /* + This makes no sense under emulation as this would do + absolutely nothing, so just break. + */ break; case 2: /* Eject the disc if possible. */ scsi_cdrom_stop(sc); @@ -3512,11 +3199,15 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) preamble_len = 4; size_idx = 3; - dev->buffer[idx++] = 5; - dev->buffer[idx++] = cdb[2]; - dev->buffer[idx++] = 0; + if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) + dev->buffer[idx++] = 0x7f; /* No physical device on this LUN */ + else + dev->buffer[idx++] = 0x05; /* CD-ROM */ - idx++; + dev->buffer[idx++] = cdb[2]; + + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 0x00; switch (cdb[2]) { case 0x00: @@ -3525,7 +3216,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) break; case 0x83: if (idx + 24 > max_len) { - scsi_cdrom_data_phase_error(dev); + scsi_cdrom_data_phase_error(dev, idx + 24); scsi_cdrom_buf_free(dev); return; } @@ -3533,37 +3224,33 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[idx++] = 0x02; dev->buffer[idx++] = 0x00; dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 20; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ + dev->buffer[idx++] = 0x14; + ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ idx += 20; if (idx + 72 > cdb[4]) goto atapi_out; + dev->buffer[idx++] = 0x02; dev->buffer[idx++] = 0x01; dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 68; - - if (dev->drv->type == CDROM_TYPE_86BOX_100) - ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */ - else - ide_padstr8(dev->buffer + idx, 8, cdrom_drive_types[dev->drv->type].vendor); /* Vendor */ + dev->buffer[idx++] = 34; + ide_padstr8(dev->buffer + idx, 8, + cdrom_get_vendor(dev->drv->type)); /* Vendor */ idx += 8; - if (dev->drv->type == CDROM_TYPE_86BOX_100) - ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */ - else - ide_padstr8(dev->buffer + idx, 40, cdrom_drive_types[dev->drv->type].model); /* Product */ + cdrom_get_model(dev->drv->type, model, dev->id); + ide_padstr8(dev->buffer + idx, 16, model); /* Product */ + idx += 16; - idx += 40; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ - idx += 20; + ide_padstr8(dev->buffer + idx, 10, "53R141"); /* Serial */ + idx += 10; break; default: - scsi_cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - scsi_cdrom_invalid_field(dev); + scsi_cdrom_log(dev->log, "INQUIRY: Invalid page: %02X\n", cdb[2]); + scsi_cdrom_invalid_field(dev, cdb[2]); scsi_cdrom_buf_free(dev); return; } @@ -3575,99 +3262,44 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) dev->buffer[0] = 0x7f; /* No physical device on this LUN */ else - dev->buffer[0] = 5; /* CD-ROM */ + dev->buffer[0] = 0x05; /* CD-ROM */ + dev->buffer[1] = 0x80; /* Removable */ if (dev->drv->bus_type == CDROM_BUS_SCSI) { - dev->buffer[3] = 0x02; - switch (dev->drv->type) { - case CDROM_TYPE_CHINON_CDS431_H42: - case CDROM_TYPE_CHINON_CDX435_M62: - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_MATSHITA_501_10b: - case CDROM_TYPE_ShinaKen_DM3x1S_104: - case CDROM_TYPE_SONY_CDU541_10i: - case CDROM_TYPE_TEXEL_DM3024_100: - dev->buffer[2] = 0x00; - dev->buffer[3] = 0x01; /* SCSI-1 compliant */ - break; - case CDROM_TYPE_TEXEL_DM3028_106: - dev->buffer[2] = 0x02; - dev->buffer[3] = 0x01; /* SCSI-2 compliant */ - break; - case CDROM_TYPE_NEC_25_10a: - case CDROM_TYPE_NEC_75_103: - case CDROM_TYPE_NEC_77_106: - dev->buffer[3] = 0x00; /* SCSI unknown version per NEC manuals */ - break; - case CDROM_TYPE_TOSHIBA_XM3201B_3232: - dev->buffer[2] = 0x01; - dev->buffer[3] = 0x01; /* SCSI-1 compliant */ - break; - default: - dev->buffer[2] = 0x02; /* SCSI-2 compliant */ - break; - } + dev->buffer[3] = cdrom_get_scsi_std(dev->drv->type); + + if (!strcmp(cdrom_get_vendor(dev->drv->type), "TOSHIBA")) + /* Linked Command and Relative Addressing supported */ + dev->buffer[7] = 0x88; } else { dev->buffer[2] = 0x00; dev->buffer[3] = 0x21; } - dev->buffer[4] = 31; - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - switch (dev->drv->type) { - case CDROM_TYPE_TOSHIBA_XM_3433 ... CDROM_TYPE_TOSHIBA_XM5701TA_3136: - dev->buffer[4] = 91; /* - Always 91 on Toshiba SCSI-1 (or SCSI-2) - CD-ROM drives from 1989-1990 - */ - dev->buffer[7] = 0x88; /* Linked Command and Relative Addressing supported */ - break; - case CDROM_TYPE_PIONEER_DRM604X_2403: - dev->buffer[4] = 42; - break; - case CDROM_TYPE_NEC_25_10a: - case CDROM_TYPE_NEC_38_103: - case CDROM_TYPE_NEC_75_103: - case CDROM_TYPE_NEC_77_106: - break; - default: - dev->buffer[6] = 0x01; /* 16-bit transfers supported */ - dev->buffer[7] = 0x20; /* Wide bus supported */ - break; - } + if (cdrom_is_generic(dev->drv->type)) { + dev->buffer[6] = 0x01; /* 16-bit transfers supported */ + dev->buffer[7] = 0x20; /* Wide bus supported */ } - if (dev->drv->type == CDROM_TYPE_86BOX_100) { - ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */ - } else { - ide_padstr8(dev->buffer + 8, 8, cdrom_drive_types[dev->drv->type].vendor); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, cdrom_drive_types[dev->drv->type].model); /* Product */ - ide_padstr8(dev->buffer + 32, 4, cdrom_drive_types[dev->drv->type].revision); /* Revision */ - if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) { - dev->buffer[36] = 0x20; - ide_padstr8(dev->buffer + 37, 10, "1991/01/01"); /* Date */ - } + ide_padstr8(dev->buffer + 8, 8, + cdrom_get_vendor(dev->drv->type)); /* Vendor */ + cdrom_get_model(dev->drv->type, model, dev->id); + ide_padstr8(dev->buffer + 16, 16, model); /* Product */ + ide_padstr8(dev->buffer + 32, 4, + cdrom_get_revision(dev->drv->type)); /* Revision */ + + if (cdrom_has_date(dev->drv->type)) { + dev->buffer[36] = 0x20; + ide_padstr8(dev->buffer + 37, 10, "1991/01/01"); /* Date */ } - idx = 36; - if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) - idx = 47; - else { - switch (dev->drv->type) { - case CDROM_TYPE_TOSHIBA_XM_3433 ... CDROM_TYPE_TOSHIBA_XM5701TA_3136: - idx = 96; - break; - default: - if (max_len == 96) { - dev->buffer[4] = 91; - idx = 96; - } - break; - } - } + if (max_len == 96) + idx = 96; + else + idx = cdrom_get_inquiry_len(dev->drv->bus_type); + + dev->buffer[4] = idx - 5; } atapi_out: @@ -3677,7 +3309,8 @@ atapi_out: len = MIN(len, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &max_len); - scsi_cdrom_log("Inquiry = %d, max = %d, BufLen = %d.\n", len, max_len, *BufLen); + scsi_cdrom_log(dev->log, "Inquiry = %d, max = %d, BufLen = %d.\n", len, + max_len, *BufLen); scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); break; @@ -3712,17 +3345,9 @@ atapi_out: dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); - if (cdb[0] == GPCMD_SEEK_10) { - switch (dev->drv->type) { - case CDROM_TYPE_NEC_25_10a ... CDROM_TYPE_NEC_464_105: - case CDROM_TYPE_TOSHIBA_XM_3433 ... CDROM_TYPE_TOSHIBA_SDM1401_1008: - cdrom_seek(dev->drv, pos, cdb[9] & 0xc0); - break; - default: - cdrom_seek(dev->drv, pos, 0); - break; - } - } else + if (dev->use_cdb_9 && (cdb[0] == GPCMD_SEEK_10)) + cdrom_seek(dev->drv, pos, cdb[9] & 0xc0); + else cdrom_seek(dev->drv, pos, 0); scsi_cdrom_command_complete(dev); @@ -3742,7 +3367,8 @@ atapi_out: dev->buffer[6] = 8; len = 8; - scsi_cdrom_log("CD-ROM Capacity=%x.\n", dev->drv->cdrom_capacity - 1); + scsi_cdrom_log(dev->log, "CD-ROM Capacity: %08X\n", + dev->drv->cdrom_capacity - 1); scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -3751,7 +3377,7 @@ atapi_out: case GPCMD_STOP_PLAY_SCAN: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if (dev->drv->cd_status <= CD_STATUS_DATA_ONLY) { + if (dev->drv->cd_status <= CD_STATUS_DVD) { scsi_cdrom_illegal_mode(dev); break; } @@ -3761,11 +3387,11 @@ atapi_out: break; default: - scsi_cdrom_illegal_opcode(dev); + scsi_cdrom_illegal_opcode(dev, cdb[0]); break; } - /* scsi_cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->tf->phase, + /* scsi_cdrom_log(dev->log, "Phase: %02X, request length: %i\n", dev->tf->phase, dev->tf->request_length); */ if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) @@ -3789,15 +3415,14 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) uint16_t block_desc_len; uint16_t pos; uint16_t param_list_len; - uint16_t i = 0; - - uint8_t error = 0; - uint8_t page; - uint8_t page_len; - uint8_t hdr_len; - uint8_t val; - uint8_t old_val; - uint8_t ch; + uint16_t i; + uint8_t error = 0; + uint8_t page; + uint8_t page_len; + uint8_t hdr_len; + uint8_t val; + uint8_t old_val; + uint8_t ch; switch (dev->current_cdb[0]) { case GPCMD_MODE_SELECT_6: @@ -3817,7 +3442,8 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) block_desc_len = dev->buffer[2]; block_desc_len <<= 8; block_desc_len |= dev->buffer[3]; - scsi_cdrom_log("BlockDescLen (6)=%d, ParamListLen (6)=%d.\n", block_desc_len, param_list_len); + scsi_cdrom_log(dev->log, "BlockDescLen (6): %d, " + "ParamListLen (6): %d\n", block_desc_len, param_list_len); } else { block_desc_len = dev->buffer[6]; block_desc_len <<= 8; @@ -3829,21 +3455,28 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) if (block_desc_len >= 8) { pos = hdr_len + 5; - dev->drv->sector_size = (dev->drv->sector_size & 0x0000ffff) | (dev->buffer[pos++] << 16); - dev->drv->sector_size = (dev->drv->sector_size & 0x00ff00ff) | (dev->buffer[pos++] << 8); - dev->drv->sector_size = (dev->drv->sector_size & 0x00ffff00) | (dev->buffer[pos++]); - scsi_cdrom_log("CD-ROM %i: Sector size now %i bytes\n", dev->id, dev->drv->sector_size); + dev->drv->sector_size = (dev->drv->sector_size & 0x0000ffff) | + (dev->buffer[pos++] << 16); + dev->drv->sector_size = (dev->drv->sector_size & 0x00ff00ff) | + (dev->buffer[pos++] << 8); + dev->drv->sector_size = (dev->drv->sector_size & 0x00ffff00) | + (dev->buffer[pos]); + scsi_cdrom_log(dev->log, "Sector size now %i bytes\n", + dev->drv->sector_size); + + error |= scsi_cdrom_update_sector_flags(dev); } pos = hdr_len + block_desc_len; #ifdef ENABLE_SCSI_CDROM_LOG for (uint16_t j = 0; j < pos; j++) - scsi_cdrom_log("Buffer Mode Select, pos=%d, data=%02x.\n", j, dev->buffer[j]); + scsi_cdrom_log(dev->log, "Buffer Mode Select, pos=%d, data=%02x.\n", + j, dev->buffer[j]); #endif - while (1) { + if (!error) while (1) { if (pos >= param_list_len) { - scsi_cdrom_log("CD-ROM %i: Buffer has only block descriptor\n", dev->id); + scsi_cdrom_log(dev->log, "Buffer has only block descriptor\n"); break; } @@ -3852,71 +3485,39 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) pos += 2; - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - if ((page == 0x08) && (page_len == 0x02)) - dev->drv->sony_msf = dev->buffer[pos] & 0x01; + if (dev->is_sony && (page == 0x08) && (page_len == 0x02)) + dev->drv->sony_msf = dev->buffer[pos] & 0x01; - if (!(scsi_cdrom_mode_sense_page_flags_sony & (1LL << ((uint64_t) page)))) { - scsi_cdrom_log("CD-ROM %i: Unimplemented page %02X\n", dev->id, page); - error |= 1; - } else { - for (i = 0; i < page_len; i++) { - ch = scsi_cdrom_mode_sense_pages_changeable_sony.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved_sony.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved_sony.pages[page][i + 2] = val; - else { - scsi_cdrom_log("CD-ROM %i: Unchangeable value on position " - "%02X on page %02X\n", dev->id, i + 2, page); - error |= 1; - } - } + if (!(dev->ms_page_flags & (1LL << ((uint64_t) page)))) { + scsi_cdrom_log(dev->log, "Unimplemented page %02X\n", page); + error |= 1; + } else { + 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)) + pg = GPMODE_CDROM_AUDIO_PAGE; + + ch = dev->ms_pages_changeable.pages[pg][i + 2]; + val = dev->buffer[pos + i]; + old_val = dev->ms_pages_saved.pages[pg][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[pg][i + 2] = val; + else { + scsi_cdrom_log(dev->log, "Unchangeable value on position " + "%02X on page %02X\n", i + 2, page); + scsi_cdrom_invalid_field_pl(dev, val); + error |= 1; } } - break; - default: - if (!(scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { - scsi_cdrom_log("CD-ROM %i: Unimplemented page %02X\n", dev->id, page); - error |= 1; - } else { - for (i = 0; i < page_len; i++) { - ch = scsi_cdrom_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else { - scsi_cdrom_log("CD-ROM %i: Unchangeable value on position " - "%02X on page %02X\n", dev->id, i + 2, page); - error |= 1; - } - } - } - } - break; + } } pos += page_len; - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - val = scsi_cdrom_mode_sense_pages_default_sony_scsi.pages[page][0] & 0x80; - break; - default: - if (dev->drv->bus_type == CDROM_BUS_SCSI) - val = scsi_cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = scsi_cdrom_mode_sense_pages_default.pages[page][0] & 0x80; - break; - } + val = dev->ms_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) scsi_cdrom_mode_sense_save(dev); @@ -3925,21 +3526,20 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) } if (error) { - scsi_cdrom_invalid_field_pl(dev); scsi_cdrom_buf_free(dev); return 0; } break; - case 0xC9: - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - for (i = 0; i < 18; i++) - dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY][i] = dev->buffer[i]; - break; - default: - break; + case 0xc9: + if (dev->is_sony) { + for (i = 0; i < 18; i++) { + if ((i >= 8) && (i <= 15)) + dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][i] = + dev->buffer[i]; + else + dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE_SONY][i] = + dev->buffer[i]; + } } break; @@ -3956,30 +3556,31 @@ scsi_cdrom_close(void *priv) { scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; - if (dev->tf) - free(dev->tf); + if (dev != NULL) { + if (dev->tf != NULL) + free(dev->tf); + + if (dev->log != NULL) { + scsi_cdrom_log(dev->log, "Log closed\n"); + + log_close(dev->log); + dev->log = NULL; + } - if (dev) free(dev); + } } static int -scsi_cdrom_get_max(int ide_has_dma, int type) +scsi_cdrom_get_max(const ide_t *ide, const int ide_has_dma, const int type) { - int ret; + const scsi_cdrom_t *dev = (scsi_cdrom_t *) ide->sc; + int ret; switch (type) { - case TYPE_PIO: - ret = ide_has_dma ? 4 : 0; - break; - case TYPE_SDMA: - ret = ide_has_dma ? 2 : -1; - break; - case TYPE_MDMA: - ret = ide_has_dma ? 2 : -1; - break; - case TYPE_UDMA: - ret = ide_has_dma ? 5 : -1; + case TYPE_PIO: case TYPE_SDMA: + case TYPE_MDMA: case TYPE_UDMA: + ret = cdrom_get_transfer_max(dev->drv->type, type); break; default: ret = -1; @@ -3990,16 +3591,18 @@ scsi_cdrom_get_max(int ide_has_dma, int type) } static int -scsi_cdrom_get_timings(int ide_has_dma, int type) +scsi_cdrom_get_timings(const ide_t *ide, const int ide_has_dma, const int type) { - int ret; + const scsi_cdrom_t *dev = (scsi_cdrom_t *) ide->sc; + int has_dma = cdrom_has_dma(dev->drv->type); + int ret; switch (type) { case TIMINGS_DMA: - ret = ide_has_dma ? 120 : 0; + ret = has_dma ? 120 : 0; break; case TIMINGS_PIO: - ret = ide_has_dma ? 120 : 0; + ret = has_dma ? 120 : 0; break; case TIMINGS_PIO_FC: ret = 0; @@ -4016,194 +3619,29 @@ scsi_cdrom_get_timings(int ide_has_dma, int type) * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command */ static void -scsi_cdrom_identify(ide_t *ide, int ide_has_dma) +scsi_cdrom_identify(const ide_t *ide, const int ide_has_dma) { - const scsi_cdrom_t *dev; - char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; + const scsi_cdrom_t *dev = (scsi_cdrom_t *) ide->sc; + char model[2048] = { 0 }; + const int has_dma = cdrom_has_dma(dev->drv->type); - dev = (scsi_cdrom_t *) ide->sc; + cdrom_get_identify_model(dev->drv->type, model, dev->id); - device_identify[7] = dev->id + 0x30; - scsi_cdrom_log("ATAPI Identify: %s\n", device_identify); + scsi_cdrom_log(dev->log, "ATAPI Identify: %s\n", model); - if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) /*NEC only*/ + if (dev->drv->is_early) ide->buffer[0] = 0x8000 | (5 << 8) | 0x80 | (1 << 5); /* ATAPI device, CD-ROM drive, removable media, interrupt DRQ */ else ide->buffer[0] = 0x8000 | (5 << 8) | 0x80 | (2 << 5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - if (dev->drv->type == CDROM_TYPE_86BOX_100) { - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - } else { - switch (dev->drv->type) { - case CDROM_TYPE_ASUS_CDS500_141: - ide_padstr((char *) (ide->buffer + 23), "1.41 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "ASUS CD-S500/A ", 40); /* Model */ - break; - case CDROM_TYPE_ASUS_CDS520_132: - ide_padstr((char *) (ide->buffer + 23), "1.32 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "ASUS CD-S520/A4 ", 40); /* Model */ - break; - case CDROM_TYPE_AZT_CDA46802I_115: - ide_padstr((char *) (ide->buffer + 23), "1.15 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "AZT CDA46802I ", 40); /* Model */ - break; - case CDROM_TYPE_BTC_BCD36XH_U10: - ide_padstr((char *) (ide->buffer + 23), "U1.0 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "BTC CD-ROM BCD36XH ", 40); /* Model */ - break; - case CDROM_TYPE_GOLDSTAR_CRD_8160B_314: - ide_padstr((char *) (ide->buffer + 23), "3.14 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "GOLDSTAR CRD-8160B ", 40); /* Model */ - break; - case CDROM_TYPE_HITACHI_CDR_8130_0020: - ide_padstr((char *) (ide->buffer + 23), "0020 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "HITACHI CDR-8130 ", 40); /* Model */ - break; - case CDROM_TYPE_HITACHI_GD7500_A1: - ide_padstr((char *) (ide->buffer + 23), "A1 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "HITACHI GD-7500 ", 40); /* Model */ - break; - case CDROM_TYPE_HLDTST_GCR8526B_101: - ide_padstr((char *) (ide->buffer + 23), "1.01 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST CD-ROM GCR-8526B ", 40); /* Model */ - break; - case CDROM_TYPE_HLDTST_GSA4160_A302: - ide_padstr((char *) (ide->buffer + 23), "A302 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "HL-DT-ST DVDRAM GSA-4160 ", 40); /* Model */ - break; - case CDROM_TYPE_KENWOOD_UCR_421_208E: - ide_padstr((char *) (ide->buffer + 23), "208E ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "KENWOOD CD-ROM UCR-421 ", 40); /* Model */ - break; - case CDROM_TYPE_LG_CRN8245B_130: - ide_padstr((char *) (ide->buffer + 23), "1.30 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "LG CD-ROM CRN-8245B ", 40); /* Model */ - break; - case CDROM_TYPE_LG_CRD8322B_106: - ide_padstr((char *) (ide->buffer + 23), "1.06 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "LG CD-ROM CRD-8322B ", 40); /* Model */ - break; - case CDROM_TYPE_LTN48125S_1S07: - ide_padstr((char *) (ide->buffer + 23), "1S07 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "LTN48125S ", 40); /* Model */ - break; - case CDROM_TYPE_LTN526D_YSR5: - ide_padstr((char *) (ide->buffer + 23), "YSR5 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "LTN526D ", 40); /* Model */ - break; - case CDROM_TYPE_MATSHITA_583_107: - ide_padstr((char *) (ide->buffer + 23), "1.07 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-583 ", 40); /* Model */ - break; - case CDROM_TYPE_MATSHITA_585_Z18P: - ide_padstr((char *) (ide->buffer + 23), "Z18P ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-585 ", 40); /* Model */ - break; - case CDROM_TYPE_MATSHITA_587_7S13: - ide_padstr((char *) (ide->buffer + 23), "7S13 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-587 ", 40); /* Model */ - break; - case CDROM_TYPE_MATSHITA_588_LS15: - ide_padstr((char *) (ide->buffer + 23), "LS15 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-588 ", 40); /* Model */ - break; - case CDROM_TYPE_MATSHITA_571_10e: - ide_padstr((char *) (ide->buffer + 23), "1.0e ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-571 ", 40); /* Model */ - break; - case CDROM_TYPE_MATSHITA_572_10j: - ide_padstr((char *) (ide->buffer + 23), "1.0j ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-572 ", 40); /* Model */ - break; - case CDROM_TYPE_MITSUMI_FX4820T_D02A: - ide_padstr((char *) (ide->buffer + 23), "D02A ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "MITSUMI CRMC-FX4820T ", 40); /* Model */ - break; - case CDROM_TYPE_NEC_260_100: - ide_padstr((char *) (ide->buffer + 23), ".100 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "EN C DCR-MOD IREV2:06 ", 40); /* Model */ - break; - case CDROM_TYPE_NEC_260_101: - ide_padstr((char *) (ide->buffer + 23), ".110 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "EN C DCR-MOD IREV2:06 ", 40); /* Model */ - break; - case CDROM_TYPE_NEC_273_420: - ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */ - break; - case CDROM_TYPE_NEC_280_105: - ide_padstr((char *) (ide->buffer + 23), "1.05 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */ - break; - case CDROM_TYPE_NEC_280_308: - ide_padstr((char *) (ide->buffer + 23), "3.08 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */ - break; - case CDROM_TYPE_NEC_CDR_1900A_100: - ide_padstr((char *) (ide->buffer + 23), "1.00 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "NEC CDR-1900A ", 40); /* Model */ - break; - case CDROM_TYPE_PHILIPS_PCA403CD_U31P: - ide_padstr((char *) (ide->buffer + 23), "U31P ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "PHILIPS CD-ROM PCA403CD ", 40); /* Model */ - break; - case CDROM_TYPE_SONY_CDU76_10i: - ide_padstr((char *) (ide->buffer + 23), "1.0i ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU76 ", 40); /* Model */ - break; - case CDROM_TYPE_SONY_CDU311_30h: - ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */ - break; - case CDROM_TYPE_SONY_CDU5225_NYS4: - ide_padstr((char *) (ide->buffer + 23), "NYS4 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU5225 ", 40); /* Model */ - break; - case CDROM_TYPE_TEAC_CD516E_10G: - ide_padstr((char *) (ide->buffer + 23), "1.0G ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TEAC CD-516E ", 40); /* Model */ - break; - case CDROM_TYPE_TEAC_CD524EA_30D: - ide_padstr((char *) (ide->buffer + 23), "3.0D ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TEAC CD-524EA ", 40); /* Model */ - break; - case CDROM_TYPE_TEAC_CD532E_20A: - ide_padstr((char *) (ide->buffer + 23), "2.0A ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TEAC CD-532E ", 40); /* Model */ - break; - case CDROM_TYPE_TOSHIBA_5302TA_0305: - ide_padstr((char *) (ide->buffer + 23), "0305 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5302TA ", 40); /* Model */ - break; - case CDROM_TYPE_TOSHIBA_5702B_TA70: - ide_padstr((char *) (ide->buffer + 23), "TA70 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5702B ", 40); /* Model */ - break; - case CDROM_TYPE_TOSHIBA_6202B_1512: - ide_padstr((char *) (ide->buffer + 23), "1512 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6202B ", 40); /* Model */ - break; - case CDROM_TYPE_TOSHIBA_6402B_1008: - ide_padstr((char *) (ide->buffer + 23), "1008 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6402B ", 40); /* Model */ - break; - case CDROM_TYPE_TOSHIBA_6702B_1007: - ide_padstr((char *) (ide->buffer + 23), "1007 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-6702B ", 40); /* Model */ - break; - case CDROM_TYPE_TOSHIBA_M1802_1051: - ide_padstr((char *) (ide->buffer + 23), "1051 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "TOSHIBA DVD-ROM SD-M1802 ", 40); /* Model */ - break; - } - } + ide_padstr((char *) (ide->buffer + 23), cdrom_get_revision(dev->drv->type), 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ ide->buffer[49] = 0x200; /* LBA supported */ ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ - if (ide_has_dma) { + if (has_dma) { ide->buffer[71] = 30; ide->buffer[72] = 30; ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ @@ -4212,14 +3650,11 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma) } void -scsi_cdrom_drive_reset(int c) +scsi_cdrom_drive_reset(const int c) { cdrom_t *drv = &cdrom[c]; - scsi_cdrom_t *dev; - scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus = (drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = drv->scsi_device_id & 0x0f; + const uint8_t scsi_bus = (drv->scsi_device_id >> 4) & 0x0f; + const uint8_t scsi_id = drv->scsi_device_id & 0x0f; uint8_t valid = 0; if (drv->bus_type == CDROM_BUS_SCSI) { @@ -4236,12 +3671,17 @@ scsi_cdrom_drive_reset(int c) if ((drv->bus_type == CDROM_BUS_ATAPI) && (drv->ide_channel > 7)) return; - if (!drv->priv) { - drv->priv = (scsi_cdrom_t *) malloc(sizeof(scsi_cdrom_t)); - memset(drv->priv, 0, sizeof(scsi_cdrom_t)); + if (drv->priv == NULL) { + drv->priv = (scsi_cdrom_t *) calloc(1, sizeof(scsi_cdrom_t)); + scsi_cdrom_t *dev = (scsi_cdrom_t *) drv->priv; + + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i SCSI ", c + 1); + dev->log = log_open(n); } - dev = (scsi_cdrom_t *) drv->priv; + scsi_cdrom_t *dev = (scsi_cdrom_t *) drv->priv; dev->id = c; dev->drv = drv; @@ -4254,80 +3694,106 @@ scsi_cdrom_drive_reset(int c) drv->close = scsi_cdrom_close; drv->sector_size = 2048; + (void) scsi_cdrom_update_sector_flags(dev); if (drv->bus_type == CDROM_BUS_SCSI) { - valid = 1; + char *vendor = cdrom_get_vendor(dev->drv->type); - if (!dev->tf) - dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); + 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")) + dev->ven_cmd = scsi_cdrom_command_chinon; + else if (!strcmp(vendor, "DEC") || !strcmp(vendor, "ShinaKen") || + !strcmp(vendor, "SONY") || !strcmp(vendor, "TEXEL")) { + 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; + } else if (!strcmp(vendor, "MATSHITA")) + dev->ven_cmd = scsi_cdrom_command_matsushita; + else if (!strcmp(vendor, "NEC")) { + 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")) { + 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")) { + dev->ven_cmd = scsi_cdrom_command_toshiba; + dev->ven_cmd_is_data[0xc6] = 1; + dev->ven_cmd_is_data[0xc7] = 1; + dev->use_cdb_9 = 1; + } + + if (dev->tf == NULL) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); /* SCSI CD-ROM, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + scsi_device_t *sd = &scsi_devices[scsi_bus][scsi_id]; - sd->sc = (scsi_common_t *) dev; - sd->command = scsi_cdrom_command; - sd->request_sense = scsi_cdrom_request_sense_for_scsi; - sd->reset = scsi_cdrom_reset; - sd->phase_data_out = scsi_cdrom_phase_data_out; - sd->command_stop = scsi_cdrom_command_stop; - sd->type = SCSI_REMOVABLE_CDROM; + sd->sc = (scsi_common_t *) dev; + sd->command = scsi_cdrom_command; + sd->request_sense = scsi_cdrom_request_sense_for_scsi; + sd->reset = scsi_cdrom_reset; + sd->phase_data_out = scsi_cdrom_phase_data_out; + sd->command_stop = scsi_cdrom_command_stop; + sd->type = SCSI_REMOVABLE_CDROM; - scsi_cdrom_log("SCSI CD-ROM drive %i attached to SCSI ID %i\n", c, cdrom[c].scsi_device_id); + valid = 1; + + scsi_cdrom_log(dev->log, "SCSI CD-ROM drive %i attached to SCSI ID %i\n", + c, cdrom[c].scsi_device_id); } else if (drv->bus_type == CDROM_BUS_ATAPI) { /* ATAPI CD-ROM, attach to the IDE bus. */ - id = ide_get_drive(drv->ide_channel); - /* If the IDE channel is initialized, we attach to it, - otherwise, we do nothing - it's going to be a drive - that's not attached to anything. */ - if (id) { - valid = 1; + ide_t *id = ide_get_drive(drv->ide_channel); - id->sc = (scsi_common_t *) dev; - dev->tf = id->tf; - if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) - IDE_ATAPI_IS_EARLY = 1; - id->get_max = scsi_cdrom_get_max; - id->get_timings = scsi_cdrom_get_timings; - id->identify = scsi_cdrom_identify; - id->stop = scsi_cdrom_stop; - id->packet_command = scsi_cdrom_command; - id->device_reset = scsi_cdrom_reset; - 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->interrupt_drq = ((dev->drv->type == CDROM_TYPE_NEC_260_100) || - (dev->drv->type == CDROM_TYPE_NEC_260_101)); + /* + If the IDE channel is initialized, we attach to it, otherwise, we do + nothing - it's going to be a drive that's not attached to anything. + */ + 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; + dev->ms_pages_changeable = scsi_cdrom_ms_pages_changeable; + + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = dev->drv->is_early; + id->get_max = scsi_cdrom_get_max; + id->get_timings = scsi_cdrom_get_timings; + id->identify = scsi_cdrom_identify; + id->stop = scsi_cdrom_stop; + id->packet_command = scsi_cdrom_command; + id->device_reset = scsi_cdrom_reset; + 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->interrupt_drq = dev->drv->is_early; + + valid = 1; ide_atapi_attach(id); } - scsi_cdrom_log("ATAPI CD-ROM drive %i attached to IDE channel %i\n", c, cdrom[c].ide_channel); - } - - switch (dev->drv->type) { - case CDROM_TYPE_CHINON_CDS431_H42: - dev->ven_cmd = scsi_cdrom_command_chinon; - break; - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_ShinaKen_DM3x1S_104 ... CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DM3024_100 ... CDROM_TYPE_TEXEL_DM3028_106: - dev->ven_cmd = scsi_cdrom_command_dec_sony_texel; - break; - case CDROM_TYPE_MATSHITA_501_10b: - dev->ven_cmd = scsi_cdrom_command_matsushita; - break; - case CDROM_TYPE_NEC_25_10a ... CDROM_TYPE_NEC_464_105: - dev->ven_cmd = scsi_cdrom_command_nec; - break; - case CDROM_TYPE_PIONEER_DRM604X_2403: - dev->ven_cmd = scsi_cdrom_command_pioneer; - break; - case CDROM_TYPE_TOSHIBA_XM_3433 ... CDROM_TYPE_TOSHIBA_SDM1401_1008: - dev->ven_cmd = scsi_cdrom_command_toshiba; - break; - default: - dev->ven_cmd = NULL; - break; + scsi_cdrom_log(dev->log, "ATAPI CD-ROM drive %i attached to IDE channel %i\n", + c, cdrom[c].ide_channel); } if (valid) diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 10fdf04a6..c11f09443 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -12,26 +12,24 @@ * * Copyright 2017-2018 Miran Grca. */ -#include #include #include -#include +#ifdef ENABLE_SCSI_DISK_LOG +#include +#endif #include +#include #include #include -#include -#define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/config.h> #include <86box/timer.h> #include <86box/device.h> +#include <86box/log.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/machine.h> #include <86box/nvr.h> -#include <86box/hdc.h> #include <86box/hdc_ide.h> -#include <86box/sound.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/hdd.h> @@ -42,86 +40,71 @@ #define scsi_disk_sense_error dev->sense[0] #define scsi_disk_sense_key dev->sense[2] +#define scsi_disk_info *(uint32_t *) &(dev->sense[3]) #define scsi_disk_asc dev->sense[12] #define scsi_disk_ascq dev->sense[13] -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +// clang-format off +/* + Table of all SCSI commands and their flags, needed for the new disc change / + not ready handler. + */ const uint8_t scsi_disk_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ - 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ - 0, 0, - IMPLEMENTED, /* 0x1A */ - 0, 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - IMPLEMENTED | CHECK_READY, /* 0x41 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ - 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0xBD */ - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + [0x00] = IMPLEMENTED | CHECK_READY, + [0x01] = IMPLEMENTED | ALLOW_UA | SCSI_ONLY, + [0x03] = IMPLEMENTED | ALLOW_UA, + [0x04] = IMPLEMENTED | CHECK_READY | ALLOW_UA | SCSI_ONLY, + [0x08] = IMPLEMENTED | CHECK_READY, + [0x0a ... 0x0b] = IMPLEMENTED | CHECK_READY, + [0x12] = IMPLEMENTED | ALLOW_UA, + [0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x15] = IMPLEMENTED, + [0x16 ... 0x17] = IMPLEMENTED | SCSI_ONLY, + [0x1a] = IMPLEMENTED, + [0x1d] = IMPLEMENTED, + [0x1e] = IMPLEMENTED | CHECK_READY, + [0x25] = IMPLEMENTED | CHECK_READY, + [0x28] = IMPLEMENTED | CHECK_READY, + [0x2a ... 0x2b] = IMPLEMENTED | CHECK_READY, + [0x2e] = IMPLEMENTED | CHECK_READY, + [0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x41] = IMPLEMENTED | CHECK_READY, + [0x55] = IMPLEMENTED, + [0x5a] = IMPLEMENTED, + [0xa8] = IMPLEMENTED | CHECK_READY, + [0xaa] = IMPLEMENTED | CHECK_READY, + [0xae] = IMPLEMENTED | CHECK_READY, + [0xaf] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xbd] = IMPLEMENTED }; -uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_FORMAT_DEVICE_PAGE | GPMODEP_RIGID_DISK_PAGE | GPMODEP_UNK_VENDOR_PAGE | GPMODEP_ALL_PAGES); +uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_FORMAT_DEVICE_PAGE | GPMODEP_RIGID_DISK_PAGE | + GPMODEP_UNK_VENDOR_PAGE | GPMODEP_ALL_PAGES); -/* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = { - {[GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [GPMODE_RIGID_DISK_PAGE] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 200, 0xff, 0xff, 0xff, 0, 0, 0, 0x15, 0x18, 0, 0 }, - [GPMODE_UNK_VENDOR_PAGE] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }} + { [0x03] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x04] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x15, 0x18, 0x00, 0x00 }, + [0x30] = { GPMODE_UNK_VENDOR_PAGE | 0x80, 0x16, '8' , '6' , 'B' , 'o' , 'x' , ' ' , + ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , + ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' } } }; static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = { - {[GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [GPMODE_RIGID_DISK_PAGE] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [GPMODE_UNK_VENDOR_PAGE] = { 0xB0, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }} + { [0x03] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x04] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x30] = { GPMODE_UNK_VENDOR_PAGE | 0x80, 0x16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } }; +// clang-format on static void scsi_disk_command_complete(scsi_disk_t *dev); @@ -133,116 +116,116 @@ static void scsi_disk_init(scsi_disk_t *dev); int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; static void -scsi_disk_log(const char *fmt, ...) +scsi_disk_log(void *priv, const char *fmt, ...) { va_list ap; if (scsi_disk_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define scsi_disk_log(fmt, ...) +# define scsi_disk_log(priv, fmt, ...) #endif static void -scsi_disk_set_callback(scsi_disk_t *dev) +scsi_disk_set_callback(const scsi_disk_t *dev) { - if (dev->drv->bus != HDD_BUS_SCSI) + if (dev->drv->bus_type != HDD_BUS_SCSI) ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); } static void scsi_disk_init(scsi_disk_t *dev) { - if (!dev) - return; + if (dev != NULL) { + /* Do a reset (which will also rezero it). */ + scsi_disk_reset((scsi_common_t *) dev); - /* Do a reset (which will also rezero it). */ - scsi_disk_reset((scsi_common_t *) dev); + /* Configure the drive. */ + dev->requested_blocks = 1; - /* Configure the drive. */ - dev->requested_blocks = 1; + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= HDD_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < HDD_BUS_SCSI) + dev->drv->bus_mode |= 1; + scsi_disk_log(dev->log, "Bus type %i, bus mode %i\n", + dev->drv->bus_type, dev->drv->bus_mode); - dev->drv->bus_mode = 0; - if (dev->drv->bus >= HDD_BUS_ATAPI) - dev->drv->bus_mode |= 2; - if (dev->drv->bus < HDD_BUS_SCSI) - dev->drv->bus_mode |= 1; - scsi_disk_log("SCSI HDD %i: Bus type %i, bus mode %i\n", - dev->id, dev->drv->bus, dev->drv->bus_mode); + dev->sense[0] = 0xf0; + dev->sense[7] = 10; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - /* NEC only */ - dev->tf->status = 0; - dev->tf->pos = 0; - dev->packet_status = PHASE_NONE; - scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = dev->unit_attention = 0; - scsi_disk_mode_sense_load(dev); + dev->tf->status = 0; + dev->tf->pos = 0; + dev->packet_status = PHASE_NONE; + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = dev->unit_attention = 0; + scsi_disk_info = 0x00; + scsi_disk_mode_sense_load(dev); + } } /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int -scsi_disk_current_mode(scsi_disk_t *dev) +scsi_disk_current_mode(const scsi_disk_t *dev) { - if (dev->drv->bus == HDD_BUS_SCSI) - return 2; - else if (dev->drv->bus == HDD_BUS_ATAPI) { - scsi_disk_log("SCSI DISK %i: ATAPI drive, setting to %s\n", dev->id, + int ret = 0; + + if (dev->drv->bus_type == HDD_BUS_SCSI) + ret = 2; + else if (dev->drv->bus_type == HDD_BUS_ATAPI) { + scsi_disk_log(dev->log, "ATAPI drive, setting to %s\n", (dev->tf->features & 1) ? "DMA" : "PIO", dev->id); - return (dev->tf->features & 1) ? 2 : 1; + ret = (dev->tf->features & 1) ? 2 : 1; } - return 0; + return ret; } -void +static void scsi_disk_mode_sense_load(scsi_disk_t *dev) { - FILE *fp; - char file_name[512]; + char file_name[512] = { 0 }; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); - memcpy(&dev->ms_pages_saved, &scsi_disk_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &scsi_disk_mode_sense_pages_default, + sizeof(mode_sense_pages_t)); - memset(file_name, 0, 512); sprintf(file_name, "scsi_disk_%02i_mode_sense.bin", dev->id); - fp = plat_fopen(nvr_path(file_name), "rb"); + FILE *fp = plat_fopen(nvr_path(file_name), "rb"); if (fp) { if (fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, fp) != 0x18) - fatal("scsi_disk_mode_sense_load(): Error reading data\n"); + log_fatal(dev->log, "scsi_disk_mode_sense_load(): Error reading data\n"); fclose(fp); } } -void -scsi_disk_mode_sense_save(scsi_disk_t *dev) +static void +scsi_disk_mode_sense_save(const scsi_disk_t *dev) { - FILE *fp; - char file_name[512]; + char file_name[512] = { 0 }; - memset(file_name, 0, 512); sprintf(file_name, "scsi_disk_%02i_mode_sense.bin", dev->id); - fp = plat_fopen(nvr_path(file_name), "wb"); + FILE *fp = plat_fopen(nvr_path(file_name), "wb"); if (fp) { fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, fp); fclose(fp); } } -/*SCSI Mode Sense 6/10*/ +/* SCSI Mode Sense 6/10 */ uint8_t -scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +scsi_disk_mode_sense_read(const scsi_disk_t *dev, const uint8_t pgctl, + const uint8_t page, const uint8_t pos) { - if (page_control == 1) + if (pgctl == 1) return scsi_disk_mode_sense_pages_changeable.pages[page][pos]; if (page == GPMODE_RIGID_DISK_PAGE) - switch (page_control) { + switch (pgctl) { /* Rigid disk geometry page. */ case 0: case 2: @@ -272,7 +255,7 @@ scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, break; } else if (page == GPMODE_FORMAT_DEVICE_PAGE) - switch (page_control) { + switch (pgctl) { /* Format device page. */ case 0: case 2: @@ -293,7 +276,7 @@ scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, break; } else - switch (page_control) { + switch (pgctl) { case 0: case 3: return dev->ms_pages_saved.pages[page][pos]; @@ -308,16 +291,13 @@ scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, } uint32_t -scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +scsi_disk_mode_sense(const scsi_disk_t *dev, uint8_t *buf, uint32_t pos, + uint8_t page, const uint8_t block_descriptor_len) { - uint8_t msplen; - uint8_t page_control = (page >> 6) & 3; - int size = 0; + int size = hdd_image_get_last_sector(dev->id); page &= 0x3f; - size = hdd_image_get_last_sector(dev->id); - if (block_descriptor_len) { buf[pos++] = 1; /* Density code. */ buf[pos++] = (size >> 16) & 0xff; /* Number of blocks (0 = all). */ @@ -332,12 +312,14 @@ scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { if (scsi_disk_mode_sense_page_flags & (1LL << (uint64_t) page)) { - buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); - msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - scsi_disk_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + const uint8_t pgctl = (page >> 6) & 3; + const uint8_t msplen = scsi_disk_mode_sense_read(dev, pgctl, i, 1); + buf[pos++] = scsi_disk_mode_sense_read(dev, pgctl, i, 0); + buf[pos++] = msplen; + scsi_disk_log(dev->log, "MODE SENSE: Page [%02X] length %i\n", + i, msplen); for (uint8_t j = 0; j < msplen; j++) - buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 2 + j); + buf[pos++] = scsi_disk_mode_sense_read(dev, pgctl, i, 2 + j); } } } @@ -346,7 +328,7 @@ scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, } static void -scsi_disk_update_request_length(scsi_disk_t *dev, int len, int block_len) +scsi_disk_update_request_length(scsi_disk_t *dev, int len, const int block_len) { int bt; int min_len = 0; @@ -407,7 +389,7 @@ scsi_disk_bus_speed(scsi_disk_t *dev) { double ret = -1.0; - if (dev && dev->drv && (dev->drv->bus == HDD_BUS_SCSI)) { + if (dev && dev->drv && (dev->drv->bus_type == HDD_BUS_SCSI)) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { @@ -425,7 +407,7 @@ scsi_disk_bus_speed(scsi_disk_t *dev) void scsi_disk_command_common(scsi_disk_t *dev) { - double bytes_per_second = 0.0; + double bytes_per_second; double period; /* MAP: BUSY_STAT, no DRQ, phase 1. */ @@ -435,6 +417,7 @@ scsi_disk_command_common(scsi_disk_t *dev) dev->callback = 0; if (dev->packet_status == PHASE_COMPLETE) { + switch (dev->current_cdb[0]) { case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: @@ -446,18 +429,19 @@ scsi_disk_command_common(scsi_disk_t *dev) case GPCMD_WRITE_AND_VERIFY_12: case GPCMD_WRITE_SAME_10: /* Seek time is in us. */ - period = hdd_timing_write(dev->drv, dev->drv->seek_pos, dev->drv->seek_len); - scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); + period = hdd_timing_write(dev->drv, dev->drv->seek_pos, + dev->drv->seek_len); + scsi_disk_log(dev->log, "Seek period: %" PRIu64 " us\n", + (uint64_t) period); dev->callback += period; /* Account for seek time. */ bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); period = 1000000.0 / bytes_per_second; - scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, + scsi_disk_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", (uint64_t) period); period = period * (double) (dev->packet_len); - scsi_disk_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, + scsi_disk_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); dev->callback += period; break; @@ -473,8 +457,8 @@ scsi_disk_command_common(scsi_disk_t *dev) /* Seek time is in us. */ period = hdd_seek_get_time(dev->drv, (dev->current_cdb[0] == GPCMD_REZERO_UNIT) ? 0 : dev->sector_pos, HDD_OP_SEEK, 0, 0.0); - scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); + scsi_disk_log(dev->log, "Seek period: %" PRIu64 " us\n", + (uint64_t) period); dev->callback += period; scsi_disk_set_callback(dev); return; @@ -482,9 +466,10 @@ scsi_disk_command_common(scsi_disk_t *dev) case 0x28: case 0xa8: /* Seek time is in us. */ - period = hdd_timing_read(dev->drv, dev->drv->seek_pos, dev->drv->seek_len); - scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); + period = hdd_timing_read(dev->drv, dev->drv->seek_pos, + dev->drv->seek_len); + scsi_disk_log(dev->log, "Seek period: %" PRIu64 " us\n", + (uint64_t) period); dev->callback += period; /* Account for seek time. */ bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); @@ -500,9 +485,11 @@ scsi_disk_command_common(scsi_disk_t *dev) } period = 1000000.0 / bytes_per_second; - scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + scsi_disk_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", + (uint64_t) period); period = period * (double) (dev->packet_len); - scsi_disk_log("SCSI HD %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + scsi_disk_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", + (uint64_t) period); dev->callback += period; } scsi_disk_set_callback(dev); @@ -543,16 +530,19 @@ scsi_disk_command_write_dma(scsi_disk_t *dev) scsi_disk_command_common(dev); } -/* id = Current ZIP device ID; +/* + dev = Pointer to current SCSI disk device; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; - direction = Transfer direction (0 = read from host, 1 = write to host). */ + direction = Transfer direction (0 = read from host, 1 = write to host). + */ static void -scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) +scsi_disk_data_command_finish(scsi_disk_t *dev, int len, const int block_len, + const int alloc_len, const int direction) { - scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, + scsi_disk_log(dev->log, "Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); dev->tf->pos = 0; if (alloc_len >= 0) { @@ -560,13 +550,13 @@ scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int allo len = alloc_len; } if ((len == 0) || (scsi_disk_current_mode(dev) == 0)) { - if (dev->drv->bus != HDD_BUS_SCSI) + if (dev->drv->bus_type != HDD_BUS_SCSI) dev->packet_len = 0; scsi_disk_command_complete(dev); } else { if (scsi_disk_current_mode(dev) == 2) { - if (dev->drv->bus != HDD_BUS_SCSI) + if (dev->drv->bus_type != HDD_BUS_SCSI) dev->packet_len = alloc_len; if (direction == 0) @@ -582,27 +572,27 @@ scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int allo } } - scsi_disk_log("SCSI HD %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, - dev->tf->phase); + scsi_disk_log(dev->log, "Status: %i, cylinder %i, packet length: %i, position: %i, " + "phase: %i\n", + dev->packet_status, dev->tf->request_length, dev->packet_len, + dev->tf->pos, dev->tf->phase); } static void scsi_disk_sense_clear(scsi_disk_t *dev, UNUSED(int command)) { scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; + scsi_disk_info = 0x00000000; } static void -scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) +scsi_disk_set_phase(const scsi_disk_t *dev, const uint8_t phase) { - uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + const uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_id & 0x0f; - if (dev->drv->bus != HDD_BUS_SCSI) - return; - - scsi_devices[scsi_bus][scsi_id].phase = phase; + if (dev->drv->bus_type == HDD_BUS_SCSI) + scsi_devices[scsi_bus][scsi_id].phase = phase; } static void @@ -615,15 +605,16 @@ scsi_disk_cmd_error(scsi_disk_t *dev) dev->packet_status = PHASE_ERROR; dev->callback = 50.0 * SCSI_TIME; scsi_disk_set_callback(dev); - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); - scsi_disk_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); + ui_sb_update_icon(SB_HDD | dev->drv->bus_type, 0); + scsi_disk_log(dev->log, "ERROR: %02X/%02X/%02X\n", scsi_disk_sense_key, + scsi_disk_asc, scsi_disk_ascq); } static void scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len) { - scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len); - if (!dev->temp_buffer) + scsi_disk_log(dev->log, "Allocated buffer length: %i\n", len); + if (dev->temp_buffer == NULL) dev->temp_buffer = (uint8_t *) malloc(len); } @@ -631,7 +622,7 @@ static void scsi_disk_buf_free(scsi_disk_t *dev) { if (dev->temp_buffer) { - scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id); + scsi_disk_log(dev->log, "Freeing buffer...\n"); free(dev->temp_buffer); dev->temp_buffer = NULL; } @@ -644,6 +635,10 @@ scsi_disk_bus_master_error(scsi_common_t *sc) scsi_disk_buf_free(dev); scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; + scsi_disk_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_disk_cmd_error(dev); } @@ -653,6 +648,10 @@ scsi_disk_write_error(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_MEDIUM_ERROR; scsi_disk_asc = ASC_WRITE_ERROR; scsi_disk_ascq = 0; + scsi_disk_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_disk_cmd_error(dev); } @@ -662,25 +661,31 @@ scsi_disk_read_error(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_MEDIUM_ERROR; scsi_disk_asc = ASC_UNRECOVERED_READ_ERROR; scsi_disk_ascq = 0; + scsi_disk_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_disk_cmd_error(dev); } static void -scsi_disk_invalid_lun(scsi_disk_t *dev) +scsi_disk_invalid_lun(scsi_disk_t *dev, const uint8_t lun) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_INV_LUN; scsi_disk_ascq = 0; scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_info = lun << 24; scsi_disk_cmd_error(dev); } static void -scsi_disk_illegal_opcode(scsi_disk_t *dev) +scsi_disk_illegal_opcode(scsi_disk_t *dev, const uint8_t opcode) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_ILLEGAL_OPCODE; scsi_disk_ascq = 0; + scsi_disk_info = opcode << 24; scsi_disk_cmd_error(dev); } @@ -690,54 +695,72 @@ scsi_disk_lba_out_of_range(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; scsi_disk_ascq = 0; + scsi_disk_info = (dev->sector_pos >> 24) | + ((dev->sector_pos >> 16) << 8) | + ((dev->sector_pos >> 8) << 16) | + ( dev->sector_pos << 24); scsi_disk_cmd_error(dev); } static void -scsi_disk_invalid_field(scsi_disk_t *dev) +scsi_disk_invalid_field(scsi_disk_t *dev, const uint32_t field) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; scsi_disk_ascq = 0; + scsi_disk_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); scsi_disk_cmd_error(dev); dev->tf->status = 0x53; } static void -scsi_disk_invalid_field_pl(scsi_disk_t *dev) +scsi_disk_invalid_field_pl(scsi_disk_t *dev, const uint32_t field) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; scsi_disk_ascq = 0; + scsi_disk_info = (field >> 24) | + ((field >> 16) << 8) | + ((field >> 8) << 16) | + ( field << 24); scsi_disk_cmd_error(dev); dev->tf->status = 0x53; } static void -scsi_disk_data_phase_error(scsi_disk_t *dev) +scsi_disk_data_phase_error(scsi_disk_t *dev, const uint32_t info) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_DATA_PHASE_ERROR; scsi_disk_ascq = 0; + scsi_disk_info = (info >> 24) | + ((info >> 16) << 8) | + ((info >> 8) << 16) | + ( info << 24); scsi_disk_cmd_error(dev); } static int -scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), int out) +scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), const int out) { + const uint32_t medium_size = hdd_image_get_last_sector(dev->id) + 1; + *len = 0; - uint32_t medium_size = hdd_image_get_last_sector(dev->id) + 1; if (!dev->sector_len) { scsi_disk_command_complete(dev); return -1; } - scsi_disk_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", + scsi_disk_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); if (dev->sector_pos >= medium_size) { - scsi_disk_log("SCSI HD %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); + scsi_disk_log(dev->log, "Trying to %s beyond the end of disk\n", + out ? "write" : "read"); scsi_disk_lba_out_of_range(dev); return 0; } @@ -746,68 +769,90 @@ scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), int ou for (int i = 0; i < dev->requested_blocks; i++) { if (out) { - if (hdd_image_write(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)) < 0) { + if (hdd_image_write(dev->id, dev->sector_pos, 1, dev->temp_buffer + + (i << 9)) < 0) { scsi_disk_write_error(dev); return -1; } } else { - if (hdd_image_read(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)) < 0) { + if (hdd_image_read(dev->id, dev->sector_pos, 1, dev->temp_buffer + + (i << 9)) < 0) { scsi_disk_read_error(dev); return -1; } } + dev->sector_pos++; } - scsi_disk_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + scsi_disk_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); - dev->sector_pos += dev->requested_blocks; dev->sector_len -= dev->requested_blocks; return 1; } static int -scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) +scsi_disk_pre_execution_check(scsi_disk_t *dev, const uint8_t *cdb) { - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - scsi_disk_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->tf->request_length >> 5) & 7)); - scsi_disk_invalid_lun(dev); + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && + (cdb[1] & 0xe0)) { + scsi_disk_log(dev->log, "Attempting to execute a unknown command " + "targeted at SCSI LUN %i\n", + ((dev->tf->request_length >> 5) & 7)); + scsi_disk_invalid_lun(dev, cdb[1] >> 5); return 0; } if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus == HDD_BUS_SCSI) ? "SCSI" : "ATAPI"); - scsi_disk_illegal_opcode(dev); + scsi_disk_log(dev->log, "Attempting to execute unknown " + "command %02X over %s\n", cdb[0], + (dev->drv->bus_type == HDD_BUS_SCSI) ? "SCSI" : "ATAPI"); + scsi_disk_illegal_opcode(dev, cdb[0]); return 0; } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ + if ((dev->drv->bus_type < HDD_BUS_SCSI) && + (scsi_disk_command_flags[cdb[0]] & SCSI_ONLY)) { + scsi_disk_log(dev->log, "Attempting to execute SCSI-only command %02X " + "over ATAPI\n", cdb[0]); + scsi_disk_illegal_opcode(dev, cdb[0]); + return 0; + } + + if ((dev->drv->bus_type == HDD_BUS_SCSI) && + (scsi_disk_command_flags[cdb[0]] & ATAPI_ONLY)) { + scsi_disk_log(dev->log, "Attempting to execute ATAPI-only command %02X " + "over SCSI\n", cdb[0]); + scsi_disk_illegal_opcode(dev, cdb[0]); + return 0; + } + + /* + Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. + */ if (cdb[0] != GPCMD_REQUEST_SENSE) scsi_disk_sense_clear(dev, cdb[0]); - scsi_disk_log("SCSI HD %i: Continuing with command\n", dev->id); + scsi_disk_log(dev->log, "Continuing with command %02X\n", cdb[0]); return 1; } static void -scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) +scsi_disk_seek(const scsi_disk_t *dev, const uint32_t pos) { - /* scsi_disk_log("SCSI HD %i: Seek %08X\n", dev->id, pos); */ + /* scsi_disk_log(dev->log, "Seek %08X\n", pos); */ hdd_image_seek(dev->id, pos); } static void scsi_disk_rezero(scsi_disk_t *dev) { - if (dev->id == 0xff) - return; - - dev->sector_pos = dev->sector_len = 0; - scsi_disk_seek(dev, 0); + if (dev->id != 0xff) { + dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); + } } void @@ -824,34 +869,38 @@ scsi_disk_reset(scsi_common_t *sc) dev->packet_status = PHASE_NONE; dev->unit_attention = 0; dev->cur_lun = SCSI_LUN_USE_CDB; + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = dev->unit_attention = 0; + scsi_disk_info = 0x00; } void -scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) +scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, + const uint8_t alloc_length, const int desc) { - /*Will return 18 bytes of 0*/ + /* Will return 18 bytes of 0. */ if (alloc_length != 0) { memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, dev->sense, alloc_length); - else { + if (desc) { buffer[1] = scsi_disk_sense_key; buffer[2] = scsi_disk_asc; buffer[3] = scsi_disk_ascq; - } - } else - return; + } else + memcpy(buffer, dev->sense, alloc_length); - buffer[0] = 0x70; + buffer[0] = desc ? 0x70 : 0xf0; + buffer[7] = 10; - scsi_disk_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + scsi_disk_log(dev->log, "Reporting sense: %02X %02X %02X\n", + buffer[2], buffer[12], buffer[13]); - /* Clear the sense stuff as per the spec. */ - scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); + /* Clear the sense stuff as per the spec. */ + scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); + } } static void -scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) +scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, + const uint8_t alloc_length) { scsi_disk_t *dev = (scsi_disk_t *) sc; @@ -859,41 +908,42 @@ scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t all } static void -scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) +scsi_disk_set_buf_len(const scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) { - if (dev->drv->bus == HDD_BUS_SCSI) { + if (dev->drv->bus_type == HDD_BUS_SCSI) { if (*BufLen == -1) *BufLen = *src_len; else { *BufLen = MIN(*src_len, *BufLen); *src_len = *BufLen; } - scsi_disk_log("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); + scsi_disk_log(dev->log, "Actual transfer length: %i\n", *BufLen); } } static void -scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) +scsi_disk_command(scsi_common_t *sc, const uint8_t *cdb) { - scsi_disk_t *dev = (scsi_disk_t *) sc; - int ret; - int32_t blen = 0; - int32_t *BufLen; - int32_t len; - int32_t max_len; - int32_t alloc_length; - int pos = 0; - int idx = 0; - unsigned size_idx; - unsigned preamble_len; - uint32_t last_sector = 0; - char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int block_desc = 0; - uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', + 'v', '1', '.', '0', '0', 0 }; + scsi_disk_t * dev = (scsi_disk_t *) sc; + const uint32_t last_sector = hdd_image_get_last_sector(dev->id); + const uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + int32_t blen = 0; + int pos = 0; + int idx = 0; + int block_desc; + int ret; + int32_t * BufLen; + int32_t len; + int32_t max_len; + int32_t alloc_length; + unsigned size_idx; + unsigned preamble_len; - if (dev->drv->bus == HDD_BUS_SCSI) { + if (dev->drv->bus_type == HDD_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; dev->tf->status &= ~ERR_STAT; } else { @@ -901,8 +951,6 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->tf->error = 0; } - last_sector = hdd_image_get_last_sector(dev->id); - dev->packet_len = 0; dev->request_pos = 0; @@ -918,11 +966,12 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - scsi_disk_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", - dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); - scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->tf->request_length); + scsi_disk_log(dev->log, "Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", + cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); + scsi_disk_log(dev->log, "Request length: %04X\n", dev->tf->request_length); - scsi_disk_log("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + scsi_disk_log(dev->log, "CDB: %02X %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X\n", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); } @@ -931,14 +980,17 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + /* + This handles the Not Ready/Unit Attention check if it has to be + handled at this point. + */ if (scsi_disk_pre_execution_check(dev, cdb) == 0) return; switch (cdb[0]) { case GPCMD_SEND_DIAGNOSTIC: if (!(cdb[1] & (1 << 2))) { - scsi_disk_invalid_field(dev); + scsi_disk_invalid_field(dev, cdb[1]); return; } fallthrough; @@ -961,9 +1013,6 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not - ready, a standalone REQUEST SENSE should forget about the not - ready, and report unit attention straight away. */ len = cdb[4]; if (!len) { @@ -977,14 +1026,11 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) scsi_disk_buf_alloc(dev, 256); scsi_disk_set_buf_len(dev, BufLen, &len); - if (*BufLen < cdb[4]) - cdb[4] = *BufLen; - len = (cdb[1] & 1) ? 8 : 18; scsi_disk_request_sense(dev, dev->temp_buffer, *BufLen, cdb[1] & 1); scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, cdb[4], 0); + scsi_disk_data_command_finish(dev, len, len, *BufLen, 0); break; case GPCMD_MECHANISM_STATUS: @@ -1020,12 +1066,15 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_READ_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; break; case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; @@ -1033,54 +1082,45 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) break; } - if (dev->sector_pos > last_sector) { + if (dev->sector_pos > last_sector) scsi_disk_lba_out_of_range(dev); - return; + else { + if (dev->sector_len) { + max_len = dev->sector_len; + dev->requested_blocks = max_len; + + dev->packet_len = max_len * alloc_length; + scsi_disk_buf_alloc(dev, dev->packet_len); + + dev->drv->seek_pos = dev->sector_pos; + dev->drv->seek_len = dev->sector_len; + + ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); + if (ret > 0) { + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + scsi_disk_data_command_finish(dev, alloc_length, 512, alloc_length, 0); + + ui_sb_update_icon(SB_HDD | dev->drv->bus_type, dev->packet_status != PHASE_COMPLETE); + } else { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + scsi_disk_buf_free(dev); + } + } else { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log(dev->log, "All done - callback set\n"); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + } } - - if (!dev->sector_len) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - scsi_disk_set_callback(dev); - break; - } - - max_len = dev->sector_len; - /* - If we're reading all blocks in one go for DMA, why not also for - PIO, it should NOT matter anyway, this step should be identical - and only the way the read dat is transferred to the host should - be different. - */ - dev->requested_blocks = max_len; - - dev->packet_len = max_len * alloc_length; - scsi_disk_buf_alloc(dev, dev->packet_len); - - dev->drv->seek_pos = dev->sector_pos; - dev->drv->seek_len = dev->sector_len; - - ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); - if (ret <= 0) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - scsi_disk_set_callback(dev); - scsi_disk_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - scsi_disk_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - - ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); - return; + break; case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: @@ -1111,23 +1151,26 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->sector_len = 256; dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, + scsi_disk_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_10: case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + scsi_disk_log(dev->log, "Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + dev->sector_len = (((uint32_t) cdb[6]) << 24) | + (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | + (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; @@ -1135,90 +1178,79 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) break; } - if (dev->sector_pos > last_sector) { + if (dev->sector_pos > last_sector) scsi_disk_lba_out_of_range(dev); - return; + else { + if (dev->sector_len) { + dev->drv->seek_pos = dev->sector_pos; + dev->drv->seek_len = dev->sector_len; + + max_len = dev->sector_len; + dev->requested_blocks = max_len; + + dev->packet_len = max_len * alloc_length; + scsi_disk_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; + + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + scsi_disk_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); + + ui_sb_update_icon(SB_HDD | dev->drv->bus_type, dev->packet_status != PHASE_COMPLETE); + } else { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log(dev->log, "All done - callback set\n"); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + } } - - if (!dev->sector_len) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - scsi_disk_set_callback(dev); - break; - } - - dev->drv->seek_pos = dev->sector_pos; - dev->drv->seek_len = dev->sector_len; - - max_len = dev->sector_len; - /* - If we're writing all blocks in one go for DMA, why not also for - PIO, it should NOT matter anyway, this step should be identical - and only the way the read dat is transferred to the host should - be different. - */ - dev->requested_blocks = max_len; - - dev->packet_len = max_len * alloc_length; - scsi_disk_buf_alloc(dev, dev->packet_len); - - dev->requested_blocks = max_len; - dev->packet_len = max_len << 9; - - scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - scsi_disk_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - - ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); - return; + break; case GPCMD_WRITE_SAME_10: alloc_length = 512; - if ((cdb[1] & 6) == 6) { - scsi_disk_invalid_field(dev); - return; + if ((cdb[1] & 6) == 6) + scsi_disk_invalid_field(dev, cdb[1]); + else { + 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 > last_sector) + scsi_disk_lba_out_of_range(dev); + else { + if (dev->sector_len) { + scsi_disk_buf_alloc(dev, alloc_length); + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + dev->requested_blocks = 1; + + dev->packet_len = alloc_length; + + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + + scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1); + + ui_sb_update_icon(SB_HDD | dev->drv->bus_type, + dev->packet_status != PHASE_COMPLETE); + } else { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log(dev->log, "All done - callback set\n"); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + } + } } - - 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 > last_sector) { - scsi_disk_lba_out_of_range(dev); - return; - } - - if (!dev->sector_len) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - scsi_disk_set_callback(dev); - break; - } - - scsi_disk_buf_alloc(dev, alloc_length); - scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - max_len = 1; - dev->requested_blocks = 1; - - dev->packet_len = alloc_length; - - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - - scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1); - - ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); - return; + break; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - if (dev->drv->bus == HDD_BUS_SCSI) + if (dev->drv->bus_type == HDD_BUS_SCSI) block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; else block_desc = 0; @@ -1235,7 +1267,8 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) alloc_length = len; if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc); + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, + cdb[2], block_desc); if (len > alloc_length) len = alloc_length; dev->temp_buffer[0] = len - 1; @@ -1261,10 +1294,10 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) alloc_length = len; scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_log("SCSI HDD %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + scsi_disk_log(dev->log, "Reading mode page: %02X...\n", cdb[2]); scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); - return; + break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: @@ -1282,7 +1315,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->total_length = len; dev->do_page_save = cdb[1] & 1; scsi_disk_data_command_finish(dev, len, len, len, 1); - return; + break; case GPCMD_INQUIRY: max_len = cdb[3]; @@ -1291,7 +1324,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) if ((!max_len) || (*BufLen == 0)) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - /* scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); */ + /* scsi_disk_log(dev->log, "All done - callback set\n"); */ dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * SCSI_TIME; break; @@ -1317,7 +1350,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) case 0x83: if (idx + 24 > max_len) { scsi_disk_buf_free(dev); - scsi_disk_data_phase_error(dev); + scsi_disk_data_phase_error(dev, idx + 24); return; } @@ -1325,7 +1358,8 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->temp_buffer[idx++] = 0x00; dev->temp_buffer[idx++] = 0x00; dev->temp_buffer[idx++] = 20; - ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Serial */ + /* Serial */ + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); idx += 20; if (idx + 72 > cdb[4]) @@ -1334,16 +1368,19 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->temp_buffer[idx++] = 0x01; dev->temp_buffer[idx++] = 0x00; dev->temp_buffer[idx++] = 68; - ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); /* Vendor */ + /* Vendor */ + ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); idx += 8; - ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); /* Product */ + /* Product */ + ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); idx += 40; - ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Product */ + /* Product */ + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); idx += 20; break; default: - scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - scsi_disk_invalid_field(dev); + scsi_disk_log(dev->log, "INQUIRY: Invalid page: %02X\n", cdb[2]); + scsi_disk_invalid_field(dev, cdb[2]); scsi_disk_buf_free(dev); return; } @@ -1353,19 +1390,23 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) memset(dev->temp_buffer, 0, 8); if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) - dev->temp_buffer[0] = 0x7f; /*No physical device on this LUN*/ + dev->temp_buffer[0] = 0x7f; /* No physical device on this LUN */ else - dev->temp_buffer[0] = 0; /*SCSI HD*/ - dev->temp_buffer[1] = 0; /*Fixed*/ - dev->temp_buffer[2] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - dev->temp_buffer[3] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x21; + dev->temp_buffer[0] = 0; /* SCSI HD */ + dev->temp_buffer[1] = 0; /* Fixed */ + /* SCSI-2 compliant */ + dev->temp_buffer[2] = (dev->drv->bus_type == HDD_BUS_SCSI) ? 0x02 : 0x00; + dev->temp_buffer[3] = (dev->drv->bus_type == HDD_BUS_SCSI) ? 0x02 : 0x21; dev->temp_buffer[4] = 31; - dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ - dev->temp_buffer[7] = 0x20; /* Wide bus supported */ + dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ + dev->temp_buffer[7] = 0x20; /* Wide bus supported */ - ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->temp_buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION_EX); /* Revision */ + /* Vendor */ + ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); + /* Product */ + ide_padstr8(dev->temp_buffer + 16, 16, device_identify); + /* Revision */ + ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION_EX); idx = 36; if (max_len == 96) { @@ -1437,12 +1478,12 @@ atapi_out: break; default: - scsi_disk_illegal_opcode(dev); + scsi_disk_illegal_opcode(dev, cdb[0]); break; } - /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, - dev->tf->request_length); */ + /* scsi_disk_log(dev->log, "Phase: %02X, request length: %i\n", + dev->tf->phase, dev->tf->request_length); */ if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) scsi_disk_buf_free(dev); @@ -1460,35 +1501,30 @@ scsi_disk_command_stop(scsi_common_t *sc) static uint8_t scsi_disk_phase_data_out(scsi_common_t *sc) { - scsi_disk_t *dev = (scsi_disk_t *) sc; - uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + scsi_disk_t *dev = (scsi_disk_t *) sc; + const uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + const uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + const int32_t *BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + const uint32_t last_sector = hdd_image_get_last_sector(dev->id); + int len = 0; + uint8_t error = 0; + int ret = 1; int i; - const int32_t *BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - uint32_t last_sector = hdd_image_get_last_sector(dev->id); - uint32_t c; - uint32_t h; - uint32_t s; - int len = 0; - uint32_t last_to_write = 0; + uint32_t last_to_write; uint16_t block_desc_len; uint16_t pos; uint16_t param_list_len; uint8_t hdr_len; uint8_t val; - uint8_t old_val; - uint8_t ch; - uint8_t error = 0; - uint8_t page; - uint8_t page_len; - if (!*BufLen) { + if (!*BufLen) scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + else switch (dev->current_cdb[0]) { + default: + log_fatal(dev->log, "Bad Command for phase 2 (%02X)\n", dev->current_cdb[0]); + ret = 0; + break; - return 1; - } - - switch (dev->current_cdb[0]) { case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: case GPCMD_VERIFY_12: @@ -1514,9 +1550,9 @@ scsi_disk_phase_data_out(scsi_common_t *sc) dev->temp_buffer[2] = (i >> 8) & 0xff; dev->temp_buffer[3] = i & 0xff; } else if (dev->current_cdb[1] & 4) { - s = (i % dev->drv->spt); - h = ((i - s) / dev->drv->spt) % dev->drv->hpc; - c = ((i - s) / dev->drv->spt) / dev->drv->hpc; + uint32_t s = (i % dev->drv->spt); + uint32_t h = ((i - s) / dev->drv->spt) % dev->drv->hpc; + uint32_t c = ((i - s) / dev->drv->spt) / dev->drv->hpc; dev->temp_buffer[0] = (c >> 16) & 0xff; dev->temp_buffer[1] = (c >> 8) & 0xff; dev->temp_buffer[2] = c & 0xff; @@ -1542,7 +1578,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc) param_list_len = dev->current_cdb[4]; } - if (dev->drv->bus == HDD_BUS_SCSI) { + if (dev->drv->bus_type == HDD_BUS_SCSI) { if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { block_desc_len = dev->temp_buffer[2]; block_desc_len <<= 8; @@ -1559,27 +1595,29 @@ scsi_disk_phase_data_out(scsi_common_t *sc) while (1) { if (pos >= param_list_len) { - scsi_disk_log("SCSI HD %i: Buffer has only block descriptor\n", dev->id); + scsi_disk_log(dev->log, "Buffer has only block descriptor\n"); break; } - page = dev->temp_buffer[pos] & 0x3F; - page_len = dev->temp_buffer[pos + 1]; + const uint8_t page = dev->temp_buffer[pos] & 0x3f; + const uint8_t page_len = dev->temp_buffer[pos + 1]; pos += 2; if (!(scsi_disk_mode_sense_page_flags & (1LL << ((uint64_t) page)))) error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->temp_buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; + else for (i = 0; i < page_len; i++) { + const uint8_t old = dev->ms_pages_saved.pages[page][i + 2]; + const uint8_t ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; + + val = dev->temp_buffer[pos + i]; + + if (val != old) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + scsi_disk_invalid_field_pl(dev, val); + error |= 1; } } } @@ -1594,22 +1632,17 @@ scsi_disk_phase_data_out(scsi_common_t *sc) break; } - if (error) { + if (error) scsi_disk_buf_free(dev); - scsi_disk_invalid_field_pl(dev); - } - break; - default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); break; } scsi_disk_command_stop((scsi_common_t *) dev); - return 1; + return ret; } static int -scsi_disk_get_max(int ide_has_dma, int type) +scsi_disk_get_max(const ide_t *ide, int ide_has_dma, const int type) { int ret; @@ -1635,7 +1668,7 @@ scsi_disk_get_max(int ide_has_dma, int type) } static int -scsi_disk_get_timings(int ide_has_dma, int type) +scsi_disk_get_timings(const ide_t *ide, const int ide_has_dma, const int type) { int ret; @@ -1657,29 +1690,28 @@ scsi_disk_get_timings(int ide_has_dma, int type) return ret; } -/** - * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command +/* + Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command */ static void -scsi_disk_identify(ide_t *ide, int ide_has_dma) +scsi_disk_identify(const ide_t *ide, const int ide_has_dma) { - const scsi_disk_t *dev; - char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; - - dev = (scsi_disk_t *) ide->sc; + const scsi_disk_t *dev = (scsi_disk_t *) ide->sc; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; device_identify[7] = dev->id + 0x30; - scsi_disk_log("ATAPI Identify: %s\n", device_identify); + scsi_disk_log(dev->log, "ATAPI Identify: %s\n", device_identify); /* ATAPI device, direct-access device, non-removable media, accelerated DRQ */ ide->buffer[0] = 0x8000 | (0 << 8) | 0x00 | (2 << 5); - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + ide->buffer[49] = 0x200; /* LBA supported */ + /* Interpret zero byte count limit as maximum length. */ + ide->buffer[126] = 0xfffe; if (ide_has_dma) { ide->buffer[71] = 30; @@ -1693,19 +1725,13 @@ void scsi_disk_hard_reset(void) { scsi_disk_t *dev; - scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus; - uint8_t scsi_id; - uint8_t valid = 0; for (uint8_t c = 0; c < HDD_NUM; c++) { - valid = 0; - if (hdd[c].bus == HDD_BUS_SCSI) { - scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); + uint8_t valid = 0; - scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; - scsi_id = hdd[c].scsi_id & 0x0f; + if (hdd[c].bus_type == HDD_BUS_SCSI) { + const uint8_t scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + const uint8_t scsi_id = hdd[c].scsi_id & 0x0f; /* Make sure to ignore any SCSI disk that has an out of range SCSI bus. */ if (scsi_bus >= SCSI_BUS_MAX) @@ -1727,16 +1753,25 @@ scsi_disk_hard_reset(void) hdd_preset_apply(c); - if (!hdd[c].priv) - hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); + if (hdd[c].priv == NULL) { + hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); + dev = (scsi_disk_t *) hdd[c].priv; + + char n[1024] = { 0 }; + + sprintf(n, "HDD %i SCSI ", c + 1); + dev->log = log_open(n); + } dev = (scsi_disk_t *) hdd[c].priv; - if (!dev->tf) + scsi_disk_log(dev->log, "SCSI disk hard_reset drive=%d\n", c); + + if (dev->tf == NULL) dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); /* SCSI disk, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + scsi_device_t *sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = scsi_disk_command; @@ -1746,18 +1781,22 @@ scsi_disk_hard_reset(void) sd->command_stop = scsi_disk_command_stop; sd->type = SCSI_FIXED_DISK; - scsi_disk_log("SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id); - } else if (hdd[c].bus == HDD_BUS_ATAPI) { + scsi_disk_log(dev->log, "SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id); + } else if (hdd[c].bus_type == HDD_BUS_ATAPI) { /* Make sure to ignore any SCSI disk whose image file name is empty. */ if (strlen(hdd[c].fn) == 0) continue; /* Make sure to ignore any SCSI disk whose image fails to load. */ + /* ATAPI hard disk, attach to the IDE bus. */ - id = ide_get_drive(hdd[c].ide_channel); - /* If the IDE channel is initialized, we attach to it, + ide_t *id = ide_get_drive(hdd[c].ide_channel); + + /* + If the IDE channel is initialized, we attach to it, otherwise, we do nothing - it's going to be a drive - that's not attached to anything. */ + that's not attached to anything. + */ if (id) { if (!hdd_image_load(c)) continue; @@ -1766,7 +1805,7 @@ scsi_disk_hard_reset(void) hdd_preset_apply(c); - if (!hdd[c].priv) + if (hdd[c].priv == NULL) hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); dev = (scsi_disk_t *) hdd[c].priv; @@ -1786,12 +1825,15 @@ scsi_disk_hard_reset(void) id->interrupt_drq = 0; ide_atapi_attach(id); - } - scsi_disk_log("ATAPI hard disk drive %i attached to IDE channel %i\n", c, hdd[c].ide_channel); + scsi_disk_log(dev->log, "ATAPI hard disk drive %i attached to IDE channel %i\n", + c, hdd[c].ide_channel); + } } if (valid) { + dev = (scsi_disk_t *) hdd[c].priv; + dev->id = c; dev->drv = &hdd[c]; @@ -1807,28 +1849,32 @@ scsi_disk_hard_reset(void) void scsi_disk_close(void) { - scsi_disk_t *dev; - uint8_t scsi_bus; - uint8_t scsi_id; - for (uint8_t c = 0; c < HDD_NUM; c++) { - if ((hdd[c].bus == HDD_BUS_SCSI) || (hdd[c].bus == HDD_BUS_ATAPI)) { - if (hdd[c].bus == HDD_BUS_SCSI) { - scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; - scsi_id = hdd[c].scsi_id & 0x0f; + if ((hdd[c].bus_type == HDD_BUS_SCSI) || (hdd[c].bus_type == HDD_BUS_ATAPI)) { + if (hdd[c].bus_type == HDD_BUS_SCSI) { + const uint8_t scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + const uint8_t scsi_id = hdd[c].scsi_id & 0x0f; memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); } hdd_image_close(c); - dev = hdd[c].priv; + scsi_disk_t *dev = hdd[c].priv; if (dev) { if (dev->tf) free(dev->tf); + if (dev->log != NULL) { + scsi_disk_log(dev->log, "Log closed\n"); + + log_close(dev->log); + dev->log = NULL; + } + free(dev); + hdd[c].priv = NULL; } } diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 016e50c40..2f4f5da14 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -5913,7 +5913,7 @@ const device_t sb_16_pnp_device = { .init = sb_16_pnp_init, .close = sb_close, .reset = NULL, - { .available = sb_16_pnp_noide_available }, + .available = sb_16_pnp_noide_available, .speed_changed = sb_speed_changed, .force_redraw = NULL, .config = sb_16_pnp_config @@ -6039,7 +6039,7 @@ const device_t sb_awe64_device = { .init = sb_awe32_pnp_init, .close = sb_awe32_close, .reset = NULL, - { .available = sb_awe64_noide_available }, + .available = sb_awe64_noide_available, .speed_changed = sb_speed_changed, .force_redraw = NULL, .config = sb_awe64_config diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index fb0224bc6..c85628e01 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -17,16 +17,18 @@ * Copyright 2023 Miran Grca. */ #include +#ifdef ENABLE_IOCTL_LOG #include +#endif #include #include #include #include #include #define HAVE_STDARG_H -#include <86box/86box.h> #include <86box/scsi_device.h> #include <86box/cdrom.h> +#include <86box/log.h> #include <86box/plat_unused.h> #include <86box/plat_cdrom.h> @@ -35,223 +37,203 @@ 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) -typedef struct dummy_cdrom_ioctl_t { +typedef struct ioctl_t { + cdrom_t *dev; + void *log; int toc_valid; -} dummy_cdrom_ioctl_t; +} ioctl_t; -#ifdef ENABLE_DUMMY_CDROM_IOCTL_LOG -int dummy_cdrom_ioctl_do_log = ENABLE_DUMMY_CDROM_IOCTL_LOG; +#ifdef ENABLE_IOCTL_LOG +int ioctl_do_log = ENABLE_IOCTL_LOG; void -dummy_cdrom_ioctl_log(const char *fmt, ...) +ioctl_log(void *priv, const char *fmt, ...) { - va_list ap; - - if (dummy_cdrom_ioctl_do_log) { + if (ioctl_do_log) { + va_list ap; va_start(ap, fmt); - pclog_ex(fmt, ap); + log_out(priv, fmt, ap); va_end(ap); } } #else -# define dummy_cdrom_ioctl_log(fmt, ...) +# define ioctl_log(priv, fmt, ...) #endif -static int -plat_cdrom_open(void *local) +/* Internal functions. */ +static void +ioctl_close_handle(UNUSED(const ioctl_t *ioctl)) { return 0; } static int -plat_cdrom_load(void *local) +ioctl_open_handle(UNUSED(ioctl_t *ioctl)) { return 0; } static void -plat_cdrom_read_toc(void *local) +ioctl_read_toc(ioctl_t *ioctl) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + if (!ioctl->toc_valid) { + ioctl->toc_valid = 1; + } +} + +/* Shared functions. */ +static int +ioctl_get_track_info(UNUSED(const void *local), UNUSED(const uint32_t track), + UNUSED(int end), UNUSED(track_info_t *ti)) +{ + return 0; +} + +static void +ioctl_get_raw_track_info(const void *local, UNUSED(int *num), UNUSED(uint8_t *rti)) +{ + ioctl_t *ioctl = (ioctl_t *) local; if (!ioctl->toc_valid) ioctl->toc_valid = 1; } -void -plat_cdrom_get_raw_track_info(UNUSED(void *local), int *num, raw_track_info_t *rti) +static void +ioctl_get_raw_track_info(UNUSED(const void *local), int *num, uint8_t *rti) { *num = 1; memset(rti, 0x00, 11); } -int -plat_cdrom_is_track_audio(void *local, uint32_t sector) +static int +ioctl_is_track_pre(const void *local, const uint32_t sector) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - const int ret = 0; - - dummy_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); - - return ret; -} - -int -plat_cdrom_is_track_pre(void *local, uint32_t sector) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + ioctl_t *ioctl = (ioctl_t *) local; plat_cdrom_read_toc(ioctl); const int ret = 0; - dummy_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); + ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); return ret; } -uint32_t -plat_cdrom_get_track_start(void *local, uint32_t sector, uint8_t *attr, uint8_t *track) +static int +ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - return 0x00000000; -} - -uint32_t -plat_cdrom_get_last_block(void *local) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - return 0x00000000; -} - -int -plat_cdrom_ext_medium_changed(UNUSED(void *local)) -{ -#if 0 - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); -#endif - - int ret = 0; - - dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); - - return ret; -} - -/* This replaces both Info and EndInfo, they are specified by a variable. */ -int -plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - if ((track < 1) || (track == 0xaa)) { - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i)\n", track); - return 0; - } - - start->min = 0; - start->sec = 0; - start->fr = 2; - - *track_num = 1; - *attr = 0x14; - - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n", - track, start->min, start->sec, start->fr, *track_num, *attr); - - return 1; -} - -/* TODO: See if track start is adjusted by 150 or not. */ -int -plat_cdrom_get_audio_sub(UNUSED(void *local), UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track, uint8_t *index, - TMSF *rel_pos, TMSF *abs_pos) -{ - *track = 1; - *attr = 0x14; - *index = 1; - - rel_pos->min = 0; - rel_pos->sec = 0; - rel_pos->fr = 0; - abs_pos->min = 0; - abs_pos->sec = 0; - abs_pos->fr = 2; - - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_sub(): %02i, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", - *track, *attr, *index, rel_pos->min, rel_pos->sec, rel_pos->fr, abs_pos->min, abs_pos->sec, abs_pos->fr); - - return 1; -} - -int -plat_cdrom_get_sector_size(UNUSED(void *local), UNUSED(uint32_t sector)) -{ - dummy_cdrom_ioctl_log("BytesPerSector=2048\n"); - - return 2048; -} - -int -plat_cdrom_read_sector(void *local, uint8_t *buffer, uint32_t sector) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + ioctl_t *ioctl = (ioctl_t *) local; plat_cdrom_open(ioctl); /* Raw */ - dummy_cdrom_ioctl_log("Raw\n"); + ioctl_log("Raw\n"); plat_cdrom_close(ioctl); - dummy_cdrom_ioctl_log("ReadSector sector=%d.\n", sector); + ioctl_log("ReadSector sector=%d.\n", sector); return 0; } -void -plat_cdrom_eject(void *local) +static uint8_t +ioctl_get_track_type(UNUSED(const void *local), UNUSED(const uint32_t sector)) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_open(ioctl); - plat_cdrom_close(ioctl); + return 0x00; } -void -plat_cdrom_close(UNUSED(void *local)) +static uint32_t +ioctl_get_last_block(const void *local) { + ioctl_t *ioctl = (ioctl_t *) local; + + ioctl_read_toc(ioctl); + + return 0x00000000; } -int -plat_cdrom_set_drive(void *local, const char *drv) +static int +ioctl_read_dvd_structure(UNUSED(const void *local), UNUSED(const uint8_t layer), UNUSED(const uint8_t format), + UNUSED(uint8_t *buffer), UNUSED(uint32_t *info)) { - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_close(ioctl); - - ioctl->toc_valid = 0; - - plat_cdrom_load(ioctl); - - return 1; + return -0x00052100; } -int -plat_cdrom_get_local_size(void) +static int +ioctl_is_dvd(UNUSED(const void *local)) { - return sizeof(dummy_cdrom_ioctl_t); + return 0; +} + +static int +ioctl_has_audio(UNUSED(const void *local)) +{ + return 0; +} + +static int +ioctl_ext_medium_changed(UNUSED(void *local)) +{ +#if 0 + ioctl_t *ioctl = (ioctl_t *) local; +#endif + int ret = 0; + + ioctl_log("ioctl_ext_medium_changed(): %i\n", ret); + + return ret; +} + +static void +ioctl_close(void *local) +{ + ioctl_t *ioctl = (ioctl_t *) local; + + ioctl_close_handle(ioctl); + ioctl->handle = NULL; + + ioctl_log(ioctl->log, "Log closed\n"); + + log_close(ioctl->log); + ioctl->log = NULL; +} + +static const cdrom_ops_t ioctl_ops = { + ioctl_get_track_info, + ioctl_get_raw_track_info, + ioctl_is_track_pre, + ioctl_read_sector, + ioctl_get_track_type, + ioctl_get_last_block, + ioctl_read_dvd_structure, + ioctl_is_dvd, + ioctl_has_audio, + ioctl_ext_medium_changed, + ioctl_close +}; + +/* Public functions. */ +void * +ioctl_open(cdrom_t *dev, const char *drv) +{ + ioctl_t *ioctl = (ioctl_t *) calloc(1, sizeof(ioctl_t)); + + if (ioctl != NULL) { + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i IOCtl", dev->id + 1); + ioctl->log = log_open(n); + + memset(ioctl->path, 0x00, sizeof(ioctl->path)); + + wsprintf(ioctl->path, L"%S", &(drv[8])); + ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); + + ioctl->dev = dev; + ioctl->toc_valid = 0; + + dev->ops = &ioctl_ops; + } + + return ioctl; } From 7c6f45b4cd59e3d54f731f22965bc004f62fa9e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 18:39:26 +0100 Subject: [PATCH 0160/1190] Fixed CD-ROM image mounting crashes and, hopefully, Linux compiles. --- src/CMakeLists.txt | 1 + src/cdrom/cdrom.c | 9 +++++---- src/cdrom/cdrom_image.c | 4 ++-- src/qt/dummy_cdrom_ioctl.c | 2 +- src/unix/dummy_cdrom_ioctl.c | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7d6daff9c..4e2a2313d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,6 +22,7 @@ endif() add_executable(86Box 86box.c + all_devices.c config.c log.c random.c diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 5ddd788cb..2c439e76a 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -22,6 +22,7 @@ #include #include #include +#include #include <86box/86box.h> #include <86box/device.h> #include <86box/config.h> @@ -1522,14 +1523,14 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) case 0x00: dev->cd_end = pos2; break; - case 0x40: + case 0x40: { const int m = bcd2bin((pos >> 24) & 0xff); const int s = bcd2bin((pos >> 16) & 0xff); const int f = bcd2bin((pos >> 8) & 0xff); pos2 = MSFtoLBA(m, s, f) - 150; dev->cd_end = pos2; break; - case 0x80: + } case 0x80: dev->cd_end = (pos2 >> 24) & 0xff; break; case 0xc0: @@ -1572,7 +1573,7 @@ cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type) } dev->seek_pos = pos2; break; - case 0x40: + case 0x40: { const int m = bcd2bin((pos >> 24) & 0xff); const int s = bcd2bin((pos >> 16) & 0xff); const int f = bcd2bin((pos >> 8) & 0xff); @@ -1584,7 +1585,7 @@ cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type) dev->seek_pos = pos2; break; - case 0x80: + } case 0x80: dev->seek_pos = (pos >> 24) & 0xff; break; default: diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index e4a425c78..ba4f0164a 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -2006,6 +2006,8 @@ image_open(cdrom_t *dev, const char *path) int ret; const int is_cue = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE")); + img->dev = dev; + if (is_cue) { ret = image_load_cue(img, path); @@ -2029,8 +2031,6 @@ image_open(cdrom_t *dev, const char *path) sprintf(n, "CD-ROM %i Image", dev->id + 1); img->log = log_open(n); - img->dev = dev; - dev->ops = &image_ops; } } diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index c85628e01..a0f95f213 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -30,7 +30,7 @@ #include <86box/cdrom.h> #include <86box/log.h> #include <86box/plat_unused.h> -#include <86box/plat_cdrom.h> +#include <86box/plat_cdrom_ioctl.h> /* 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 diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index c85628e01..a0f95f213 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -30,7 +30,7 @@ #include <86box/cdrom.h> #include <86box/log.h> #include <86box/plat_unused.h> -#include <86box/plat_cdrom.h> +#include <86box/plat_cdrom_ioctl.h> /* 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 From ab2d1a3b75f695de65d3dcd826e9efb3fc30d266 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 28 Jan 2025 12:56:44 -0500 Subject: [PATCH 0161/1190] Remove incorrect addition to cmakelist. --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e2a2313d..7d6daff9c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,7 +22,6 @@ endif() add_executable(86Box 86box.c - all_devices.c config.c log.c random.c From 1843ad39fdce4b48a47643a8a3e1a489ff2b5704 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 19:25:47 +0100 Subject: [PATCH 0162/1190] More *nix compile fixes. --- src/qt/dummy_cdrom_ioctl.c | 13 +++++++------ src/unix/dummy_cdrom_ioctl.c | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index a0f95f213..59ebee6f3 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -41,6 +41,7 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; int toc_valid; + char path[256]; } ioctl_t; #ifdef ENABLE_IOCTL_LOG @@ -110,11 +111,11 @@ ioctl_is_track_pre(const void *local, const uint32_t sector) { ioctl_t *ioctl = (ioctl_t *) local; - plat_cdrom_read_toc(ioctl); + ioctl_read_toc(ioctl); const int ret = 0; - ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); + ioctl_log("ioctl_is_track_audio(%08X): %i\n", sector, ret); return ret; } @@ -124,12 +125,12 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) { ioctl_t *ioctl = (ioctl_t *) local; - plat_cdrom_open(ioctl); + ioctl_open_handle(ioctl); /* Raw */ ioctl_log("Raw\n"); - plat_cdrom_close(ioctl); + ioctl_close_handle(ioctl); ioctl_log("ReadSector sector=%d.\n", sector); @@ -226,8 +227,8 @@ ioctl_open(cdrom_t *dev, const char *drv) memset(ioctl->path, 0x00, sizeof(ioctl->path)); - wsprintf(ioctl->path, L"%S", &(drv[8])); - ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); + sprintf(ioctl->path, "%s", drv); + ioctl_log(ioctl->log, "Path is %s\n", ioctl->path); ioctl->dev = dev; ioctl->toc_valid = 0; diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index a0f95f213..59ebee6f3 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -41,6 +41,7 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; int toc_valid; + char path[256]; } ioctl_t; #ifdef ENABLE_IOCTL_LOG @@ -110,11 +111,11 @@ ioctl_is_track_pre(const void *local, const uint32_t sector) { ioctl_t *ioctl = (ioctl_t *) local; - plat_cdrom_read_toc(ioctl); + ioctl_read_toc(ioctl); const int ret = 0; - ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); + ioctl_log("ioctl_is_track_audio(%08X): %i\n", sector, ret); return ret; } @@ -124,12 +125,12 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) { ioctl_t *ioctl = (ioctl_t *) local; - plat_cdrom_open(ioctl); + ioctl_open_handle(ioctl); /* Raw */ ioctl_log("Raw\n"); - plat_cdrom_close(ioctl); + ioctl_close_handle(ioctl); ioctl_log("ReadSector sector=%d.\n", sector); @@ -226,8 +227,8 @@ ioctl_open(cdrom_t *dev, const char *drv) memset(ioctl->path, 0x00, sizeof(ioctl->path)); - wsprintf(ioctl->path, L"%S", &(drv[8])); - ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); + sprintf(ioctl->path, "%s", drv); + ioctl_log(ioctl->log, "Path is %s\n", ioctl->path); ioctl->dev = dev; ioctl->toc_valid = 0; From 3cc677ededd0bd2021f0d1a63a9e7c58ce76a1d4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 19:27:28 +0100 Subject: [PATCH 0163/1190] And another. --- src/qt/dummy_cdrom_ioctl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index 59ebee6f3..c849869cb 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -65,7 +65,6 @@ ioctl_log(void *priv, const char *fmt, ...) static void ioctl_close_handle(UNUSED(const ioctl_t *ioctl)) { - return 0; } static int From d52e01bf8f223abca81024a6fc2143d776ebf785 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 19:45:41 +0100 Subject: [PATCH 0164/1190] And yet more *nix compile fixes. --- src/qt/dummy_cdrom_ioctl.c | 16 ++-------------- src/unix/dummy_cdrom_ioctl.c | 17 ++--------------- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index c849869cb..a2ea26e3f 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -41,6 +41,7 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; int toc_valid; + HANDLE handle; char path[256]; } ioctl_t; @@ -76,9 +77,8 @@ ioctl_open_handle(UNUSED(ioctl_t *ioctl)) static void ioctl_read_toc(ioctl_t *ioctl) { - if (!ioctl->toc_valid) { + if (!ioctl->toc_valid) ioctl->toc_valid = 1; - } } /* Shared functions. */ @@ -89,15 +89,6 @@ ioctl_get_track_info(UNUSED(const void *local), UNUSED(const uint32_t track), return 0; } -static void -ioctl_get_raw_track_info(const void *local, UNUSED(int *num), UNUSED(uint8_t *rti)) -{ - ioctl_t *ioctl = (ioctl_t *) local; - - if (!ioctl->toc_valid) - ioctl->toc_valid = 1; -} - static void ioctl_get_raw_track_info(UNUSED(const void *local), int *num, uint8_t *rti) { @@ -126,9 +117,6 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) ioctl_open_handle(ioctl); - /* Raw */ - ioctl_log("Raw\n"); - ioctl_close_handle(ioctl); ioctl_log("ReadSector sector=%d.\n", sector); diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index 59ebee6f3..a2ea26e3f 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -41,6 +41,7 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; int toc_valid; + HANDLE handle; char path[256]; } ioctl_t; @@ -65,7 +66,6 @@ ioctl_log(void *priv, const char *fmt, ...) static void ioctl_close_handle(UNUSED(const ioctl_t *ioctl)) { - return 0; } static int @@ -77,9 +77,8 @@ ioctl_open_handle(UNUSED(ioctl_t *ioctl)) static void ioctl_read_toc(ioctl_t *ioctl) { - if (!ioctl->toc_valid) { + if (!ioctl->toc_valid) ioctl->toc_valid = 1; - } } /* Shared functions. */ @@ -90,15 +89,6 @@ ioctl_get_track_info(UNUSED(const void *local), UNUSED(const uint32_t track), return 0; } -static void -ioctl_get_raw_track_info(const void *local, UNUSED(int *num), UNUSED(uint8_t *rti)) -{ - ioctl_t *ioctl = (ioctl_t *) local; - - if (!ioctl->toc_valid) - ioctl->toc_valid = 1; -} - static void ioctl_get_raw_track_info(UNUSED(const void *local), int *num, uint8_t *rti) { @@ -127,9 +117,6 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) ioctl_open_handle(ioctl); - /* Raw */ - ioctl_log("Raw\n"); - ioctl_close_handle(ioctl); ioctl_log("ReadSector sector=%d.\n", sector); From 1968a36350fd15143b137c3d7b3f33182fdf3c8b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 20:07:18 +0100 Subject: [PATCH 0165/1190] Make handle a void pointer on *nix. --- src/qt/dummy_cdrom_ioctl.c | 2 +- src/unix/dummy_cdrom_ioctl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index a2ea26e3f..ae4eb1727 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -41,7 +41,7 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; int toc_valid; - HANDLE handle; + void *handle; char path[256]; } ioctl_t; diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index a2ea26e3f..ae4eb1727 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -41,7 +41,7 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; int toc_valid; - HANDLE handle; + void *handle; char path[256]; } ioctl_t; From 2d7fb728308e6f27d444dc701c7d42dd2afe7ca3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 28 Jan 2025 23:22:06 +0100 Subject: [PATCH 0166/1190] CD-ROM Image: close log before closing the file, fixes segmentation fault on image unload. --- src/cdrom/cdrom_image.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index ba4f0164a..afc70bda7 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -357,18 +357,15 @@ index_file_init(const uint8_t id, const char *filename, int *error, int *is_viso *is_viso = 1; } - return tf; + return tf; } static void index_file_close(track_index_t *idx) { - if ((idx == NULL) || (idx->file == NULL) || - (idx->file->close == NULL)) + if ((idx == NULL) || (idx->file == NULL)) return; - idx->file->close(idx->file); - image_log(idx->file->log, "Log closed\n"); if (idx->file->log != NULL) { @@ -376,6 +373,9 @@ index_file_close(track_index_t *idx) idx->file->log = NULL; } + if (idx->file->close != NULL) + idx->file->close(idx->file); + idx->file = NULL; } @@ -567,7 +567,7 @@ image_cue_get_buffer(char *str, char **line, const int up) static int image_cue_get_keyword(char **dest, char **line) { - int success = image_cue_get_buffer(temp_keyword, line, 1); + const int success = image_cue_get_buffer(temp_keyword, line, 1); if (success) *dest = temp_keyword; @@ -1676,16 +1676,16 @@ image_clear_tracks(cd_image_t *img) if (((cur->point >= 1) && (cur->point <= 99)) || (cur->point == 0xa2)) for (int j = 0; j < 3; j++) { - idx = &(cur->idx[j]); - /* Make sure we do not attempt to close a NULL file. */ - if ((idx->file != NULL) && (idx->type == INDEX_NORMAL)) { - if (idx->file != last) { - last = idx->file; - index_file_close(idx); - } else - idx->file = NULL; + idx = &(cur->idx[j]); + /* Make sure we do not attempt to close a NULL file. */ + if ((idx->file != NULL) && (idx->type == INDEX_NORMAL)) { + if (idx->file != last) { + last = idx->file; + index_file_close(idx); + } else + idx->file = NULL; + } } - } } /* Now free the array. */ @@ -1905,8 +1905,8 @@ image_get_track_type(const void *local, const uint32_t sector) const track_t *nt = &(img->tracks[i + 1]); if (ct->point == 0xa0) { - uint8_t first = (ct->idx[1].start / 75 / 60); - uint8_t last = (nt->idx[1].start / 75 / 60); + const uint8_t first = (ct->idx[1].start / 75 / 60); + const uint8_t last = (nt->idx[1].start / 75 / 60); if ((trk->point >= first) && (trk->point <= last)) { ret = (ct->idx[1].start / 75) % 60; From b7100a6169579ef89eff96b836fbf935d8486cd7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 29 Jan 2025 00:33:24 +0100 Subject: [PATCH 0167/1190] Video changes of the night (January 29th, 2025) Matrox MGA: A break from work can save the day all so to say. Fixes bitblt'ing on WinNT4.0/Win2000 using 32bpp modes and possibly other stuff using said Matrox chip. --- src/video/vid_mga.c | 48 ++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 2b9e63af4..ee422fd3f 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -5558,6 +5558,7 @@ blit_bitblt(mystique_t *mystique) mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; src_addr = mystique->dwgreg.ar[3]; + break; } else src_addr += x_dir; @@ -5670,6 +5671,7 @@ blit_bitblt(mystique_t *mystique) mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; src_addr = mystique->dwgreg.ar[3]; + break; } else src_addr += x_dir; @@ -5756,6 +5758,7 @@ blit_bitblt(mystique_t *mystique) mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; src_addr = mystique->dwgreg.ar[3]; + break; } else src_addr += x_dir; @@ -5852,6 +5855,7 @@ blit_bitblt(mystique_t *mystique) mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; src_addr = mystique->dwgreg.ar[3]; + break; } else src_addr += x_dir; @@ -6521,6 +6525,7 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) mystique->pci_regs[addr] = val; if (addr == 0x30) mystique->pci_regs[addr] &= 1; + if (mystique->pci_regs[0x30] & 0x01) { uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); @@ -6533,26 +6538,24 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) return; case 0x40: - mystique->pci_regs[addr] = val & 0x3f; + mystique->pci_regs[0x40] = val & 0x3f; break; case 0x41: - mystique->pci_regs[addr] = val; + mystique->pci_regs[0x41] = val; break; case 0x42: - mystique->pci_regs[addr] = val & 0x1f; + mystique->pci_regs[0x42] = val & 0x1f; break; case 0x43: - mystique->pci_regs[addr] = val; - if (addr == 0x43) { - if (val & 0x40) { - if (mystique->pci_regs[0x30] & 0x01) { - uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); - mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); - } else - mem_mapping_disable(&mystique->bios_rom.mapping); + mystique->pci_regs[0x43] = val; + if (val & 0x40) { + if (mystique->pci_regs[0x30] & 0x01) { + uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } else - mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); - } + mem_mapping_disable(&mystique->bios_rom.mapping); + } else + mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); break; case 0x4c: @@ -6580,17 +6583,17 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) mystique_ctrl_write_b(addr, val, mystique); break; - case 0xf8: - mystique->pci_regs[0xf8] = val & 0x7; - break; + case 0xf8: + mystique->pci_regs[0xf8] = val & 0x7; + break; - case 0xf9: - mystique->pci_regs[0xf9] = val & 0x3; - break; + case 0xf9: + mystique->pci_regs[0xf9] = val & 0x3; + break; - case 0xfb: - mystique->pci_regs[0xfb] = val; - break; + case 0xfb: + mystique->pci_regs[0xfb] = val; + break; default: break; @@ -6677,6 +6680,7 @@ mystique_init(const device_t *info) mystique->svga.conv_16to32 = tvp3026_conv_16to32; if (mystique->type == MGA_2164W) mystique->svga.decode_mask = 0xffffff; + tvp3026_gpio(mystique_tvp3026_gpio_read, mystique_tvp3026_gpio_write, mystique, mystique->svga.ramdac); } else { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); From 4457456b010aa1a12bf5286cff353873dc1ab176 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 29 Jan 2025 00:56:57 +0100 Subject: [PATCH 0168/1190] Unix SDL: Fix compile-breaking errors. --- src/unix/unix_cdrom.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 186c7649b..7fe64bee6 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -140,8 +140,8 @@ void cdrom_mount(uint8_t id, char *fn) { strcpy(cdrom[id].prev_image_path, cdrom[id].image_path); - if (cdrom[id].ops && cdrom[id].ops->exit) - cdrom[id].ops->exit(&(cdrom[id])); + if (cdrom[id].ops && cdrom[id].ops->close) + cdrom[id].ops->close(cdrom[id].local); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\')) @@ -187,8 +187,7 @@ mo_mount(uint8_t id, char *fn, uint8_t wp) mo_disk_close(dev); mo_drives[id].read_only = wp; - mo_load(dev, fn); - mo_insert(dev); + mo_load(dev, fn, 0); ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1); #if 0 @@ -245,8 +244,7 @@ zip_mount(uint8_t id, char *fn, uint8_t wp) zip_disk_close(dev); zip_drives[id].read_only = wp; - zip_load(dev, fn); - zip_insert(dev); + zip_load(dev, fn, 0); ui_sb_update_icon_state(SB_ZIP | id, strlen(zip_drives[id].image_path) ? 0 : 1); #if 0 From 2db2fef78b2ba9c3a2cec950134711ba7c5aefd1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 29 Jan 2025 01:08:36 +0100 Subject: [PATCH 0169/1190] And a missing include file. --- src/unix/unix_cdrom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 7fe64bee6..8655865a1 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -32,6 +32,7 @@ #include <86box/hdd.h> #include <86box/scsi_device.h> #include <86box/cdrom.h> +#include <86box/cdrom_image.h> #include <86box/mo.h> #include <86box/zip.h> #include <86box/scsi_disk.h> From b57281c57e31a70605bd87691a001c6cf83337e3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 29 Jan 2025 23:48:09 +0100 Subject: [PATCH 0170/1190] CD-ROM: No longer fatal when encountering a mode 1 sector on a XA disc - apparently such discs actually exist. --- src/cdrom/cdrom.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 2c439e76a..3a6f17d7b 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2207,7 +2207,11 @@ cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, cons if (mode2) { if (raw_buffer[0x000f] == 0x01) - log_fatal(dev->log, "Mode 1 sector on CD-I/XA disc\n"); + /* + Use Mode 1, since evidently specification-violating discs + exist. + */ + mode2 = 0; else if (raw_buffer[0x0012] != raw_buffer[0x0016]) { cdrom_log(dev->log, "[%s] XA Mode 2 sector with malformed " "sub-header\n", cdrom_req_modes[cdrom_sector_type], From 76fb3365cd1623dfc28087ec504727e1d1acc191 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 30 Jan 2025 05:39:17 +0100 Subject: [PATCH 0171/1190] It's image_open(), no longer cdrom_image_open(). --- src/unix/unix_cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 8655865a1..5223b08ba 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -147,7 +147,7 @@ cdrom_mount(uint8_t id, char *fn) memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\')) fn[strlen(fn) - 1] = '/'; - cdrom_image_open(&(cdrom[id]), fn); + image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) cdrom[id].insert(cdrom[id].priv); From 8a1862c4b2838b4107f81f53850de3bee4d2688e Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 30 Jan 2025 06:38:05 +0100 Subject: [PATCH 0172/1190] CD-ROM: Correctly return from read sector with the return code from the back-end in case of error, fixes System Shock 2 CD detection. --- src/cdrom/cdrom.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 3a6f17d7b..33e8b0cf1 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2192,13 +2192,22 @@ cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, cons if (audio) { if (!track_type_is_valid(dev, cdrom_sector_type, cdrom_sector_flags, 1, 0x00)) ret = 0; - else + else { ret = read_audio(dev, lba, temp_b); + + /* Return with error if we had one. */ + if (ret < 0) + return ret; + } } else { int form = 0; ret = read_data(dev, lba); + /* Return with error if we had one. */ + if (ret < 0) + return ret; + if ((raw_buffer[0x000f] == 0x00) || (raw_buffer[0x000f] > 0x02)) { cdrom_log(dev->log, "[%s] Unknown mode: %02X\n", cdrom_req_modes[cdrom_sector_type], raw_buffer[0x000f]); From e11b5535e1896927abd3cdd8bf06af94ae2b786e Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 30 Jan 2025 08:15:39 +0100 Subject: [PATCH 0173/1190] Fixed some CD-ROM commands not stopping audio play when they should have (fixes data playing as audio, producing nasty artifacts, in some games), and increased the media history for all drive types from 4 to 10, also refactored cdrom_read_sector() and moved the last module-wide variables into the cdrom_t struct. --- src/cdrom/cdrom.c | 458 +++++++++++++++++----------------- src/include/86box/86box.h | 2 +- src/include/86box/cartridge.h | 2 +- src/include/86box/cassette.h | 2 +- src/include/86box/cdrom.h | 22 +- src/include/86box/fdd.h | 2 +- src/include/86box/mo.h | 2 +- src/include/86box/zip.h | 2 +- src/scsi/scsi_cdrom.c | 9 + 9 files changed, 262 insertions(+), 239 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 33e8b0cf1..595d89f70 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -43,11 +43,6 @@ #define MIN_SEEK 2000 #define MAX_SEEK 333333 -static int cdrom_sector_size; -/* Needs some extra breathing space in case of overflows. */ -static uint8_t raw_buffer[4096]; -static uint8_t extra_buffer[296]; - cdrom_t cdrom[CDROM_NUM] = { 0 }; int cdrom_interface_current; @@ -69,16 +64,16 @@ cdrom_log(void *priv, const char *fmt, ...) # define cdrom_log(priv, fmt, ...) #endif -static void process_mode1(const cdrom_t *dev, const int cdrom_sector_flags, +static void process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b); -static void process_mode2_non_xa(const cdrom_t *dev, const int cdrom_sector_flags, +static void process_mode2_non_xa(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b); -static void process_mode2_xa_form1(const cdrom_t *dev, const int cdrom_sector_flags, +static void process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b); -static void process_mode2_xa_form2(const cdrom_t *dev, const int cdrom_sector_flags, +static void process_mode2_xa_form2(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b); -typedef void (*cdrom_process_data_t)(const cdrom_t *dev, const int cdrom_sector_flags, +typedef void (*cdrom_process_data_t)(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b); static cdrom_process_data_t cdrom_process_data[4] = { process_mode1, process_mode2_non_xa, @@ -289,13 +284,13 @@ msf_to_bcd(int *m, int *s, int *f) } static int -read_data(const cdrom_t *dev, const uint32_t lba) +read_data(cdrom_t *dev, const uint32_t lba) { - return dev->ops->read_sector(dev->local, raw_buffer, lba); + return dev->ops->read_sector(dev->local, dev->raw_buffer, lba); } static void -cdrom_get_subchannel(const cdrom_t *dev, const uint32_t lba, +cdrom_get_subchannel(cdrom_t *dev, const uint32_t lba, subchannel_t *subc, const int cooked) { const uint8_t *scb; @@ -306,10 +301,10 @@ cdrom_get_subchannel(const cdrom_t *dev, const uint32_t lba, ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED))) scb = dev->subch_buffer; else { - scb = (const uint8_t *) raw_buffer; + scb = (const uint8_t *) dev->raw_buffer; scb_offs = 2352; - memset(raw_buffer, 0, 2448); + memset(dev->raw_buffer, 0, 2448); (void) read_data(dev, lba); } @@ -645,36 +640,36 @@ track_type_is_valid(const cdrom_t *dev, const int type, const int flags, const i } static int -read_audio(const cdrom_t *dev, const uint32_t lba, uint8_t *b) +read_audio(cdrom_t *dev, const uint32_t lba, uint8_t *b) { - const int ret = dev->ops->read_sector(dev->local, raw_buffer, lba); + const int ret = dev->ops->read_sector(dev->local, dev->raw_buffer, lba); - memcpy(b, raw_buffer, 2352); + memcpy(b, dev->raw_buffer, 2352); - cdrom_sector_size = 2352; + dev->cdrom_sector_size = 2352; return ret; } static void -process_mode1(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) { - cdrom_sector_size = 0; + dev->cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[Mode 1] Sync\n"); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; + memcpy(b, dev->raw_buffer, 12); + dev->cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[Mode 1] Header\n"); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; + memcpy(b, dev->raw_buffer + 12, 4); + dev->cdrom_sector_size += 4; b += 4; } @@ -683,8 +678,8 @@ process_mode1(const 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, raw_buffer + 16, 8); - cdrom_sector_size += 8; + memcpy(b, dev->raw_buffer + 16, 8); + dev->cdrom_sector_size += 8; b += 8; } } @@ -693,12 +688,13 @@ process_mode1(const 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, raw_buffer + 16 + (part * dev->sector_size), dev->sector_size); - cdrom_sector_size += dev->sector_size; + memcpy(b, dev->raw_buffer + 16 + (part * dev->sector_size), + dev->sector_size); + dev->cdrom_sector_size += dev->sector_size; b += dev->sector_size; } else { - memcpy(b, raw_buffer + 16, 2048); - cdrom_sector_size += 2048; + memcpy(b, dev->raw_buffer + 16, 2048); + dev->cdrom_sector_size += 2048; b += 2048; } } @@ -706,29 +702,30 @@ process_mode1(const 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, raw_buffer + 2064, (288 - ecc_diff)); - cdrom_sector_size += (288 - ecc_diff); + memcpy(b, dev->raw_buffer + 2064, (288 - ecc_diff)); + dev->cdrom_sector_size += (288 - ecc_diff); } } static void -process_mode2_non_xa(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +process_mode2_non_xa(cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b) { - cdrom_sector_size = 0; + dev->cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[Mode 2 Formless] Sync\n"); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; + memcpy(b, dev->raw_buffer, 12); + dev->cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[Mode 2 Formless] Header\n"); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; + memcpy(b, dev->raw_buffer + 12, 4); + dev->cdrom_sector_size += 4; b += 4; } @@ -736,45 +733,46 @@ process_mode2_non_xa(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t * if (cdrom_sector_flags & 0x40) { /* Sub-header */ cdrom_log(dev->log, "[Mode 2 Formless] Sub-header\n"); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; + memcpy(b, dev->raw_buffer + 16, 8); + dev->cdrom_sector_size += 8; b += 8; } if (cdrom_sector_flags & 0x10) { /* User data */ cdrom_log(dev->log, "[Mode 2 Formless] User data\n"); - memcpy(b, raw_buffer + 24, (2336 - ecc_diff)); - cdrom_sector_size += (2336 - ecc_diff); + memcpy(b, dev->raw_buffer + 24, (2336 - ecc_diff)); + dev->cdrom_sector_size += (2336 - ecc_diff); } } static void -process_mode2_xa_form1(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b) { - cdrom_sector_size = 0; + dev->cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[XA Mode 2 Form 1] Sync\n"); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; + memcpy(b, dev->raw_buffer, 12); + dev->cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[XA Mode 2 Form 1] Header\n"); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; + memcpy(b, dev->raw_buffer + 12, 4); + dev->cdrom_sector_size += 4; b += 4; } if (cdrom_sector_flags & 0x40) { /* Sub-header */ cdrom_log(dev->log, "[XA Mode 2 Form 1] Sub-header\n"); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; + memcpy(b, dev->raw_buffer + 16, 8); + dev->cdrom_sector_size += 8; b += 8; } @@ -782,12 +780,13 @@ process_mode2_xa_form1(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t /* User data */ cdrom_log(dev->log, "[XA Mode 2 Form 1] User data\n"); if (mult > 1) { - memcpy(b, raw_buffer + 24 + (part * dev->sector_size), dev->sector_size); - cdrom_sector_size += dev->sector_size; + memcpy(b, dev->raw_buffer + 24 + (part * dev->sector_size), + dev->sector_size); + dev->cdrom_sector_size += dev->sector_size; b += dev->sector_size; } else { - memcpy(b, raw_buffer + 24, 2048); - cdrom_sector_size += 2048; + memcpy(b, dev->raw_buffer + 24, 2048); + dev->cdrom_sector_size += 2048; b += 2048; } } @@ -795,48 +794,80 @@ process_mode2_xa_form1(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ cdrom_log(dev->log, "[XA Mode 2 Form 1] EDC/ECC\n"); - memcpy(b, raw_buffer + 2072, (280 - ecc_diff)); - cdrom_sector_size += (280 - ecc_diff); + memcpy(b, dev->raw_buffer + 2072, (280 - ecc_diff)); + dev->cdrom_sector_size += (280 - ecc_diff); } } static void -process_mode2_xa_form2(const cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) +process_mode2_xa_form2(cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b) { - cdrom_sector_size = 0; + dev->cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[XA Mode 2 Form 2] Sync\n"); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; + memcpy(b, dev->raw_buffer, 12); + dev->cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[XA Mode 2 Form 2] Header\n"); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; + memcpy(b, dev->raw_buffer + 12, 4); + dev->cdrom_sector_size += 4; b += 4; } if (cdrom_sector_flags & 0x40) { /* Sub-header */ cdrom_log(dev->log, "[XA Mode 2 Form 2] Sub-header\n"); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; + memcpy(b, dev->raw_buffer + 16, 8); + dev->cdrom_sector_size += 8; b += 8; } if (cdrom_sector_flags & 0x10) { /* User data */ cdrom_log(dev->log, "[XA Mode 2 Form 2] User data\n"); - memcpy(b, raw_buffer + 24, (2328 - ecc_diff)); - cdrom_sector_size += (2328 - ecc_diff); + memcpy(b, dev->raw_buffer + 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) +{ + if ((cdrom_sector_flags & 0x06) == 0x02) { + /* Add error flags. */ + cdrom_log(dev->log, "Error flags\n"); + memcpy(b + dev->cdrom_sector_size, dev->extra_buffer, 294); + dev->cdrom_sector_size += 294; + } else if ((cdrom_sector_flags & 0x06) == 0x04) { + /* Add error flags. */ + cdrom_log(dev->log, "Full error flags\n"); + memcpy(b + dev->cdrom_sector_size, dev->extra_buffer, 296); + dev->cdrom_sector_size += 296; + } + + 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); + 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); + 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); + dev->cdrom_sector_size += 96; + } +} + static void cdrom_drive_reset(cdrom_t *dev) { @@ -855,7 +886,9 @@ cdrom_drive_reset(cdrom_t *dev) static void cdrom_unload(cdrom_t *dev) { - cdrom_log(dev->log, "CDROM: cdrom_unload(%s)\n", dev->image_path); + if (dev->log != NULL) { + cdrom_log(dev->log, "CDROM: cdrom_unload(%s)\n", dev->image_path); + } dev->cd_status = CD_STATUS_EMPTY; @@ -1624,7 +1657,7 @@ cdrom_get_current_status(const cdrom_t *dev) } void -cdrom_get_current_subchannel(const cdrom_t *dev, uint8_t *b, const int msf) +cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) { subchannel_t subc; @@ -1709,7 +1742,7 @@ cdrom_get_current_subchannel(const cdrom_t *dev, uint8_t *b, const int msf) } void -cdrom_get_current_subchannel_sony(const cdrom_t *dev, uint8_t *b, const int msf) +cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, const int msf) { subchannel_t subc; @@ -1743,7 +1776,7 @@ cdrom_get_current_subchannel_sony(const cdrom_t *dev, uint8_t *b, const int msf) } uint8_t -cdrom_get_audio_status_pioneer(const cdrom_t *dev, uint8_t *b) +cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b) { uint8_t ret; subchannel_t subc; @@ -1769,7 +1802,7 @@ cdrom_get_audio_status_pioneer(const cdrom_t *dev, uint8_t *b) } uint8_t -cdrom_get_audio_status_sony(const cdrom_t *dev, uint8_t *b, const int msf) +cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, const int msf) { uint8_t ret; subchannel_t subc; @@ -1803,7 +1836,7 @@ cdrom_get_audio_status_sony(const cdrom_t *dev, uint8_t *b, const int msf) } void -cdrom_get_current_subcodeq(const cdrom_t *dev, uint8_t *b) +cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b) { subchannel_t subc; @@ -2098,16 +2131,12 @@ cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, } int -cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, +cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, int cdrom_sector_type, const int cdrom_sector_flags, int *len, const uint8_t vendor_type) { - uint8_t *temp_b; - uint32_t lba; - int audio = 0; - int mode2 = 0; int pos = sector; - int ret; + int ret = 0; if ((cdrom_sector_type & 0x0f) >= 0x08) { mult = cdrom_sector_type >> 4; @@ -2121,164 +2150,143 @@ cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, cons ecc_diff = 0; } - if (dev->cd_status == CD_STATUS_EMPTY) - return 0; + if (dev->cd_status != CD_STATUS_EMPTY) { + uint8_t *temp_b; + uint8_t *b = temp_b = buffer; + int audio = 0; + uint32_t lba; + int mode2 = 0; - uint8_t *b = temp_b = buffer; + *len = 0; - *len = 0; + if (ismsf) { + const int m = (pos >> 16) & 0xff; + const int s = (pos >> 8) & 0xff; + const int f = pos & 0xff; - if (ismsf) { - const int m = (pos >> 16) & 0xff; - const int s = (pos >> 8) & 0xff; - const int f = pos & 0xff; + lba = MSFtoLBA(m, s, f) - 150; + } else { + switch (vendor_type) { + case 0x00: + lba = pos; + break; + case 0x40: { + const int m = bcd2bin((pos >> 24) & 0xff); + const int s = bcd2bin((pos >> 16) & 0xff); + const int f = bcd2bin((pos >> 8) & 0xff); - lba = MSFtoLBA(m, s, f) - 150; - } else { - switch (vendor_type) { - case 0x00: - lba = pos; - break; - case 0x40: { - const int m = bcd2bin((pos >> 24) & 0xff); - const int s = bcd2bin((pos >> 16) & 0xff); - const int f = bcd2bin((pos >> 8) & 0xff); - - lba = MSFtoLBA(m, s, f) - 150; - break; - } case 0x80: - lba = bcd2bin((pos >> 24) & 0xff); - break; - /* Never used values but the compiler complains. */ - default: - lba = 0; - } - } - - if (dev->ops->get_track_type) - audio = dev->ops->get_track_type(dev->local, lba); - - int dm = audio & CD_TRACK_MODE_MASK; - audio &= CD_TRACK_AUDIO; - - if (dm != CD_TRACK_NORMAL) - mode2 = 1; - - memset(raw_buffer, 0, 2448); - memset(extra_buffer, 0, 296); - - if ((cdrom_sector_flags & 0xf8) == 0x08) { - /* 0x08 is an illegal mode */ - cdrom_log(dev->log, "[Mode 1] 0x08 is an illegal mode\n"); - return 0; - } - - if ((cdrom_sector_type > 5) && (cdrom_sector_type < 8)) { - cdrom_log(dev->log, "Attempting to read an unrecognized sector " - "type from an image\n"); - return 0; - } else { - if ((cdrom_sector_type > 1) && audio && (dev->cd_status & CD_STATUS_HAS_AUDIO)) { - cdrom_log(dev->log, "[%s] Attempting to read a data sector " - "from an audio track\n", cdrom_req_modes[cdrom_sector_type]); - return 0; - } else if ((cdrom_sector_type == 1) && - (!audio || !(dev->cd_status & CD_STATUS_HAS_AUDIO))) { - cdrom_log(dev->log, "[Audio] Attempting to read an audio sector " - "from a data track\n"); - return 0; + lba = MSFtoLBA(m, s, f) - 150; + break; + } case 0x80: + lba = bcd2bin((pos >> 24) & 0xff); + break; + /* Never used values but the compiler complains. */ + default: + lba = 0; + } } - if (audio) { - if (!track_type_is_valid(dev, cdrom_sector_type, cdrom_sector_flags, 1, 0x00)) - ret = 0; - else { - ret = read_audio(dev, lba, temp_b); + if (dev->ops->get_track_type) + audio = dev->ops->get_track_type(dev->local, lba); + + const int dm = audio & CD_TRACK_MODE_MASK; + audio &= CD_TRACK_AUDIO; + + 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) { + /* 0x08 is an illegal mode */ + cdrom_log(dev->log, "[Mode 1] 0x08 is an illegal mode\n"); + } else if ((cdrom_sector_type > 5) && (cdrom_sector_type < 8)) { + cdrom_log(dev->log, "Attempting to read an unrecognized sector " + "type from an image\n"); + return 0; + } else { + if ((cdrom_sector_type > 1) && audio && + (dev->cd_status & CD_STATUS_HAS_AUDIO)) { + cdrom_log(dev->log, "[%s] Attempting to read a data sector " + "from an audio track\n", + cdrom_req_modes[cdrom_sector_type]); + } else if ((cdrom_sector_type == 1) && + (!audio || !(dev->cd_status & CD_STATUS_HAS_AUDIO))) { + cdrom_log(dev->log, "[Audio] Attempting to read an audio " + "sector from a data track\n"); + } else if (audio) { + if (!track_type_is_valid(dev, cdrom_sector_type, + cdrom_sector_flags, 1, 0x00)) + ret = 0; + else + ret = read_audio(dev, lba, temp_b); + } else { + ret = read_data(dev, lba); /* Return with error if we had one. */ - if (ret < 0) - return ret; - } - } else { - int form = 0; + if (ret > 0) { + int form = 0; - ret = read_data(dev, lba); + if ((dev->raw_buffer[0x000f] == 0x00) || + (dev->raw_buffer[0x000f] > 0x02)) { + cdrom_log(dev->log, "[%s] Unknown mode: %02X\n", + cdrom_req_modes[cdrom_sector_type], + dev->raw_buffer[0x000f]); + ret = 0; + } else if (mode2) { + if (dev->raw_buffer[0x000f] == 0x01) + /* + Use Mode 1, since evidently specification-violating + discs exist. + */ + mode2 = 0; + else if (dev->raw_buffer[0x0012] != + dev->raw_buffer[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) + mode2 = 1; - /* Return with error if we had one. */ - if (ret < 0) - return ret; + if (ret > 0) { + const int mode_id = mode2 + form; - if ((raw_buffer[0x000f] == 0x00) || (raw_buffer[0x000f] > 0x02)) { - cdrom_log(dev->log, "[%s] Unknown mode: %02X\n", - cdrom_req_modes[cdrom_sector_type], raw_buffer[0x000f]); - return 0; + cdrom_log(dev->log, "[%s] %s detected\n", + cdrom_req_modes[cdrom_sector_type], + cdrom_modes[mode_id]); + + if (!track_type_is_valid(dev, cdrom_sector_type, + cdrom_sector_flags, 0, + (mode2 << 2) + form)) { + cdrom_log(dev->log, "[%s] Invalid track type\n", + cdrom_req_modes[cdrom_sector_type]); + ret = 0; + } else if (cdrom_mode_masks[cdrom_sector_type] & + (1 << mode_id)) + cdrom_process_data[mode_id](dev, cdrom_sector_flags, + temp_b); + else { + cdrom_log(dev->log, "[%s] Attempting to read a " + "%s sector\n", + cdrom_req_modes[cdrom_sector_type], + cdrom_modes[mode_id]); + ret = 0; + } + } + } } - if (mode2) { - if (raw_buffer[0x000f] == 0x01) - /* - Use Mode 1, since evidently specification-violating discs - exist. - */ - mode2 = 0; - else if (raw_buffer[0x0012] != raw_buffer[0x0016]) { - cdrom_log(dev->log, "[%s] XA Mode 2 sector with malformed " - "sub-header\n", cdrom_req_modes[cdrom_sector_type], - raw_buffer[0x000f]); - return 0; - } else - form = ((raw_buffer[0x0012] & 0x20) >> 5) + 1; - } else if (raw_buffer[0x000f] == 0x02) - mode2 = 1; - - const int mode_id = mode2 + form; - - cdrom_log(dev->log, "[%s] %s detected\n", cdrom_req_modes[cdrom_sector_type], - cdrom_modes[mode_id]); - - if (!track_type_is_valid(dev, cdrom_sector_type, cdrom_sector_flags, 0, - (mode2 << 2) + form)) - return 0; - - /* It just so happens that only modes with even ID's have a sector user data size of 2048. */ - if (cdrom_mode_masks[cdrom_sector_type] & (1 << mode_id)) - cdrom_process_data[mode_id](dev, cdrom_sector_flags, temp_b); - else { - cdrom_log(dev->log, "[%s] Attempting to read a %s sector\n", - cdrom_req_modes[cdrom_sector_type], cdrom_modes[mode_id]); - return 0; + if (ret > 0) { + process_ecc_and_subch(dev, cdrom_sector_flags, b); + *len = dev->cdrom_sector_size; } } } - if ((cdrom_sector_flags & 0x06) == 0x02) { - /* Add error flags. */ - cdrom_log(dev->log, "Error flags\n"); - memcpy(b + cdrom_sector_size, extra_buffer, 294); - cdrom_sector_size += 294; - } else if ((cdrom_sector_flags & 0x06) == 0x04) { - /* Add error flags. */ - cdrom_log(dev->log, "Full error flags\n"); - memcpy(b + cdrom_sector_size, extra_buffer, 296); - cdrom_sector_size += 296; - } - - if ((cdrom_sector_flags & 0x700) == 0x100) { - cdrom_log(dev->log, "Raw subchannel data\n"); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; - } else if ((cdrom_sector_flags & 0x700) == 0x200) { - cdrom_log(dev->log, "Q subchannel data\n"); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); - cdrom_sector_size += 16; - } else if ((cdrom_sector_flags & 0x700) == 0x400) { - cdrom_log(dev->log, "R/W subchannel data\n"); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; - } - - *len = cdrom_sector_size; - return ret; } @@ -2495,7 +2503,7 @@ cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer) } int -cdrom_read_track_information(const cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer) +cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer) { uint8_t rti[65536] = { 0 }; const raw_track_info_t *t = (raw_track_info_t *) rti; @@ -2609,7 +2617,7 @@ cdrom_read_track_information(const cdrom_t *dev, const uint8_t *cdb, uint8_t *bu if (track->adr_ctl & 0x04) { ret = read_data(dev, start); - mode = raw_buffer[3]; + mode = dev->raw_buffer[3]; } } else if (track->point != 0xa2) start = 0x00000000; @@ -2763,9 +2771,7 @@ cdrom_hard_reset(void) cdrom_t *dev = &cdrom[i]; if (dev->bus_type) { - cdrom_log(dev->log, "Hard reset\n"); - - dev->id = i; + dev->id = i; dev->is_early = cdrom_is_early(dev->type); dev->is_nec = (dev->bus_type == CDROM_BUS_SCSI) && @@ -2778,6 +2784,8 @@ cdrom_hard_reset(void) sprintf(n, "CD-ROM %i ", i + 1); dev->log = log_open(n); + cdrom_log(dev->log, "Hard reset\n"); + switch (dev->bus_type) { case CDROM_BUS_ATAPI: case CDROM_BUS_SCSI: diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 96aeb645c..5dc0116fc 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -33,7 +33,7 @@ #define SCREENSHOT_PATH "screenshots" /* Recently used images */ -#define MAX_PREV_IMAGES 4 +#define MAX_PREV_IMAGES 10 #define MAX_IMAGE_PATH_LEN 2048 /* Max UUID Length */ diff --git a/src/include/86box/cartridge.h b/src/include/86box/cartridge.h index 2ea7ec734..2b0662703 100644 --- a/src/include/86box/cartridge.h +++ b/src/include/86box/cartridge.h @@ -21,7 +21,7 @@ extern "C" { #endif -#define CART_IMAGE_HISTORY 4 +#define CART_IMAGE_HISTORY 10 extern char cart_fns[2][512]; extern char *cart_image_history[2][CART_IMAGE_HISTORY]; diff --git a/src/include/86box/cassette.h b/src/include/86box/cassette.h index bb0899e24..168d82099 100644 --- a/src/include/86box/cassette.h +++ b/src/include/86box/cassette.h @@ -153,7 +153,7 @@ void pc_cas_print_state(const pc_cassette_t *cas); void pc_cas_clock(pc_cassette_t *cas, unsigned long cnt); void pc_cas_advance(pc_cassette_t *cas); -#define CASSETTE_IMAGE_HISTORY 4 +#define CASSETTE_IMAGE_HISTORY 10 extern pc_cassette_t *cassette; diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index b9dbccb4b..de20facdb 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -48,7 +48,7 @@ #define CD_TOC_SESSION 1 #define CD_TOC_RAW 2 -#define CD_IMAGE_HISTORY 4 +#define CD_IMAGE_HISTORY 10 #define BUF_SIZE 32768 @@ -333,6 +333,12 @@ typedef struct cdrom { int16_t cd_buffer[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 extra_buffer[296]; } cdrom_t; extern cdrom_t cdrom[CDROM_NUM]; @@ -394,11 +400,11 @@ extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const extern void cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume); extern uint8_t cdrom_get_current_status(const cdrom_t *dev); -extern void cdrom_get_current_subchannel(const cdrom_t *dev, uint8_t *b, const int msf); -extern void cdrom_get_current_subchannel_sony(const cdrom_t *dev, uint8_t *b, const int msf); -extern uint8_t cdrom_get_audio_status_pioneer(const cdrom_t *dev, uint8_t *b); -extern uint8_t cdrom_get_audio_status_sony(const cdrom_t *dev, uint8_t *b, const int msf); -extern void cdrom_get_current_subcodeq(const cdrom_t *dev, uint8_t *b); +extern void cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf); +extern void cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, const int msf); +extern uint8_t cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b); +extern uint8_t cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, const int msf); +extern void cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b); extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b); extern int cdrom_read_toc(const cdrom_t *dev, uint8_t *b, const int type, const uint8_t start_track, const int msf, const int max_len); @@ -411,13 +417,13 @@ extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint #endif extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, const uint8_t track, const int type); -extern int cdrom_readsector_raw(const cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, +extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, int cdrom_sector_type, const int cdrom_sector_flags, int *len, const uint8_t vendor_type); extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_t layer, const uint8_t format, 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(const cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer); +extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer); extern int cdrom_ext_medium_changed(const cdrom_t *dev); extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert); diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h index 0331f4fcc..ff9315f1d 100644 --- a/src/include/86box/fdd.h +++ b/src/include/86box/fdd.h @@ -22,7 +22,7 @@ #define EMU_FDD_H #define FDD_NUM 4 -#define FLOPPY_IMAGE_HISTORY 4 +#define FLOPPY_IMAGE_HISTORY 10 #define SEEK_RECALIBRATE -999 #ifdef __cplusplus diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index 0b494952c..1df16c3fe 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -27,7 +27,7 @@ #define MO_TIME 10.0 -#define MO_IMAGE_HISTORY 4 +#define MO_IMAGE_HISTORY 10 typedef struct mo_type_t { uint32_t sectors; diff --git a/src/include/86box/zip.h b/src/include/86box/zip.h index 59b78b64e..06c6e8485 100644 --- a/src/include/86box/zip.h +++ b/src/include/86box/zip.h @@ -29,7 +29,7 @@ #define ZIP_250_SECTORS (489532) -#define ZIP_IMAGE_HISTORY 4 +#define ZIP_IMAGE_HISTORY 10 enum { ZIP_BUS_DISABLED = 0, diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 65604758d..33858ebbc 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1108,6 +1108,9 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, const int vendor_type) 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: @@ -1508,6 +1511,9 @@ scsi_cdrom_stop(const scsi_common_t *sc) static void scsi_cdrom_set_speed(scsi_cdrom_t *dev, const uint8_t *cdb) { + /* Stop the audio playing. */ + cdrom_stop(dev->drv); + dev->drv->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; if (dev->drv->cur_speed < 1) dev->drv->cur_speed = 1; @@ -3345,6 +3351,9 @@ atapi_out: dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); + /* Stop the audio playing. */ + cdrom_stop(dev->drv); + if (dev->use_cdb_9 && (cdb[0] == GPCMD_SEEK_10)) cdrom_seek(dev->drv, pos, cdb[9] & 0xc0); else From 9dbdc14af5e72df99360f5648dfc925bd8d30d0a Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Fri, 31 Jan 2025 01:09:43 +0700 Subject: [PATCH 0174/1190] Make the HDD models' speed accurate Also make some, but few, of HDD model names more accurate. --- src/disk/hdd.c | 194 ++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 25257e878..8292dc472 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -415,35 +415,35 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[1997] 5400 RPM", .internal_name = "1997_5400rpm", .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 }, { .name = "[1998] 5400 RPM", .internal_name = "1998_5400rpm", .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, { .name = "[2000] 7200 RPM", .internal_name = "2000_7200rpm", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, - { .name = "[PIO IDE] IBM WDA-L42", .internal_name = "WDAL42", .model = "IBM-WDA-L42", .zones = 1, .avg_spt = 85, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 2.5, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 1 }, + { .name = "[PIO IDE] IBM WDA-L42", .internal_name = "WDAL42", .model = "WDA-L42", .zones = 1, .avg_spt = 85, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 2.5, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 1 }, { .name = "[ATA-1] Conner CP3024", .internal_name = "CP3024", .model = "Conner Peripherals 20MB - CP3024", .zones = 1, .avg_spt = 33, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3044", .internal_name = "CP3044", .model = "Conner Peripherals 40MB - CP3044", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3104", .internal_name = "CP3104", .model = "Conner Peripherals 104MB - CP3104", .zones = 1, .avg_spt = 33, .heads = 8, .rpm = 3500, .full_stroke_ms = 45, .track_seek_ms = 8, .rcache_num_seg = 4, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work - { .name = "[ATA-1] Conner CFS420A", .internal_name = "CFS420A", .model = "Conner Peripherals 420MB - CFS420A", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-1] HP Kittyhawk", .internal_name = "C3014A", .model = "HP C3014A", .zones = 6, .avg_spt = 180, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, - { .name = "[ATA-1] IBM H3256-A3", .internal_name = "H3256A3", .model = "IBM-H3256-A3", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, - { .name = "[ATA-1] IBM H3342-A4", .internal_name = "H3342A4", .model = "IBM-H3342-A4", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, - { .name = "[ATA-1] Kalok KL343", .internal_name = "KL343", .model = "KALOK KL-343", .zones = 1, .avg_spt = 280, .heads = 6, .rpm = 3600, .full_stroke_ms = 50, .track_seek_ms = 2, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, - { .name = "[ATA-1] Kalok KL3100", .internal_name = "KL3100", .model = "KALOK KL-3100", .zones = 1, .avg_spt = 200, .heads = 6, .rpm = 3662, .full_stroke_ms = 50, .track_seek_ms = 2, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-1] Maxtor 7060AT", .internal_name = "7060AT", .model = "Maxtor 7060AT", .zones = 1, .avg_spt = 162, .heads = 2, .rpm = 3524, .full_stroke_ms = 30, .track_seek_ms = 3.6, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-1] Maxtor 7131AT", .internal_name = "7131AT", .model = "Maxtor 7131AT", .zones = 2, .avg_spt = 154, .heads = 2, .rpm = 3551, .full_stroke_ms = 27, .track_seek_ms = 4.5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-1] Maxtor 7213AT", .internal_name = "7213AT", .model = "Maxtor 7213AT", .zones = 4, .avg_spt = 155, .heads = 4, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6.5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-1] Maxtor 7245AT", .internal_name = "7245AT", .model = "Maxtor 7245AT", .zones = 4, .avg_spt = 149, .heads = 4, .rpm = 3551, .full_stroke_ms = 27, .track_seek_ms = 4.4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-1] Quantum ProDrive LPS 105", .internal_name = "LPS105AT", .model = "QUANTUM PRODRIVE 105", .zones = 1, .avg_spt = 170, .heads = 2, .rpm = 3662, .full_stroke_ms = 45, .track_seek_ms = 5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-1] Quantum ProDrive LPS 120AT", .internal_name = "GM12A012", .model = "QUANTUM PRODRIVE 120AT", .zones = 1, .avg_spt = 150, .heads = 2, .rpm = 3605, .full_stroke_ms = 45, .track_seek_ms = 4, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-1] Seagate ST3243A", .internal_name = "ST3243A", .model = "ST3243A", .zones = 1, .avg_spt = 140, .heads = 4, .rpm = 3811, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 140", .internal_name = "AC140", .model = "WDC AC140", .zones = 4, .avg_spt = 170, .heads = 2, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 8, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 280", .internal_name = "AC280", .model = "WDC AC280", .zones = 4, .avg_spt = 170, .heads = 4, .rpm = 3595, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 1210", .internal_name = "AC1210", .model = "WDC AC1210F", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 3314, .full_stroke_ms = 33, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-1] Western Digital Caviar 2120", .internal_name = "AC2120", .model = "WDC AC2120M", .zones = 4, .avg_spt = 140, .heads = 2, .rpm = 3605, .full_stroke_ms = 28, .track_seek_ms = 2.8, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-2] IBM DBOA-2720", .internal_name = "DBOA2720", .model = "IBM-DBOA-2720", .zones = 2, .avg_spt = 135, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-2] IBM DeskStar 4 (DCAA-32880)", .internal_name = "DCAA32880", .model = "IBM-DCAA-32880", .zones = 8, .avg_spt = 85, .heads = 2, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, - { .name = "[ATA-2] IBM DeskStar 4 (DCAA-33610)", .internal_name = "DCAA33610", .model = "IBM-DCAA-33610", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, - { .name = "[ATA-2] IBM DeskStar 4 (DCAA-34330)", .internal_name = "DCAA34330", .model = "IBM-DCAA-34330", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, - { .name = "[ATA-2] Maxtor 7540AV", .internal_name = "7540AV", .model = "Maxtor 7540AV", .zones = 2, .avg_spt = 120, .heads = 4, .rpm = 3551, .full_stroke_ms = 31, .track_seek_ms = 4.3, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, - { .name = "[ATA-2] Maxtor 7546AT", .internal_name = "7546AT", .model = "Maxtor 7546AT", .zones = 2, .avg_spt = 100, .heads = 4, .rpm = 4500, .full_stroke_ms = 28, .track_seek_ms = 2.3, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 }, - { .name = "[ATA-2] Maxtor 7850AV", .internal_name = "7850AV", .model = "Maxtor 7850AV", .zones = 4, .avg_spt = 120, .heads = 4, .rpm = 3551, .full_stroke_ms = 31, .track_seek_ms = 3.7, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-2] Maxtor 71336AP", .internal_name = "71336AP", .model = "Maxtor 71336AP", .zones = 4, .avg_spt = 105, .heads = 4, .rpm = 4480, .full_stroke_ms = 12, .track_seek_ms = 3.4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-1] Conner CFS420A", .internal_name = "CFS420A", .model = "Conner Peripherals 420MB - CFS420A", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] HP Kittyhawk", .internal_name = "C3014A", .model = "HP C3014A", .zones = 6, .avg_spt = 80, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, + { .name = "[ATA-1] IBM H3256-A3", .internal_name = "H3256A3", .model = "H3256-A3", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3600, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, + { .name = "[ATA-1] IBM H3342-A4", .internal_name = "H3342A4", .model = "H3342-A4", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, + { .name = "[ATA-1] Kalok KL343", .internal_name = "KL343", .model = "KALOK KL-343", .zones = 1, .avg_spt = 80, .heads = 6, .rpm = 3600, .full_stroke_ms = 50, .track_seek_ms = 2, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, + { .name = "[ATA-1] Kalok KL3100", .internal_name = "KL3100", .model = "KALOK KL-3100", .zones = 1, .avg_spt = 100, .heads = 6, .rpm = 3662, .full_stroke_ms = 50, .track_seek_ms = 2, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] Maxtor 7060AT", .internal_name = "7060AT", .model = "Maxtor 7060 AT", .zones = 1, .avg_spt = 62, .heads = 2, .rpm = 3524, .full_stroke_ms = 30, .track_seek_ms = 3.6, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Maxtor 7131AT", .internal_name = "7131AT", .model = "Maxtor 7131 AT", .zones = 2, .avg_spt = 54, .heads = 2, .rpm = 3551, .full_stroke_ms = 27, .track_seek_ms = 4.5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Maxtor 7213AT", .internal_name = "7213AT", .model = "Maxtor 7213 AT", .zones = 4, .avg_spt = 55, .heads = 4, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6.5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Maxtor 7245AT", .internal_name = "7245AT", .model = "Maxtor 7245 AT", .zones = 4, .avg_spt = 49, .heads = 4, .rpm = 3551, .full_stroke_ms = 27, .track_seek_ms = 4.4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Quantum ProDrive LPS 105", .internal_name = "LPS105AT", .model = "QUANTUM PRODRIVE 105", .zones = 1, .avg_spt = 70, .heads = 2, .rpm = 3662, .full_stroke_ms = 45, .track_seek_ms = 5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Quantum ProDrive LPS 120AT", .internal_name = "GM12A012", .model = "QUANTUM PRODRIVE 120AT", .zones = 1, .avg_spt = 50, .heads = 2, .rpm = 3605, .full_stroke_ms = 45, .track_seek_ms = 4, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Seagate ST3243A", .internal_name = "ST3243A", .model = "ST3243A", .zones = 1, .avg_spt = 40, .heads = 4, .rpm = 3811, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 140", .internal_name = "AC140", .model = "WDC AC140", .zones = 4, .avg_spt = 70, .heads = 2, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 8, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 280", .internal_name = "AC280", .model = "WDC AC280", .zones = 4, .avg_spt = 70, .heads = 4, .rpm = 3595, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 1210", .internal_name = "AC1210", .model = "WDC AC1210F", .zones = 4, .avg_spt = 30, .heads = 2, .rpm = 3314, .full_stroke_ms = 33, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 2120", .internal_name = "AC2120", .model = "WDC AC2120M", .zones = 4, .avg_spt = 40, .heads = 2, .rpm = 3605, .full_stroke_ms = 28, .track_seek_ms = 2.8, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-2] IBM DBOA-2720", .internal_name = "DBOA2720", .model = "DBOA-2720", .zones = 2, .avg_spt = 135, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-2] IBM DeskStar 4 (DCAA-32880)", .internal_name = "DCAA32880", .model = "IBM-DCAA-32880", .zones = 8, .avg_spt = 185, .heads = 2, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, + { .name = "[ATA-2] IBM DeskStar 4 (DCAA-33610)", .internal_name = "DCAA33610", .model = "IBM-DCAA-33610", .zones = 8, .avg_spt = 185, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, + { .name = "[ATA-2] IBM DeskStar 4 (DCAA-34330)", .internal_name = "DCAA34330", .model = "IBM-DCAA-34330", .zones = 8, .avg_spt = 185, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, + { .name = "[ATA-2] Maxtor 7540AV", .internal_name = "7540AV", .model = "Maxtor 7540 AV", .zones = 2, .avg_spt = 120, .heads = 4, .rpm = 3551, .full_stroke_ms = 31, .track_seek_ms = 4.3, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-2] Maxtor 7546AT", .internal_name = "7546AT", .model = "Maxtor 7546 AT", .zones = 2, .avg_spt = 100, .heads = 4, .rpm = 4500, .full_stroke_ms = 28, .track_seek_ms = 2.3, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 }, + { .name = "[ATA-2] Maxtor 7850AV", .internal_name = "7850AV", .model = "Maxtor 7850 AV", .zones = 4, .avg_spt = 120, .heads = 4, .rpm = 3551, .full_stroke_ms = 31, .track_seek_ms = 3.7, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-2] Maxtor 71336AP", .internal_name = "71336AP", .model = "Maxtor 71336 AP", .zones = 4, .avg_spt = 105, .heads = 4, .rpm = 4480, .full_stroke_ms = 12, .track_seek_ms = 3.4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Quantum Bigfoot 1.2AT", .internal_name = "BF12A011", .model = "QUANTUM BIGFOOT BF1.2A", .zones = 2, .avg_spt = 155, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Quantum Bigfoot (CY4320A)", .internal_name = "CY4320A", .model = "QUANTUM BIGFOOT_CY4320A", .zones = 2, .avg_spt = 130, .heads = 2, .rpm = 4000, .full_stroke_ms = 29, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, // from Hardcore Windows NT Final Segment by Kugee { .name = "[ATA-2] Quantum Fireball 640AT", .internal_name = "FB64A341", .model = "QUANTUM FIREBALL 640AT", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3.1, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, @@ -458,89 +458,89 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Seagate Medalist 545xe", .internal_name = "ST3660A", .model = "ST3660A", .zones = 4, .avg_spt = 130, .heads = 4, .rpm = 3811, .full_stroke_ms = 34, .track_seek_ms = 3.4, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, { .name = "[ATA-2] Seagate Medalist 640xe", .internal_name = "ST3630A", .model = "ST3630A", .zones = 4, .avg_spt = 130, .heads = 4, .rpm = 3811, .full_stroke_ms = 34, .track_seek_ms = 3.5, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, { .name = "[ATA-2] Seagate Medalist 850xe", .internal_name = "ST3850A", .model = "ST3850A", .zones = 8, .avg_spt = 150, .heads = 4, .rpm = 3811, .full_stroke_ms = 34, .track_seek_ms = 3.8, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, - { .name = "[ATA-2] Seagate Medalist 1270SL", .internal_name = "ST51270A", .model = "ST51270A", .zones = 8, .avg_spt = 105, .heads = 3, .rpm = 5736, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Seagate Medalist 3240", .internal_name = "ST33240A", .model = "ST33240A", .zones = 16, .avg_spt = 125, .heads = 8, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-2] Seagate Medalist 1270SL", .internal_name = "ST51270A", .model = "ST51270A", .zones = 8, .avg_spt = 205, .heads = 3, .rpm = 5736, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-2] Seagate Medalist 3240", .internal_name = "ST33240A", .model = "ST33240A", .zones = 16, .avg_spt = 225, .heads = 8, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Toshiba MK2101MAN (HDD2616)", .internal_name = "HDD2616", .model = "TOSHIBA MK2101MAN", .zones = 8, .avg_spt = 130, .heads = 10, .rpm = 4200, .full_stroke_ms = 36, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Western Digital Caviar 2540", .internal_name = "AC2540", .model = "WDC AC2540H", .zones = 4, .avg_spt = 250, .heads = 2, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, - { .name = "[ATA-2] Western Digital Caviar 2850", .internal_name = "AC2850", .model = "WDC AC2850F", .zones = 4, .avg_spt = 230, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 2540", .internal_name = "AC2540", .model = "WDC AC2540H", .zones = 4, .avg_spt = 150, .heads = 2, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 2850", .internal_name = "AC2850", .model = "WDC AC2850F", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 11000", .internal_name = "AC11000", .model = "WDC AC11000H", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 21200", .internal_name = "AC21200", .model = "WDC AC21200H", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 5200, .full_stroke_ms = 39, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 21600", .internal_name = "AC21600", .model = "WDC AC21600H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "AC22100", .model = "WDC AC22100H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "AC31200", .model = "WDC AC31200F", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, + { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "AC31200", .model = "WDC AC31200F", .zones = 8, .avg_spt = 210, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, { .name = "[ATA-3] Connor CFS1275A", .internal_name = "CFS1275A", .model = "Connor Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, // Either ATA-2 or ATA-3 - { .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-3] Fujitsu MPA3043AT", .internal_name = "MPA3043AT", .model = "FUJITSU MPA3043AT", .zones = 15, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-3] Fujitsu MPA3052AT", .internal_name = "MPA3052AT", .model = "FUJITSU MPA3052AT", .zones = 16, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-3] Samsung Voyager 6", .internal_name = "SV0844A", .model = "SAMSUNG SV0844A", .zones = 8, .avg_spt = 105, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-3] Samsung Winner 5X", .internal_name = "WU33205A", .model = "SAMSUNG WU33205A", .zones = 16, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 195, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 195, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 195, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Fujitsu MPA3043AT", .internal_name = "MPA3043AT", .model = "FUJITSU MPA3043AT", .zones = 15, .avg_spt = 195, .heads = 5, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Fujitsu MPA3052AT", .internal_name = "MPA3052AT", .model = "FUJITSU MPA3052AT", .zones = 16, .avg_spt = 195, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Samsung Voyager 6", .internal_name = "SV0844A", .model = "SAMSUNG SV0844A", .zones = 8, .avg_spt = 205, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-3] Samsung Winner 5X", .internal_name = "WU33205A", .model = "SAMSUNG WU33205A", .zones = 16, .avg_spt = 200, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Seagate Medalist 636", .internal_name = "ST3636A", .model = "Seagate Technology 636MB - ST3636A", .zones = 2, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-3] Seagate Medalist 1082", .internal_name = "ST31082A", .model = "Seagate Technology 1082MB - ST31082A", .zones = 4, .avg_spt = 130, .heads = 3, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-3] Seagate Medalist 1276", .internal_name = "ST31276A", .model = "Seagate Technology 1275MB - ST31276A", .zones = 4, .avg_spt = 130, .heads = 3, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, { .name = "[ATA-3] Seagate Medalist 1720", .internal_name = "ST31720A", .model = "ST31720A", .zones = 4, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Seagate Medalist 2132", .internal_name = "ST32132A", .model = "ST32132A", .zones = 8, .avg_spt = 125, .heads = 6, .rpm = 4500, .full_stroke_ms = 30, .track_seek_ms = 2.3, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 16 }, - { .name = "[ATA-3] Western Digital Caviar 21700", .internal_name = "AC21700", .model = "WDC AC21700H", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5200, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, // Apple Computer OEM only, not retail version - { .name = "[ATA-4] Fujitsu MPB3021AT", .internal_name = "MPB3021AT", .model = "FUJITSU MPB3021AT", .zones = 7, .avg_spt = 100, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 16 }, - { .name = "[ATA-4] Fujitsu MPD3043AT", .internal_name = "MPD3043AT", .model = "FUJITSU MPD3043AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 29, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-4] Fujitsu MPD3064AT", .internal_name = "MPD3064AT", .model = "FUJITSU MPD3064AT", .zones = 7, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-4] Fujitsu MPD3084AT", .internal_name = "MPD3084AT", .model = "FUJITSU MPD3084AT", .zones = 7, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-4] Fujitsu MPE3064AT", .internal_name = "MPE3064AT", .model = "FUJITSU MPE3064AT", .zones = 7, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax 2160", .internal_name = "86480D6", .model = "Maxtor 86480D6", .zones = 8, .avg_spt = 97, .heads = 4, .rpm = 5200, .full_stroke_ms = 18, .track_seek_ms = 1, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax 2880", .internal_name = "90432D3", .model = "Maxtor 90432D3", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax 3400", .internal_name = "90644D3", .model = "Maxtor 90644D3", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax 4320 (90432D2)", .internal_name = "90432D2", .model = "Maxtor 90432D2", .zones = 16, .avg_spt = 90, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax 4320 (90845D4)", .internal_name = "90845D4", .model = "Maxtor 90845D4", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (90683U2)", .internal_name = "90683U2", .model = "Maxtor 90683U2", .zones = 16, .avg_spt = 90, .heads = 2, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (91024U3)", .internal_name = "91024U3", .model = "Maxtor 91024U3", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (91366U4)", .internal_name = "91366U4", .model = "Maxtor 91366U4", .zones = 16, .avg_spt = 90, .heads = 4, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92049U6)", .internal_name = "92049U6", .model = "Maxtor 92049U6", .zones = 16, .avg_spt = 90, .heads = 6, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92732U8)", .internal_name = "92732U8", .model = "Maxtor 92732U8", .zones = 16, .avg_spt = 90, .heads = 8, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Quantum Bigfoot TX4.3AT", .internal_name = "TX043A011", .model = "QUANTUM BIGFOOT TX4.3A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, - { .name = "[ATA-4] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Quantum Fireball SE4.3A", .internal_name = "SE43A011", .model = "QUANTUM FIREBALL SE4.3A", .zones = 2, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Seagate Medalist 2122", .internal_name = "ST32122A", .model = "ST32122A", .zones = 16, .avg_spt = 115, .heads = 2, .rpm = 4500, .full_stroke_ms = 23, .track_seek_ms = 3.8, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Seagate Medalist 3321", .internal_name = "ST33221A", .model = "ST33221A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Seagate Medalist 4321", .internal_name = "ST34321A", .model = "ST34321A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Seagate Medalist 6531", .internal_name = "ST36531A", .model = "ST36531A", .zones = 16, .avg_spt = 115, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-4] Seagate Medalist 8420", .internal_name = "ST38420A", .model = "ST38420A", .zones = 16, .avg_spt = 90, .heads = 4, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Seagate Medalist 13030", .internal_name = "ST313030A", .model = "ST313030A", .zones = 16, .avg_spt = 90, .heads = 6, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Seagate Medalist 17240", .internal_name = "ST317240A", .model = "ST317240A", .zones = 16, .avg_spt = 90, .heads = 8, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Toshiba MK4006MAV", .internal_name = "MK4006MAV", .model = "TOSHIBA MK4006MAV", .zones = 8, .avg_spt = 130, .heads = 6, .rpm = 4200, .full_stroke_ms = 25, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Western Digital Caviar 14300", .internal_name = "AC14300", .model = "WDC AC14300RT", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 5.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-4] Western Digital Caviar 23200", .internal_name = "AC23200", .model = "WDC AC23200LB", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-4] Western Digital Caviar 26400", .internal_name = "AC26400", .model = "WDC AC26400RN", .zones = 16, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-4] Western Digital Caviar 33200", .internal_name = "AC33200", .model = "WDC AC33200LA", .zones = 16, .avg_spt = 110, .heads = 5, .rpm = 5200, .full_stroke_ms = 40, .track_seek_ms = 3, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-5] IBM Travelstar 6GN", .internal_name = "DARA206000", .model = "IBM-DARA-206000", .zones = 12, .avg_spt = 92, .heads = 2, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] IBM Travelstar 9GN", .internal_name = "DARA209000", .model = "IBM-DARA-209000", .zones = 12, .avg_spt = 92, .heads = 3, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] IBM/Hitachi Travelstar 12GN", .internal_name = "DARA212000", .model = "IBM-DARA-212000", .zones = 12, .avg_spt = 92, .heads = 4, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Either Hitachi or IBM OEM - { .name = "[ATA-5] Maxtor DiamondMax VL 17", .internal_name = "90871U2", .model = "Maxtor 90871U2", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-5] Maxtor DiamondMax VL 20 (91021U2)", .internal_name = "91021U2", .model = "Maxtor 91021U2", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Maxtor DiamondMax VL 20 (91531U3)", .internal_name = "91531U3", .model = "Maxtor 91531U3", .zones = 16, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Maxtor DiamondMax VL 20 (92041U4)", .internal_name = "92041U4", .model = "Maxtor 92041U4", .zones = 16, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Quantum Fireball EX3.2A", .internal_name = "EX32A012", .model = "QUANTUM FIREBALL EX3.2A", .zones = 1, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball EX6.4A", .internal_name = "EX64A012", .model = "QUANTUM FIREBALL EX6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR4.3A", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR6.4A", .internal_name = "CR64A011", .model = "QUANTUM FIREBALL CR6.4A", .zones = 2, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR8.4A", .internal_name = "CR84A011", .model = "QUANTUM FIREBALL CR8.4A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Quantum Fireball CR13.0A", .internal_name = "CR13A011", .model = "QUANTUM FIREBALL CR13.0A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-5] Samsung SpinPoint V6800 (SV0682D)", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1364D)", .internal_name = "SV1364D", .model = "SAMSUNG SV1364D", .zones = 8, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1705D)", .internal_name = "SV1705D", .model = "SAMSUNG SV1705D", .zones = 8, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Samsung SpinPoint V6800 (SV2046D)", .internal_name = "SV2046D", .model = "SAMSUNG SV2046D", .zones = 8, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 89, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Seagate U8 - 8.4gb", .internal_name = "ST38410A", .model = "ST38410A", .zones = 16, .avg_spt = 89, .heads = 2, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Seagate U8 - 13gb", .internal_name = "ST313021A", .model = "ST313021A", .zones = 16, .avg_spt = 89, .heads = 4, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Seagate U8 - 17.2gb", .internal_name = "ST317221A", .model = "ST317221A", .zones = 16, .avg_spt = 89, .heads = 3, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Western Digital Caviar 102AA", .internal_name = "WD102AA", .model = "WDC WD102AA-00ANA0", .zones = 16, .avg_spt = 95, .heads = 8, .rpm = 5400, .full_stroke_ms = 12, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-3] Western Digital Caviar 21700", .internal_name = "AC21700", .model = "WDC AC21700H", .zones = 8, .avg_spt = 185, .heads = 3, .rpm = 5200, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, // Apple Computer OEM only, not retail version + { .name = "[ATA-4] Fujitsu MPB3021AT", .internal_name = "MPB3021AT", .model = "FUJITSU MPB3021AT", .zones = 7, .avg_spt = 200, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 16 }, + { .name = "[ATA-4] Fujitsu MPD3043AT", .internal_name = "MPD3043AT", .model = "FUJITSU MPD3043AT", .zones = 5, .avg_spt = 195, .heads = 2, .rpm = 5400, .full_stroke_ms = 29, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Fujitsu MPD3064AT", .internal_name = "MPD3064AT", .model = "FUJITSU MPD3064AT", .zones = 7, .avg_spt = 195, .heads = 3, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Fujitsu MPD3084AT", .internal_name = "MPD3084AT", .model = "FUJITSU MPD3084AT", .zones = 7, .avg_spt = 195, .heads = 4, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Fujitsu MPE3064AT", .internal_name = "MPE3064AT", .model = "FUJITSU MPE3064AT", .zones = 7, .avg_spt = 295, .heads = 2, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 2160", .internal_name = "86480D6", .model = "Maxtor 86480D6", .zones = 8, .avg_spt = 197, .heads = 4, .rpm = 5200, .full_stroke_ms = 18, .track_seek_ms = 1, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 2880", .internal_name = "90432D3", .model = "Maxtor 90432D3", .zones = 16, .avg_spt = 190, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 3400", .internal_name = "90644D3", .model = "Maxtor 90644D3", .zones = 16, .avg_spt = 290, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 4320 (90432D2)", .internal_name = "90432D2", .model = "Maxtor 90432D2", .zones = 16, .avg_spt = 290, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 4320 (90845D4)", .internal_name = "90845D4", .model = "Maxtor 90845D4", .zones = 16, .avg_spt = 290, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (90683U2)", .internal_name = "90683U2", .model = "Maxtor 90683U2", .zones = 16, .avg_spt = 290, .heads = 2, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (91024U3)", .internal_name = "91024U3", .model = "Maxtor 91024U3", .zones = 16, .avg_spt = 290, .heads = 3, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (91366U4)", .internal_name = "91366U4", .model = "Maxtor 91366U4", .zones = 16, .avg_spt = 290, .heads = 4, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92049U6)", .internal_name = "92049U6", .model = "Maxtor 92049U6", .zones = 16, .avg_spt = 290, .heads = 6, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92732U8)", .internal_name = "92732U8", .model = "Maxtor 92732U8", .zones = 16, .avg_spt = 290, .heads = 8, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Quantum Bigfoot TX4.3AT", .internal_name = "TX043A011", .model = "QUANTUM BIGFOOT TX4.3A", .zones = 2, .avg_spt = 220, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[ATA-4] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 200, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Quantum Fireball SE4.3A", .internal_name = "SE43A011", .model = "QUANTUM FIREBALL SE4.3A", .zones = 2, .avg_spt = 200, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 200, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 200, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Seagate Medalist 2122", .internal_name = "ST32122A", .model = "ST32122A", .zones = 16, .avg_spt = 215, .heads = 2, .rpm = 4500, .full_stroke_ms = 23, .track_seek_ms = 3.8, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Seagate Medalist 3321", .internal_name = "ST33221A", .model = "ST33221A", .zones = 16, .avg_spt = 210, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Seagate Medalist 4321", .internal_name = "ST34321A", .model = "ST34321A", .zones = 16, .avg_spt = 210, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Seagate Medalist 6531", .internal_name = "ST36531A", .model = "ST36531A", .zones = 16, .avg_spt = 215, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Seagate Medalist 8420", .internal_name = "ST38420A", .model = "ST38420A", .zones = 16, .avg_spt = 290, .heads = 4, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Seagate Medalist 13030", .internal_name = "ST313030A", .model = "ST313030A", .zones = 16, .avg_spt = 290, .heads = 6, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Seagate Medalist 17240", .internal_name = "ST317240A", .model = "ST317240A", .zones = 16, .avg_spt = 290, .heads = 8, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Toshiba MK4006MAV", .internal_name = "MK4006MAV", .model = "TOSHIBA MK4006MAV", .zones = 8, .avg_spt = 230, .heads = 6, .rpm = 4200, .full_stroke_ms = 25, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Western Digital Caviar 14300", .internal_name = "AC14300", .model = "WDC AC14300RT", .zones = 16, .avg_spt = 195, .heads = 2, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 5.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Western Digital Caviar 23200", .internal_name = "AC23200", .model = "WDC AC23200LB", .zones = 16, .avg_spt = 210, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Western Digital Caviar 26400", .internal_name = "AC26400", .model = "WDC AC26400RN", .zones = 16, .avg_spt = 295, .heads = 5, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-4] Western Digital Caviar 33200", .internal_name = "AC33200", .model = "WDC AC33200LA", .zones = 16, .avg_spt = 310, .heads = 5, .rpm = 5200, .full_stroke_ms = 40, .track_seek_ms = 3, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-5] IBM Travelstar 6GN", .internal_name = "DARA206000", .model = "IBM-DARA-206000", .zones = 12, .avg_spt = 292, .heads = 2, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] IBM Travelstar 9GN", .internal_name = "DARA209000", .model = "IBM-DARA-209000", .zones = 12, .avg_spt = 292, .heads = 3, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] IBM/Hitachi Travelstar 12GN", .internal_name = "DARA212000", .model = "IBM-DARA-212000", .zones = 12, .avg_spt = 292, .heads = 4, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Either Hitachi or IBM OEM + { .name = "[ATA-5] Maxtor DiamondMax VL 17", .internal_name = "90871U2", .model = "Maxtor 90871U2", .zones = 16, .avg_spt = 290, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20 (91021U2)", .internal_name = "91021U2", .model = "Maxtor 91021U2", .zones = 16, .avg_spt = 295, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20 (91531U3)", .internal_name = "91531U3", .model = "Maxtor 91531U3", .zones = 16, .avg_spt = 295, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20 (92041U4)", .internal_name = "92041U4", .model = "Maxtor 92041U4", .zones = 16, .avg_spt = 295, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Quantum Fireball EX3.2A", .internal_name = "EX32A012", .model = "QUANTUM FIREBALL EX3.2A", .zones = 1, .avg_spt = 210, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 2, .avg_spt = 210, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX6.4A", .internal_name = "EX64A012", .model = "QUANTUM FIREBALL EX6.4A", .zones = 2, .avg_spt = 210, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 210, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 210, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR4.3A", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 310, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR6.4A", .internal_name = "CR64A011", .model = "QUANTUM FIREBALL CR6.4A", .zones = 2, .avg_spt = 310, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR8.4A", .internal_name = "CR84A011", .model = "QUANTUM FIREBALL CR8.4A", .zones = 3, .avg_spt = 310, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Quantum Fireball CR13.0A", .internal_name = "CR13A011", .model = "QUANTUM FIREBALL CR13.0A", .zones = 4, .avg_spt = 310, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV0682D)", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 295, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 295, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1364D)", .internal_name = "SV1364D", .model = "SAMSUNG SV1364D", .zones = 8, .avg_spt = 295, .heads = 4, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1705D)", .internal_name = "SV1705D", .model = "SAMSUNG SV1705D", .zones = 8, .avg_spt = 295, .heads = 5, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV2046D)", .internal_name = "SV2046D", .model = "SAMSUNG SV2046D", .zones = 8, .avg_spt = 295, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 289, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 8.4gb", .internal_name = "ST38410A", .model = "ST38410A", .zones = 16, .avg_spt = 289, .heads = 2, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 13gb", .internal_name = "ST313021A", .model = "ST313021A", .zones = 16, .avg_spt = 289, .heads = 4, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 17.2gb", .internal_name = "ST317221A", .model = "ST317221A", .zones = 16, .avg_spt = 289, .heads = 3, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Western Digital Caviar 102AA", .internal_name = "WD102AA", .model = "WDC WD102AA-00ANA0", .zones = 16, .avg_spt = 295, .heads = 8, .rpm = 5400, .full_stroke_ms = 12, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-5] Western Digital Expert", .internal_name = "WD135BA", .model = "WDC WD135BA-60AK", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 1920, .max_multiple = 32 }, // clang-format on }; From 6725d93b37d42cc317eee10060d196cba95b681d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 26 Jan 2025 03:01:19 -0500 Subject: [PATCH 0175/1190] Fixes to tmacm --- src/game/gameport.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/game/gameport.c b/src/game/gameport.c index 8d2a684fc..ae2135a39 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -48,6 +48,11 @@ typedef struct _gameport_ { struct _gameport_ *next; } gameport_t; +typedef struct _tmacm_ { + struct gameport_t *port1; + struct gameport_t *port2; +} tmacm_t; + typedef struct _joystick_instance_ { uint8_t state; g_axis_t axis[4]; @@ -402,25 +407,24 @@ gameport_init(const device_t *info) static void * tmacm_init(UNUSED(const device_t *info)) { - uint16_t port = 0x0000; - gameport_t *dev = NULL; + uint16_t port = 0x0000; + tmacm_t *dev = NULL; - dev = malloc(sizeof(gameport_t)); - memset(dev, 0x00, sizeof(gameport_t)); + dev = calloc(1, sizeof(tmacm_t)); port = (uint16_t) device_get_config_hex16("port1_addr"); switch (port) { case 0x201: - dev = gameport_add(&gameport_201_device); + dev->port1 = gameport_add(&gameport_201_device); break; case 0x203: - dev = gameport_add(&gameport_203_device); + dev->port1 = gameport_add(&gameport_203_device); break; case 0x205: - dev = gameport_add(&gameport_205_device); + dev->port1 = gameport_add(&gameport_205_device); break; case 0x207: - dev = gameport_add(&gameport_207_device); + dev->port1 = gameport_add(&gameport_207_device); break; default: break; @@ -429,16 +433,16 @@ tmacm_init(UNUSED(const device_t *info)) port = (uint16_t) device_get_config_hex16("port2_addr"); switch (port) { case 0x209: - dev = gameport_add(&gameport_209_device); + dev->port2 = gameport_add(&gameport_209_device); break; case 0x20b: - dev = gameport_add(&gameport_20b_device); + dev->port2 = gameport_add(&gameport_20b_device); break; case 0x20d: - dev = gameport_add(&gameport_20d_device); + dev->port2 = gameport_add(&gameport_20d_device); break; case 0x20f: - dev = gameport_add(&gameport_20f_device); + dev->port2 = gameport_add(&gameport_20f_device); break; default: break; From 26fb3bf69479c8bb8fdd04c51ab4633d31b2a711 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 26 Jan 2025 03:01:44 -0500 Subject: [PATCH 0176/1190] Actually close cartridge on error --- src/device/cartridge.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/device/cartridge.c b/src/device/cartridge.c index 52f36a4ca..22b36484a 100644 --- a/src/device/cartridge.c +++ b/src/device/cartridge.c @@ -104,6 +104,7 @@ cart_image_load(int drive, char *fn) if (size < 0x1200) { cartridge_log("cart_image_load(): File size %i is too small\n", size); cart_load_error(drive, fn); + fclose(fp); return; } if (size & 0x00000fff) { From e96c6579ba12b5c492d187ffffa5b32d4d8c3508 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 30 Nov 2024 15:26:06 -0500 Subject: [PATCH 0177/1190] Gameport backend work --- src/86box.c | 4 ++- src/game/gameport.c | 70 ++++++++++++++++++++++++++++++++++-- src/include/86box/86box.h | 5 +-- src/include/86box/gameport.h | 25 +++++++++++-- 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/86box.c b/src/86box.c index 97c211bee..e2cc55e75 100644 --- a/src/86box.c +++ b/src/86box.c @@ -11,6 +11,7 @@ * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, + * Jasmine Iwanek, * * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2020 Miran Grca. @@ -18,7 +19,7 @@ * Copyright 2021 Laci bá' * Copyright 2021 dob205 * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. */ #include #include @@ -178,6 +179,7 @@ int bugger_enabled = 0; /* (C) enable int novell_keycard_enabled = 0; /* (C) enable Novell NetWare 2.x key card emulation. */ int postcard_enabled = 0; /* (C) enable POST card */ int unittester_enabled = 0; /* (C) enable unit tester device */ +int gameport_type[GAMEPORT_MAX] = { 0, 0 }; /* (C) enable gameports */ int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */ int isartc_type = 0; /* (C) enable ISA RTC card */ int gfxcard[GFXCARD_MAX] = { 0, 0 }; /* (C) graphics/video card */ diff --git a/src/game/gameport.c b/src/game/gameport.c index ae2135a39..079f8edb4 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -8,8 +8,6 @@ * * Implementation of a generic Game Port. * - * - * * Authors: Miran Grca, * Sarah Walker, * RichardG, @@ -18,7 +16,7 @@ * Copyright 2016-2022 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2021 RichardG. - * Copyright 2021-2024 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. */ #include #include @@ -35,6 +33,12 @@ #include <86box/gameport.h> #include <86box/plat_unused.h> +device_t game_ports[GAMEPORT_MAX]; + +typedef struct { + const device_t *device; +} GAMEPORT; + typedef struct g_axis_t { pc_timer_t timer; int axis_nr; @@ -733,3 +737,63 @@ const device_t gameport_sio_1io_device = { .force_redraw = NULL, .config = NULL }; + +static const GAMEPORT gameports[] = { + { &device_none }, + { &device_internal }, + { &gameport_device }, + { &gameport_208_device }, + { &gameport_pnp_device }, + { &gameport_tm_acm_device }, + { NULL } + // clang-format on +}; + +/* UI */ +int +gameport_available(int port) +{ + if (gameports[port].device) + return (device_available(gameports[port].device)); + + return 1; +} + +/* UI */ +const device_t * +gameports_getdevice(int port) +{ + return (gameports[port].device); +} + +/* UI */ +int +gameport_has_config(int port) +{ + if (!gameports[port].device) + return 0; + + return (device_has_config(gameports[port].device) ? 1 : 0); +} + +/* UI */ +const char * +gameport_get_internal_name(int port) +{ + return device_get_internal_name(gameports[port].device); +} + +/* UI */ +int +gameport_get_from_internal_name(const char *str) +{ + int c = 0; + + while (gameports[c].device != NULL) { + if (!strcmp(gameports[c].device->internal_name, str)) + return c; + c++; + } + + return 0; +} diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 5dc0116fc..6f6caf743 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -8,14 +8,14 @@ * * Main include file for the application. * - * - * * Authors: Miran Grca, * Fred N. van Kempen, + * Jasmine Iwanek, * * Copyright 2016-2020 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2021 Laci bá' + * Copyright 2021-2025 Jasmine Iwanek. */ #ifndef EMU_86BOX_H #define EMU_86BOX_H @@ -131,6 +131,7 @@ extern int bugger_enabled; /* (C) enable ISAbugger */ extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */ extern int postcard_enabled; /* (C) enable POST card */ extern int unittester_enabled; /* (C) enable unit tester device */ +extern int gameport_type[]; /* (C) enable gameports */ extern int isamem_type[]; /* (C) enable ISA mem cards */ extern int isartc_type; /* (C) enable ISA RTC card */ extern int sound_is_float; /* (C) sound uses FP values */ diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index 3d3a253e8..6dda4b400 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -8,8 +8,6 @@ * * Definitions for the generic game port handlers. * - * - * * Authors: Miran Grca, * Sarah Walker, * RichardG, @@ -18,11 +16,13 @@ * Copyright 2016-2022 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2021 RichardG. - * Copyright 2021-2024 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. */ #ifndef EMU_GAMEPORT_H #define EMU_GAMEPORT_H +#define GAMEPORT_MAX 2 + #define MAX_PLAT_JOYSTICKS 8 #define MAX_JOYSTICKS 4 @@ -110,10 +110,20 @@ typedef struct joystick_if_t { const char *pov_names[MAX_JOY_POVS]; } joystick_if_t; +extern device_t game_ports[GAMEPORT_MAX]; + #ifdef __cplusplus extern "C" { #endif +extern int gameport_available(int port); +#ifdef EMU_DEVICE_H +extern const device_t *gameport_getdevice(int port); +#endif +extern int gameport_has_config(int port); +extern const char *gameport_get_internal_name(int port); +extern int gameport_get_from_internal_name(const char *str); + #ifdef EMU_DEVICE_H extern const device_t gameport_device; extern const device_t gameport_201_device; @@ -173,6 +183,15 @@ extern const joystick_if_t joystick_ch_flightstick_pro; extern const joystick_if_t joystick_sw_pad; extern const joystick_if_t joystick_tm_fcs; + +extern int gameport_available(int); +extern int gameport_has_config(int); +extern const char *gameport_get_internal_name(int); +extern int gampeport_get_from_internal_name(char *); +#ifdef EMU_DEVICE_H +extern const device_t *gameport_getdevice(int); +#endif + #ifdef __cplusplus } #endif From 3b29b769c36ba9afd7476a7173b768da9e8a3383 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 30 Nov 2024 18:48:22 -0500 Subject: [PATCH 0178/1190] Config --- src/config.c | 55 +++++++++++++++++++++++++++++++++++--- src/include/86box/config.h | 5 ++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/config.c b/src/config.c index 83b010eb2..22f94a9b3 100644 --- a/src/config.c +++ b/src/config.c @@ -8,20 +8,19 @@ * * Configuration file handler. * - * - * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * Overdoze, * David Hrdlička, + * Jasmine Iwanek, * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2018-2019 David Hrdlička. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * NOTE: Forcing config files to be in Unicode encoding breaks * it on Windows XP, and possibly also Vista. Use the @@ -760,6 +759,28 @@ load_ports(void) p = ini_section_get_string(cat, temp, "none"); lpt_ports[c].device = lpt_device_get_from_internal_name(p); } + +#if 0 +// TODO: Load + for (c = 0; c < GAMEPORT_MAX; c++) { + sprintf(temp, "gameport%d_enabled", c + 1); + game_ports[c].enabled = !!ini_section_get_int(cat, temp, (c == 0) ? 1 : 0); + + sprintf(temp, "gameport%d_device", c + 1); + p = ini_section_get_string(cat, temp, "none"); + game_ports[c].device = gameport_get_from_internal_name(p); + } + + for (uint8_t c = 0; c < GAMEPORT_MAX; c++) { + sprintf(temp, "gameport%d_type", c); + + p = ini_section_get_string(cat, temp, "none"); + gameport_type[c] = gameport_get_from_internal_name(p); + + if (!strcmp(p, "none")) + ini_section_delete_var(cat, temp); + } +#endif } /* Load "Storage Controllers" section. */ @@ -2377,6 +2398,34 @@ save_ports(void) lpt_device_get_internal_name(lpt_ports[c].device)); } +#if 0 +// TODO: Save + for (c = 0; c < GAMEPORT_MAX; c++) { + sprintf(temp, "gameport%d_enabled", c + 1); + d = (c == 0) ? 1 : 0; + if (game_ports[c].enabled == d) + ini_section_delete_var(cat, temp); + else + ini_section_set_int(cat, temp, game_ports[c].enabled); + + sprintf(temp, "gameport%d_device", c + 1); + if (game_ports[c].device == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + gameport_get_internal_name(game_ports[c].device)); + } + + for (uint8_t c = 0; c < GAMEPORT_MAX; c++) { + sprintf(temp, "gameport%d_enabled", c); + if (gameport_type[c] == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + gameport_get_internal_name(gameport_type[c])); + } +#endif + ini_delete_section_if_empty(config, cat); } diff --git a/src/include/86box/config.h b/src/include/86box/config.h index a043fb22a..693f38ab7 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -8,16 +8,16 @@ * * Configuration file handler header. * - * - * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * Overdoze, + * Jasmine Iwanek, * * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. + * Copyright 2021-2025 Jasmine Iwanek. */ #ifndef EMU_CONFIG_H #define EMU_CONFIG_H @@ -111,6 +111,7 @@ typedef struct config_t { # ifdef USE_SERIAL_DEVICES char serial_devices[SERIAL_MAX][32]; /* Serial device names */ # endif + char gameport_devices[GAMEPORT_MAX][32]; /* gameport device names */ /* Other peripherals category */ int fdc_current[FDC_MAX]; /* Floppy disk controller type */ From ac891a05a5863d331b2bcac0a1ee090e9e3a8811 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 18:42:09 -0500 Subject: [PATCH 0179/1190] Initial code for joystick port instancing --- src/config.c | 26 ++++----- src/game/gameport.c | 54 ++++++++--------- src/game/joystick_ch_flightstick_pro.c | 28 ++++----- src/game/joystick_standard.c | 80 +++++++++++++------------- src/game/joystick_sw_pad.c | 18 +++--- src/game/joystick_tm_fcs.c | 26 ++++----- src/include/86box/gameport.h | 4 +- src/qt/qt_joystickconfiguration.cpp | 8 +-- src/qt/qt_settingsinput.cpp | 16 +++--- src/qt/sdl_joystick.c | 46 +++++++-------- src/qt/win_joystick_rawinput.c | 38 ++++++------ src/unix/unix.c | 2 +- 12 files changed, 172 insertions(+), 174 deletions(-) diff --git a/src/config.c b/src/config.c index 22f94a9b3..c52ec48ad 100644 --- a/src/config.c +++ b/src/config.c @@ -524,23 +524,23 @@ load_input_devices(void) for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { sprintf(temp, "joystick_%i_nr", js); - joystick_state[js].plat_joystick_nr = ini_section_get_int(cat, temp, 0); + joystick_state[0][js].plat_joystick_nr = ini_section_get_int(cat, temp, 0); - if (joystick_state[js].plat_joystick_nr) { + if (joystick_state[0][js].plat_joystick_nr) { for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) { sprintf(temp, "joystick_%i_axis_%i", js, axis_nr); - joystick_state[js].axis_mapping[axis_nr] = ini_section_get_int(cat, temp, axis_nr); + joystick_state[0][js].axis_mapping[axis_nr] = ini_section_get_int(cat, temp, axis_nr); } for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) { sprintf(temp, "joystick_%i_button_%i", js, button_nr); - joystick_state[js].button_mapping[button_nr] = ini_section_get_int(cat, temp, button_nr); + joystick_state[0][js].button_mapping[button_nr] = ini_section_get_int(cat, temp, button_nr); } for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { sprintf(temp, "joystick_%i_pov_%i", js, pov_nr); p = ini_section_get_string(cat, temp, "0, 0"); - joystick_state[js].pov_mapping[pov_nr][0] = joystick_state[js].pov_mapping[pov_nr][1] = 0; - sscanf(p, "%i, %i", &joystick_state[js].pov_mapping[pov_nr][0], - &joystick_state[js].pov_mapping[pov_nr][1]); + joystick_state[0][js].pov_mapping[pov_nr][0] = joystick_state[0][js].pov_mapping[pov_nr][1] = 0; + sscanf(p, "%i, %i", &joystick_state[0][js].pov_mapping[pov_nr][0], + &joystick_state[0][js].pov_mapping[pov_nr][1]); } } } @@ -2195,21 +2195,21 @@ save_input_devices(void) for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { sprintf(tmp2, "joystick_%i_nr", js); - ini_section_set_int(cat, tmp2, joystick_state[js].plat_joystick_nr); + ini_section_set_int(cat, tmp2, joystick_state[0][js].plat_joystick_nr); - if (joystick_state[js].plat_joystick_nr) { + if (joystick_state[0][js].plat_joystick_nr) { for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) { sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); - ini_section_set_int(cat, tmp2, joystick_state[js].axis_mapping[axis_nr]); + ini_section_set_int(cat, tmp2, joystick_state[0][js].axis_mapping[axis_nr]); } for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) { sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); - ini_section_set_int(cat, tmp2, joystick_state[js].button_mapping[button_nr]); + ini_section_set_int(cat, tmp2, joystick_state[0][js].button_mapping[button_nr]); } for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); - sprintf(temp, "%i, %i", joystick_state[js].pov_mapping[pov_nr][0], - joystick_state[js].pov_mapping[pov_nr][1]); + sprintf(temp, "%i, %i", joystick_state[0][js].pov_mapping[pov_nr][0], + joystick_state[0][js].pov_mapping[pov_nr][1]); ini_section_set_string(cat, tmp2, temp); } } diff --git a/src/game/gameport.c b/src/game/gameport.c index 079f8edb4..9f61a2fbd 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -102,7 +102,7 @@ static const struct { { NULL } }; -static joystick_instance_t *joystick_instance = NULL; +static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL }; static uint8_t gameport_pnp_rom[] = { 0x09, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0002, dummy checksum (filled in by isapnp_add_card) */ @@ -284,10 +284,10 @@ gameport_update_joystick_type(void) gameport_add(standalone_gameport_type); /* Reset the joystick interface. */ - if (joystick_instance) { - joystick_instance->intf->close(joystick_instance->dat); - joystick_instance->intf = joysticks[joystick_type].joystick; - joystick_instance->dat = joystick_instance->intf->init(); + if (joystick_instance[0]) { + joystick_instance[0]->intf->close(joystick_instance[0]->dat); + joystick_instance[0]->intf = joysticks[joystick_type].joystick; + joystick_instance[0]->dat = joystick_instance[0]->intf->init(); } } @@ -372,30 +372,30 @@ gameport_init(const device_t *info) memset(dev, 0x00, sizeof(gameport_t)); /* Allocate global instance. */ - if (!joystick_instance && joystick_type) { - joystick_instance = malloc(sizeof(joystick_instance_t)); - memset(joystick_instance, 0x00, sizeof(joystick_instance_t)); + if (!joystick_instance[0] && joystick_type) { + joystick_instance[0] = malloc(sizeof(joystick_instance_t)); + memset(joystick_instance[0], 0x00, sizeof(joystick_instance_t)); - joystick_instance->axis[0].joystick = joystick_instance; - joystick_instance->axis[1].joystick = joystick_instance; - joystick_instance->axis[2].joystick = joystick_instance; - joystick_instance->axis[3].joystick = joystick_instance; + joystick_instance[0]->axis[0].joystick = joystick_instance[0]; + joystick_instance[0]->axis[1].joystick = joystick_instance[0]; + joystick_instance[0]->axis[2].joystick = joystick_instance[0]; + joystick_instance[0]->axis[3].joystick = joystick_instance[0]; - joystick_instance->axis[0].axis_nr = 0; - joystick_instance->axis[1].axis_nr = 1; - joystick_instance->axis[2].axis_nr = 2; - joystick_instance->axis[3].axis_nr = 3; + joystick_instance[0]->axis[0].axis_nr = 0; + joystick_instance[0]->axis[1].axis_nr = 1; + joystick_instance[0]->axis[2].axis_nr = 2; + joystick_instance[0]->axis[3].axis_nr = 3; - timer_add(&joystick_instance->axis[0].timer, timer_over, &joystick_instance->axis[0], 0); - timer_add(&joystick_instance->axis[1].timer, timer_over, &joystick_instance->axis[1], 0); - timer_add(&joystick_instance->axis[2].timer, timer_over, &joystick_instance->axis[2], 0); - timer_add(&joystick_instance->axis[3].timer, timer_over, &joystick_instance->axis[3], 0); + timer_add(&joystick_instance[0]->axis[0].timer, timer_over, &joystick_instance[0]->axis[0], 0); + timer_add(&joystick_instance[0]->axis[1].timer, timer_over, &joystick_instance[0]->axis[1], 0); + timer_add(&joystick_instance[0]->axis[2].timer, timer_over, &joystick_instance[0]->axis[2], 0); + timer_add(&joystick_instance[0]->axis[3].timer, timer_over, &joystick_instance[0]->axis[3], 0); - joystick_instance->intf = joysticks[joystick_type].joystick; - joystick_instance->dat = joystick_instance->intf->init(); + joystick_instance[0]->intf = joysticks[joystick_type].joystick; + joystick_instance[0]->dat = joystick_instance[0]->intf->init(); } - dev->joystick = joystick_instance; + dev->joystick = joystick_instance[0]; /* Map game port to the default address. Not applicable on PnP-only ports. */ dev->len = (info->local >> 16) & 0xff; @@ -464,11 +464,11 @@ gameport_close(void *priv) gameport_remap(dev, 0); /* Free the global instance here, if it wasn't already freed. */ - if (joystick_instance) { - joystick_instance->intf->close(joystick_instance->dat); + if (joystick_instance[0]) { + joystick_instance[0]->intf->close(joystick_instance[0]->dat); - free(joystick_instance); - joystick_instance = NULL; + free(joystick_instance[0]); + joystick_instance[0] = NULL; } free(dev); diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 8ca51d531..6aaaa5dc5 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -62,23 +62,23 @@ ch_flightstick_pro_read(UNUSED(void *priv)) { uint8_t ret = 0xf0; - if (JOYSTICK_PRESENT(0)) { - if (joystick_state[0].button[0]) + if (JOYSTICK_PRESENT(0, 0)) { + if (joystick_state[0][0].button[0]) ret &= ~0x10; - if (joystick_state[0].button[1]) + if (joystick_state[0][0].button[1]) ret &= ~0x20; - if (joystick_state[0].button[2]) + if (joystick_state[0][0].button[2]) ret &= ~0x40; - if (joystick_state[0].button[3]) + if (joystick_state[0][0].button[3]) ret &= ~0x80; - if (joystick_state[0].pov[0] != -1) { - if (joystick_state[0].pov[0] > 315 || joystick_state[0].pov[0] < 45) + if (joystick_state[0][0].pov[0] != -1) { + if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45) ret &= ~0xf0; - else if (joystick_state[0].pov[0] >= 45 && joystick_state[0].pov[0] < 135) + else if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135) ret &= ~0xb0; - else if (joystick_state[0].pov[0] >= 135 && joystick_state[0].pov[0] < 225) + else if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225) ret &= ~0x70; - else if (joystick_state[0].pov[0] >= 225 && joystick_state[0].pov[0] < 315) + else if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315) ret &= ~0x30; } } @@ -95,18 +95,18 @@ ch_flightstick_pro_write(UNUSED(void *priv)) static int ch_flightstick_pro_read_axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: return 0; case 3: - return joystick_state[0].axis[2]; + return joystick_state[0][0].axis[2]; default: return 0; } diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 201574126..122d2c65f 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -63,10 +63,10 @@ joystick_standard_read(UNUSED(void *priv)) uint8_t ret = 0xf0; for (int js = 0; js < 2; js++) { - if (JOYSTICK_PRESENT(js)) { - if (joystick_state[js].button[0]) + if (JOYSTICK_PRESENT(0, js)) { + if (joystick_state[0][js].button[0]) ret &= ~0x10; - if (joystick_state[js].button[1]) + if (joystick_state[0][js].button[1]) ret &= ~0x20; } } @@ -79,14 +79,14 @@ joystick_standard_read_4button(UNUSED(void *priv)) { uint8_t ret = 0xf0; - if (JOYSTICK_PRESENT(0)) { - if (joystick_state[0].button[0]) + if (JOYSTICK_PRESENT(0, 0)) { + if (joystick_state[0][0].button[0]) ret &= ~0x10; - if (joystick_state[0].button[1]) + if (joystick_state[0][0].button[1]) ret &= ~0x20; - if (joystick_state[0].button[2]) + if (joystick_state[0][0].button[2]) ret &= ~0x40; - if (joystick_state[0].button[3]) + if (joystick_state[0][0].button[3]) ret &= ~0x80; } @@ -104,21 +104,21 @@ joystick_standard_read_axis(UNUSED(void *priv), int axis) { switch (axis) { case 0: - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: - if (!JOYSTICK_PRESENT(1)) + if (!JOYSTICK_PRESENT(0, 1)) return AXIS_NOT_PRESENT; - return joystick_state[1].axis[0]; + return joystick_state[0][1].axis[0]; case 3: - if (!JOYSTICK_PRESENT(1)) + if (!JOYSTICK_PRESENT(0, 1)) return AXIS_NOT_PRESENT; - return joystick_state[1].axis[1]; + return joystick_state[0][1].axis[1]; default: return 0; } @@ -127,14 +127,14 @@ joystick_standard_read_axis(UNUSED(void *priv), int axis) static int joystick_standard_read_axis_4button(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: case 3: default: @@ -145,16 +145,16 @@ joystick_standard_read_axis_4button(UNUSED(void *priv), int axis) static int joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: - return joystick_state[0].axis[2]; + return joystick_state[0][0].axis[2]; case 3: default: return 0; @@ -164,18 +164,18 @@ joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis) static int joystick_standard_read_axis_4axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: - return joystick_state[0].axis[2]; + return joystick_state[0][0].axis[2]; case 3: - return joystick_state[0].axis[3]; + return joystick_state[0][0].axis[3]; default: return 0; } @@ -184,18 +184,18 @@ joystick_standard_read_axis_4axis(UNUSED(void *priv), int axis) static int joystick_standard_read_axis_6button(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: - return joystick_state[0].button[4] ? -32767 : 32768; + return joystick_state[0][0].button[4] ? -32767 : 32768; case 3: - return joystick_state[0].button[5] ? -32767 : 32768; + return joystick_state[0][0].button[5] ? -32767 : 32768; default: return 0; } @@ -203,24 +203,24 @@ joystick_standard_read_axis_6button(UNUSED(void *priv), int axis) static int joystick_standard_read_axis_8button(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: - if (joystick_state[0].button[4]) + if (joystick_state[0][0].button[4]) return -32767; - if (joystick_state[0].button[6]) + if (joystick_state[0][0].button[6]) return 32768; return 0; case 3: - if (joystick_state[0].button[5]) + if (joystick_state[0][0].button[5]) return -32767; - if (joystick_state[0].button[7]) + if (joystick_state[0][0].button[7]) return 32768; return 0; default: diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 238e84d11..bfdc0e025 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -141,7 +141,7 @@ sw_read(void *priv) sw_data *sw = (sw_data *) priv; uint8_t temp = 0; - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return 0xff; if (timer_is_enabled(&sw->poll_timer)) { @@ -167,7 +167,7 @@ sw_write(void *priv) sw_data *sw = (sw_data *) priv; int64_t time_since_last = timer_get_remaining_us(&sw->trigger_timer); - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return; if (!sw->poll_left) { @@ -193,20 +193,20 @@ sw_write(void *priv) for (uint8_t js = 0; js < 4; js++) { uint16_t data = 0x3fff; - if (!JOYSTICK_PRESENT(js)) + if (!JOYSTICK_PRESENT(0, js)) break; - if (joystick_state[js].axis[1] < -16383) + if (joystick_state[0][js].axis[1] < -16383) data &= ~1; - if (joystick_state[js].axis[1] > 16383) + if (joystick_state[0][js].axis[1] > 16383) data &= ~2; - if (joystick_state[js].axis[0] > 16383) + if (joystick_state[0][js].axis[0] > 16383) data &= ~4; - if (joystick_state[js].axis[0] < -16383) + if (joystick_state[0][js].axis[0] < -16383) data &= ~8; for (uint8_t button_nr = 0; button_nr < 10; button_nr++) { - if (joystick_state[js].button[button_nr]) + if (joystick_state[0][js].button[button_nr]) data &= ~(1 << (button_nr + 4)); } @@ -230,7 +230,7 @@ sw_write(void *priv) static int sw_read_axis(UNUSED(void *priv), UNUSED(int axis)) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; return 0; /*No analogue support on Sidewinder game pad*/ diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index f5c1e64e6..4440b039e 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -62,14 +62,14 @@ tm_fcs_read(UNUSED(void *priv)) { uint8_t ret = 0xf0; - if (JOYSTICK_PRESENT(0)) { - if (joystick_state[0].button[0]) + if (JOYSTICK_PRESENT(0, 0)) { + if (joystick_state[0][0].button[0]) ret &= ~0x10; - if (joystick_state[0].button[1]) + if (joystick_state[0][0].button[1]) ret &= ~0x20; - if (joystick_state[0].button[2]) + if (joystick_state[0][0].button[2]) ret &= ~0x40; - if (joystick_state[0].button[3]) + if (joystick_state[0][0].button[3]) ret &= ~0x80; } @@ -85,26 +85,26 @@ tm_fcs_write(UNUSED(void *priv)) static int tm_fcs_read_axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) + if (!JOYSTICK_PRESENT(0, 0)) return AXIS_NOT_PRESENT; switch (axis) { case 0: - return joystick_state[0].axis[0]; + return joystick_state[0][0].axis[0]; case 1: - return joystick_state[0].axis[1]; + return joystick_state[0][0].axis[1]; case 2: return 0; case 3: - if (joystick_state[0].pov[0] == -1) + if (joystick_state[0][0].pov[0] == -1) return 32767; - if (joystick_state[0].pov[0] > 315 || joystick_state[0].pov[0] < 45) + if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45) return -32768; - if (joystick_state[0].pov[0] >= 45 && joystick_state[0].pov[0] < 135) + if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135) return -16384; - if (joystick_state[0].pov[0] >= 135 && joystick_state[0].pov[0] < 225) + if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225) return 0; - if (joystick_state[0].pov[0] >= 225 && joystick_state[0].pov[0] < 315) + if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315) return 16384; return 0; default: diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index 6dda4b400..c5fc1d192 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -45,7 +45,7 @@ #define AXIS_NOT_PRESENT -99999 -#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) +#define JOYSTICK_PRESENT(gp, js) (joystick_state[gp][js].plat_joystick_nr != 0) #define GAMEPORT_1ADDR 0x010000 #define GAMEPORT_6ADDR 0x060000 @@ -146,7 +146,7 @@ extern const device_t *standalone_gameport_type; #endif extern int gameport_instance_id; extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -extern joystick_t joystick_state[MAX_JOYSTICKS]; +extern joystick_t joystick_state[GAMEPORT_MAX][MAX_JOYSTICKS]; extern int joysticks_present; extern int joystick_type; diff --git a/src/qt/qt_joystickconfiguration.cpp b/src/qt/qt_joystickconfiguration.cpp index 8489dfd22..62a9302d1 100644 --- a/src/qt/qt_joystickconfiguration.cpp +++ b/src/qt/qt_joystickconfiguration.cpp @@ -41,7 +41,7 @@ JoystickConfiguration::JoystickConfiguration(int type, int joystick_nr, QWidget Models::AddEntry(model, plat_joystick_state[c].name, c + 1); } - ui->comboBoxDevice->setCurrentIndex(joystick_state[joystick_nr].plat_joystick_nr); + ui->comboBoxDevice->setCurrentIndex(joystick_state[0][joystick_nr].plat_joystick_nr); layout()->setSizeConstraint(QLayout::SetFixedSize); } @@ -119,7 +119,7 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) } int nr_axes = plat_joystick_state[joystick].nr_axes; - int mapping = joystick_state[joystick_nr].axis_mapping[c]; + int mapping = joystick_state[0][joystick_nr].axis_mapping[c]; if (mapping & POV_X) cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2); else if (mapping & POV_Y) @@ -147,7 +147,7 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) Models::AddEntry(model, plat_joystick_state[joystick].button[d].name, 0); } - cbox->setCurrentIndex(joystick_state[joystick_nr].button_mapping[c]); + cbox->setCurrentIndex(joystick_state[0][joystick_nr].button_mapping[c]); ui->ct->addWidget(label, row, 0); ui->ct->addWidget(cbox, row, 1); @@ -179,7 +179,7 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) Models::AddEntry(model, plat_joystick_state[joystick].axis[d].name, 0); } - int mapping = joystick_state[joystick_nr].pov_mapping[c / 2][c & 1]; + int mapping = joystick_state[0][joystick_nr].pov_mapping[c / 2][c & 1]; int nr_povs = plat_joystick_state[joystick].nr_povs; if (mapping & POV_X) cbox->setCurrentIndex((mapping & 3) * 2); diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index d7b69442c..d7c61e8d2 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -136,7 +136,7 @@ static int get_axis(JoystickConfiguration &jc, int axis, int joystick_nr) { int axis_sel = jc.selectedAxis(axis); - int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; + int nr_axes = plat_joystick_state[joystick_state[0][joystick_nr].plat_joystick_nr - 1].nr_axes; if (axis_sel < nr_axes) { return axis_sel; @@ -153,7 +153,7 @@ static int get_pov(JoystickConfiguration &jc, int pov, int joystick_nr) { int pov_sel = jc.selectedPov(pov); - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs * 2; + int nr_povs = plat_joystick_state[joystick_state[0][joystick_nr].plat_joystick_nr - 1].nr_povs * 2; if (pov_sel < nr_povs) { if (pov_sel & 1) @@ -176,19 +176,19 @@ updateJoystickConfig(int type, int joystick_nr, QWidget *parent) break; } - joystick_state[joystick_nr].plat_joystick_nr = jc.selectedDevice(); - if (joystick_state[joystick_nr].plat_joystick_nr) { + joystick_state[0][joystick_nr].plat_joystick_nr = jc.selectedDevice(); + if (joystick_state[0][joystick_nr].plat_joystick_nr) { for (int axis_nr = 0; axis_nr < joystick_get_axis_count(type); axis_nr++) { - joystick_state[joystick_nr].axis_mapping[axis_nr] = get_axis(jc, axis_nr, joystick_nr); + joystick_state[0][joystick_nr].axis_mapping[axis_nr] = get_axis(jc, axis_nr, joystick_nr); } for (int button_nr = 0; button_nr < joystick_get_button_count(type); button_nr++) { - joystick_state[joystick_nr].button_mapping[button_nr] = jc.selectedButton(button_nr); + joystick_state[0][joystick_nr].button_mapping[button_nr] = jc.selectedButton(button_nr); } for (int pov_nr = 0; pov_nr < joystick_get_pov_count(type) * 2; pov_nr += 2) { - joystick_state[joystick_nr].pov_mapping[pov_nr][0] = get_pov(jc, pov_nr, joystick_nr); - joystick_state[joystick_nr].pov_mapping[pov_nr][1] = get_pov(jc, pov_nr + 1, joystick_nr); + joystick_state[0][joystick_nr].pov_mapping[pov_nr][0] = get_pov(jc, pov_nr, joystick_nr); + joystick_state[0][joystick_nr].pov_mapping[pov_nr][1] = get_pov(jc, pov_nr + 1, joystick_nr); } } } diff --git a/src/qt/sdl_joystick.c b/src/qt/sdl_joystick.c index 03159ba7f..83a2a67b1 100644 --- a/src/qt/sdl_joystick.c +++ b/src/qt/sdl_joystick.c @@ -8,13 +8,13 @@ * * SDL2 joystick interface. * - * - * * Authors: Sarah Walker, - * Joakim L. Gilje + * Joakim L. Gilje, + * Jasmine Iwanek, jriwanek@gmail.com> * - * Copyright 2017-2021 Sarah Walker - * Copyright 2021 Joakim L. Gilje + * Copyright 2017-2021 Sarah Walker. + * Copyright 2021 Joakim L. Gilje. + * Copyright 2021-2025 Jasmine Iwanek. */ #include @@ -33,8 +33,8 @@ #include <86box/gameport.h> #include <86box/plat_unused.h> -int joysticks_present; -joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present = 0; +joystick_t joystick_state[GAMEPORT_MAX][MAX_JOYSTICKS]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; static SDL_Joystick *sdl_joy[MAX_PLAT_JOYSTICKS]; @@ -89,7 +89,7 @@ joystick_close(void) } static int -joystick_get_axis(int joystick_nr, int mapping) +joystick_get_axis(int gameport, int joystick_nr, int mapping) { if (mapping & POV_X) { switch (plat_joystick_state[joystick_nr].p[mapping & 3]) { @@ -144,44 +144,44 @@ joystick_process(void) #if 0 pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, - joystick_state[js].x, - joystick_state[js].y, - joystick_state[js].b[0], - joystick_state[js].b[1], + joystick_state[0][js].x, + joystick_state[0][js].y, + joystick_state[0][js].b[0], + joystick_state[0][js].b[1], joysticks_present); #endif } for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { - if (joystick_state[js].plat_joystick_nr) { - int joystick_nr = joystick_state[js].plat_joystick_nr - 1; + if (joystick_state[0][js].plat_joystick_nr) { + int joystick_nr = joystick_state[0][js].plat_joystick_nr - 1; for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) - joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]); + joystick_state[0][js].axis[axis_nr] = joystick_get_axis(0, joystick_nr, joystick_state[0][js].axis_mapping[axis_nr]); for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) - joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; + joystick_state[0][js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[0][js].button_mapping[button_nr]]; for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { - int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); - int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); + int x = joystick_get_axis(0, joystick_nr, joystick_state[0][js].pov_mapping[pov_nr][0]); + int y = joystick_get_axis(0, joystick_nr, joystick_state[0][js].pov_mapping[pov_nr][1]); double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); double magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) - joystick_state[js].pov[pov_nr] = -1; + joystick_state[0][js].pov[pov_nr] = -1; else - joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; + joystick_state[0][js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; } } else { for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) - joystick_state[js].axis[axis_nr] = 0; + joystick_state[0][js].axis[axis_nr] = 0; for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) - joystick_state[js].button[button_nr] = 0; + joystick_state[0][js].button[button_nr] = 0; for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) - joystick_state[js].pov[pov_nr] = -1; + joystick_state[0][js].pov[pov_nr] = -1; } } } diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index c293dcaca..5173d4f05 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -8,15 +8,13 @@ * * RawInput joystick interface. * - * - * * Authors: Miran Grca, * GH Cao, - * Jasmine Iwanek, + * Jasmine Iwanek, * * Copyright 2016-2018 Miran Grca. * Copyright 2020 GH Cao. - * Copyright 2021-2023 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. */ #include #include @@ -98,9 +96,9 @@ typedef struct { } pov[MAX_JOY_POVS]; } raw_joystick_t; -plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; int joysticks_present = 0; +joystick_t joystick_state[GAMEPORT_MAX][MAX_JOYSTICKS]; +plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS]; @@ -419,7 +417,7 @@ win_joystick_handle(PRAWINPUT raw) if (r == HIDP_STATUS_SUCCESS) { for (int i = 0; i < usage_length; i++) { - int button = raw_joystick_state[j].usage_button[usage_list[i]]; + int button = raw_joystick_state[j].usage_button[usage_list[i]]; plat_joystick_state[j].b[button] = 128; } } @@ -455,7 +453,7 @@ win_joystick_handle(PRAWINPUT raw) plat_joystick_state[j].a[axis_nr] = value; #if 0 - joystick_log("%s %-06d ", plat_joystick_state[j].axis[axis_nr].name, plat_joystick_state[j].a[axis_nr]); + joystick_log("%s %-06d ", plat_joystick_state[0][j].axis[axis_nr].name, plat_joystick_state[j].a[axis_nr]); #endif } @@ -477,7 +475,7 @@ win_joystick_handle(PRAWINPUT raw) plat_joystick_state[j].p[pov_nr] = value; #if 0 - joystick_log("%s %-3d ", plat_joystick_state[j].pov[pov_nr].name, plat_joystick_state[j].p[pov_nr]); + joystick_log("%s %-3d ", plat_joystick_state[0][j].pov[pov_nr].name, plat_joystick_state[j].p[pov_nr]); #endif } #if 0 @@ -512,35 +510,35 @@ joystick_process(void) return; for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { - if (joystick_state[js].plat_joystick_nr) { - int joystick_nr = joystick_state[js].plat_joystick_nr - 1; + if (joystick_state[0][js].plat_joystick_nr) { + int joystick_nr = joystick_state[0][js].plat_joystick_nr - 1; for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) - joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]); + joystick_state[0][js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[0][js].axis_mapping[axis_nr]); for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) - joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; + joystick_state[0][js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[0][js].button_mapping[button_nr]]; for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { - int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); - int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); + int x = joystick_get_axis(joystick_nr, joystick_state[0][js].pov_mapping[pov_nr][0]); + int y = joystick_get_axis(joystick_nr, joystick_state[0][js].pov_mapping[pov_nr][1]); double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); double magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) - joystick_state[js].pov[pov_nr] = -1; + joystick_state[0][js].pov[pov_nr] = -1; else - joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; + joystick_state[0][js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; } } else { for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) - joystick_state[js].axis[axis_nr] = 0; + joystick_state[0][js].axis[axis_nr] = 0; for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) - joystick_state[js].button[button_nr] = 0; + joystick_state[0][js].button[button_nr] = 0; for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) - joystick_state[js].pov[pov_nr] = -1; + joystick_state[0][js].pov[pov_nr] = -1; } } } diff --git a/src/unix/unix.c b/src/unix/unix.c index 911905ef2..8e070d372 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -61,7 +61,7 @@ int fixed_size_y = 480; extern int title_set; extern wchar_t sdl_win_title[512]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; +joystick_t joystick_state[GAMEPORT_MAX][MAX_JOYSTICKS]; int joysticks_present; SDL_mutex *blitmtx; SDL_threadID eventthread; From 81b8038bc5115674db8a1c84fa0af70fa6ee9825 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 7 Jan 2025 01:12:42 -0500 Subject: [PATCH 0180/1190] Clean up .available & .poll --- src/acpi.c | 16 +- src/apm.c | 6 +- src/chipset/82c100.c | 2 +- src/chipset/acc2168.c | 2 +- src/chipset/ali1409.c | 2 +- src/chipset/ali1429.c | 4 +- src/chipset/ali1435.c | 2 +- src/chipset/ali1489.c | 2 +- src/chipset/ali1531.c | 2 +- src/chipset/ali1541.c | 2 +- src/chipset/ali1543.c | 4 +- src/chipset/ali1621.c | 2 +- src/chipset/ali6117.c | 4 +- src/chipset/compaq_386.c | 4 +- src/chipset/contaq_82c59x.c | 4 +- src/chipset/cs4031.c | 2 +- src/chipset/cs8230.c | 2 +- src/chipset/et6000.c | 2 +- src/chipset/gc100.c | 4 +- src/chipset/headland.c | 14 +- src/chipset/ims8848.c | 2 +- src/chipset/intel_420ex.c | 4 +- src/chipset/intel_4x0.c | 32 +-- src/chipset/intel_82335.c | 2 +- src/chipset/intel_i450kx.c | 2 +- src/chipset/intel_piix.c | 16 +- src/chipset/intel_sio.c | 4 +- src/chipset/neat.c | 2 +- src/chipset/olivetti_eva.c | 2 +- src/chipset/opti283.c | 2 +- src/chipset/opti291.c | 2 +- src/chipset/opti391.c | 6 +- src/chipset/opti495.c | 4 +- src/chipset/opti499.c | 2 +- src/chipset/opti5x7.c | 4 +- src/chipset/opti602.c | 4 +- src/chipset/opti822.c | 2 +- src/chipset/opti895.c | 6 +- src/chipset/scamp.c | 2 +- src/chipset/scat.c | 6 +- src/chipset/sis_5511.c | 2 +- src/chipset/sis_5511_h2p.c | 2 +- src/chipset/sis_5513_ide.c | 8 +- src/chipset/sis_5513_p2i.c | 10 +- src/chipset/sis_5571.c | 2 +- src/chipset/sis_5571_h2p.c | 2 +- src/chipset/sis_5571_old.c | 2 +- src/chipset/sis_5572_usb.c | 6 +- src/chipset/sis_5581.c | 2 +- src/chipset/sis_5581_h2p.c | 2 +- src/chipset/sis_5591.c | 4 +- src/chipset/sis_5591_h2p.c | 2 +- src/chipset/sis_5595_pmu.c | 4 +- src/chipset/sis_55xx.c | 2 +- src/chipset/sis_5600.c | 4 +- src/chipset/sis_5600_h2p.c | 2 +- src/chipset/sis_85c310.c | 2 +- src/chipset/sis_85c496.c | 4 +- src/chipset/sis_85c4xx.c | 8 +- src/chipset/sis_85c50x.c | 8 +- src/chipset/stpc.c | 12 +- src/chipset/umc_8886.c | 6 +- src/chipset/umc_8890.c | 2 +- src/chipset/umc_hb4.c | 2 +- src/chipset/via_apollo.c | 16 +- src/chipset/via_pipc.c | 12 +- src/chipset/via_vt82c49x.c | 8 +- src/chipset/via_vt82c505.c | 2 +- src/chipset/vl82c480.c | 4 +- src/chipset/wd76c10.c | 2 +- src/ddma.c | 2 +- src/device/bugger.c | 2 +- src/device/cassette.c | 2 +- src/device/hwm_gl518sm.c | 8 +- src/device/hwm_lm75.c | 4 +- src/device/hwm_lm78.c | 12 +- src/device/hwm_vt82c686.c | 2 +- src/device/ibm_5161.c | 2 +- src/device/isamem.c | 38 ++-- src/device/isapnp.c | 2 +- src/device/kbc_at.c | 50 ++--- src/device/keyboard_xt.c | 26 +-- src/device/mouse_bus.c | 6 +- src/device/mouse_microtouch_touchscreen.c | 2 +- src/device/mouse_ps2.c | 2 +- src/device/mouse_serial.c | 6 +- src/device/mouse_wacom_tablet.c | 6 +- src/device/nec_mate_unk.c | 2 +- src/device/novell_cardkey.c | 2 +- src/device/pci_bridge.c | 22 +- src/device/phoenix_486_jumper.c | 4 +- src/device/postcard.c | 2 +- src/device/serial.c | 16 +- src/device/serial_passthrough.c | 14 +- src/device/smbus_ali7101.c | 2 +- src/device/smbus_piix4.c | 4 +- src/device/smbus_sis5595.c | 2 +- src/device/unittester.c | 18 +- src/disk/hdc_esdi_at.c | 2 +- src/disk/hdc_esdi_mca.c | 2 +- src/disk/hdc_ide.c | 22 +- src/disk/hdc_ide_ali5213.c | 4 +- src/disk/hdc_ide_cmd640.c | 20 +- src/disk/hdc_ide_cmd646.c | 6 +- src/disk/hdc_ide_opti611.c | 4 +- src/disk/hdc_ide_sff8038i.c | 2 +- src/disk/hdc_ide_um8673f.c | 4 +- src/disk/hdc_ide_w83769f.c | 11 +- src/disk/hdc_st506_at.c | 2 +- src/disk/hdc_st506_xt.c | 26 +-- src/disk/hdc_xta.c | 36 +-- src/disk/hdc_xtide.c | 8 +- src/disk/lba_enhancer.c | 2 +- src/floppy/fdc.c | 42 ++-- src/floppy/fdc_magitronic.c | 2 +- src/floppy/fdc_monster.c | 2 +- src/floppy/fdc_pii15xb.c | 4 +- src/game/gameport.c | 32 +-- src/ioapic.c | 2 +- src/machine/m_amstrad.c | 12 +- src/machine/m_at_compaq.c | 2 +- src/machine/m_at_grid.c | 2 +- src/machine/m_at_t3100e_vid.c | 2 +- src/machine/m_europc.c | 2 +- src/machine/m_pcjr.c | 2 +- src/machine/m_ps1.c | 2 +- src/machine/m_ps1_hdc.c | 2 +- src/machine/m_tandy.c | 10 +- src/machine/m_xt_olivetti.c | 4 +- src/machine/m_xt_philips.c | 2 +- src/machine/m_xt_t1000_vid.c | 4 +- src/machine/m_xt_xi8088.c | 2 +- src/machine/m_xt_zenith.c | 2 +- src/mem/catalyst_flash.c | 2 +- src/mem/intel_flash.c | 6 +- src/mem/row.c | 18 +- src/mem/spd.c | 2 +- src/mem/sst_flash.c | 60 ++--- src/network/net_3c501.c | 2 +- src/network/net_3c503.c | 18 +- src/network/net_dp8390.c | 2 +- src/network/net_eeprom_nmc93cxx.c | 2 +- src/network/net_modem.c | 2 +- src/network/net_ne2000.c | 18 +- src/network/net_null.c | 8 +- src/network/net_pcap.c | 8 +- src/network/net_pcnet.c | 14 +- src/network/net_plip.c | 2 +- src/network/net_rtl8139.c | 2 +- src/network/net_slirp.c | 7 +- src/network/net_tulip.c | 8 +- src/network/net_vde.c | 8 +- src/network/net_wd8003.c | 12 +- src/nvr_at.c | 32 +-- src/nvr_ps2.c | 4 +- src/pci_dummy.c | 4 +- src/pit.c | 32 +-- src/pit_fast.c | 30 +-- src/port_6x.c | 8 +- src/port_92.c | 10 +- src/scsi/scsi_aha154x.c | 12 +- src/scsi/scsi_buslogic.c | 16 +- src/scsi/scsi_ncr53c400.c | 10 +- src/scsi/scsi_ncr53c8xx.c | 14 +- src/scsi/scsi_pcscsi.c | 6 +- src/scsi/scsi_spock.c | 4 +- src/scsi/scsi_t128.c | 6 +- src/sio/sio_82091aa.c | 8 +- src/sio/sio_acc3221.c | 2 +- src/sio/sio_ali5123.c | 2 +- src/sio/sio_detect.c | 2 +- src/sio/sio_f82c710.c | 4 +- src/sio/sio_fdc37c669.c | 4 +- src/sio/sio_fdc37c67x.c | 2 +- src/sio/sio_fdc37c6xx.c | 24 +- src/sio/sio_fdc37c93x.c | 18 +- src/sio/sio_fdc37m60x.c | 4 +- src/sio/sio_it86x1f.c | 4 +- src/sio/sio_pc87306.c | 2 +- src/sio/sio_pc87307.c | 8 +- src/sio/sio_pc87309.c | 4 +- src/sio/sio_pc87310.c | 6 +- src/sio/sio_pc87311.c | 4 +- src/sio/sio_pc87332.c | 10 +- src/sio/sio_prime3b.c | 4 +- src/sio/sio_prime3c.c | 4 +- src/sio/sio_um8663f.c | 12 +- src/sio/sio_um8669f.c | 6 +- src/sio/sio_vl82c113.c | 2 +- src/sio/sio_vt82c686.c | 2 +- src/sio/sio_w83787f.c | 10 +- src/sio/sio_w83877f.c | 8 +- src/sio/sio_w83977f.c | 10 +- src/sound/snd_sb.c | 4 +- src/usb.c | 2 +- src/video/agpgart.c | 2 +- src/video/vid_8514a.c | 12 +- src/video/vid_ati18800.c | 10 +- src/video/vid_ati28800.c | 22 +- src/video/vid_ati68860_ramdac.c | 2 +- src/video/vid_ati68875_ramdac.c | 2 +- src/video/vid_ati_mach64.c | 16 +- src/video/vid_ati_mach8.c | 124 +++++------ src/video/vid_att20c49x_ramdac.c | 6 +- src/video/vid_att2xc498_ramdac.c | 2 +- src/video/vid_av9194.c | 2 +- src/video/vid_bochs_vbe.c | 6 +- src/video/vid_bt481_ramdac.c | 2 +- src/video/vid_bt48x_ramdac.c | 10 +- src/video/vid_cga.c | 8 +- src/video/vid_chips_69000.c | 4 +- src/video/vid_cl54xx.c | 106 ++++----- src/video/vid_colorplus.c | 6 +- src/video/vid_compaq_cga.c | 4 +- src/video/vid_ega.c | 16 +- src/video/vid_et3000.c | 4 +- src/video/vid_et4000.c | 24 +- src/video/vid_et4000w32.c | 32 ++- src/video/vid_f82c425.c | 2 +- src/video/vid_genius.c | 2 +- src/video/vid_hercules.c | 6 +- src/video/vid_herculesplus.c | 6 +- src/video/vid_ht216.c | 16 +- src/video/vid_ibm_rgb528_ramdac.c | 2 +- src/video/vid_icd2061.c | 4 +- src/video/vid_ics2494.c | 8 +- src/video/vid_ics2595.c | 2 +- src/video/vid_im1024.c | 2 +- src/video/vid_incolor.c | 2 +- src/video/vid_mda.c | 6 +- src/video/vid_mga.c | 14 +- src/video/vid_nga.c | 6 +- src/video/vid_oak_oti.c | 28 +-- src/video/vid_ogc.c | 8 +- src/video/vid_paradise.c | 22 +- src/video/vid_pgc.c | 2 +- src/video/vid_rtg310x.c | 12 +- src/video/vid_s3.c | 257 +++++++++++----------- src/video/vid_s3_virge.c | 48 ++-- src/video/vid_sc1148x_ramdac.c | 8 +- src/video/vid_sc1502x_ramdac.c | 2 +- src/video/vid_sdac_ramdac.c | 8 +- src/video/vid_sigma.c | 6 +- src/video/vid_stg_ramdac.c | 2 +- src/video/vid_tgui9440.c | 22 +- src/video/vid_ti_cf62011.c | 2 +- src/video/vid_tkd8001_ramdac.c | 2 +- src/video/vid_tvga.c | 94 ++++---- src/video/vid_tvp3026_ramdac.c | 2 +- src/video/vid_vga.c | 6 +- src/video/vid_voodoo.c | 6 +- src/video/vid_voodoo_banshee.c | 44 ++-- src/video/vid_wy700.c | 2 +- src/video/vid_xga.c | 6 +- 254 files changed, 1214 insertions(+), 1313 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 339ea7dcf..0d5c1fe00 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -2576,7 +2576,7 @@ const device_t acpi_ali_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2590,7 +2590,7 @@ const device_t acpi_intel_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2604,7 +2604,7 @@ const device_t acpi_via_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2618,7 +2618,7 @@ const device_t acpi_via_596b_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2632,7 +2632,7 @@ const device_t acpi_smc_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2646,7 +2646,7 @@ const device_t acpi_sis_5582_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2660,7 +2660,7 @@ const device_t acpi_sis_5595_1997_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL @@ -2674,7 +2674,7 @@ const device_t acpi_sis_5595_device = { .init = acpi_init, .close = acpi_close, .reset = acpi_reset, - { .available = NULL }, + .available = NULL, .speed_changed = acpi_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/apm.c b/src/apm.c index d7ce262a3..3973f2b23 100644 --- a/src/apm.c +++ b/src/apm.c @@ -122,7 +122,7 @@ const device_t apm_device = { .init = apm_init, .close = apm_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -136,7 +136,7 @@ const device_t apm_pci_device = { .init = apm_init, .close = apm_close, .reset = apm_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -150,7 +150,7 @@ const device_t apm_pci_acpi_device = { .init = apm_init, .close = apm_close, .reset = apm_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c index 689234ebb..05c3522d8 100644 --- a/src/chipset/82c100.c +++ b/src/chipset/82c100.c @@ -393,7 +393,7 @@ const device_t ct_82c100_device = { .init = ct_82c100_init, .close = ct_82c100_close, .reset = ct_82c100_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 9ce29bdff..982f50e82 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -201,7 +201,7 @@ const device_t acc2168_device = { .init = acc2168_init, .close = acc2168_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c index 3e4286f80..8cda1a22b 100644 --- a/src/chipset/ali1409.c +++ b/src/chipset/ali1409.c @@ -191,7 +191,7 @@ const device_t ali1409_device = { .init = ali1409_init, .close = ali1409_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index 34c3e18c2..4a6a5cfa9 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -358,7 +358,7 @@ const device_t ali1429_device = { .init = ali1429_init, .close = ali1429_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -372,7 +372,7 @@ const device_t ali1429g_device = { .init = ali1429_init, .close = ali1429_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1435.c b/src/chipset/ali1435.c index 9476d2b45..8360267c9 100644 --- a/src/chipset/ali1435.c +++ b/src/chipset/ali1435.c @@ -308,7 +308,7 @@ const device_t ali1435_device = { .init = ali1435_init, .close = ali1435_close, .reset = ali1435_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 3550f1da6..c61dd1511 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -499,7 +499,7 @@ const device_t ali1489_device = { .init = ali1489_init, .close = ali1489_close, .reset = ali1489_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index 06d0a0a60..1ff0689ad 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -389,7 +389,7 @@ const device_t ali1531_device = { .init = ali1531_init, .close = ali1531_close, .reset = ali1531_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c index d57ef51e7..3d7c1c546 100644 --- a/src/chipset/ali1541.c +++ b/src/chipset/ali1541.c @@ -665,7 +665,7 @@ const device_t ali1541_device = { .init = ali1541_init, .close = ali1541_close, .reset = ali1541_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index f35ec7590..2b9c93cb4 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1673,7 +1673,7 @@ const device_t ali1543_device = { .init = ali1543_init, .close = ali1543_close, .reset = ali1543_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1687,7 +1687,7 @@ const device_t ali1543c_device = { .init = ali1543_init, .close = ali1543_close, .reset = ali1543_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali1621.c b/src/chipset/ali1621.c index 6194dce19..96748ce34 100644 --- a/src/chipset/ali1621.c +++ b/src/chipset/ali1621.c @@ -692,7 +692,7 @@ const device_t ali1621_device = { .init = ali1621_init, .close = ali1621_close, .reset = ali1621_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index cc2e465a2..2d66ba9d1 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -499,7 +499,7 @@ const device_t ali1217_device = { .init = ali6117_init, .close = ali6117_close, .reset = ali6117_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -513,7 +513,7 @@ const device_t ali6117d_device = { .init = ali6117_init, .close = ali6117_close, .reset = ali6117_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/compaq_386.c b/src/chipset/compaq_386.c index 8c241e087..bc81c5472 100644 --- a/src/chipset/compaq_386.c +++ b/src/chipset/compaq_386.c @@ -772,7 +772,7 @@ const device_t compaq_386_device = { .init = compaq_386_init, .close = compaq_386_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -786,7 +786,7 @@ const device_t compaq_genoa_device = { .init = compaq_genoa_init, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index 5c2910227..90667c42f 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -359,7 +359,7 @@ const device_t contaq_82c596a_device = { .init = contaq_82c59x_init, .close = contaq_82c59x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -373,7 +373,7 @@ const device_t contaq_82c597_device = { .init = contaq_82c59x_init, .close = contaq_82c59x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/cs4031.c b/src/chipset/cs4031.c index fb439ec3a..b482fa254 100644 --- a/src/chipset/cs4031.c +++ b/src/chipset/cs4031.c @@ -185,7 +185,7 @@ const device_t cs4031_device = { .init = cs4031_init, .close = cs4031_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/cs8230.c b/src/chipset/cs8230.c index 93a7f1bba..62852b88d 100644 --- a/src/chipset/cs8230.c +++ b/src/chipset/cs8230.c @@ -178,7 +178,7 @@ const device_t cs8230_device = { .init = cs8230_init, .close = cs8230_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/et6000.c b/src/chipset/et6000.c index f2cffd7f7..608f2cc9b 100644 --- a/src/chipset/et6000.c +++ b/src/chipset/et6000.c @@ -162,7 +162,7 @@ const device_t et6000_device = { .init = et6000_init, .close = et6000_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/gc100.c b/src/chipset/gc100.c index 0b4717903..fc2321fae 100644 --- a/src/chipset/gc100.c +++ b/src/chipset/gc100.c @@ -238,7 +238,7 @@ const device_t gc100_device = { .init = gc100_init, .close = gc100_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -252,7 +252,7 @@ const device_t gc100a_device = { .init = gc100_init, .close = gc100_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/headland.c b/src/chipset/headland.c index db5922470..9d7cf97c7 100644 --- a/src/chipset/headland.c +++ b/src/chipset/headland.c @@ -699,7 +699,7 @@ const device_t headland_gc10x_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -713,7 +713,7 @@ const device_t headland_gc113_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -727,7 +727,7 @@ const device_t headland_ht18a_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -741,7 +741,7 @@ const device_t headland_ht18b_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -755,7 +755,7 @@ const device_t headland_ht18c_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -769,7 +769,7 @@ const device_t headland_ht21c_d_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -783,7 +783,7 @@ const device_t headland_ht21e_device = { .init = headland_init, .close = headland_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/ims8848.c b/src/chipset/ims8848.c index 3e86a44e1..0ce3a5e44 100644 --- a/src/chipset/ims8848.c +++ b/src/chipset/ims8848.c @@ -416,7 +416,7 @@ const device_t ims8848_device = { .init = ims8848_init, .close = ims8848_close, .reset = ims8848_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/intel_420ex.c b/src/chipset/intel_420ex.c index 34335d53c..7b069cce3 100644 --- a/src/chipset/intel_420ex.c +++ b/src/chipset/intel_420ex.c @@ -579,7 +579,7 @@ const device_t i420ex_device = { .init = i420ex_init, .close = i420ex_close, .reset = i420ex_reset, - { .available = NULL }, + .available = NULL, .speed_changed = i420ex_speed_changed, .force_redraw = NULL, .config = NULL @@ -593,7 +593,7 @@ const device_t i420ex_ide_device = { .init = i420ex_init, .close = i420ex_close, .reset = i420ex_reset, - { .available = NULL }, + .available = NULL, .speed_changed = i420ex_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 2f6afa940..36303deb7 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1967,7 +1967,7 @@ const device_t i420tx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1981,7 +1981,7 @@ const device_t i420zx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1995,7 +1995,7 @@ const device_t i430lx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2009,7 +2009,7 @@ const device_t i430nx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2023,7 +2023,7 @@ const device_t i430fx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2037,7 +2037,7 @@ const device_t i430fx_rev02_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2051,7 +2051,7 @@ const device_t i430hx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2065,7 +2065,7 @@ const device_t i430vx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2079,7 +2079,7 @@ const device_t i430tx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2093,7 +2093,7 @@ const device_t i440fx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2107,7 +2107,7 @@ const device_t i440lx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2121,7 +2121,7 @@ const device_t i440ex_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2135,7 +2135,7 @@ const device_t i440bx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2149,7 +2149,7 @@ const device_t i440bx_no_agp_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2163,7 +2163,7 @@ const device_t i440gx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2177,7 +2177,7 @@ const device_t i440zx_device = { .init = i4x0_init, .close = i4x0_close, .reset = i4x0_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/intel_82335.c b/src/chipset/intel_82335.c index da0cc30f6..cc7f07c3a 100644 --- a/src/chipset/intel_82335.c +++ b/src/chipset/intel_82335.c @@ -209,7 +209,7 @@ const device_t intel_82335_device = { .init = intel_82335_init, .close = intel_82335_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index 2f6547309..1dfd6f315 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -824,7 +824,7 @@ const device_t i450kx_device = { .init = i450kx_init, .close = i450kx_close, .reset = i450kx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index c6a6fc0ac..e52492df9 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1674,7 +1674,7 @@ const device_t piix_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1688,7 +1688,7 @@ const device_t piix_no_mirq_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1702,7 +1702,7 @@ const device_t piix_rev02_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1716,7 +1716,7 @@ const device_t piix3_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1730,7 +1730,7 @@ const device_t piix3_ioapic_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1744,7 +1744,7 @@ const device_t piix4_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1758,7 +1758,7 @@ const device_t piix4e_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL @@ -1772,7 +1772,7 @@ const device_t slc90e66_device = { .init = piix_init, .close = piix_close, .reset = piix_reset, - { .available = NULL }, + .available = NULL, .speed_changed = piix_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index 03a292da8..c66b5ce04 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -568,7 +568,7 @@ const device_t sio_device = { .init = sio_init, .close = sio_close, .reset = sio_reset, - { .available = NULL }, + .available = NULL, .speed_changed = sio_speed_changed, .force_redraw = NULL, .config = NULL @@ -582,7 +582,7 @@ const device_t sio_zb_device = { .init = sio_init, .close = sio_close, .reset = sio_reset, - { .available = NULL }, + .available = NULL, .speed_changed = sio_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 000492d14..6f7dc5be3 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -1124,7 +1124,7 @@ const device_t neat_device = { .init = neat_init, .close = neat_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/olivetti_eva.c b/src/chipset/olivetti_eva.c index 1f5eacc6c..bdb5440c9 100644 --- a/src/chipset/olivetti_eva.c +++ b/src/chipset/olivetti_eva.c @@ -171,7 +171,7 @@ const device_t olivetti_eva_device = { .init = olivetti_eva_init, .close = olivetti_eva_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti283.c b/src/chipset/opti283.c index 63976985b..b708eb0ab 100644 --- a/src/chipset/opti283.c +++ b/src/chipset/opti283.c @@ -324,7 +324,7 @@ const device_t opti283_device = { .init = opti283_init, .close = opti283_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti291.c b/src/chipset/opti291.c index 6d2256974..0ff037434 100644 --- a/src/chipset/opti291.c +++ b/src/chipset/opti291.c @@ -161,7 +161,7 @@ const device_t opti291_device = { .init = opti291_init, .close = opti291_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti391.c b/src/chipset/opti391.c index c22c2a04b..7d3c10c98 100644 --- a/src/chipset/opti391.c +++ b/src/chipset/opti391.c @@ -374,7 +374,7 @@ const device_t opti381_device = { .init = opti391_init, .close = opti391_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -388,7 +388,7 @@ const device_t opti481_device = { .init = opti391_init, .close = opti391_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -402,7 +402,7 @@ const device_t opti391_device = { .init = opti391_init, .close = opti391_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index 84ef6a202..f53ae0899 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -271,7 +271,7 @@ const device_t opti493_device = { .init = opti495_init, .close = opti495_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -285,7 +285,7 @@ const device_t opti495_device = { .init = opti495_init, .close = opti495_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index ecadd2224..81c5bee5a 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -265,7 +265,7 @@ const device_t opti499_device = { .init = opti499_init, .close = opti499_close, .reset = opti499_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 494fdee64..015ffb9f4 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -193,7 +193,7 @@ const device_t opti5x7_device = { .init = opti5x7_init, .close = opti5x7_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -207,7 +207,7 @@ const device_t opti5x7_pci_device = { .init = opti5x7_init, .close = opti5x7_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti602.c b/src/chipset/opti602.c index 3b5614ff4..7082408c7 100644 --- a/src/chipset/opti602.c +++ b/src/chipset/opti602.c @@ -218,7 +218,7 @@ const device_t opti601_device = { .init = opti602_init, .close = opti602_close, .reset = opti602_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -232,7 +232,7 @@ const device_t opti602_device = { .init = opti602_init, .close = opti602_close, .reset = opti602_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti822.c b/src/chipset/opti822.c index 3e9316f2b..9dd835412 100644 --- a/src/chipset/opti822.c +++ b/src/chipset/opti822.c @@ -412,7 +412,7 @@ const device_t opti822_device = { .init = opti822_init, .close = opti822_close, .reset = opti822_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index f1878a51b..4ce31c362 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -306,7 +306,7 @@ const device_t opti802g_device = { .init = opti895_init, .close = opti895_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -320,7 +320,7 @@ const device_t opti802g_pci_device = { .init = opti895_init, .close = opti895_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -334,7 +334,7 @@ const device_t opti895_device = { .init = opti895_init, .close = opti895_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 31e24eeba..6a38f4ec2 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -1204,7 +1204,7 @@ const device_t vlsi_scamp_device = { .init = scamp_init, .close = scamp_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/scat.c b/src/chipset/scat.c index d168b643f..edbaf41e3 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1559,7 +1559,7 @@ const device_t scat_device = { .init = scat_init, .close = scat_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1573,7 +1573,7 @@ const device_t scat_4_device = { .init = scat_init, .close = scat_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1587,7 +1587,7 @@ const device_t scat_sx_device = { .init = scat_init, .close = scat_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index aa841ed9c..38fcfe717 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -165,7 +165,7 @@ const device_t sis_5511_device = { .init = sis_5511_init, .close = sis_5511_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c index 7916d6ae2..543fcacc5 100644 --- a/src/chipset/sis_5511_h2p.c +++ b/src/chipset/sis_5511_h2p.c @@ -454,7 +454,7 @@ const device_t sis_5511_h2p_device = { .init = sis_5511_host_to_pci_init, .close = sis_5511_host_to_pci_close, .reset = sis_5511_host_to_pci_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5513_ide.c b/src/chipset/sis_5513_ide.c index 5cbfbdea8..9e3a0ad07 100644 --- a/src/chipset/sis_5513_ide.c +++ b/src/chipset/sis_5513_ide.c @@ -456,7 +456,7 @@ const device_t sis_5513_ide_device = { .init = sis_5513_ide_init, .close = sis_5513_ide_close, .reset = sis_5513_ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -470,7 +470,7 @@ const device_t sis_5572_ide_device = { .init = sis_5513_ide_init, .close = sis_5513_ide_close, .reset = sis_5513_ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -484,7 +484,7 @@ const device_t sis_5582_ide_device = { .init = sis_5513_ide_init, .close = sis_5513_ide_close, .reset = sis_5513_ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -498,7 +498,7 @@ const device_t sis_5591_5600_ide_device = { .init = sis_5513_ide_init, .close = sis_5513_ide_close, .reset = sis_5513_ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index 4205db161..e7012e1b6 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -1318,7 +1318,7 @@ const device_t sis_5513_p2i_device = { .init = sis_5513_pci_to_isa_init, .close = sis_5513_pci_to_isa_close, .reset = sis_5513_pci_to_isa_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1332,7 +1332,7 @@ const device_t sis_5572_p2i_device = { .init = sis_5513_pci_to_isa_init, .close = sis_5513_pci_to_isa_close, .reset = sis_5513_pci_to_isa_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1347,7 +1347,7 @@ const device_t sis_5582_p2i_device = { .init = sis_5513_pci_to_isa_init, .close = sis_5513_pci_to_isa_close, .reset = sis_5513_pci_to_isa_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1362,7 +1362,7 @@ const device_t sis_5595_1997_p2i_device = { .init = sis_5513_pci_to_isa_init, .close = sis_5513_pci_to_isa_close, .reset = sis_5513_pci_to_isa_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1376,7 +1376,7 @@ const device_t sis_5595_p2i_device = { .init = sis_5513_pci_to_isa_init, .close = sis_5513_pci_to_isa_close, .reset = sis_5513_pci_to_isa_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 3fb111978..3980704fd 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -177,7 +177,7 @@ const device_t sis_5571_device = { .init = sis_5571_init, .close = sis_5571_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5571_h2p.c b/src/chipset/sis_5571_h2p.c index 4a4ee9b83..d04964581 100644 --- a/src/chipset/sis_5571_h2p.c +++ b/src/chipset/sis_5571_h2p.c @@ -451,7 +451,7 @@ const device_t sis_5571_h2p_device = { .init = sis_5571_host_to_pci_init, .close = sis_5571_host_to_pci_close, .reset = sis_5571_host_to_pci_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5571_old.c b/src/chipset/sis_5571_old.c index f130ecd8a..422ed4bb8 100644 --- a/src/chipset/sis_5571_old.c +++ b/src/chipset/sis_5571_old.c @@ -765,7 +765,7 @@ const device_t sis_5571_device = { .init = sis_5571_init, .close = sis_5571_close, .reset = sis_5571_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5572_usb.c b/src/chipset/sis_5572_usb.c index 250c32587..bc7dc7d38 100644 --- a/src/chipset/sis_5572_usb.c +++ b/src/chipset/sis_5572_usb.c @@ -288,7 +288,7 @@ const device_t sis_5572_usb_device = { .init = sis_5572_usb_init, .close = sis_5572_usb_close, .reset = sis_5572_usb_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -302,7 +302,7 @@ const device_t sis_5582_usb_device = { .init = sis_5572_usb_init, .close = sis_5572_usb_close, .reset = sis_5572_usb_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -316,7 +316,7 @@ const device_t sis_5595_usb_device = { .init = sis_5572_usb_init, .close = sis_5572_usb_close, .reset = sis_5572_usb_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5581.c b/src/chipset/sis_5581.c index e2308c2d9..998ac5350 100644 --- a/src/chipset/sis_5581.c +++ b/src/chipset/sis_5581.c @@ -177,7 +177,7 @@ const device_t sis_5581_device = { .init = sis_5581_init, .close = sis_5581_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5581_h2p.c b/src/chipset/sis_5581_h2p.c index 30bd70bfe..d01e9dd28 100644 --- a/src/chipset/sis_5581_h2p.c +++ b/src/chipset/sis_5581_h2p.c @@ -545,7 +545,7 @@ const device_t sis_5581_h2p_device = { .init = sis_5581_host_to_pci_init, .close = sis_5581_host_to_pci_close, .reset = sis_5581_host_to_pci_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5591.c b/src/chipset/sis_5591.c index 969fcb8dd..3cb11cb5b 100644 --- a/src/chipset/sis_5591.c +++ b/src/chipset/sis_5591.c @@ -189,7 +189,7 @@ const device_t sis_5591_1997_device = { .init = sis_5591_init, .close = sis_5591_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -203,7 +203,7 @@ const device_t sis_5591_device = { .init = sis_5591_init, .close = sis_5591_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5591_h2p.c b/src/chipset/sis_5591_h2p.c index 8fcbeeb6f..048e7deea 100644 --- a/src/chipset/sis_5591_h2p.c +++ b/src/chipset/sis_5591_h2p.c @@ -486,7 +486,7 @@ const device_t sis_5591_h2p_device = { .init = sis_5591_host_to_pci_init, .close = sis_5591_host_to_pci_close, .reset = sis_5591_host_to_pci_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5595_pmu.c b/src/chipset/sis_5595_pmu.c index de351ad7c..2f5aa10b1 100644 --- a/src/chipset/sis_5595_pmu.c +++ b/src/chipset/sis_5595_pmu.c @@ -433,7 +433,7 @@ const device_t sis_5595_1997_pmu_device = { .init = sis_5595_pmu_init, .close = sis_5595_pmu_close, .reset = sis_5595_pmu_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -447,7 +447,7 @@ const device_t sis_5595_pmu_device = { .init = sis_5595_pmu_init, .close = sis_5595_pmu_close, .reset = sis_5595_pmu_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_55xx.c b/src/chipset/sis_55xx.c index 2cad21f22..1cb0744eb 100644 --- a/src/chipset/sis_55xx.c +++ b/src/chipset/sis_55xx.c @@ -89,7 +89,7 @@ const device_t sis_55xx_common_device = { .init = sis_55xx_common_init, .close = sis_55xx_common_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5600.c b/src/chipset/sis_5600.c index ed7384740..1ed7f9ad0 100644 --- a/src/chipset/sis_5600.c +++ b/src/chipset/sis_5600.c @@ -189,7 +189,7 @@ const device_t sis_5600_1997_device = { .init = sis_5600_init, .close = sis_5600_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -203,7 +203,7 @@ const device_t sis_5600_device = { .init = sis_5600_init, .close = sis_5600_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_5600_h2p.c b/src/chipset/sis_5600_h2p.c index f6ee926da..a15c6fff5 100644 --- a/src/chipset/sis_5600_h2p.c +++ b/src/chipset/sis_5600_h2p.c @@ -427,7 +427,7 @@ const device_t sis_5600_h2p_device = { .init = sis_5600_host_to_pci_init, .close = sis_5600_host_to_pci_close, .reset = sis_5600_host_to_pci_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_85c310.c b/src/chipset/sis_85c310.c index 296307fe1..d62cc3b24 100644 --- a/src/chipset/sis_85c310.c +++ b/src/chipset/sis_85c310.c @@ -146,7 +146,7 @@ const device_t rabbit_device = { .init = rabbit_init, .close = rabbit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index 3c3d5bd8c..5ba315822 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -702,7 +702,7 @@ const device_t sis_85c496_device = { .init = sis_85c496_init, .close = sis_85c496_close, .reset = sis_85c496_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -716,7 +716,7 @@ const device_t sis_85c496_ls486e_device = { .init = sis_85c496_init, .close = sis_85c496_close, .reset = sis_85c496_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index f80ecf99e..1f98ee8a6 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -403,7 +403,7 @@ const device_t sis_85c401_device = { .init = sis_85c4xx_init, .close = sis_85c4xx_close, .reset = sis_85c4xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -417,7 +417,7 @@ const device_t sis_85c460_device = { .init = sis_85c4xx_init, .close = sis_85c4xx_close, .reset = sis_85c4xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -432,7 +432,7 @@ const device_t sis_85c461_device = { .init = sis_85c4xx_init, .close = sis_85c4xx_close, .reset = sis_85c4xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -446,7 +446,7 @@ const device_t sis_85c471_device = { .init = sis_85c4xx_init, .close = sis_85c4xx_close, .reset = sis_85c4xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 2286105ce..192ae3767 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -684,7 +684,7 @@ const device_t sis_85c50x_device = { .init = sis_85c50x_init, .close = sis_85c50x_close, .reset = sis_85c50x_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -698,7 +698,7 @@ const device_t sis_550x_85c503_device = { .init = sis_85c50x_init, .close = sis_85c50x_close, .reset = sis_85c50x_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -712,7 +712,7 @@ const device_t sis_85c50x_5503_device = { .init = sis_85c50x_init, .close = sis_85c50x_close, .reset = sis_85c50x_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -726,7 +726,7 @@ const device_t sis_550x_device = { .init = sis_85c50x_init, .close = sis_85c50x_close, .reset = sis_85c50x_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index dbe39ec5c..3bb3a7c2a 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -1096,7 +1096,7 @@ const device_t stpc_client_device = { .init = stpc_init, .close = stpc_close, .reset = stpc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1110,7 +1110,7 @@ const device_t stpc_consumer2_device = { .init = stpc_init, .close = stpc_close, .reset = stpc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1124,7 +1124,7 @@ const device_t stpc_elite_device = { .init = stpc_init, .close = stpc_close, .reset = stpc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1138,7 +1138,7 @@ const device_t stpc_atlas_device = { .init = stpc_init, .close = stpc_close, .reset = stpc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1153,7 +1153,7 @@ const device_t stpc_serial_device = { .init = stpc_serial_init, .close = stpc_serial_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1167,7 +1167,7 @@ const device_t stpc_lpt_device = { .init = stpc_lpt_init, .close = stpc_lpt_close, .reset = stpc_lpt_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index 4242062c6..30b0ecb71 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -431,7 +431,7 @@ const device_t umc_8886f_device = { .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -445,7 +445,7 @@ const device_t umc_8886af_device = { .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -459,7 +459,7 @@ const device_t umc_8886bf_device = { .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/umc_8890.c b/src/chipset/umc_8890.c index 7de2ca1d0..37862e2fc 100644 --- a/src/chipset/umc_8890.c +++ b/src/chipset/umc_8890.c @@ -234,7 +234,7 @@ const device_t umc_8890_device = { .init = umc_8890_init, .close = umc_8890_close, .reset = umc_8890_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index c1f359f26..98bdfc82c 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -477,7 +477,7 @@ const device_t umc_hb4_device = { .init = hb4_init, .close = hb4_close, .reset = hb4_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index 20e2c7f74..fa96c4927 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -793,7 +793,7 @@ const device_t via_vpx_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -807,7 +807,7 @@ const device_t amd640_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -821,7 +821,7 @@ const device_t via_vp3_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -835,7 +835,7 @@ const device_t via_mvp3_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -849,7 +849,7 @@ const device_t via_apro_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -863,7 +863,7 @@ const device_t via_apro133_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -877,7 +877,7 @@ const device_t via_apro133a_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -891,7 +891,7 @@ const device_t via_vt8601_device = { .init = via_apollo_init, .close = via_apollo_close, .reset = via_apollo_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 1f153092b..3a6e6fc5c 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -1721,7 +1721,7 @@ const device_t via_vt82c586b_device = { .init = pipc_init, .close = pipc_close, .reset = pipc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1735,7 +1735,7 @@ const device_t via_vt82c596a_device = { .init = pipc_init, .close = pipc_close, .reset = pipc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1749,7 +1749,7 @@ const device_t via_vt82c596b_device = { .init = pipc_init, .close = pipc_close, .reset = pipc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1763,7 +1763,7 @@ const device_t via_vt82c686a_device = { .init = pipc_init, .close = pipc_close, .reset = pipc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1777,7 +1777,7 @@ const device_t via_vt82c686b_device = { .init = pipc_init, .close = pipc_close, .reset = pipc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1791,7 +1791,7 @@ const device_t via_vt8231_device = { .init = pipc_init, .close = pipc_close, .reset = pipc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/via_vt82c49x.c b/src/chipset/via_vt82c49x.c index de55f7060..f36dad2e7 100644 --- a/src/chipset/via_vt82c49x.c +++ b/src/chipset/via_vt82c49x.c @@ -375,7 +375,7 @@ const device_t via_vt82c49x_device = { .init = vt82c49x_init, .close = vt82c49x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -389,7 +389,7 @@ const device_t via_vt82c49x_pci_device = { .init = vt82c49x_init, .close = vt82c49x_close, .reset = vt82c49x_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -403,7 +403,7 @@ const device_t via_vt82c49x_ide_device = { .init = vt82c49x_init, .close = vt82c49x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -417,7 +417,7 @@ const device_t via_vt82c49x_pci_ide_device = { .init = vt82c49x_init, .close = vt82c49x_close, .reset = vt82c49x_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/via_vt82c505.c b/src/chipset/via_vt82c505.c index 34efbead9..8cb6c67a0 100644 --- a/src/chipset/via_vt82c505.c +++ b/src/chipset/via_vt82c505.c @@ -232,7 +232,7 @@ const device_t via_vt82c505_device = { .init = vt82c505_init, .close = vt82c505_close, .reset = vt82c505_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 00adcc2a4..38a6bdfb9 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -207,7 +207,7 @@ const device_t vl82c480_device = { .init = vl82c480_init, .close = vl82c480_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -221,7 +221,7 @@ const device_t vl82c486_device = { .init = vl82c480_init, .close = vl82c480_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index df8558b05..6de921af1 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -1022,7 +1022,7 @@ const device_t wd76c10_device = { .init = wd76c10_init, .close = wd76c10_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/ddma.c b/src/ddma.c index 7cbe2831e..0ca1bb879 100644 --- a/src/ddma.c +++ b/src/ddma.c @@ -193,7 +193,7 @@ const device_t ddma_device = { .init = ddma_init, .close = ddma_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/bugger.c b/src/device/bugger.c index c2678d66a..56cac91bc 100644 --- a/src/device/bugger.c +++ b/src/device/bugger.c @@ -351,7 +351,7 @@ const device_t bugger_device = { .init = bug_init, .close = bug_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/cassette.c b/src/device/cassette.c index a239c6393..608de7463 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -722,7 +722,7 @@ const device_t cassette_device = { .init = cassette_init, .close = cassette_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index 6ba1083d9..23763ebb8 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -325,7 +325,7 @@ const device_t gl518sm_2c_device = { .init = gl518sm_init, .close = gl518sm_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -340,7 +340,7 @@ const device_t gl518sm_2d_device = { .init = gl518sm_init, .close = gl518sm_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -355,7 +355,7 @@ const device_t gl520sm_2c_device = { .init = gl518sm_init, .close = gl518sm_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -371,7 +371,7 @@ const device_t gl520sm_2d_device = { .init = gl518sm_init, .close = gl518sm_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index 14b638365..831d16ded 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -243,7 +243,7 @@ const device_t lm75_1_4a_device = { .init = lm75_init, .close = lm75_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -259,7 +259,7 @@ const device_t lm75_w83781d_device = { .init = lm75_init, .close = lm75_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index f3003db26..3219e87e6 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -857,7 +857,7 @@ const device_t lm78_device = { .init = lm78_init, .close = lm78_close, .reset = lm78_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -872,7 +872,7 @@ const device_t w83781d_device = { .init = lm78_init, .close = lm78_close, .reset = lm78_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -887,7 +887,7 @@ const device_t w83781d_p5a_device = { .init = lm78_init, .close = lm78_close, .reset = lm78_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -903,7 +903,7 @@ const device_t as99127f_device = { .init = lm78_init, .close = lm78_close, .reset = lm78_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -918,7 +918,7 @@ const device_t as99127f_rev2_device = { .init = lm78_init, .close = lm78_close, .reset = lm78_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -933,7 +933,7 @@ const device_t w83782d_device = { .init = lm78_init, .close = lm78_close, .reset = lm78_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/hwm_vt82c686.c b/src/device/hwm_vt82c686.c index b6a0dddda..7d764bcb9 100644 --- a/src/device/hwm_vt82c686.c +++ b/src/device/hwm_vt82c686.c @@ -222,7 +222,7 @@ const device_t via_vt82c686_hwm_device = { .init = vt82c686_init, .close = vt82c686_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/ibm_5161.c b/src/device/ibm_5161.c index 762a379a1..456227676 100644 --- a/src/device/ibm_5161.c +++ b/src/device/ibm_5161.c @@ -116,7 +116,7 @@ const device_t ibm_5161_device = { .init = ibm_5161_init, .close = ibm_5161_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/isamem.c b/src/device/isamem.c index f63a5a5a1..5d3164757 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -895,7 +895,7 @@ static const device_t ibmxt_32k_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ibmxt_32k_config @@ -943,7 +943,7 @@ static const device_t ibmxt_64k_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ibmxt_64k_config @@ -991,7 +991,7 @@ static const device_t ibmxt_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ibmxt_config @@ -1039,7 +1039,7 @@ static const device_t genericxt_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = genericxt_config @@ -1087,7 +1087,7 @@ static const device_t msramcard_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = msramcard_config @@ -1135,7 +1135,7 @@ static const device_t mssystemcard_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = mssystemcard_config @@ -1149,7 +1149,7 @@ static const device_t ibmat_128k_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1197,7 +1197,7 @@ static const device_t ibmat_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ibmat_config @@ -1245,7 +1245,7 @@ static const device_t genericat_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = genericat_config @@ -1293,7 +1293,7 @@ static const device_t p5pak_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = p5pak_config @@ -1341,7 +1341,7 @@ static const device_t a6pak_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = a6pak_config @@ -1392,7 +1392,7 @@ static const device_t ems5150_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ems5150_config @@ -1534,7 +1534,7 @@ static const device_t ev159_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ev159_config @@ -1629,7 +1629,7 @@ static const device_t ev165a_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ev165a_config @@ -1693,7 +1693,7 @@ static const device_t brxt_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = brxt_config @@ -1799,7 +1799,7 @@ static const device_t brat_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = brat_config @@ -1865,7 +1865,7 @@ static const device_t lotech_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = lotech_config @@ -1934,7 +1934,7 @@ static const device_t rampage_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = rampage_config @@ -2033,7 +2033,7 @@ static const device_t iab_device = { .init = isamem_init, .close = isamem_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = iab_config diff --git a/src/device/isapnp.c b/src/device/isapnp.c index f69c69612..479b6b9b2 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -1231,7 +1231,7 @@ static const device_t isapnp_device = { .init = isapnp_init, .close = isapnp_close, .reset = NULL, - { .available = 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 74be59017..aef3b2cc6 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2417,7 +2417,7 @@ const device_t keyboard_at_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2431,7 +2431,7 @@ const device_t keyboard_at_siemens_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2445,7 +2445,7 @@ const device_t keyboard_at_ami_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2459,7 +2459,7 @@ const device_t keyboard_at_tg_ami_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2473,7 +2473,7 @@ const device_t keyboard_at_toshiba_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2487,7 +2487,7 @@ const device_t keyboard_at_olivetti_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2501,7 +2501,7 @@ const device_t keyboard_at_ncr_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2515,7 +2515,7 @@ const device_t keyboard_at_compaq_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2529,7 +2529,7 @@ const device_t keyboard_ps2_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2543,7 +2543,7 @@ const device_t keyboard_ps2_ps1_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2557,7 +2557,7 @@ const device_t keyboard_ps2_ps1_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2571,7 +2571,7 @@ const device_t keyboard_ps2_xi8088_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2585,7 +2585,7 @@ const device_t keyboard_ps2_ami_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2599,7 +2599,7 @@ const device_t keyboard_ps2_holtek_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2613,7 +2613,7 @@ const device_t keyboard_ps2_phoenix_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2627,7 +2627,7 @@ const device_t keyboard_ps2_tg_ami_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2641,7 +2641,7 @@ const device_t keyboard_ps2_mca_1_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2655,7 +2655,7 @@ const device_t keyboard_ps2_mca_2_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2669,7 +2669,7 @@ const device_t keyboard_ps2_quadtel_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2683,7 +2683,7 @@ const device_t keyboard_ps2_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2697,7 +2697,7 @@ const device_t keyboard_ps2_ami_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2711,7 +2711,7 @@ const device_t keyboard_ps2_ali_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2725,7 +2725,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2739,7 +2739,7 @@ const device_t keyboard_ps2_tg_ami_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2753,7 +2753,7 @@ const device_t keyboard_ps2_acer_pci_device = { .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index b90f4a77a..c614bad8c 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -1188,7 +1188,7 @@ const device_t keyboard_pc_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1202,7 +1202,7 @@ const device_t keyboard_pc82_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1216,7 +1216,7 @@ const device_t keyboard_pravetz_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1230,7 +1230,7 @@ const device_t keyboard_xt_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1244,7 +1244,7 @@ const device_t keyboard_xt86_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1258,7 +1258,7 @@ const device_t keyboard_xt_compaq_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1272,7 +1272,7 @@ const device_t keyboard_tandy_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1286,7 +1286,7 @@ const device_t keyboard_xt_t1x00_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1301,7 +1301,7 @@ const device_t keyboard_xt_lxt3_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1316,7 +1316,7 @@ const device_t keyboard_xt_olivetti_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1330,7 +1330,7 @@ const device_t keyboard_xt_zenith_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1344,7 +1344,7 @@ const device_t keyboard_xt_hyundai_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1358,7 +1358,7 @@ const device_t keyboard_xtclone_device = { .init = kbd_init, .close = kbd_close, .reset = kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/mouse_bus.c b/src/device/mouse_bus.c index fdd58b404..9c0d8b02e 100644 --- a/src/device/mouse_bus.c +++ b/src/device/mouse_bus.c @@ -812,7 +812,7 @@ const device_t mouse_logibus_device = { .init = bm_init, .close = bm_close, .reset = NULL, - { .poll = bm_poll }, + .poll = bm_poll, .speed_changed = NULL, .force_redraw = NULL, .config = lt_config @@ -826,7 +826,7 @@ const device_t mouse_logibus_onboard_device = { .init = bm_init, .close = bm_close, .reset = NULL, - { .poll = bm_poll }, + .poll = bm_poll, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -840,7 +840,7 @@ const device_t mouse_msinport_device = { .init = bm_init, .close = bm_close, .reset = NULL, - { .poll = bm_poll }, + .poll = bm_poll, .speed_changed = NULL, .force_redraw = NULL, .config = ms_config diff --git a/src/device/mouse_microtouch_touchscreen.c b/src/device/mouse_microtouch_touchscreen.c index 442b25b91..c6bef89dc 100644 --- a/src/device/mouse_microtouch_touchscreen.c +++ b/src/device/mouse_microtouch_touchscreen.c @@ -599,7 +599,7 @@ const device_t mouse_mtouch_device = { .init = mtouch_init, .close = mtouch_close, .reset = NULL, - { .poll = mtouch_poll }, + .poll = mtouch_poll, .speed_changed = NULL, .force_redraw = NULL, .config = mtouch_config diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index e5f9dd410..53af97b78 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -396,7 +396,7 @@ const device_t mouse_ps2_device = { .init = mouse_ps2_init, .close = ps2_close, .reset = NULL, - { .poll = ps2_poll }, + .poll = ps2_poll, .speed_changed = NULL, .force_redraw = NULL, .config = ps2_config diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index fa3190536..99d08cd37 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -1061,7 +1061,7 @@ const device_t mouse_mssystems_device = { .init = sermouse_init, .close = sermouse_close, .reset = NULL, - { .poll = sermouse_poll }, + .poll = sermouse_poll, .speed_changed = sermouse_speed_changed, .force_redraw = NULL, .config = msssermouse_config @@ -1075,7 +1075,7 @@ const device_t mouse_msserial_device = { .init = sermouse_init, .close = sermouse_close, .reset = NULL, - { .poll = sermouse_poll }, + .poll = sermouse_poll, .speed_changed = sermouse_speed_changed, .force_redraw = NULL, .config = mssermouse_config @@ -1089,7 +1089,7 @@ const device_t mouse_ltserial_device = { .init = sermouse_init, .close = sermouse_close, .reset = NULL, - { .poll = sermouse_poll }, + .poll = sermouse_poll, .speed_changed = sermouse_speed_changed, .force_redraw = NULL, .config = ltsermouse_config diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c index d299d8bab..d74e58411 100644 --- a/src/device/mouse_wacom_tablet.c +++ b/src/device/mouse_wacom_tablet.c @@ -720,7 +720,7 @@ const device_t mouse_wacom_device = { .init = wacom_init, .close = wacom_close, .reset = NULL, - { .poll = wacom_poll }, + .poll = wacom_poll, .speed_changed = wacom_speed_changed, .force_redraw = NULL, .config = wacom_config @@ -730,11 +730,11 @@ const device_t mouse_wacom_artpad_device = { .name = "Wacom ArtPad", .internal_name = "wacom_serial_artpad", .flags = DEVICE_COM, - .local = (uintptr_t)&artpad_id, + .local = (uintptr_t) &artpad_id, .init = wacom_init, .close = wacom_close, .reset = NULL, - { .poll = wacom_poll }, + .poll = wacom_poll, .speed_changed = wacom_speed_changed, .force_redraw = NULL, .config = wacom_config diff --git a/src/device/nec_mate_unk.c b/src/device/nec_mate_unk.c index 165962f30..3244733c9 100644 --- a/src/device/nec_mate_unk.c +++ b/src/device/nec_mate_unk.c @@ -68,7 +68,7 @@ const device_t nec_mate_unk_device = { .init = nec_mate_unk_init, .close = nec_mate_unk_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index 4730b6bb4..737b4104d 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -116,7 +116,7 @@ const device_t novell_keycard_device = { .init = novell_cardkey_init, .close = novell_cardkey_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = keycard_config diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index c1f551162..4321bf433 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -542,7 +542,7 @@ const device_t dec21150_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -557,7 +557,7 @@ const device_t ali5243_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -572,7 +572,7 @@ const device_t ali5247_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -586,7 +586,7 @@ const device_t i440lx_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -600,7 +600,7 @@ const device_t i440bx_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -614,7 +614,7 @@ const device_t i440gx_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -628,7 +628,7 @@ const device_t via_vp3_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -642,7 +642,7 @@ const device_t via_mvp3_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -656,7 +656,7 @@ const device_t via_apro_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -670,7 +670,7 @@ const device_t via_vt8601_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -684,7 +684,7 @@ const device_t sis_5xxx_agp_device = { .init = pci_bridge_init, .close = NULL, .reset = pci_bridge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index a3c891c90..6032a59dc 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -130,7 +130,7 @@ const device_t phoenix_486_jumper_device = { .init = phoenix_486_jumper_init, .close = phoenix_486_jumper_close, .reset = phoenix_486_jumper_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -144,7 +144,7 @@ const device_t phoenix_486_jumper_pci_device = { .init = phoenix_486_jumper_init, .close = phoenix_486_jumper_close, .reset = phoenix_486_jumper_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/postcard.c b/src/device/postcard.c index dbae3232a..9e2c629c1 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -187,7 +187,7 @@ const device_t postcard_device = { .init = postcard_init, .close = postcard_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/serial.c b/src/device/serial.c index dcaff0f7f..1e2618449 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -996,7 +996,7 @@ const device_t ns8250_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1010,7 +1010,7 @@ const device_t ns8250_pcjr_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1024,7 +1024,7 @@ const device_t ns16450_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1038,7 +1038,7 @@ const device_t ns16550_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1052,7 +1052,7 @@ const device_t ns16650_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1066,7 +1066,7 @@ const device_t ns16750_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1080,7 +1080,7 @@ const device_t ns16850_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL @@ -1094,7 +1094,7 @@ const device_t ns16950_device = { .init = serial_init, .close = serial_close, .reset = serial_reset, - { .available = NULL }, + .available = NULL, .speed_changed = serial_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index ed5abe618..445b67d04 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -370,13 +370,13 @@ static const device_config_t serial_passthrough_config[] = { // clang-format on const device_t serial_passthrough_device = { - .name = "Serial Passthrough Device", - .flags = 0, - .local = 0, - .init = serial_passthrough_dev_init, - .close = serial_passthrough_dev_close, - .reset = NULL, - { .poll = NULL }, + .name = "Serial Passthrough Device", + .flags = 0, + .local = 0, + .init = serial_passthrough_dev_init, + .close = serial_passthrough_dev_close, + .reset = NULL, + .poll = NULL, .speed_changed = serial_passthrough_speed_changed, .force_redraw = NULL, .config = serial_passthrough_config diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index 349de470d..de487ef73 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -307,7 +307,7 @@ const device_t ali7101_smbus_device = { .init = smbus_ali7101_init, .close = smbus_ali7101_close, .reset = smbus_ali7101_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/smbus_piix4.c b/src/device/smbus_piix4.c index 6f2b1632e..d72712cc6 100644 --- a/src/device/smbus_piix4.c +++ b/src/device/smbus_piix4.c @@ -392,7 +392,7 @@ const device_t piix4_smbus_device = { .init = smbus_piix4_init, .close = smbus_piix4_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -406,7 +406,7 @@ const device_t via_smbus_device = { .init = smbus_piix4_init, .close = smbus_piix4_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/smbus_sis5595.c b/src/device/smbus_sis5595.c index 191e7a6a5..e7cffc577 100644 --- a/src/device/smbus_sis5595.c +++ b/src/device/smbus_sis5595.c @@ -379,7 +379,7 @@ const device_t sis5595_smbus_device = { .init = smbus_sis5595_init, .close = smbus_sis5595_close, .reset = smbus_sis5595_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/unittester.c b/src/device/unittester.c index 614438fcb..5f0fa5712 100644 --- a/src/device/unittester.c +++ b/src/device/unittester.c @@ -115,12 +115,16 @@ static struct unittester_state unittester_defaults = { }; static const device_config_t unittester_config[] = { - { .name = "exit_enabled", - .description = "Enable 0x04 \"Exit 86Box\" command", - .type = CONFIG_BINARY, - .default_int = 1, - .default_string = "" }, - { .type = CONFIG_END } +// clang-format off + { + .name = "exit_enabled", + .description = "Enable 0x04 \"Exit 86Box\" command", + .type = CONFIG_BINARY, + .default_int = 1, + .default_string = "" + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on }; /* Kept separate, as we will be reusing this object */ @@ -628,7 +632,7 @@ const device_t unittester_device = { .init = unittester_init, .close = unittester_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = unittester_config, diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index 82314e6db..d9dc02da0 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -990,7 +990,7 @@ const device_t esdi_at_wd1007vse1_device = { .init = wd1007vse1_init, .close = wd1007vse1_close, .reset = NULL, - { .available = wd1007vse1_available }, + .available = wd1007vse1_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 539684b81..83d2dc3b7 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1342,7 +1342,7 @@ const device_t esdi_ps2_device = { .init = esdi_init, .close = esdi_close, .reset = NULL, - { .available = esdi_available }, + .available = esdi_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 3af561989..49d23daee 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3269,7 +3269,7 @@ const device_t ide_isa_device = { .init = ide_init, .close = ide_close, .reset = ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3283,7 +3283,7 @@ const device_t ide_isa_2ch_device = { .init = ide_init, .close = ide_close, .reset = ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3297,7 +3297,7 @@ const device_t ide_vlb_device = { .init = ide_init, .close = ide_close, .reset = ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3311,7 +3311,7 @@ const device_t ide_vlb_2ch_device = { .init = ide_init, .close = ide_close, .reset = ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3325,7 +3325,7 @@ const device_t ide_pci_device = { .init = ide_init, .close = ide_close, .reset = ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3339,7 +3339,7 @@ const device_t ide_pci_2ch_device = { .init = ide_init, .close = ide_close, .reset = ide_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3353,7 +3353,7 @@ const device_t mcide_device = { .init = mcide_init, .close = mcide_close, .reset = mcide_reset, - { .available = mcide_available }, + .available = mcide_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3422,7 +3422,7 @@ const device_t ide_ter_device = { .init = ide_ter_init, .close = ide_ter_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ide_ter_config @@ -3436,7 +3436,7 @@ const device_t ide_ter_pnp_device = { .init = ide_ter_init, .close = ide_ter_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -3450,7 +3450,7 @@ const device_t ide_qua_device = { .init = ide_qua_init, .close = ide_qua_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ide_qua_config @@ -3464,7 +3464,7 @@ const device_t ide_qua_pnp_device = { .init = ide_qua_init, .close = ide_qua_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_ali5213.c b/src/disk/hdc_ide_ali5213.c index 8ff3d392c..67f959e1a 100644 --- a/src/disk/hdc_ide_ali5213.c +++ b/src/disk/hdc_ide_ali5213.c @@ -246,7 +246,7 @@ const device_t ide_ali1489_device = { .init = ali5213_init, .close = ali5213_close, .reset = ali5213_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -260,7 +260,7 @@ const device_t ide_ali5213_device = { .init = ali5213_init, .close = ali5213_close, .reset = ali5213_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index 3e77730a2..9c0178a47 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -563,7 +563,7 @@ const device_t ide_cmd640_vlb_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -577,7 +577,7 @@ const device_t ide_cmd640_vlb_178_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -591,7 +591,7 @@ const device_t ide_cmd640_vlb_pri_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -605,7 +605,7 @@ const device_t ide_cmd640_vlb_pri_178_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -619,7 +619,7 @@ const device_t ide_cmd640_vlb_sec_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -633,7 +633,7 @@ const device_t ide_cmd640_vlb_sec_178_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -647,7 +647,7 @@ const device_t ide_cmd640_pci_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -661,7 +661,7 @@ const device_t ide_cmd640_pci_legacy_only_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -675,7 +675,7 @@ const device_t ide_cmd640_pci_single_channel_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -689,7 +689,7 @@ const device_t ide_cmd640_pci_single_channel_sec_device = { .init = cmd640_init, .close = cmd640_close, .reset = cmd640_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index 8367b9a41..b79f84f03 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -431,7 +431,7 @@ const device_t ide_cmd646_device = { .init = cmd646_init, .close = cmd646_close, .reset = cmd646_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -445,7 +445,7 @@ const device_t ide_cmd646_legacy_only_device = { .init = cmd646_init, .close = cmd646_close, .reset = cmd646_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -459,7 +459,7 @@ const device_t ide_cmd646_single_channel_device = { .init = cmd646_init, .close = cmd646_close, .reset = cmd646_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_opti611.c b/src/disk/hdc_ide_opti611.c index 480331201..67cdfc779 100644 --- a/src/disk/hdc_ide_opti611.c +++ b/src/disk/hdc_ide_opti611.c @@ -341,7 +341,7 @@ const device_t ide_opti611_vlb_device = { .init = opti611_init, .close = opti611_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -355,7 +355,7 @@ const device_t ide_opti611_vlb_sec_device = { .init = opti611_init, .close = opti611_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 3b8da3f2e..ec4c7228c 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -611,7 +611,7 @@ const device_t sff8038i_device = { .init = sff_init, .close = sff_close, .reset = sff_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_um8673f.c b/src/disk/hdc_ide_um8673f.c index bc046dd26..b40595750 100644 --- a/src/disk/hdc_ide_um8673f.c +++ b/src/disk/hdc_ide_um8673f.c @@ -191,7 +191,7 @@ const device_t ide_um8886af_device = { .init = um8673f_init, .close = um8673f_close, .reset = um8673f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -205,7 +205,7 @@ const device_t ide_um8673f_device = { .init = um8673f_init, .close = um8673f_close, .reset = um8673f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c index 608d7a8a7..897a26593 100644 --- a/src/disk/hdc_ide_w83769f.c +++ b/src/disk/hdc_ide_w83769f.c @@ -410,7 +410,7 @@ const device_t ide_w83769f_vlb_device = { .init = w83769f_init, .close = w83769f_close, .reset = w83769f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -424,7 +424,7 @@ const device_t ide_w83769f_vlb_34_device = { .init = w83769f_init, .close = w83769f_close, .reset = w83769f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -438,7 +438,7 @@ const device_t ide_w83769f_pci_device = { .init = w83769f_init, .close = w83769f_close, .reset = w83769f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -452,7 +452,7 @@ const device_t ide_w83769f_pci_34_device = { .init = w83769f_init, .close = w83769f_close, .reset = w83769f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -466,9 +466,8 @@ const device_t ide_w83769f_pci_single_channel_device = { .init = w83769f_init, .close = w83769f_close, .reset = w83769f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL }; - diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index 8cc5fe20a..abd379646 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -801,7 +801,7 @@ const device_t st506_at_wd1003_device = { .init = mfm_init, .close = mfm_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 5d310e96b..d950fbe34 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -2258,7 +2258,7 @@ const device_t st506_xt_xebec_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = xebec_available }, + .available = xebec_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2272,7 +2272,7 @@ const device_t st506_xt_wdxt_gen_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wdxt_available }, + .available = wdxt_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2286,7 +2286,7 @@ const device_t st506_xt_dtc5150x_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = dtc5150x_available }, + .available = dtc5150x_available, .speed_changed = NULL, .force_redraw = NULL, .config = dtc_config @@ -2300,7 +2300,7 @@ const device_t st506_xt_st11_m_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = st11_m_available }, + .available = st11_m_available, .speed_changed = NULL, .force_redraw = NULL, .config = st11_config @@ -2314,7 +2314,7 @@ const device_t st506_xt_st11_r_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = st11_r_available }, + .available = st11_r_available, .speed_changed = NULL, .force_redraw = NULL, .config = st11_config @@ -2328,7 +2328,7 @@ const device_t st506_xt_wd1002a_wx1_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wd1002a_wx1_available }, + .available = wd1002a_wx1_available, .speed_changed = NULL, .force_redraw = NULL, .config = wd_config @@ -2342,7 +2342,7 @@ const device_t st506_xt_wd1002a_wx1_nobios_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wd1002a_wx1_available }, + .available = wd1002a_wx1_available, .speed_changed = NULL, .force_redraw = NULL, .config = wd_nobios_config @@ -2356,7 +2356,7 @@ const device_t st506_xt_wd1002a_27x_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wd1002a_27x_available }, + .available = wd1002a_27x_available, .speed_changed = NULL, .force_redraw = NULL, .config = wd_rll_config @@ -2370,7 +2370,7 @@ const device_t st506_xt_wd1004a_wx1_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wd1004a_wx1_available }, + .available = wd1004a_wx1_available, .speed_changed = NULL, .force_redraw = NULL, .config = wd1004a_config @@ -2384,7 +2384,7 @@ const device_t st506_xt_wd1004_27x_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wd1004_27x_available }, + .available = wd1004_27x_available, .speed_changed = NULL, .force_redraw = NULL, .config = wd1004_rll_config @@ -2398,7 +2398,7 @@ const device_t st506_xt_wd1004a_27x_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = wd1004a_27x_available }, + .available = wd1004a_27x_available, .speed_changed = NULL, .force_redraw = NULL, .config = wd_rll_config @@ -2412,7 +2412,7 @@ const device_t st506_xt_victor_v86p_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = victor_v86p_available }, + .available = victor_v86p_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2426,7 +2426,7 @@ const device_t st506_xt_toshiba_t1200_device = { .init = st506_init, .close = st506_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 91bdd709d..1ddbd33e2 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1170,29 +1170,29 @@ static const device_config_t wdxt150_config[] = { }; const device_t xta_wdxt150_device = { - .name = "WDXT-150 XTA Fixed Disk Controller", + .name = "WDXT-150 XTA Fixed Disk Controller", .internal_name = "xta_wdxt150", - .flags = DEVICE_ISA, - .local = 0, - .init = xta_init, - .close = xta_close, - .reset = NULL, - { .available = NULL /*xta_available*/ }, + .flags = DEVICE_ISA, + .local = 0, + .init = xta_init, + .close = xta_close, + .reset = NULL, + .available = NULL /*xta_available*/, .speed_changed = NULL, - .force_redraw = NULL, - .config = wdxt150_config + .force_redraw = NULL, + .config = wdxt150_config }; const device_t xta_hd20_device = { - .name = "EuroPC HD20 Fixed Disk Controller", + .name = "EuroPC HD20 Fixed Disk Controller", .internal_name = "xta_hd20", - .flags = DEVICE_ISA, - .local = 1, - .init = xta_init, - .close = xta_close, - .reset = NULL, - { .available = NULL }, + .flags = DEVICE_ISA, + .local = 1, + .init = xta_init, + .close = xta_close, + .reset = NULL, + .available = NULL, .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index b324b4d32..623f68cb5 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -281,7 +281,7 @@ const device_t xtide_device = { .init = xtide_init, .close = xtide_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = xtide_config @@ -295,7 +295,7 @@ const device_t xtide_at_device = { .init = xtide_at_init, .close = xtide_at_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = xtide_at_config @@ -309,7 +309,7 @@ const device_t xtide_acculogic_device = { .init = xtide_acculogic_init, .close = xtide_close, .reset = NULL, - { .available = xtide_acculogic_available }, + .available = xtide_acculogic_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -323,7 +323,7 @@ const device_t xtide_at_ps2_device = { .init = xtide_at_ps2_init, .close = xtide_at_close, .reset = NULL, - { .available = xtide_at_ps2_available }, + .available = xtide_at_ps2_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/disk/lba_enhancer.c b/src/disk/lba_enhancer.c index 35c845c16..c7f3fd969 100644 --- a/src/disk/lba_enhancer.c +++ b/src/disk/lba_enhancer.c @@ -92,7 +92,7 @@ const device_t lba_enhancer_device = { .init = lba_enhancer_init, .close = lba_enhancer_close, .reset = NULL, - { .available = lba_enhancer_available }, + .available = lba_enhancer_available, .speed_changed = NULL, .force_redraw = NULL, .config = lba_enhancer_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 4cb2a8491..5c377f95f 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2371,7 +2371,7 @@ const device_t fdc_xt_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2385,7 +2385,7 @@ const device_t fdc_xt_sec_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2399,7 +2399,7 @@ const device_t fdc_xt_ter_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2413,7 +2413,7 @@ const device_t fdc_xt_qua_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2427,7 +2427,7 @@ const device_t fdc_xt_t1x00_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2441,7 +2441,7 @@ const device_t fdc_xt_amstrad_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2455,7 +2455,7 @@ const device_t fdc_xt_tandy_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2469,7 +2469,7 @@ const device_t fdc_xt_umc_um8398_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2483,7 +2483,7 @@ const device_t fdc_pcjr_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2497,7 +2497,7 @@ const device_t fdc_at_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2511,7 +2511,7 @@ const device_t fdc_at_sec_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2525,7 +2525,7 @@ const device_t fdc_at_ter_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2539,7 +2539,7 @@ const device_t fdc_at_qua_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2553,7 +2553,7 @@ const device_t fdc_at_actlow_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2567,7 +2567,7 @@ const device_t fdc_at_smc_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2581,7 +2581,7 @@ const device_t fdc_at_ali_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2595,7 +2595,7 @@ const device_t fdc_at_winbond_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2609,7 +2609,7 @@ const device_t fdc_at_nsc_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2623,7 +2623,7 @@ const device_t fdc_at_nsc_dp8473_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2638,7 +2638,7 @@ const device_t fdc_ps2_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2653,7 +2653,7 @@ const device_t fdc_ps2_mca_device = { .init = fdc_init, .close = fdc_close, .reset = fdc_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/floppy/fdc_magitronic.c b/src/floppy/fdc_magitronic.c index 306440b9c..09b766d6c 100644 --- a/src/floppy/fdc_magitronic.c +++ b/src/floppy/fdc_magitronic.c @@ -135,7 +135,7 @@ const device_t fdc_b215_device = { .init = b215_init, .close = b215_close, .reset = NULL, - { .available = b215_available }, + .available = b215_available, .speed_changed = NULL, .force_redraw = NULL, .config = b215_config diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c index 00b6d37f5..bb210fb44 100644 --- a/src/floppy/fdc_monster.c +++ b/src/floppy/fdc_monster.c @@ -286,7 +286,7 @@ const device_t fdc_monster_device = { .init = monster_fdc_init, .close = monster_fdc_close, .reset = NULL, - { .available = monster_fdc_available }, + .available = monster_fdc_available, .speed_changed = NULL, .force_redraw = NULL, .config = monster_fdc_config diff --git a/src/floppy/fdc_pii15xb.c b/src/floppy/fdc_pii15xb.c index 013d6d39b..6a8bbbd43 100644 --- a/src/floppy/fdc_pii15xb.c +++ b/src/floppy/fdc_pii15xb.c @@ -150,7 +150,7 @@ const device_t fdc_pii151b_device = { .init = pii_init, .close = pii_close, .reset = NULL, - { .available = pii_151b_available }, + .available = pii_151b_available, .speed_changed = NULL, .force_redraw = NULL, .config = pii_config @@ -164,7 +164,7 @@ const device_t fdc_pii158b_device = { .init = pii_init, .close = pii_close, .reset = NULL, - { .available = pii_158_available }, + .available = pii_158_available, .speed_changed = NULL, .force_redraw = NULL, .config = pii_config diff --git a/src/game/gameport.c b/src/game/gameport.c index ae2135a39..0b2a641bc 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -478,7 +478,7 @@ const device_t gameport_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -492,7 +492,7 @@ const device_t gameport_201_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -506,7 +506,7 @@ const device_t gameport_203_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -520,7 +520,7 @@ const device_t gameport_205_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -534,7 +534,7 @@ const device_t gameport_207_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -548,7 +548,7 @@ const device_t gameport_208_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -562,7 +562,7 @@ const device_t gameport_209_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -576,7 +576,7 @@ const device_t gameport_20b_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -590,7 +590,7 @@ const device_t gameport_20d_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -604,7 +604,7 @@ const device_t gameport_20f_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -658,7 +658,7 @@ const device_t gameport_tm_acm_device = { .init = tmacm_init, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = tmacm_config @@ -672,7 +672,7 @@ const device_t gameport_pnp_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -686,7 +686,7 @@ const device_t gameport_pnp_1io_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -700,7 +700,7 @@ const device_t gameport_pnp_6io_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -714,7 +714,7 @@ const device_t gameport_sio_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -728,7 +728,7 @@ const device_t gameport_sio_1io_device = { .init = gameport_init, .close = gameport_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/ioapic.c b/src/ioapic.c index c3939f249..b5ca4c7a7 100644 --- a/src/ioapic.c +++ b/src/ioapic.c @@ -122,7 +122,7 @@ const device_t ioapic_device = { .init = ioapic_init, .close = ioapic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 530362b89..891f02e84 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -726,7 +726,7 @@ const device_t vid_1512_device = { .init = NULL, .close = vid_close_1512, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_change_1512, .force_redraw = NULL, .config = vid_1512_config @@ -906,7 +906,7 @@ const device_t vid_1640_device = { .init = NULL, .close = vid_close_1640, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed_1640, .force_redraw = NULL, .config = vid_1640_config @@ -1831,7 +1831,7 @@ const device_t vid_200_device = { .init = NULL, .close = vid_close_200, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed_200, .force_redraw = NULL, .config = vid_200_config @@ -1931,7 +1931,7 @@ const device_t vid_ppc512_device = { .init = NULL, .close = vid_close_200, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed_200, .force_redraw = NULL, .config = vid_ppc512_config @@ -1965,7 +1965,7 @@ const device_t vid_pc2086_device = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = vid_pc2086_config @@ -1999,7 +1999,7 @@ const device_t vid_pc3086_device = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = vid_pc3086_config diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 0ac541e90..3b9462f90 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -714,7 +714,7 @@ const device_t compaq_plasma_device = { .init = compaq_plasma_init, .close = compaq_plasma_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = compaq_plasma_speed_changed, .force_redraw = NULL, .config = compaq_plasma_config diff --git a/src/machine/m_at_grid.c b/src/machine/m_at_grid.c index 2fc757129..443607382 100644 --- a/src/machine/m_at_grid.c +++ b/src/machine/m_at_grid.c @@ -324,7 +324,7 @@ const device_t grid_device = { .init = grid_init, .close = grid_close, .reset = grid_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index 50c9ec05a..80af959af 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -711,7 +711,7 @@ const device_t t3100e_device = { .init = t3100e_init, .close = t3100e_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = t3100e_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index 42034e2f6..b98a1f51e 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -703,7 +703,7 @@ const device_t europc_device = { .init = europc_boot, .close = europc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = europc_config diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 16020826d..847053bdb 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -1513,7 +1513,7 @@ const device_t pcjr_device = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = speed_changed, .force_redraw = NULL, .config = pcjr_config diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 3c9f1819f..8b2a096c7 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -287,7 +287,7 @@ const device_t ps1_2011_device = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = &ps1_2011_config[0] diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index e3f6428a7..06c7a2c95 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -1386,7 +1386,7 @@ const device_t ps1_hdc_device = { .init = ps1_hdc_init, .close = ps1_hdc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 11bd41a66..8e46c6154 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1416,7 +1416,7 @@ const device_t vid_device = { .init = NULL, .close = vid_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed, .force_redraw = NULL, .config = vid_config @@ -1430,7 +1430,7 @@ const device_t vid_device_hx = { .init = NULL, .close = vid_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed, .force_redraw = NULL, .config = vid_config @@ -1444,7 +1444,7 @@ const device_t vid_device_sl = { .init = NULL, .close = vid_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed, .force_redraw = NULL, .config = NULL @@ -1592,7 +1592,7 @@ static const device_t eep_1000hx_device = { .init = eep_init, .close = eep_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1606,7 +1606,7 @@ static const device_t eep_1000sl2_device = { .init = eep_init, .close = eep_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 817b0d0cc..3b907f4df 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -2075,7 +2075,7 @@ const device_t m24_kbd_device = { .init = NULL, .close = m24_kbd_close, .reset = m24_kbd_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2119,7 +2119,7 @@ const device_t m19_vid_device = { .init = NULL, .close = m19_vid_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = m19_vid_speed_changed, .force_redraw = NULL, .config = m19_vid_config diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index 1fc284a46..604ccebaf 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -142,7 +142,7 @@ const device_t philips_device = { .init = philips_init, .close = philips_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index 4ec13b5c4..0d1ba714b 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -741,7 +741,7 @@ const device_t t1000_video_device = { .init = t1000_init, .close = t1000_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = t1000_speed_changed, .force_redraw = NULL, .config = t1000_config @@ -755,7 +755,7 @@ const device_t t1200_video_device = { .init = t1000_init, .close = t1000_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = t1000_speed_changed, .force_redraw = NULL, .config = t1000_config diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index 9b55dc021..886c1be6e 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -168,7 +168,7 @@ const device_t xi8088_device = { .init = xi8088_init, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = xi8088_config diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index f5e231772..776e10c9f 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -103,7 +103,7 @@ static const device_t zenith_scratchpad_device = { .init = zenith_scratchpad_init, .close = zenith_scratchpad_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/mem/catalyst_flash.c b/src/mem/catalyst_flash.c index 7cd40e9d7..4bb9b585a 100644 --- a/src/mem/catalyst_flash.c +++ b/src/mem/catalyst_flash.c @@ -240,7 +240,7 @@ const device_t catalyst_flash_device = { .init = catalyst_flash_init, .close = catalyst_flash_close, .reset = catalyst_flash_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/mem/intel_flash.c b/src/mem/intel_flash.c index 7949f302a..56a7ad0e0 100644 --- a/src/mem/intel_flash.c +++ b/src/mem/intel_flash.c @@ -564,7 +564,7 @@ const device_t intel_flash_bxt_ami_device = { .init = intel_flash_init, .close = intel_flash_close, .reset = intel_flash_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -578,7 +578,7 @@ const device_t intel_flash_bxt_device = { .init = intel_flash_init, .close = intel_flash_close, .reset = intel_flash_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -592,7 +592,7 @@ const device_t intel_flash_bxb_device = { .init = intel_flash_init, .close = intel_flash_close, .reset = intel_flash_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/mem/row.c b/src/mem/row.c index ccd0325a4..633d0e31a 100644 --- a/src/mem/row.c +++ b/src/mem/row.c @@ -334,15 +334,15 @@ row_init(const device_t *info) /* NOTE: NOT const, so that we can patch it at init. */ device_t row_device = { - .name = "DRAM Rows", + .name = "DRAM Rows", .internal_name = "dram_rows", - .flags = DEVICE_AT, - .local = 0x0000, - .init = row_init, - .close = row_close, - .reset = row_reset, - { .available = NULL }, + .flags = DEVICE_AT, + .local = 0x0000, + .init = row_init, + .close = row_close, + .reset = row_reset, + .available = NULL, .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL + .force_redraw = NULL, + .config = NULL }; diff --git a/src/mem/spd.c b/src/mem/spd.c index a0896a05a..fee9b0b11 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -595,7 +595,7 @@ static const device_t spd_device = { .init = spd_init, .close = spd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index cd6ec7cd9..3dce35444 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -576,7 +576,7 @@ const device_t sst_flash_29ee010_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -590,7 +590,7 @@ const device_t sst_flash_29ee020_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -604,7 +604,7 @@ const device_t winbond_flash_w29c512_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -618,7 +618,7 @@ const device_t winbond_flash_w29c010_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -632,7 +632,7 @@ const device_t winbond_flash_w29c020_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -646,7 +646,7 @@ const device_t winbond_flash_w29c040_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -660,7 +660,7 @@ const device_t sst_flash_39sf512_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -674,7 +674,7 @@ const device_t sst_flash_39sf010_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -688,7 +688,7 @@ const device_t sst_flash_39sf020_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -702,7 +702,7 @@ const device_t sst_flash_39sf040_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -716,7 +716,7 @@ const device_t sst_flash_39lf512_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -730,7 +730,7 @@ const device_t sst_flash_39lf010_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -744,7 +744,7 @@ const device_t sst_flash_39lf020_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -758,7 +758,7 @@ const device_t sst_flash_39lf040_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -772,7 +772,7 @@ const device_t sst_flash_39lf080_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -786,7 +786,7 @@ const device_t sst_flash_39lf016_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -808,7 +808,7 @@ const device_t sst_flash_49lf002_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -822,7 +822,7 @@ const device_t sst_flash_49lf020_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -836,7 +836,7 @@ const device_t sst_flash_49lf020a_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -850,7 +850,7 @@ const device_t sst_flash_49lf003_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -864,7 +864,7 @@ const device_t sst_flash_49lf030_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -878,7 +878,7 @@ const device_t sst_flash_49lf004_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -892,7 +892,7 @@ const device_t sst_flash_49lf004c_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -906,7 +906,7 @@ const device_t sst_flash_49lf040_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -920,7 +920,7 @@ const device_t sst_flash_49lf008_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -934,7 +934,7 @@ const device_t sst_flash_49lf008c_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -948,7 +948,7 @@ const device_t sst_flash_49lf080_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -962,7 +962,7 @@ const device_t sst_flash_49lf016_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -977,7 +977,7 @@ const device_t sst_flash_49lf160_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -991,7 +991,7 @@ const device_t amd_flash_29f020a_device = { .init = sst_init, .close = sst_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c index 2cafb1d46..21d71d75e 100644 --- a/src/network/net_3c501.c +++ b/src/network/net_3c501.c @@ -1222,7 +1222,7 @@ const device_t threec501_device = { .init = threec501_nic_init, .close = threec501_nic_close, .reset = elnkR3Reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = threec501_config diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index 6191c02bf..f96e76a11 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -739,15 +739,15 @@ static const device_config_t threec503_config[] = { }; const device_t threec503_device = { - .name = "3Com EtherLink II", + .name = "3Com EtherLink II", .internal_name = "3c503", - .flags = DEVICE_ISA, - .local = 0, - .init = threec503_nic_init, - .close = threec503_nic_close, - .reset = NULL, - { .available = NULL }, + .flags = DEVICE_ISA, + .local = 0, + .init = threec503_nic_init, + .close = threec503_nic_close, + .reset = NULL, + .available = NULL, .speed_changed = NULL, - .force_redraw = NULL, - .config = threec503_config + .force_redraw = NULL, + .config = threec503_config }; diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index d6062604f..297e11424 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -1047,7 +1047,7 @@ const device_t dp8390_device = { .init = dp8390_init, .close = dp8390_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index 3ad6bd030..b4fdce1e6 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -277,7 +277,7 @@ const device_t nmc93cxx_device = { .init = nmc93cxx_eeprom_init, .close = nmc93cxx_eeprom_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/network/net_modem.c b/src/network/net_modem.c index bb312ec31..732190254 100644 --- a/src/network/net_modem.c +++ b/src/network/net_modem.c @@ -1608,7 +1608,7 @@ const device_t modem_device = { .init = modem_init, .close = modem_close, .reset = NULL, - { .poll = NULL }, + .poll = NULL, .speed_changed = modem_speed_changed, .force_redraw = NULL, .config = modem_config diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 324154947..1f191e047 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -1633,7 +1633,7 @@ const device_t ne1000_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ne1000_config @@ -1647,7 +1647,7 @@ const device_t ne1000_compat_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ne1000_compat_config @@ -1661,7 +1661,7 @@ const device_t ne2000_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ne2000_config @@ -1675,7 +1675,7 @@ const device_t ne2000_compat_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ne2000_compat_config @@ -1689,7 +1689,7 @@ const device_t ne2000_compat_8bit_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ne2000_compat_8bit_config @@ -1703,7 +1703,7 @@ const device_t ethernext_mc_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = mca_mac_config @@ -1717,7 +1717,7 @@ const device_t rtl8019as_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = rtl8019as_available }, + .available = rtl8019as_available, .speed_changed = NULL, .force_redraw = NULL, .config = rtl8019as_config @@ -1731,7 +1731,7 @@ const device_t de220p_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = de220p_available }, + .available = de220p_available, .speed_changed = NULL, .force_redraw = NULL, .config = rtl8019as_config @@ -1745,7 +1745,7 @@ const device_t rtl8029as_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = rtl8029as_config diff --git a/src/network/net_null.c b/src/network/net_null.c index 6fb3f3440..6d5f68e46 100644 --- a/src/network/net_null.c +++ b/src/network/net_null.c @@ -218,8 +218,8 @@ net_null_close(void *priv) } const netdrv_t net_null_drv = { - &net_null_in_available, - &net_null_init, - &net_null_close, - NULL + .notify_in = &net_null_in_available, + .init = &net_null_init, + .close = &net_null_close, + .priv = NULL }; diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index 852191c55..2af34d786 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -572,8 +572,8 @@ net_pcap_close(void *priv) } const netdrv_t net_pcap_drv = { - &net_pcap_in_available, - &net_pcap_init, - &net_pcap_close, - NULL + .notify_in = &net_pcap_in_available, + .init = &net_pcap_init, + .close = &net_pcap_close, + .priv = NULL }; diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index b1fca8feb..c9323e702 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -3220,7 +3220,7 @@ const device_t pcnet_am79c960_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_isa_config @@ -3234,7 +3234,7 @@ const device_t pcnet_am79c960_eb_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_isa_config @@ -3248,7 +3248,7 @@ const device_t pcnet_am79c960_vlb_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_vlb_config @@ -3262,7 +3262,7 @@ const device_t pcnet_am79c961_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_pci_config @@ -3276,7 +3276,7 @@ const device_t pcnet_am79c970a_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_pci_config @@ -3290,7 +3290,7 @@ const device_t pcnet_am79c973_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_pci_config @@ -3304,7 +3304,7 @@ const device_t pcnet_am79c973_onboard_device = { .init = pcnet_init, .close = pcnet_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = pcnet_pci_config diff --git a/src/network/net_plip.c b/src/network/net_plip.c index 8b0bf460c..b1264b045 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -508,7 +508,7 @@ const device_t plip_device = { .init = plip_net_init, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 0dac29a8c..b9b7fc957 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -3333,7 +3333,7 @@ const device_t rtl8139c_plus_device = { .init = nic_init, .close = nic_close, .reset = rtl8139_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = rtl8139c_config diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 92434973d..22fdc722d 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -544,7 +544,8 @@ net_slirp_close(void *priv) } const netdrv_t net_slirp_drv = { - &net_slirp_in_available, - &net_slirp_init, - &net_slirp_close + .notify_in = &net_slirp_in_available, + .init = &net_slirp_init, + .close = &net_slirp_close, + .priv = NULL }; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index ca43b0844..af30c5505 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1700,7 +1700,7 @@ const device_t dec_tulip_device = { .init = nic_init, .close = nic_close, .reset = tulip_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = dec_tulip_21143_config @@ -1714,7 +1714,7 @@ const device_t dec_tulip_21140_device = { .init = nic_init, .close = nic_close, .reset = tulip_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = dec_tulip_21140_config @@ -1728,7 +1728,7 @@ const device_t dec_tulip_21140_vpc_device = { .init = nic_init, .close = nic_close, .reset = tulip_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = dec_tulip_21140_config @@ -1742,7 +1742,7 @@ const device_t dec_tulip_21040_device = { .init = nic_init, .close = nic_close, .reset = tulip_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = dec_tulip_21143_config diff --git a/src/network/net_vde.c b/src/network/net_vde.c index d783c9c9d..4f8d5c21f 100644 --- a/src/network/net_vde.c +++ b/src/network/net_vde.c @@ -302,9 +302,9 @@ void *net_vde_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, c // VDE Driver structure //- const netdrv_t net_vde_drv = { - &net_vde_in_available, - &net_vde_init, - &net_vde_close, - NULL + .notify_in = &net_vde_in_available, + .init = &net_vde_init, + .close = &net_vde_close, + .priv = NULL }; diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 72a4b7fd0..d22b6076c 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -1084,7 +1084,7 @@ const device_t wd8003e_device = { .init = wd_init, .close = wd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = wd8003_config @@ -1098,7 +1098,7 @@ const device_t wd8003eb_device = { .init = wd_init, .close = wd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = wd8003eb_config @@ -1112,7 +1112,7 @@ const device_t wd8013ebt_device = { .init = wd_init, .close = wd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = wd8013_config @@ -1126,7 +1126,7 @@ const device_t wd8003eta_device = { .init = wd_init, .close = wd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = mca_mac_config @@ -1140,7 +1140,7 @@ const device_t wd8003ea_device = { .init = wd_init, .close = wd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = mca_mac_config @@ -1154,7 +1154,7 @@ const device_t wd8013epa_device = { .init = wd_init, .close = wd_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = wd8013epa_config diff --git a/src/nvr_at.c b/src/nvr_at.c index 9465839a7..147795f8e 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -1224,7 +1224,7 @@ const device_t at_nvr_old_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1238,7 +1238,7 @@ const device_t at_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1252,7 +1252,7 @@ const device_t at_mb_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1266,7 +1266,7 @@ const device_t ps_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1280,7 +1280,7 @@ const device_t amstrad_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1294,7 +1294,7 @@ const device_t ibmat_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1308,7 +1308,7 @@ const device_t piix4_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1322,7 +1322,7 @@ const device_t ps_no_nmi_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1336,7 +1336,7 @@ const device_t amstrad_no_nmi_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1350,7 +1350,7 @@ const device_t ami_1992_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1364,7 +1364,7 @@ const device_t ami_1994_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1378,7 +1378,7 @@ const device_t ami_1995_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1392,7 +1392,7 @@ const device_t via_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1406,7 +1406,7 @@ const device_t p6rp4_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1420,7 +1420,7 @@ const device_t amstrad_megapc_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL @@ -1434,7 +1434,7 @@ const device_t elt_nvr_device = { .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, - { .available = NULL }, + .available = NULL, .speed_changed = nvr_at_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 67eaccc38..809083395 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -170,7 +170,7 @@ const device_t ps2_nvr_device = { .init = ps2_nvr_init, .close = ps2_nvr_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -184,7 +184,7 @@ const device_t ps2_nvr_55ls_device = { .init = ps2_nvr_init, .close = ps2_nvr_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/pci_dummy.c b/src/pci_dummy.c index 704f85d8c..bceb58c22 100644 --- a/src/pci_dummy.c +++ b/src/pci_dummy.c @@ -278,7 +278,7 @@ pci_dummy_card_init(UNUSED(const device_t *info)) { pci_dummy_t *dev = (pci_dummy_t *) calloc(1, sizeof(pci_dummy_t)); - pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev, &dev->pci_slot); + pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev, &dev->pci_slot); return dev; } @@ -291,7 +291,7 @@ const device_t pci_dummy_device = { .init = pci_dummy_card_init, .close = pci_dummy_close, .reset = pci_dummy_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/pit.c b/src/pit.c index 8b9f23a79..a283d1205 100644 --- a/src/pit.c +++ b/src/pit.c @@ -960,7 +960,7 @@ const device_t i8253_device = { .init = pit_init, .close = pit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL @@ -974,7 +974,7 @@ const device_t i8253_ext_io_device = { .init = pit_init, .close = pit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -988,7 +988,7 @@ const device_t i8254_device = { .init = pit_init, .close = pit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL @@ -1002,7 +1002,7 @@ const device_t i8254_sec_device = { .init = pit_init, .close = pit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL @@ -1016,7 +1016,7 @@ const device_t i8254_ext_io_device = { .init = pit_init, .close = pit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1030,7 +1030,7 @@ const device_t i8254_ps2_device = { .init = pit_init, .close = pit_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL @@ -1250,14 +1250,14 @@ pit_set_clock(uint32_t clock) } const pit_intf_t pit_classic_intf = { - &pit_read, - &pit_write, - &pit_ctr_get_count, - &pit_ctr_set_gate, - &pit_ctr_set_using_timer, - &pit_ctr_set_out_func, - &pit_ctr_set_load_func, - &ctr_clock, - &pit_set_pit_const, - NULL, + .read = &pit_read, + .write = &pit_write, + .get_count = &pit_ctr_get_count, + .set_gate = &pit_ctr_set_gate, + .set_using_timer = &pit_ctr_set_using_timer, + .set_out_func = &pit_ctr_set_out_func, + .set_load_func = &pit_ctr_set_load_func, + .ctr_clock = &ctr_clock, + .set_pit_const = &pit_set_pit_const, + .data = NULL, }; diff --git a/src/pit_fast.c b/src/pit_fast.c index 0d56a6616..b92b59f3c 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -751,7 +751,7 @@ const device_t i8253_fast_device = { .init = pitf_init, .close = pitf_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL @@ -765,7 +765,7 @@ const device_t i8254_fast_device = { .init = pitf_init, .close = pitf_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL @@ -779,7 +779,7 @@ const device_t i8254_sec_fast_device = { .init = pitf_init, .close = pitf_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL @@ -793,7 +793,7 @@ const device_t i8254_ext_io_fast_device = { .init = pitf_init, .close = pitf_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -807,21 +807,21 @@ const device_t i8254_ps2_fast_device = { .init = pitf_init, .close = pitf_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; const pit_intf_t pit_fast_intf = { - &pitf_read, - &pitf_write, - &pitf_ctr_get_count, - &pitf_ctr_set_gate, - &pitf_ctr_set_using_timer, - &pitf_ctr_set_out_func, - &pitf_ctr_set_load_func, - &pitf_ctr_clock, - &pitf_set_pit_const, - NULL, + .read = &pitf_read, + .write = &pitf_write, + .get_count = &pitf_ctr_get_count, + .set_gate = &pitf_ctr_set_gate, + .set_using_timer = &pitf_ctr_set_using_timer, + .set_out_func = &pitf_ctr_set_out_func, + .set_load_func = &pitf_ctr_set_load_func, + .ctr_clock = &pitf_ctr_clock, + .set_pit_const = &pitf_set_pit_const, + .data = NULL, }; diff --git a/src/port_6x.c b/src/port_6x.c index 971b92d28..b8183d651 100644 --- a/src/port_6x.c +++ b/src/port_6x.c @@ -212,7 +212,7 @@ const device_t port_6x_device = { .init = port_6x_init, .close = port_6x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -226,7 +226,7 @@ const device_t port_6x_xi8088_device = { .init = port_6x_init, .close = port_6x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -240,7 +240,7 @@ const device_t port_6x_ps2_device = { .init = port_6x_init, .close = port_6x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -254,7 +254,7 @@ const device_t port_6x_olivetti_device = { .init = port_6x_init, .close = port_6x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/port_92.c b/src/port_92.c index 18e60326c..d1a53a321 100644 --- a/src/port_92.c +++ b/src/port_92.c @@ -235,7 +235,7 @@ const device_t port_92_device = { .init = port_92_init, .close = port_92_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -249,7 +249,7 @@ const device_t port_92_key_device = { .init = port_92_init, .close = port_92_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -263,7 +263,7 @@ const device_t port_92_inv_device = { .init = port_92_init, .close = port_92_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -277,7 +277,7 @@ const device_t port_92_word_device = { .init = port_92_init, .close = port_92_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -291,7 +291,7 @@ const device_t port_92_pci_device = { .init = port_92_init, .close = port_92_close, .reset = port_92_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 937213b85..9e19e8524 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1447,7 +1447,7 @@ const device_t aha154xa_device = { .init = aha_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = aha_154xb_config @@ -1461,7 +1461,7 @@ const device_t aha154xb_device = { .init = aha_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = aha_154xb_config @@ -1475,7 +1475,7 @@ const device_t aha154xc_device = { .init = aha_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = aha_154x_config @@ -1489,7 +1489,7 @@ const device_t aha154xcf_device = { .init = aha_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = aha_154xcf_config @@ -1503,7 +1503,7 @@ const device_t aha154xcp_device = { .init = aha_init, .close = aha1542cp_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = aha_154xcp_config @@ -1517,7 +1517,7 @@ const device_t aha1640_device = { .init = aha_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index b0aeedfa4..6d95ce44a 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1870,7 +1870,7 @@ const device_t buslogic_542b_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT_ISA_Config @@ -1884,7 +1884,7 @@ const device_t buslogic_545s_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT_ISA_Config @@ -1898,7 +1898,7 @@ const device_t buslogic_542bh_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT_ISA_Config @@ -1912,7 +1912,7 @@ const device_t buslogic_545c_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT_ISA_Config @@ -1926,7 +1926,7 @@ const device_t buslogic_640a_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1940,7 +1940,7 @@ const device_t buslogic_445s_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT_ISA_Config @@ -1954,7 +1954,7 @@ const device_t buslogic_445c_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT_ISA_Config @@ -1968,7 +1968,7 @@ const device_t buslogic_958d_pci_device = { .init = buslogic_init, .close = x54x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = BT958D_Config diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index fcfda69e4..def001624 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -954,7 +954,7 @@ const device_t scsi_lcs6821n_device = { .init = ncr53c400_init, .close = ncr53c400_close, .reset = NULL, - { .available = lcs6821n_available }, + .available = lcs6821n_available, .speed_changed = NULL, .force_redraw = NULL, .config = ncr53c400_mmio_config @@ -968,7 +968,7 @@ const device_t scsi_rt1000b_device = { .init = ncr53c400_init, .close = ncr53c400_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = rt1000b_config @@ -982,7 +982,7 @@ const device_t scsi_rt1000mc_device = { .init = ncr53c400_init, .close = ncr53c400_close, .reset = NULL, - { .available = rt1000b_mc_available }, + .available = rt1000b_mc_available, .speed_changed = NULL, .force_redraw = NULL, .config = rt1000b_mc_config @@ -996,7 +996,7 @@ const device_t scsi_t130b_device = { .init = ncr53c400_init, .close = ncr53c400_close, .reset = NULL, - { .available = t130b_available }, + .available = t130b_available, .speed_changed = NULL, .force_redraw = NULL, .config = t130b_config @@ -1010,7 +1010,7 @@ const device_t scsi_ls2000_device = { .init = ncr53c400_init, .close = ncr53c400_close, .reset = NULL, - { .available = corel_ls2000_available }, + .available = corel_ls2000_available, .speed_changed = NULL, .force_redraw = NULL, .config = ncr53c400_mmio_config diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 1425f468b..27542028a 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -2692,7 +2692,7 @@ const device_t ncr53c810_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2706,7 +2706,7 @@ const device_t ncr53c810_onboard_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2720,7 +2720,7 @@ const device_t ncr53c815_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, ncr53c8xx_pci_config @@ -2734,7 +2734,7 @@ const device_t ncr53c820_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2748,7 +2748,7 @@ const device_t ncr53c825a_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ncr53c8xx_pci_config @@ -2762,7 +2762,7 @@ const device_t ncr53c860_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ncr53c8xx_pci_config @@ -2776,7 +2776,7 @@ const device_t ncr53c875_pci_device = { .init = ncr53c8xx_init, .close = ncr53c8xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ncr53c8xx_pci_config diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index c2e5c9168..e8f256bed 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -2482,7 +2482,7 @@ const device_t dc390_pci_device = { .init = dc390_init, .close = esp_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = bios_enable_config @@ -2496,7 +2496,7 @@ const device_t am53c974_pci_device = { .init = dc390_init, .close = esp_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -2510,7 +2510,7 @@ const device_t ncr53c90a_mca_device = { .init = ncr53c9x_mca_init, .close = esp_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index e308d0788..8be075833 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1257,7 +1257,7 @@ const device_t spock_device = { .init = spock_init, .close = spock_close, .reset = NULL, - { .available = spock_available }, + .available = spock_available, .speed_changed = NULL, .force_redraw = NULL, .config = spock_rom_config @@ -1271,7 +1271,7 @@ const device_t tribble_device = { .init = spock_init, .close = spock_close, .reset = NULL, - { .available = spock_available }, + .available = spock_available, .speed_changed = NULL, .force_redraw = NULL, .config = spock_rom_config diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 0d653469a..92de9d17b 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -608,7 +608,7 @@ const device_t scsi_t128_device = { .init = t128_init, .close = t128_close, .reset = NULL, - { .available = t128_available }, + .available = t128_available, .speed_changed = NULL, .force_redraw = NULL, .config = t128_config @@ -623,7 +623,7 @@ const device_t scsi_t228_device = { .init = t128_init, .close = t128_close, .reset = NULL, - { .available = t128_available }, + .available = t128_available, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -637,7 +637,7 @@ const device_t scsi_pas_device = { .init = t128_init, .close = t128_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index cbe89c682..59349dcbe 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -290,7 +290,7 @@ const device_t i82091aa_device = { .init = i82091aa_init, .close = i82091aa_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -304,7 +304,7 @@ const device_t i82091aa_398_device = { .init = i82091aa_init, .close = i82091aa_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -318,7 +318,7 @@ const device_t i82091aa_ide_pri_device = { .init = i82091aa_init, .close = i82091aa_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -332,7 +332,7 @@ const device_t i82091aa_ide_device = { .init = i82091aa_init, .close = i82091aa_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_acc3221.c b/src/sio/sio_acc3221.c index 275d9ae2e..6fcac024c 100644 --- a/src/sio/sio_acc3221.c +++ b/src/sio/sio_acc3221.c @@ -477,7 +477,7 @@ const device_t acc3221_device = { .init = acc3221_init, .close = acc3221_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c index 78c585c11..ce250ff2b 100644 --- a/src/sio/sio_ali5123.c +++ b/src/sio/sio_ali5123.c @@ -492,7 +492,7 @@ const device_t ali5123_device = { .init = ali5123_init, .close = ali5123_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_detect.c b/src/sio/sio_detect.c index 38faf3c2c..ae34730ac 100644 --- a/src/sio/sio_detect.c +++ b/src/sio/sio_detect.c @@ -110,7 +110,7 @@ const device_t sio_detect_device = { .init = sio_detect_init, .close = sio_detect_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index d4afb11da..04dcf109a 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -393,7 +393,7 @@ const device_t f82c606_device = { .init = f82c710_init, .close = f82c710_close, .reset = f82c710_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -407,7 +407,7 @@ const device_t f82c710_device = { .init = f82c710_init, .close = f82c710_close, .reset = f82c710_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index 0cd686991..7f02026e5 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -364,7 +364,7 @@ const device_t fdc37c669_device = { .init = fdc37c669_init, .close = fdc37c669_close, .reset = fdc37c669_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -378,7 +378,7 @@ const device_t fdc37c669_370_device = { .init = fdc37c669_init, .close = fdc37c669_close, .reset = fdc37c669_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_fdc37c67x.c b/src/sio/sio_fdc37c67x.c index 871f3b1c8..bac4685f5 100644 --- a/src/sio/sio_fdc37c67x.c +++ b/src/sio/sio_fdc37c67x.c @@ -625,7 +625,7 @@ const device_t fdc37c67x_device = { .init = fdc37c67x_init, .close = fdc37c67x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index c1fb2c1a5..6340218b7 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -346,7 +346,7 @@ const device_t fdc37c651_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -360,7 +360,7 @@ const device_t fdc37c651_ide_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -374,7 +374,7 @@ const device_t fdc37c661_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -388,7 +388,7 @@ const device_t fdc37c661_ide_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -402,7 +402,7 @@ const device_t fdc37c661_ide_sec_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -416,7 +416,7 @@ const device_t fdc37c663_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -430,7 +430,7 @@ const device_t fdc37c663_ide_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -444,7 +444,7 @@ const device_t fdc37c665_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -458,7 +458,7 @@ const device_t fdc37c665_ide_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -472,7 +472,7 @@ const device_t fdc37c665_ide_pri_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -486,7 +486,7 @@ const device_t fdc37c665_ide_sec_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -500,7 +500,7 @@ const device_t fdc37c666_device = { .init = fdc37c6xx_init, .close = fdc37c6xx_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index a0152c34a..0279903c6 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -932,7 +932,7 @@ static const device_t access_bus_device = { .init = access_bus_init, .close = access_bus_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1014,7 +1014,7 @@ const device_t fdc37c931apm_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1028,7 +1028,7 @@ const device_t fdc37c931apm_compaq_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1042,7 +1042,7 @@ const device_t fdc37c932_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1056,7 +1056,7 @@ const device_t fdc37c932fr_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1070,7 +1070,7 @@ const device_t fdc37c932qf_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1084,7 +1084,7 @@ const device_t fdc37c935_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1098,7 +1098,7 @@ const device_t fdc37c935_370_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -1112,7 +1112,7 @@ const device_t fdc37c935_no_nvr_device = { .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_fdc37m60x.c b/src/sio/sio_fdc37m60x.c index 38a163538..aab4d8968 100644 --- a/src/sio/sio_fdc37m60x.c +++ b/src/sio/sio_fdc37m60x.c @@ -329,7 +329,7 @@ const device_t fdc37m60x_device = { .init = fdc37m60x_init, .close = fdc37m60x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -343,7 +343,7 @@ const device_t fdc37m60x_370_device = { .init = fdc37m60x_init, .close = fdc37m60x_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index 00524863a..610d69197 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -844,7 +844,7 @@ const device_t it8661f_device = { .init = it86x1f_init, .close = it86x1f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -858,7 +858,7 @@ const device_t it8671f_device = { .init = it86x1f_init, .close = it86x1f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index ab7f8597e..b21c2d1fc 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -495,7 +495,7 @@ const device_t pc87306_device = { .init = pc87306_init, .close = pc87306_close, .reset = pc87306_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index cb772aa5b..1f84152f5 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -625,7 +625,7 @@ const device_t pc87307_device = { .init = pc87307_init, .close = pc87307_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -639,7 +639,7 @@ const device_t pc87307_15c_device = { .init = pc87307_init, .close = pc87307_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -653,7 +653,7 @@ const device_t pc87307_both_device = { .init = pc87307_init, .close = pc87307_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -667,7 +667,7 @@ const device_t pc97307_device = { .init = pc87307_init, .close = pc87307_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index d10cb3e0b..f445ee189 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -497,7 +497,7 @@ const device_t pc87309_device = { .init = pc87309_init, .close = pc87309_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -511,7 +511,7 @@ const device_t pc87309_15c_device = { .init = pc87309_init, .close = pc87309_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_pc87310.c b/src/sio/sio_pc87310.c index 075b819ff..674db6364 100644 --- a/src/sio/sio_pc87310.c +++ b/src/sio/sio_pc87310.c @@ -309,7 +309,7 @@ const device_t pc87310_device = { .init = pc87310_init, .close = pc87310_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -323,7 +323,7 @@ const device_t pc87310_ide_device = { .init = pc87310_init, .close = pc87310_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -337,7 +337,7 @@ const device_t ali5105_device = { .init = pc87310_init, .close = pc87310_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_pc87311.c b/src/sio/sio_pc87311.c index 9740753d1..f1b823e47 100644 --- a/src/sio/sio_pc87311.c +++ b/src/sio/sio_pc87311.c @@ -298,7 +298,7 @@ const device_t pc87311_device = { .init = pc87311_init, .close = pc87311_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -312,7 +312,7 @@ const device_t pc87311_ide_device = { .init = pc87311_init, .close = pc87311_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_pc87332.c b/src/sio/sio_pc87332.c index 5cbf9f694..494c6d8bb 100644 --- a/src/sio/sio_pc87332.c +++ b/src/sio/sio_pc87332.c @@ -354,7 +354,7 @@ const device_t pc87332_device = { .init = pc87332_init, .close = pc87332_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -368,7 +368,7 @@ const device_t pc87332_398_device = { .init = pc87332_init, .close = pc87332_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -382,7 +382,7 @@ const device_t pc87332_398_ide_device = { .init = pc87332_init, .close = pc87332_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -396,7 +396,7 @@ const device_t pc87332_398_ide_sec_device = { .init = pc87332_init, .close = pc87332_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -410,7 +410,7 @@ const device_t pc87332_398_ide_fdcon_device = { .init = pc87332_init, .close = pc87332_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_prime3b.c b/src/sio/sio_prime3b.c index c93630516..1633c844b 100644 --- a/src/sio/sio_prime3b.c +++ b/src/sio/sio_prime3b.c @@ -290,7 +290,7 @@ const device_t prime3b_device = { .init = prime3b_init, .close = prime3b_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -304,7 +304,7 @@ const device_t prime3b_ide_device = { .init = prime3b_init, .close = prime3b_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c index b19f861bf..68361d3e0 100644 --- a/src/sio/sio_prime3c.c +++ b/src/sio/sio_prime3c.c @@ -335,7 +335,7 @@ const device_t prime3c_device = { .init = prime3c_init, .close = prime3c_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -349,7 +349,7 @@ const device_t prime3c_ide_device = { .init = prime3c_init, .close = prime3c_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_um8663f.c b/src/sio/sio_um8663f.c index 7391b029f..79cb37da4 100644 --- a/src/sio/sio_um8663f.c +++ b/src/sio/sio_um8663f.c @@ -289,7 +289,7 @@ const device_t um8663af_device = { .init = um8663f_init, .close = um8663f_close, .reset = um8663f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -303,7 +303,7 @@ const device_t um8663af_ide_device = { .init = um8663f_init, .close = um8663f_close, .reset = um8663f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -317,7 +317,7 @@ const device_t um8663af_ide_sec_device = { .init = um8663f_init, .close = um8663f_close, .reset = um8663f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -331,7 +331,7 @@ const device_t um8663bf_device = { .init = um8663f_init, .close = um8663f_close, .reset = um8663f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -345,7 +345,7 @@ const device_t um8663bf_ide_device = { .init = um8663f_init, .close = um8663f_close, .reset = um8663f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -359,7 +359,7 @@ const device_t um8663bf_ide_sec_device = { .init = um8663f_init, .close = um8663f_close, .reset = um8663f_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_um8669f.c b/src/sio/sio_um8669f.c index 136b1add6..e3ef81e11 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -362,7 +362,7 @@ const device_t um8669f_device = { .init = um8669f_init, .close = um8669f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -376,7 +376,7 @@ const device_t um8669f_ide_device = { .init = um8669f_init, .close = um8669f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -390,7 +390,7 @@ const device_t um8669f_ide_sec_device = { .init = um8669f_init, .close = um8669f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c index 6a02ef359..ecfc7ba09 100644 --- a/src/sio/sio_vl82c113.c +++ b/src/sio/sio_vl82c113.c @@ -155,7 +155,7 @@ const device_t vl82c113_device = { .init = vl82c113_init, .close = vl82c113_close, .reset = vl82c113_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_vt82c686.c b/src/sio/sio_vt82c686.c index f22af07df..47b5e1c09 100644 --- a/src/sio/sio_vt82c686.c +++ b/src/sio/sio_vt82c686.c @@ -311,7 +311,7 @@ const device_t via_vt82c686_sio_device = { .init = vt82c686_init, .close = vt82c686_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index 2e4b82059..69bdb1220 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -474,7 +474,7 @@ const device_t w83787f_88h_device = { .init = w83787f_init, .close = w83787f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -488,7 +488,7 @@ const device_t w83787f_device = { .init = w83787f_init, .close = w83787f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -502,7 +502,7 @@ const device_t w83787f_ide_device = { .init = w83787f_init, .close = w83787f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -516,7 +516,7 @@ const device_t w83787f_ide_en_device = { .init = w83787f_init, .close = w83787f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -530,7 +530,7 @@ const device_t w83787f_ide_sec_device = { .init = w83787f_init, .close = w83787f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_w83877f.c b/src/sio/sio_w83877f.c index c9a437630..a6ea6f4e4 100644 --- a/src/sio/sio_w83877f.c +++ b/src/sio/sio_w83877f.c @@ -467,7 +467,7 @@ const device_t w83877f_device = { .init = w83877f_init, .close = w83877f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -481,7 +481,7 @@ const device_t w83877f_president_device = { .init = w83877f_init, .close = w83877f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -495,7 +495,7 @@ const device_t w83877tf_device = { .init = w83877f_init, .close = w83877f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -509,7 +509,7 @@ const device_t w83877tf_acorp_device = { .init = w83877f_init, .close = w83877f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sio/sio_w83977f.c b/src/sio/sio_w83977f.c index 063f0ca69..7df0163a5 100644 --- a/src/sio/sio_w83977f.c +++ b/src/sio/sio_w83977f.c @@ -624,7 +624,7 @@ const device_t w83977f_device = { .init = w83977f_init, .close = w83977f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -638,7 +638,7 @@ const device_t w83977f_370_device = { .init = w83977f_init, .close = w83977f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -652,7 +652,7 @@ const device_t w83977tf_device = { .init = w83977f_init, .close = w83977f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -666,7 +666,7 @@ const device_t w83977ef_device = { .init = w83977f_init, .close = w83977f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -680,7 +680,7 @@ const device_t w83977ef_370_device = { .init = w83977f_init, .close = w83977f_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 2f4f5da14..692a53aa3 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -5913,7 +5913,7 @@ const device_t sb_16_pnp_device = { .init = sb_16_pnp_init, .close = sb_close, .reset = NULL, - .available = sb_16_pnp_noide_available, + .available = sb_16_pnp_noide_available, .speed_changed = sb_speed_changed, .force_redraw = NULL, .config = sb_16_pnp_config @@ -6039,7 +6039,7 @@ const device_t sb_awe64_device = { .init = sb_awe32_pnp_init, .close = sb_awe32_close, .reset = NULL, - .available = sb_awe64_noide_available, + .available = sb_awe64_noide_available, .speed_changed = sb_speed_changed, .force_redraw = NULL, .config = sb_awe64_config diff --git a/src/usb.c b/src/usb.c index 6bdc8e6c0..222062f4f 100644 --- a/src/usb.c +++ b/src/usb.c @@ -433,7 +433,7 @@ const device_t usb_device = { .init = usb_init, .close = usb_close, .reset = usb_reset, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/agpgart.c b/src/video/agpgart.c index b8ae2bdc8..bf1976b73 100644 --- a/src/video/agpgart.c +++ b/src/video/agpgart.c @@ -167,7 +167,7 @@ const device_t agpgart_device = { .init = agpgart_init, .close = agpgart_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 470642884..1c81e8166 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -4038,9 +4038,7 @@ static const device_config_t isa_ext8514_config[] = { { .description = "" } }, }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format off @@ -4083,9 +4081,7 @@ static const device_config_t mca_ext8514_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format off @@ -4097,7 +4093,7 @@ const device_t gen8514_isa_device = { .init = ibm8514_init, .close = ibm8514_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ibm8514_speed_changed, .force_redraw = ibm8514_force_redraw, .config = isa_ext8514_config @@ -4111,7 +4107,7 @@ const device_t ibm8514_mca_device = { .init = ibm8514_init, .close = ibm8514_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ibm8514_speed_changed, .force_redraw = ibm8514_force_redraw, .config = mca_ext8514_config diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index df41e5d3f..59688087f 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -347,9 +347,7 @@ static const device_config_t ati18800_wonder_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; const device_t ati18800_wonder_device = { @@ -360,7 +358,7 @@ const device_t ati18800_wonder_device = { .init = ati18800_init, .close = ati18800_close, .reset = NULL, - { .available = ati18800_wonder_available }, + .available = ati18800_wonder_available, .speed_changed = ati18800_speed_changed, .force_redraw = ati18800_force_redraw, .config = ati18800_wonder_config @@ -374,7 +372,7 @@ const device_t ati18800_vga88_device = { .init = ati18800_init, .close = ati18800_close, .reset = NULL, - { .available = ati18800_vga88_available }, + .available = ati18800_vga88_available, .speed_changed = ati18800_speed_changed, .force_redraw = ati18800_force_redraw, .config = NULL @@ -388,7 +386,7 @@ const device_t ati18800_device = { .init = ati18800_init, .close = ati18800_close, .reset = NULL, - { .available = ati18800_available }, + .available = ati18800_available, .speed_changed = ati18800_speed_changed, .force_redraw = ati18800_force_redraw, .config = NULL diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index b3cf8aad1..4c039d9e6 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -766,9 +766,7 @@ static const device_config_t ati28800_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; #ifdef USE_XL24 @@ -796,9 +794,7 @@ static const device_config_t ati28800_wonderxl_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; #endif /* USE_XL24 */ // clang-format on @@ -811,7 +807,7 @@ const device_t ati28800_device = { .init = ati28800_init, .close = ati28800_close, .reset = NULL, - { .available = ati28800_available }, + .available = ati28800_available, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = ati28800_config @@ -825,7 +821,7 @@ const device_t ati28800k_device = { .init = ati28800k_init, .close = ati28800_close, .reset = NULL, - { .available = ati28800k_available }, + .available = ati28800k_available, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = ati28800_config @@ -839,7 +835,7 @@ const device_t ati28800k_spc4620p_device = { .init = ati28800k_init, .close = ati28800_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = NULL @@ -853,7 +849,7 @@ const device_t ati28800k_spc6033p_device = { .init = ati28800k_init, .close = ati28800_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = NULL @@ -867,7 +863,7 @@ const device_t compaq_ati28800_device = { .init = ati28800_init, .close = ati28800_close, .reset = NULL, - { .available = compaq_ati28800_available }, + .available = compaq_ati28800_available, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = ati28800_config @@ -881,7 +877,7 @@ const device_t ati28800_wonder1024d_xl_plus_device = { .init = ati28800_init, .close = ati28800_close, .reset = NULL, - { .available = ati28800_wonder1024d_xl_plus_available }, + .available = ati28800_wonder1024d_xl_plus_available, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = NULL @@ -896,7 +892,7 @@ const device_t ati28800_wonderxl24_device = { .init = ati28800_init, .close = ati28800_close, .reset = NULL, - { .available = ati28800_wonderxl24_available }, + .available = ati28800_wonderxl24_available, .speed_changed = ati28800_speed_changed, .force_redraw = ati28800_force_redraw, .config = ati28800_wonderxl_config diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index cb6de4353..bb5ccbf31 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -314,7 +314,7 @@ const device_t ati68860_ramdac_device = { .init = ati68860_ramdac_init, .close = ati68860_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_ati68875_ramdac.c b/src/video/vid_ati68875_ramdac.c index 447a8eca8..5d573a282 100644 --- a/src/video/vid_ati68875_ramdac.c +++ b/src/video/vid_ati68875_ramdac.c @@ -160,7 +160,7 @@ const device_t ati68875_ramdac_device = { .init = ati68875_ramdac_init, .close = ati68875_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 1c79ae1d5..b3a544fc1 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -4733,9 +4733,7 @@ static const device_config_t mach64gx_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t mach64vt2_config[] = { @@ -4758,9 +4756,7 @@ static const device_config_t mach64vt2_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -4772,7 +4768,7 @@ const device_t mach64gx_isa_device = { .init = mach64gx_init, .close = mach64_close, .reset = NULL, - { .available = mach64gx_isa_available }, + .available = mach64gx_isa_available, .speed_changed = mach64_speed_changed, .force_redraw = mach64_force_redraw, .config = mach64gx_config @@ -4786,7 +4782,7 @@ const device_t mach64gx_vlb_device = { .init = mach64gx_init, .close = mach64_close, .reset = NULL, - { .available = mach64gx_vlb_available }, + .available = mach64gx_vlb_available, .speed_changed = mach64_speed_changed, .force_redraw = mach64_force_redraw, .config = mach64gx_config @@ -4800,7 +4796,7 @@ const device_t mach64gx_pci_device = { .init = mach64gx_init, .close = mach64_close, .reset = NULL, - { .available = mach64gx_available }, + .available = mach64gx_available, .speed_changed = mach64_speed_changed, .force_redraw = mach64_force_redraw, .config = mach64gx_config @@ -4814,7 +4810,7 @@ const device_t mach64vt2_device = { .init = mach64vt2_init, .close = mach64_close, .reset = NULL, - { .available = mach64vt2_available }, + .available = mach64vt2_available, .speed_changed = mach64_speed_changed, .force_redraw = mach64_force_redraw, .config = mach64vt2_config diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 812885559..c9cdca0db 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -6329,12 +6329,9 @@ static const device_config_t mach8_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; -// clang-format off static const device_config_t mach32_config[] = { { .name = "memory", @@ -6363,12 +6360,9 @@ static const device_config_t mach32_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; -// clang-format off static const device_config_t mach32_pci_config[] = { { .name = "ramdac", @@ -6416,92 +6410,90 @@ static const device_config_t mach32_pci_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; +// clang-format on const device_t mach8_vga_isa_device = { - .name = "ATI Mach8 (ATI Graphics Ultra) (ISA)", + .name = "ATI Mach8 (ATI Graphics Ultra) (ISA)", .internal_name = "mach8_vga_isa", - .flags = DEVICE_ISA, - .local = 1, - .init = mach8_init, - .close = mach_close, - .reset = NULL, - { .available = mach8_vga_available }, + .flags = DEVICE_ISA, + .local = 1, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + .available = mach8_vga_available, .speed_changed = mach_speed_changed, - .force_redraw = mach_force_redraw, - .config = mach8_config + .force_redraw = mach_force_redraw, + .config = mach8_config }; const device_t mach32_isa_device = { - .name = "ATI Mach32 (ISA)", + .name = "ATI Mach32 (ISA)", .internal_name = "mach32_isa", - .flags = DEVICE_ISA, - .local = 2, - .init = mach8_init, - .close = mach_close, - .reset = NULL, - { .available = mach32_isa_available }, + .flags = DEVICE_ISA, + .local = 2, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + .available = mach32_isa_available, .speed_changed = mach_speed_changed, - .force_redraw = mach_force_redraw, - .config = mach32_config + .force_redraw = mach_force_redraw, + .config = mach32_config }; const device_t mach32_vlb_device = { - .name = "ATI Mach32 (VLB)", + .name = "ATI Mach32 (VLB)", .internal_name = "mach32_vlb", - .flags = DEVICE_VLB, - .local = 2, - .init = mach8_init, - .close = mach_close, - .reset = NULL, - { .available = mach32_vlb_available }, + .flags = DEVICE_VLB, + .local = 2, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + .available = mach32_vlb_available, .speed_changed = mach_speed_changed, - .force_redraw = mach_force_redraw, - .config = mach32_config + .force_redraw = mach_force_redraw, + .config = mach32_config }; const device_t mach32_mca_device = { - .name = "ATI Mach32 (MCA)", + .name = "ATI Mach32 (MCA)", .internal_name = "mach32_mca", - .flags = DEVICE_MCA, - .local = 2, - .init = mach8_init, - .close = mach_close, - .reset = NULL, - { .available = mach32_mca_available }, + .flags = DEVICE_MCA, + .local = 2, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + .available = mach32_mca_available, .speed_changed = mach_speed_changed, - .force_redraw = mach_force_redraw, - .config = mach32_config + .force_redraw = mach_force_redraw, + .config = mach32_config }; const device_t mach32_pci_device = { - .name = "ATI Mach32 (PCI)", + .name = "ATI Mach32 (PCI)", .internal_name = "mach32_pci", - .flags = DEVICE_PCI, - .local = 2, - .init = mach8_init, - .close = mach_close, - .reset = NULL, - { .available = mach32_pci_available }, + .flags = DEVICE_PCI, + .local = 2, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + .available = mach32_pci_available, .speed_changed = mach_speed_changed, - .force_redraw = mach_force_redraw, - .config = mach32_pci_config + .force_redraw = mach_force_redraw, + .config = mach32_pci_config }; const device_t mach32_onboard_pci_device = { - .name = "ATI Mach32 (PCI) On-Board", + .name = "ATI Mach32 (PCI) On-Board", .internal_name = "mach32_pci_onboard", - .flags = DEVICE_PCI, - .local = 2 | 0x100, - .init = mach8_init, - .close = mach_close, - .reset = NULL, - { .available = NULL }, + .flags = DEVICE_PCI, + .local = 2 | 0x100, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + .available = NULL, .speed_changed = mach_speed_changed, - .force_redraw = mach_force_redraw, - .config = mach32_pci_config + .force_redraw = mach_force_redraw, + .config = mach32_pci_config }; - diff --git a/src/video/vid_att20c49x_ramdac.c b/src/video/vid_att20c49x_ramdac.c index f13740d34..7815f79be 100644 --- a/src/video/vid_att20c49x_ramdac.c +++ b/src/video/vid_att20c49x_ramdac.c @@ -182,7 +182,7 @@ const device_t att490_ramdac_device = { .init = att49x_ramdac_init, .close = att49x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -196,7 +196,7 @@ const device_t att491_ramdac_device = { .init = att49x_ramdac_init, .close = att49x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -210,7 +210,7 @@ const device_t att492_ramdac_device = { .init = att49x_ramdac_init, .close = att49x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_att2xc498_ramdac.c b/src/video/vid_att2xc498_ramdac.c index 47eebccae..f52b1432f 100644 --- a/src/video/vid_att2xc498_ramdac.c +++ b/src/video/vid_att2xc498_ramdac.c @@ -183,7 +183,7 @@ const device_t att498_ramdac_device = { .init = att498_ramdac_init, .close = att498_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_av9194.c b/src/video/vid_av9194.c index e7cf75dee..951f3519c 100644 --- a/src/video/vid_av9194.c +++ b/src/video/vid_av9194.c @@ -103,7 +103,7 @@ const device_t av9194_device = { .init = av9194_init, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index a4459ce4c..473b10983 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -962,9 +962,7 @@ static const device_config_t bochs_vbe_config[] = { }, .default_int = 16 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -976,7 +974,7 @@ const device_t bochs_svga_device = { .init = bochs_vbe_init, .close = bochs_vbe_close, .reset = bochs_vbe_reset, - { .available = bochs_vbe_available }, + .available = bochs_vbe_available, .speed_changed = bochs_vbe_speed_changed, .force_redraw = bochs_vbe_force_redraw, .config = bochs_vbe_config diff --git a/src/video/vid_bt481_ramdac.c b/src/video/vid_bt481_ramdac.c index 6cf5f2b1b..d1c85dcfe 100644 --- a/src/video/vid_bt481_ramdac.c +++ b/src/video/vid_bt481_ramdac.c @@ -153,7 +153,7 @@ const device_t bt481_ramdac_device = { .init = bt481_ramdac_init, .close = bt481_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/vid_bt48x_ramdac.c index 6b0ec300b..d608750e3 100644 --- a/src/video/vid_bt48x_ramdac.c +++ b/src/video/vid_bt48x_ramdac.c @@ -538,7 +538,7 @@ const device_t bt484_ramdac_device = { .init = bt48x_ramdac_init, .close = bt48x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -552,7 +552,7 @@ const device_t att20c504_ramdac_device = { .init = bt48x_ramdac_init, .close = bt48x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -566,7 +566,7 @@ const device_t bt485_ramdac_device = { .init = bt48x_ramdac_init, .close = bt48x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -580,7 +580,7 @@ const device_t att20c505_ramdac_device = { .init = bt48x_ramdac_init, .close = bt48x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -594,7 +594,7 @@ const device_t bt485a_ramdac_device = { .init = bt48x_ramdac_init, .close = bt48x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index c58c319df..375830f3c 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -914,9 +914,7 @@ const device_config_t cga_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -928,7 +926,7 @@ const device_t cga_device = { .init = cga_standalone_init, .close = cga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = cga_speed_changed, .force_redraw = NULL, .config = cga_config @@ -942,7 +940,7 @@ const device_t cga_pravetz_device = { .init = cga_pravetz_init, .close = cga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = cga_speed_changed, .force_redraw = NULL, .config = cga_config diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 5d41dc4a7..de66a37aa 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -2567,7 +2567,7 @@ const device_t chips_69000_device = { .init = chips_69000_init, .close = chips_69000_close, .reset = chips_69000_reset, - { .available = chips_69000_available }, + .available = chips_69000_available, .speed_changed = chips_69000_speed_changed, .force_redraw = chips_69000_force_redraw, .config = NULL @@ -2581,7 +2581,7 @@ const device_t chips_69000_onboard_device = { .init = chips_69000_init, .close = chips_69000_close, .reset = chips_69000_reset, - { .available = chips_69000_available }, + .available = chips_69000_available, .speed_changed = chips_69000_speed_changed, .force_redraw = chips_69000_force_redraw, .config = NULL diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 08a8c7677..51e4ba335 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4719,9 +4719,7 @@ static const device_config_t gd542x_config[] = { }, .default_int = 512 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5426_config[] = { @@ -4748,9 +4746,7 @@ static const device_config_t gd5426_config[] = { }, .default_int = 2048 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5428_onboard_config[] = { @@ -4777,9 +4773,7 @@ static const device_config_t gd5428_onboard_config[] = { }, .default_int = 2048 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5429_config[] = { @@ -4802,9 +4796,7 @@ static const device_config_t gd5429_config[] = { }, .default_int = 2 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5440_onboard_config[] = { @@ -4827,9 +4819,7 @@ static const device_config_t gd5440_onboard_config[] = { }, .default_int = 2 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5434_config[] = { @@ -4856,9 +4846,7 @@ static const device_config_t gd5434_config[] = { }, .default_int = 4 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5434_onboard_config[] = { @@ -4885,9 +4873,7 @@ static const device_config_t gd5434_onboard_config[] = { }, .default_int = 4 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5480_config[] = { @@ -4910,9 +4896,7 @@ static const device_config_t gd5480_config[] = { }, .default_int = 4 }, - { - .type = -1 - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -4924,7 +4908,7 @@ const device_t gd5401_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5401_available }, + .available = gd5401_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = NULL, @@ -4938,7 +4922,7 @@ const device_t gd5402_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5402_available }, + .available = gd5402_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = NULL, @@ -4952,7 +4936,7 @@ const device_t gd5402_onboard_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = NULL, @@ -4966,7 +4950,7 @@ const device_t gd5420_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5420_available }, + .available = gd5420_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd542x_config, @@ -4980,7 +4964,7 @@ const device_t gd5422_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5422_available }, /* Common BIOS between 5422 and 5424 */ + .available = gd5422_available, /* Common BIOS between 5422 and 5424 */ .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd542x_config, @@ -4994,7 +4978,7 @@ const device_t gd5424_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5422_available }, /* Common BIOS between 5422 and 5424 */ + .available = gd5422_available, /* Common BIOS between 5422 and 5424 */ .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd542x_config, @@ -5008,7 +4992,7 @@ const device_t gd5426_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_isa_available }, + .available = gd5428_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5023,7 +5007,7 @@ const device_t gd5426_diamond_speedstar_pro_a1_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5426_diamond_a1_available }, + .available = gd5426_diamond_a1_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5037,7 +5021,7 @@ const device_t gd5426_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_available }, + .available = gd5428_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5051,7 +5035,7 @@ const device_t gd5426_onboard_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = NULL @@ -5065,7 +5049,7 @@ const device_t gd5428_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_isa_available }, + .available = gd5428_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5079,7 +5063,7 @@ const device_t gd5428_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_available }, + .available = gd5428_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5094,7 +5078,7 @@ const device_t gd5428_diamond_speedstar_pro_b1_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_diamond_b1_available }, + .available = gd5428_diamond_b1_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5108,7 +5092,7 @@ const device_t gd5428_boca_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_boca_isa_available }, + .available = gd5428_boca_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5122,7 +5106,7 @@ const device_t gd5428_mca_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_mca_available }, + .available = gd5428_mca_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = NULL @@ -5136,7 +5120,7 @@ const device_t gd5426_mca_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5426_mca_available }, + .available = gd5426_mca_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5426_config @@ -5150,7 +5134,7 @@ const device_t gd5428_onboard_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5428_isa_available }, + .available = gd5428_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5428_onboard_config @@ -5164,7 +5148,7 @@ const device_t gd5428_vlb_onboard_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5428_onboard_config @@ -5178,7 +5162,7 @@ const device_t gd5429_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5429_available }, + .available = gd5429_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5192,7 +5176,7 @@ const device_t gd5429_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5429_available }, + .available = gd5429_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5207,7 +5191,7 @@ const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5430_diamond_a8_available }, + .available = gd5430_diamond_a8_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5221,7 +5205,7 @@ const device_t gd5430_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5430_orchid_vlb_available }, + .available = gd5430_orchid_vlb_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5235,7 +5219,7 @@ const device_t gd5430_onboard_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5249,7 +5233,7 @@ const device_t gd5430_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5430_available }, + .available = gd5430_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5263,7 +5247,7 @@ const device_t gd5430_onboard_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5277,7 +5261,7 @@ const device_t gd5434_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5434_isa_available }, + .available = gd5434_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5292,7 +5276,7 @@ const device_t gd5434_diamond_speedstar_64_a3_isa_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5434_diamond_a3_available }, + .available = gd5434_diamond_a3_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5306,7 +5290,7 @@ const device_t gd5434_onboard_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_onboard_config @@ -5320,7 +5304,7 @@ const device_t gd5434_vlb_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5430_orchid_vlb_available }, + .available = gd5430_orchid_vlb_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5334,7 +5318,7 @@ const device_t gd5434_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5434_available }, + .available = gd5434_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5348,7 +5332,7 @@ const device_t gd5436_onboard_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5362,7 +5346,7 @@ const device_t gd5436_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5436_available }, + .available = gd5436_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5376,7 +5360,7 @@ const device_t gd5440_onboard_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = NULL }, + .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5440_onboard_config @@ -5390,7 +5374,7 @@ const device_t gd5440_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5440_available }, + .available = gd5440_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5429_config @@ -5404,7 +5388,7 @@ const device_t gd5446_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5446_available }, + .available = gd5446_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5418,7 +5402,7 @@ const device_t gd5446_stb_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5446_stb_available }, + .available = gd5446_stb_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5434_config @@ -5432,7 +5416,7 @@ const device_t gd5480_pci_device = { .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, - { .available = gd5480_available }, + .available = gd5480_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, .config = gd5480_config diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index dcc72a76b..98d6adea7 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -425,9 +425,7 @@ static const device_config_t colorplus_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -439,7 +437,7 @@ const device_t colorplus_device = { .init = colorplus_standalone_init, .close = colorplus_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = colorplus_speed_changed, .force_redraw = NULL, .config = colorplus_config diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 430c7a64d..13fc399eb 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -481,7 +481,7 @@ const device_t compaq_cga_device = { .init = compaq_cga_init, .close = compaq_cga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = compaq_cga_speed_changed, .force_redraw = NULL, .config = cga_config @@ -495,7 +495,7 @@ const device_t compaq_cga_2_device = { .init = compaq_cga_init, .close = compaq_cga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = compaq_cga_speed_changed, .force_redraw = NULL, .config = cga_config diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index fccd4f629..faf4b9066 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1655,9 +1655,7 @@ static const device_config_t ega_config[] = { }, .default_int = 9 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1669,7 +1667,7 @@ const device_t ega_device = { .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = ega_standalone_available }, + .available = ega_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, .config = ega_config @@ -1683,7 +1681,7 @@ const device_t cpqega_device = { .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = cpqega_standalone_available }, + .available = cpqega_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, .config = ega_config @@ -1697,7 +1695,7 @@ const device_t sega_device = { .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = sega_standalone_available }, + .available = sega_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, .config = ega_config @@ -1711,7 +1709,7 @@ const device_t atiega800p_device = { .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = atiega800p_standalone_available }, + .available = atiega800p_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, .config = ega_config @@ -1725,7 +1723,7 @@ const device_t iskra_ega_device = { .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = iskra_ega_standalone_available }, + .available = iskra_ega_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, .config = ega_config @@ -1739,7 +1737,7 @@ const device_t et2000_device = { .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = et2000_standalone_available }, + .available = et2000_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, .config = ega_config diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index 45a2fc199..8585fedff 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -560,7 +560,7 @@ static const device_config_t et3000_config[] = { { .description = "" } } }, - { .type = CONFIG_END } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -572,7 +572,7 @@ const device_t et3000_isa_device = { .init = et3000_init, .close = et3000_close, .reset = NULL, - { .available = et3000_available }, + .available = et3000_available, .speed_changed = et3000_speed_changed, .force_redraw = et3000_force_redraw, .config = et3000_config diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index ad8cf5c46..169dc659b 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -981,9 +981,7 @@ static const device_config_t et4000_tc6058af_config[] = { { .files_no = 0 } }, }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1028,9 +1026,7 @@ static const device_config_t et4000_bios_config[] = { { .files_no = 0 } }, }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1059,9 +1055,7 @@ static const device_config_t et4000_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1073,7 +1067,7 @@ const device_t et4000_tc6058af_isa_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, .config = et4000_tc6058af_config @@ -1087,7 +1081,7 @@ const device_t et4000_isa_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, .config = et4000_bios_config @@ -1101,7 +1095,7 @@ const device_t et4000_mca_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = et4000_available }, + .available = et4000_available, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, .config = et4000_config @@ -1115,7 +1109,7 @@ const device_t et4000k_isa_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = et4000k_available }, + .available = et4000k_available, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, .config = et4000_config @@ -1129,7 +1123,7 @@ const device_t et4000k_tg286_isa_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = et4000k_available }, + .available = et4000k_available, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, .config = et4000_config @@ -1143,7 +1137,7 @@ const device_t et4000_kasan_isa_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = et4000_kasan_available }, + .available = et4000_kasan_available, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, .config = et4000_config diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 2f086f3c7..351dfba5d 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -2961,9 +2961,7 @@ static const device_config_t et4000w32p_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -2975,7 +2973,7 @@ const device_t et4000w32_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32_available }, + .available = et4000w32_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = NULL @@ -2989,7 +2987,7 @@ const device_t et4000w32_onboard_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32_available }, + .available = et4000w32_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = NULL @@ -3003,7 +3001,7 @@ const device_t et4000w32i_isa_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32i_isa_available }, + .available = et4000w32i_isa_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = NULL @@ -3017,7 +3015,7 @@ const device_t et4000w32i_vlb_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32i_vlb_available }, + .available = et4000w32i_vlb_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3031,7 +3029,7 @@ const device_t et4000w32p_videomagic_revb_vlb_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_videomagic_revb_vlb_available }, + .available = et4000w32p_videomagic_revb_vlb_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3045,7 +3043,7 @@ const device_t et4000w32p_videomagic_revb_pci_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_videomagic_revb_vlb_available }, + .available = et4000w32p_videomagic_revb_vlb_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3059,7 +3057,7 @@ const device_t et4000w32p_revc_vlb_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_revc_available }, + .available = et4000w32p_revc_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3073,7 +3071,7 @@ const device_t et4000w32p_revc_pci_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_revc_available }, + .available = et4000w32p_revc_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3087,7 +3085,7 @@ const device_t et4000w32p_noncardex_vlb_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_noncardex_available }, + .available = et4000w32p_noncardex_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3101,7 +3099,7 @@ const device_t et4000w32p_noncardex_pci_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_noncardex_available }, + .available = et4000w32p_noncardex_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3115,7 +3113,7 @@ const device_t et4000w32p_cardex_vlb_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_cardex_available }, + .available = et4000w32p_cardex_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3129,7 +3127,7 @@ const device_t et4000w32p_cardex_pci_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_cardex_available }, + .available = et4000w32p_cardex_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3143,7 +3141,7 @@ const device_t et4000w32p_vlb_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_available }, + .available = et4000w32p_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config @@ -3157,7 +3155,7 @@ const device_t et4000w32p_pci_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - { .available = et4000w32p_available }, + .available = et4000w32p_available, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index 772926e1e..c607cda14 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -631,7 +631,7 @@ const device_t f82c425_video_device = { .init = f82c425_init, .close = f82c425_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = f82c425_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index 4ae8e6fd1..c7a91aac6 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -826,7 +826,7 @@ const device_t genius_device = { .init = genius_init, .close = genius_close, .reset = NULL, - { .available = genius_available }, + .available = genius_available, .speed_changed = genius_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 2a725488d..8d99e9c7b 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -647,9 +647,7 @@ static const device_config_t hercules_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -661,7 +659,7 @@ const device_t hercules_device = { .init = hercules_init, .close = hercules_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = speed_changed, .force_redraw = NULL, .config = hercules_config diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 429632f19..1b6b74033 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -732,9 +732,7 @@ static const device_config_t herculesplus_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -746,7 +744,7 @@ const device_t herculesplus_device = { .init = herculesplus_init, .close = herculesplus_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = speed_changed, .force_redraw = NULL, .config = herculesplus_config diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index f349864df..3ed9e2bce 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1731,7 +1731,7 @@ static const device_config_t v7_vga_1024i_config[] = { { .description = "" } } }, - { .type = CONFIG_END } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ht216_32_standalone_config[] = { @@ -1748,7 +1748,7 @@ static const device_config_t ht216_32_standalone_config[] = { { .description = "" } } }, - { .type = CONFIG_END } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -1760,7 +1760,7 @@ const device_t g2_gc205_device = { .init = g2_gc205_init, .close = ht216_close, .reset = NULL, - { .available = g2_gc205_available }, + .available = g2_gc205_available, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, .config = NULL @@ -1774,7 +1774,7 @@ const device_t v7_vga_1024i_device = { .init = v7_vga_1024i_init, .close = ht216_close, .reset = NULL, - { .available = v7_vga_1024i_available }, + .available = v7_vga_1024i_available, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, .config = v7_vga_1024i_config @@ -1788,7 +1788,7 @@ const device_t ht216_32_pb410a_device = { .init = ht216_pb410a_init, .close = ht216_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, .config = NULL @@ -1802,7 +1802,7 @@ const device_t ht216_32_standalone_device = { .init = ht216_standalone_init, .close = ht216_close, .reset = NULL, - { .available = ht216_standalone_available }, + .available = ht216_standalone_available, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, .config = ht216_32_standalone_config @@ -1816,7 +1816,7 @@ const device_t radius_svga_multiview_isa_device = { .init = radius_svga_multiview_init, .close = ht216_close, .reset = NULL, - { .available = radius_svga_multiview_available }, + .available = radius_svga_multiview_available, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, .config = NULL @@ -1830,7 +1830,7 @@ const device_t radius_svga_multiview_mca_device = { .init = radius_svga_multiview_init, .close = ht216_close, .reset = NULL, - { .available = radius_svga_multiview_available }, + .available = radius_svga_multiview_available, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, .config = NULL diff --git a/src/video/vid_ibm_rgb528_ramdac.c b/src/video/vid_ibm_rgb528_ramdac.c index 1b19a3a0f..dcdbbb25b 100644 --- a/src/video/vid_ibm_rgb528_ramdac.c +++ b/src/video/vid_ibm_rgb528_ramdac.c @@ -982,7 +982,7 @@ const device_t ibm_rgb528_ramdac_device = { .init = ibm_rgb528_ramdac_init, .close = ibm_rgb528_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_icd2061.c b/src/video/vid_icd2061.c index 4c23d6ec5..7b80a5484 100644 --- a/src/video/vid_icd2061.c +++ b/src/video/vid_icd2061.c @@ -179,7 +179,7 @@ const device_t icd2061_device = { .init = icd2061_init, .close = icd2061_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -193,7 +193,7 @@ const device_t ics9161_device = { .init = icd2061_init, .close = icd2061_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_ics2494.c b/src/video/vid_ics2494.c index e85b4539e..350a490cc 100644 --- a/src/video/vid_ics2494.c +++ b/src/video/vid_ics2494.c @@ -168,7 +168,7 @@ const device_t ics2494an_305_device = { .init = ics2494_init, .close = ics2494_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -182,7 +182,7 @@ const device_t ati18810_device = { .init = ics2494_init, .close = ics2494_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -196,7 +196,7 @@ const device_t ati18811_0_device = { .init = ics2494_init, .close = ics2494_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -210,7 +210,7 @@ const device_t ati18811_1_device = { .init = ics2494_init, .close = ics2494_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_ics2595.c b/src/video/vid_ics2595.c index ecb414f2b..b5da3d7e2 100644 --- a/src/video/vid_ics2595.c +++ b/src/video/vid_ics2595.c @@ -129,7 +129,7 @@ const device_t ics2595_device = { .init = ics2595_init, .close = ics2595_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index c7602ffd0..a77ad09c3 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -1090,7 +1090,7 @@ const device_t im1024_device = { .init = im1024_init, .close = im1024_close, .reset = NULL, - { .available = im1024_available }, + .available = im1024_available, .speed_changed = im1024_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index e3f37ec65..0abb4a6c2 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -1053,7 +1053,7 @@ const device_t incolor_device = { .init = incolor_init, .close = incolor_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 702fb7e32..edadb4e46 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -379,9 +379,7 @@ static const device_config_t mda_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -393,7 +391,7 @@ const device_t mda_device = { .init = mda_standalone_init, .close = mda_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = mda_speed_changed, .force_redraw = NULL, .config = mda_config diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index ee422fd3f..a0d92ef9e 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -6872,7 +6872,7 @@ static const device_config_t mystique_config[] = { }, .default_int = 8 }, - { .type = CONFIG_END } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -6899,7 +6899,7 @@ static const device_config_t millennium_ii_config[] = { }, .default_int = 8 }, - { .type = CONFIG_END } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -6911,7 +6911,7 @@ const device_t millennium_device = { .init = mystique_init, .close = mystique_close, .reset = NULL, - { .available = millennium_available }, + .available = millennium_available, .speed_changed = mystique_speed_changed, .force_redraw = mystique_force_redraw, .config = mystique_config @@ -6925,7 +6925,7 @@ const device_t mystique_device = { .init = mystique_init, .close = mystique_close, .reset = NULL, - { .available = mystique_available }, + .available = mystique_available, .speed_changed = mystique_speed_changed, .force_redraw = mystique_force_redraw, .config = mystique_config @@ -6939,7 +6939,7 @@ const device_t mystique_220_device = { .init = mystique_init, .close = mystique_close, .reset = NULL, - { .available = mystique_220_available }, + .available = mystique_220_available, .speed_changed = mystique_speed_changed, .force_redraw = mystique_force_redraw, .config = mystique_config @@ -6953,7 +6953,7 @@ const device_t millennium_ii_device = { .init = mystique_init, .close = mystique_close, .reset = NULL, - { .available = millennium_ii_available }, + .available = millennium_ii_available, .speed_changed = mystique_speed_changed, .force_redraw = mystique_force_redraw, .config = millennium_ii_config @@ -6968,7 +6968,7 @@ const device_t productiva_g100_device = { .init = mystique_init, .close = mystique_close, .reset = NULL, - { .available = matrox_g100_available }, + .available = matrox_g100_available, .speed_changed = mystique_speed_changed, .force_redraw = mystique_force_redraw, .config = millennium_ii_config diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 32c103a8b..3cb7426b8 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -682,9 +682,7 @@ const device_config_t nga_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -696,7 +694,7 @@ const device_t nga_device = { .init = nga_init, .close = nga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = nga_speed_changed, .force_redraw = NULL, .config = nga_config diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 715ba0df3..c7d42275d 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -589,9 +589,7 @@ static const device_config_t oti067_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t oti067_ama932j_config[] = { @@ -614,9 +612,7 @@ static const device_config_t oti067_ama932j_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t oti077_acer100t_config[] = { @@ -643,9 +639,7 @@ static const device_config_t oti077_acer100t_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t oti077_config[] = { @@ -672,9 +666,7 @@ static const device_config_t oti077_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -686,7 +678,7 @@ const device_t oti037c_device = { .init = oti_init, .close = oti_close, .reset = NULL, - { .available = oti037c_available }, + .available = oti037c_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, .config = NULL @@ -700,7 +692,7 @@ const device_t oti067_device = { .init = oti_init, .close = oti_close, .reset = NULL, - { .available = oti067_077_available }, + .available = oti067_077_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, .config = oti067_config @@ -714,7 +706,7 @@ const device_t oti067_m300_device = { .init = oti_init, .close = oti_close, .reset = NULL, - { .available = oti067_m300_available }, + .available = oti067_m300_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, .config = oti067_config @@ -728,7 +720,7 @@ const device_t oti067_ama932j_device = { .init = oti_init, .close = oti_close, .reset = NULL, - { .available = oti067_ama932j_available }, + .available = oti067_ama932j_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, .config = oti067_ama932j_config @@ -742,7 +734,7 @@ const device_t oti077_acer100t_device = { .init = oti_init, .close = oti_close, .reset = NULL, - { .available = oti077_acer100t_available }, + .available = oti077_acer100t_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, .config = oti077_acer100t_config @@ -757,7 +749,7 @@ const device_t oti077_device = { .init = oti_init, .close = oti_close, .reset = NULL, - { .available = oti067_077_available }, + .available = oti067_077_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, .config = oti077_config diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index 9ac94169c..d430d2e14 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -666,9 +666,7 @@ const device_config_t ogc_m24_config[] = { .type = CONFIG_BINARY, .default_int = 1, }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -680,7 +678,7 @@ const device_t ogc_m24_device = { .init = ogc_init, .close = ogc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ogc_speed_changed, .force_redraw = NULL, .config = ogc_m24_config @@ -694,7 +692,7 @@ const device_t ogc_device = { .init = ogc_init, .close = ogc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = ogc_speed_changed, .force_redraw = NULL, .config = cga_config diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 27e98d32d..8e3241efd 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -712,7 +712,7 @@ const device_t paradise_pvga1a_pc2086_device = { .init = paradise_pvga1a_pc2086_init, .close = paradise_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = NULL @@ -726,7 +726,7 @@ const device_t paradise_pvga1a_pc3086_device = { .init = paradise_pvga1a_pc3086_init, .close = paradise_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = NULL @@ -753,9 +753,7 @@ static const device_config_t paradise_pvga1a_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -767,7 +765,7 @@ const device_t paradise_pvga1a_ncr3302_device = { .init = paradise_pvga1a_ncr3302_init, .close = paradise_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = paradise_pvga1a_config @@ -781,7 +779,7 @@ const device_t paradise_pvga1a_device = { .init = paradise_pvga1a_standalone_init, .close = paradise_close, .reset = NULL, - { .available = paradise_pvga1a_standalone_available }, + .available = paradise_pvga1a_standalone_available, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = paradise_pvga1a_config @@ -795,7 +793,7 @@ const device_t paradise_wd90c11_megapc_device = { .init = paradise_wd90c11_megapc_init, .close = paradise_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = NULL @@ -809,7 +807,7 @@ const device_t paradise_wd90c11_device = { .init = paradise_wd90c11_standalone_init, .close = paradise_close, .reset = NULL, - { .available = paradise_wd90c11_standalone_available }, + .available = paradise_wd90c11_standalone_available, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = NULL @@ -840,9 +838,7 @@ static const device_config_t paradise_wd90c30_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -854,7 +850,7 @@ const device_t paradise_wd90c30_device = { .init = paradise_wd90c30_standalone_init, .close = paradise_close, .reset = NULL, - { .available = paradise_wd90c30_standalone_available }, + .available = paradise_wd90c30_standalone_available, .speed_changed = paradise_speed_changed, .force_redraw = paradise_force_redraw, .config = paradise_wd90c30_config diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 354c7e265..5cb35dc4e 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2743,7 +2743,7 @@ const device_t pgc_device = { .init = pgc_standalone_init, .close = pgc_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = pgc_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index e82763d15..b6e0085f8 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -405,9 +405,7 @@ static const device_config_t rtg3105_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -436,9 +434,7 @@ static const device_config_t rtg3106_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -450,7 +446,7 @@ const device_t realtek_rtg3105_device = { .init = rtg_init, .close = rtg_close, .reset = NULL, - { .available = rtg3105_available }, + .available = rtg3105_available, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, .config = rtg3105_config @@ -464,7 +460,7 @@ const device_t realtek_rtg3106_device = { .init = rtg_init, .close = rtg_close, .reset = NULL, - { .available = rtg3106_available }, + .available = rtg3106_available, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, .config = rtg3106_config diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7839a602a..7e3b7a2ef 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -10544,97 +10544,98 @@ s3_force_redraw(void *priv) } static const device_config_t s3_orchid_86c911_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1, - .selection = { - { .description = "512 KB", - .value = 0 }, - { .description = "1 MB", - .value = 1 }, - { .description = "" } } }, - { .type = CONFIG_END } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1, + .selection = { + { .description = "512 KB", .value = 0 }, + { .description = "1 MB", .value = 1 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_9fx_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { - { .description = "1 MB", - .value = 1 }, - { .description = "2 MB", - .value = 2 }, - /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ - { - .description = "" } } }, - { .type = CONFIG_END } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + /* Trio64 also supports 4 MB, however the Number Nine BIOS does not */ + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_phoenix_trio32_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { - { .description = "512 KB", - .value = 0 }, - { .description = "1 MB", - .value = 1 }, - { .description = "2 MB", - .value = 2 }, - { .description = "" } } }, - { .type = CONFIG_END } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { .description = "512 KB", .value = 0 }, + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_standard_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { .description = "1 MB", - .value = 1 }, - { .description = "2 MB", - .value = 2 }, - { .description = "4 MB", - .value = 4 }, - { .description = "" } } }, - { .type = CONFIG_END } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_968_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { .description = "1 MB", - .value = 1 }, - { .description = "2 MB", - .value = 2 }, - { .description = "4 MB", - .value = 4 }, - { .description = "8 MB", - .value = 8 }, - { .description = "" } } }, - { .type = CONFIG_END } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "8 MB", .value = 8 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_standard_config2[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { .description = "2 MB", - .value = 2 }, - { .description = "4 MB", - .value = 4 }, - { .description = "" } } }, - { .type = CONFIG_END } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; const device_t s3_orchid_86c911_isa_device = { @@ -10645,7 +10646,7 @@ const device_t s3_orchid_86c911_isa_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_orchid_86c911_available }, + .available = s3_orchid_86c911_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_orchid_86c911_config @@ -10659,7 +10660,7 @@ const device_t s3_diamond_stealth_vram_isa_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth_vram_available }, + .available = s3_diamond_stealth_vram_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_orchid_86c911_config @@ -10673,7 +10674,7 @@ const device_t s3_ami_86c924_isa_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_ami_86c924_available }, + .available = s3_ami_86c924_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_orchid_86c911_config @@ -10687,7 +10688,7 @@ const device_t s3_spea_mirage_86c801_isa_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_spea_mirage_86c801_available }, + .available = s3_spea_mirage_86c801_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10701,7 +10702,7 @@ const device_t s3_86c805_onboard_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10715,7 +10716,7 @@ const device_t s3_spea_mirage_86c805_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_spea_mirage_86c805_available }, + .available = s3_spea_mirage_86c805_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10729,7 +10730,7 @@ const device_t s3_mirocrystal_8s_805_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_mirocrystal_8s_805_available }, + .available = s3_mirocrystal_8s_805_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10743,7 +10744,7 @@ const device_t s3_mirocrystal_10sd_805_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_mirocrystal_10sd_805_available }, + .available = s3_mirocrystal_10sd_805_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10757,7 +10758,7 @@ const device_t s3_phoenix_86c801_isa_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_86c80x_available }, + .available = s3_phoenix_86c80x_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10771,7 +10772,7 @@ const device_t s3_phoenix_86c805_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_86c80x_available }, + .available = s3_phoenix_86c80x_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10785,7 +10786,7 @@ const device_t s3_metheus_86c928_isa_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_metheus_86c928_available }, + .available = s3_metheus_86c928_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -10799,7 +10800,7 @@ const device_t s3_metheus_86c928_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_metheus_86c928_available }, + .available = s3_metheus_86c928_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -10813,7 +10814,7 @@ const device_t s3_spea_mercury_lite_86c928_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_spea_mercury_lite_pci_available }, + .available = s3_spea_mercury_lite_pci_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_orchid_86c911_config @@ -10827,7 +10828,7 @@ const device_t s3_mirocrystal_20sd_864_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_mirocrystal_20sd_864_vlb_available }, + .available = s3_mirocrystal_20sd_864_vlb_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10841,7 +10842,7 @@ const device_t s3_bahamas64_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_bahamas64_available }, + .available = s3_bahamas64_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10855,7 +10856,7 @@ const device_t s3_bahamas64_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_bahamas64_available }, + .available = s3_bahamas64_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10869,7 +10870,7 @@ const device_t s3_mirocrystal_20sv_964_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_mirocrystal_20sv_964_vlb_available }, + .available = s3_mirocrystal_20sv_964_vlb_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10883,7 +10884,7 @@ const device_t s3_mirocrystal_20sv_964_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_mirocrystal_20sv_964_pci_available }, + .available = s3_mirocrystal_20sv_964_pci_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -10897,7 +10898,7 @@ const device_t s3_diamond_stealth64_964_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth64_964_available }, + .available = s3_diamond_stealth64_964_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -10911,7 +10912,7 @@ const device_t s3_diamond_stealth64_964_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth64_964_available }, + .available = s3_diamond_stealth64_964_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -10925,7 +10926,7 @@ const device_t s3_diamond_stealth64_968_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth64_968_available }, + .available = s3_diamond_stealth64_968_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config2 @@ -10939,7 +10940,7 @@ const device_t s3_diamond_stealth64_968_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth64_968_available }, + .available = s3_diamond_stealth64_968_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config2 @@ -10953,7 +10954,7 @@ const device_t s3_9fx_771_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_9fx_771_available }, + .available = s3_9fx_771_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_968_config @@ -10967,7 +10968,7 @@ const device_t s3_phoenix_vision968_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_vision968_available }, + .available = s3_phoenix_vision968_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -10981,7 +10982,7 @@ const device_t s3_mirovideo_40sv_ergo_968_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_mirovideo_40sv_ergo_968_pci_available }, + .available = s3_mirovideo_40sv_ergo_968_pci_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -10995,7 +10996,7 @@ const device_t s3_spea_mercury_p64v_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_spea_mercury_p64v_pci_available }, + .available = s3_spea_mercury_p64v_pci_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11009,7 +11010,7 @@ const device_t s3_9fx_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_9fx_available }, + .available = s3_9fx_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -11023,7 +11024,7 @@ const device_t s3_9fx_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_9fx_available }, + .available = s3_9fx_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -11037,7 +11038,7 @@ const device_t s3_phoenix_trio32_onboard_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11051,7 +11052,7 @@ const device_t s3_phoenix_trio32_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_trio32_available }, + .available = s3_phoenix_trio32_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11065,7 +11066,7 @@ const device_t s3_phoenix_trio32_onboard_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11079,7 +11080,7 @@ const device_t s3_phoenix_trio32_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_trio32_available }, + .available = s3_phoenix_trio32_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11093,7 +11094,7 @@ const device_t s3_diamond_stealth_se_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth_se_available }, + .available = s3_diamond_stealth_se_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11107,7 +11108,7 @@ const device_t s3_diamond_stealth_se_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth_se_available }, + .available = s3_diamond_stealth_se_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11121,7 +11122,7 @@ const device_t s3_phoenix_trio64_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_trio64_available }, + .available = s3_phoenix_trio64_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11135,7 +11136,7 @@ const device_t s3_phoenix_trio64_onboard_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11149,7 +11150,7 @@ const device_t s3_phoenix_trio64_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_trio64_available }, + .available = s3_phoenix_trio64_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11163,7 +11164,7 @@ const device_t s3_stb_powergraph_64_video_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_stb_powergraph_64_video_available }, + .available = s3_stb_powergraph_64_video_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_phoenix_trio32_config @@ -11177,7 +11178,7 @@ const device_t s3_phoenix_trio64vplus_onboard_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11191,7 +11192,7 @@ const device_t s3_phoenix_trio64vplus_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_trio64vplus_available }, + .available = s3_phoenix_trio64vplus_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11205,7 +11206,7 @@ const device_t s3_cardex_trio64vplus_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_cardex_trio64vplus_available }, + .available = s3_cardex_trio64vplus_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11219,7 +11220,7 @@ const device_t s3_phoenix_vision864_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_vision864_available }, + .available = s3_phoenix_vision864_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11233,7 +11234,7 @@ const device_t s3_phoenix_vision864_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_vision864_available }, + .available = s3_phoenix_vision864_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11247,7 +11248,7 @@ const device_t s3_9fx_531_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_9fx_531_available }, + .available = s3_9fx_531_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -11261,7 +11262,7 @@ const device_t s3_phoenix_vision868_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_phoenix_vision868_available }, + .available = s3_phoenix_vision868_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11275,7 +11276,7 @@ const device_t s3_diamond_stealth64_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth64_764_available }, + .available = s3_diamond_stealth64_764_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -11289,7 +11290,7 @@ const device_t s3_diamond_stealth64_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_diamond_stealth64_764_available }, + .available = s3_diamond_stealth64_764_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -11303,7 +11304,7 @@ const device_t s3_spea_mirage_p64_vlb_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_spea_mirage_p64_vlb_available }, + .available = s3_spea_mirage_p64_vlb_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_9fx_config @@ -11317,7 +11318,7 @@ const device_t s3_elsa_winner2000_pro_x_964_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_elsa_winner2000_pro_x_964_available }, + .available = s3_elsa_winner2000_pro_x_964_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_968_config @@ -11331,7 +11332,7 @@ const device_t s3_elsa_winner2000_pro_x_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_elsa_winner2000_pro_x_available }, + .available = s3_elsa_winner2000_pro_x_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_968_config @@ -11345,7 +11346,7 @@ const device_t s3_trio64v2_dx_pci_device = { .init = s3_init, .close = s3_close, .reset = s3_reset, - { .available = s3_trio64v2_dx_available }, + .available = s3_trio64v2_dx_available, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config @@ -11359,7 +11360,7 @@ const device_t s3_trio64v2_dx_onboard_pci_device = { .init = s3_init, .close = s3_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, .config = s3_standard_config diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 08a01dbd6..3c61f3a57 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -4734,9 +4734,7 @@ static const device_config_t s3_virge_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -4777,9 +4775,7 @@ static const device_config_t s3_virge_stb_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -4797,9 +4793,7 @@ static const device_config_t s3_virge_357_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -4836,9 +4830,7 @@ static const device_config_t s3_trio3d2x_config[] = { .type = CONFIG_BINARY, .default_int = 1 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -4850,7 +4842,7 @@ const device_t s3_virge_325_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_325_available }, + .available = s3_virge_325_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4864,7 +4856,7 @@ const device_t s3_virge_325_onboard_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4878,7 +4870,7 @@ const device_t s3_diamond_stealth_2000_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_325_diamond_available }, + .available = s3_virge_325_diamond_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4892,7 +4884,7 @@ const device_t s3_mirocrystal_3d_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_mirocrystal_3d_available }, + .available = s3_mirocrystal_3d_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4906,7 +4898,7 @@ const device_t s3_diamond_stealth_3000_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_988_diamond_available }, + .available = s3_virge_988_diamond_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_stb_config @@ -4920,7 +4912,7 @@ const device_t s3_stb_velocity_3d_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_988_stb_available }, + .available = s3_virge_988_stb_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_stb_config @@ -4934,7 +4926,7 @@ const device_t s3_virge_375_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_375_available }, + .available = s3_virge_375_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4948,7 +4940,7 @@ const device_t s3_virge_375_onboard_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = NULL }, + .available = NULL, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4962,7 +4954,7 @@ const device_t s3_diamond_stealth_2000pro_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_375_diamond_available }, + .available = s3_virge_375_diamond_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4976,7 +4968,7 @@ const device_t s3_virge_385_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_385_available }, + .available = s3_virge_385_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_config @@ -4990,7 +4982,7 @@ const device_t s3_virge_357_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_357_available }, + .available = s3_virge_357_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_357_config @@ -5004,7 +4996,7 @@ const device_t s3_virge_357_agp_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_357_available }, + .available = s3_virge_357_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_357_config @@ -5018,7 +5010,7 @@ const device_t s3_diamond_stealth_4000_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_357_diamond_available }, + .available = s3_virge_357_diamond_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_357_config @@ -5032,7 +5024,7 @@ const device_t s3_diamond_stealth_4000_agp_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_virge_357_diamond_available }, + .available = s3_virge_357_diamond_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_virge_357_config @@ -5046,7 +5038,7 @@ const device_t s3_trio3d2x_pci_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_trio3d2x_available }, + .available = s3_trio3d2x_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_trio3d2x_config @@ -5060,7 +5052,7 @@ const device_t s3_trio3d2x_agp_device = { .init = s3_virge_init, .close = s3_virge_close, .reset = s3_virge_reset, - { .available = s3_trio3d2x_available }, + .available = s3_trio3d2x_available, .speed_changed = s3_virge_speed_changed, .force_redraw = s3_virge_force_redraw, .config = s3_trio3d2x_config diff --git a/src/video/vid_sc1148x_ramdac.c b/src/video/vid_sc1148x_ramdac.c index 24ca4aeec..0ebcb49b6 100644 --- a/src/video/vid_sc1148x_ramdac.c +++ b/src/video/vid_sc1148x_ramdac.c @@ -156,7 +156,7 @@ const device_t sc11483_ramdac_device = { .init = sc1148x_ramdac_init, .close = sc1148x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -170,7 +170,7 @@ const device_t sc11487_ramdac_device = { .init = sc1148x_ramdac_init, .close = sc1148x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -184,7 +184,7 @@ const device_t sc11484_nors2_ramdac_device = { .init = sc1148x_ramdac_init, .close = sc1148x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -198,7 +198,7 @@ const device_t sc11486_ramdac_device = { .init = sc1148x_ramdac_init, .close = sc1148x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/vid_sc1502x_ramdac.c index 7315c65ad..1c7d4014d 100644 --- a/src/video/vid_sc1502x_ramdac.c +++ b/src/video/vid_sc1502x_ramdac.c @@ -249,7 +249,7 @@ const device_t sc1502x_ramdac_device = { .init = sc1502x_ramdac_init, .close = sc1502x_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_sdac_ramdac.c b/src/video/vid_sdac_ramdac.c index 83796506e..4e6deacdc 100644 --- a/src/video/vid_sdac_ramdac.c +++ b/src/video/vid_sdac_ramdac.c @@ -313,7 +313,7 @@ const device_t gendac_ramdac_device = { .init = sdac_ramdac_init, .close = sdac_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -327,7 +327,7 @@ const device_t tseng_ics5301_ramdac_device = { .init = sdac_ramdac_init, .close = sdac_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -341,7 +341,7 @@ const device_t tseng_ics5341_ramdac_device = { .init = sdac_ramdac_init, .close = sdac_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -355,7 +355,7 @@ const device_t sdac_ramdac_device = { .init = sdac_ramdac_init, .close = sdac_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 56f8b99aa..161331918 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -951,9 +951,7 @@ device_config_t sigma_config[] = { } }, }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -965,7 +963,7 @@ const device_t sigma_device = { .init = sigma_init, .close = sigma_close, .reset = NULL, - { .available = sigma_available }, + .available = sigma_available, .speed_changed = sigma_speed_changed, .force_redraw = NULL, .config = sigma_config diff --git a/src/video/vid_stg_ramdac.c b/src/video/vid_stg_ramdac.c index 187139b3b..85d492ce7 100644 --- a/src/video/vid_stg_ramdac.c +++ b/src/video/vid_stg_ramdac.c @@ -263,7 +263,7 @@ const device_t stg_ramdac_device = { .init = stg_ramdac_init, .close = stg_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 9ec7e6105..efab288de 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -3382,9 +3382,7 @@ static const device_config_t tgui9440_config[] = { }, .default_int = 2 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t tgui96xx_config[] = { @@ -3411,9 +3409,7 @@ static const device_config_t tgui96xx_config[] = { }, .default_int = 4 }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -3425,7 +3421,7 @@ const device_t tgui9400cxi_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9400cxi_available }, + .available = tgui9400cxi_available, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3439,7 +3435,7 @@ const device_t tgui9440_vlb_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_vlb_available }, + .available = tgui9440_vlb_available, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3453,7 +3449,7 @@ const device_t tgui9440_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_pci_available }, + .available = tgui9440_pci_available, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3467,7 +3463,7 @@ const device_t tgui9440_onboard_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3481,7 +3477,7 @@ const device_t tgui9660_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui96xx_available }, + .available = tgui96xx_available, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui96xx_config @@ -3495,7 +3491,7 @@ const device_t tgui9660_onboard_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui96xx_config @@ -3509,7 +3505,7 @@ const device_t tgui9680_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui96xx_available }, + .available = tgui96xx_available, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui96xx_config diff --git a/src/video/vid_ti_cf62011.c b/src/video/vid_ti_cf62011.c index f23cb7396..fcc046cb4 100644 --- a/src/video/vid_ti_cf62011.c +++ b/src/video/vid_ti_cf62011.c @@ -266,7 +266,7 @@ const device_t ibm_ps1_2121_device = { .init = vid_init, .close = vid_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vid_speed_changed, .force_redraw = vid_force_redraw, .config = NULL diff --git a/src/video/vid_tkd8001_ramdac.c b/src/video/vid_tkd8001_ramdac.c index 4108b9a4e..c8ad1c421 100644 --- a/src/video/vid_tkd8001_ramdac.c +++ b/src/video/vid_tkd8001_ramdac.c @@ -129,7 +129,7 @@ const device_t tkd8001_ramdac_device = { .init = tkd8001_ramdac_init, .close = tkd8001_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index eb0d1a780..9f329a604 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -544,78 +544,76 @@ static const device_config_t tvga_config[] = { } } }, - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format off }; const device_t tvga8900b_device = { - .name = "Trident TVGA 8900B", + .name = "Trident TVGA 8900B", .internal_name = "tvga8900b", - .flags = DEVICE_ISA, - .local = TVGA8900B_ID, - .init = tvga_init, - .close = tvga_close, - .reset = NULL, - { .available = tvga8900b_available }, + .flags = DEVICE_ISA, + .local = TVGA8900B_ID, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + .available = tvga8900b_available, .speed_changed = tvga_speed_changed, - .force_redraw = tvga_force_redraw, - .config = tvga_config + .force_redraw = tvga_force_redraw, + .config = tvga_config }; const device_t tvga8900d_device = { - .name = "Trident TVGA 8900D", + .name = "Trident TVGA 8900D", .internal_name = "tvga8900d", - .flags = DEVICE_ISA, - .local = TVGA8900CLD_ID, - .init = tvga_init, - .close = tvga_close, - .reset = NULL, - { .available = tvga8900d_available }, + .flags = DEVICE_ISA, + .local = TVGA8900CLD_ID, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + .available = tvga8900d_available, .speed_changed = tvga_speed_changed, - .force_redraw = tvga_force_redraw, - .config = tvga_config + .force_redraw = tvga_force_redraw, + .config = tvga_config }; const device_t tvga8900dr_device = { - .name = "Trident TVGA 8900D-R", + .name = "Trident TVGA 8900D-R", .internal_name = "tvga8900dr", - .flags = DEVICE_ISA, - .local = TVGA8900CLD_ID | 0x0100, - .init = tvga_init, - .close = tvga_close, - .reset = NULL, - { .available = tvga8900dr_available }, + .flags = DEVICE_ISA, + .local = TVGA8900CLD_ID | 0x0100, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + .available = tvga8900dr_available, .speed_changed = tvga_speed_changed, - .force_redraw = tvga_force_redraw, - .config = tvga_config + .force_redraw = tvga_force_redraw, + .config = tvga_config }; const device_t tvga9000b_device = { - .name = "Trident TVGA 9000B", + .name = "Trident TVGA 9000B", .internal_name = "tvga9000b", - .flags = DEVICE_ISA, - .local = TVGA9000B_ID, - .init = tvga_init, - .close = tvga_close, - .reset = NULL, - { .available = tvga9000b_available }, + .flags = DEVICE_ISA, + .local = TVGA9000B_ID, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + .available = tvga9000b_available, .speed_changed = tvga_speed_changed, - .force_redraw = tvga_force_redraw, - .config = NULL + .force_redraw = tvga_force_redraw, + .config = NULL }; const device_t nec_sv9000_device = { - .name = "NEC SV9000 (Trident TVGA 9000B)", + .name = "NEC SV9000 (Trident TVGA 9000B)", .internal_name = "nec_sv9000", - .flags = DEVICE_ISA, - .local = TVGA9000B_ID | 0x100, - .init = tvga_init, - .close = tvga_close, - .reset = NULL, - { .available = tvga9000b_nec_sv9000_available }, + .flags = DEVICE_ISA, + .local = TVGA9000B_ID | 0x100, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + .available = tvga9000b_nec_sv9000_available, .speed_changed = tvga_speed_changed, - .force_redraw = tvga_force_redraw, - .config = NULL + .force_redraw = tvga_force_redraw, + .config = NULL }; diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c index 6c001b461..bd5a83fd0 100644 --- a/src/video/vid_tvp3026_ramdac.c +++ b/src/video/vid_tvp3026_ramdac.c @@ -733,7 +733,7 @@ const device_t tvp3026_ramdac_device = { .init = tvp3026_ramdac_init, .close = tvp3026_ramdac_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 881a3c6fd..ad66192ac 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -194,7 +194,7 @@ const device_t vga_device = { .init = vga_init, .close = vga_close, .reset = NULL, - { .available = vga_available }, + .available = vga_available, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL @@ -208,7 +208,7 @@ const device_t ps1vga_device = { .init = ps1vga_init, .close = vga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL @@ -222,7 +222,7 @@ const device_t ps1vga_mca_device = { .init = ps1vga_init, .close = vga_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index a9981333b..bf3b63736 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -1423,9 +1423,7 @@ static const device_config_t voodoo_config[] = { .default_int = 1 }, #endif - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1437,7 +1435,7 @@ const device_t voodoo_device = { .init = voodoo_init, .close = voodoo_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = voodoo_speed_changed, .force_redraw = voodoo_force_blit, .config = voodoo_config diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 4fa27e2e4..93b557fec 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -3228,9 +3228,7 @@ static const device_config_t banshee_sgram_config[] = { .default_int = 1 }, #endif - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t banshee_sgram_16mbonly_config[] = { @@ -3283,9 +3281,7 @@ static const device_config_t banshee_sgram_16mbonly_config[] = { .default_int = 1 }, #endif - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t banshee_sdram_config[] = { @@ -3338,9 +3334,7 @@ static const device_config_t banshee_sdram_config[] = { .default_int = 1 }, #endif - { - .type = CONFIG_END - } + { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on @@ -3743,7 +3737,7 @@ const device_t voodoo_banshee_device = { .init = banshee_init, .close = banshee_close, .reset = NULL, - { .available = banshee_available }, + .available = banshee_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sgram_config @@ -3757,7 +3751,7 @@ const device_t creative_voodoo_banshee_device = { .init = creative_banshee_init, .close = banshee_close, .reset = NULL, - { .available = creative_banshee_available }, + .available = creative_banshee_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3771,7 +3765,7 @@ const device_t voodoo_3_1000_device = { .init = v3_1000_init, .close = banshee_close, .reset = NULL, - { .available = v3_1000_available }, + .available = v3_1000_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sgram_config @@ -3785,7 +3779,7 @@ const device_t voodoo_3_1000_agp_device = { .init = v3_1000_agp_init, .close = banshee_close, .reset = NULL, - { .available = v3_1000_agp_available }, + .available = v3_1000_agp_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sgram_16mbonly_config @@ -3799,7 +3793,7 @@ const device_t voodoo_3_2000_device = { .init = v3_2000_init, .close = banshee_close, .reset = NULL, - { .available = v3_2000_available }, + .available = v3_2000_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3813,7 +3807,7 @@ const device_t voodoo_3_2000_agp_device = { .init = v3_2000_agp_init, .close = banshee_close, .reset = NULL, - { .available = v3_2000_agp_available }, + .available = v3_2000_agp_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3827,7 +3821,7 @@ const device_t voodoo_3_2000_agp_onboard_8m_device = { .init = v3_2000_agp_onboard_init, .close = banshee_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sgram_config @@ -3841,7 +3835,7 @@ const device_t voodoo_3_3000_device = { .init = v3_3000_init, .close = banshee_close, .reset = NULL, - { .available = v3_3000_available }, + .available = v3_3000_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3855,7 +3849,7 @@ const device_t voodoo_3_3000_agp_device = { .init = v3_3000_agp_init, .close = banshee_close, .reset = NULL, - { .available = v3_3000_agp_available }, + .available = v3_3000_agp_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3869,7 +3863,7 @@ const device_t voodoo_3_3500_agp_ntsc_device = { .init = v3_3500_agp_ntsc_init, .close = banshee_close, .reset = NULL, - { .available = v3_3500_agp_ntsc_available }, + .available = v3_3500_agp_ntsc_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3883,7 +3877,7 @@ const device_t voodoo_3_3500_agp_pal_device = { .init = v3_3500_agp_pal_init, .close = banshee_close, .reset = NULL, - { .available = v3_3500_agp_pal_available }, + .available = v3_3500_agp_pal_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3897,7 +3891,7 @@ const device_t compaq_voodoo_3_3500_agp_device = { .init = compaq_v3_3500_agp_init, .close = banshee_close, .reset = NULL, - { .available = compaq_v3_3500_agp_available }, + .available = compaq_v3_3500_agp_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3911,7 +3905,7 @@ const device_t voodoo_3_3500_se_agp_device = { .init = v3_3500_se_agp_init, .close = banshee_close, .reset = NULL, - { .available = v3_3500_se_agp_available }, + .available = v3_3500_se_agp_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3925,7 +3919,7 @@ const device_t voodoo_3_3500_si_agp_device = { .init = v3_3500_si_agp_init, .close = banshee_close, .reset = NULL, - { .available = v3_3500_si_agp_available }, + .available = v3_3500_si_agp_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3939,7 +3933,7 @@ const device_t velocity_100_agp_device = { .init = velocity_100_agp_init, .close = banshee_close, .reset = NULL, - { .available = velocity_100_available }, + .available = velocity_100_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sdram_config @@ -3953,7 +3947,7 @@ const device_t velocity_200_agp_device = { .init = velocity_200_agp_init, .close = banshee_close, .reset = NULL, - { .available = velocity_200_available }, + .available = velocity_200_available, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, .config = banshee_sgram_16mbonly_config diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 600fa21a8..a52bad4ee 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -1004,7 +1004,7 @@ const device_t wy700_device = { .init = wy700_init, .close = wy700_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = wy700_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 8bdc72fc6..862dbd1cf 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -3813,7 +3813,7 @@ const device_t xga_device = { .init = xga_init, .close = xga_close, .reset = xga_reset, - { .available = xga_available }, + .available = xga_available, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, .config = xga_mca_configuration @@ -3827,7 +3827,7 @@ const device_t xga_isa_device = { .init = xga_init, .close = xga_close, .reset = xga_reset, - { .available = xga_available }, + .available = xga_available, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, .config = xga_isa_configuration @@ -3841,7 +3841,7 @@ const device_t inmos_isa_device = { .init = svga_xga_init, .close = xga_close, .reset = xga_reset, - { .available = inmos_xga_available }, + .available = inmos_xga_available, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, .config = xga_inmos_isa_configuration From 4e6f29a7d585452bdede8c4ee866adf5f015ced2 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 7 Jan 2025 00:42:06 -0500 Subject: [PATCH 0181/1190] malloc to calloc --- src/chipset/82c100.c | 3 +-- src/chipset/acc2168.c | 3 +-- src/chipset/ali1409.c | 3 +-- src/chipset/ali1429.c | 3 +-- src/chipset/ali1435.c | 3 +-- src/chipset/ali1489.c | 3 +-- src/chipset/ali1531.c | 3 +-- src/chipset/ali1541.c | 3 +-- src/chipset/ali1543.c | 3 +-- src/chipset/ali1621.c | 3 +-- src/chipset/ali6117.c | 3 +-- src/chipset/contaq_82c59x.c | 3 +-- src/chipset/cs4031.c | 3 +-- src/chipset/cs8230.c | 3 +-- src/chipset/et6000.c | 3 +-- src/chipset/gc100.c | 3 +-- src/chipset/headland.c | 3 +-- src/chipset/ims8848.c | 3 +-- src/chipset/intel_420ex.c | 3 +-- src/chipset/intel_4x0.c | 4 +--- src/chipset/intel_82335.c | 3 +-- src/chipset/intel_i450kx.c | 4 ++-- src/chipset/intel_piix.c | 3 +-- src/chipset/intel_sio.c | 3 +-- src/chipset/neat.c | 3 +-- src/chipset/olivetti_eva.c | 3 +-- src/chipset/opti283.c | 3 +-- src/chipset/opti291.c | 3 +-- src/chipset/opti495.c | 3 +-- src/chipset/opti499.c | 3 +-- src/chipset/opti5x7.c | 3 +-- src/chipset/opti822.c | 3 +-- src/chipset/opti895.c | 3 +-- src/chipset/scamp.c | 3 +-- src/chipset/scat.c | 3 +-- src/chipset/sis_5571_old.c | 3 +-- src/chipset/sis_85c310.c | 3 +-- src/chipset/sis_85c496.c | 3 +-- src/chipset/sis_85c4xx.c | 3 +-- src/chipset/stpc.c | 9 +++----- src/chipset/umc_8886.c | 3 +-- src/chipset/umc_hb4.c | 3 +-- src/chipset/via_apollo.c | 3 +-- src/chipset/via_pipc.c | 3 +-- src/chipset/via_vt82c49x.c | 3 +-- src/chipset/via_vt82c505.c | 5 ++-- src/chipset/vl82c480.c | 3 +-- src/chipset/wd76c10.c | 2 +- src/device/cartridge.c | 6 ++--- src/device/cassette.c | 4 +--- src/device/clock_ics9xxx.c | 6 ++--- src/device/hasp.c | 3 +-- src/device/hwm_gl518sm.c | 3 +-- src/device/hwm_lm75.c | 3 +-- src/device/hwm_lm78.c | 3 +-- src/device/hwm_vt82c686.c | 3 +-- src/device/i2c.c | 6 ++--- src/device/i2c_gpio.c | 3 +-- src/device/isamem.c | 3 +-- src/device/isapnp.c | 5 ++-- src/device/isartc.c | 3 +-- src/device/kbc_at.c | 6 ++--- src/device/keyboard_xt.c | 3 +-- src/device/mouse_bus.c | 3 +-- src/device/mouse_microtouch_touchscreen.c | 3 +-- src/device/mouse_serial.c | 3 +-- src/device/pci_bridge.c | 3 +-- src/device/phoenix_486_jumper.c | 3 +-- src/device/serial.c | 3 +-- src/device/serial_passthrough.c | 3 +-- src/device/smbus_ali7101.c | 2 +- src/device/smbus_piix4.c | 3 +-- src/device/smbus_sis5595.c | 3 +-- src/disk/hdc_esdi_at.c | 3 +-- src/disk/hdc_esdi_mca.c | 3 +-- src/disk/hdc_ide_cmd640.c | 3 +-- src/disk/hdc_ide_cmd646.c | 3 +-- src/disk/hdc_ide_opti611.c | 3 +-- src/disk/hdc_ide_sff8038i.c | 3 +-- src/disk/hdc_ide_w83769f.c | 3 +-- src/disk/hdc_st506_at.c | 3 +-- src/disk/hdc_st506_xt.c | 3 +-- src/disk/hdc_xta.c | 3 +-- src/disk/hdc_xtide.c | 28 ++++++++--------------- src/floppy/fdc.c | 3 +-- src/floppy/fdc_magitronic.c | 3 +-- src/floppy/fdc_monster.c | 2 +- src/floppy/fdc_pii15xb.c | 3 +-- src/floppy/fdd_86f.c | 6 ++--- src/floppy/fdd_fdi.c | 4 +--- src/floppy/fdd_imd.c | 3 +-- src/floppy/fdd_img.c | 3 +-- src/floppy/fdd_mfm.c | 3 +-- src/floppy/fdd_pcjs.c | 3 +-- src/floppy/fdd_td0.c | 3 +-- src/game/gameport.c | 8 ++----- src/machine/m_amstrad.c | 12 ++++------ src/machine/m_at_compaq.c | 3 +-- src/machine/m_at_t3100e_vid.c | 3 +-- src/machine/m_pcjr.c | 3 +-- src/machine/m_ps1.c | 3 +-- src/machine/m_ps1_hdc.c | 3 +-- src/machine/m_ps2_isa.c | 3 +-- src/machine/m_tandy.c | 6 ++--- src/machine/m_xt_olivetti.c | 15 ++++-------- src/machine/m_xt_t1000_vid.c | 3 +-- src/machine/m_xt_zenith.c | 3 +-- src/mem/catalyst_flash.c | 3 +-- src/mem/i2c_eeprom.c | 3 +-- src/mem/intel_flash.c | 3 +-- src/mem/smram.c | 5 ++-- src/mem/spd.c | 3 +-- src/mem/sst_flash.c | 3 +-- src/network/net_3c501.c | 3 +-- src/network/net_3c503.c | 3 +-- src/network/net_dp8390.c | 6 ++--- src/network/net_ne2000.c | 6 ++--- src/network/net_pcnet.c | 3 +-- src/network/net_plip.c | 3 +-- src/network/net_slirp.c | 5 ++-- src/network/net_wd8003.c | 3 +-- src/nvr_ps2.c | 3 +-- src/printer/prt_escp.c | 5 ++-- src/printer/prt_ps.c | 9 +++----- src/printer/prt_text.c | 6 ++--- src/qt/win_opendir.c | 6 ++--- src/scsi/scsi_aha154x.c | 3 +-- src/scsi/scsi_buslogic.c | 3 +-- src/scsi/scsi_ncr53c400.c | 8 ++----- src/scsi/scsi_ncr53c8xx.c | 5 +--- src/scsi/scsi_pcscsi.c | 10 ++------ src/scsi/scsi_spock.c | 3 +-- src/scsi/scsi_t128.c | 8 ++----- src/scsi/scsi_x54x.c | 18 +++++---------- src/sio/sio_82091aa.c | 3 +-- src/sio/sio_acc3221.c | 3 +-- src/sio/sio_ali5123.c | 3 +-- src/sio/sio_detect.c | 3 +-- src/sio/sio_f82c710.c | 3 +-- src/sio/sio_fdc37c669.c | 3 +-- src/sio/sio_fdc37c67x.c | 3 +-- src/sio/sio_fdc37c6xx.c | 3 +-- src/sio/sio_fdc37c93x.c | 6 ++--- src/sio/sio_fdc37m60x.c | 3 +-- src/sio/sio_it86x1f.c | 3 +-- src/sio/sio_pc87306.c | 3 +-- src/sio/sio_pc87307.c | 3 +-- src/sio/sio_pc87309.c | 3 +-- src/sio/sio_pc87311.c | 3 +-- src/sio/sio_pc87332.c | 3 +-- src/sio/sio_prime3b.c | 3 +-- src/sio/sio_prime3c.c | 3 +-- src/sio/sio_um8669f.c | 3 +-- src/sio/sio_vt82c686.c | 3 +-- src/sio/sio_w83787f.c | 3 +-- src/sio/sio_w83877f.c | 3 +-- src/sio/sio_w83977f.c | 3 +-- src/sound/midi.c | 9 +++----- src/sound/midi_fluidsynth.c | 3 +-- src/sound/midi_mt32.c | 3 +-- src/sound/midi_opl4.c | 3 +-- src/sound/midi_rtmidi.cpp | 6 ++--- src/sound/snd_ac97_codec.c | 3 +-- src/sound/snd_ac97_via.c | 3 +-- src/sound/snd_adlib.c | 3 +-- src/sound/snd_adlibgold.c | 3 +-- src/sound/snd_audiopci.c | 6 ++--- src/sound/snd_azt2316a.c | 9 +++----- src/sound/snd_cmi8x38.c | 3 +-- src/sound/snd_cms.c | 3 +-- src/sound/snd_cs423x.c | 6 ++--- src/sound/snd_emu8k.c | 6 ++--- src/sound/snd_gus.c | 6 ++--- src/sound/snd_lpt_dac.c | 3 +-- src/sound/snd_lpt_dss.c | 3 +-- src/sound/snd_opl2board.c | 3 +-- src/sound/snd_optimc.c | 3 +-- src/sound/snd_pas16.c | 3 +-- src/sound/snd_ps1.c | 3 +-- src/sound/snd_pssj.c | 9 +++----- src/sound/snd_sn76489.c | 9 +++----- src/sound/snd_ssi2001.c | 9 +++----- src/sound/snd_wss.c | 6 ++--- 183 files changed, 245 insertions(+), 493 deletions(-) diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c index 05c3522d8..a9d61b3b9 100644 --- a/src/chipset/82c100.c +++ b/src/chipset/82c100.c @@ -358,8 +358,7 @@ ct_82c100_init(UNUSED(const device_t *info)) { ct_82c100_t *dev; - dev = (ct_82c100_t *) malloc(sizeof(ct_82c100_t)); - memset(dev, 0x00, sizeof(ct_82c100_t)); + dev = (ct_82c100_t *) calloc(1, sizeof(ct_82c100_t)); ct_82c100_reset(dev); diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 982f50e82..dbbdc99f6 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -184,8 +184,7 @@ acc2168_close(void *priv) static void * acc2168_init(UNUSED(const device_t *info)) { - acc2168_t *dev = (acc2168_t *) malloc(sizeof(acc2168_t)); - memset(dev, 0, sizeof(acc2168_t)); + acc2168_t *dev = (acc2168_t *) calloc(1, sizeof(acc2168_t)); device_add(&port_92_device); io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, dev); diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c index 8cda1a22b..5644d4077 100644 --- a/src/chipset/ali1409.c +++ b/src/chipset/ali1409.c @@ -163,8 +163,7 @@ ali1409_close(void *priv) static void * ali1409_init(const device_t *info) { - ali1409_t *dev = (ali1409_t *) malloc(sizeof(ali1409_t)); - memset(dev, 0, sizeof(ali1409_t)); + ali1409_t *dev = (ali1409_t *) calloc(1, sizeof(ali1409_t)); dev->cfg_locked = 1; diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index 4a6a5cfa9..e2478078f 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -331,8 +331,7 @@ ali1429_defaults(ali1429_t *dev) static void * ali1429_init(const device_t *info) { - ali1429_t *dev = (ali1429_t *) malloc(sizeof(ali1429_t)); - memset(dev, 0, sizeof(ali1429_t)); + ali1429_t *dev = (ali1429_t *) calloc(1, sizeof(ali1429_t)); dev->cfg_locked = 1; GREEN = info->local; diff --git a/src/chipset/ali1435.c b/src/chipset/ali1435.c index 8360267c9..ff096ac55 100644 --- a/src/chipset/ali1435.c +++ b/src/chipset/ali1435.c @@ -282,8 +282,7 @@ ali1435_close(void *priv) static void * ali1435_init(UNUSED(const device_t *info)) { - ali1435_t *dev = (ali1435_t *) malloc(sizeof(ali1435_t)); - memset(dev, 0, sizeof(ali1435_t)); + ali1435_t *dev = (ali1435_t *) calloc(1, sizeof(ali1435_t)); dev->cfg_locked = 1; diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index c61dd1511..fc51bbed2 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -470,8 +470,7 @@ ali1489_close(void *priv) static void * ali1489_init(UNUSED(const device_t *info)) { - ali1489_t *dev = (ali1489_t *) malloc(sizeof(ali1489_t)); - memset(dev, 0, sizeof(ali1489_t)); + ali1489_t *dev = (ali1489_t *) calloc(1, sizeof(ali1489_t)); /* M1487/M1489 22h Index Port diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index 1ff0689ad..e765e6d45 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -369,8 +369,7 @@ ali1531_close(void *priv) static void * ali1531_init(UNUSED(const device_t *info)) { - ali1531_t *dev = (ali1531_t *) malloc(sizeof(ali1531_t)); - memset(dev, 0, sizeof(ali1531_t)); + ali1531_t *dev = (ali1531_t *) calloc(1, sizeof(ali1531_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev, &dev->pci_slot); diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c index 3d7c1c546..eed6ddbc5 100644 --- a/src/chipset/ali1541.c +++ b/src/chipset/ali1541.c @@ -643,8 +643,7 @@ ali1541_close(void *priv) static void * ali1541_init(UNUSED(const device_t *info)) { - ali1541_t *dev = (ali1541_t *) malloc(sizeof(ali1541_t)); - memset(dev, 0, sizeof(ali1541_t)); + ali1541_t *dev = (ali1541_t *) calloc(1, sizeof(ali1541_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev, &dev->pci_slot); diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 2b9c93cb4..69a8990e9 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1599,8 +1599,7 @@ ali1543_close(void *priv) static void * ali1543_init(const device_t *info) { - ali1543_t *dev = (ali1543_t *) malloc(sizeof(ali1543_t)); - memset(dev, 0, sizeof(ali1543_t)); + ali1543_t *dev = (ali1543_t *) calloc(1, sizeof(ali1543_t)); /* Device 02: M1533 Southbridge */ pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev, &dev->pci_slot); diff --git a/src/chipset/ali1621.c b/src/chipset/ali1621.c index 96748ce34..d44c0f5a9 100644 --- a/src/chipset/ali1621.c +++ b/src/chipset/ali1621.c @@ -669,8 +669,7 @@ ali1621_close(void *priv) static void * ali1621_init(UNUSED(const device_t *info)) { - ali1621_t *dev = (ali1621_t *) malloc(sizeof(ali1621_t)); - memset(dev, 0, sizeof(ali1621_t)); + ali1621_t *dev = (ali1621_t *) calloc(1, sizeof(ali1621_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev, &dev->pci_slot); diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index 2d66ba9d1..c351a0cfa 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -466,8 +466,7 @@ ali6117_init(const device_t *info) ali6117_log("ALI6117: init()\n"); - ali6117_t *dev = (ali6117_t *) malloc(sizeof(ali6117_t)); - memset(dev, 0, sizeof(ali6117_t)); + ali6117_t *dev = (ali6117_t *) calloc(1, sizeof(ali6117_t)); dev->local = info->local; diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index 90667c42f..1981fd11c 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -322,8 +322,7 @@ contaq_82c59x_close(void *priv) static void * contaq_82c59x_init(const device_t *info) { - contaq_82c59x_t *dev = (contaq_82c59x_t *) malloc(sizeof(contaq_82c59x_t)); - memset(dev, 0x00, sizeof(contaq_82c59x_t)); + contaq_82c59x_t *dev = (contaq_82c59x_t *) calloc(1, sizeof(contaq_82c59x_t)); dev->green = info->local; diff --git a/src/chipset/cs4031.c b/src/chipset/cs4031.c index b482fa254..cfec9ad30 100644 --- a/src/chipset/cs4031.c +++ b/src/chipset/cs4031.c @@ -164,8 +164,7 @@ cs4031_close(void *priv) static void * cs4031_init(UNUSED(const device_t *info)) { - cs4031_t *dev = (cs4031_t *) malloc(sizeof(cs4031_t)); - memset(dev, 0, sizeof(cs4031_t)); + cs4031_t *dev = (cs4031_t *) calloc(1, sizeof(cs4031_t)); dev->port_92 = device_add(&port_92_device); diff --git a/src/chipset/cs8230.c b/src/chipset/cs8230.c index 62852b88d..0374a44a6 100644 --- a/src/chipset/cs8230.c +++ b/src/chipset/cs8230.c @@ -157,8 +157,7 @@ cs8230_close(void *priv) static void * cs8230_init(UNUSED(const device_t *info)) { - cs8230_t *cs8230 = (cs8230_t *) malloc(sizeof(cs8230_t)); - memset(cs8230, 0, sizeof(cs8230_t)); + cs8230_t *cs8230 = (cs8230_t *) calloc(1, sizeof(cs8230_t)); io_sethandler(0x0022, 0x0002, cs8230_read, NULL, NULL, cs8230_write, NULL, NULL, cs8230); diff --git a/src/chipset/et6000.c b/src/chipset/et6000.c index 608f2cc9b..14ebf852e 100644 --- a/src/chipset/et6000.c +++ b/src/chipset/et6000.c @@ -137,8 +137,7 @@ et6000_close(void *priv) static void * et6000_init(UNUSED(const device_t *info)) { - et6000_t *dev = (et6000_t *) malloc(sizeof(et6000_t)); - memset(dev, 0, sizeof(et6000_t)); + et6000_t *dev = (et6000_t *) calloc(1, sizeof(et6000_t)); /* Port 92h */ device_add(&port_92_device); diff --git a/src/chipset/gc100.c b/src/chipset/gc100.c index fc2321fae..23455b952 100644 --- a/src/chipset/gc100.c +++ b/src/chipset/gc100.c @@ -208,8 +208,7 @@ gc100_close(void *priv) static void * gc100_init(const device_t *info) { - gc100_t *dev = (gc100_t *) malloc(sizeof(gc100_t)); - memset(dev, 0, sizeof(gc100_t)); + gc100_t *dev = (gc100_t *) calloc(1, sizeof(gc100_t)); dev->reg[0x2] = 0xff; dev->reg[0x3] = 0x0; diff --git a/src/chipset/headland.c b/src/chipset/headland.c index 9d7cf97c7..1172d105d 100644 --- a/src/chipset/headland.c +++ b/src/chipset/headland.c @@ -594,8 +594,7 @@ headland_init(const device_t *info) headland_t *dev; int ht386 = 0; - dev = (headland_t *) malloc(sizeof(headland_t)); - memset(dev, 0x00, sizeof(headland_t)); + dev = (headland_t *) calloc(1, sizeof(headland_t)); dev->has_cri = (info->local & HEADLAND_HAS_CRI); dev->has_sleep = (info->local & HEADLAND_HAS_SLEEP); diff --git a/src/chipset/ims8848.c b/src/chipset/ims8848.c index 0ce3a5e44..094ee31f8 100644 --- a/src/chipset/ims8848.c +++ b/src/chipset/ims8848.c @@ -381,8 +381,7 @@ ims8848_close(void *priv) static void * ims8848_init(UNUSED(const device_t *info)) { - ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t)); - memset(dev, 0, sizeof(ims8848_t)); + ims8848_t *dev = (ims8848_t *) calloc(1, sizeof(ims8848_t)); device_add(&port_92_device); diff --git a/src/chipset/intel_420ex.c b/src/chipset/intel_420ex.c index 7b069cce3..662fd0509 100644 --- a/src/chipset/intel_420ex.c +++ b/src/chipset/intel_420ex.c @@ -533,8 +533,7 @@ i420ex_speed_changed(void *priv) static void * i420ex_init(const device_t *info) { - i420ex_t *dev = (i420ex_t *) malloc(sizeof(i420ex_t)); - memset(dev, 0, sizeof(i420ex_t)); + i420ex_t *dev = (i420ex_t *) calloc(1, sizeof(i420ex_t)); dev->smram = smram_add(); diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 36303deb7..f9d6af150 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1608,11 +1608,9 @@ i4x0_close(void *priv) static void * i4x0_init(const device_t *info) { - i4x0_t *dev = (i4x0_t *) malloc(sizeof(i4x0_t)); + i4x0_t *dev = (i4x0_t *) calloc(1, sizeof(i4x0_t)); uint8_t *regs; - memset(dev, 0, sizeof(i4x0_t)); - dev->smram_low = smram_add(); dev->smram_high = smram_add(); diff --git a/src/chipset/intel_82335.c b/src/chipset/intel_82335.c index cc7f07c3a..bd53e0d05 100644 --- a/src/chipset/intel_82335.c +++ b/src/chipset/intel_82335.c @@ -171,8 +171,7 @@ intel_82335_close(void *priv) static void * intel_82335_init(UNUSED(const device_t *info)) { - intel_82335_t *dev = (intel_82335_t *) malloc(sizeof(intel_82335_t)); - memset(dev, 0, sizeof(intel_82335_t)); + intel_82335_t *dev = (intel_82335_t *) calloc(1, sizeof(intel_82335_t)); memset(dev->regs, 0, sizeof(dev->regs)); diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index 1dfd6f315..34cc6a62f 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -799,8 +799,8 @@ i450kx_close(void *priv) static void * i450kx_init(UNUSED(const device_t *info)) { - i450kx_t *dev = (i450kx_t *) malloc(sizeof(i450kx_t)); - memset(dev, 0, sizeof(i450kx_t)); + i450kx_t *dev = (i450kx_t *) calloc(1, sizeof(i450kx_t)); + pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev, &dev->pb_slot); /* Device 19h: Intel 450KX PCI Bridge PB */ pci_add_card(PCI_ADD_NORTHBRIDGE_SEC, mc_read, mc_write, dev, &dev->mc_slot); /* Device 14h: Intel 450KX Memory Controller MC */ diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index e52492df9..6969d3274 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1538,8 +1538,7 @@ piix_speed_changed(void *priv) static void * piix_init(const device_t *info) { - piix_t *dev = (piix_t *) malloc(sizeof(piix_t)); - memset(dev, 0, sizeof(piix_t)); + piix_t *dev = (piix_t *) calloc(1, sizeof(piix_t)); dev->type = info->local & 0x0f; /* If (dev->type == 4) and (dev->rev & 0x08), then this is PIIX4E. */ diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index c66b5ce04..9b6d28ab1 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -508,8 +508,7 @@ sio_speed_changed(void *priv) static void * sio_init(const device_t *info) { - sio_t *dev = (sio_t *) malloc(sizeof(sio_t)); - memset(dev, 0, sizeof(sio_t)); + sio_t *dev = (sio_t *) calloc(1, sizeof(sio_t)); pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev, &dev->pci_slot); diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 6f7dc5be3..069fa87e4 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -906,8 +906,7 @@ neat_init(UNUSED(const device_t *info)) uint8_t j; /* Create an instance. */ - dev = (neat_t *) malloc(sizeof(neat_t)); - memset(dev, 0x00, sizeof(neat_t)); + dev = (neat_t *) calloc(1, sizeof(neat_t)); /* Get configured I/O address. */ j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; diff --git a/src/chipset/olivetti_eva.c b/src/chipset/olivetti_eva.c index bdb5440c9..7defac6ae 100644 --- a/src/chipset/olivetti_eva.c +++ b/src/chipset/olivetti_eva.c @@ -134,8 +134,7 @@ olivetti_eva_close(void *priv) static void * olivetti_eva_init(UNUSED(const device_t *info)) { - olivetti_eva_t *dev = (olivetti_eva_t *) malloc(sizeof(olivetti_eva_t)); - memset(dev, 0, sizeof(olivetti_eva_t)); + olivetti_eva_t *dev = (olivetti_eva_t *) calloc(1, sizeof(olivetti_eva_t)); /* GA98 registers */ dev->reg_065 = 0x00; diff --git a/src/chipset/opti283.c b/src/chipset/opti283.c index b708eb0ab..395ad4212 100644 --- a/src/chipset/opti283.c +++ b/src/chipset/opti283.c @@ -284,8 +284,7 @@ opti283_close(void *priv) static void * opti283_init(UNUSED(const device_t *info)) { - opti283_t *dev = (opti283_t *) malloc(sizeof(opti283_t)); - memset(dev, 0x00, sizeof(opti283_t)); + opti283_t *dev = (opti283_t *) calloc(1, sizeof(opti283_t)); io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); io_sethandler(0x0023, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); diff --git a/src/chipset/opti291.c b/src/chipset/opti291.c index 0ff037434..91b9010e2 100644 --- a/src/chipset/opti291.c +++ b/src/chipset/opti291.c @@ -138,8 +138,7 @@ opti291_close(void *priv) static void * opti291_init(UNUSED(const device_t *info)) { - opti291_t *dev = (opti291_t *) malloc(sizeof(opti291_t)); - memset(dev, 0, sizeof(opti291_t)); + opti291_t *dev = (opti291_t *) calloc(1, sizeof(opti291_t)); io_sethandler(0x022, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev); io_sethandler(0x024, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev); diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index f53ae0899..aa4e4b4c5 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -219,8 +219,7 @@ opti495_close(void *priv) static void * opti495_init(const device_t *info) { - opti495_t *dev = (opti495_t *) malloc(sizeof(opti495_t)); - memset(dev, 0, sizeof(opti495_t)); + opti495_t *dev = (opti495_t *) calloc(1, sizeof(opti495_t)); device_add(&port_92_device); diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index 81c5bee5a..d54e8184e 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -242,8 +242,7 @@ opti499_close(void *priv) static void * opti499_init(UNUSED(const device_t *info)) { - opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t)); - memset(dev, 0, sizeof(opti499_t)); + opti499_t *dev = (opti499_t *) calloc(1, sizeof(opti499_t)); device_add(&port_92_device); diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 015ffb9f4..03fde4173 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -172,8 +172,7 @@ opti5x7_close(void *priv) static void * opti5x7_init(const device_t *info) { - opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t)); - memset(dev, 0, sizeof(opti5x7_t)); + opti5x7_t *dev = (opti5x7_t *) calloc(1, sizeof(opti5x7_t)); dev->is_pci = info->local; diff --git a/src/chipset/opti822.c b/src/chipset/opti822.c index 9dd835412..471fbe393 100644 --- a/src/chipset/opti822.c +++ b/src/chipset/opti822.c @@ -394,8 +394,7 @@ opti822_close(void *priv) static void * opti822_init(UNUSED(const device_t *info)) { - opti822_t *dev = (opti822_t *) malloc(sizeof(opti822_t)); - memset(dev, 0, sizeof(opti822_t)); + opti822_t *dev = (opti822_t *) calloc(1, sizeof(opti822_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev, &dev->pci_slot); diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index 4ce31c362..cb55ef2a7 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -259,8 +259,7 @@ opti895_close(void *priv) static void * opti895_init(const device_t *info) { - opti895_t *dev = (opti895_t *) malloc(sizeof(opti895_t)); - memset(dev, 0, sizeof(opti895_t)); + opti895_t *dev = (opti895_t *) calloc(1, sizeof(opti895_t)); device_add(&port_92_device); diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 6a38f4ec2..8e7892c2e 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -1046,8 +1046,7 @@ static void * scamp_init(UNUSED(const device_t *info)) { uint32_t addr; - scamp_t *dev = (scamp_t *) malloc(sizeof(scamp_t)); - memset(dev, 0x00, sizeof(scamp_t)); + scamp_t *dev = (scamp_t *) calloc(1, sizeof(scamp_t)); dev->cfg_regs[CFG_ID] = ID_VL82C311; dev->cfg_enable = 1; diff --git a/src/chipset/scat.c b/src/chipset/scat.c index edbaf41e3..43f93649e 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1403,8 +1403,7 @@ scat_init(const device_t *info) uint32_t k; int sx; - dev = (scat_t *) malloc(sizeof(scat_t)); - memset(dev, 0x00, sizeof(scat_t)); + dev = (scat_t *) calloc(1, sizeof(scat_t)); dev->type = info->local; sx = (dev->type == 32) ? 1 : 0; diff --git a/src/chipset/sis_5571_old.c b/src/chipset/sis_5571_old.c index 422ed4bb8..495137aed 100644 --- a/src/chipset/sis_5571_old.c +++ b/src/chipset/sis_5571_old.c @@ -732,8 +732,7 @@ sis_5571_close(void *priv) static void * sis_5571_init(UNUSED(const device_t *info)) { - sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t)); - memset(dev, 0x00, sizeof(sis_5571_t)); + sis_5571_t *dev = (sis_5571_t *) calloc(1, sizeof(sis_5571_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot); pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot); diff --git a/src/chipset/sis_85c310.c b/src/chipset/sis_85c310.c index d62cc3b24..dfbd4b465 100644 --- a/src/chipset/sis_85c310.c +++ b/src/chipset/sis_85c310.c @@ -130,8 +130,7 @@ rabbit_close(void *priv) static void * rabbit_init(UNUSED(const device_t *info)) { - rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t)); - memset(dev, 0, sizeof(rabbit_t)); + rabbit_t *dev = (rabbit_t *) calloc(1, sizeof(rabbit_t)); io_sethandler(0x0022, 0x0002, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev); diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index 5ba315822..10bccc1c8 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -637,8 +637,7 @@ static void * sis_85c496_init(const device_t *info) { - sis_85c496_t *dev = malloc(sizeof(sis_85c496_t)); - memset(dev, 0x00, sizeof(sis_85c496_t)); + sis_85c496_t *dev = calloc(1, sizeof(sis_85c496_t)); dev->smram = smram_add(); diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 1f98ee8a6..6e26a4751 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -368,8 +368,7 @@ sis_85c4xx_close(void *priv) static void * sis_85c4xx_init(const device_t *info) { - sis_85c4xx_t *dev = (sis_85c4xx_t *) malloc(sizeof(sis_85c4xx_t)); - memset(dev, 0, sizeof(sis_85c4xx_t)); + sis_85c4xx_t *dev = (sis_85c4xx_t *) calloc(1, sizeof(sis_85c4xx_t)); dev->is_471 = (info->local >> 8) & 0xff; diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index 3bb3a7c2a..23cc56bd3 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -912,8 +912,7 @@ stpc_init(const device_t *info) { stpc_log("STPC: init()\n"); - stpc_t *dev = (stpc_t *) malloc(sizeof(stpc_t)); - memset(dev, 0, sizeof(stpc_t)); + stpc_t *dev = (stpc_t *) calloc(1, sizeof(stpc_t)); dev->local = info->local; @@ -963,8 +962,7 @@ stpc_serial_init(UNUSED(const device_t *info)) { stpc_log("STPC: serial_init()\n"); - stpc_serial_t *dev = (stpc_serial_t *) malloc(sizeof(stpc_serial_t)); - memset(dev, 0, sizeof(stpc_serial_t)); + stpc_serial_t *dev = (stpc_serial_t *) calloc(1, sizeof(stpc_serial_t)); dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); @@ -1076,8 +1074,7 @@ stpc_lpt_init(UNUSED(const device_t *info)) { stpc_log("STPC: lpt_init()\n"); - stpc_lpt_t *dev = (stpc_lpt_t *) malloc(sizeof(stpc_lpt_t)); - memset(dev, 0, sizeof(stpc_lpt_t)); + stpc_lpt_t *dev = (stpc_lpt_t *) calloc(1, sizeof(stpc_lpt_t)); stpc_lpt_reset(dev); diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index 30b0ecb71..f96480c2c 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -392,8 +392,7 @@ umc_8886_close(void *priv) static void * umc_8886_init(const device_t *info) { - umc_8886_t *dev = (umc_8886_t *) malloc(sizeof(umc_8886_t)); - memset(dev, 0, sizeof(umc_8886_t)); + umc_8886_t *dev = (umc_8886_t *) calloc(1, sizeof(umc_8886_t)); /* Device 12: UMC 8886xx */ pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index 98bdfc82c..889691988 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -450,8 +450,7 @@ ims8848_read(uint16_t addr, void *priv) static void * hb4_init(UNUSED(const device_t *info)) { - hb4_t *dev = (hb4_t *) malloc(sizeof(hb4_t)); - memset(dev, 0, sizeof(hb4_t)); + hb4_t *dev = (hb4_t *) calloc(1, sizeof(hb4_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev, &dev->pci_slot); /* Device 10: UMC 8881x */ diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index fa96c4927..110b1f8e1 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -725,8 +725,7 @@ via_apollo_reset(void *priv) static void * via_apollo_init(const device_t *info) { - via_apollo_t *dev = (via_apollo_t *) malloc(sizeof(via_apollo_t)); - memset(dev, 0, sizeof(via_apollo_t)); + via_apollo_t *dev = (via_apollo_t *) calloc(1, sizeof(via_apollo_t)); dev->smram = smram_add(); if (dev->id != VIA_8601) diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 3a6e6fc5c..dcfe41811 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -1627,8 +1627,7 @@ pipc_reset(void *priv) static void * pipc_init(const device_t *info) { - pipc_t *dev = (pipc_t *) malloc(sizeof(pipc_t)); - memset(dev, 0, sizeof(pipc_t)); + pipc_t *dev = (pipc_t *) calloc(1, sizeof(pipc_t)); pipc_log("PIPC: init()\n"); diff --git a/src/chipset/via_vt82c49x.c b/src/chipset/via_vt82c49x.c index f36dad2e7..3aaef55a6 100644 --- a/src/chipset/via_vt82c49x.c +++ b/src/chipset/via_vt82c49x.c @@ -342,8 +342,7 @@ vt82c49x_close(void *priv) static void * vt82c49x_init(const device_t *info) { - vt82c49x_t *dev = (vt82c49x_t *) malloc(sizeof(vt82c49x_t)); - memset(dev, 0x00, sizeof(vt82c49x_t)); + vt82c49x_t *dev = (vt82c49x_t *) calloc(1, sizeof(vt82c49x_t)); dev->smram_smm = smram_add(); dev->smram_low = smram_add(); diff --git a/src/chipset/via_vt82c505.c b/src/chipset/via_vt82c505.c index 8cb6c67a0..dbbb447c7 100644 --- a/src/chipset/via_vt82c505.c +++ b/src/chipset/via_vt82c505.c @@ -167,7 +167,7 @@ vt82c505_in(uint16_t addr, void *priv) static void vt82c505_reset(void *priv) { - vt82c505_t *dev = (vt82c505_t *) malloc(sizeof(vt82c505_t)); + vt82c505_t *dev = (vt82c505_t *) calloc(1, sizeof(vt82c505_t)); dev->pci_conf[0x04] = 0x07; dev->pci_conf[0x07] = 0x00; @@ -204,8 +204,7 @@ vt82c505_close(void *priv) static void * vt82c505_init(UNUSED(const device_t *info)) { - vt82c505_t *dev = (vt82c505_t *) malloc(sizeof(vt82c505_t)); - memset(dev, 0, sizeof(vt82c505_t)); + vt82c505_t *dev = (vt82c505_t *) calloc(1, sizeof(vt82c505_t)); pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev, &dev->pci_slot); diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 38a6bdfb9..496544c63 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -180,8 +180,7 @@ vl82c480_close(void *priv) static void * vl82c480_init(const device_t *info) { - vl82c480_t *dev = (vl82c480_t *) malloc(sizeof(vl82c480_t)); - memset(dev, 0, sizeof(vl82c480_t)); + vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index 6de921af1..9b13dc5da 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -884,7 +884,7 @@ wd76c10_init(const device_t *info) wd76c10_t *dev = (wd76c10_t *) calloc(1, sizeof(wd76c10_t)); uint32_t total_mem = mem_size << 10; uint32_t accum_mem = 0x00000000; - ram_bank_t *rb; + ram_bank_t *rb = NULL; /* Calculate the physical RAM banks. */ for (uint8_t i = 0; i < 4; i++) { diff --git a/src/device/cartridge.c b/src/device/cartridge.c index 22b36484a..d2e91ecb3 100644 --- a/src/device/cartridge.c +++ b/src/device/cartridge.c @@ -113,8 +113,7 @@ cart_image_load(int drive, char *fn) (void) !fread(&base, 1, 2, fp); base <<= 4; fseek(fp, 0x00000200, SEEK_SET); - carts[drive].buf = (uint8_t *) malloc(size); - memset(carts[drive].buf, 0x00, size); + carts[drive].buf = (uint8_t *) calloc(1, size); (void) !fread(carts[drive].buf, 1, size, fp); fclose(fp); } else { @@ -122,8 +121,7 @@ cart_image_load(int drive, char *fn) if (size == 32768) base += 0x8000; fseek(fp, 0x00000000, SEEK_SET); - carts[drive].buf = (uint8_t *) malloc(size); - memset(carts[drive].buf, 0x00, size); + carts[drive].buf = (uint8_t *) calloc(1, size); (void) !fread(carts[drive].buf, 1, size, fp); fclose(fp); } diff --git a/src/device/cassette.c b/src/device/cassette.c index 608de7463..ac79edff2 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -131,9 +131,7 @@ pc_cas_free(pc_cassette_t *cas) pc_cassette_t * pc_cas_new(void) { - pc_cassette_t *cas; - - cas = malloc(sizeof(pc_cassette_t)); + pc_cassette_t *cas = calloc(1, sizeof( pc_cassette_t)); if (cas == NULL) { return (NULL); diff --git a/src/device/clock_ics9xxx.c b/src/device/clock_ics9xxx.c index 263170741..02f033e9b 100644 --- a/src/device/clock_ics9xxx.c +++ b/src/device/clock_ics9xxx.c @@ -1181,8 +1181,7 @@ ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_ static void * ics9xxx_init(const device_t *info) { - ics9xxx_t *dev = (ics9xxx_t *) malloc(sizeof(ics9xxx_t)); - memset(dev, 0, sizeof(ics9xxx_t)); + ics9xxx_t *dev = (ics9xxx_t *) calloc(1, sizeof(ics9xxx_t)); dev->model_idx = info->local; dev->model = (ics9xxx_model_t *) &ics9xxx_models[dev->model_idx]; @@ -1267,8 +1266,7 @@ ics9xxx_close(void *priv) device_t * ics9xxx_get(uint8_t model) { - device_t *dev = (device_t *) malloc(sizeof(device_t)); - memset(dev, 0, sizeof(device_t)); + device_t *dev = (device_t *) calloc(1, sizeof(device_t)); dev->name = "ICS9xxx-xx Clock Generator"; dev->local = model; diff --git a/src/device/hasp.c b/src/device/hasp.c index 9873c3460..3834af4cd 100644 --- a/src/device/hasp.c +++ b/src/device/hasp.c @@ -305,8 +305,7 @@ hasp_read_status(void *priv) static void * hasp_init(void *lpt, int type) { - hasp_t *dev = malloc(sizeof(hasp_t)); - memset(dev, 0, sizeof(hasp_t)); + hasp_t *dev = calloc(1, sizeof(hasp_t)); hasp_log("HASP: init(%d)\n", type); diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index 23763ebb8..cfc16664a 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -282,8 +282,7 @@ gl518sm_close(void *priv) static void * gl518sm_init(const device_t *info) { - gl518sm_t *dev = (gl518sm_t *) malloc(sizeof(gl518sm_t)); - memset(dev, 0, sizeof(gl518sm_t)); + gl518sm_t *dev = (gl518sm_t *) calloc(1, sizeof(gl518sm_t)); dev->local = info->local; diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index 831d16ded..29fe2024f 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -216,8 +216,7 @@ lm75_close(void *priv) static void * lm75_init(const device_t *info) { - lm75_t *dev = (lm75_t *) malloc(sizeof(lm75_t)); - memset(dev, 0, sizeof(lm75_t)); + lm75_t *dev = (lm75_t *) calloc(1, sizeof(lm75_t)); dev->local = info->local; diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index 3219e87e6..1e61168ac 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -771,8 +771,7 @@ lm78_close(void *priv) static void * lm78_init(const device_t *info) { - lm78_t *dev = (lm78_t *) malloc(sizeof(lm78_t)); - memset(dev, 0, sizeof(lm78_t)); + lm78_t *dev = (lm78_t *) calloc(1, sizeof(lm78_t)); dev->local = info->local; diff --git a/src/device/hwm_vt82c686.c b/src/device/hwm_vt82c686.c index 7d764bcb9..8623a9f6b 100644 --- a/src/device/hwm_vt82c686.c +++ b/src/device/hwm_vt82c686.c @@ -183,8 +183,7 @@ vt82c686_close(void *priv) static void * vt82c686_init(UNUSED(const device_t *info)) { - vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t)); - memset(dev, 0, sizeof(vt82c686_t)); + vt82c686_t *dev = (vt82c686_t *) calloc(1, sizeof(vt82c686_t)); /* Set default values. Since this hardware monitor has a complex voltage factor system, the values struct contains voltage values *before* applying their respective factors. */ diff --git a/src/device/i2c.c b/src/device/i2c.c index 56e6f8f4c..eb80f413b 100644 --- a/src/device/i2c.c +++ b/src/device/i2c.c @@ -67,8 +67,7 @@ i2c_log(const char *fmt, ...) void * i2c_addbus(char *name) { - i2c_bus_t *bus = (i2c_bus_t *) malloc(sizeof(i2c_bus_t)); - memset(bus, 0, sizeof(i2c_bus_t)); + i2c_bus_t *bus = (i2c_bus_t *) calloc(1, sizeof(i2c_bus_t)); bus->name = name; @@ -127,8 +126,7 @@ i2c_sethandler(void *bus_handle, uint8_t base, int size, for (int c = 0; c < size; c++) { p = bus->last[base + c]; - q = (i2c_t *) malloc(sizeof(i2c_t)); - memset(q, 0, sizeof(i2c_t)); + q = (i2c_t *) calloc(1, sizeof(i2c_t)); if (p) { p->next = q; q->prev = p; diff --git a/src/device/i2c_gpio.c b/src/device/i2c_gpio.c index 22bdaffd3..61a3dbe05 100644 --- a/src/device/i2c_gpio.c +++ b/src/device/i2c_gpio.c @@ -59,8 +59,7 @@ i2c_gpio_log(int level, const char *fmt, ...) void * i2c_gpio_init(char *bus_name) { - i2c_gpio_t *dev = (i2c_gpio_t *) malloc(sizeof(i2c_gpio_t)); - memset(dev, 0, sizeof(i2c_gpio_t)); + i2c_gpio_t *dev = (i2c_gpio_t *) calloc(1, sizeof(i2c_gpio_t)); i2c_gpio_log(1, "I2C GPIO %s: init()\n", bus_name); diff --git a/src/device/isamem.c b/src/device/isamem.c index 5d3164757..4dc88cc6c 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -483,8 +483,7 @@ isamem_init(const device_t *info) uint8_t *ptr; /* Find our device and create an instance. */ - dev = (memdev_t *) malloc(sizeof(memdev_t)); - memset(dev, 0x00, sizeof(memdev_t)); + dev = (memdev_t *) calloc(1, sizeof(memdev_t)); dev->name = info->name; dev->board = info->local; diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 479b6b9b2..1ee8be040 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -679,7 +679,7 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) static void * isapnp_init(UNUSED(const device_t *info)) { - isapnp_t *dev = (isapnp_t *) malloc(sizeof(isapnp_t)); + isapnp_t *dev = (isapnp_t *) calloc(1, sizeof(isapnp_t)); memset(dev, 0, sizeof(isapnp_t)); io_sethandler(0x279, 1, NULL, NULL, NULL, isapnp_write_addr, NULL, NULL, dev); @@ -728,8 +728,7 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, if (!dev) dev = (isapnp_t *) device_add(&isapnp_device); - isapnp_card_t *card = (isapnp_card_t *) malloc(sizeof(isapnp_card_t)); - memset(card, 0, sizeof(isapnp_card_t)); + isapnp_card_t *card = (isapnp_card_t *) calloc(1, sizeof(isapnp_card_t)); card->enable = 1; card->priv = priv; diff --git a/src/device/isartc.c b/src/device/isartc.c index 77f35ffc7..f24ffb72b 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -520,8 +520,7 @@ isartc_init(const device_t *info) is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); /* Create a device instance. */ - dev = (rtcdev_t *) malloc(sizeof(rtcdev_t)); - memset(dev, 0x00, sizeof(rtcdev_t)); + dev = (rtcdev_t *) calloc(1, sizeof(rtcdev_t)); dev->name = info->name; dev->board = info->local; dev->irq = -1; diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index aef3b2cc6..ad1625873 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2282,8 +2282,7 @@ kbc_at_init(const device_t *info) atkbc_t *dev; int max_ports; - dev = (atkbc_t *) malloc(sizeof(atkbc_t)); - memset(dev, 0x00, sizeof(atkbc_t)); + dev = (atkbc_t *) calloc(1, sizeof(atkbc_t)); dev->flags = info->local; @@ -2393,8 +2392,7 @@ kbc_at_init(const device_t *info) #endif for (int i = 0; i < max_ports; i++) { - kbc_at_ports[i] = (kbc_at_port_t *) malloc(sizeof(kbc_at_port_t)); - memset(kbc_at_ports[i], 0x00, sizeof(kbc_at_port_t)); + kbc_at_ports[i] = (kbc_at_port_t *) calloc(1, sizeof(kbc_at_port_t)); kbc_at_ports[i]->out_new = -1; } diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index c614bad8c..644168004 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -1000,8 +1000,7 @@ kbd_init(const device_t *info) { xtkbd_t *kbd; - kbd = (xtkbd_t *) malloc(sizeof(xtkbd_t)); - memset(kbd, 0x00, sizeof(xtkbd_t)); + kbd = (xtkbd_t *) calloc(1, sizeof(xtkbd_t)); io_sethandler(0x0060, 4, kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); diff --git a/src/device/mouse_bus.c b/src/device/mouse_bus.c index 9c0d8b02e..b56a3cc18 100644 --- a/src/device/mouse_bus.c +++ b/src/device/mouse_bus.c @@ -614,8 +614,7 @@ bm_init(const device_t *info) mouse_t *dev; int hz; - dev = (mouse_t *) malloc(sizeof(mouse_t)); - memset(dev, 0x00, sizeof(mouse_t)); + dev = (mouse_t *) calloc(1, sizeof(mouse_t)); if ((info->local & ~MOUSE_TYPE_ONBOARD) == MOUSE_TYPE_INPORT) dev->flags = FLAG_INPORT; diff --git a/src/device/mouse_microtouch_touchscreen.c b/src/device/mouse_microtouch_touchscreen.c index c6bef89dc..80e89df1f 100644 --- a/src/device/mouse_microtouch_touchscreen.c +++ b/src/device/mouse_microtouch_touchscreen.c @@ -128,8 +128,7 @@ mtouch_initnvr(void *priv) FILE *fp; /* Allocate and initialize the EEPROM. */ - dev->nvr = (uint8_t *) malloc(NVR_SIZE); - memset(dev->nvr, 0x00, NVR_SIZE); + dev->nvr = (uint8_t *) calloc(1, NVR_SIZE); fp = nvr_fopen(dev->nvr_path, "rb"); if (fp) { diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 99d08cd37..c64be5a6d 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -845,8 +845,7 @@ sermouse_init(const device_t *info) void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data); void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period); - dev = (mouse_t *) malloc(sizeof(mouse_t)); - memset(dev, 0x00, sizeof(mouse_t)); + dev = (mouse_t *) calloc(1, sizeof(mouse_t)); dev->name = info->name; dev->but = device_get_config_int("buttons"); dev->rev = device_get_config_int("revision"); diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 4321bf433..7dda00aee 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -491,8 +491,7 @@ pci_bridge_init(const device_t *info) uint8_t interrupt_mask; uint8_t slot_count; - pci_bridge_t *dev = (pci_bridge_t *) malloc(sizeof(pci_bridge_t)); - memset(dev, 0, sizeof(pci_bridge_t)); + pci_bridge_t *dev = (pci_bridge_t *) calloc(1, sizeof(pci_bridge_t)); dev->local = info->local; dev->bus_index = pci_register_bus(); diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index 6032a59dc..a3e2f0e7e 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -110,8 +110,7 @@ phoenix_486_jumper_close(void *priv) static void * phoenix_486_jumper_init(const device_t *info) { - phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) malloc(sizeof(phoenix_486_jumper_t)); - memset(dev, 0, sizeof(phoenix_486_jumper_t)); + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) calloc(1, sizeof(phoenix_486_jumper_t)); dev->type = info->local; diff --git a/src/device/serial.c b/src/device/serial.c index 1e2618449..0ba60551c 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -914,8 +914,7 @@ serial_reset(void *priv) static void * serial_init(const device_t *info) { - serial_t *dev = (serial_t *) malloc(sizeof(serial_t)); - memset(dev, 0, sizeof(serial_t)); + serial_t *dev = (serial_t *) calloc(1, sizeof(serial_t)); dev->inst = next_inst; diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index 445b67d04..bb2378a22 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -178,8 +178,7 @@ serial_passthrough_dev_init(const device_t *info) { serial_passthrough_t *dev; - dev = (serial_passthrough_t *) malloc(sizeof(serial_passthrough_t)); - memset(dev, 0, sizeof(serial_passthrough_t)); + dev = (serial_passthrough_t *) calloc(1, sizeof(serial_passthrough_t)); dev->mode = device_get_config_int("mode"); dev->port = device_get_instance() - 1; diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index de487ef73..3907a065e 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -273,7 +273,7 @@ smbus_ali7101_reset(void *priv) static void * smbus_ali7101_init(const device_t *info) { - smbus_ali7101_t *dev = (smbus_ali7101_t *) malloc(sizeof(smbus_ali7101_t)); + smbus_ali7101_t *dev = (smbus_ali7101_t *) calloc(1, sizeof(smbus_ali7101_t)); memset(dev, 0, sizeof(smbus_ali7101_t)); dev->local = info->local; diff --git a/src/device/smbus_piix4.c b/src/device/smbus_piix4.c index d72712cc6..a9ffcd847 100644 --- a/src/device/smbus_piix4.c +++ b/src/device/smbus_piix4.c @@ -357,8 +357,7 @@ smbus_piix4_setclock(smbus_piix4_t *dev, int clock) static void * smbus_piix4_init(const device_t *info) { - smbus_piix4_t *dev = (smbus_piix4_t *) malloc(sizeof(smbus_piix4_t)); - memset(dev, 0, sizeof(smbus_piix4_t)); + smbus_piix4_t *dev = (smbus_piix4_t *) calloc(1, sizeof(smbus_piix4_t)); dev->local = info->local; /* We save the I2C bus handle on dev but use i2c_smbus for all operations because diff --git a/src/device/smbus_sis5595.c b/src/device/smbus_sis5595.c index e7cffc577..0a24d2355 100644 --- a/src/device/smbus_sis5595.c +++ b/src/device/smbus_sis5595.c @@ -343,8 +343,7 @@ smbus_sis5595_reset(void *priv) static void * smbus_sis5595_init(const device_t *info) { - smbus_sis5595_t *dev = (smbus_sis5595_t *) malloc(sizeof(smbus_sis5595_t)); - memset(dev, 0, sizeof(smbus_sis5595_t)); + smbus_sis5595_t *dev = (smbus_sis5595_t *) calloc(1, sizeof(smbus_sis5595_t)); dev->local = info->local; diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index d9dc02da0..adc39d509 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -920,8 +920,7 @@ wd1007vse1_init(UNUSED(const device_t *info)) { int c; - esdi_t *esdi = malloc(sizeof(esdi_t)); - memset(esdi, 0x00, sizeof(esdi_t)); + esdi_t *esdi = calloc(1, sizeof(esdi_t)); c = 0; for (uint8_t d = 0; d < HDD_NUM; d++) { diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 83d2dc3b7..b7ab5ff9f 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1249,10 +1249,9 @@ esdi_init(UNUSED(const device_t *info)) uint8_t c; uint8_t i; - dev = malloc(sizeof(esdi_t)); + dev = calloc(1, sizeof(esdi_t)); if (dev == NULL) return (NULL); - memset(dev, 0x00, sizeof(esdi_t)); /* Mark as unconfigured. */ dev->irq_status = 0xff; diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index 9c0178a47..84a40efa4 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -504,8 +504,7 @@ cmd640_close(void *priv) static void * cmd640_init(const device_t *info) { - cmd640_t *dev = (cmd640_t *) malloc(sizeof(cmd640_t)); - memset(dev, 0x00, sizeof(cmd640_t)); + cmd640_t *dev = (cmd640_t *) calloc(1, sizeof(cmd640_t)); dev->id = next_id | 0x60; diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index b79f84f03..b548390fd 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -391,8 +391,7 @@ cmd646_close(void *priv) static void * cmd646_init(const device_t *info) { - cmd646_t *dev = (cmd646_t *) malloc(sizeof(cmd646_t)); - memset(dev, 0x00, sizeof(cmd646_t)); + cmd646_t *dev = (cmd646_t *) calloc(1, sizeof(cmd646_t)); dev->local = info->local; diff --git a/src/disk/hdc_ide_opti611.c b/src/disk/hdc_ide_opti611.c index 67cdfc779..4927b5fe3 100644 --- a/src/disk/hdc_ide_opti611.c +++ b/src/disk/hdc_ide_opti611.c @@ -317,8 +317,7 @@ opti611_close(void *priv) static void * opti611_init(UNUSED(const device_t *info)) { - opti611_t *dev = (opti611_t *) malloc(sizeof(opti611_t)); - memset(dev, 0, sizeof(opti611_t)); + opti611_t *dev = (opti611_t *) calloc(1, sizeof(opti611_t)); dev->is_sec = info->local; diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index ec4c7228c..73dc5f36b 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -578,8 +578,7 @@ sff_close(void *priv) static void * sff_init(UNUSED(const device_t *info)) { - sff8038i_t *dev = (sff8038i_t *) malloc(sizeof(sff8038i_t)); - memset(dev, 0, sizeof(sff8038i_t)); + sff8038i_t *dev = (sff8038i_t *) calloc(1, sizeof(sff8038i_t)); /* Make sure to only add IDE once. */ if (next_id == 0) diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c index 897a26593..9c0f744b2 100644 --- a/src/disk/hdc_ide_w83769f.c +++ b/src/disk/hdc_ide_w83769f.c @@ -353,8 +353,7 @@ w83769f_close(void *priv) static void * w83769f_init(const device_t *info) { - w83769f_t *dev = (w83769f_t *) malloc(sizeof(w83769f_t)); - memset(dev, 0x00, sizeof(w83769f_t)); + w83769f_t *dev = (w83769f_t *) calloc(1, sizeof(w83769f_t)); dev->id = next_id | 0x60; diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index abd379646..eeb242a94 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -744,8 +744,7 @@ mfm_init(UNUSED(const device_t *info)) int c; st506_at_log("WD1003: ISA MFM/RLL Fixed Disk Adapter initializing ...\n"); - mfm = malloc(sizeof(mfm_t)); - memset(mfm, 0x00, sizeof(mfm_t)); + mfm = calloc(1, sizeof(mfm_t)); c = 0; for (uint8_t d = 0; d < HDD_NUM; d++) { diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index d950fbe34..789e7e6c4 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1627,8 +1627,7 @@ st506_init(const device_t *info) int i; int c; - dev = (hdc_t *) malloc(sizeof(hdc_t)); - memset(dev, 0x00, sizeof(hdc_t)); + dev = (hdc_t *) calloc(1, sizeof(hdc_t)); dev->type = info->local & 255; /* Set defaults for the controller. */ diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 1ddbd33e2..553e53b48 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1000,8 +1000,7 @@ xta_init(const device_t *info) int max = XTA_NUM; /* Allocate and initialize device block. */ - dev = malloc(sizeof(hdc_t)); - memset(dev, 0x00, sizeof(hdc_t)); + dev = calloc(1, sizeof(hdc_t)); dev->type = info->local; /* Do per-controller-type setup. */ diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 623f68cb5..7ec7695b3 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -132,13 +132,11 @@ xtide_read(uint16_t port, void *priv) static void * xtide_init(const device_t *info) { - xtide_t *xtide = malloc(sizeof(xtide_t)); + xtide_t *xtide = calloc(1, sizeof(xtide_t)); - memset(xtide, 0x00, sizeof(xtide_t)); - - rom_init(&xtide->bios_rom, - device_get_bios_file(info, device_get_config_bios("bios"), 0), - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&xtide->bios_rom, + device_get_bios_file(info, device_get_config_bios("bios"), 0), + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); @@ -152,13 +150,11 @@ xtide_init(const device_t *info) static void * xtide_at_init(const device_t *info) { - xtide_t *xtide = malloc(sizeof(xtide_t)); + xtide_t *xtide = calloc(1, sizeof(xtide_t)); - memset(xtide, 0x00, sizeof(xtide_t)); - - rom_init(&xtide->bios_rom, - device_get_bios_file(info, device_get_config_bios("bios"), 0), - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&xtide->bios_rom, + device_get_bios_file(info, device_get_config_bios("bios"), 0), + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); device_add(&ide_isa_2ch_device); @@ -168,9 +164,7 @@ xtide_at_init(const device_t *info) static void * xtide_acculogic_init(UNUSED(const device_t *info)) { - xtide_t *xtide = malloc(sizeof(xtide_t)); - - memset(xtide, 0x00, sizeof(xtide_t)); + xtide_t *xtide = calloc(1, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2, 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); @@ -203,9 +197,7 @@ xtide_close(void *priv) static void * xtide_at_ps2_init(UNUSED(const device_t *info)) { - xtide_t *xtide = malloc(sizeof(xtide_t)); - - memset(xtide, 0x00, sizeof(xtide_t)); + xtide_t *xtide = calloc(1, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2AT, 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 5c377f95f..300d775c5 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2314,8 +2314,7 @@ fdc_close(void *priv) static void * fdc_init(const device_t *info) { - fdc_t *fdc = (fdc_t *) malloc(sizeof(fdc_t)); - memset(fdc, 0, sizeof(fdc_t)); + fdc_t *fdc = (fdc_t *) calloc(1, sizeof(fdc_t)); fdc->flags = info->local; diff --git a/src/floppy/fdc_magitronic.c b/src/floppy/fdc_magitronic.c index 09b766d6c..2b708a121 100644 --- a/src/floppy/fdc_magitronic.c +++ b/src/floppy/fdc_magitronic.c @@ -90,8 +90,7 @@ b215_close(void *priv) static void * b215_init(UNUSED(const device_t *info)) { - b215_t *dev = (b215_t *) malloc(sizeof(b215_t)); - memset(dev, 0, sizeof(b215_t)); + b215_t *dev = (b215_t *) calloc(1, sizeof(b215_t)); rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c index bb210fb44..51fb108d6 100644 --- a/src/floppy/fdc_monster.c +++ b/src/floppy/fdc_monster.c @@ -13,7 +13,7 @@ * Authors: Jasmine Iwanek, * Miran Grca, * - * Copyright 2022-2024 Jasmine Iwanek. + * Copyright 2022-2025 Jasmine Iwanek. * Copyright 2024 Miran Grca. */ #include diff --git a/src/floppy/fdc_pii15xb.c b/src/floppy/fdc_pii15xb.c index 6a8bbbd43..587eb64fa 100644 --- a/src/floppy/fdc_pii15xb.c +++ b/src/floppy/fdc_pii15xb.c @@ -97,8 +97,7 @@ pii_init(const device_t *info) { pii_t *dev; - dev = (pii_t *) malloc(sizeof(pii_t)); - memset(dev, 0, sizeof(pii_t)); + dev = (pii_t *) calloc(1, sizeof(pii_t)); if (BIOS_ADDR != 0) rom_init(&dev->bios_rom, DTK_VARIANT, BIOS_ADDR, 0x2000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL); diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 0e8a6590a..140e87899 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -2731,8 +2731,7 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t uint16_t datadam_mfm = 0x4A55; if (fdd_get_turbo(drive) && (dev->version == 0x0063)) { - s = (sector_t *) malloc(sizeof(sector_t)); - memset(s, 0, sizeof(sector_t)); + s = (sector_t *) calloc(1, sizeof(sector_t)); s->c = id_buf[0]; s->h = id_buf[1]; s->r = id_buf[2]; @@ -3921,8 +3920,7 @@ d86f_setup(int drive) d86f_t *dev; /* Allocate a drive structure. */ - dev = (d86f_t *) malloc(sizeof(d86f_t)); - memset(dev, 0x00, sizeof(d86f_t)); + dev = (d86f_t *) calloc(1, sizeof(d86f_t)); dev->state = STATE_IDLE; dev->last_side_sector[0] = NULL; diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index f14bf2cd4..97b6441a0 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -316,15 +316,13 @@ fdi_load(int drive, char *fn) writeprot[drive] = fwriteprot[drive] = 1; /* Allocate a drive block. */ - dev = (fdi_t *) malloc(sizeof(fdi_t)); + dev = (fdi_t *) calloc(1, sizeof(fdi_t)); if (dev == NULL) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } - memset(dev, 0x00, sizeof(fdi_t)); - d86f_unregister(drive); dev->fp = plat_fopen(fn, "rb"); diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 0839c2900..7994530ed 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -635,8 +635,7 @@ imd_load(int drive, char *fn) writeprot[drive] = 0; /* Allocate a drive block. */ - dev = (imd_t *) malloc(sizeof(imd_t)); - memset(dev, 0x00, sizeof(imd_t)); + dev = (imd_t *) calloc(1, sizeof(imd_t)); dev->fp = plat_fopen(fn, "rb+"); if (dev->fp == NULL) { diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 69a753ef5..30e0212cd 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -681,8 +681,7 @@ img_load(int drive, char *fn) writeprot[drive] = 0; /* Allocate a drive block. */ - dev = (img_t *) malloc(sizeof(img_t)); - memset(dev, 0x00, sizeof(img_t)); + dev = (img_t *) calloc(1, sizeof(img_t)); dev->fp = plat_fopen(fn, "rb+"); if (dev->fp == NULL) { diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index a332d25c9..87da4e08b 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -396,8 +396,7 @@ mfm_load(int drive, char *fn) writeprot[drive] = fwriteprot[drive] = 1; /* Allocate a drive block. */ - dev = (mfm_t *) malloc(sizeof(mfm_t)); - memset(dev, 0x00, sizeof(mfm_t)); + dev = (mfm_t *) calloc(1, sizeof(mfm_t)); dev->fp = plat_fopen(fn, "rb"); if (dev->fp == NULL) { diff --git a/src/floppy/fdd_pcjs.c b/src/floppy/fdd_pcjs.c index 76f8ca7dc..41db65a1a 100644 --- a/src/floppy/fdd_pcjs.c +++ b/src/floppy/fdd_pcjs.c @@ -617,8 +617,7 @@ pcjs_load(int drive, char *fn) d86f_unregister(drive); /* Allocate a drive block */ - dev = (pcjs_t *) malloc(sizeof(pcjs_t)); - memset(dev, 0x00, sizeof(pcjs_t)); + dev = (pcjs_t *) calloc(1, sizeof(pcjs_t)); /* Open the image file, read-only */ dev->fp = plat_fopen(fn, "rb"); diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 0bf4b1c71..f5882158b 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -1214,8 +1214,7 @@ td0_load(int drive, char *fn) writeprot[drive] = 1; - dev = (td0_t *) malloc(sizeof(td0_t)); - memset(dev, 0x00, sizeof(td0_t)); + dev = (td0_t *) calloc(1, sizeof(td0_t)); td0[drive] = dev; dev->fp = plat_fopen(fn, "rb"); diff --git a/src/game/gameport.c b/src/game/gameport.c index f3b54c803..579f5c235 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -366,15 +366,11 @@ gameport_add(const device_t *gameport_type) static void * gameport_init(const device_t *info) { - gameport_t *dev = NULL; - - dev = malloc(sizeof(gameport_t)); - memset(dev, 0x00, sizeof(gameport_t)); + gameport_t *dev = calloc(1, sizeof(gameport_t)); /* Allocate global instance. */ if (!joystick_instance[0] && joystick_type) { - joystick_instance[0] = malloc(sizeof(joystick_instance_t)); - memset(joystick_instance[0], 0x00, sizeof(joystick_instance_t)); + joystick_instance[0] = calloc(1, sizeof(joystick_instance_t)); joystick_instance[0]->axis[0].joystick = joystick_instance[0]; joystick_instance[0]->axis[1].joystick = joystick_instance[0]; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 891f02e84..3dba578bd 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -619,8 +619,7 @@ vid_init_1512(amstrad_t *ams) amsvid_t *vid; /* Allocate a video controller block. */ - vid = (amsvid_t *) malloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); + vid = (amsvid_t *) calloc(1, sizeof(amsvid_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pc1512); @@ -823,8 +822,7 @@ vid_init_1640(amstrad_t *ams) amsvid_t *vid; /* Allocate a video controller block. */ - vid = (amsvid_t *) malloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); + vid = (amsvid_t *) calloc(1, sizeof(amsvid_t)); rom_init(&vid->bios_rom, "roms/machines/pc1640/40100", 0xc0000, 0x8000, 0x7fff, 0, 0); @@ -1620,8 +1618,7 @@ vid_init_200(amstrad_t *ams) mda_t *mda; /* Allocate a video controller block. */ - vid = (amsvid_t *) malloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); + vid = (amsvid_t *) calloc(1, sizeof(amsvid_t)); vid->emulation = device_get_config_int("video_emulation"); @@ -2870,8 +2867,7 @@ machine_amstrad_init(const machine_t *model, int type) { amstrad_t *ams; - ams = (amstrad_t *) malloc(sizeof(amstrad_t)); - memset(ams, 0x00, sizeof(amstrad_t)); + ams = (amstrad_t *) calloc(1, sizeof(amstrad_t)); ams->type = type; amstrad_latch = 0x80000000; diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 3b9462f90..904122bad 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -629,8 +629,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) static void * compaq_plasma_init(UNUSED(const device_t *info)) { - compaq_plasma_t *self = malloc(sizeof(compaq_plasma_t)); - memset(self, 0, sizeof(compaq_plasma_t)); + compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); if (compaq_machine_type == COMPAQ_PORTABLEIII) diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index 80af959af..c827a05e5 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -655,8 +655,7 @@ t3100e_recalcattrs(t3100e_t *t3100e) void * t3100e_init(UNUSED(const device_t *info)) { - t3100e_t *t3100e = malloc(sizeof(t3100e_t)); - memset(t3100e, 0, sizeof(t3100e_t)); + t3100e_t *t3100e = calloc(1, sizeof(t3100e_t)); loadfont("roms/machines/t3100e/t3100e_font.bin", 5); cga_init(&t3100e->cga); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_t3100e); diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 847053bdb..ca9e72fca 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -1532,8 +1532,7 @@ machine_pcjr_init(UNUSED(const machine_t *model)) if (bios_only || !ret) return ret; - pcjr = malloc(sizeof(pcjr_t)); - memset(pcjr, 0x00, sizeof(pcjr_t)); + pcjr = calloc(1, sizeof(pcjr_t)); pic_init_pcjr(); pit_common_init(0, pit_irq0_timer_pcjr, NULL); diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 8b2a096c7..92846c401 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -299,8 +299,7 @@ ps1_setup(int model) ps1_t *ps; void *priv; - ps = (ps1_t *) malloc(sizeof(ps1_t)); - memset(ps, 0x00, sizeof(ps1_t)); + ps = (ps1_t *) calloc(1, sizeof(ps1_t)); ps->model = model; io_sethandler(0x0091, 1, diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index 06c7a2c95..d407953b4 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -1297,8 +1297,7 @@ ps1_hdc_init(UNUSED(const device_t *info)) int c; /* Allocate and initialize device block. */ - dev = malloc(sizeof(hdc_t)); - memset(dev, 0x00, sizeof(hdc_t)); + dev = calloc(1, sizeof(hdc_t)); /* Set up controller parameters for PS/1 2011. */ dev->base = 0x0320; diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index c0c4f7c79..7d024c335 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -151,8 +151,7 @@ ps2_isa_setup(int model, int cpu_type) ps2_isa_t *ps2; void *priv; - ps2 = (ps2_isa_t *) malloc(sizeof(ps2_isa_t)); - memset(ps2, 0x00, sizeof(ps2_isa_t)); + ps2 = (ps2_isa_t *) calloc(1, sizeof(ps2_isa_t)); ps2->model = model; ps2->cpu_type = cpu_type; diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 8e46c6154..7072c5e78 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1359,8 +1359,7 @@ vid_init(tandy_t *dev) int display_type; t1kvid_t *vid; - vid = malloc(sizeof(t1kvid_t)); - memset(vid, 0x00, sizeof(t1kvid_t)); + vid = calloc(1, sizeof(t1kvid_t)); vid->memctrl = -1; video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); @@ -1540,8 +1539,7 @@ eep_init(const device_t *info) t1keep_t *eep; FILE *fp = NULL; - eep = (t1keep_t *) malloc(sizeof(t1keep_t)); - memset(eep, 0x00, sizeof(t1keep_t)); + eep = (t1keep_t *) calloc(1, sizeof(t1keep_t)); switch (info->local) { case TYPE_TANDY1000HX: diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 3b907f4df..b6e4fb94a 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -2313,8 +2313,7 @@ machine_xt_m24_init(const machine_t *model) if (bios_only || !ret) return ret; - m24_kbd = (m24_kbd_t *) malloc(sizeof(m24_kbd_t)); - memset(m24_kbd, 0x00, sizeof(m24_kbd_t)); + m24_kbd = (m24_kbd_t *) calloc(1, sizeof(m24_kbd_t)); machine_common_init(model); @@ -2330,10 +2329,9 @@ machine_xt_m24_init(const machine_t *model) nmi_init(); /* Allocate an NVR for this machine. */ - nvr = (nvr_t *) malloc(sizeof(nvr_t)); + nvr = (nvr_t *) calloc(1, sizeof(nvr_t)); if (nvr == NULL) return 0; - memset(nvr, 0x00, sizeof(nvr_t)); mm58174_init(nvr, model->nvrmask + 1); @@ -2374,8 +2372,7 @@ machine_xt_m240_init(const machine_t *model) if (bios_only || !ret) return ret; - m24_kbd = (m24_kbd_t *) malloc(sizeof(m24_kbd_t)); - memset(m24_kbd, 0x00, sizeof(m24_kbd_t)); + m24_kbd = (m24_kbd_t *) calloc(1, sizeof(m24_kbd_t)); machine_common_init(model); @@ -2404,10 +2401,9 @@ machine_xt_m240_init(const machine_t *model) nmi_init(); /* Allocate an NVR for this machine. */ - nvr = (nvr_t *) malloc(sizeof(nvr_t)); + nvr = (nvr_t *) calloc(1, sizeof(nvr_t)); if (nvr == NULL) return 0; - memset(nvr, 0x00, sizeof(nvr_t)); mm58274_init(nvr, model->nvrmask + 1); @@ -2438,8 +2434,7 @@ machine_xt_m19_init(const machine_t *model) m19_vid_t *vid; /* Do not move memory allocation elsewhere. */ - vid = (m19_vid_t *) malloc(sizeof(m19_vid_t)); - memset(vid, 0x00, sizeof(m19_vid_t)); + vid = (m19_vid_t *) calloc(1, sizeof(m19_vid_t)); machine_common_init(model); diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index 0d1ba714b..efad869e1 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -651,8 +651,7 @@ t1000_recalcattrs(t1000_t *t1000) static void * t1000_init(UNUSED(const device_t *info)) { - t1000_t *t1000 = malloc(sizeof(t1000_t)); - memset(t1000, 0, sizeof(t1000_t)); + t1000_t *t1000 = calloc(1, sizeof(t1000_t)); loadfont("roms/machines/t1000/t1000font.bin", 8); cga_init(&t1000->cga); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_t1000); diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 776e10c9f..833529ffb 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -73,8 +73,7 @@ zenith_scratchpad_init(UNUSED(const device_t *info)) { zenith_t *dev; - dev = (zenith_t *) malloc(sizeof(zenith_t)); - memset(dev, 0x00, sizeof(zenith_t)); + dev = (zenith_t *) calloc(1, sizeof(zenith_t)); dev->scratchpad_ram = malloc(0x4000); diff --git a/src/mem/catalyst_flash.c b/src/mem/catalyst_flash.c index 4bb9b585a..fd2bb739f 100644 --- a/src/mem/catalyst_flash.c +++ b/src/mem/catalyst_flash.c @@ -192,8 +192,7 @@ catalyst_flash_init(UNUSED(const device_t *info)) FILE *fp; flash_t *dev; - dev = malloc(sizeof(flash_t)); - memset(dev, 0, sizeof(flash_t)); + dev = calloc(1, sizeof(flash_t)); sprintf(flash_path, "%s.bin", machine_get_internal_name_ex(machine)); diff --git a/src/mem/i2c_eeprom.c b/src/mem/i2c_eeprom.c index 8e4a6cc14..a8ae7ed04 100644 --- a/src/mem/i2c_eeprom.c +++ b/src/mem/i2c_eeprom.c @@ -128,8 +128,7 @@ log2i(uint32_t i) void * i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t writable) { - i2c_eeprom_t *dev = (i2c_eeprom_t *) malloc(sizeof(i2c_eeprom_t)); - memset(dev, 0, sizeof(i2c_eeprom_t)); + i2c_eeprom_t *dev = (i2c_eeprom_t *) calloc(1, sizeof(i2c_eeprom_t)); /* Round size up to the next power of 2. */ uint32_t pow_size = 1 << log2i(size); diff --git a/src/mem/intel_flash.c b/src/mem/intel_flash.c index 56a7ad0e0..7375b1f42 100644 --- a/src/mem/intel_flash.c +++ b/src/mem/intel_flash.c @@ -351,8 +351,7 @@ intel_flash_init(const device_t *info) flash_t *dev; uint8_t type = info->local & 0xff; - dev = malloc(sizeof(flash_t)); - memset(dev, 0, sizeof(flash_t)); + dev = calloc(1, sizeof(flash_t)); sprintf(flash_path, "%s.bin", machine_get_internal_name_ex(machine)); diff --git a/src/mem/smram.c b/src/mem/smram.c index 0532e2dd5..afbc5475c 100644 --- a/src/mem/smram.c +++ b/src/mem/smram.c @@ -245,12 +245,11 @@ smram_add(void) return NULL; } - temp_smram = (smram_t *) malloc(sizeof(smram_t)); + temp_smram = (smram_t *) calloc(1, sizeof(smram_t)); if (temp_smram == NULL) { - fatal("smram_add(): temp_smram malloc failed\n"); + fatal("smram_add(): temp_smram calloc failed\n"); return NULL; } - memset(temp_smram, 0x00, sizeof(smram_t)); memset(&(temp_smram->mapping), 0x00, sizeof(mem_mapping_t)); /* Add struct to the beginning of the list if necessary.*/ diff --git a/src/mem/spd.c b/src/mem/spd.c index fee9b0b11..01cd7b464 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -221,8 +221,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) if (!(slot_mask & (1 << slot))) continue; /* slot disabled */ - spd_modules[slot] = (spd_t *) malloc(sizeof(spd_t)); - memset(spd_modules[slot], 0, sizeof(spd_t)); + spd_modules[slot] = (spd_t *) calloc(1, sizeof(spd_t)); spd_modules[slot]->slot = slot; spd_modules[slot]->size = rows[row]; diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 3dce35444..5a9c9c877 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -505,8 +505,7 @@ static void * sst_init(const device_t *info) { FILE *fp; - sst_t *dev = malloc(sizeof(sst_t)); - memset(dev, 0, sizeof(sst_t)); + sst_t *dev = calloc(1, sizeof(sst_t)); sprintf(flash_path, "%s.bin", machine_get_internal_name_ex(machine)); diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c index 21d71d75e..33e9d59bd 100644 --- a/src/network/net_3c501.c +++ b/src/network/net_3c501.c @@ -1080,8 +1080,7 @@ threec501_nic_init(UNUSED(const device_t *info)) uint32_t mac; threec501_t *dev; - dev = malloc(sizeof(threec501_t)); - memset(dev, 0x00, sizeof(threec501_t)); + dev = calloc(1, sizeof(threec501_t)); dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ dev->maclocal[1] = 0x60; dev->maclocal[2] = 0x8C; diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index f96e76a11..31156fa9a 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -573,8 +573,7 @@ threec503_nic_init(UNUSED(const device_t *info)) uint32_t mac; threec503_t *dev; - dev = malloc(sizeof(threec503_t)); - memset(dev, 0x00, sizeof(threec503_t)); + dev = calloc(1, sizeof(threec503_t)); dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ dev->maclocal[1] = 0x60; dev->maclocal[2] = 0x8C; diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index 297e11424..623dec56c 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -918,8 +918,7 @@ dp8390_set_defaults(dp8390_t *dev, uint8_t flags) void dp8390_mem_alloc(dp8390_t *dev, uint32_t start, uint32_t size) { - dev->mem = (uint8_t *) malloc(size * sizeof(uint8_t)); - memset(dev->mem, 0, size * sizeof(uint8_t)); + dev->mem = (uint8_t *) calloc(size, sizeof(uint8_t)); dev->mem_start = start; dev->mem_end = start + size; dev->mem_size = size; @@ -1007,8 +1006,7 @@ dp8390_soft_reset(dp8390_t *dev) static void * dp8390_init(UNUSED(const device_t *info)) { - dp8390_t *dp8390 = (dp8390_t *) malloc(sizeof(dp8390_t)); - memset(dp8390, 0, sizeof(dp8390_t)); + dp8390_t *dp8390 = (dp8390_t *) calloc(1, sizeof(dp8390_t)); /* Set values assuming WORD and only the clear IRQ flag - - the NIC can then call dp8390_set_defaults() again to diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 1f191e047..d3de47852 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -912,15 +912,13 @@ nic_init(const device_t *info) { uint32_t mac; uint32_t mac_oui; - char *rom; + char *rom = NULL; nic_t *dev; int set_oui = 0; - dev = malloc(sizeof(nic_t)); - memset(dev, 0x00, sizeof(nic_t)); + dev = calloc(1, sizeof(nic_t)); dev->name = info->name; dev->board = info->local; - rom = NULL; if (dev->board >= NE2K_RTL8019AS) { dev->base_address = 0x340; diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index c9323e702..fea20e3c9 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -2916,8 +2916,7 @@ pcnet_init(const device_t *info) int c; uint16_t checksum; - dev = malloc(sizeof(nic_t)); - memset(dev, 0x00, sizeof(nic_t)); + dev = calloc(1, sizeof(nic_t)); dev->name = info->name; dev->board = info->local & 0xff; diff --git a/src/network/net_plip.c b/src/network/net_plip.c index b1264b045..f80effeec 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -445,8 +445,7 @@ plip_rx(void *priv, uint8_t *buf, int io_len) static void * plip_lpt_init(void *lpt) { - plip_t *dev = (plip_t *) malloc(sizeof(plip_t)); - memset(dev, 0, sizeof(plip_t)); + plip_t *dev = (plip_t *) calloc(1, sizeof(plip_t)); plip_log(1, "PLIP: lpt_init()\n"); diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 22fdc722d..11f1a74b2 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -133,7 +133,7 @@ net_slirp_clock_get_ns(UNUSED(void *opaque)) static void * net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, UNUSED(void *opaque)) { - pc_timer_t *timer = malloc(sizeof(pc_timer_t)); + pc_timer_t *timer = calloc(1, sizeof(pc_timer_t)); timer_add(timer, cb, cb_opaque, 0); return timer; } @@ -422,8 +422,7 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv #ifndef _WIN32 slirp->pfd_size = 16 * sizeof(struct pollfd); - slirp->pfd = malloc(slirp->pfd_size); - memset(slirp->pfd, 0, slirp->pfd_size); + slirp->pfd = calloc(1, slirp->pfd_size); #endif /* Set the IP addresses to use. */ diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index d22b6076c..3d50c8f67 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -651,8 +651,7 @@ wd_init(const device_t *info) uint32_t mac; wd_t *dev; - dev = malloc(sizeof(wd_t)); - memset(dev, 0x00, sizeof(wd_t)); + dev = calloc(1, sizeof(wd_t)); dev->name = info->name; dev->board = info->local; diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 809083395..3ca0b0ba5 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -114,8 +114,7 @@ ps2_nvr_init(const device_t *info) FILE *fp = NULL; int c; - nvr = (ps2_nvr_t *) malloc(sizeof(ps2_nvr_t)); - memset(nvr, 0x00, sizeof(ps2_nvr_t)); + nvr = (ps2_nvr_t *) calloc(1, sizeof(ps2_nvr_t)); if (info->local) nvr->size = 2048; diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 0b40bec90..0198444a0 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1952,7 +1952,7 @@ read_status(void *priv) static void * escp_init(void *lpt) { - escp_t *dev; + escp_t *dev = NULL; /* Initialize FreeType. */ if (ft_lib == NULL) { @@ -1964,8 +1964,7 @@ escp_init(void *lpt) } /* Initialize a device instance. */ - dev = (escp_t *) malloc(sizeof(escp_t)); - memset(dev, 0x00, sizeof(escp_t)); + dev = (escp_t *) calloc(1, sizeof(escp_t)); dev->ctrl = 0x04; dev->lpt = lpt; diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index dcd018881..1a9d5c0e8 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -366,13 +366,12 @@ ps_read_status(void *priv) static void * ps_init(void *lpt) { - ps_t *dev; + ps_t *dev = (ps_t *) calloc(1, sizeof(ps_t)); gsapi_revision_t rev; - dev = (ps_t *) malloc(sizeof(ps_t)); - memset(dev, 0x00, sizeof(ps_t)); dev->ctrl = 0x04; dev->lpt = lpt; + dev->pcl = false; /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); @@ -415,11 +414,9 @@ ps_init(void *lpt) static void * pcl_init(void *lpt) { - ps_t *dev; + ps_t *dev = (ps_t *) calloc(1, sizeof(ps_t)); gsapi_revision_t rev; - dev = (ps_t *) malloc(sizeof(ps_t)); - memset(dev, 0x00, sizeof(ps_t)); dev->ctrl = 0x04; dev->lpt = lpt; dev->pcl = true; diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index ddf9faf53..e04ef9680 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -421,11 +421,9 @@ read_status(void *priv) static void * prnt_init(void *lpt) { - prnt_t *dev; - /* Initialize a device instance. */ - dev = (prnt_t *) malloc(sizeof(prnt_t)); - memset(dev, 0x00, sizeof(prnt_t)); + prnt_t *dev = (prnt_t *) calloc(1, sizeof(prnt_t)); + dev->ctrl = 0x04; dev->lpt = lpt; diff --git a/src/qt/win_opendir.c b/src/qt/win_opendir.c index 051ed20bb..46c7eb21e 100644 --- a/src/qt/win_opendir.c +++ b/src/qt/win_opendir.c @@ -40,21 +40,19 @@ opendir(const char *name) DIR *p; /* Create a new control structure. */ - p = (DIR *) malloc(sizeof(DIR)); + p = (DIR *) calloc(1, sizeof(DIR)); if (p == NULL) return (NULL); - memset(p, 0x00, sizeof(DIR)); p->flags = (DIR_F_LOWER | DIR_F_SANE); p->offset = 0; p->sts = 0; /* Create a work area. */ - p->dta = (char *) malloc(sizeof(FINDATA)); + p->dta = (char *) calloc(1, sizeof(FINDATA)); if (p->dta == NULL) { free(p); return (NULL); } - memset(p->dta, 0x00, sizeof(struct _finddata_t)); /* Add search filespec. */ strcpy(p->dir, name); diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 9e19e8524..b6a1698c5 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -925,8 +925,7 @@ aha_setnvr(x54x_t *dev) return; /* Allocate and initialize the EEPROM. */ - dev->nvr = (uint8_t *) malloc(NVR_SIZE); - memset(dev->nvr, 0x00, NVR_SIZE); + dev->nvr = (uint8_t *) calloc(1, NVR_SIZE); fp = nvr_fopen(dev->nvr_path, "rb"); if (fp) { diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 6d95ce44a..b235f2c3c 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1546,8 +1546,7 @@ buslogic_init(const device_t *info) dev = x54x_init(info); dev->bus = scsi_get_bus(); - dev->ven_data = malloc(sizeof(buslogic_data_t)); - memset(dev->ven_data, 0x00, sizeof(buslogic_data_t)); + dev->ven_data = calloc(1, sizeof(buslogic_data_t)); bl = (buslogic_data_t *) dev->ven_data; diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index def001624..d8008cf02 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -632,14 +632,10 @@ ncr53c400_init(const device_t *info) { const char *bios_ver = NULL; const char *fn; - ncr53c400_t *ncr400; - ncr_t *ncr; + ncr53c400_t *ncr400 = calloc(1, sizeof(ncr53c400_t)); + ncr_t *ncr = &ncr400->ncr; scsi_bus_t *scsi_bus; - ncr400 = malloc(sizeof(ncr53c400_t)); - memset(ncr400, 0x00, sizeof(ncr53c400_t)); - ncr = &ncr400->ncr; - ncr400->type = info->local; ncr->bus = scsi_get_bus(); diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 27542028a..d26da3bb3 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -2530,10 +2530,7 @@ ncr53c8xx_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) static void * ncr53c8xx_init(const device_t *info) { - ncr53c8xx_t *dev; - - dev = malloc(sizeof(ncr53c8xx_t)); - memset(dev, 0x00, sizeof(ncr53c8xx_t)); + ncr53c8xx_t *dev = calloc(1, sizeof(ncr53c8xx_t)); dev->bus = scsi_get_bus(); diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index e8f256bed..012d5524b 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -2204,10 +2204,7 @@ esp_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) static void * dc390_init(UNUSED(const device_t *info)) { - esp_t *dev; - - dev = malloc(sizeof(esp_t)); - memset(dev, 0x00, sizeof(esp_t)); + esp_t *dev = calloc(1, sizeof(esp_t)); dev->bus = scsi_get_bus(); @@ -2419,10 +2416,7 @@ ncr53c9x_mca_feedb(void *priv) static void * ncr53c9x_mca_init(const device_t *info) { - esp_t *dev; - - dev = malloc(sizeof(esp_t)); - memset(dev, 0x00, sizeof(esp_t)); + esp_t *dev = calloc(1, sizeof(esp_t)); dev->bus = scsi_get_bus(); diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 8be075833..cbf6ff205 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1162,8 +1162,7 @@ spock_mca_reset(void *priv) static void * spock_init(const device_t *info) { - spock_t *scsi = malloc(sizeof(spock_t)); - memset(scsi, 0x00, sizeof(spock_t)); + spock_t *scsi = calloc(1, sizeof(spock_t)); scsi->bus = scsi_get_bus(); diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 92de9d17b..ff5f584f1 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -472,14 +472,10 @@ t228_feedb(void *priv) static void * t128_init(const device_t *info) { - t128_t *t128; - ncr_t *ncr; + t128_t *t128 = calloc(1, sizeof(t128_t)); + ncr_t *ncr = &t128->ncr; scsi_bus_t *scsi_bus; - t128 = malloc(sizeof(t128_t)); - memset(t128, 0x00, sizeof(t128_t)); - ncr = &t128->ncr; - ncr->bus = scsi_get_bus(); scsi_bus = &ncr->scsibus; diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 6876e4385..c248fbe92 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -287,10 +287,9 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, static uint8_t x54x_bios_read_capacity(scsi_device_t *sd, uint8_t *buf, int transfer_size) { - uint8_t *cdb; + uint8_t *cdb = (uint8_t *) malloc(12);; uint8_t ret; - cdb = (uint8_t *) malloc(12); memset(cdb, 0, 12); cdb[0] = GPCMD_READ_CDROM_CAPACITY; @@ -305,10 +304,9 @@ x54x_bios_read_capacity(scsi_device_t *sd, uint8_t *buf, int transfer_size) static uint8_t x54x_bios_inquiry(scsi_device_t *sd, uint8_t *buf, int transfer_size) { - uint8_t *cdb; + uint8_t *cdb = (uint8_t *) malloc(12); uint8_t ret; - cdb = (uint8_t *) malloc(12); memset(cdb, 0, 12); cdb[0] = GPCMD_INQUIRY; cdb[4] = 36; @@ -324,14 +322,13 @@ x54x_bios_inquiry(scsi_device_t *sd, uint8_t *buf, int transfer_size) static uint8_t x54x_bios_command_08(scsi_device_t *sd, uint8_t *buffer, int transfer_size) { - uint8_t *rcbuf; + uint8_t *rcbuf = (uint8_t *) malloc(8); uint8_t ret; int i; memset(buffer, 0x00, 6); - rcbuf = (uint8_t *) malloc(8); - ret = x54x_bios_read_capacity(sd, rcbuf, transfer_size); + ret = x54x_bios_read_capacity(sd, rcbuf, transfer_size); if (ret) { free(rcbuf); return ret; @@ -353,13 +350,12 @@ x54x_bios_command_08(scsi_device_t *sd, uint8_t *buffer, int transfer_size) static int x54x_bios_command_15(scsi_device_t *sd, uint8_t *buffer, int transfer_size) { - uint8_t *inqbuf; + uint8_t *inqbuf = (uint8_t *) malloc(36); uint8_t *rcbuf; uint8_t ret; memset(buffer, 0x00, 6); - inqbuf = (uint8_t *) malloc(36); ret = x54x_bios_inquiry(sd, inqbuf, transfer_size); if (ret) { free(inqbuf); @@ -1896,13 +1892,11 @@ x54x_mem_disable(x54x_t *dev) void * x54x_init(const device_t *info) { - x54x_t *dev; + x54x_t *dev = calloc(1, sizeof(x54x_t)); /* Allocate control block and set up basic stuff. */ - dev = malloc(sizeof(x54x_t)); if (dev == NULL) return dev; - memset(dev, 0x00, sizeof(x54x_t)); dev->type = info->local; dev->card_bus = info->flags; diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index 59349dcbe..76c7ba3f5 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -257,8 +257,7 @@ i82091aa_close(void *priv) static void * i82091aa_init(const device_t *info) { - i82091aa_t *dev = (i82091aa_t *) malloc(sizeof(i82091aa_t)); - memset(dev, 0, sizeof(i82091aa_t)); + i82091aa_t *dev = (i82091aa_t *) calloc(1, sizeof(i82091aa_t)); dev->fdc = device_add(&fdc_at_device); diff --git a/src/sio/sio_acc3221.c b/src/sio/sio_acc3221.c index 6fcac024c..d52949d46 100644 --- a/src/sio/sio_acc3221.c +++ b/src/sio/sio_acc3221.c @@ -454,8 +454,7 @@ acc3221_close(void *priv) static void * acc3221_init(UNUSED(const device_t *info)) { - acc3221_t *dev = (acc3221_t *) malloc(sizeof(acc3221_t)); - memset(dev, 0, sizeof(acc3221_t)); + acc3221_t *dev = (acc3221_t *) calloc(1, sizeof(acc3221_t)); dev->fdc = device_add(&fdc_at_device); diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c index ce250ff2b..5380e065a 100644 --- a/src/sio/sio_ali5123.c +++ b/src/sio/sio_ali5123.c @@ -463,8 +463,7 @@ ali5123_close(void *priv) static void * ali5123_init(const device_t *info) { - ali5123_t *dev = (ali5123_t *) malloc(sizeof(ali5123_t)); - memset(dev, 0, sizeof(ali5123_t)); + ali5123_t *dev = (ali5123_t *) calloc(1, sizeof(ali5123_t)); dev->fdc = device_add(&fdc_at_ali_device); diff --git a/src/sio/sio_detect.c b/src/sio/sio_detect.c index ae34730ac..ffa0ec9d0 100644 --- a/src/sio/sio_detect.c +++ b/src/sio/sio_detect.c @@ -65,8 +65,7 @@ sio_detect_close(void *priv) static void * sio_detect_init(UNUSED(const device_t *info)) { - sio_detect_t *dev = (sio_detect_t *) malloc(sizeof(sio_detect_t)); - memset(dev, 0, sizeof(sio_detect_t)); + sio_detect_t *dev = (sio_detect_t *) calloc(1, sizeof(sio_detect_t)); device_add(&fdc_at_smc_device); diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index 04dcf109a..8882f16e0 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -364,8 +364,7 @@ f82c710_close(void *priv) static void * f82c710_init(const device_t *info) { - upc_t *dev = (upc_t *) malloc(sizeof(upc_t)); - memset(dev, 0, sizeof(upc_t)); + upc_t *dev = (upc_t *) calloc(1, sizeof(upc_t)); dev->local = info->local; if (dev->local == 606) { diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index 7f02026e5..7f97e79b0 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -335,8 +335,7 @@ fdc37c669_close(void *priv) static void * fdc37c669_init(const device_t *info) { - fdc37c669_t *dev = (fdc37c669_t *) malloc(sizeof(fdc37c669_t)); - memset(dev, 0, sizeof(fdc37c669_t)); + fdc37c669_t *dev = (fdc37c669_t *) calloc(1, sizeof(fdc37c669_t)); dev->id = next_id; diff --git a/src/sio/sio_fdc37c67x.c b/src/sio/sio_fdc37c67x.c index bac4685f5..f0fb8cd64 100644 --- a/src/sio/sio_fdc37c67x.c +++ b/src/sio/sio_fdc37c67x.c @@ -591,8 +591,7 @@ fdc37c67x_close(void *priv) static void * fdc37c67x_init(const device_t *info) { - fdc37c67x_t *dev = (fdc37c67x_t *) malloc(sizeof(fdc37c67x_t)); - memset(dev, 0, sizeof(fdc37c67x_t)); + fdc37c67x_t *dev = (fdc37c67x_t *) calloc(1, sizeof(fdc37c67x_t)); dev->fdc = device_add(&fdc_at_smc_device); diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 6340218b7..530fff216 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -312,8 +312,7 @@ fdc37c6xx_close(void *priv) static void * fdc37c6xx_init(const device_t *info) { - fdc37c6xx_t *dev = (fdc37c6xx_t *) malloc(sizeof(fdc37c6xx_t)); - memset(dev, 0, sizeof(fdc37c6xx_t)); + fdc37c6xx_t *dev = (fdc37c6xx_t *) calloc(1, sizeof(fdc37c6xx_t)); dev->fdc = device_add(&fdc_at_smc_device); diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 0279903c6..42908ecaf 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -918,8 +918,7 @@ access_bus_close(void *priv) static void * access_bus_init(UNUSED(const device_t *info)) { - access_bus_t *dev = (access_bus_t *) malloc(sizeof(access_bus_t)); - memset(dev, 0, sizeof(access_bus_t)); + access_bus_t *dev = (access_bus_t *) calloc(1, sizeof(access_bus_t)); return dev; } @@ -950,8 +949,7 @@ static void * fdc37c93x_init(const device_t *info) { int is_compaq; - fdc37c93x_t *dev = (fdc37c93x_t *) malloc(sizeof(fdc37c93x_t)); - memset(dev, 0, sizeof(fdc37c93x_t)); + fdc37c93x_t *dev = (fdc37c93x_t *) calloc(1, sizeof(fdc37c93x_t)); dev->fdc = device_add(&fdc_at_smc_device); diff --git a/src/sio/sio_fdc37m60x.c b/src/sio/sio_fdc37m60x.c index aab4d8968..671b3581b 100644 --- a/src/sio/sio_fdc37m60x.c +++ b/src/sio/sio_fdc37m60x.c @@ -306,8 +306,7 @@ fdc37m60x_close(void *priv) static void * fdc37m60x_init(const device_t *info) { - fdc37m60x_t *dev = (fdc37m60x_t *) malloc(sizeof(fdc37m60x_t)); - memset(dev, 0, sizeof(fdc37m60x_t)); + fdc37m60x_t *dev = (fdc37m60x_t *) calloc(1, sizeof(fdc37m60x_t)); SIO_INDEX_PORT = info->local; dev->fdc = device_add(&fdc_at_smc_device); diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index 610d69197..aee1b6a1d 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -799,8 +799,7 @@ it86x1f_close(void *priv) static void * it86x1f_init(UNUSED(const device_t *info)) { - it86x1f_t *dev = (it86x1f_t *) malloc(sizeof(it86x1f_t)); - memset(dev, 0, sizeof(it86x1f_t)); + it86x1f_t *dev = (it86x1f_t *) calloc(1, sizeof(it86x1f_t)); uint8_t i; for (i = 0; i < (sizeof(it86x1f_models) / sizeof(it86x1f_models[0])); i++) { diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index b21c2d1fc..5da43581f 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -467,8 +467,7 @@ pc87306_close(void *priv) static void * pc87306_init(UNUSED(const device_t *info)) { - pc87306_t *dev = (pc87306_t *) malloc(sizeof(pc87306_t)); - memset(dev, 0, sizeof(pc87306_t)); + pc87306_t *dev = (pc87306_t *) calloc(1, sizeof(pc87306_t)); dev->fdc = device_add(&fdc_at_nsc_device); diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index 1f84152f5..eba0748c9 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -593,8 +593,7 @@ pc87307_close(void *priv) static void * pc87307_init(const device_t *info) { - pc87307_t *dev = (pc87307_t *) malloc(sizeof(pc87307_t)); - memset(dev, 0, sizeof(pc87307_t)); + pc87307_t *dev = (pc87307_t *) calloc(1, sizeof(pc87307_t)); dev->id = info->local & 0xff; diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index f445ee189..1b790bc6b 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -466,8 +466,7 @@ pc87309_close(void *priv) static void * pc87309_init(const device_t *info) { - pc87309_t *dev = (pc87309_t *) malloc(sizeof(pc87309_t)); - memset(dev, 0, sizeof(pc87309_t)); + pc87309_t *dev = (pc87309_t *) calloc(1, sizeof(pc87309_t)); dev->id = info->local & 0xff; diff --git a/src/sio/sio_pc87311.c b/src/sio/sio_pc87311.c index f1b823e47..1f38e6aa8 100644 --- a/src/sio/sio_pc87311.c +++ b/src/sio/sio_pc87311.c @@ -269,8 +269,7 @@ pc87311_close(void *priv) static void * pc87311_init(const device_t *info) { - pc87311_t *dev = (pc87311_t *) malloc(sizeof(pc87311_t)); - memset(dev, 0, sizeof(pc87311_t)); + pc87311_t *dev = (pc87311_t *) calloc(1, sizeof(pc87311_t)); /* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */ HAS_IDE_FUNCTIONALITY = info->local; diff --git a/src/sio/sio_pc87332.c b/src/sio/sio_pc87332.c index 494c6d8bb..f746306bd 100644 --- a/src/sio/sio_pc87332.c +++ b/src/sio/sio_pc87332.c @@ -323,8 +323,7 @@ pc87332_close(void *priv) static void * pc87332_init(const device_t *info) { - pc87332_t *dev = (pc87332_t *) malloc(sizeof(pc87332_t)); - memset(dev, 0, sizeof(pc87332_t)); + pc87332_t *dev = (pc87332_t *) calloc(1, sizeof(pc87332_t)); dev->fdc = device_add(&fdc_at_nsc_device); diff --git a/src/sio/sio_prime3b.c b/src/sio/sio_prime3b.c index 1633c844b..2cadda2ab 100644 --- a/src/sio/sio_prime3b.c +++ b/src/sio/sio_prime3b.c @@ -257,8 +257,7 @@ prime3b_close(void *priv) static void * prime3b_init(const device_t *info) { - prime3b_t *dev = (prime3b_t *) malloc(sizeof(prime3b_t)); - memset(dev, 0, sizeof(prime3b_t)); + prime3b_t *dev = (prime3b_t *) calloc(1, sizeof(prime3b_t)); /* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */ HAS_IDE_FUNCTIONALITY = info->local; diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c index 68361d3e0..e646a3653 100644 --- a/src/sio/sio_prime3c.c +++ b/src/sio/sio_prime3c.c @@ -296,8 +296,7 @@ prime3c_close(void *priv) static void * prime3c_init(const device_t *info) { - prime3c_t *dev = (prime3c_t *) malloc(sizeof(prime3c_t)); - memset(dev, 0, sizeof(prime3c_t)); + prime3c_t *dev = (prime3c_t *) calloc(1, sizeof(prime3c_t)); /* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */ HAS_IDE_FUNCTIONALITY = info->local; diff --git a/src/sio/sio_um8669f.c b/src/sio/sio_um8669f.c index e3ef81e11..b3d5259a2 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -328,8 +328,7 @@ um8669f_init(const device_t *info) { um8669f_log("UM8669F: init(%02X)\n", info->local); - um8669f_t *dev = (um8669f_t *) malloc(sizeof(um8669f_t)); - memset(dev, 0, sizeof(um8669f_t)); + um8669f_t *dev = (um8669f_t *) calloc(1, sizeof(um8669f_t)); dev->pnp_card = isapnp_add_card(um8669f_pnp_rom, sizeof(um8669f_pnp_rom), um8669f_pnp_config_changed, NULL, NULL, NULL, dev); for (uint8_t i = 0; i < (sizeof(um8669f_pnp_defaults) / sizeof(isapnp_device_config_t)); i++) diff --git a/src/sio/sio_vt82c686.c b/src/sio/sio_vt82c686.c index 47b5e1c09..fa0bf3c63 100644 --- a/src/sio/sio_vt82c686.c +++ b/src/sio/sio_vt82c686.c @@ -287,8 +287,7 @@ vt82c686_close(void *priv) static void * vt82c686_init(UNUSED(const device_t *info)) { - vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t)); - memset(dev, 0, sizeof(vt82c686_t)); + vt82c686_t *dev = (vt82c686_t *) calloc(1, sizeof(vt82c686_t)); dev->fdc = device_add(&fdc_at_smc_device); dev->fdc_dma = 2; diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index 69bdb1220..ea5169afc 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -443,8 +443,7 @@ w83787f_close(void *priv) static void * w83787f_init(const device_t *info) { - w83787f_t *dev = (w83787f_t *) malloc(sizeof(w83787f_t)); - memset(dev, 0, sizeof(w83787f_t)); + w83787f_t *dev = (w83787f_t *) calloc(1, sizeof(w83787f_t)); HAS_IDE_FUNCTIONALITY = (info->local & 0x30); diff --git a/src/sio/sio_w83877f.c b/src/sio/sio_w83877f.c index a6ea6f4e4..90a3dba1b 100644 --- a/src/sio/sio_w83877f.c +++ b/src/sio/sio_w83877f.c @@ -444,8 +444,7 @@ w83877f_close(void *priv) static void * w83877f_init(const device_t *info) { - w83877f_t *dev = (w83877f_t *) malloc(sizeof(w83877f_t)); - memset(dev, 0, sizeof(w83877f_t)); + w83877f_t *dev = (w83877f_t *) calloc(1, sizeof(w83877f_t)); dev->fdc = device_add(&fdc_at_winbond_device); diff --git a/src/sio/sio_w83977f.c b/src/sio/sio_w83977f.c index 7df0163a5..1d743cc64 100644 --- a/src/sio/sio_w83977f.c +++ b/src/sio/sio_w83977f.c @@ -593,8 +593,7 @@ w83977f_close(void *priv) static void * w83977f_init(const device_t *info) { - w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t)); - memset(dev, 0, sizeof(w83977f_t)); + w83977f_t *dev = (w83977f_t *) calloc(1, sizeof(w83977f_t)); dev->type = info->local & 0x0f; dev->hefras = info->local & 0x40; diff --git a/src/sound/midi.c b/src/sound/midi.c index e9b4a82b6..9f83e88dc 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -157,8 +157,7 @@ midi_out_device_init(void) void midi_out_init(midi_device_t *device) { - midi_out = (midi_t *) malloc(sizeof(midi_t)); - memset(midi_out, 0, sizeof(midi_t)); + midi_out = (midi_t *) calloc(1, sizeof(midi_t)); midi_out->m_out_device = device; } @@ -166,8 +165,7 @@ midi_out_init(midi_device_t *device) void midi_in_init(midi_device_t *device, midi_t **mididev) { - *mididev = (midi_t *) malloc(sizeof(midi_t)); - memset(*mididev, 0, sizeof(midi_t)); + *mididev = (midi_t *) calloc(1, sizeof(midi_t)); (*mididev)->m_in_device = device; } @@ -394,8 +392,7 @@ midi_in_handler(int set, void (*msg)(void *priv, uint8_t *msg, uint32_t len), in if ((mih_first != NULL) && (mih_last == NULL)) fatal("First MIDI IN handler present with no last MIDI IN handler\n"); - temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t)); - memset(temp, 0, sizeof(midi_in_handler_t)); + temp = (midi_in_handler_t *) calloc(1, sizeof(midi_in_handler_t)); temp->msg = msg; temp->sysex = sysex; temp->priv = priv; diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 51383bdcf..6ba017cd1 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -262,8 +262,7 @@ fluidsynth_init(UNUSED(const device_t *info)) al_set_midi(data->samplerate, data->buf_size); - dev = malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + dev = calloc(1, sizeof(midi_device_t)); dev->play_msg = fluidsynth_msg; dev->play_sysex = fluidsynth_sysex; diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index f95445540..ab2165c52 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -298,8 +298,7 @@ mt32emu_init(char *control_rom, char *pcm_rom) al_set_midi(samplerate, buf_size); - dev = malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + dev = calloc(1, sizeof(midi_device_t)); dev->play_msg = mt32_msg; dev->play_sysex = mt32_sysex; diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index cf99e092d..e1f80b0f5 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -658,8 +658,7 @@ opl4_init(const device_t *info) midi_device_t *dev; extern void al_set_midi(int freq, int buf_size); - dev = malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + dev = calloc(1, sizeof(midi_device_t)); dev->play_msg = opl4_midi_msg; dev->play_sysex = opl4_midi_sysex; diff --git a/src/sound/midi_rtmidi.cpp b/src/sound/midi_rtmidi.cpp index e2458c9fe..9da3fdb91 100644 --- a/src/sound/midi_rtmidi.cpp +++ b/src/sound/midi_rtmidi.cpp @@ -73,8 +73,7 @@ rtmidi_play_sysex(uint8_t *sysex, unsigned int len) void * rtmidi_output_init(UNUSED(const device_t *info)) { - midi_device_t *dev = (midi_device_t *) malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + midi_device_t *dev = (midi_device_t *) calloc(1, sizeof(midi_device_t)); dev->play_msg = rtmidi_play_msg; dev->play_sysex = rtmidi_play_sysex; @@ -156,8 +155,7 @@ rtmidi_input_callback(UNUSED(double timeStamp), std::vector *mess void * rtmidi_input_init(UNUSED(const device_t *info)) { - midi_device_t *dev = (midi_device_t *) malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + midi_device_t *dev = (midi_device_t *) calloc(1, sizeof(midi_device_t)); try { if (!midiin) diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index f6c01c4ea..e92830f67 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -577,8 +577,7 @@ ac97_codec_getrate(void *priv, uint8_t reg) static void * ac97_codec_init(const device_t *info) { - ac97_codec_t *dev = malloc(sizeof(ac97_codec_t)); - memset(dev, 0, sizeof(ac97_codec_t)); + ac97_codec_t *dev = calloc(1, sizeof(ac97_codec_t)); for (; dev->model < (sizeof(ac97_codecs) / sizeof(ac97_codecs[0])); dev->model++) { if (ac97_codecs[dev->model].device->local == info->local) diff --git a/src/sound/snd_ac97_via.c b/src/sound/snd_ac97_via.c index e3fa9d2e4..8c1e45c40 100644 --- a/src/sound/snd_ac97_via.c +++ b/src/sound/snd_ac97_via.c @@ -787,8 +787,7 @@ ac97_via_speed_changed(void *priv) static void * ac97_via_init(UNUSED(const device_t *info)) { - ac97_via_t *dev = malloc(sizeof(ac97_via_t)); - memset(dev, 0, sizeof(ac97_via_t)); + ac97_via_t *dev = calloc(1, sizeof(ac97_via_t)); ac97_via_log("AC97 VIA: init()\n"); diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index 983ccf7d3..1f307596c 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -103,8 +103,7 @@ adlib_mca_feedb(void *priv) void * adlib_init(UNUSED(const device_t *info)) { - adlib_t *adlib = malloc(sizeof(adlib_t)); - memset(adlib, 0, sizeof(adlib_t)); + adlib_t *adlib = calloc(1, sizeof(adlib_t)); adlib_log("adlib_init\n"); fm_driver_get(FM_YM3812, &adlib->opl); diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 7b5deaac5..8a809803d 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -1066,8 +1066,7 @@ adgold_init(UNUSED(const device_t *info)) FILE *fp; int c; double out; - adgold_t *adgold = malloc(sizeof(adgold_t)); - memset(adgold, 0, sizeof(adgold_t)); + adgold_t *adgold = calloc(1, sizeof(adgold_t)); adgold->dma = device_get_config_int("dma"); adgold->irq = device_get_config_int("irq"); diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 07add5062..9e520bcf5 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -2645,8 +2645,7 @@ static void es137x_speed_changed(void *priv); static void * es1370_init(const device_t *info) { - es137x_t *dev = malloc(sizeof(es137x_t)); - memset(dev, 0x00, sizeof(es137x_t)); + es137x_t *dev = calloc(1, sizeof(es137x_t)); dev->type = info->local; if (device_get_config_int("receive_input")) @@ -2689,8 +2688,7 @@ es1370_init(const device_t *info) static void * es1371_init(const device_t *info) { - es137x_t *dev = malloc(sizeof(es137x_t)); - memset(dev, 0x00, sizeof(es137x_t)); + es137x_t *dev = calloc(1, sizeof(es137x_t)); dev->type = info->local & 0xffffff00; if (device_get_config_int("receive_input")) diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index cf05203f3..dfbab2bd3 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -974,8 +974,7 @@ azt_init(const device_t *info) int loaded_from_eeprom = 0; uint16_t addr_setting; uint8_t read_eeprom[AZTECH_EEPROM_SIZE]; - azt2316a_t *azt2316a = malloc(sizeof(azt2316a_t)); - memset(azt2316a, 0, sizeof(azt2316a_t)); + azt2316a_t *azt2316a = calloc(1, sizeof(azt2316a_t)); azt2316a->type = info->local; @@ -1226,8 +1225,7 @@ azt_init(const device_t *info) 2x4 to 2x5 -> Mixer interface 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices).*/ - azt2316a->sb = malloc(sizeof(sb_t)); - memset(azt2316a->sb, 0, sizeof(sb_t)); + azt2316a->sb = calloc(1, sizeof(sb_t)); azt2316a->sb->opl_enabled = device_get_config_int("opl"); @@ -1259,8 +1257,7 @@ azt_init(const device_t *info) sound_set_cd_audio_filter(sbpro_filter_cd_audio, azt2316a->sb); if (azt2316a->cur_mpu401_enabled) { - azt2316a->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(azt2316a->mpu, 0, sizeof(mpu_t)); + azt2316a->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(azt2316a->mpu, azt2316a->cur_mpu401_addr, azt2316a->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401")); } else azt2316a->mpu = NULL; diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index 833124bb2..5f75d0dc3 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -1434,8 +1434,7 @@ cmi8x38_reset(void *priv) static void * cmi8x38_init(const device_t *info) { - cmi8x38_t *dev = malloc(sizeof(cmi8x38_t)); - memset(dev, 0, sizeof(cmi8x38_t)); + cmi8x38_t *dev = calloc(1, sizeof(cmi8x38_t)); /* Set the chip type. */ if ((info->local == CMEDIA_CMI8738_6CH) && !device_get_config_int("six_channel")) diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 2ec81b53d..f8db04fed 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -181,8 +181,7 @@ cms_read(uint16_t addr, void *priv) void * cms_init(UNUSED(const device_t *info)) { - cms_t *cms = malloc(sizeof(cms_t)); - memset(cms, 0, sizeof(cms_t)); + cms_t *cms = calloc(1, sizeof(cms_t)); uint16_t addr = device_get_config_hex16("base"); io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 0a383e13f..d164e3ac6 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -468,10 +468,9 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) if (dev->slam_config) cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev); else - dev->slam_config = (isapnp_device_config_t *) malloc(sizeof(isapnp_device_config_t)); + dev->slam_config = (isapnp_device_config_t *) calloc(1, sizeof(isapnp_device_config_t)); /* Start new logical device. */ - memset(dev->slam_config, 0, sizeof(isapnp_device_config_t)); dev->slam_ld = val; break; @@ -846,8 +845,7 @@ cs423x_reset(void *priv) static void * cs423x_init(const device_t *info) { - cs423x_t *dev = malloc(sizeof(cs423x_t)); - memset(dev, 0, sizeof(cs423x_t)); + cs423x_t *dev = calloc(1, sizeof(cs423x_t)); /* Initialize model-specific data. */ dev->type = info->local & 0xff; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index 5f13d2f8e..8eb5260c0 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -2171,8 +2171,7 @@ emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) emu8k->rom[0x7ffff] = 0; } - emu8k->empty = malloc(2 * BLOCK_SIZE_WORDS); - memset(emu8k->empty, 0, 2 * BLOCK_SIZE_WORDS); + emu8k->empty = calloc(2, BLOCK_SIZE_WORDS); int j = 0; for (; j < 0x8; j++) { @@ -2186,8 +2185,7 @@ emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) /*Clip to 28MB, since that's the max that we can address. */ if (onboard_ram > 0x7000) onboard_ram = 0x7000; - emu8k->ram = malloc(onboard_ram * 1024); - memset(emu8k->ram, 0, onboard_ram * 1024); + emu8k->ram = calloc(1024, onboard_ram); const int i_end = onboard_ram >> 7; int i = 0; for (; i < i_end; i++, j++) { diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index b39d77708..9dcf0f00b 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1348,12 +1348,10 @@ gus_init(UNUSED(const device_t *info)) int c; double out = 1.0; uint8_t gus_ram = device_get_config_int("gus_ram"); - gus_t *gus = malloc(sizeof(gus_t)); - memset(gus, 0x00, sizeof(gus_t)); + gus_t *gus = calloc(1, sizeof(gus_t)); gus->gus_end_ram = 1 << (18 + gus_ram); - gus->ram = (uint8_t *) malloc(gus->gus_end_ram); - memset(gus->ram, 0x00, (gus->gus_end_ram)); + gus->ram = (uint8_t *) calloc(1, gus->gus_end_ram); for (c = 0; c < 32; c++) { gus->ctrl[c] = 1; diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index 8fb526f14..812a649a8 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -82,8 +82,7 @@ dac_get_buffer(int32_t *buffer, int len, void *priv) static void * dac_init(void *lpt) { - lpt_dac_t *lpt_dac = malloc(sizeof(lpt_dac_t)); - memset(lpt_dac, 0, sizeof(lpt_dac_t)); + lpt_dac_t *lpt_dac = calloc(1, sizeof(lpt_dac_t)); lpt_dac->lpt = lpt; diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index bd794fffb..06160ce4c 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -115,8 +115,7 @@ dss_callback(void *priv) static void * dss_init(void *lpt) { - dss_t *dss = malloc(sizeof(dss_t)); - memset(dss, 0, sizeof(dss_t)); + dss_t *dss = calloc(1, sizeof(dss_t)); dss->lpt = lpt; diff --git a/src/sound/snd_opl2board.c b/src/sound/snd_opl2board.c index f1bda3398..a76b6bf4d 100644 --- a/src/sound/snd_opl2board.c +++ b/src/sound/snd_opl2board.c @@ -124,8 +124,7 @@ opl2board_device_mca_feedb(void *priv) void * opl2board_device_init(UNUSED(const device_t *info)) { - opl2board_device_t *serial = malloc(sizeof(opl2board_device_t)); - memset(serial, 0, sizeof(opl2board_device_t)); + opl2board_device_t *serial = calloc(1, sizeof(opl2board_device_t)); opl2board_device_log("opl2board_device_init\n"); fm_driver_get(FM_OPL2BOARD, &serial->opl); diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index d69986d98..7058d918c 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -419,8 +419,7 @@ optimc_init(const device_t *info) music_add_handler(sb_get_music_buffer_sbpro, optimc->sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, optimc->sb); /* CD audio filter for the default context */ - optimc->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(optimc->mpu, 0, sizeof(mpu_t)); + optimc->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(optimc->mpu, optimc->cur_mpu401_addr, optimc->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401")); if (device_get_config_int("receive_input")) diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 110ee95c9..400f176a8 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -2320,8 +2320,7 @@ pas16_init(const device_t *info) fm_driver_get(FM_YMF262, &pas16->opl); sb_dsp_set_real_opl(&pas16->dsp, 1); sb_dsp_init(&pas16->dsp, SB_DSP_201, SB_SUBTYPE_DEFAULT, pas16); - pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(pas16->mpu, 0, sizeof(mpu_t)); + pas16->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&pas16->dsp, pas16->mpu); diff --git a/src/sound/snd_ps1.c b/src/sound/snd_ps1.c index 531c2a369..15cad0051 100644 --- a/src/sound/snd_ps1.c +++ b/src/sound/snd_ps1.c @@ -166,8 +166,7 @@ ps1snd_get_buffer(int32_t *buffer, int len, void *priv) static void * ps1snd_init(UNUSED(const device_t *info)) { - ps1snd_t *ps1snd = malloc(sizeof(ps1snd_t)); - memset(ps1snd, 0x00, sizeof(ps1snd_t)); + ps1snd_t *ps1snd = calloc(1, sizeof(ps1snd_t)); sn76489_init(&ps1snd->sn76489, 0x0205, 0x0001, SN76496, 4000000); diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 657f94b01..0b09a7b2e 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -193,8 +193,7 @@ pssj_get_buffer(int32_t *buffer, int len, void *priv) void * pssj_init(UNUSED(const device_t *info)) { - pssj_t *pssj = malloc(sizeof(pssj_t)); - memset(pssj, 0, sizeof(pssj_t)); + pssj_t *pssj = calloc(1, sizeof(pssj_t)); sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); @@ -208,8 +207,7 @@ pssj_init(UNUSED(const device_t *info)) void * pssj_1e0_init(UNUSED(const device_t *info)) { - pssj_t *pssj = malloc(sizeof(pssj_t)); - memset(pssj, 0, sizeof(pssj_t)); + pssj_t *pssj = calloc(1, sizeof(pssj_t)); sn76489_init(&pssj->sn76489, 0x01e0, 0x0004, PSSJ, 3579545); @@ -223,8 +221,7 @@ pssj_1e0_init(UNUSED(const device_t *info)) void * pssj_isa_init(UNUSED(const device_t *info)) { - pssj_t *pssj = malloc(sizeof(pssj_t)); - memset(pssj, 0, sizeof(pssj_t)); + pssj_t *pssj = calloc(1, sizeof(pssj_t)); uint16_t addr = device_get_config_hex16("base"); diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 8fb8db06e..89064bea4 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -228,8 +228,7 @@ sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int fre void * sn76489_device_init(UNUSED(const device_t *info)) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); - memset(sn76489, 0, sizeof(sn76489_t)); + sn76489_t *sn76489 = calloc(1, sizeof(sn76489_t)); sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545); @@ -239,8 +238,7 @@ sn76489_device_init(UNUSED(const device_t *info)) void * ncr8496_device_init(UNUSED(const device_t *info)) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); - memset(sn76489, 0, sizeof(sn76489_t)); + sn76489_t *sn76489 = calloc(1, sizeof(sn76489_t)); sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545); @@ -250,8 +248,7 @@ ncr8496_device_init(UNUSED(const device_t *info)) void * tndy_device_init(UNUSED(const device_t *info)) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); - memset(sn76489, 0, sizeof(sn76489_t)); + sn76489_t *sn76489 = calloc(1, sizeof(sn76489_t)); uint16_t addr = device_get_config_hex16("base"); diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index e03be6b4c..762b243be 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -70,8 +70,7 @@ ssi2001_write(uint16_t addr, uint8_t val, void *priv) void * ssi2001_init(UNUSED(const device_t *info)) { - ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); - memset(ssi2001, 0, sizeof(ssi2001_t)); + ssi2001_t *ssi2001 = calloc(1, sizeof(ssi2001_t)); ssi2001->psid = sid_init(0); sid_reset(ssi2001->psid); @@ -110,10 +109,8 @@ entertainer_write(uint16_t addr, uint8_t val, void *priv) void * entertainer_init(UNUSED(const device_t *info)) { - ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); - entertainer_t *entertainer = malloc(sizeof(entertainer_t)); - memset(ssi2001, 0, sizeof(ssi2001_t)); - memset(entertainer, 0, sizeof(entertainer_t)); + ssi2001_t *ssi2001 = calloc(1, sizeof(ssi2001_t)); + entertainer_t *entertainer = calloc(1, sizeof(entertainer_t)); ssi2001->psid = sid_init(0); sid_reset(ssi2001->psid); diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index 833308280..0f37cbf27 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -107,8 +107,7 @@ wss_get_music_buffer(int32_t *buffer, int len, void *priv) void * wss_init(UNUSED(const device_t *info)) { - wss_t *wss = malloc(sizeof(wss_t)); - memset(wss, 0, sizeof(wss_t)); + wss_t *wss = calloc(1, sizeof(wss_t)); uint16_t addr = device_get_config_hex16("base"); wss->opl_enabled = device_get_config_int("opl"); @@ -209,8 +208,7 @@ ncr_audio_mca_feedb(void *priv) void * ncr_audio_init(UNUSED(const device_t *info)) { - wss_t *wss = malloc(sizeof(wss_t)); - memset(wss, 0, sizeof(wss_t)); + wss_t *wss = calloc(1, sizeof(wss_t)); fm_driver_get(FM_YMF262, &wss->opl); ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT); From 403a7a995b2719f92d652d291338376f840832d3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 1 Feb 2025 21:39:15 +0100 Subject: [PATCH 0182/1190] New recompiler: read the two bytes of unaligned 16-bit immediates into the correct IR bytes, fixes Windows 95 Setup GPF'ing. --- src/codegen_new/codegen_ops_helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen_new/codegen_ops_helpers.c b/src/codegen_new/codegen_ops_helpers.c index f2a4ce41a..037d91469 100644 --- a/src/codegen_new/codegen_ops_helpers.c +++ b/src/codegen_new/codegen_ops_helpers.c @@ -18,8 +18,8 @@ void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(UNUSED(codeblock_t *block), ir_data_t *ir, int dest_reg, uint32_t addr) { /*Word access that crosses two pages. Perform reads from both pages, shift and combine*/ - uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr)); - uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr + 1)); + uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr + 1)); + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8); uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W); } From d881321268e64e574868b1330b8cfc8443f4b310 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 1 Feb 2025 22:19:55 +0100 Subject: [PATCH 0183/1190] Minor ATI 8514/A Ultra add-on change of the night (February 1st, 2025) Actually make it work on NT by setting bit 0 of the read only config2 reg. --- src/video/vid_ati_mach8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index c9cdca0db..0ef4df6df 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -6239,7 +6239,7 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) if (dev->vram_amount >= 1024) mach->config1 |= 0x20; - mach->config2 = 0x02; + mach->config2 = 0x01 | 0x02; } static int From 5f273265aed164af1280c30a5e84f079345bda7c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 26 Jan 2025 15:15:53 -0500 Subject: [PATCH 0184/1190] Assorted warning fixes --- src/86box.c | 4 +- src/acpi.c | 2 +- src/cdrom/cdrom.c | 4 +- src/cdrom/cdrom_image_viso.c | 2 +- src/chipset/ali1409.c | 7 +- src/chipset/sis_5513_p2i.c | 4 +- src/chipset/sis_5595_pmu.c | 2 +- src/chipset/umc_8890.c | 3 +- src/chipset/wd76c10.c | 3 +- src/codegen/codegen_ops_arith.h | 60 ++-- src/codegen/codegen_ops_fpu.h | 206 ++++++----- src/codegen/codegen_ops_jump.h | 94 ++--- src/codegen/codegen_ops_logic.h | 48 +-- src/codegen/codegen_ops_misc.h | 16 +- src/codegen/codegen_ops_mmx.h | 80 +++-- src/codegen/codegen_ops_mov.h | 58 +-- src/codegen/codegen_ops_shift.h | 12 +- src/codegen/codegen_ops_stack.h | 144 ++++---- src/codegen/codegen_ops_x86-64.h | 18 +- src/codegen/codegen_ops_xchg.h | 66 ++-- src/codegen/codegen_x86-64.c | 2 +- src/codegen_new/codegen_ir.c | 1 + src/codegen_new/codegen_ir_defs.h | 2 +- src/codegen_new/codegen_ops.c | 1 + src/codegen_new/codegen_ops_3dnow.c | 4 +- src/codegen_new/codegen_ops_arith.c | 28 +- src/codegen_new/codegen_ops_branch.c | 16 +- src/codegen_new/codegen_ops_fpu_arith.c | 52 +-- src/codegen_new/codegen_ops_fpu_constant.c | 4 +- src/codegen_new/codegen_ops_fpu_misc.c | 2 +- src/codegen_new/codegen_ops_helpers.h | 4 +- src/codegen_new/codegen_ops_jump.c | 30 +- src/codegen_new/codegen_ops_logic.c | 16 +- src/codegen_new/codegen_ops_misc.c | 28 +- src/codegen_new/codegen_ops_mmx_arith.c | 5 +- src/codegen_new/codegen_ops_mmx_cmp.c | 5 +- src/codegen_new/codegen_ops_mmx_pack.c | 5 +- src/codegen_new/codegen_ops_mov.c | 22 +- src/codegen_new/codegen_ops_stack.c | 42 +-- src/cpu/386.c | 1 + src/cpu/386_common.c | 8 +- src/cpu/386_dynarec.c | 1 + src/cpu/808x.c | 5 +- src/cpu/codegen_timing_486.c | 2 +- src/cpu/codegen_timing_k5.c | 5 +- src/cpu/codegen_timing_k6.c | 5 +- src/cpu/codegen_timing_p6.c | 4 +- src/cpu/codegen_timing_winchip.c | 2 +- src/cpu/codegen_timing_winchip2.c | 2 +- src/cpu/x86_ops_3dnow.h | 50 +-- src/cpu/x86_ops_arith.h | 6 +- src/cpu/x86_ops_bcd.h | 8 +- src/cpu/x86_ops_call.h | 2 +- src/cpu/x86_ops_cyrix.h | 10 +- src/cpu/x86_ops_flag.h | 30 +- src/cpu/x86_ops_flag_2386.h | 30 +- src/cpu/x86_ops_fpu.h | 2 +- src/cpu/x86_ops_fpu_2386.h | 2 +- src/cpu/x86_ops_inc_dec.h | 2 +- src/cpu/x86_ops_int.h | 6 +- src/cpu/x86_ops_io.h | 12 +- src/cpu/x86_ops_jump.h | 12 +- src/cpu/x86_ops_misc.h | 32 +- src/cpu/x86_ops_mmx.h | 2 +- src/cpu/x86_ops_mov.h | 32 +- src/cpu/x86_ops_msr.h | 4 +- src/cpu/x86_ops_pmode.h | 12 +- src/cpu/x86_ops_rep.h | 42 +-- src/cpu/x86_ops_rep_2386.h | 42 +-- src/cpu/x86_ops_rep_dyn.h | 42 +-- src/cpu/x86_ops_ret.h | 12 +- src/cpu/x86_ops_ret_2386.h | 12 +- src/cpu/x86_ops_stack.h | 30 +- src/cpu/x86_ops_string.h | 84 ++--- src/cpu/x86_ops_string_2386.h | 84 ++--- src/cpu/x86_ops_xchg.h | 32 +- src/cpu/x87.c | 3 +- src/cpu/x87_ops.h | 2 +- src/cpu/x87_ops_arith.h | 24 +- src/cpu/x87_ops_loadstore.h | 36 +- src/cpu/x87_ops_misc.h | 76 ++-- src/cpu/x87_ops_sf.h | 22 +- src/cpu/x87_ops_sf_arith.h | 12 +- src/cpu/x87_ops_sf_compare.h | 2 +- src/cpu/x87_ops_sf_misc.h | 4 +- src/device/mouse_microtouch_touchscreen.c | 4 +- src/device/nec_mate_unk.c | 4 +- src/device/novell_cardkey.c | 2 +- src/disk/hdc_ide.c | 6 +- src/disk/lba_enhancer.c | 2 +- src/disk/mo.c | 4 +- src/disk/zip.c | 4 +- src/floppy/fdc_compaticard.c | 5 +- src/floppy/fdd_pcjs.c | 2 +- src/game/gameport.c | 2 +- src/include/86box/bswap.h | 4 +- src/include/86box/cdrom.h | 17 +- src/machine/m_at_grid.c | 3 +- src/network/net_3c501.c | 1 - src/network/net_3c503.c | 1 - src/network/net_modem.c | 4 +- src/network/net_ne2000.c | 1 - src/network/net_pcnet.c | 2 +- src/network/net_rtl8139.c | 6 +- src/network/net_tulip.c | 2 +- src/network/net_wd8003.c | 1 - src/pic.c | 2 +- src/qt/dummy_cdrom_ioctl.c | 4 +- src/qt/qt_main.cpp | 18 +- src/qt/qt_platform.cpp | 3 +- src/scsi/scsi_cdrom.c | 10 +- src/scsi/scsi_disk.c | 4 +- src/sio/sio_it86x1f.c | 8 +- src/sio/sio_pc87306.c | 2 +- src/sio/sio_vl82c113.c | 3 +- src/sound/midi_opl4.c | 7 +- src/sound/snd_emu8k.c | 2 +- src/sound/snd_opl_esfm.c | 3 +- src/sound/snd_pas16.c | 2 +- src/sound/snd_resid.cpp | 6 +- src/sound/snd_sb.c | 6 +- src/sound/snd_ssi2001.c | 24 +- src/unix/dummy_cdrom_ioctl.c | 4 +- src/unix/unix.c | 29 +- src/unix/unix_cdrom.c | 4 +- src/unix/unix_sdl.c | 6 +- src/video/vid_ati_mach8.c | 2 +- src/video/vid_bt481_ramdac.c | 3 +- src/video/vid_cga.c | 2 +- src/video/vid_chips_69000.c | 80 ++--- src/video/vid_mga.c | 2 +- src/video/vid_svga.c | 2 +- src/video/vid_table.c | 392 ++++++++++----------- src/video/vid_tgui9440.c | 2 +- src/video/vid_voodoo_banshee.c | 2 +- src/video/vid_xga.c | 2 +- 136 files changed, 1374 insertions(+), 1291 deletions(-) diff --git a/src/86box.c b/src/86box.c index e2cc55e75..246d06b16 100644 --- a/src/86box.c +++ b/src/86box.c @@ -293,7 +293,7 @@ void pclog_ensure_stdlog_open(void) * being logged, and catch repeating entries. */ void -pclog_ex(const char *fmt, va_list ap) +pclog_ex(UNUSED(const char *fmt), UNUSED(va_list ap)) { #ifndef RELEASE_BUILD char temp[LOG_SIZE_BUFFER]; @@ -330,7 +330,7 @@ pclog_toggle_suppr(void) /* Log something. We only do this in non-release builds. */ void -pclog(const char *fmt, ...) +pclog(UNUSED(const char *fmt), ...) { #ifndef RELEASE_BUILD va_list ap; diff --git a/src/acpi.c b/src/acpi.c index 0d5c1fe00..2850a340d 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -89,7 +89,7 @@ acpi_timer_get(acpi_t *dev) } static uint8_t -acpi_gp_timer_get(acpi_t *dev) +acpi_gp_timer_get(UNUSED(acpi_t *dev)) { uint64_t clock = acpi_clock_get(); clock -= acpi_last_clock; diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 595d89f70..4ccb81442 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -593,7 +593,7 @@ read_toc_raw(const cdrom_t *dev, unsigned char *b, const unsigned char start_tra } static int -track_type_is_valid(const cdrom_t *dev, const int type, const int flags, const int audio, +track_type_is_valid(UNUSED(const cdrom_t *dev), const int type, const int flags, const int audio, const int mode2) { if (!(flags & 0x70) && (flags & 0xf8)) { /* 0x08/0x80/0x88 are illegal modes */ @@ -1968,7 +1968,7 @@ cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf) /* TODO: Actually implement this properly. */ void -cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode) +cdrom_get_q(UNUSED(cdrom_t *dev), uint8_t *buf, UNUSED(int *curtoctrk), UNUSED(uint8_t mode)) { memset(buf, 0x00, 10); } diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index 52657e38d..4bf976794 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -32,13 +32,13 @@ #include #include #include <86box/86box.h> -#include <86box/bswap.h> #include <86box/cdrom.h> #include <86box/cdrom_image.h> #include <86box/cdrom_image_viso.h> #include <86box/log.h> #include <86box/path.h> #include <86box/plat.h> +#include <86box/bswap.h> #include <86box/plat_dir.h> #include <86box/version.h> #include <86box/nvr.h> diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c index 5644d4077..5009a6505 100644 --- a/src/chipset/ali1409.c +++ b/src/chipset/ali1409.c @@ -40,9 +40,8 @@ #include <86box/fdc.h> #include <86box/smram.h> #include <86box/chipset.h> - +#include <86box/plat_unused.h> - #ifdef ENABLE_ALI1409_LOG int ali1409_do_log = ENABLE_ALI1409_LOG; @@ -161,7 +160,7 @@ ali1409_close(void *priv) } static void * -ali1409_init(const device_t *info) +ali1409_init(UNUSED(const device_t *info)) { ali1409_t *dev = (ali1409_t *) calloc(1, sizeof(ali1409_t)); @@ -172,7 +171,7 @@ ali1409_init(const device_t *info) 23h Data Port */ - ali1409_log ("Bus speed: %i",cpu_busspeed); + ali1409_log ("Bus speed: %i", cpu_busspeed); io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index e7012e1b6..3655ccc3f 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -115,7 +115,7 @@ sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev) } static void -sis_5513_apc_write(uint16_t addr, uint8_t val, void *priv) +sis_5513_apc_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; uint8_t nvr_index = nvr_get_index(dev->nvr, 0); @@ -135,7 +135,7 @@ sis_5513_apc_write(uint16_t addr, uint8_t val, void *priv) } static uint8_t -sis_5513_apc_read(uint16_t addr, void *priv) +sis_5513_apc_read(UNUSED(uint16_t addr), void *priv) { sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; uint8_t nvr_index = nvr_get_index(dev->nvr, 0); diff --git a/src/chipset/sis_5595_pmu.c b/src/chipset/sis_5595_pmu.c index 2f5aa10b1..7de9735f1 100644 --- a/src/chipset/sis_5595_pmu.c +++ b/src/chipset/sis_5595_pmu.c @@ -119,7 +119,7 @@ sis_5595_pmu_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, v } static void -sis_5595_pmu_trap_io_ide_bm(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +sis_5595_pmu_trap_io_ide_bm(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), void *priv) { sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv; diff --git a/src/chipset/umc_8890.c b/src/chipset/umc_8890.c index 37862e2fc..cb69ce6a8 100644 --- a/src/chipset/umc_8890.c +++ b/src/chipset/umc_8890.c @@ -38,6 +38,7 @@ #include <86box/smram.h> #include <86box/chipset.h> +#include <86box/plat_unused.h> #ifdef ENABLE_UMC_8890_LOG int umc_8890_do_log = ENABLE_UMC_8890_LOG; @@ -209,7 +210,7 @@ umc_8890_close(void *priv) static void * -umc_8890_init(const device_t *info) +umc_8890_init(UNUSED(const device_t *info)) { umc_8890_t *dev = (umc_8890_t *) calloc(1, sizeof(umc_8890_t)); diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index 9b13dc5da..d7d8b0fe2 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -37,6 +37,7 @@ #include <86box/port_92.h> #include <86box/serial.h> #include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> /* Lock/Unlock Procedures */ @@ -879,7 +880,7 @@ wd76c10_reset(void *priv) static void * -wd76c10_init(const device_t *info) +wd76c10_init(UNUSED(const device_t *info)) { wd76c10_t *dev = (wd76c10_t *) calloc(1, sizeof(wd76c10_t)); uint32_t total_mem = mem_size << 10; diff --git a/src/codegen/codegen_ops_arith.h b/src/codegen/codegen_ops_arith.h index 28ee6d06c..50ef4310f 100644 --- a/src/codegen/codegen_ops_arith.h +++ b/src/codegen/codegen_ops_arith.h @@ -1,5 +1,5 @@ static uint32_t -ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropINC_rw(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -22,7 +22,7 @@ ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc; } static uint32_t -ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropINC_rl(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -45,7 +45,7 @@ ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc; } static uint32_t -ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropDEC_rw(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -68,7 +68,7 @@ ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc; } static uint32_t -ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropDEC_rl(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -93,7 +93,7 @@ ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod #define ROP_ARITH_RMW(name, op, writeback) \ static uint32_t \ - rop##name##_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_b_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -129,7 +129,7 @@ ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc + 1; \ } \ static uint32_t \ - rop##name##_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_w_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -165,7 +165,7 @@ ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc + 1; \ } \ static uint32_t \ - rop##name##_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_l_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -203,7 +203,7 @@ ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod #define ROP_ARITH_RM(name, op, writeback) \ static uint32_t \ - rop##name##_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_b_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -233,7 +233,7 @@ ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc + 1; \ } \ static uint32_t \ - rop##name##_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_w_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -263,7 +263,7 @@ ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc + 1; \ } \ static uint32_t \ - rop##name##_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_l_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -299,7 +299,7 @@ ROP_ARITH_RM(ADD, ADD, 1) ROP_ARITH_RM(SUB, SUB, 1) static uint32_t -ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_b_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -326,7 +326,7 @@ ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc + 1; } static uint32_t -ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_w_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -353,7 +353,7 @@ ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc + 1; } static uint32_t -ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_l_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -381,7 +381,7 @@ ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c } static uint32_t -ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_b_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -408,7 +408,7 @@ ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_w_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -435,7 +435,7 @@ ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_l_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -463,7 +463,7 @@ ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropADD_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -478,7 +478,7 @@ ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropADD_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -493,7 +493,7 @@ ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropADD_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -510,7 +510,7 @@ ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc } static uint32_t -ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -525,7 +525,7 @@ ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -540,7 +540,7 @@ ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCMP_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -557,7 +557,7 @@ ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc } static uint32_t -ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropSUB_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -572,7 +572,7 @@ ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropSUB_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -587,7 +587,7 @@ ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropSUB_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -604,7 +604,7 @@ ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc } static uint32_t -rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +rop80(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; uint32_t imm; @@ -679,7 +679,7 @@ rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblo } static uint32_t -rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +rop81_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; uint32_t imm; @@ -753,7 +753,7 @@ rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc + 3; } static uint32_t -rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +rop81_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; uint32_t imm; @@ -827,7 +827,7 @@ rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb } static uint32_t -rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +rop83_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; uint32_t imm; @@ -904,7 +904,7 @@ rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc + 2; } static uint32_t -rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +rop83_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; uint32_t imm; diff --git a/src/codegen/codegen_ops_fpu.h b/src/codegen/codegen_ops_fpu.h index 242743dee..a82b10d82 100644 --- a/src/codegen/codegen_ops_fpu.h +++ b/src/codegen/codegen_ops_fpu.h @@ -1,5 +1,5 @@ static uint32_t -ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFXCH(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); @@ -9,7 +9,7 @@ ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb } static uint32_t -ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFLD(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); @@ -19,7 +19,7 @@ ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codebl } static uint32_t -ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFST(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); @@ -28,7 +28,7 @@ ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codebl return op_pc; } static uint32_t -ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSTP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); @@ -39,7 +39,7 @@ ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb } static uint32_t -ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFLDs(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; @@ -57,7 +57,7 @@ ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc + 1; } static uint32_t -ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFLDd(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; @@ -76,7 +76,7 @@ ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb } static uint32_t -ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFILDw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; @@ -94,7 +94,7 @@ ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc + 1; } static uint32_t -ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFILDl(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; @@ -112,7 +112,7 @@ ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc + 1; } static uint32_t -ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFILDq(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; @@ -133,7 +133,7 @@ ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code } static uint32_t -ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSTs(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg; @@ -153,7 +153,7 @@ ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc + 1; } static uint32_t -ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSTd(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg1; @@ -194,24 +194,28 @@ ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return new_pc; } -#define ropFarith(name, size, load, op) \ - static uint32_t \ - ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(FPU_##name); \ - \ - return op_pc + 1; \ +#define ropFarith(name, size, load, op) \ + static uint32_t \ + ropF##name##size(UNUSED(uint8_t opcode), \ + uint32_t fetchdat, \ + uint32_t op_32, \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + x86seg *target_seg; \ + \ + FP_ENTER(); \ + op_pc--; \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + load(target_seg); \ + \ + op(FPU_##name); \ + \ + return op_pc + 1; \ } ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); @@ -239,32 +243,40 @@ ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -#define ropFcompare(name, size, load, op) \ - static uint32_t \ - ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(); \ - \ - return op_pc + 1; \ - } \ - static uint32_t ropF##name##P##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - uint32_t new_pc = ropF##name##size(opcode, fetchdat, op_32, op_pc, block); \ - \ - FP_POP(); \ - \ - return new_pc; \ +#define ropFcompare(name, size, load, op) \ + static uint32_t \ + ropF##name##size(UNUSED(uint8_t opcode), \ + uint32_t fetchdat, \ + uint32_t op_32, \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + x86seg *target_seg; \ + \ + FP_ENTER(); \ + op_pc--; \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + load(target_seg); \ + \ + op(); \ + \ + return op_pc + 1; \ + } \ + static uint32_t ropF##name##P##size(uint8_t opcode, \ + uint32_t fetchdat, \ + uint32_t op_32, \ + uint32_t op_pc, \ + codeblock_t *block) \ + { \ + uint32_t new_pc = ropF##name##size(opcode, fetchdat, op_32, op_pc, block); \ + \ + FP_POP(); \ + \ + return new_pc; \ } ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S); @@ -348,7 +360,7 @@ ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code #endif static uint32_t -ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFADD(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_ADD, 0, opcode & 7); @@ -356,7 +368,7 @@ ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc; } static uint32_t -ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFCOM(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_COMPARE_REG(0, opcode & 7); @@ -364,7 +376,7 @@ ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc; } static uint32_t -ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFDIV(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_DIV, 0, opcode & 7); @@ -372,7 +384,7 @@ ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc; } static uint32_t -ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFDIVR(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_DIVR, 0, opcode & 7); @@ -380,7 +392,7 @@ ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFMUL(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_MUL, 0, opcode & 7); @@ -388,7 +400,7 @@ ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc; } static uint32_t -ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSUB(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_SUB, 0, opcode & 7); @@ -396,7 +408,7 @@ ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc; } static uint32_t -ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSUBR(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_SUBR, 0, opcode & 7); @@ -405,7 +417,7 @@ ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code } static uint32_t -ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFADDr(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_ADD, opcode & 7, 0); @@ -413,7 +425,7 @@ ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFDIVr(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_DIV, opcode & 7, 0); @@ -421,7 +433,7 @@ ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFDIVRr(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_DIVR, opcode & 7, 0); @@ -429,7 +441,7 @@ ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc; } static uint32_t -ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFMULr(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_MUL, opcode & 7, 0); @@ -437,7 +449,7 @@ ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSUBr(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_SUB, opcode & 7, 0); @@ -445,7 +457,7 @@ ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSUBRr(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_SUBR, opcode & 7, 0); @@ -454,7 +466,7 @@ ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFADDP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_ADD, opcode & 7, 0); @@ -463,7 +475,7 @@ ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFCOMP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_COMPARE_REG(0, opcode & 7); @@ -472,7 +484,7 @@ ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFDIVP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_DIV, opcode & 7, 0); @@ -481,7 +493,7 @@ ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFDIVRP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_DIVR, opcode & 7, 0); @@ -490,7 +502,7 @@ ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc; } static uint32_t -ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFMULP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_MUL, opcode & 7, 0); @@ -499,7 +511,7 @@ ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSUBP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_SUB, opcode & 7, 0); @@ -508,7 +520,7 @@ ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc; } static uint32_t -ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSUBRP(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_OP_REG(FPU_SUBR, opcode & 7, 0); @@ -518,7 +530,7 @@ ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFCOMPP(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_COMPARE_REG(0, 1); @@ -528,7 +540,7 @@ ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSTSW_AX(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -540,7 +552,7 @@ ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c } static uint32_t -ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFISTw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg; @@ -560,7 +572,7 @@ ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc + 1; } static uint32_t -ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFISTl(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg; @@ -599,7 +611,7 @@ ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return new_pc; } static uint32_t -ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFISTPq(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg1; @@ -623,7 +635,7 @@ ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFLDCW(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; @@ -640,7 +652,7 @@ ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc + 1; } static uint32_t -ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFSTCW(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; x86seg *target_seg; @@ -658,7 +670,7 @@ ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code } static uint32_t -ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFCHS(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_FCHS(); @@ -666,17 +678,21 @@ ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc; } -#define opFLDimm(name, v) \ - static uint32_t \ - ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - static double fp_imm = v; \ - static uint64_t *fptr = (uint64_t *) &fp_imm; \ - \ - FP_ENTER(); \ - FP_LOAD_IMM_Q(*fptr); \ - \ - return op_pc; \ +#define opFLDimm(name, v) \ + static uint32_t \ + ropFLD##name(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + static double fp_imm = v; \ + static uint64_t *fptr = (uint64_t *) &fp_imm; \ + \ + FP_ENTER(); \ + FP_LOAD_IMM_Q(*fptr); \ + \ + return op_pc; \ } // clang-format off @@ -689,7 +705,7 @@ opFLDimm(Z, 0.0) // clang-format on static uint32_t -ropFLDLN2(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) +ropFLDLN2(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { FP_ENTER(); FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ULL); diff --git a/src/codegen/codegen_ops_jump.h b/src/codegen/codegen_ops_jump.h index da16ce03e..4572b623b 100644 --- a/src/codegen/codegen_ops_jump.h +++ b/src/codegen/codegen_ops_jump.h @@ -1,5 +1,5 @@ static uint32_t -ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropJMP_r8(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t offset = fetchdat & 0xff; @@ -12,7 +12,7 @@ ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropJMP_r16(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint16_t offset = fetchdat & 0xffff; @@ -22,7 +22,7 @@ ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co } static uint32_t -ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropJMP_r32(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t offset = fastreadl(cs + op_pc); @@ -32,7 +32,7 @@ ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co } static uint32_t -ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropJCXZ(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t offset = fetchdat & 0xff; @@ -51,7 +51,7 @@ ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb } static uint32_t -ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropLOOP(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t offset = fetchdat & 0xff; @@ -214,45 +214,51 @@ BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) } } -#define ropBRANCH(name, func, not ) \ - static uint32_t \ - rop##name(uint8_t opcode, uint32_t fetchdat, \ - uint32_t op_32, uint32_t op_pc, \ - codeblock_t *block) \ - { \ - uint32_t offset = fetchdat & 0xff; \ - \ - if (offset & 0x80) \ - offset |= 0xffffff00; \ - \ - func(1, op_pc, offset, not ); \ - \ - return op_pc + 1; \ - } \ - static uint32_t \ - rop##name##_w(uint8_t opcode, \ - uint32_t fetchdat, uint32_t op_32, \ - uint32_t op_pc, codeblock_t *block) \ - { \ - uint32_t offset = fetchdat & 0xffff; \ - \ - if (offset & 0x8000) \ - offset |= 0xffff0000; \ - \ - func(2, op_pc, offset, not ); \ - \ - return op_pc + 2; \ - } \ - static uint32_t \ - rop##name##_l(uint8_t opcode, \ - uint32_t fetchdat, uint32_t op_32, \ - uint32_t op_pc, codeblock_t *block) \ - { \ - uint32_t offset = fastreadl(cs + op_pc); \ - \ - func(4, op_pc, offset, not ); \ - \ - return op_pc + 4; \ +#define ropBRANCH(name, func, not ) \ + static uint32_t \ + rop##name(UNUSED(uint8_t opcode), \ + uint32_t fetchdat, \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + uint32_t offset = fetchdat & 0xff; \ + \ + if (offset & 0x80) \ + offset |= 0xffffff00; \ + \ + func(1, op_pc, offset, not ); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_w(UNUSED(uint8_t opcode), \ + uint32_t fetchdat, \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + uint32_t offset = fetchdat & 0xffff; \ + \ + if (offset & 0x8000) \ + offset |= 0xffff0000; \ + \ + func(2, op_pc, offset, not ); \ + \ + return op_pc + 2; \ + } \ + static uint32_t \ + rop##name##_l(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + uint32_t offset = fastreadl(cs + op_pc); \ + \ + func(4, op_pc, offset, not ); \ + \ + return op_pc + 4; \ } // clang-format off diff --git a/src/codegen/codegen_ops_logic.h b/src/codegen/codegen_ops_logic.h index 9f23723e2..2c79c4a2d 100644 --- a/src/codegen/codegen_ops_logic.h +++ b/src/codegen/codegen_ops_logic.h @@ -1,6 +1,6 @@ #define ROP_LOGIC(name, op, writeback) \ static uint32_t \ - rop##name##_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_b_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -33,7 +33,7 @@ return op_pc + 1; \ } \ static uint32_t \ - rop##name##_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_w_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -66,7 +66,7 @@ return op_pc + 1; \ } \ static uint32_t \ - rop##name##_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_l_rmw(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -99,7 +99,7 @@ return op_pc + 1; \ } \ static uint32_t \ - rop##name##_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_b_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -126,7 +126,7 @@ return op_pc + 1; \ } \ static uint32_t \ - rop##name##_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_w_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -153,7 +153,7 @@ return op_pc + 1; \ } \ static uint32_t \ - rop##name##_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + rop##name##_l_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int src_reg; \ int dst_reg; \ @@ -185,7 +185,7 @@ ROP_LOGIC(OR, OR, 1) ROP_LOGIC(XOR, XOR, 1) static uint32_t -ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropTEST_b_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -209,7 +209,7 @@ ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropTEST_w_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -233,7 +233,7 @@ ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropTEST_l_rm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -258,7 +258,7 @@ ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropAND_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -270,7 +270,7 @@ ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropAND_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -282,7 +282,7 @@ ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropAND_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -296,7 +296,7 @@ ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc } static uint32_t -ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropOR_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -308,7 +308,7 @@ ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropOR_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -320,7 +320,7 @@ ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropOR_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -334,7 +334,7 @@ ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropTEST_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -346,7 +346,7 @@ ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc return op_pc + 1; } static uint32_t -ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropTEST_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -358,7 +358,7 @@ ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc return op_pc + 2; } static uint32_t -ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropTEST_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -372,7 +372,7 @@ ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_p } static uint32_t -ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropXOR_AL_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B(REG_AL); @@ -384,7 +384,7 @@ ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropXOR_AX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W(REG_AX); @@ -396,7 +396,7 @@ ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropXOR_EAX_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_L(REG_EAX); @@ -410,7 +410,7 @@ ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc } static uint32_t -ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropF6(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg; @@ -458,7 +458,7 @@ ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblo return 0; } static uint32_t -ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropF7_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg; @@ -506,7 +506,7 @@ ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return 0; } static uint32_t -ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropF7_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg; int host_reg; diff --git a/src/codegen/codegen_ops_misc.h b/src/codegen/codegen_ops_misc.h index 61854ab37..db16dc09e 100644 --- a/src/codegen/codegen_ops_misc.h +++ b/src/codegen/codegen_ops_misc.h @@ -1,24 +1,24 @@ static uint32_t -ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropNOP(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { return op_pc; } static uint32_t -ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCLD(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { CLEAR_BITS((uintptr_t) &cpu_state.flags, D_FLAG); return op_pc; } static uint32_t -ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropSTD(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { SET_BITS((uintptr_t) &cpu_state.flags, D_FLAG); return op_pc; } static uint32_t -ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCLI(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) return 0; @@ -29,7 +29,7 @@ ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codebl return op_pc; } static uint32_t -ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropSTI(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) return 0; @@ -38,7 +38,7 @@ ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codebl } static uint32_t -ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFE(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int host_reg; @@ -88,7 +88,7 @@ ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblo } static uint32_t codegen_temp; static uint32_t -ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFF_16(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int host_reg; @@ -175,7 +175,7 @@ ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return 0; } static uint32_t -ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropFF_32(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int host_reg; diff --git a/src/codegen/codegen_ops_mmx.h b/src/codegen/codegen_ops_mmx.h index 4c5a92c8f..2e07bde77 100644 --- a/src/codegen/codegen_ops_mmx.h +++ b/src/codegen/codegen_ops_mmx.h @@ -1,5 +1,5 @@ static uint32_t -ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVQ_q_mm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg1; int host_reg2 = 0; @@ -25,7 +25,7 @@ ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVQ_mm_q(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { MMX_ENTER(); @@ -50,7 +50,7 @@ ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVD_l_mm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -74,7 +74,7 @@ ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVD_mm_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { MMX_ENTER(); @@ -95,36 +95,40 @@ ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } -#define MMX_OP(name, func) \ - static uint32_t \ - name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg1; \ - int src_reg2; \ - int xmm_src; \ - int xmm_dst; \ - \ - MMX_ENTER(); \ - \ - if ((fetchdat & 0xc0) == 0xc0) { \ - xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ - } else { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - \ - MEM_LOAD_ADDR_EA_Q(target_seg); \ - src_reg1 = LOAD_Q_REG_1; \ - src_reg2 = LOAD_Q_REG_2; \ - xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ - } \ - xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \ - func(xmm_dst, xmm_src); \ - STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \ - \ - return op_pc + 1; \ +#define MMX_OP(name, func) \ + static uint32_t \ + name(UNUSED(uint8_t opcode), \ + uint32_t fetchdat, \ + uint32_t op_32, \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + int src_reg1; \ + int src_reg2; \ + int xmm_src; \ + int xmm_dst; \ + \ + MMX_ENTER(); \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + \ + MEM_LOAD_ADDR_EA_Q(target_seg); \ + src_reg1 = LOAD_Q_REG_1; \ + src_reg2 = LOAD_Q_REG_2; \ + xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ + } \ + xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \ + func(xmm_dst, xmm_src); \ + STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \ + \ + return op_pc + 1; \ } MMX_OP(ropPAND, MMX_AND) @@ -179,7 +183,7 @@ MMX_OP(ropPMULHW, MMX_PMULHW); MMX_OP(ropPMADDWD, MMX_PMADDWD); static uint32_t -ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPSxxW_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int xmm_dst; @@ -207,7 +211,7 @@ ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPSxxD_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int xmm_dst; @@ -235,7 +239,7 @@ ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPSxxQ_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int xmm_dst; @@ -264,7 +268,7 @@ ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropEMMS(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc), UNUSED(codeblock_t *block)) { codegen_mmx_entered = 0; diff --git a/src/codegen/codegen_ops_mov.h b/src/codegen/codegen_ops_mov.h index 04c4bf2bc..039489035 100644 --- a/src/codegen/codegen_ops_mov.h +++ b/src/codegen/codegen_ops_mov.h @@ -1,19 +1,19 @@ static uint32_t -ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff); return op_pc + 1; } static uint32_t -ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff); return op_pc + 2; } static uint32_t -ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { fetchdat = fastreadl(cs + op_pc); @@ -23,7 +23,7 @@ ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_b_r(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); @@ -44,7 +44,7 @@ ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co return op_pc + 1; } static uint32_t -ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_w_r(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); @@ -66,7 +66,7 @@ ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co } static uint32_t -ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_l_r(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -90,7 +90,7 @@ ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co } static uint32_t -ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_r_b(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); @@ -109,7 +109,7 @@ ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co return op_pc + 1; } static uint32_t -ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_r_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_W(fetchdat & 7); @@ -128,7 +128,7 @@ ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co return op_pc + 1; } static uint32_t -ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_r_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_L(fetchdat & 7); @@ -148,7 +148,7 @@ ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co } static uint32_t -ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_b_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); @@ -167,7 +167,7 @@ ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 2; } static uint32_t -ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_w_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); @@ -186,7 +186,7 @@ ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 3; } static uint32_t -ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_l_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { uint32_t imm = fastreadl(cs + op_pc + 1); @@ -208,7 +208,7 @@ ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_AL_a(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t addr; @@ -226,7 +226,7 @@ ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc + ((op_32 & 0x200) ? 4 : 2); } static uint32_t -ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_AX_a(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t addr; @@ -244,7 +244,7 @@ ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc + ((op_32 & 0x200) ? 4 : 2); } static uint32_t -ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_EAX_a(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t addr; @@ -263,7 +263,7 @@ ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_a_AL(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t addr; int host_reg; @@ -284,7 +284,7 @@ ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc + ((op_32 & 0x200) ? 4 : 2); } static uint32_t -ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_a_AX(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t addr; int host_reg; @@ -305,7 +305,7 @@ ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc + ((op_32 & 0x200) ? 4 : 2); } static uint32_t -ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_a_EAX(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t addr; int host_reg; @@ -327,7 +327,7 @@ ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropLEA_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int dest_reg = (fetchdat >> 3) & 7; @@ -341,7 +341,7 @@ ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code return op_pc + 1; } static uint32_t -ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropLEA_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int dest_reg = (fetchdat >> 3) & 7; @@ -356,7 +356,7 @@ ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, code } static uint32_t -ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVZX_w_b(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); @@ -377,7 +377,7 @@ ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVZX_l_b(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); @@ -398,7 +398,7 @@ ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVZX_l_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_W(fetchdat & 7); @@ -420,7 +420,7 @@ ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVSX_w_b(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); @@ -441,7 +441,7 @@ ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVSX_l_b(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); @@ -462,7 +462,7 @@ ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOVSX_l_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_W(fetchdat & 7); @@ -484,7 +484,7 @@ ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_w_seg(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -531,7 +531,7 @@ ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return op_pc + 1; } static uint32_t -ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropMOV_seg_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -578,7 +578,7 @@ ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } #define ropLseg(seg, rseg) \ - static uint32_t ropL##seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + static uint32_t ropL##seg(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) \ { \ int dest_reg = (fetchdat >> 3) & 7; \ x86seg *target_seg; \ diff --git a/src/codegen/codegen_ops_shift.h b/src/codegen/codegen_ops_shift.h index d750bfcad..a36fb3fdc 100644 --- a/src/codegen/codegen_ops_shift.h +++ b/src/codegen/codegen_ops_shift.h @@ -43,7 +43,7 @@ } static uint32_t -ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropC0(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int count; @@ -57,7 +57,7 @@ ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblo return op_pc + 2; } static uint32_t -ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropC1_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int count; @@ -71,7 +71,7 @@ ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc + 2; } static uint32_t -ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropC1_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int count; @@ -86,7 +86,7 @@ ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb } static uint32_t -ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropD0(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int count = 1; @@ -100,7 +100,7 @@ ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblo return op_pc + 1; } static uint32_t -ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropD1_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int count = 1; @@ -114,7 +114,7 @@ ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb return op_pc + 1; } static uint32_t -ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropD1_l(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, UNUSED(codeblock_t *block)) { x86seg *target_seg = NULL; int count = 1; diff --git a/src/codegen/codegen_ops_stack.h b/src/codegen/codegen_ops_stack.h index 342ddedd4..b7e3d66fe 100644 --- a/src/codegen/codegen_ops_stack.h +++ b/src/codegen/codegen_ops_stack.h @@ -1,5 +1,5 @@ static uint32_t -ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPUSH_16(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -12,7 +12,7 @@ ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co return op_pc; } static uint32_t -ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPUSH_32(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -26,7 +26,7 @@ ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, co } static uint32_t -ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPUSH_imm_16(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint16_t imm = fetchdat & 0xffff; int host_reg; @@ -40,7 +40,7 @@ ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc return op_pc + 2; } static uint32_t -ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPUSH_imm_32(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t imm = fastreadl(cs + op_pc); int host_reg; @@ -55,7 +55,7 @@ ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc } static uint32_t -ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPUSH_imm_b16(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint16_t imm = fetchdat & 0xff; int host_reg; @@ -72,7 +72,7 @@ ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_p return op_pc + 1; } static uint32_t -ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPUSH_imm_b32(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t imm = fetchdat & 0xff; int host_reg; @@ -90,7 +90,7 @@ ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_p } static uint32_t -ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPOP_16(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); LOAD_STACK_TO_EA(0); @@ -101,7 +101,7 @@ ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc; } static uint32_t -ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropPOP_32(uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); LOAD_STACK_TO_EA(0); @@ -113,7 +113,7 @@ ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropRET_16(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc), UNUSED(codeblock_t *block)) { STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); LOAD_STACK_TO_EA(0); @@ -124,7 +124,7 @@ ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return -1; } static uint32_t -ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropRET_32(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc), UNUSED(codeblock_t *block)) { STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); LOAD_STACK_TO_EA(0); @@ -136,7 +136,7 @@ ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod } static uint32_t -ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropRET_imm_16(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc), UNUSED(codeblock_t *block)) { uint16_t offset = fetchdat & 0xffff; @@ -149,7 +149,7 @@ ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, return -1; } static uint32_t -ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropRET_imm_32(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc), UNUSED(codeblock_t *block)) { uint16_t offset = fetchdat & 0xffff; @@ -163,7 +163,7 @@ ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, } static uint32_t -ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCALL_r16(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint16_t offset = fetchdat & 0xffff; int host_reg; @@ -178,7 +178,7 @@ ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return -1; } static uint32_t -ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropCALL_r32(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { uint32_t offset = fastreadl(cs + op_pc); int host_reg; @@ -194,7 +194,7 @@ ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c } static uint32_t -ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropLEAVE_16(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -209,7 +209,7 @@ ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc; } static uint32_t -ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropLEAVE_32(UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int host_reg; @@ -224,32 +224,40 @@ ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, c return op_pc; } -#define ROP_PUSH_SEG(seg) \ - static uint32_t \ - ropPUSH_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-2); \ - host_reg = LOAD_VAR_W((uintptr_t) &seg); \ - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \ - SP_MODIFY(-2); \ - \ - return op_pc; \ - } \ - static uint32_t \ - ropPUSH_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-4); \ - host_reg = LOAD_VAR_W((uintptr_t) &seg); \ - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \ - SP_MODIFY(-4); \ - \ - return op_pc; \ +#define ROP_PUSH_SEG(seg) \ + static uint32_t \ + ropPUSH_##seg##_16(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-2); \ + host_reg = LOAD_VAR_W((uintptr_t) &seg); \ + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \ + SP_MODIFY(-2); \ + \ + return op_pc; \ + } \ + static uint32_t \ + ropPUSH_##seg##_32(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-4); \ + host_reg = LOAD_VAR_W((uintptr_t) &seg); \ + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \ + SP_MODIFY(-4); \ + \ + return op_pc; \ } ROP_PUSH_SEG(CS) @@ -259,28 +267,36 @@ ROP_PUSH_SEG(FS) ROP_PUSH_SEG(GS) ROP_PUSH_SEG(SS) -#define ROP_POP_SEG(seg, rseg) \ - static uint32_t \ - ropPOP_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(2); \ - \ - return op_pc; \ - } \ - static uint32_t \ - ropPOP_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(4); \ - \ - return op_pc; \ +#define ROP_POP_SEG(seg, rseg) \ + static uint32_t \ + ropPOP_##seg##_16(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(2); \ + \ + return op_pc; \ + } \ + static uint32_t \ + ropPOP_##seg##_32(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(4); \ + \ + return op_pc; \ } ROP_POP_SEG(DS, cpu_state.seg_ds) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 08b9ee5f2..e46f55a05 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -55,7 +55,7 @@ call_long(uintptr_t func) } static __inline void -load_param_1_32(codeblock_t *block, uint32_t param) +load_param_1_32(UNUSED(codeblock_t *block), uint32_t param) { #if _WIN64 addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ @@ -93,7 +93,7 @@ static __inline void load_param_1_64(codeblock_t *block, uint64_t param) #endif static __inline void -load_param_2_32(codeblock_t *block, uint32_t param) +load_param_2_32(UNUSED(codeblock_t *block), uint32_t param) { #if _WIN64 addbyte(0xba); /*MOVL $fetchdat,%edx*/ @@ -118,7 +118,7 @@ load_param_2_reg_32(int reg) #endif } static __inline void -load_param_2_64(codeblock_t *block, uint64_t param) +load_param_2_64(UNUSED(codeblock_t *block), uint64_t param) { addbyte(0x48); #if _WIN64 @@ -1492,7 +1492,7 @@ MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) /*done:*/ } static __inline void -MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, UNUSED(int host_reg2)) { if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { addbyte(0x31); /*XOR ECX, ECX*/ @@ -3926,7 +3926,7 @@ FP_LOAD_REG(int reg) return REG_EBX; } static __inline void -FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +FP_LOAD_REG_D(int reg, int *host_reg1, UNUSED(int *host_reg2)) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4086,7 +4086,7 @@ FP_LOAD_REG_INT(int reg) return REG_EBX; } static __inline void -FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) +FP_LOAD_REG_INT_Q(int reg, int *host_reg1, UNUSED(int *host_reg2)) { addbyte(0x89); /*MOV EBX, EAX*/ addbyte(0xc3); @@ -4693,7 +4693,7 @@ LOAD_MMX_D(int guest_reg) return host_reg; } static __inline void -LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +LOAD_MMX_Q(int guest_reg, int *host_reg1, UNUSED(int *host_reg2)) { int host_reg = REG_EBX; @@ -4725,7 +4725,7 @@ LOAD_MMX_Q_MMX(int guest_reg) } static __inline int -LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +LOAD_INT_TO_MMX(int src_reg1, UNUSED(int src_reg2)) { int dst_reg = find_host_xmm_reg(); host_reg_xmm_mapping[dst_reg] = 100; @@ -4758,7 +4758,7 @@ STORE_MMX_LQ(int guest_reg, int host_reg1) addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); } static __inline void -STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) +STORE_MMX_Q(int guest_reg, int host_reg1, UNUSED(int host_reg2)) { if (host_reg1 & 8) addbyte(0x4c); diff --git a/src/codegen/codegen_ops_xchg.h b/src/codegen/codegen_ops_xchg.h index 28a558078..467f711e4 100644 --- a/src/codegen/codegen_ops_xchg.h +++ b/src/codegen/codegen_ops_xchg.h @@ -1,16 +1,20 @@ -#define OP_XCHG_AX_(reg) \ - static uint32_t \ - ropXCHG_AX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int ax_reg, host_reg, temp_reg; \ - \ - ax_reg = LOAD_REG_W(REG_AX); \ - host_reg = LOAD_REG_W(REG_##reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_W_RELEASE(ax_reg, REG_##reg); \ - STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ - \ - return op_pc; \ +#define OP_XCHG_AX_(reg) \ + static uint32_t \ + ropXCHG_AX_##reg(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + int ax_reg, host_reg, temp_reg; \ + \ + ax_reg = LOAD_REG_W(REG_AX); \ + host_reg = LOAD_REG_W(REG_##reg); \ + temp_reg = COPY_REG(host_reg); \ + STORE_REG_TARGET_W_RELEASE(ax_reg, REG_##reg); \ + STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ + \ + return op_pc; \ } OP_XCHG_AX_(BX) @@ -21,19 +25,23 @@ OP_XCHG_AX_(DI) OP_XCHG_AX_(SP) OP_XCHG_AX_(BP) -#define OP_XCHG_EAX_(reg) \ - static uint32_t \ - ropXCHG_EAX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int eax_reg, host_reg, temp_reg; \ - \ - eax_reg = LOAD_REG_L(REG_EAX); \ - host_reg = LOAD_REG_L(REG_##reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_L_RELEASE(eax_reg, REG_##reg); \ - STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ - \ - return op_pc; \ +#define OP_XCHG_EAX_(reg) \ + static uint32_t \ + ropXCHG_EAX_##reg(UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc, \ + UNUSED(codeblock_t *block)) \ + { \ + int eax_reg, host_reg, temp_reg; \ + \ + eax_reg = LOAD_REG_L(REG_EAX); \ + host_reg = LOAD_REG_L(REG_##reg); \ + temp_reg = COPY_REG(host_reg); \ + STORE_REG_TARGET_L_RELEASE(eax_reg, REG_##reg); \ + STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ + \ + return op_pc; \ } OP_XCHG_EAX_(EBX) @@ -45,7 +53,7 @@ OP_XCHG_EAX_(ESP) OP_XCHG_EAX_(EBP) static uint32_t -ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropXCHG_b(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -63,7 +71,7 @@ ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc + 1; } static uint32_t -ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropXCHG_w(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; @@ -81,7 +89,7 @@ ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, cod return op_pc + 1; } static uint32_t -ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +ropXCHG_l(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { int src_reg; int dst_reg; diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index 59f411612..04c2136ff 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -125,7 +125,7 @@ add_to_block_list(codeblock_t *block) } static void -remove_from_block_list(codeblock_t *block, uint32_t pc) +remove_from_block_list(codeblock_t *block, UNUSED(uint32_t pc)) { if (!block->page_mask) return; diff --git a/src/codegen_new/codegen_ir.c b/src/codegen_new/codegen_ir.c index 6345bbe86..ed8ae051f 100644 --- a/src/codegen_new/codegen_ir.c +++ b/src/codegen_new/codegen_ir.c @@ -2,6 +2,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index 26a1c3cb4..9bd2f9afe 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -410,7 +410,7 @@ uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) } static inline void -uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) +uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, UNUSED(int arg), int src_reg_a) { uop_t *uop = uop_alloc(ir, uop_type); diff --git a/src/codegen_new/codegen_ops.c b/src/codegen_new/codegen_ops.c index 59e148659..bb7d1f3ee 100644 --- a/src/codegen_new/codegen_ops.c +++ b/src/codegen_new/codegen_ops.c @@ -2,6 +2,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "codegen.h" #include "codegen_ir.h" diff --git a/src/codegen_new/codegen_ops_3dnow.c b/src/codegen_new/codegen_ops_3dnow.c index 8b4d471ba..03af718d1 100644 --- a/src/codegen_new/codegen_ops_3dnow.c +++ b/src/codegen_new/codegen_ops_3dnow.c @@ -17,7 +17,7 @@ #include "codegen_ops_helpers.h" #define ropParith(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ int dest_reg = (fetchdat >> 3) & 7; \ \ @@ -192,7 +192,7 @@ ropPFRSQRT(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f } uint32_t -ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MMX_ENTER(ir); diff --git a/src/codegen_new/codegen_ops_arith.c b/src/codegen_new/codegen_ops_arith.c index 9e136ace5..c899c13d8 100644 --- a/src/codegen_new/codegen_ops_arith.c +++ b/src/codegen_new/codegen_ops_arith.c @@ -22,7 +22,7 @@ get_cf(ir_data_t *ir, int dest_reg) } uint32_t -ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -39,7 +39,7 @@ ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -274,7 +274,7 @@ ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -289,7 +289,7 @@ ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -511,7 +511,7 @@ ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -526,7 +526,7 @@ ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -734,7 +734,7 @@ ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -751,7 +751,7 @@ ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -988,7 +988,7 @@ ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -1003,7 +1003,7 @@ ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -2293,7 +2293,7 @@ rebuild_c(ir_data_t *ir) } uint32_t -ropINC_r16(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropINC_r16(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { rebuild_c(ir); @@ -2307,7 +2307,7 @@ ropINC_r16(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opc return op_pc; } uint32_t -ropINC_r32(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropINC_r32(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { rebuild_c(ir); @@ -2322,7 +2322,7 @@ ropINC_r32(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opc } uint32_t -ropDEC_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropDEC_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { rebuild_c(ir); @@ -2336,7 +2336,7 @@ ropDEC_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } uint32_t -ropDEC_r32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropDEC_r32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { rebuild_c(ir); diff --git a/src/codegen_new/codegen_ops_branch.c b/src/codegen_new/codegen_ops_branch.c index cedb54177..1e2589f8b 100644 --- a/src/codegen_new/codegen_ops_branch.c +++ b/src/codegen_new/codegen_ops_branch.c @@ -816,7 +816,7 @@ ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t n } #define ropJ(cond) \ - uint32_t ropJ##cond##_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropJ##cond##_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) \ { \ uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); \ uint32_t dest_addr = op_pc + 1 + offset; \ @@ -829,7 +829,7 @@ ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t n codegen_mark_code_present(block, cs + op_pc, 1); \ return ret ? dest_addr : (op_pc + 1); \ } \ - uint32_t ropJ##cond##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropJ##cond##_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ { \ uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); \ uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ @@ -840,7 +840,7 @@ ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t n codegen_mark_code_present(block, cs + op_pc, 2); \ return ret ? dest_addr : (op_pc + 2); \ } \ - uint32_t ropJ##cond##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropJ##cond##_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ { \ uint32_t offset = fastreadl(cs + op_pc); \ uint32_t dest_addr = op_pc + 4 + offset; \ @@ -852,6 +852,7 @@ ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t n return ret ? dest_addr : (op_pc + 4); \ } +// clang-format off ropJ(O) ropJ(NO) ropJ(B) @@ -868,9 +869,10 @@ ropJ(L) ropJ(NL) ropJ(LE) ropJ(NLE) +// clang-format on uint32_t -ropJCXZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropJCXZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); uint32_t dest_addr = op_pc + 1 + offset; @@ -892,7 +894,7 @@ ropJCXZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc } uint32_t -ropLOOP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropLOOP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); uint32_t dest_addr = op_pc + 1 + offset; @@ -932,7 +934,7 @@ ropLOOP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc } uint32_t -ropLOOPE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropLOOPE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); uint32_t dest_addr = op_pc + 1 + offset; @@ -965,7 +967,7 @@ ropLOOPE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet return op_pc + 1; } uint32_t -ropLOOPNE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropLOOPNE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); uint32_t dest_addr = op_pc + 1 + offset; diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c index a7b5290f4..43d243c0f 100644 --- a/src/codegen_new/codegen_ops_fpu_arith.c +++ b/src/codegen_new/codegen_ops_fpu_arith.c @@ -79,7 +79,7 @@ ropFCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet return op_pc; } uint32_t -ropFCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); @@ -289,7 +289,7 @@ ropFUCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe return op_pc; } uint32_t -ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); @@ -301,7 +301,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f } #define ropF_arith_mem(name, load_uop) \ - uint32_t ropFADD##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFADD##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -318,7 +318,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f \ return op_pc + 1; \ } \ - uint32_t ropFCOM##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFCOM##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -329,12 +329,12 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f codegen_check_seg_read(block, ir, target_seg); \ load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ \ return op_pc + 1; \ } \ - uint32_t ropFCOMP##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFCOMP##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -351,7 +351,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f \ return op_pc + 1; \ } \ - uint32_t ropFDIV##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFDIV##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -366,7 +366,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f \ return op_pc + 1; \ } \ - uint32_t ropFDIVR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFDIVR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -381,7 +381,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f \ return op_pc + 1; \ } \ - uint32_t ropFMUL##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFMUL##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -396,7 +396,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f \ return op_pc + 1; \ } \ - uint32_t ropFSUB##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFSUB##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -411,7 +411,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f \ return op_pc + 1; \ } \ - uint32_t ropFSUBR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFSUBR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -433,7 +433,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) // clang-format on #define ropFI_arith_mem(name, temp_reg) \ - uint32_t ropFIADD##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFIADD##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -449,7 +449,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) \ return op_pc + 1; \ } \ - uint32_t ropFICOM##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFICOM##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -461,12 +461,12 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ \ return op_pc + 1; \ } \ - uint32_t ropFICOMP##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFICOMP##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -478,13 +478,13 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ fpu_POP(block, ir); \ \ return op_pc + 1; \ } \ - uint32_t ropFIDIV##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFIDIV##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -500,7 +500,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) \ return op_pc + 1; \ } \ - uint32_t ropFIDIVR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFIDIVR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -516,7 +516,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) \ return op_pc + 1; \ } \ - uint32_t ropFIMUL##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFIMUL##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -532,7 +532,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) \ return op_pc + 1; \ } \ - uint32_t ropFISUB##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFISUB##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -548,7 +548,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) \ return op_pc + 1; \ } \ - uint32_t ropFISUBR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropFISUBR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ \ @@ -565,11 +565,13 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) return op_pc + 1; \ } +// clang-format off ropFI_arith_mem(l, IREG_temp0) ropFI_arith_mem(w, IREG_temp0_W) +// clang-format on uint32_t -ropFABS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFABS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_FABS(ir, IREG_ST(0), IREG_ST(0)); @@ -579,7 +581,7 @@ ropFABS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 } uint32_t -ropFCHS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFCHS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_FCHS(ir, IREG_ST(0), IREG_ST(0)); @@ -588,7 +590,7 @@ ropFCHS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 return op_pc; } uint32_t -ropFSQRT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFSQRT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_FSQRT(ir, IREG_ST(0), IREG_ST(0)); @@ -597,7 +599,7 @@ ropFSQRT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint return op_pc; } uint32_t -ropFTST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFTST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); diff --git a/src/codegen_new/codegen_ops_fpu_constant.c b/src/codegen_new/codegen_ops_fpu_constant.c index a91d675c5..6ec2f6888 100644 --- a/src/codegen_new/codegen_ops_fpu_constant.c +++ b/src/codegen_new/codegen_ops_fpu_constant.c @@ -19,7 +19,7 @@ #include "codegen_ops_helpers.h" uint32_t -ropFLD1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFLD1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_MOV_IMM(ir, IREG_temp0, 1); @@ -30,7 +30,7 @@ ropFLD1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc return op_pc; } uint32_t -ropFLDZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFLDZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_MOV_IMM(ir, IREG_temp0, 0); diff --git a/src/codegen_new/codegen_ops_fpu_misc.c b/src/codegen_new/codegen_ops_fpu_misc.c index 31b668488..938204a70 100644 --- a/src/codegen_new/codegen_ops_fpu_misc.c +++ b/src/codegen_new/codegen_ops_fpu_misc.c @@ -98,7 +98,7 @@ ropFSTSW(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet return op_pc + 1; } uint32_t -ropFSTSW_AX(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropFSTSW_AX(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_FP_ENTER(ir); uop_MOV(ir, IREG_AX, IREG_NPXS); diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 5a8f1e1c7..92b721099 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -71,7 +71,7 @@ fpu_PUSH(codeblock_t *block, ir_data_t *ir) } static inline void -CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset) +CHECK_SEG_LIMITS(UNUSED(codeblock_t *block), ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset) { if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) return; @@ -85,7 +85,7 @@ CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, i } static inline void -LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +LOAD_IMMEDIATE_FROM_RAM_8(UNUSED(codeblock_t *block), ir_data_t *ir, int dest_reg, uint32_t addr) { uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); } diff --git a/src/codegen_new/codegen_ops_jump.c b/src/codegen_new/codegen_ops_jump.c index fb2f1e5ba..430b16b2b 100644 --- a/src/codegen_new/codegen_ops_jump.c +++ b/src/codegen_new/codegen_ops_jump.c @@ -15,7 +15,7 @@ #include "codegen_ops_mov.h" uint32_t -ropJMP_r8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropJMP_r8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); uint32_t dest_addr = op_pc + 1 + offset; @@ -29,7 +29,7 @@ ropJMP_r8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe return dest_addr; } uint32_t -ropJMP_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropJMP_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); uint32_t dest_addr = op_pc + 2 + offset; @@ -42,7 +42,7 @@ ropJMP_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f return dest_addr; } uint32_t -ropJMP_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropJMP_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t offset = fastreadl(cs + op_pc); uint32_t dest_addr = op_pc + 4 + offset; @@ -54,7 +54,7 @@ ropJMP_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f } uint32_t -ropJMP_far_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropJMP_far_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t new_pc = fastreadw(cs + op_pc); uint16_t new_cs = fastreadw(cs + op_pc + 2); @@ -69,7 +69,7 @@ ropJMP_far_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return -1; } uint32_t -ropJMP_far_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropJMP_far_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t new_pc = fastreadl(cs + op_pc); uint16_t new_cs = fastreadw(cs + op_pc + 4); @@ -85,7 +85,7 @@ ropJMP_far_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ } uint32_t -ropCALL_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCALL_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); uint16_t ret_addr = op_pc + 2; @@ -104,7 +104,7 @@ ropCALL_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return -1; } uint32_t -ropCALL_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCALL_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t offset = fastreadl(cs + op_pc); uint32_t ret_addr = op_pc + 4; @@ -122,7 +122,7 @@ ropCALL_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropRET_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) +ropRET_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -138,7 +138,7 @@ ropRET_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uin return -1; } uint32_t -ropRET_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) +ropRET_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -154,7 +154,7 @@ ropRET_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uin } uint32_t -ropRET_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropRET_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t offset = fastreadw(cs + op_pc); @@ -173,7 +173,7 @@ ropRET_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return -1; } uint32_t -ropRET_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropRET_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t offset = fastreadw(cs + op_pc); @@ -192,7 +192,7 @@ ropRET_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ } uint32_t -ropRETF_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) +ropRETF_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) return 0; @@ -215,7 +215,7 @@ ropRETF_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), ui return -1; } uint32_t -ropRETF_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) +ropRETF_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) return 0; @@ -239,7 +239,7 @@ ropRETF_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), ui } uint32_t -ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t offset; @@ -266,7 +266,7 @@ ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32 return -1; } uint32_t -ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t offset; diff --git a/src/codegen_new/codegen_ops_logic.c b/src/codegen_new/codegen_ops_logic.c index 684052fea..f289f1cba 100644 --- a/src/codegen_new/codegen_ops_logic.c +++ b/src/codegen_new/codegen_ops_logic.c @@ -16,7 +16,7 @@ #include "codegen_ops_logic.h" uint32_t -ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -29,7 +29,7 @@ ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -226,7 +226,7 @@ ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -239,7 +239,7 @@ ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return op_pc + 1; } uint32_t -ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -437,7 +437,7 @@ ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -449,7 +449,7 @@ ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32 return op_pc + 1; } uint32_t -ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); @@ -557,7 +557,7 @@ ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uint32_t -ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -570,7 +570,7 @@ ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + 1; } uint32_t -ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm_data = fastreadw(cs + op_pc); diff --git a/src/codegen_new/codegen_ops_misc.c b/src/codegen_new/codegen_ops_misc.c index 545634672..c709dffc9 100644 --- a/src/codegen_new/codegen_ops_misc.c +++ b/src/codegen_new/codegen_ops_misc.c @@ -485,34 +485,34 @@ ropFF_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet } uint32_t -ropNOP(UNUSED(codeblock_t *block), UNUSED(ir_data_t *ir), UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropNOP(UNUSED(codeblock_t *block), UNUSED(ir_data_t *ir), UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { return op_pc; } uint32_t -ropCBW(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCBW(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MOVSX(ir, IREG_AX, IREG_AL); return op_pc; } uint32_t -ropCDQ(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCDQ(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31); return op_pc; } uint32_t -ropCWD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCWD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15); return op_pc; } uint32_t -ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MOVSX(ir, IREG_EAX, IREG_AX); @@ -520,7 +520,7 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 } #define ropLxS(name, seg) \ - uint32_t rop##name##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t rop##name##_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg = NULL; \ int dest_reg = (fetchdat >> 3) & 7; \ @@ -542,7 +542,7 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 \ return op_pc + 1; \ } \ - uint32_t rop##name##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t rop##name##_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg = NULL; \ int dest_reg = (fetchdat >> 3) & 7; \ @@ -572,21 +572,21 @@ ropLxS(LGS, &cpu_state.seg_gs) ropLxS(LSS, &cpu_state.seg_ss) uint32_t -ropCLC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCLC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_CALL_FUNC(ir, flags_rebuild); uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG); return op_pc; } uint32_t -ropCMC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCMC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_CALL_FUNC(ir, flags_rebuild); uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); return op_pc; } uint32_t -ropSTC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSTC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_CALL_FUNC(ir, flags_rebuild); uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); @@ -594,20 +594,20 @@ ropSTC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32 } uint32_t -ropCLD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCLD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG); return op_pc; } uint32_t -ropSTD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSTD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG); return op_pc; } uint32_t -ropCLI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropCLI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) return 0; @@ -616,7 +616,7 @@ ropCLI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32 return op_pc; } uint32_t -ropSTI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropSTI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) return 0; diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index e99b4c56d..8fd1d1651 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -2,6 +2,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" @@ -16,7 +17,7 @@ #include "codegen_ops_helpers.h" #define ropParith(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ int dest_reg = (fetchdat >> 3) & 7; \ \ @@ -58,4 +59,4 @@ ropParith(PSUBUSW) ropParith(PMADDWD) ropParith(PMULHW) ropParith(PMULLW) - // clang-format on +// clang-format on diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index 6f38cba67..e00e56472 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -2,6 +2,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" @@ -16,7 +17,7 @@ #include "codegen_ops_helpers.h" #define ropPcmp(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ int dest_reg = (fetchdat >> 3) & 7; \ \ @@ -45,4 +46,4 @@ ropPcmp(PCMPEQD) ropPcmp(PCMPGTB) ropPcmp(PCMPGTW) ropPcmp(PCMPGTD) - // clang-format on +// clang-format on diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index d25edd52e..18377e142 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -2,6 +2,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" @@ -16,7 +17,7 @@ #include "codegen_ops_helpers.h" #define ropPpack(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ int dest_reg = (fetchdat >> 3) & 7; \ \ @@ -48,4 +49,4 @@ ropPpack(PUNPCKLDQ) ropPpack(PUNPCKHBW) ropPpack(PUNPCKHWD) ropPpack(PUNPCKHDQ) - // clang-format on +// clang-format on diff --git a/src/codegen_new/codegen_ops_mov.c b/src/codegen_new/codegen_ops_mov.c index eae7045a8..031d2ea05 100644 --- a/src/codegen_new/codegen_ops_mov.c +++ b/src/codegen_new/codegen_ops_mov.c @@ -15,7 +15,7 @@ #include "codegen_ops_mov.h" uint32_t -ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint8_t imm = fastreadb(cs + op_pc); @@ -25,7 +25,7 @@ ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchd return op_pc + 1; } uint32_t -ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm = fastreadw(cs + op_pc); @@ -172,7 +172,7 @@ ropMOV_r_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f } uint32_t -ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t addr; @@ -189,7 +189,7 @@ ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t -ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t addr; @@ -206,7 +206,7 @@ ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t -ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t addr = 0; @@ -233,7 +233,7 @@ ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32 } uint32_t -ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t addr; @@ -250,7 +250,7 @@ ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t -ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t addr; @@ -267,7 +267,7 @@ ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_ return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t -ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uint32_t addr; @@ -614,7 +614,7 @@ ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32 } uint32_t -ropXCHG_AX(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropXCHG_AX(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int reg2 = IREG_16(opcode & 7); @@ -625,7 +625,7 @@ ropXCHG_AX(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } uint32_t -ropXCHG_EAX(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropXCHG_EAX(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int reg2 = IREG_32(opcode & 7); @@ -716,7 +716,7 @@ ropXCHG_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f } uint32_t -ropXLAT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +ropXLAT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index 92ad9509d..057cccb0f 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -16,7 +16,7 @@ #include "codegen_ops_misc.h" uint32_t -ropPUSH_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSH_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -28,7 +28,7 @@ ropPUSH_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t return op_pc; } uint32_t -ropPUSH_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSH_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -41,7 +41,7 @@ ropPUSH_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t -ropPOP_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPOP_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -57,7 +57,7 @@ ropPOP_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } uint32_t -ropPOP_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPOP_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -74,7 +74,7 @@ ropPOP_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t f } uint32_t -ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm = fastreadw(cs + op_pc); int sp_reg; @@ -88,7 +88,7 @@ ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32 return op_pc + 2; } uint32_t -ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t imm = fastreadl(cs + op_pc); int sp_reg; @@ -103,7 +103,7 @@ ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32 } uint32_t -ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint16_t imm = (int16_t) (int8_t) fastreadb(cs + op_pc); int sp_reg; @@ -117,7 +117,7 @@ ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint return op_pc + 1; } uint32_t -ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uint32_t imm = (int32_t) (int8_t) fastreadb(cs + op_pc); int sp_reg; @@ -197,7 +197,7 @@ ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet } #define ROP_PUSH_SEG(seg) \ - uint32_t ropPUSH_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropPUSH_##seg##_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ { \ int sp_reg; \ \ @@ -208,7 +208,7 @@ ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet \ return op_pc; \ } \ - uint32_t ropPUSH_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropPUSH_##seg##_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ { \ int sp_reg; \ \ @@ -222,7 +222,7 @@ ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet } #define ROP_POP_SEG(seg, rseg) \ - uint32_t ropPOP_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropPOP_##seg##_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ { \ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ \ @@ -237,7 +237,7 @@ ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet \ return op_pc; \ } \ - uint32_t ropPOP_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + uint32_t ropPOP_##seg##_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ { \ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ \ @@ -253,6 +253,7 @@ ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet return op_pc; \ } +// clang-format off ROP_PUSH_SEG(CS) ROP_PUSH_SEG(DS) ROP_PUSH_SEG(ES) @@ -263,9 +264,10 @@ ROP_POP_SEG(DS, cpu_state.seg_ds) ROP_POP_SEG(ES, cpu_state.seg_es) ROP_POP_SEG(FS, cpu_state.seg_fs) ROP_POP_SEG(GS, cpu_state.seg_gs) +// clang-format on uint32_t -ropLEAVE_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropLEAVE_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -281,7 +283,7 @@ ropLEAVE_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), u return op_pc; } uint32_t -ropLEAVE_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropLEAVE_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -298,7 +300,7 @@ ropLEAVE_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), u } uint32_t -ropPUSHA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSHA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -317,7 +319,7 @@ ropPUSHA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), u return op_pc; } uint32_t -ropPUSHA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSHA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -337,7 +339,7 @@ ropPUSHA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), u } uint32_t -ropPOPA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPOPA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -355,7 +357,7 @@ ropPOPA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), ui return op_pc; } uint32_t -ropPOPA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPOPA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -374,7 +376,7 @@ ropPOPA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), ui } uint32_t -ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; @@ -390,7 +392,7 @@ ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint return op_pc; } uint32_t -ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) { int sp_reg; diff --git a/src/cpu/386.c b/src/cpu/386.c index 21db155e9..caa5f84a2 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -27,6 +27,7 @@ #include <86box/fdc.h> #include <86box/machine.h> #include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include <86box/gdbstub.h> #ifndef OPS_286_386 # define OPS_286_386 diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index a68d866bf..8a2bb4ab8 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1825,7 +1825,7 @@ cpu_386_check_instruction_fault(void) } int -sysenter(uint32_t fetchdat) +sysenter(UNUSED(uint32_t fetchdat)) { #ifdef ENABLE_386_COMMON_LOG x386_common_log("SYSENTER called\n"); @@ -1907,7 +1907,7 @@ sysenter(uint32_t fetchdat) } int -sysexit(uint32_t fetchdat) +sysexit(UNUSED(uint32_t fetchdat)) { #ifdef ENABLE_386_COMMON_LOG x386_common_log("SYSEXIT called\n"); @@ -1994,7 +1994,7 @@ sysexit(uint32_t fetchdat) } int -syscall_op(uint32_t fetchdat) +syscall_op(UNUSED(uint32_t fetchdat)) { #ifdef ENABLE_386_COMMON_LOG x386_common_log("SYSCALL called\n"); @@ -2046,7 +2046,7 @@ syscall_op(uint32_t fetchdat) } int -sysret(uint32_t fetchdat) +sysret(UNUSED(uint32_t fetchdat)) { #ifdef ENABLE_386_COMMON_LOG x386_common_log("SYSRET called\n"); diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index c4c095735..5f41c416a 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -30,6 +30,7 @@ #include <86box/fdc.h> #include <86box/machine.h> #include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include <86box/gdbstub.h> #ifdef USE_DYNAREC # include "codegen.h" diff --git a/src/cpu/808x.c b/src/cpu/808x.c index f37672a5c..a74cf84ab 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -35,6 +35,7 @@ #include <86box/ppi.h> #include <86box/timer.h> #include <86box/gdbstub.h> +#include <86box/plat_unused.h> /* Is the CPU 8088 or 8086. */ int is8086 = 0; @@ -815,7 +816,7 @@ pop(void) } static void -access(int num, int bits) +access(int num, UNUSED(int bits)) { switch (num) { case 0: @@ -1419,7 +1420,7 @@ set_pzs(int bits) } static void -set_co_mul(int bits, int carry) +set_co_mul(UNUSED(int bits), int carry) { set_cf(carry); set_of(carry); diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c index 90d682211..d8f05cfd3 100644 --- a/src/cpu/codegen_timing_486.c +++ b/src/cpu/codegen_timing_486.c @@ -328,7 +328,7 @@ codegen_timing_486_start(void) } void -codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat) +codegen_timing_486_prefix(uint8_t prefix, UNUSED(uint32_t fetchdat)) { timing_count += COUNT(opcode_timings_486[prefix], 0); last_prefix = prefix; diff --git a/src/cpu/codegen_timing_k5.c b/src/cpu/codegen_timing_k5.c index 42b1129fe..8ce2f4cea 100644 --- a/src/cpu/codegen_timing_k5.c +++ b/src/cpu/codegen_timing_k5.c @@ -8,6 +8,7 @@ #include <86box/mem.h> #include "cpu.h" #include <86box/machine.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_ops.h" @@ -2037,7 +2038,7 @@ codegen_timing_k5_start(void) } void -codegen_timing_k5_prefix(uint8_t prefix, uint32_t fetchdat) +codegen_timing_k5_prefix(uint8_t prefix, UNUSED(uint32_t fetchdat)) { if (prefix != 0x0f) decode_timestamp++; @@ -2047,7 +2048,7 @@ codegen_timing_k5_prefix(uint8_t prefix, uint32_t fetchdat) } void -codegen_timing_k5_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +codegen_timing_k5_opcode(uint8_t opcode, UNUSED(uint32_t fetchdat), int op_32, uint32_t op_pc) { const risc86_instruction_t **ins_table; const uint64_t *deps; diff --git a/src/cpu/codegen_timing_k6.c b/src/cpu/codegen_timing_k6.c index 5566fbbcd..34297211b 100644 --- a/src/cpu/codegen_timing_k6.c +++ b/src/cpu/codegen_timing_k6.c @@ -8,6 +8,7 @@ #include <86box/mem.h> #include "cpu.h" #include <86box/machine.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_ops.h" @@ -2037,7 +2038,7 @@ codegen_timing_k6_start(void) } void -codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) +codegen_timing_k6_prefix(uint8_t prefix, UNUSED(uint32_t fetchdat)) { if (prefix != 0x0f) decode_timestamp++; @@ -2047,7 +2048,7 @@ codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) } void -codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +codegen_timing_k6_opcode(uint8_t opcode, UNUSED(uint32_t fetchdat), int op_32, uint32_t op_pc) { const risc86_instruction_t **ins_table; const uint64_t *deps; diff --git a/src/cpu/codegen_timing_p6.c b/src/cpu/codegen_timing_p6.c index a22813068..42db319c3 100644 --- a/src/cpu/codegen_timing_p6.c +++ b/src/cpu/codegen_timing_p6.c @@ -1845,7 +1845,7 @@ codegen_timing_p6_start(void) } void -codegen_timing_p6_prefix(uint8_t prefix, uint32_t fetchdat) +codegen_timing_p6_prefix(uint8_t prefix, UNUSED(uint32_t fetchdat)) { if (prefix != 0x0f) decode_timestamp++; @@ -1855,7 +1855,7 @@ codegen_timing_p6_prefix(uint8_t prefix, uint32_t fetchdat) } void -codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) +codegen_timing_p6_opcode(uint8_t opcode, UNUSED(uint32_t fetchdat), int op_32, UNUSED(uint32_t op_pc)) { const macro_op_t **ins_table; const uint64_t *deps; diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c index 3597517ce..0d39f4151 100644 --- a/src/cpu/codegen_timing_winchip.c +++ b/src/cpu/codegen_timing_winchip.c @@ -328,7 +328,7 @@ codegen_timing_winchip_start(void) } void -codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat) +codegen_timing_winchip_prefix(uint8_t prefix, UNUSED(uint32_t fetchdat)) { timing_count += COUNT(opcode_timings_winchip[prefix], 0); last_prefix = prefix; diff --git a/src/cpu/codegen_timing_winchip2.c b/src/cpu/codegen_timing_winchip2.c index f37fe3366..696a059cf 100644 --- a/src/cpu/codegen_timing_winchip2.c +++ b/src/cpu/codegen_timing_winchip2.c @@ -589,7 +589,7 @@ codegen_timing_winchip2_start(void) } static void -codegen_timing_winchip2_prefix(uint8_t prefix, uint32_t fetchdat) +codegen_timing_winchip2_prefix(uint8_t prefix, UNUSED(uint32_t fetchdat)) { if (prefix == 0x0f) { /*0fh prefix is 'free'*/ diff --git a/src/cpu/x86_ops_3dnow.h b/src/cpu/x86_ops_3dnow.h index b72cbc06c..2b4ed1a6d 100644 --- a/src/cpu/x86_ops_3dnow.h +++ b/src/cpu/x86_ops_3dnow.h @@ -20,7 +20,7 @@ opPREFETCH_a32(uint32_t fetchdat) } static int -opFEMMS(uint32_t fetchdat) +opFEMMS(UNUSED(uint32_t fetchdat)) { ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX)); if (cr0 & 0xc) { @@ -33,7 +33,7 @@ opFEMMS(uint32_t fetchdat) } static int -opPAVGUSB(uint32_t fetchdat) +opPAVGUSB(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -54,7 +54,7 @@ opPAVGUSB(uint32_t fetchdat) return 0; } static int -opPF2ID(uint32_t fetchdat) +opPF2ID(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -69,7 +69,7 @@ opPF2ID(uint32_t fetchdat) return 0; } static int -opPF2IW(uint32_t fetchdat) +opPF2IW(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -84,7 +84,7 @@ opPF2IW(uint32_t fetchdat) return 0; } static int -opPFACC(uint32_t fetchdat) +opPFACC(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -101,7 +101,7 @@ opPFACC(uint32_t fetchdat) return 0; } static int -opPFNACC(uint32_t fetchdat) +opPFNACC(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -118,7 +118,7 @@ opPFNACC(uint32_t fetchdat) return 0; } static int -opPFPNACC(uint32_t fetchdat) +opPFPNACC(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -135,7 +135,7 @@ opPFPNACC(uint32_t fetchdat) return 0; } static int -opPSWAPD(uint32_t fetchdat) +opPSWAPD(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -155,7 +155,7 @@ opPSWAPD(uint32_t fetchdat) return 0; } static int -opPFADD(uint32_t fetchdat) +opPFADD(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -170,7 +170,7 @@ opPFADD(uint32_t fetchdat) return 0; } static int -opPFCMPEQ(uint32_t fetchdat) +opPFCMPEQ(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -185,7 +185,7 @@ opPFCMPEQ(uint32_t fetchdat) return 0; } static int -opPFCMPGE(uint32_t fetchdat) +opPFCMPGE(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -200,7 +200,7 @@ opPFCMPGE(uint32_t fetchdat) return 0; } static int -opPFCMPGT(uint32_t fetchdat) +opPFCMPGT(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -215,7 +215,7 @@ opPFCMPGT(uint32_t fetchdat) return 0; } static int -opPFMAX(uint32_t fetchdat) +opPFMAX(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -232,7 +232,7 @@ opPFMAX(uint32_t fetchdat) return 0; } static int -opPFMIN(uint32_t fetchdat) +opPFMIN(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -249,7 +249,7 @@ opPFMIN(uint32_t fetchdat) return 0; } static int -opPFMUL(uint32_t fetchdat) +opPFMUL(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -264,7 +264,7 @@ opPFMUL(uint32_t fetchdat) return 0; } static int -opPFRCP(uint32_t fetchdat) +opPFRCP(UNUSED(uint32_t fetchdat)) { MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -293,7 +293,7 @@ opPFRCP(uint32_t fetchdat) } /*Since opPFRCP() calculates a full precision reciprocal, treat the followup iterations as MOVs*/ static int -opPFRCPIT1(uint32_t fetchdat) +opPFRCPIT1(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -308,7 +308,7 @@ opPFRCPIT1(uint32_t fetchdat) return 0; } static int -opPFRCPIT2(uint32_t fetchdat) +opPFRCPIT2(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -323,7 +323,7 @@ opPFRCPIT2(uint32_t fetchdat) return 0; } static int -opPFRSQRT(uint32_t fetchdat) +opPFRSQRT(UNUSED(uint32_t fetchdat)) { MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -352,7 +352,7 @@ opPFRSQRT(uint32_t fetchdat) } /*Since opPFRSQRT() calculates a full precision inverse square root, treat the followup iteration as a NOP*/ static int -opPFRSQIT1(uint32_t fetchdat) +opPFRSQIT1(UNUSED(uint32_t fetchdat)) { MMX_REG src; @@ -362,7 +362,7 @@ opPFRSQIT1(uint32_t fetchdat) return 0; } static int -opPFSUB(uint32_t fetchdat) +opPFSUB(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -377,7 +377,7 @@ opPFSUB(uint32_t fetchdat) return 0; } static int -opPFSUBR(uint32_t fetchdat) +opPFSUBR(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -392,7 +392,7 @@ opPFSUBR(uint32_t fetchdat) return 0; } static int -opPI2FD(uint32_t fetchdat) +opPI2FD(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -407,7 +407,7 @@ opPI2FD(uint32_t fetchdat) return 0; } static int -opPI2FW(uint32_t fetchdat) +opPI2FW(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); @@ -422,7 +422,7 @@ opPI2FW(uint32_t fetchdat) return 0; } static int -opPMULHRW(uint32_t fetchdat) +opPMULHRW(UNUSED(uint32_t fetchdat)) { MMX_REG src; MMX_REG *dst = MMX_GETREGP(cpu_reg); diff --git a/src/cpu/x86_ops_arith.h b/src/cpu/x86_ops_arith.h index 4e3f74e36..0764877a4 100644 --- a/src/cpu/x86_ops_arith.h +++ b/src/cpu/x86_ops_arith.h @@ -313,7 +313,7 @@ return 0; \ } \ \ - static int op##name##_EAX_imm(uint32_t fetchdat) \ + static int op##name##_EAX_imm(UNUSED(uint32_t fetchdat)) \ { \ uint32_t dst = EAX; \ uint32_t src = getlong(); \ @@ -581,7 +581,7 @@ opCMP_AX_imm(uint32_t fetchdat) } static int -opCMP_EAX_imm(uint32_t fetchdat) +opCMP_EAX_imm(UNUSED(uint32_t fetchdat)) { uint32_t src = getlong(); @@ -747,7 +747,7 @@ opTEST_AX(uint32_t fetchdat) return 0; } static int -opTEST_EAX(uint32_t fetchdat) +opTEST_EAX(UNUSED(uint32_t fetchdat)) { uint32_t temp = getlong(); if (cpu_state.abrt) diff --git a/src/cpu/x86_ops_bcd.h b/src/cpu/x86_ops_bcd.h index a04dea65a..a0d18875d 100644 --- a/src/cpu/x86_ops_bcd.h +++ b/src/cpu/x86_ops_bcd.h @@ -1,5 +1,5 @@ static int -opAAA(uint32_t fetchdat) +opAAA(UNUSED(uint32_t fetchdat)) { flags_rebuild(); if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { @@ -46,7 +46,7 @@ opAAM(uint32_t fetchdat) } static int -opAAS(uint32_t fetchdat) +opAAS(UNUSED(uint32_t fetchdat)) { flags_rebuild(); if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { @@ -63,7 +63,7 @@ opAAS(uint32_t fetchdat) } static int -opDAA(uint32_t fetchdat) +opDAA(UNUSED(uint32_t fetchdat)) { uint16_t tempw; uint16_t old_AL; @@ -100,7 +100,7 @@ opDAA(uint32_t fetchdat) } static int -opDAS(uint32_t fetchdat) +opDAS(UNUSED(uint32_t fetchdat)) { uint16_t tempw; uint16_t old_AL; diff --git a/src/cpu/x86_ops_call.h b/src/cpu/x86_ops_call.h index 9d52a2764..ee54dceff 100644 --- a/src/cpu/x86_ops_call.h +++ b/src/cpu/x86_ops_call.h @@ -209,7 +209,7 @@ opCALL_far_w(uint32_t fetchdat) return 0; } static int -opCALL_far_l(uint32_t fetchdat) +opCALL_far_l(UNUSED(uint32_t fetchdat)) { uint32_t old_cs; uint32_t old_pc; diff --git a/src/cpu/x86_ops_cyrix.h b/src/cpu/x86_ops_cyrix.h index 672ebd08e..8c3d6e155 100644 --- a/src/cpu/x86_ops_cyrix.h +++ b/src/cpu/x86_ops_cyrix.h @@ -212,7 +212,7 @@ opRSTS_a32(uint32_t fetchdat) } static int -opSMINT(uint32_t fetchdat) +opSMINT(UNUSED(uint32_t fetchdat)) { if (in_smm) fatal("opSMINT\n"); @@ -223,7 +223,7 @@ opSMINT(uint32_t fetchdat) } static int -opRDSHR_a16(uint32_t fetchdat) +opRDSHR_a16(UNUSED(uint32_t fetchdat)) { if (in_smm) fatal("opRDSHR_a16\n"); @@ -233,7 +233,7 @@ opRDSHR_a16(uint32_t fetchdat) return 1; } static int -opRDSHR_a32(uint32_t fetchdat) +opRDSHR_a32(UNUSED(uint32_t fetchdat)) { if (in_smm) fatal("opRDSHR_a32\n"); @@ -244,7 +244,7 @@ opRDSHR_a32(uint32_t fetchdat) } static int -opWRSHR_a16(uint32_t fetchdat) +opWRSHR_a16(UNUSED(uint32_t fetchdat)) { if (in_smm) fatal("opWRSHR_a16\n"); @@ -254,7 +254,7 @@ opWRSHR_a16(uint32_t fetchdat) return 1; } static int -opWRSHR_a32(uint32_t fetchdat) +opWRSHR_a32(UNUSED(uint32_t fetchdat)) { if (in_smm) fatal("opWRSHR_a32\n"); diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index 019472aa0..a0fa612a8 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -1,5 +1,5 @@ static int -opCMC(uint32_t fetchdat) +opCMC(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags ^= C_FLAG; @@ -9,7 +9,7 @@ opCMC(uint32_t fetchdat) } static int -opCLC(uint32_t fetchdat) +opCLC(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags &= ~C_FLAG; @@ -18,7 +18,7 @@ opCLC(uint32_t fetchdat) return 0; } static int -opCLD(uint32_t fetchdat) +opCLD(UNUSED(uint32_t fetchdat)) { cpu_state.flags &= ~D_FLAG; CLOCK_CYCLES(2); @@ -26,7 +26,7 @@ opCLD(uint32_t fetchdat) return 0; } static int -opCLI(uint32_t fetchdat) +opCLI(UNUSED(uint32_t fetchdat)) { if (!IOPLp) { if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { @@ -44,7 +44,7 @@ opCLI(uint32_t fetchdat) } static int -opSTC(uint32_t fetchdat) +opSTC(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags |= C_FLAG; @@ -53,7 +53,7 @@ opSTC(uint32_t fetchdat) return 0; } static int -opSTD(uint32_t fetchdat) +opSTD(UNUSED(uint32_t fetchdat)) { cpu_state.flags |= D_FLAG; CLOCK_CYCLES(2); @@ -61,7 +61,7 @@ opSTD(uint32_t fetchdat) return 0; } static int -opSTI(uint32_t fetchdat) +opSTI(UNUSED(uint32_t fetchdat)) { if (!IOPLp) { if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { @@ -87,7 +87,7 @@ opSTI(uint32_t fetchdat) } static int -opSAHF(uint32_t fetchdat) +opSAHF(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; @@ -101,7 +101,7 @@ opSAHF(uint32_t fetchdat) return 0; } static int -opLAHF(uint32_t fetchdat) +opLAHF(UNUSED(uint32_t fetchdat)) { flags_rebuild(); AH = cpu_state.flags & 0xff; @@ -111,7 +111,7 @@ opLAHF(uint32_t fetchdat) } static int -opPUSHF(uint32_t fetchdat) +opPUSHF(UNUSED(uint32_t fetchdat)) { if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { if (cr4 & CR4_VME) { @@ -135,7 +135,7 @@ opPUSHF(uint32_t fetchdat) return cpu_state.abrt; } static int -opPUSHFD(uint32_t fetchdat) +opPUSHFD(UNUSED(uint32_t fetchdat)) { uint16_t tempw; if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { @@ -156,7 +156,7 @@ opPUSHFD(uint32_t fetchdat) } static int -opPOPF_186(uint32_t fetchdat) +opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -192,7 +192,7 @@ opPOPF_186(uint32_t fetchdat) return 0; } static int -opPOPF_286(uint32_t fetchdat) +opPOPF_286(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -228,7 +228,7 @@ opPOPF_286(uint32_t fetchdat) return 0; } static int -opPOPF(uint32_t fetchdat) +opPOPF(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -284,7 +284,7 @@ opPOPF(uint32_t fetchdat) return 0; } static int -opPOPFD(uint32_t fetchdat) +opPOPFD(UNUSED(uint32_t fetchdat)) { uint32_t templ; diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h index ba34ae5e7..c9a2d5ab2 100644 --- a/src/cpu/x86_ops_flag_2386.h +++ b/src/cpu/x86_ops_flag_2386.h @@ -1,5 +1,5 @@ static int -opCMC(uint32_t fetchdat) +opCMC(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags ^= C_FLAG; @@ -9,7 +9,7 @@ opCMC(uint32_t fetchdat) } static int -opCLC(uint32_t fetchdat) +opCLC(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags &= ~C_FLAG; @@ -18,7 +18,7 @@ opCLC(uint32_t fetchdat) return 0; } static int -opCLD(uint32_t fetchdat) +opCLD(UNUSED(uint32_t fetchdat)) { cpu_state.flags &= ~D_FLAG; CLOCK_CYCLES(2); @@ -26,7 +26,7 @@ opCLD(uint32_t fetchdat) return 0; } static int -opCLI(uint32_t fetchdat) +opCLI(UNUSED(uint32_t fetchdat)) { if (!IOPLp) { if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { @@ -44,7 +44,7 @@ opCLI(uint32_t fetchdat) } static int -opSTC(uint32_t fetchdat) +opSTC(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags |= C_FLAG; @@ -53,7 +53,7 @@ opSTC(uint32_t fetchdat) return 0; } static int -opSTD(uint32_t fetchdat) +opSTD(UNUSED(uint32_t fetchdat)) { cpu_state.flags |= D_FLAG; CLOCK_CYCLES(2); @@ -61,7 +61,7 @@ opSTD(uint32_t fetchdat) return 0; } static int -opSTI(uint32_t fetchdat) +opSTI(UNUSED(uint32_t fetchdat)) { if (!IOPLp) { if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { @@ -87,7 +87,7 @@ opSTI(uint32_t fetchdat) } static int -opSAHF(uint32_t fetchdat) +opSAHF(UNUSED(uint32_t fetchdat)) { flags_rebuild(); cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; @@ -101,7 +101,7 @@ opSAHF(uint32_t fetchdat) return 0; } static int -opLAHF(uint32_t fetchdat) +opLAHF(UNUSED(uint32_t fetchdat)) { flags_rebuild(); AH = cpu_state.flags & 0xff; @@ -111,7 +111,7 @@ opLAHF(uint32_t fetchdat) } static int -opPUSHF(uint32_t fetchdat) +opPUSHF(UNUSED(uint32_t fetchdat)) { if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { if (cr4 & CR4_VME) { @@ -135,7 +135,7 @@ opPUSHF(uint32_t fetchdat) return cpu_state.abrt; } static int -opPUSHFD(uint32_t fetchdat) +opPUSHFD(UNUSED(uint32_t fetchdat)) { uint16_t tempw; if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { @@ -156,7 +156,7 @@ opPUSHFD(uint32_t fetchdat) } static int -opPOPF_186(uint32_t fetchdat) +opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -190,7 +190,7 @@ opPOPF_186(uint32_t fetchdat) return 0; } static int -opPOPF_286(uint32_t fetchdat) +opPOPF_286(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -224,7 +224,7 @@ opPOPF_286(uint32_t fetchdat) return 0; } static int -opPOPF(uint32_t fetchdat) +opPOPF(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -278,7 +278,7 @@ opPOPF(uint32_t fetchdat) return 0; } static int -opPOPFD(uint32_t fetchdat) +opPOPFD(UNUSED(uint32_t fetchdat)) { uint32_t templ; diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index 74c67c2ee..3434c4a73 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -90,7 +90,7 @@ opESCAPE_df_a32(uint32_t fetchdat) } static int -opWAIT(uint32_t fetchdat) +opWAIT(UNUSED(uint32_t fetchdat)) { if ((cr0 & 0xa) == 0xa) { x86_int(7); diff --git a/src/cpu/x86_ops_fpu_2386.h b/src/cpu/x86_ops_fpu_2386.h index cc9c6dcc2..c2252af12 100644 --- a/src/cpu/x86_ops_fpu_2386.h +++ b/src/cpu/x86_ops_fpu_2386.h @@ -90,7 +90,7 @@ opESCAPE_df_a32(uint32_t fetchdat) } static int -opWAIT(uint32_t fetchdat) +opWAIT(UNUSED(uint32_t fetchdat)) { if ((cr0 & 0xa) == 0xa) { x86_int(7); diff --git a/src/cpu/x86_ops_inc_dec.h b/src/cpu/x86_ops_inc_dec.h index 3eb908c57..b33d02f45 100644 --- a/src/cpu/x86_ops_inc_dec.h +++ b/src/cpu/x86_ops_inc_dec.h @@ -1,5 +1,5 @@ #define INC_DEC_OP(name, reg, inc, setflags) \ - static int op##name(uint32_t fetchdat) \ + static int op##name(UNUSED(uint32_t fetchdat)) \ { \ setflags(reg, 1); \ reg += inc; \ diff --git a/src/cpu/x86_ops_int.h b/src/cpu/x86_ops_int.h index a73ed62e0..1ed5e6c2f 100644 --- a/src/cpu/x86_ops_int.h +++ b/src/cpu/x86_ops_int.h @@ -1,5 +1,5 @@ static int -opINT3(uint32_t fetchdat) +opINT3(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -18,7 +18,7 @@ opINT3(uint32_t fetchdat) } static int -opINT1(uint32_t fetchdat) +opINT1(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -75,7 +75,7 @@ opINT(uint32_t fetchdat) } static int -opINTO(uint32_t fetchdat) +opINTO(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); diff --git a/src/cpu/x86_ops_io.h b/src/cpu/x86_ops_io.h index 8a99b8668..36bf05cd3 100644 --- a/src/cpu/x86_ops_io.h +++ b/src/cpu/x86_ops_io.h @@ -75,7 +75,7 @@ opOUT_EAX_imm(uint32_t fetchdat) } static int -opIN_AL_DX(uint32_t fetchdat) +opIN_AL_DX(UNUSED(uint32_t fetchdat)) { check_io_perm(DX, 1); AL = inb(DX); @@ -86,7 +86,7 @@ opIN_AL_DX(uint32_t fetchdat) return 0; } static int -opIN_AX_DX(uint32_t fetchdat) +opIN_AX_DX(UNUSED(uint32_t fetchdat)) { check_io_perm(DX, 2); AX = inw(DX); @@ -97,7 +97,7 @@ opIN_AX_DX(uint32_t fetchdat) return 0; } static int -opIN_EAX_DX(uint32_t fetchdat) +opIN_EAX_DX(UNUSED(uint32_t fetchdat)) { check_io_perm(DX, 4); EAX = inl(DX); @@ -109,7 +109,7 @@ opIN_EAX_DX(uint32_t fetchdat) } static int -opOUT_AL_DX(uint32_t fetchdat) +opOUT_AL_DX(UNUSED(uint32_t fetchdat)) { check_io_perm(DX, 1); outb(DX, AL); @@ -120,7 +120,7 @@ opOUT_AL_DX(uint32_t fetchdat) return x86_was_reset; } static int -opOUT_AX_DX(uint32_t fetchdat) +opOUT_AX_DX(UNUSED(uint32_t fetchdat)) { check_io_perm(DX, 2); outw(DX, AX); @@ -131,7 +131,7 @@ opOUT_AX_DX(uint32_t fetchdat) return 0; } static int -opOUT_EAX_DX(uint32_t fetchdat) +opOUT_EAX_DX(UNUSED(uint32_t fetchdat)) { check_io_perm(DX, 4); outl(DX, EAX); diff --git a/src/cpu/x86_ops_jump.h b/src/cpu/x86_ops_jump.h index 97ca673d7..fc99fc5fd 100644 --- a/src/cpu/x86_ops_jump.h +++ b/src/cpu/x86_ops_jump.h @@ -51,7 +51,7 @@ return 0; \ } \ \ - static int opJ##condition##_l(uint32_t fetchdat) \ + static int opJ##condition##_l(UNUSED(uint32_t fetchdat)) \ { \ uint32_t offset = getlong(); \ if (cpu_state.abrt) \ @@ -256,7 +256,7 @@ opJMP_r16(uint32_t fetchdat) return 0; } static int -opJMP_r32(uint32_t fetchdat) +opJMP_r32(UNUSED(uint32_t fetchdat)) { int32_t offset = (int32_t) getlong(); if (cpu_state.abrt) @@ -289,7 +289,7 @@ opJMP_far_a16(uint32_t fetchdat) return 0; } static int -opJMP_far_a32(uint32_t fetchdat) +opJMP_far_a32(UNUSED(uint32_t fetchdat)) { uint16_t seg; uint32_t addr; @@ -323,7 +323,7 @@ opCALL_r16(uint32_t fetchdat) return 0; } static int -opCALL_r32(uint32_t fetchdat) +opCALL_r32(UNUSED(uint32_t fetchdat)) { int32_t addr = getlong(); @@ -339,7 +339,7 @@ opCALL_r32(uint32_t fetchdat) } static int -opRET_w(uint32_t fetchdat) +opRET_w(UNUSED(uint32_t fetchdat)) { uint16_t ret; @@ -355,7 +355,7 @@ opRET_w(uint32_t fetchdat) return 0; } static int -opRET_l(uint32_t fetchdat) +opRET_l(UNUSED(uint32_t fetchdat)) { uint32_t ret; diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index c0b9de437..ffc79f0e8 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -1,5 +1,5 @@ static int -opCBW(uint32_t fetchdat) +opCBW(UNUSED(uint32_t fetchdat)) { AH = (AL & 0x80) ? 0xff : 0; CLOCK_CYCLES(3); @@ -7,7 +7,7 @@ opCBW(uint32_t fetchdat) return 0; } static int -opCWDE(uint32_t fetchdat) +opCWDE(UNUSED(uint32_t fetchdat)) { EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX; CLOCK_CYCLES(3); @@ -15,7 +15,7 @@ opCWDE(uint32_t fetchdat) return 0; } static int -opCWD(uint32_t fetchdat) +opCWD(UNUSED(uint32_t fetchdat)) { DX = (AX & 0x8000) ? 0xFFFF : 0; CLOCK_CYCLES(2); @@ -23,7 +23,7 @@ opCWD(uint32_t fetchdat) return 0; } static int -opCDQ(uint32_t fetchdat) +opCDQ(UNUSED(uint32_t fetchdat)) { EDX = (EAX & 0x80000000) ? 0xffffffff : 0; CLOCK_CYCLES(2); @@ -32,7 +32,7 @@ opCDQ(uint32_t fetchdat) } static int -opNOP(uint32_t fetchdat) +opNOP(UNUSED(uint32_t fetchdat)) { CLOCK_CYCLES((is486) ? 1 : 3); PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); @@ -40,7 +40,7 @@ opNOP(uint32_t fetchdat) } static int -opSETALC(uint32_t fetchdat) +opSETALC(UNUSED(uint32_t fetchdat)) { AL = (CF_SET()) ? 0xff : 0; CLOCK_CYCLES(timing_rr); @@ -701,7 +701,7 @@ opF7_l_a32(uint32_t fetchdat) } static int -opHLT(uint32_t fetchdat) +opHLT(UNUSED(uint32_t fetchdat)) { if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); @@ -856,7 +856,7 @@ opBOUND_l_a32(uint32_t fetchdat) } static int -opCLTS(uint32_t fetchdat) +opCLTS(UNUSED(uint32_t fetchdat)) { if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); @@ -869,14 +869,14 @@ opCLTS(uint32_t fetchdat) } static int -opINVD(uint32_t fetchdat) +opINVD(UNUSED(uint32_t fetchdat)) { CLOCK_CYCLES(1000); CPU_BLOCK_END(); return 0; } static int -opWBINVD(uint32_t fetchdat) +opWBINVD(UNUSED(uint32_t fetchdat)) { if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); @@ -888,7 +888,7 @@ opWBINVD(uint32_t fetchdat) } static int -opLOADALL(uint32_t fetchdat) +opLOADALL(UNUSED(uint32_t fetchdat)) { if (CPL && (cr0 & 1)) { x86gpf(NULL, 0); @@ -998,7 +998,7 @@ loadall_load_segment(uint32_t addr, x86seg *s) } static int -opLOADALL386(uint32_t fetchdat) +opLOADALL386(UNUSED(uint32_t fetchdat)) { uint32_t la_addr = es + EDI; @@ -1046,7 +1046,7 @@ opLOADALL386(uint32_t fetchdat) } static int -opCPUID(uint32_t fetchdat) +opCPUID(UNUSED(uint32_t fetchdat)) { if (CPUID) { cpu_CPUID(); @@ -1059,7 +1059,7 @@ opCPUID(uint32_t fetchdat) } static int -opRDMSR(uint32_t fetchdat) +opRDMSR(UNUSED(uint32_t fetchdat)) { if (cpu_has_feature(CPU_FEATURE_MSR)) { cpu_RDMSR(); @@ -1072,7 +1072,7 @@ opRDMSR(uint32_t fetchdat) } static int -opWRMSR(uint32_t fetchdat) +opWRMSR(UNUSED(uint32_t fetchdat)) { if (cpu_has_feature(CPU_FEATURE_MSR)) { cpu_WRMSR(); @@ -1085,7 +1085,7 @@ opWRMSR(uint32_t fetchdat) } static int -opRSM(uint32_t fetchdat) +opRSM(UNUSED(uint32_t fetchdat)) { if (in_smm) { leave_smm(); diff --git a/src/cpu/x86_ops_mmx.h b/src/cpu/x86_ops_mmx.h index ab5e19762..338948af5 100644 --- a/src/cpu/x86_ops_mmx.h +++ b/src/cpu/x86_ops_mmx.h @@ -34,7 +34,7 @@ x87_set_mmx() static int -opEMMS(uint32_t fetchdat) +opEMMS(UNUSED(uint32_t fetchdat)) { if (!cpu_has_feature(CPU_FEATURE_MMX)) { cpu_state.pc = cpu_state.oldpc; diff --git a/src/cpu/x86_ops_mov.h b/src/cpu/x86_ops_mov.h index e77876d5c..787a727d3 100644 --- a/src/cpu/x86_ops_mov.h +++ b/src/cpu/x86_ops_mov.h @@ -129,7 +129,7 @@ opMOV_SP_imm(uint32_t fetchdat) } static int -opMOV_EAX_imm(uint32_t fetchdat) +opMOV_EAX_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -140,7 +140,7 @@ opMOV_EAX_imm(uint32_t fetchdat) return 0; } static int -opMOV_EBX_imm(uint32_t fetchdat) +opMOV_EBX_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -151,7 +151,7 @@ opMOV_EBX_imm(uint32_t fetchdat) return 0; } static int -opMOV_ECX_imm(uint32_t fetchdat) +opMOV_ECX_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -162,7 +162,7 @@ opMOV_ECX_imm(uint32_t fetchdat) return 0; } static int -opMOV_EDX_imm(uint32_t fetchdat) +opMOV_EDX_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -173,7 +173,7 @@ opMOV_EDX_imm(uint32_t fetchdat) return 0; } static int -opMOV_ESI_imm(uint32_t fetchdat) +opMOV_ESI_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -184,7 +184,7 @@ opMOV_ESI_imm(uint32_t fetchdat) return 0; } static int -opMOV_EDI_imm(uint32_t fetchdat) +opMOV_EDI_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -195,7 +195,7 @@ opMOV_EDI_imm(uint32_t fetchdat) return 0; } static int -opMOV_EBP_imm(uint32_t fetchdat) +opMOV_EBP_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -206,7 +206,7 @@ opMOV_EBP_imm(uint32_t fetchdat) return 0; } static int -opMOV_ESP_imm(uint32_t fetchdat) +opMOV_ESP_imm(UNUSED(uint32_t fetchdat)) { uint32_t templ = getlong(); if (cpu_state.abrt) @@ -326,7 +326,7 @@ opMOV_AL_a16(uint32_t fetchdat) return 0; } static int -opMOV_AL_a32(uint32_t fetchdat) +opMOV_AL_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; uint32_t addr = getlong(); @@ -356,7 +356,7 @@ opMOV_AX_a16(uint32_t fetchdat) return 0; } static int -opMOV_AX_a32(uint32_t fetchdat) +opMOV_AX_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; uint32_t addr = getlong(); @@ -386,7 +386,7 @@ opMOV_EAX_a16(uint32_t fetchdat) return 0; } static int -opMOV_EAX_a32(uint32_t fetchdat) +opMOV_EAX_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; uint32_t addr = getlong(); @@ -413,7 +413,7 @@ opMOV_a16_AL(uint32_t fetchdat) return cpu_state.abrt; } static int -opMOV_a32_AL(uint32_t fetchdat) +opMOV_a32_AL(UNUSED(uint32_t fetchdat)) { uint32_t addr = getlong(); SEG_CHECK_WRITE(cpu_state.ea_seg); @@ -435,7 +435,7 @@ opMOV_a16_AX(uint32_t fetchdat) return cpu_state.abrt; } static int -opMOV_a32_AX(uint32_t fetchdat) +opMOV_a32_AX(UNUSED(uint32_t fetchdat)) { uint32_t addr = getlong(); if (cpu_state.abrt) @@ -459,7 +459,7 @@ opMOV_a16_EAX(uint32_t fetchdat) return cpu_state.abrt; } static int -opMOV_a32_EAX(uint32_t fetchdat) +opMOV_a32_EAX(UNUSED(uint32_t fetchdat)) { uint32_t addr = getlong(); if (cpu_state.abrt) @@ -515,7 +515,7 @@ opLEA_l_a32(uint32_t fetchdat) } static int -opXLAT_a16(uint32_t fetchdat) +opXLAT_a16(UNUSED(uint32_t fetchdat)) { uint32_t addr = (BX + AL) & 0xFFFF; uint8_t temp; @@ -530,7 +530,7 @@ opXLAT_a16(uint32_t fetchdat) return 0; } static int -opXLAT_a32(uint32_t fetchdat) +opXLAT_a32(UNUSED(uint32_t fetchdat)) { uint32_t addr = EBX + AL; uint8_t temp; diff --git a/src/cpu/x86_ops_msr.h b/src/cpu/x86_ops_msr.h index daae01d84..a59cecdd4 100644 --- a/src/cpu/x86_ops_msr.h +++ b/src/cpu/x86_ops_msr.h @@ -1,5 +1,5 @@ static int -opRDTSC(uint32_t fetchdat) +opRDTSC(UNUSED(uint32_t fetchdat)) { if (!cpu_has_feature(CPU_FEATURE_RDTSC)) { cpu_state.pc = cpu_state.oldpc; @@ -21,7 +21,7 @@ opRDTSC(uint32_t fetchdat) } static int -opRDPMC(uint32_t fetchdat) +opRDPMC(UNUSED(uint32_t fetchdat)) { if (ECX > 1 || (!(cr4 & CR4_PCE) && (cr0 & 1) && CPL)) { x86gpf("RDPMC not allowed", 0); diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h index 4f32b0e37..81f194f14 100644 --- a/src/cpu/x86_ops_pmode.h +++ b/src/cpu/x86_ops_pmode.h @@ -172,12 +172,12 @@ opLAR(w_a16, fetch_ea_16, 0, 0) return cpu_state.abrt; \ } - opLSL(w_a16, fetch_ea_16, 0, 0) - opLSL(w_a32, fetch_ea_32, 0, 1) - opLSL(l_a16, fetch_ea_16, 1, 0) - opLSL(l_a32, fetch_ea_32, 1, 1) +opLSL(w_a16, fetch_ea_16, 0, 0) +opLSL(w_a32, fetch_ea_32, 0, 1) +opLSL(l_a16, fetch_ea_16, 1, 0) +opLSL(l_a32, fetch_ea_32, 1, 1) - static int op0F00_common(uint32_t fetchdat, int ea32) +static int op0F00_common(uint32_t fetchdat, UNUSED(int ea32)) { int dpl; int valid; @@ -359,7 +359,7 @@ op0F00_a32(uint32_t fetchdat) } static int -op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) +op0F01_common(UNUSED(uint32_t fetchdat), int is32, int is286, UNUSED(int ea32)) { uint32_t base; uint16_t limit; diff --git a/src/cpu/x86_ops_rep.h b/src/cpu/x86_ops_rep.h index a49db7e81..c75684d31 100644 --- a/src/cpu/x86_ops_rep.h +++ b/src/cpu/x86_ops_rep.h @@ -1,5 +1,5 @@ #define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ - static int opREP_INSB_##size(uint32_t fetchdat) \ + static int opREP_INSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -38,7 +38,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_INSW_##size(uint32_t fetchdat) \ + static int opREP_INSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -77,7 +77,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_INSL_##size(uint32_t fetchdat) \ + static int opREP_INSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -117,7 +117,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_OUTSB_##size(uint32_t fetchdat) \ + static int opREP_OUTSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -148,7 +148,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_OUTSW_##size(uint32_t fetchdat) \ + static int opREP_OUTSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -179,7 +179,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_OUTSL_##size(uint32_t fetchdat) \ + static int opREP_OUTSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -211,7 +211,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_MOVSB_##size(uint32_t fetchdat) \ + static int opREP_MOVSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -264,7 +264,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_MOVSW_##size(uint32_t fetchdat) \ + static int opREP_MOVSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -318,7 +318,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_MOVSL_##size(uint32_t fetchdat) \ + static int opREP_MOVSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -373,7 +373,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_STOSB_##size(uint32_t fetchdat) \ + static int opREP_STOSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -405,7 +405,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_STOSW_##size(uint32_t fetchdat) \ + static int opREP_STOSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -437,7 +437,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_STOSL_##size(uint32_t fetchdat) \ + static int opREP_STOSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -470,7 +470,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_LODSB_##size(uint32_t fetchdat) \ + static int opREP_LODSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -502,7 +502,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_LODSW_##size(uint32_t fetchdat) \ + static int opREP_LODSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -534,7 +534,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_LODSL_##size(uint32_t fetchdat) \ + static int opREP_LODSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -570,7 +570,7 @@ #define CHEK_READ(a, b, c) #define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ - static int opREP_CMPSB_##size(uint32_t fetchdat) \ + static int opREP_CMPSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ \ @@ -623,7 +623,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_CMPSW_##size(uint32_t fetchdat) \ + static int opREP_CMPSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ \ @@ -677,7 +677,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_CMPSL_##size(uint32_t fetchdat) \ + static int opREP_CMPSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ \ @@ -732,7 +732,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_SCASB_##size(uint32_t fetchdat) \ + static int opREP_SCASB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -767,7 +767,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_SCASW_##size(uint32_t fetchdat) \ + static int opREP_SCASW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -802,7 +802,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_SCASL_##size(uint32_t fetchdat) \ + static int opREP_SCASL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ diff --git a/src/cpu/x86_ops_rep_2386.h b/src/cpu/x86_ops_rep_2386.h index fe5048340..aa1984f81 100644 --- a/src/cpu/x86_ops_rep_2386.h +++ b/src/cpu/x86_ops_rep_2386.h @@ -1,5 +1,5 @@ #define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ - static int opREP_INSB_##size(uint32_t fetchdat) \ + static int opREP_INSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -38,7 +38,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_INSW_##size(uint32_t fetchdat) \ + static int opREP_INSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -77,7 +77,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_INSL_##size(uint32_t fetchdat) \ + static int opREP_INSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -117,7 +117,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_OUTSB_##size(uint32_t fetchdat) \ + static int opREP_OUTSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -148,7 +148,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_OUTSW_##size(uint32_t fetchdat) \ + static int opREP_OUTSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -179,7 +179,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_OUTSL_##size(uint32_t fetchdat) \ + static int opREP_OUTSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ \ @@ -211,7 +211,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_MOVSB_##size(uint32_t fetchdat) \ + static int opREP_MOVSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -264,7 +264,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_MOVSW_##size(uint32_t fetchdat) \ + static int opREP_MOVSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -318,7 +318,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_MOVSL_##size(uint32_t fetchdat) \ + static int opREP_MOVSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -373,7 +373,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_STOSB_##size(uint32_t fetchdat) \ + static int opREP_STOSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -405,7 +405,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_STOSW_##size(uint32_t fetchdat) \ + static int opREP_STOSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -437,7 +437,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_STOSL_##size(uint32_t fetchdat) \ + static int opREP_STOSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -470,7 +470,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_LODSB_##size(uint32_t fetchdat) \ + static int opREP_LODSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -502,7 +502,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_LODSW_##size(uint32_t fetchdat) \ + static int opREP_LODSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -534,7 +534,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_LODSL_##size(uint32_t fetchdat) \ + static int opREP_LODSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -570,7 +570,7 @@ #define CHEK_READ(a, b, c) #define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ - static int opREP_CMPSB_##size(uint32_t fetchdat) \ + static int opREP_CMPSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ \ @@ -619,7 +619,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_CMPSW_##size(uint32_t fetchdat) \ + static int opREP_CMPSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ \ @@ -669,7 +669,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_CMPSL_##size(uint32_t fetchdat) \ + static int opREP_CMPSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ \ @@ -720,7 +720,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_SCASB_##size(uint32_t fetchdat) \ + static int opREP_SCASB_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -755,7 +755,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_SCASW_##size(uint32_t fetchdat) \ + static int opREP_SCASW_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ @@ -790,7 +790,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_SCASL_##size(uint32_t fetchdat) \ + static int opREP_SCASL_##size(UNUSED(uint32_t fetchdat)) \ { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ diff --git a/src/cpu/x86_ops_rep_dyn.h b/src/cpu/x86_ops_rep_dyn.h index cf32209cc..bdb721ab0 100644 --- a/src/cpu/x86_ops_rep_dyn.h +++ b/src/cpu/x86_ops_rep_dyn.h @@ -1,5 +1,5 @@ #define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ - static int opREP_INSB_##size(uint32_t fetchdat) \ + static int opREP_INSB_##size(UNUSED(uint32_t fetchdat)) \ { \ addr64 = 0x00000000; \ \ @@ -32,7 +32,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_INSW_##size(uint32_t fetchdat) \ + static int opREP_INSW_##size(UNUSED(uint32_t fetchdat)) \ { \ addr64a[0] = addr64a[1] = 0x00000000; \ \ @@ -65,7 +65,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_INSL_##size(uint32_t fetchdat) \ + static int opREP_INSL_##size(UNUSED(uint32_t fetchdat)) \ { \ addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ \ @@ -99,7 +99,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_OUTSB_##size(uint32_t fetchdat) \ + static int opREP_OUTSB_##size(UNUSED(uint32_t fetchdat)) \ { \ if (CNT_REG > 0) { \ uint8_t temp; \ @@ -124,7 +124,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_OUTSW_##size(uint32_t fetchdat) \ + static int opREP_OUTSW_##size(UNUSED(uint32_t fetchdat)) \ { \ if (CNT_REG > 0) { \ uint16_t temp; \ @@ -149,7 +149,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_OUTSL_##size(uint32_t fetchdat) \ + static int opREP_OUTSL_##size(UNUSED(uint32_t fetchdat)) \ { \ if (CNT_REG > 0) { \ uint32_t temp; \ @@ -175,7 +175,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_MOVSB_##size(uint32_t fetchdat) \ + static int opREP_MOVSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ addr64 = addr64_2 = 0x00000000; \ @@ -223,7 +223,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_MOVSW_##size(uint32_t fetchdat) \ + static int opREP_MOVSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ addr64a[0] = addr64a[1] = 0x00000000; \ @@ -272,7 +272,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_MOVSL_##size(uint32_t fetchdat) \ + static int opREP_MOVSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ @@ -322,7 +322,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_STOSB_##size(uint32_t fetchdat) \ + static int opREP_STOSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ @@ -350,7 +350,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_STOSW_##size(uint32_t fetchdat) \ + static int opREP_STOSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ @@ -378,7 +378,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_STOSL_##size(uint32_t fetchdat) \ + static int opREP_STOSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ @@ -407,7 +407,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_LODSB_##size(uint32_t fetchdat) \ + static int opREP_LODSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ @@ -435,7 +435,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_LODSW_##size(uint32_t fetchdat) \ + static int opREP_LODSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ @@ -463,7 +463,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_LODSL_##size(uint32_t fetchdat) \ + static int opREP_LODSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ @@ -495,7 +495,7 @@ #define CHEK_READ(a, b, c) #define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ - static int opREP_CMPSB_##size(uint32_t fetchdat) \ + static int opREP_CMPSB_##size(UNUSED(uint32_t fetchdat)) \ { \ int tempz; \ \ @@ -545,7 +545,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_CMPSW_##size(uint32_t fetchdat) \ + static int opREP_CMPSW_##size(UNUSED(uint32_t fetchdat)) \ { \ int tempz; \ \ @@ -596,7 +596,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_CMPSL_##size(uint32_t fetchdat) \ + static int opREP_CMPSL_##size(UNUSED(uint32_t fetchdat)) \ { \ int tempz; \ \ @@ -648,7 +648,7 @@ return cpu_state.abrt; \ } \ \ - static int opREP_SCASB_##size(uint32_t fetchdat) \ + static int opREP_SCASB_##size(UNUSED(uint32_t fetchdat)) \ { \ int tempz; \ int cycles_end = cycles - 1000; \ @@ -680,7 +680,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_SCASW_##size(uint32_t fetchdat) \ + static int opREP_SCASW_##size(UNUSED(uint32_t fetchdat)) \ { \ int tempz; \ int cycles_end = cycles - 1000; \ @@ -712,7 +712,7 @@ } \ return cpu_state.abrt; \ } \ - static int opREP_SCASL_##size(uint32_t fetchdat) \ + static int opREP_SCASL_##size(UNUSED(uint32_t fetchdat)) \ { \ int tempz; \ int cycles_end = cycles - 1000; \ diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index d30d4eb8f..935fb5aa0 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -47,7 +47,7 @@ cycles -= timing_retf_rm; static int -opRETF_a16(uint32_t fetchdat) +opRETF_a16(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -60,7 +60,7 @@ opRETF_a16(uint32_t fetchdat) return 0; } static int -opRETF_a32(uint32_t fetchdat) +opRETF_a32(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -103,7 +103,7 @@ opRETF_a32_imm(uint32_t fetchdat) } static int -opIRET_186(uint32_t fetchdat) +opIRET_186(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -146,7 +146,7 @@ opIRET_186(uint32_t fetchdat) } static int -opIRET_286(uint32_t fetchdat) +opIRET_286(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -189,7 +189,7 @@ opIRET_286(uint32_t fetchdat) } static int -opIRET(uint32_t fetchdat) +opIRET(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -260,7 +260,7 @@ opIRET(uint32_t fetchdat) } static int -opIRETD(uint32_t fetchdat) +opIRETD(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); diff --git a/src/cpu/x86_ops_ret_2386.h b/src/cpu/x86_ops_ret_2386.h index ca85bf2b0..155925dfe 100644 --- a/src/cpu/x86_ops_ret_2386.h +++ b/src/cpu/x86_ops_ret_2386.h @@ -47,7 +47,7 @@ cycles -= timing_retf_rm; static int -opRETF_a16(uint32_t fetchdat) +opRETF_a16(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -60,7 +60,7 @@ opRETF_a16(uint32_t fetchdat) return 0; } static int -opRETF_a32(uint32_t fetchdat) +opRETF_a32(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -103,7 +103,7 @@ opRETF_a32_imm(uint32_t fetchdat) } static int -opIRET_186(uint32_t fetchdat) +opIRET_186(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -144,7 +144,7 @@ opIRET_186(uint32_t fetchdat) } static int -opIRET_286(uint32_t fetchdat) +opIRET_286(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -185,7 +185,7 @@ opIRET_286(uint32_t fetchdat) } static int -opIRET(uint32_t fetchdat) +opIRET(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); @@ -254,7 +254,7 @@ opIRET(uint32_t fetchdat) } static int -opIRETD(uint32_t fetchdat) +opIRETD(UNUSED(uint32_t fetchdat)) { int cycles_old = cycles; UN_USED(cycles_old); diff --git a/src/cpu/x86_ops_stack.h b/src/cpu/x86_ops_stack.h index fbf603ddb..f5d608fbb 100644 --- a/src/cpu/x86_ops_stack.h +++ b/src/cpu/x86_ops_stack.h @@ -1,5 +1,5 @@ #define PUSH_W_OP(reg) \ - static int opPUSH_##reg(uint32_t fetchdat) \ + static int opPUSH_##reg(UNUSED(uint32_t fetchdat)) \ { \ PUSH_W(reg); \ CLOCK_CYCLES((is486) ? 1 : 2); \ @@ -8,7 +8,7 @@ } #define PUSH_L_OP(reg) \ - static int opPUSH_##reg(uint32_t fetchdat) \ + static int opPUSH_##reg(UNUSED(uint32_t fetchdat)) \ { \ PUSH_L(reg); \ CLOCK_CYCLES((is486) ? 1 : 2); \ @@ -17,7 +17,7 @@ } #define POP_W_OP(reg) \ - static int opPOP_##reg(uint32_t fetchdat) \ + static int opPOP_##reg(UNUSED(uint32_t fetchdat)) \ { \ reg = POP_W(); \ CLOCK_CYCLES((is486) ? 1 : 4); \ @@ -26,7 +26,7 @@ } #define POP_L_OP(reg) \ - static int opPOP_##reg(uint32_t fetchdat) \ + static int opPOP_##reg(UNUSED(uint32_t fetchdat)) \ { \ reg = POP_L(); \ CLOCK_CYCLES((is486) ? 1 : 4); \ @@ -71,7 +71,7 @@ POP_L_OP(EBP) POP_L_OP(ESP) static int -opPUSHA_w(uint32_t fetchdat) +opPUSHA_w(UNUSED(uint32_t fetchdat)) { if (stack32) { writememw(ss, ESP - 2, AX); @@ -101,7 +101,7 @@ opPUSHA_w(uint32_t fetchdat) return cpu_state.abrt; } static int -opPUSHA_l(uint32_t fetchdat) +opPUSHA_l(UNUSED(uint32_t fetchdat)) { if (stack32) { writememl(ss, ESP - 4, EAX); @@ -132,7 +132,7 @@ opPUSHA_l(uint32_t fetchdat) } static int -opPOPA_w(uint32_t fetchdat) +opPOPA_w(UNUSED(uint32_t fetchdat)) { if (stack32) { DI = readmemw(ss, ESP); @@ -186,7 +186,7 @@ opPOPA_w(uint32_t fetchdat) return 0; } static int -opPOPA_l(uint32_t fetchdat) +opPOPA_l(UNUSED(uint32_t fetchdat)) { if (stack32) { EDI = readmeml(ss, ESP); @@ -250,7 +250,7 @@ opPUSH_imm_w(uint32_t fetchdat) return cpu_state.abrt; } static int -opPUSH_imm_l(uint32_t fetchdat) +opPUSH_imm_l(UNUSED(uint32_t fetchdat)) { uint32_t val = getlong(); if (cpu_state.abrt) @@ -550,7 +550,7 @@ opENTER_l(uint32_t fetchdat) } static int -opLEAVE_w(uint32_t fetchdat) +opLEAVE_w(UNUSED(uint32_t fetchdat)) { uint32_t tempESP = ESP; uint16_t temp; @@ -568,7 +568,7 @@ opLEAVE_w(uint32_t fetchdat) return 0; } static int -opLEAVE_l(uint32_t fetchdat) +opLEAVE_l(UNUSED(uint32_t fetchdat)) { uint32_t tempESP = ESP; uint32_t temp; @@ -587,14 +587,14 @@ opLEAVE_l(uint32_t fetchdat) } #define PUSH_SEG_OPS(seg) \ - static int opPUSH_##seg##_w(uint32_t fetchdat) \ + static int opPUSH_##seg##_w(UNUSED(uint32_t fetchdat)) \ { \ PUSH_W(seg); \ CLOCK_CYCLES(2); \ PREFETCH_RUN(2, 1, -1, 0, 0, 1, 0, 0); \ return cpu_state.abrt; \ } \ - static int opPUSH_##seg##_l(uint32_t fetchdat) \ + static int opPUSH_##seg##_l(UNUSED(uint32_t fetchdat)) \ { \ PUSH_L(seg); \ CLOCK_CYCLES(2); \ @@ -603,7 +603,7 @@ opLEAVE_l(uint32_t fetchdat) } #define POP_SEG_OPS(seg, realseg) \ - static int opPOP_##seg##_w(uint32_t fetchdat) \ + static int opPOP_##seg##_w(UNUSED(uint32_t fetchdat)) \ { \ uint16_t temp_seg; \ uint32_t temp_esp = ESP; \ @@ -617,7 +617,7 @@ opLEAVE_l(uint32_t fetchdat) PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0, 0, 1, 0, 0); \ return cpu_state.abrt; \ } \ - static int opPOP_##seg##_l(uint32_t fetchdat) \ + static int opPOP_##seg##_l(UNUSED(uint32_t fetchdat)) \ { \ uint32_t temp_seg; \ uint32_t temp_esp = ESP; \ diff --git a/src/cpu/x86_ops_string.h b/src/cpu/x86_ops_string.h index 619386fcb..d3a7d89a9 100644 --- a/src/cpu/x86_ops_string.h +++ b/src/cpu/x86_ops_string.h @@ -1,5 +1,5 @@ static int -opMOVSB_a16(uint32_t fetchdat) +opMOVSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -35,7 +35,7 @@ opMOVSB_a16(uint32_t fetchdat) return 0; } static int -opMOVSB_a32(uint32_t fetchdat) +opMOVSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -71,7 +71,7 @@ opMOVSB_a32(uint32_t fetchdat) } static int -opMOVSW_a16(uint32_t fetchdat) +opMOVSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -107,7 +107,7 @@ opMOVSW_a16(uint32_t fetchdat) return 0; } static int -opMOVSW_a32(uint32_t fetchdat) +opMOVSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -144,7 +144,7 @@ opMOVSW_a32(uint32_t fetchdat) } static int -opMOVSL_a16(uint32_t fetchdat) +opMOVSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -180,7 +180,7 @@ opMOVSL_a16(uint32_t fetchdat) return 0; } static int -opMOVSL_a32(uint32_t fetchdat) +opMOVSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -217,7 +217,7 @@ opMOVSL_a32(uint32_t fetchdat) } static int -opCMPSB_a16(uint32_t fetchdat) +opCMPSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t src; uint8_t dst; @@ -258,7 +258,7 @@ opCMPSB_a16(uint32_t fetchdat) return 0; } static int -opCMPSB_a32(uint32_t fetchdat) +opCMPSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t src; uint8_t dst; @@ -300,7 +300,7 @@ opCMPSB_a32(uint32_t fetchdat) } static int -opCMPSW_a16(uint32_t fetchdat) +opCMPSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t src; uint16_t dst; @@ -342,7 +342,7 @@ opCMPSW_a16(uint32_t fetchdat) return 0; } static int -opCMPSW_a32(uint32_t fetchdat) +opCMPSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t src; uint16_t dst; @@ -385,7 +385,7 @@ opCMPSW_a32(uint32_t fetchdat) } static int -opCMPSL_a16(uint32_t fetchdat) +opCMPSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t src; uint32_t dst; @@ -427,7 +427,7 @@ opCMPSL_a16(uint32_t fetchdat) return 0; } static int -opCMPSL_a32(uint32_t fetchdat) +opCMPSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t src; uint32_t dst; @@ -470,7 +470,7 @@ opCMPSL_a32(uint32_t fetchdat) } static int -opSTOSB_a16(uint32_t fetchdat) +opSTOSB_a16(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, DI, DI); @@ -486,7 +486,7 @@ opSTOSB_a16(uint32_t fetchdat) return 0; } static int -opSTOSB_a32(uint32_t fetchdat) +opSTOSB_a32(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); @@ -503,7 +503,7 @@ opSTOSB_a32(uint32_t fetchdat) } static int -opSTOSW_a16(uint32_t fetchdat) +opSTOSW_a16(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); @@ -519,7 +519,7 @@ opSTOSW_a16(uint32_t fetchdat) return 0; } static int -opSTOSW_a32(uint32_t fetchdat) +opSTOSW_a32(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); @@ -536,7 +536,7 @@ opSTOSW_a32(uint32_t fetchdat) } static int -opSTOSL_a16(uint32_t fetchdat) +opSTOSL_a16(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); @@ -552,7 +552,7 @@ opSTOSL_a16(uint32_t fetchdat) return 0; } static int -opSTOSL_a32(uint32_t fetchdat) +opSTOSL_a32(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); @@ -569,7 +569,7 @@ opSTOSL_a32(uint32_t fetchdat) } static int -opLODSB_a16(uint32_t fetchdat) +opLODSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -588,7 +588,7 @@ opLODSB_a16(uint32_t fetchdat) return 0; } static int -opLODSB_a32(uint32_t fetchdat) +opLODSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -608,7 +608,7 @@ opLODSB_a32(uint32_t fetchdat) } static int -opLODSW_a16(uint32_t fetchdat) +opLODSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -627,7 +627,7 @@ opLODSW_a16(uint32_t fetchdat) return 0; } static int -opLODSW_a32(uint32_t fetchdat) +opLODSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -647,7 +647,7 @@ opLODSW_a32(uint32_t fetchdat) } static int -opLODSL_a16(uint32_t fetchdat) +opLODSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -666,7 +666,7 @@ opLODSL_a16(uint32_t fetchdat) return 0; } static int -opLODSL_a32(uint32_t fetchdat) +opLODSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -686,7 +686,7 @@ opLODSL_a32(uint32_t fetchdat) } static int -opSCASB_a16(uint32_t fetchdat) +opSCASB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -705,7 +705,7 @@ opSCASB_a16(uint32_t fetchdat) return 0; } static int -opSCASB_a32(uint32_t fetchdat) +opSCASB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -725,7 +725,7 @@ opSCASB_a32(uint32_t fetchdat) } static int -opSCASW_a16(uint32_t fetchdat) +opSCASW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -744,7 +744,7 @@ opSCASW_a16(uint32_t fetchdat) return 0; } static int -opSCASW_a32(uint32_t fetchdat) +opSCASW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -764,7 +764,7 @@ opSCASW_a32(uint32_t fetchdat) } static int -opSCASL_a16(uint32_t fetchdat) +opSCASL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -783,7 +783,7 @@ opSCASL_a16(uint32_t fetchdat) return 0; } static int -opSCASL_a32(uint32_t fetchdat) +opSCASL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -803,7 +803,7 @@ opSCASL_a32(uint32_t fetchdat) } static int -opINSB_a16(uint32_t fetchdat) +opINSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -829,7 +829,7 @@ opINSB_a16(uint32_t fetchdat) return 0; } static int -opINSB_a32(uint32_t fetchdat) +opINSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -856,7 +856,7 @@ opINSB_a32(uint32_t fetchdat) } static int -opINSW_a16(uint32_t fetchdat) +opINSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -882,7 +882,7 @@ opINSW_a16(uint32_t fetchdat) return 0; } static int -opINSW_a32(uint32_t fetchdat) +opINSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -909,7 +909,7 @@ opINSW_a32(uint32_t fetchdat) } static int -opINSL_a16(uint32_t fetchdat) +opINSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -935,7 +935,7 @@ opINSL_a16(uint32_t fetchdat) return 0; } static int -opINSL_a32(uint32_t fetchdat) +opINSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -962,7 +962,7 @@ opINSL_a32(uint32_t fetchdat) } static int -opOUTSB_a16(uint32_t fetchdat) +opOUTSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -982,7 +982,7 @@ opOUTSB_a16(uint32_t fetchdat) return 0; } static int -opOUTSB_a32(uint32_t fetchdat) +opOUTSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -1003,7 +1003,7 @@ opOUTSB_a32(uint32_t fetchdat) } static int -opOUTSW_a16(uint32_t fetchdat) +opOUTSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -1023,7 +1023,7 @@ opOUTSW_a16(uint32_t fetchdat) return 0; } static int -opOUTSW_a32(uint32_t fetchdat) +opOUTSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -1044,7 +1044,7 @@ opOUTSW_a32(uint32_t fetchdat) } static int -opOUTSL_a16(uint32_t fetchdat) +opOUTSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -1064,7 +1064,7 @@ opOUTSL_a16(uint32_t fetchdat) return 0; } static int -opOUTSL_a32(uint32_t fetchdat) +opOUTSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; diff --git a/src/cpu/x86_ops_string_2386.h b/src/cpu/x86_ops_string_2386.h index 98875e54f..32d69d4b2 100644 --- a/src/cpu/x86_ops_string_2386.h +++ b/src/cpu/x86_ops_string_2386.h @@ -1,5 +1,5 @@ static int -opMOVSB_a16(uint32_t fetchdat) +opMOVSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -35,7 +35,7 @@ opMOVSB_a16(uint32_t fetchdat) return 0; } static int -opMOVSB_a32(uint32_t fetchdat) +opMOVSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -71,7 +71,7 @@ opMOVSB_a32(uint32_t fetchdat) } static int -opMOVSW_a16(uint32_t fetchdat) +opMOVSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -107,7 +107,7 @@ opMOVSW_a16(uint32_t fetchdat) return 0; } static int -opMOVSW_a32(uint32_t fetchdat) +opMOVSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -144,7 +144,7 @@ opMOVSW_a32(uint32_t fetchdat) } static int -opMOVSL_a16(uint32_t fetchdat) +opMOVSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -180,7 +180,7 @@ opMOVSL_a16(uint32_t fetchdat) return 0; } static int -opMOVSL_a32(uint32_t fetchdat) +opMOVSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -217,7 +217,7 @@ opMOVSL_a32(uint32_t fetchdat) } static int -opCMPSB_a16(uint32_t fetchdat) +opCMPSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t src; uint8_t dst; @@ -254,7 +254,7 @@ opCMPSB_a16(uint32_t fetchdat) return 0; } static int -opCMPSB_a32(uint32_t fetchdat) +opCMPSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t src; uint8_t dst; @@ -292,7 +292,7 @@ opCMPSB_a32(uint32_t fetchdat) } static int -opCMPSW_a16(uint32_t fetchdat) +opCMPSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t src; uint16_t dst; @@ -330,7 +330,7 @@ opCMPSW_a16(uint32_t fetchdat) return 0; } static int -opCMPSW_a32(uint32_t fetchdat) +opCMPSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t src; uint16_t dst; @@ -369,7 +369,7 @@ opCMPSW_a32(uint32_t fetchdat) } static int -opCMPSL_a16(uint32_t fetchdat) +opCMPSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t src; uint32_t dst; @@ -407,7 +407,7 @@ opCMPSL_a16(uint32_t fetchdat) return 0; } static int -opCMPSL_a32(uint32_t fetchdat) +opCMPSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t src; uint32_t dst; @@ -446,7 +446,7 @@ opCMPSL_a32(uint32_t fetchdat) } static int -opSTOSB_a16(uint32_t fetchdat) +opSTOSB_a16(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, DI, DI); @@ -462,7 +462,7 @@ opSTOSB_a16(uint32_t fetchdat) return 0; } static int -opSTOSB_a32(uint32_t fetchdat) +opSTOSB_a32(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); @@ -479,7 +479,7 @@ opSTOSB_a32(uint32_t fetchdat) } static int -opSTOSW_a16(uint32_t fetchdat) +opSTOSW_a16(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); @@ -495,7 +495,7 @@ opSTOSW_a16(uint32_t fetchdat) return 0; } static int -opSTOSW_a32(uint32_t fetchdat) +opSTOSW_a32(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); @@ -512,7 +512,7 @@ opSTOSW_a32(uint32_t fetchdat) } static int -opSTOSL_a16(uint32_t fetchdat) +opSTOSL_a16(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); @@ -528,7 +528,7 @@ opSTOSL_a16(uint32_t fetchdat) return 0; } static int -opSTOSL_a32(uint32_t fetchdat) +opSTOSL_a32(UNUSED(uint32_t fetchdat)) { SEG_CHECK_WRITE(&cpu_state.seg_es); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); @@ -545,7 +545,7 @@ opSTOSL_a32(uint32_t fetchdat) } static int -opLODSB_a16(uint32_t fetchdat) +opLODSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -564,7 +564,7 @@ opLODSB_a16(uint32_t fetchdat) return 0; } static int -opLODSB_a32(uint32_t fetchdat) +opLODSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -584,7 +584,7 @@ opLODSB_a32(uint32_t fetchdat) } static int -opLODSW_a16(uint32_t fetchdat) +opLODSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -603,7 +603,7 @@ opLODSW_a16(uint32_t fetchdat) return 0; } static int -opLODSW_a32(uint32_t fetchdat) +opLODSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -623,7 +623,7 @@ opLODSW_a32(uint32_t fetchdat) } static int -opLODSL_a16(uint32_t fetchdat) +opLODSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -642,7 +642,7 @@ opLODSL_a16(uint32_t fetchdat) return 0; } static int -opLODSL_a32(uint32_t fetchdat) +opLODSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -662,7 +662,7 @@ opLODSL_a32(uint32_t fetchdat) } static int -opSCASB_a16(uint32_t fetchdat) +opSCASB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -681,7 +681,7 @@ opSCASB_a16(uint32_t fetchdat) return 0; } static int -opSCASB_a32(uint32_t fetchdat) +opSCASB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -701,7 +701,7 @@ opSCASB_a32(uint32_t fetchdat) } static int -opSCASW_a16(uint32_t fetchdat) +opSCASW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -720,7 +720,7 @@ opSCASW_a16(uint32_t fetchdat) return 0; } static int -opSCASW_a32(uint32_t fetchdat) +opSCASW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -740,7 +740,7 @@ opSCASW_a32(uint32_t fetchdat) } static int -opSCASL_a16(uint32_t fetchdat) +opSCASL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -759,7 +759,7 @@ opSCASL_a16(uint32_t fetchdat) return 0; } static int -opSCASL_a32(uint32_t fetchdat) +opSCASL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -779,7 +779,7 @@ opSCASL_a32(uint32_t fetchdat) } static int -opINSB_a16(uint32_t fetchdat) +opINSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -805,7 +805,7 @@ opINSB_a16(uint32_t fetchdat) return 0; } static int -opINSB_a32(uint32_t fetchdat) +opINSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -832,7 +832,7 @@ opINSB_a32(uint32_t fetchdat) } static int -opINSW_a16(uint32_t fetchdat) +opINSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -858,7 +858,7 @@ opINSW_a16(uint32_t fetchdat) return 0; } static int -opINSW_a32(uint32_t fetchdat) +opINSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -885,7 +885,7 @@ opINSW_a32(uint32_t fetchdat) } static int -opINSL_a16(uint32_t fetchdat) +opINSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -911,7 +911,7 @@ opINSL_a16(uint32_t fetchdat) return 0; } static int -opINSL_a32(uint32_t fetchdat) +opINSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -938,7 +938,7 @@ opINSL_a32(uint32_t fetchdat) } static int -opOUTSB_a16(uint32_t fetchdat) +opOUTSB_a16(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -958,7 +958,7 @@ opOUTSB_a16(uint32_t fetchdat) return 0; } static int -opOUTSB_a32(uint32_t fetchdat) +opOUTSB_a32(UNUSED(uint32_t fetchdat)) { uint8_t temp; @@ -979,7 +979,7 @@ opOUTSB_a32(uint32_t fetchdat) } static int -opOUTSW_a16(uint32_t fetchdat) +opOUTSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -999,7 +999,7 @@ opOUTSW_a16(uint32_t fetchdat) return 0; } static int -opOUTSW_a32(uint32_t fetchdat) +opOUTSW_a32(UNUSED(uint32_t fetchdat)) { uint16_t temp; @@ -1020,7 +1020,7 @@ opOUTSW_a32(uint32_t fetchdat) } static int -opOUTSL_a16(uint32_t fetchdat) +opOUTSL_a16(UNUSED(uint32_t fetchdat)) { uint32_t temp; @@ -1040,7 +1040,7 @@ opOUTSL_a16(uint32_t fetchdat) return 0; } static int -opOUTSL_a32(uint32_t fetchdat) +opOUTSL_a32(UNUSED(uint32_t fetchdat)) { uint32_t temp; diff --git a/src/cpu/x86_ops_xchg.h b/src/cpu/x86_ops_xchg.h index 70e7be58c..826181a8e 100644 --- a/src/cpu/x86_ops_xchg.h +++ b/src/cpu/x86_ops_xchg.h @@ -116,7 +116,7 @@ opXCHG_l_a32(uint32_t fetchdat) } static int -opXCHG_AX_BX(uint32_t fetchdat) +opXCHG_AX_BX(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = BX; @@ -126,7 +126,7 @@ opXCHG_AX_BX(uint32_t fetchdat) return 0; } static int -opXCHG_AX_CX(uint32_t fetchdat) +opXCHG_AX_CX(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = CX; @@ -136,7 +136,7 @@ opXCHG_AX_CX(uint32_t fetchdat) return 0; } static int -opXCHG_AX_DX(uint32_t fetchdat) +opXCHG_AX_DX(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = DX; @@ -146,7 +146,7 @@ opXCHG_AX_DX(uint32_t fetchdat) return 0; } static int -opXCHG_AX_SI(uint32_t fetchdat) +opXCHG_AX_SI(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = SI; @@ -156,7 +156,7 @@ opXCHG_AX_SI(uint32_t fetchdat) return 0; } static int -opXCHG_AX_DI(uint32_t fetchdat) +opXCHG_AX_DI(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = DI; @@ -166,7 +166,7 @@ opXCHG_AX_DI(uint32_t fetchdat) return 0; } static int -opXCHG_AX_BP(uint32_t fetchdat) +opXCHG_AX_BP(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = BP; @@ -176,7 +176,7 @@ opXCHG_AX_BP(uint32_t fetchdat) return 0; } static int -opXCHG_AX_SP(uint32_t fetchdat) +opXCHG_AX_SP(UNUSED(uint32_t fetchdat)) { uint16_t temp = AX; AX = SP; @@ -187,7 +187,7 @@ opXCHG_AX_SP(uint32_t fetchdat) } static int -opXCHG_EAX_EBX(uint32_t fetchdat) +opXCHG_EAX_EBX(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = EBX; @@ -197,7 +197,7 @@ opXCHG_EAX_EBX(uint32_t fetchdat) return 0; } static int -opXCHG_EAX_ECX(uint32_t fetchdat) +opXCHG_EAX_ECX(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = ECX; @@ -207,7 +207,7 @@ opXCHG_EAX_ECX(uint32_t fetchdat) return 0; } static int -opXCHG_EAX_EDX(uint32_t fetchdat) +opXCHG_EAX_EDX(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = EDX; @@ -217,7 +217,7 @@ opXCHG_EAX_EDX(uint32_t fetchdat) return 0; } static int -opXCHG_EAX_ESI(uint32_t fetchdat) +opXCHG_EAX_ESI(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = ESI; @@ -227,7 +227,7 @@ opXCHG_EAX_ESI(uint32_t fetchdat) return 0; } static int -opXCHG_EAX_EDI(uint32_t fetchdat) +opXCHG_EAX_EDI(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = EDI; @@ -237,7 +237,7 @@ opXCHG_EAX_EDI(uint32_t fetchdat) return 0; } static int -opXCHG_EAX_EBP(uint32_t fetchdat) +opXCHG_EAX_EBP(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = EBP; @@ -247,7 +247,7 @@ opXCHG_EAX_EBP(uint32_t fetchdat) return 0; } static int -opXCHG_EAX_ESP(uint32_t fetchdat) +opXCHG_EAX_ESP(UNUSED(uint32_t fetchdat)) { uint32_t temp = EAX; EAX = ESP; @@ -258,7 +258,7 @@ opXCHG_EAX_ESP(uint32_t fetchdat) } #define opBSWAP(reg) \ - static int opBSWAP_##reg(uint32_t fetchdat) \ + static int opBSWAP_##reg(UNUSED(uint32_t fetchdat)) \ { \ reg = (reg >> 24) | ((reg >> 8) & 0xff00) | ((reg << 8) & 0xff0000) | ((reg << 24) & 0xff000000); \ CLOCK_CYCLES(1); \ @@ -275,4 +275,4 @@ opBSWAP(ESI) opBSWAP(EDI) opBSWAP(EBP) opBSWAP(ESP) - // clang-format on +// clang-format on diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 3b06cab3c..fecca0772 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -20,6 +20,7 @@ #include "softfloat3e/config.h" #include "softfloat3e/fpu_trans.h" #include "softfloat3e/specialize.h" +#include <86box/plat_unused.h> uint32_t x87_pc_off; uint32_t x87_op_off; @@ -312,7 +313,7 @@ FPU_write_eflags_fpu_compare(int float_relation) } uint16_t -FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) +FPU_exception(UNUSED(uint32_t fetchdat), uint16_t exceptions, int store) { uint16_t status; uint16_t unmasked; diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index d33122b5c..f1362bf76 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -542,7 +542,7 @@ op_nofpu_a32(uint32_t fetchdat) #ifdef FPU_8087 static int -FPU_ILLEGAL_a16(uint32_t fetchdat) +FPU_ILLEGAL_a16(UNUSED(uint32_t fetchdat)) { geteaw(); wait(timing_rr, 0); diff --git a/src/cpu/x87_ops_arith.h b/src/cpu/x87_ops_arith.h index 31c26231b..8d0c02167 100644 --- a/src/cpu/x87_ops_arith.h +++ b/src/cpu/x87_ops_arith.h @@ -1,5 +1,5 @@ #define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \ - static int opFADD##name##_a##a_size(uint32_t fetchdat) \ + static int opFADD##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -18,7 +18,7 @@ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFCOM##name##_a##a_size(uint32_t fetchdat) \ + static int opFCOM##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -27,13 +27,13 @@ load_var = get(); \ if (cpu_state.abrt) \ return 1; \ - cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFCOMP##name##_a##a_size(uint32_t fetchdat) \ + static int opFCOMP##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -42,14 +42,14 @@ load_var = get(); \ if (cpu_state.abrt) \ return 1; \ - cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ x87_pop(); \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFDIV##name##_a##a_size(uint32_t fetchdat) \ + static int opFDIV##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -64,7 +64,7 @@ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFDIVR##name##_a##a_size(uint32_t fetchdat) \ + static int opFDIVR##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -79,7 +79,7 @@ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv##cycle_postfix) : ((x87_concurrency.fdiv##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFMUL##name##_a##a_size(uint32_t fetchdat) \ + static int opFMUL##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -94,7 +94,7 @@ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul##cycle_postfix) : ((x87_concurrency.fmul##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFSUB##name##_a##a_size(uint32_t fetchdat) \ + static int opFSUB##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -109,7 +109,7 @@ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ return 0; \ } \ - static int opFSUBR##name##_a##a_size(uint32_t fetchdat) \ + static int opFSUBR##name##_a##a_size(UNUSED(uint32_t fetchdat)) \ { \ optype t; \ FP_ENTER(); \ @@ -208,7 +208,7 @@ opFCOMP(uint32_t fetchdat) } static int -opFCOMPP(uint32_t fetchdat) +opFCOMPP(UNUSED(uint32_t fetchdat)) { uint64_t *p, *q; FP_ENTER(); @@ -229,7 +229,7 @@ opFCOMPP(uint32_t fetchdat) } #ifndef FPU_8087 static int -opFUCOMPP(uint32_t fetchdat) +opFUCOMPP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index 0936f325b..d0b31ac85 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -17,7 +17,7 @@ * Copyright 2016-2019 Miran Grca. */ static int -opFILDiw_a16(uint32_t fetchdat) +opFILDiw_a16(UNUSED(uint32_t fetchdat)) { int16_t temp; FP_ENTER(); @@ -50,7 +50,7 @@ opFILDiw_a32(uint32_t fetchdat) #endif static int -opFISTiw_a16(uint32_t fetchdat) +opFISTiw_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -75,7 +75,7 @@ opFISTiw_a32(uint32_t fetchdat) #endif static int -opFISTPiw_a16(uint32_t fetchdat) +opFISTPiw_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -106,7 +106,7 @@ opFISTPiw_a32(uint32_t fetchdat) #endif static int -opFILDiq_a16(uint32_t fetchdat) +opFILDiq_a16(UNUSED(uint32_t fetchdat)) { int64_t temp64; FP_ENTER(); @@ -145,7 +145,7 @@ opFILDiq_a32(uint32_t fetchdat) #endif static int -FBLD_a16(uint32_t fetchdat) +FBLD_a16(UNUSED(uint32_t fetchdat)) { uint16_t load_reg_hi = 0xffff; uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); @@ -228,7 +228,7 @@ FBLD_a32(uint32_t fetchdat) #endif static int -FBSTP_a16(uint32_t fetchdat) +FBSTP_a16(UNUSED(uint32_t fetchdat)) { double dt; double tempd; @@ -296,7 +296,7 @@ FBSTP_a32(uint32_t fetchdat) #endif static int -FISTPiq_a16(uint32_t fetchdat) +FISTPiq_a16(UNUSED(uint32_t fetchdat)) { int64_t temp64; FP_ENTER(); @@ -337,7 +337,7 @@ FISTPiq_a32(uint32_t fetchdat) #endif static int -opFILDil_a16(uint32_t fetchdat) +opFILDil_a16(UNUSED(uint32_t fetchdat)) { int32_t templ; FP_ENTER(); @@ -370,7 +370,7 @@ opFILDil_a32(uint32_t fetchdat) #endif static int -opFISTil_a16(uint32_t fetchdat) +opFISTil_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -395,7 +395,7 @@ opFISTil_a32(uint32_t fetchdat) #endif static int -opFISTPil_a16(uint32_t fetchdat) +opFISTPil_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -426,7 +426,7 @@ opFISTPil_a32(uint32_t fetchdat) #endif static int -opFLDe_a16(uint32_t fetchdat) +opFLDe_a16(UNUSED(uint32_t fetchdat)) { double t; FP_ENTER(); @@ -459,7 +459,7 @@ opFLDe_a32(uint32_t fetchdat) #endif static int -opFSTPe_a16(uint32_t fetchdat) +opFSTPe_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -490,7 +490,7 @@ opFSTPe_a32(uint32_t fetchdat) #endif static int -opFLDd_a16(uint32_t fetchdat) +opFLDd_a16(UNUSED(uint32_t fetchdat)) { x87_td t; FP_ENTER(); @@ -523,7 +523,7 @@ opFLDd_a32(uint32_t fetchdat) #endif static int -opFSTd_a16(uint32_t fetchdat) +opFSTd_a16(UNUSED(uint32_t fetchdat)) { x87_td t; FP_ENTER(); @@ -552,7 +552,7 @@ opFSTd_a32(uint32_t fetchdat) #endif static int -opFSTPd_a16(uint32_t fetchdat) +opFSTPd_a16(UNUSED(uint32_t fetchdat)) { x87_td t; FP_ENTER(); @@ -587,7 +587,7 @@ opFSTPd_a32(uint32_t fetchdat) #endif static int -opFLDs_a16(uint32_t fetchdat) +opFLDs_a16(UNUSED(uint32_t fetchdat)) { x87_ts ts; FP_ENTER(); @@ -620,7 +620,7 @@ opFLDs_a32(uint32_t fetchdat) #endif static int -opFSTs_a16(uint32_t fetchdat) +opFSTs_a16(UNUSED(uint32_t fetchdat)) { x87_ts ts; FP_ENTER(); @@ -649,7 +649,7 @@ opFSTs_a32(uint32_t fetchdat) #endif static int -opFSTPs_a16(uint32_t fetchdat) +opFSTPs_a16(UNUSED(uint32_t fetchdat)) { x87_ts ts; FP_ENTER(); diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index 96750468a..c1f09fda9 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -12,7 +12,7 @@ opFI(uint32_t fetchdat) } #else static int -opFSTSW_AX(uint32_t fetchdat) +opFSTSW_AX(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -24,7 +24,7 @@ opFSTSW_AX(uint32_t fetchdat) #endif static int -opFNOP(uint32_t fetchdat) +opFNOP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -34,7 +34,7 @@ opFNOP(uint32_t fetchdat) } static int -opFXTRACT(uint32_t fetchdat) +opFXTRACT(UNUSED(uint32_t fetchdat)) { x87_conv_t test; int64_t exp80; @@ -56,7 +56,7 @@ opFXTRACT(uint32_t fetchdat) } static int -opFCLEX(uint32_t fetchdat) +opFCLEX(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -67,7 +67,7 @@ opFCLEX(uint32_t fetchdat) } static int -opFINIT(uint32_t fetchdat) +opFINIT(UNUSED(uint32_t fetchdat)) { uint64_t *p; FP_ENTER(); @@ -208,7 +208,7 @@ FSTOR(void) return cpu_state.abrt; } static int -opFSTOR_a16(uint32_t fetchdat) +opFSTOR_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -429,7 +429,7 @@ FSAVE(void) return cpu_state.abrt; } static int -opFSAVE_a16(uint32_t fetchdat) +opFSAVE_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -450,7 +450,7 @@ opFSAVE_a32(uint32_t fetchdat) #endif static int -opFSTSW_a16(uint32_t fetchdat) +opFSTSW_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -516,7 +516,7 @@ opFXCH(uint32_t fetchdat) } static int -opFCHS(uint32_t fetchdat) +opFCHS(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -528,7 +528,7 @@ opFCHS(uint32_t fetchdat) } static int -opFABS(uint32_t fetchdat) +opFABS(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -540,7 +540,7 @@ opFABS(uint32_t fetchdat) } static int -opFTST(uint32_t fetchdat) +opFTST(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -555,7 +555,7 @@ opFTST(uint32_t fetchdat) } static int -opFXAM(uint32_t fetchdat) +opFXAM(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -579,7 +579,7 @@ opFXAM(uint32_t fetchdat) } static int -opFLD1(uint32_t fetchdat) +opFLD1(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -590,7 +590,7 @@ opFLD1(uint32_t fetchdat) } static int -opFLDL2T(uint32_t fetchdat) +opFLDL2T(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -601,7 +601,7 @@ opFLDL2T(uint32_t fetchdat) } static int -opFLDL2E(uint32_t fetchdat) +opFLDL2E(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -612,7 +612,7 @@ opFLDL2E(uint32_t fetchdat) } static int -opFLDPI(uint32_t fetchdat) +opFLDPI(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -623,7 +623,7 @@ opFLDPI(uint32_t fetchdat) } static int -opFLDEG2(uint32_t fetchdat) +opFLDEG2(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -634,7 +634,7 @@ opFLDEG2(uint32_t fetchdat) } static int -opFLDLN2(uint32_t fetchdat) +opFLDLN2(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -645,7 +645,7 @@ opFLDLN2(uint32_t fetchdat) } static int -opFLDZ(uint32_t fetchdat) +opFLDZ(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -657,7 +657,7 @@ opFLDZ(uint32_t fetchdat) } static int -opF2XM1(uint32_t fetchdat) +opF2XM1(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -669,7 +669,7 @@ opF2XM1(uint32_t fetchdat) } static int -opFYL2X(uint32_t fetchdat) +opFYL2X(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -682,7 +682,7 @@ opFYL2X(uint32_t fetchdat) } static int -opFYL2XP1(uint32_t fetchdat) +opFYL2XP1(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -695,7 +695,7 @@ opFYL2XP1(uint32_t fetchdat) } static int -opFPTAN(uint32_t fetchdat) +opFPTAN(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -709,7 +709,7 @@ opFPTAN(uint32_t fetchdat) } static int -opFPATAN(uint32_t fetchdat) +opFPATAN(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -722,7 +722,7 @@ opFPATAN(uint32_t fetchdat) } static int -opFDECSTP(uint32_t fetchdat) +opFDECSTP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -737,7 +737,7 @@ opFDECSTP(uint32_t fetchdat) } static int -opFINCSTP(uint32_t fetchdat) +opFINCSTP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -752,7 +752,7 @@ opFINCSTP(uint32_t fetchdat) } static int -opFPREM(uint32_t fetchdat) +opFPREM(UNUSED(uint32_t fetchdat)) { int64_t temp64; FP_ENTER(); @@ -773,7 +773,7 @@ opFPREM(uint32_t fetchdat) } static int -opFPREM1(uint32_t fetchdat) +opFPREM1(UNUSED(uint32_t fetchdat)) { int64_t temp64; FP_ENTER(); @@ -794,7 +794,7 @@ opFPREM1(uint32_t fetchdat) } static int -opFSQRT(uint32_t fetchdat) +opFSQRT(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -807,7 +807,7 @@ opFSQRT(uint32_t fetchdat) #ifndef FPU_8087 static int -opFSINCOS(uint32_t fetchdat) +opFSINCOS(UNUSED(uint32_t fetchdat)) { double td; FP_ENTER(); @@ -824,7 +824,7 @@ opFSINCOS(uint32_t fetchdat) #endif static int -opFRNDINT(uint32_t fetchdat) +opFRNDINT(UNUSED(uint32_t fetchdat)) { double dst0; @@ -839,7 +839,7 @@ opFRNDINT(uint32_t fetchdat) } static int -opFSCALE(uint32_t fetchdat) +opFSCALE(UNUSED(uint32_t fetchdat)) { int64_t temp64; FP_ENTER(); @@ -855,7 +855,7 @@ opFSCALE(uint32_t fetchdat) #ifndef FPU_8087 static int -opFSIN(uint32_t fetchdat) +opFSIN(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -868,7 +868,7 @@ opFSIN(uint32_t fetchdat) } static int -opFCOS(uint32_t fetchdat) +opFCOS(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -909,7 +909,7 @@ FLDENV(void) } static int -opFLDENV_a16(uint32_t fetchdat) +opFLDENV_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -930,7 +930,7 @@ opFLDENV_a32(uint32_t fetchdat) #endif static int -opFLDCW_a16(uint32_t fetchdat) +opFLDCW_a16(UNUSED(uint32_t fetchdat)) { uint16_t tempw; FP_ENTER(); @@ -1011,7 +1011,7 @@ FSTENV(void) } static int -opFSTENV_a16(uint32_t fetchdat) +opFSTENV_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -1032,7 +1032,7 @@ opFSTENV_a32(uint32_t fetchdat) #endif static int -opFSTCW_a16(uint32_t fetchdat) +opFSTCW_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); diff --git a/src/cpu/x87_ops_sf.h b/src/cpu/x87_ops_sf.h index 31416447e..0d4fee81a 100644 --- a/src/cpu/x87_ops_sf.h +++ b/src/cpu/x87_ops_sf.h @@ -235,7 +235,7 @@ fpu_load_environment(void) } static int -sf_FLDCW_a16(uint32_t fetchdat) +sf_FLDCW_a16(UNUSED(uint32_t fetchdat)) { uint16_t tempw; @@ -288,7 +288,7 @@ sf_FLDCW_a32(uint32_t fetchdat) #endif static int -sf_FNSTCW_a16(uint32_t fetchdat) +sf_FNSTCW_a16(UNUSED(uint32_t fetchdat)) { uint16_t cwd = i387_get_control_word(); @@ -317,7 +317,7 @@ sf_FNSTCW_a32(uint32_t fetchdat) #endif static int -sf_FNSTSW_a16(uint32_t fetchdat) +sf_FNSTSW_a16(UNUSED(uint32_t fetchdat)) { uint16_t swd = i387_get_status_word(); @@ -359,7 +359,7 @@ sf_FI(uint32_t fetchdat) } #else static int -sf_FNSTSW_AX(uint32_t fetchdat) +sf_FNSTSW_AX(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -371,7 +371,7 @@ sf_FNSTSW_AX(uint32_t fetchdat) #endif static int -sf_FRSTOR_a16(uint32_t fetchdat) +sf_FRSTOR_a16(UNUSED(uint32_t fetchdat)) { floatx80 tmp; int offset; @@ -414,7 +414,7 @@ sf_FRSTOR_a32(uint32_t fetchdat) #endif static int -sf_FNSAVE_a16(uint32_t fetchdat) +sf_FNSAVE_a16(UNUSED(uint32_t fetchdat)) { floatx80 stn; int offset; @@ -488,7 +488,7 @@ sf_FNSAVE_a32(uint32_t fetchdat) #endif static int -sf_FNCLEX(uint32_t fetchdat) +sf_FNCLEX(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -499,7 +499,7 @@ sf_FNCLEX(uint32_t fetchdat) } static int -sf_FNINIT(uint32_t fetchdat) +sf_FNINIT(UNUSED(uint32_t fetchdat)) { FP_ENTER(); cpu_state.pc++; @@ -525,7 +525,7 @@ sf_FNINIT(uint32_t fetchdat) } static int -sf_FLDENV_a16(uint32_t fetchdat) +sf_FLDENV_a16(UNUSED(uint32_t fetchdat)) { int tag; @@ -572,7 +572,7 @@ sf_FLDENV_a32(uint32_t fetchdat) #endif static int -sf_FNSTENV_a16(uint32_t fetchdat) +sf_FNSTENV_a16(UNUSED(uint32_t fetchdat)) { FP_ENTER(); fetch_ea_16(fetchdat); @@ -605,7 +605,7 @@ sf_FNSTENV_a32(uint32_t fetchdat) #endif static int -sf_FNOP(uint32_t fetchdat) +sf_FNOP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); FPU_check_pending_exceptions(); diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index edbd64dcf..c9e25e97c 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -1,7 +1,7 @@ #define sf_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ static int sf_FADD##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ + floatx80 a, result; \ struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ @@ -31,7 +31,7 @@ next_ins: } \ static int sf_FDIV##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ + floatx80 a, result; \ struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ @@ -61,7 +61,7 @@ next_ins: } \ static int sf_FDIVR##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ + floatx80 a, result; \ struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ @@ -91,7 +91,7 @@ next_ins: } \ static int sf_FMUL##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ + floatx80 a, result; \ struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ @@ -121,7 +121,7 @@ next_ins: } \ static int sf_FSUB##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ + floatx80 a, result; \ struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ @@ -151,7 +151,7 @@ next_ins: } \ static int sf_FSUBR##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ + floatx80 a, result; \ struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index c4a38b375..945ed99d3 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -460,7 +460,7 @@ sf_FTST(uint32_t fetchdat) } static int -sf_FXAM(uint32_t fetchdat) +sf_FXAM(UNUSED(uint32_t fetchdat)) { floatx80 reg; int sign; diff --git a/src/cpu/x87_ops_sf_misc.h b/src/cpu/x87_ops_sf_misc.h index 0aab2ec08..746e85c6f 100644 --- a/src/cpu/x87_ops_sf_misc.h +++ b/src/cpu/x87_ops_sf_misc.h @@ -81,7 +81,7 @@ sf_FABS(uint32_t fetchdat) } static int -sf_FDECSTP(uint32_t fetchdat) +sf_FDECSTP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); FPU_check_pending_exceptions(); @@ -94,7 +94,7 @@ sf_FDECSTP(uint32_t fetchdat) } static int -sf_FINCSTP(uint32_t fetchdat) +sf_FINCSTP(UNUSED(uint32_t fetchdat)) { FP_ENTER(); FPU_check_pending_exceptions(); diff --git a/src/device/mouse_microtouch_touchscreen.c b/src/device/mouse_microtouch_touchscreen.c index 80e89df1f..24d5de1fb 100644 --- a/src/device/mouse_microtouch_touchscreen.c +++ b/src/device/mouse_microtouch_touchscreen.c @@ -313,7 +313,7 @@ mtouch_process_commands(mouse_microtouch_t *dev) } static void -mtouch_write(serial_t *serial, void *priv, uint8_t data) +mtouch_write(UNUSED(serial_t *serial), void *priv, uint8_t data) { mouse_microtouch_t *dev = (mouse_microtouch_t *) priv; @@ -495,7 +495,7 @@ mtouch_poll_global(void) } void * -mtouch_init(const device_t *info) +mtouch_init(UNUSED(const device_t *info)) { mouse_microtouch_t *dev = calloc(1, sizeof(mouse_microtouch_t)); diff --git a/src/device/nec_mate_unk.c b/src/device/nec_mate_unk.c index 3244733c9..c0393eaa2 100644 --- a/src/device/nec_mate_unk.c +++ b/src/device/nec_mate_unk.c @@ -30,7 +30,7 @@ #include <86box/plat_unused.h> static uint8_t -nec_mate_unk_read(UNUSED(uint16_t addr), void *priv) +nec_mate_unk_read(UNUSED(uint16_t addr), UNUSED(void *priv)) { /* Expected by this NEC machine. @@ -49,7 +49,7 @@ nec_mate_unk_close(void *priv) } static void * -nec_mate_unk_init(const device_t *info) +nec_mate_unk_init(UNUSED(const device_t *info)) { /* We have to return something non-NULL. */ uint8_t *dev = (uint8_t *) calloc(1, sizeof(uint8_t)); diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index 737b4104d..34b6390d1 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -61,7 +61,7 @@ novell_cardkey_read(uint16_t port, void *priv) return val ^ 0xFF; } -void* novell_cardkey_init(const device_t* info) +void* novell_cardkey_init(UNUSED(const device_t* info)) { char sernumstr[13] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 0 }; int i = 0; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 49d23daee..592649c0e 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -386,7 +386,7 @@ ide_atapi_get_period(uint8_t channel) } static void -ide_irq_update(ide_board_t *dev, int log) +ide_irq_update(ide_board_t *dev, UNUSED(int log)) { ide_t *ide; uint8_t set; @@ -1894,7 +1894,7 @@ ide_read_data(ide_t *ide) } static uint8_t -ide_status(ide_t *ide, ide_t *ide_other, int ch) +ide_status(ide_t *ide, UNUSED(ide_t *ide_other), UNUSED(int ch)) { uint8_t ret; @@ -3207,7 +3207,7 @@ mcide_mca_reset(void *priv) } static void -mcide_reset(void *priv) +mcide_reset(UNUSED(void *priv)) { for (uint8_t i = 0; i < 2; i++) { if (ide_boards[i] != NULL) diff --git a/src/disk/lba_enhancer.c b/src/disk/lba_enhancer.c index c7f3fd969..8e8bc480d 100644 --- a/src/disk/lba_enhancer.c +++ b/src/disk/lba_enhancer.c @@ -44,7 +44,7 @@ lba_enhancer_close(void* priv) } void * -lba_enhancer_init(const device_t *info) +lba_enhancer_init(UNUSED(const device_t *info)) { lba_enhancer_t *dev = (lba_enhancer_t *) calloc(1, sizeof(lba_enhancer_t)); diff --git a/src/disk/mo.c b/src/disk/mo.c index 7528806c7..5494fc9a8 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1975,7 +1975,7 @@ mo_global_init(void) } static int -mo_get_max(const ide_t *ide, const int ide_has_dma, const int type) +mo_get_max(UNUSED(const ide_t *ide), const int ide_has_dma, const int type) { int ret; @@ -1999,7 +1999,7 @@ mo_get_max(const ide_t *ide, const int ide_has_dma, const int type) } static int -mo_get_timings(const ide_t *ide, const int ide_has_dma, const int type) +mo_get_timings(UNUSED(const ide_t *ide), const int ide_has_dma, const int type) { int ret; diff --git a/src/disk/zip.c b/src/disk/zip.c index fd261b4dd..72781281a 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -2062,7 +2062,7 @@ zip_global_init(void) } static int -zip_get_max(const ide_t *ide, const int ide_has_dma, const int type) +zip_get_max(UNUSED(const ide_t *ide), const int ide_has_dma, const int type) { int ret; @@ -2086,7 +2086,7 @@ zip_get_max(const ide_t *ide, const int ide_has_dma, const int type) } static int -zip_get_timings(const ide_t *ide, const int ide_has_dma, const int type) +zip_get_timings(UNUSED(const ide_t *ide), const int ide_has_dma, const int type) { int ret; diff --git a/src/floppy/fdc_compaticard.c b/src/floppy/fdc_compaticard.c index a693c9cb2..4abc4abac 100644 --- a/src/floppy/fdc_compaticard.c +++ b/src/floppy/fdc_compaticard.c @@ -30,6 +30,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> +#include <86box/plat_unused.h> #define DEVICE_COMPATICARD_I 0 #define DEVICE_COMPATICARD_II 1 @@ -57,7 +58,7 @@ typedef struct compaticard_s { } compaticard_t; static void -compaticard_out(uint16_t port, uint8_t val, void *priv) +compaticard_out(UNUSED(uint16_t port), uint8_t val, void *priv) { compaticard_t *dev = (compaticard_t *) priv; @@ -65,7 +66,7 @@ compaticard_out(uint16_t port, uint8_t val, void *priv) } static uint8_t -compaticard_in(uint16_t port, void *priv) +compaticard_in(UNUSED(uint16_t port), void *priv) { compaticard_t *dev = (compaticard_t *) priv; uint8_t ret = (dev->cr_2 &CR_2_MASK); diff --git a/src/floppy/fdd_pcjs.c b/src/floppy/fdd_pcjs.c index 41db65a1a..6f69042b0 100644 --- a/src/floppy/fdd_pcjs.c +++ b/src/floppy/fdd_pcjs.c @@ -469,7 +469,7 @@ track_flags(int drive) } static void -set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +set_sector(int drive, int side, uint8_t c, UNUSED(uint8_t h), uint8_t r, UNUSED(uint8_t n)) { pcjs_t *dev = images[drive]; diff --git a/src/game/gameport.c b/src/game/gameport.c index 579f5c235..39193af88 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -646,7 +646,7 @@ static const device_config_t tmacm_config[] = { { "" } } }, - { "", "", -1 } + { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; diff --git a/src/include/86box/bswap.h b/src/include/86box/bswap.h index f7d3a3d0e..37c846d59 100644 --- a/src/include/86box/bswap.h +++ b/src/include/86box/bswap.h @@ -133,12 +133,12 @@ bswap64s(uint64_t *s) return endian##_bswap(v, size); \ } \ \ - static __inline void endian##size##_to_cpus(type *p) \ + static __inline void endian##size##_to_cpus(UNUSED(type *p)) \ { \ endian##_bswaps(p, size) \ } \ \ - static __inline void cpu_to_##endian##size##s(type *p) \ + static __inline void cpu_to_##endian##size##s(UNUSED(type *p)) \ { \ endian##_bswaps(p, size) \ } \ diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index de20facdb..82d211896 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -104,8 +104,7 @@ enum { #define CDV EMU_VERSION_EX -static const struct -{ +static const struct cdrom_drive_types_s { const char vendor[9]; const char model[17]; const char revision[5]; @@ -204,19 +203,19 @@ static const struct Unusual 2.23x according to Google, I'm rounding it upwards to 3x. Assumed caddy based on the DM-3024. */ - { "TEXEL", "CD-ROM DM-3028", "1.06", "texel_3028", BUS_TYPE_SCSI, 2, 3, 36, 1 }, /* Caddy. */ + { "TEXEL", "CD-ROM DM-3028", "1.06", "texel_3028", BUS_TYPE_SCSI, 2, 3, 36, 1, { -1, -1, -1, -1 } }, /* Caddy. */ /* The characteristics are a complete guesswork because I can't find this one on Google. Also, INQUIRY length is always 96 on these Toshiba drives. */ - { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "toshiba_xm", BUS_TYPE_SCSI, 2, 2, 96, 0 }, /* Tray. */ - { "TOSHIBA", "CD-ROM XM-3201B", "3232", "toshiba_3201b", BUS_TYPE_SCSI, 1, 1, 96, 1 }, /* Caddy. */ - { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "toshiba_3301ta", BUS_TYPE_SCSI, 2, 2, 96, 0 }, /* Tray. */ - { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "toshiba_5701a", BUS_TYPE_SCSI, 2, 12, 96, 0 }, /* Tray. */ - { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "toshiba_m1401", BUS_TYPE_SCSI, 2, 40, 96, 0 }, /* Tray. */ - { "", "", "", "", BUS_TYPE_NONE, 0, -1, 0, 0 } + { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "toshiba_xm", BUS_TYPE_SCSI, 2, 2, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */ + { "TOSHIBA", "CD-ROM XM-3201B", "3232", "toshiba_3201b", BUS_TYPE_SCSI, 1, 1, 96, 1, { -1, -1, -1, -1 } }, /* Caddy. */ + { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "toshiba_3301ta", BUS_TYPE_SCSI, 2, 2, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */ + { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "toshiba_5701a", BUS_TYPE_SCSI, 2, 12, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */ + { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "toshiba_m1401", BUS_TYPE_SCSI, 2, 40, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */ + { "", "", "", "", BUS_TYPE_NONE, 0, -1, 0, 0, { -1, -1, -1, -1 } } }; /* To shut up the GCC compilers. */ diff --git a/src/machine/m_at_grid.c b/src/machine/m_at_grid.c index 443607382..03b7288b9 100644 --- a/src/machine/m_at_grid.c +++ b/src/machine/m_at_grid.c @@ -38,6 +38,7 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/vid_cga.h> +#include <86box/plat_unused.h> #define GRID_APPROM_SELECT 0x440 #define GRID_APPROM_ENABLE 0x405 @@ -263,7 +264,7 @@ static uint8_t grid_io_read(uint16_t port, void *priv) { } static void * -grid_init(const device_t *info) +grid_init(UNUSED(const device_t *info)) { grid_t *dev = calloc(1, sizeof(grid_t)); diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c index 33e9d59bd..73dd5ef62 100644 --- a/src/network/net_3c501.c +++ b/src/network/net_3c501.c @@ -56,7 +56,6 @@ #include <86box/thread.h> #include <86box/timer.h> #include <86box/network.h> -#include <86box/bswap.h> #include <86box/plat_unused.h> /* Maximum number of times we report a link down to the guest (failure to send frame) */ diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index 31156fa9a..cd5016147 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -60,7 +60,6 @@ #include <86box/timer.h> #include <86box/network.h> #include <86box/net_dp8390.h> -#include <86box/bswap.h> #include <86box/plat_unused.h> typedef struct threec503_t { diff --git a/src/network/net_modem.c b/src/network/net_modem.c index 732190254..83dfe04d7 100644 --- a/src/network/net_modem.c +++ b/src/network/net_modem.c @@ -1133,7 +1133,7 @@ modem_dtr_callback_timer(void *priv) } void -modem_dtr_callback(serial_t *serial, int status, void *priv) +modem_dtr_callback(UNUSED(serial_t *serial), int status, void *priv) { modem_t *dev = (modem_t *) priv; dev->dtrstate = !!status; @@ -1483,7 +1483,7 @@ modem_cmdpause_timer_callback(void *priv) /* Initialize the device for use by the user. */ static void * -modem_init(const device_t *info) +modem_init(UNUSED(const device_t *info)) { modem_t *modem = (modem_t *) calloc(1, sizeof(modem_t)); const char *phonebook_file = NULL; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index d3de47852..97c2b5de2 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -66,7 +66,6 @@ #include <86box/network.h> #include <86box/net_dp8390.h> #include <86box/net_ne2000.h> -#include <86box/bswap.h> #include <86box/isapnp.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index fea20e3c9..5487486b4 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -46,9 +46,9 @@ #include <86box/thread.h> #include <86box/network.h> #include <86box/net_pcnet.h> -#include <86box/bswap.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#include <86box/bswap.h> /* PCI info. */ #define PCI_VENDID 0x1022 /* AMD */ diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index b9b7fc957..74b041b35 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -44,10 +44,10 @@ #include <86box/thread.h> #include <86box/network.h> #include <86box/net_eeprom_nmc93cxx.h> -#include <86box/bswap.h> #include <86box/nvr.h> #include "cpu.h" #include <86box/plat_unused.h> +#include <86box/bswap.h> #define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ @@ -1210,7 +1210,7 @@ rtl8139_CpCmd_read(RTL8139State *s) } static void -rtl8139_IntrMitigate_write(UNUSED(RTL8139State *s), uint32_t val) +rtl8139_IntrMitigate_write(UNUSED(RTL8139State *s), UNUSED(uint32_t val)) { rtl8139_log("C+ IntrMitigate register write(w) val=0x%04x\n", val); } @@ -3151,7 +3151,7 @@ rtl8139_pci_read(UNUSED(int func), int addr, void *priv) } static void -rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) +rtl8139_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { RTL8139State *s = (RTL8139State *) priv; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index af30c5505..2c3aab379 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -32,9 +32,9 @@ #include <86box/thread.h> #include <86box/network.h> #include <86box/net_eeprom_nmc93cxx.h> -#include <86box/bswap.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#include <86box/bswap.h> #define ROM_PATH_DEC21140 "roms/network/dec21140/BIOS13502.BIN" diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 3d50c8f67..1e5496851 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -63,7 +63,6 @@ #include <86box/network.h> #include <86box/net_dp8390.h> #include <86box/net_wd8003.h> -#include <86box/bswap.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> diff --git a/src/pic.c b/src/pic.c index fa7ff3662..7f6eda40d 100644 --- a/src/pic.c +++ b/src/pic.c @@ -245,7 +245,7 @@ pic_update_pending_at(void) } static void -pic_callback(void *priv) +pic_callback(UNUSED(void *priv)) { update_pending(); } diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index ae4eb1727..9efd67ad6 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -97,7 +97,7 @@ ioctl_get_raw_track_info(UNUSED(const void *local), int *num, uint8_t *rti) } static int -ioctl_is_track_pre(const void *local, const uint32_t sector) +ioctl_is_track_pre(const void *local, UNUSED(const uint32_t sector)) { ioctl_t *ioctl = (ioctl_t *) local; @@ -111,7 +111,7 @@ ioctl_is_track_pre(const void *local, const uint32_t sector) } static int -ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) +ioctl_read_sector(const void *local, UNUSED(uint8_t *buffer), UNUSED(uint32_t const sector)) { ioctl_t *ioctl = (ioctl_t *) local; diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index f77370574..1c917f517 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -42,15 +42,6 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) # endif #endif -#ifdef Q_OS_WINDOWS -# include "qt_rendererstack.hpp" -# include "qt_winrawinputfilter.hpp" -# include "qt_winmanagerfilter.hpp" -# include <86box/win.h> -# include -# include -#endif - extern "C" { #include <86box/86box.h> #include <86box/config.h> @@ -64,6 +55,15 @@ extern "C" { #include <86box/version.h> } +#ifdef Q_OS_WINDOWS +# include "qt_rendererstack.hpp" +# include "qt_winrawinputfilter.hpp" +# include "qt_winmanagerfilter.hpp" +# include <86box/win.h> +# include +# include +#endif + #include #include #include diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index a0ef86533..dd6c34efc 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -156,6 +156,7 @@ strnicmp(const char *s1, const char *s2, size_t n) void do_start(void) { + // } void @@ -557,7 +558,7 @@ endblit() std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } -} +} /*extern "C" */ #ifdef Q_OS_WINDOWS size_t diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 33858ebbc..ff49aef90 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1524,7 +1524,7 @@ scsi_cdrom_set_speed(scsi_cdrom_t *dev, const uint8_t *cdb) } static uint8_t -scsi_cdrom_command_chinon(void *sc, const uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_chinon(void *sc, const uint8_t *cdb, UNUSED(int32_t *BufLen)) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; uint8_t cmd_stat = 0x00; @@ -1761,7 +1761,7 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) } static uint8_t -scsi_cdrom_command_matsushita(void *sc, const uint8_t *cdb, int32_t *BufLen) +scsi_cdrom_command_matsushita(void *sc, const uint8_t *cdb, UNUSED(int32_t *BufLen)) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; const uint8_t cmd_stat = 0x00; @@ -3581,7 +3581,7 @@ scsi_cdrom_close(void *priv) } static int -scsi_cdrom_get_max(const ide_t *ide, const int ide_has_dma, const int type) +scsi_cdrom_get_max(const ide_t *ide, UNUSED(const int ide_has_dma), const int type) { const scsi_cdrom_t *dev = (scsi_cdrom_t *) ide->sc; int ret; @@ -3600,7 +3600,7 @@ scsi_cdrom_get_max(const ide_t *ide, const int ide_has_dma, const int type) } static int -scsi_cdrom_get_timings(const ide_t *ide, const int ide_has_dma, const int type) +scsi_cdrom_get_timings(const ide_t *ide, UNUSED(const int ide_has_dma), const int type) { const scsi_cdrom_t *dev = (scsi_cdrom_t *) ide->sc; int has_dma = cdrom_has_dma(dev->drv->type); @@ -3628,7 +3628,7 @@ scsi_cdrom_get_timings(const ide_t *ide, const int ide_has_dma, const int type) * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command */ static void -scsi_cdrom_identify(const ide_t *ide, const int ide_has_dma) +scsi_cdrom_identify(const ide_t *ide, UNUSED(const int ide_has_dma)) { const scsi_cdrom_t *dev = (scsi_cdrom_t *) ide->sc; char model[2048] = { 0 }; diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index c11f09443..878259094 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -1642,7 +1642,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc) } static int -scsi_disk_get_max(const ide_t *ide, int ide_has_dma, const int type) +scsi_disk_get_max(UNUSED(const ide_t *ide), int ide_has_dma, const int type) { int ret; @@ -1668,7 +1668,7 @@ scsi_disk_get_max(const ide_t *ide, int ide_has_dma, const int type) } static int -scsi_disk_get_timings(const ide_t *ide, const int ide_has_dma, const int type) +scsi_disk_get_timings(UNUSED(const ide_t *ide), const int ide_has_dma, const int type) { int ret; diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index aee1b6a1d..1cde8657e 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -602,7 +602,7 @@ it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) } static void -it86x1f_write_addr(uint16_t port, uint8_t val, void *priv) +it86x1f_write_addr(UNUSED(uint16_t port), uint8_t val, void *priv) { it86x1f_t *dev = (it86x1f_t *) priv; @@ -623,7 +623,7 @@ it86x1f_write_addr(uint16_t port, uint8_t val, void *priv) } static void -it86x1f_write_data(uint16_t port, uint8_t val, void *priv) +it86x1f_write_data(UNUSED(uint16_t port), uint8_t val, void *priv) { it86x1f_t *dev = (it86x1f_t *) priv; @@ -659,7 +659,7 @@ it86x1f_write_data(uint16_t port, uint8_t val, void *priv) } static uint8_t -it86x1f_read_addr(uint16_t port, void *priv) +it86x1f_read_addr(UNUSED(uint16_t port), void *priv) { it86x1f_t *dev = (it86x1f_t *) priv; uint8_t ret = dev->locked ? 0xff : dev->cur_reg; @@ -670,7 +670,7 @@ it86x1f_read_addr(uint16_t port, void *priv) } static uint8_t -it86x1f_read_data(uint16_t port, void *priv) +it86x1f_read_data(UNUSED(uint16_t port), void *priv) { it86x1f_t *dev = (it86x1f_t *) priv; uint8_t ret = 0xff; diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index 5da43581f..33cb0d865 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -68,7 +68,7 @@ pc87306_gpio_write(uint16_t port, uint8_t val, void *priv) } uint8_t -pc87306_gpio_read(uint16_t port, void *priv) +pc87306_gpio_read(uint16_t port, UNUSED(void *priv)) { uint32_t ret = machine_handle_gpio(0, 0xffffffff); diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c index ecfc7ba09..ee18b1893 100644 --- a/src/sio/sio_vl82c113.c +++ b/src/sio/sio_vl82c113.c @@ -24,6 +24,7 @@ #include <86box/keyboard.h> #include <86box/nvr.h> #include <86box/sio.h> +#include <86box/plat_unused.h> typedef struct vl82c113_t { uint8_t index; @@ -128,7 +129,7 @@ vl82c113_close(void *priv) } static void * -vl82c113_init(const device_t *info) +vl82c113_init(UNUSED(const device_t *info)) { vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index e1f80b0f5..5ec15cc7c 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -557,7 +557,7 @@ program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) } static void -opl4_midi_thread(void *arg) +opl4_midi_thread(UNUSED(void *arg)) { opl4_midi_t *opl4_midi = opl4_midi_cur; uint32_t i = 0; @@ -648,12 +648,13 @@ opl4_midi_msg(uint8_t *val) } void -opl4_midi_sysex(uint8_t *data, unsigned int len) +opl4_midi_sysex(UNUSED(uint8_t *data), UNUSED(unsigned int len)) { + // } void * -opl4_init(const device_t *info) +opl4_init(UNUSED(const device_t *info)) { midi_device_t *dev; extern void al_set_midi(int freq, int buf_size); diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index 8eb5260c0..822abeeaa 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -328,7 +328,7 @@ emu8k_log(const char *fmt, ...) static inline int16_t EMU8K_READ(emu8k_t *emu8k, uint32_t addr) { - const register emu8k_mem_pointers_t addrmem = { { addr } }; + register const emu8k_mem_pointers_t addrmem = { { addr } }; return emu8k->ram_pointers[addrmem.hb_address][addrmem.lw_address]; } diff --git a/src/sound/snd_opl_esfm.c b/src/sound/snd_opl_esfm.c index 993a0ec6b..bcd2a56e9 100644 --- a/src/sound/snd_opl_esfm.c +++ b/src/sound/snd_opl_esfm.c @@ -34,6 +34,7 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/snd_opl.h> +#include <86box/plat_unused.h> #define RSM_FRAC 10 @@ -175,7 +176,7 @@ esfm_drv_set_do_cycles(void *priv, int8_t do_cycles) } static void * -esfm_drv_init(const device_t *info) +esfm_drv_init(UNUSED(const device_t *info)) { esfm_drv_t *dev = (esfm_drv_t *) calloc(1, sizeof(esfm_drv_t)); dev->flags = FLAG_CYCLES | FLAG_OPL3; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 400f176a8..05df32322 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -1671,7 +1671,7 @@ pas16_out(uint16_t port, uint8_t val, void *priv) - A 16-bit sample always takes two ctr_clock() ticks. */ static uint16_t -pas16_dma_channel_read(pas16_t *pas16, int channel) +pas16_dma_channel_read(pas16_t *pas16, UNUSED(int channel)) { int status; uint16_t ret; diff --git a/src/sound/snd_resid.cpp b/src/sound/snd_resid.cpp index b9895cf7e..b0503cac2 100644 --- a/src/sound/snd_resid.cpp +++ b/src/sound/snd_resid.cpp @@ -87,10 +87,10 @@ sid_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) #define CLOCK_DELTA(n) (int) (((14318180.0 * n) / 16.0) / (float) RESID_FREQ) static void -fillbuf2(int &count, int16_t *buf, int len) +fillbuf2(int &count, int16_t *buf, UNUSED(int len)) { - int c; - c = psid->sid->clock(count, buf); + int c = psid->sid->clock(count, buf); + if (!c) *buf = psid->last_sample; psid->last_sample = *buf; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 692a53aa3..ea961a6d3 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1417,7 +1417,7 @@ sb_ct1745_mixer_reset(sb_t *sb) } static void -ess_base_write(uint16_t addr, uint8_t val, void *priv) +ess_base_write(uint16_t addr, UNUSED(uint8_t val), void *priv) { sb_t *ess = (sb_t *) priv; @@ -1463,7 +1463,7 @@ ess_base_read(uint16_t addr, void *priv) } static void -ess_fm_midi_write(uint16_t addr, uint8_t val, void *priv) +ess_fm_midi_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), void *priv) { sb_t *ess = (sb_t *) priv; @@ -1471,7 +1471,7 @@ ess_fm_midi_write(uint16_t addr, uint8_t val, void *priv) } static uint8_t -ess_fm_midi_read(uint16_t addr, void *priv) +ess_fm_midi_read(UNUSED(uint16_t addr), void *priv) { sb_t *ess = (sb_t *) priv; diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index 762b243be..0e1bbd96c 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -94,13 +94,13 @@ ssi2001_close(void *priv) } static uint8_t -entertainer_read(uint16_t addr, void *priv) +entertainer_read(UNUSED(uint16_t addr), UNUSED(void *priv)) { return 0xa5; } static void -entertainer_write(uint16_t addr, uint8_t val, void *priv) +entertainer_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { entertainer_t *entertainer = (entertainer_t *) priv; entertainer->regs = val; @@ -163,15 +163,27 @@ static const device_config_t ssi2001_config[] = { { .description = "" } } }, - { "gameport", "Enable Game port", CONFIG_BINARY, "", 1 }, - { "", "", -1 } + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } // clang-format off }; static const device_config_t entertainer_config[] = { // clang-format off - { "gameport", "Enable Game port", CONFIG_BINARY, "", 1 }, - { "", "", -1 } + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } // clang-format off }; diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index ae4eb1727..9efd67ad6 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -97,7 +97,7 @@ ioctl_get_raw_track_info(UNUSED(const void *local), int *num, uint8_t *rti) } static int -ioctl_is_track_pre(const void *local, const uint32_t sector) +ioctl_is_track_pre(const void *local, UNUSED(const uint32_t sector)) { ioctl_t *ioctl = (ioctl_t *) local; @@ -111,7 +111,7 @@ ioctl_is_track_pre(const void *local, const uint32_t sector) } static int -ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) +ioctl_read_sector(const void *local, UNUSED(uint8_t *buffer), UNUSED(uint32_t const sector)) { ioctl_t *ioctl = (ioctl_t *) local; diff --git a/src/unix/unix.c b/src/unix/unix.c index 8e070d372..7f653b9b6 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -301,7 +301,7 @@ path_abs(char *path) } void -path_normalize(char *path) +path_normalize(UNUSED(char *path)) { /* No-op. */ } @@ -459,13 +459,13 @@ plat_remove(char *path) } void -ui_sb_update_icon_state(int tag, int state) +ui_sb_update_icon_state(UNUSED(int tag), UNUSED(int state)) { /* No-op. */ } void -ui_sb_update_icon(int tag, int active) +ui_sb_update_icon(UNUSED(int tag), UNUSED(int active)) { /* No-op. */ } @@ -477,7 +477,7 @@ plat_delay_ms(uint32_t count) } void -ui_sb_update_tip(int arg) +ui_sb_update_tip(UNUSED(int arg)) { /* No-op. */ } @@ -514,8 +514,9 @@ path_get_dirname(char *dest, const char *path) *dest = '\0'; } volatile int cpu_thread_run = 1; + void -ui_sb_set_text_w(wchar_t *wstr) +ui_sb_set_text_w(UNUSED(wchar_t *wstr)) { /* No-op. */ } @@ -533,7 +534,7 @@ strnicmp(const char *s1, const char *s2, size_t n) } void -main_thread(void *param) +main_thread(UNUSED(void *param)) { uint32_t old_time; uint32_t new_time; @@ -707,7 +708,7 @@ plat_power_off(void) } void -ui_sb_bugui(char *str) +ui_sb_bugui(UNUSED(char *str)) { /* No-op. */ } @@ -726,7 +727,7 @@ int real_sdl_w; int real_sdl_h; void -ui_sb_set_ready(int ready) +ui_sb_set_ready(UNUSED(int ready)) { /* No-op. */ } @@ -912,14 +913,14 @@ void (*f_rl_callback_handler_remove)(void) = NULL; #endif uint32_t -timer_onesec(uint32_t interval, void *param) +timer_onesec(uint32_t interval, UNUSED(void *param)) { pc_onesec(); return interval; } void -monitor_thread(void *param) +monitor_thread(UNUSED(void *param)) { #ifndef USE_CLI if (isatty(fileno(stdin)) && isatty(fileno(stdout))) { @@ -1369,14 +1370,14 @@ main(int argc, char **argv) return 0; } char * -plat_vidapi_name(int i) +plat_vidapi_name(UNUSED(int i)) { return "default"; } /* Sets up the program language before initialization. */ uint32_t -plat_language_code(char *langcode) +plat_language_code(UNUSED(char *langcode)) { /* or maybe not */ return 0; @@ -1413,7 +1414,7 @@ plat_set_thread_name(void *thread, const char *name) /* Converts back the language code to LCID */ void -plat_language_code_r(uint32_t lcid, char *outbuf, int len) +plat_language_code_r(UNUSED(uint32_t lcid), UNUSED(char *outbuf), UNUSED(int len)) { /* or maybe not */ return; @@ -1451,7 +1452,7 @@ endblit(void) /* API */ void -ui_sb_mt32lcd(char *str) +ui_sb_mt32lcd(UNUSED(char *str)) { /* No-op. */ } diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 5223b08ba..b1096b0b4 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -70,7 +70,7 @@ cassette_eject(void) } void -cartridge_mount(uint8_t id, char *fn, uint8_t wp) +cartridge_mount(uint8_t id, char *fn, UNUSED(uint8_t wp)) { cart_close(id); cart_load(id, fn); @@ -121,7 +121,7 @@ floppy_eject(uint8_t id) } void -plat_cdrom_ui_update(uint8_t id, uint8_t reload) +plat_cdrom_ui_update(uint8_t id, UNUSED(uint8_t reload)) { cdrom_t *drv = &cdrom[id]; diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index 002e33fd6..651822335 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -533,19 +533,19 @@ ui_window_title(wchar_t *str) } void -ui_init_monitor(int monitor_index) +ui_init_monitor(UNUSED(int monitor_index)) { /* No-op. */ } void -ui_deinit_monitor(int monitor_index) +ui_deinit_monitor(UNUSED(int monitor_index)) { /* No-op. */ } void -plat_resize_request(int w, int h, int monitor_index) +plat_resize_request(UNUSED(int w), UNUSED(int h), int monitor_index) { atomic_store((&doresize_monitors[monitor_index]), 1); } diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 0ef4df6df..a923ea7e2 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -291,7 +291,7 @@ mach_pixel_read(mach_t *mach) } static void -mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, mach_t *mach, ibm8514_t *dev) +mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint32_t cpu_dat, UNUSED(svga_t *svga), mach_t *mach, ibm8514_t *dev) { int compare_mode; uint16_t poly_src = 0; diff --git a/src/video/vid_bt481_ramdac.c b/src/video/vid_bt481_ramdac.c index d1c85dcfe..1b81e2dc7 100644 --- a/src/video/vid_bt481_ramdac.c +++ b/src/video/vid_bt481_ramdac.c @@ -26,6 +26,7 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/plat_unused.h> typedef struct bt481_ramdac_t { int state; @@ -128,7 +129,7 @@ bt481_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) } static void * -bt481_ramdac_init(const device_t *info) +bt481_ramdac_init(UNUSED(const device_t *info)) { bt481_ramdac_t *ramdac = (bt481_ramdac_t *) malloc(sizeof(bt481_ramdac_t)); memset(ramdac, 0, sizeof(bt481_ramdac_t)); diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 375830f3c..d324368ab 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -448,7 +448,7 @@ cga_interpolate_linear(uint8_t co1, uint8_t co2, double fraction) } static color_t -cga_interpolate_lookup(cga_t *cga, color_t color1, color_t color2, double fraction) +cga_interpolate_lookup(cga_t *cga, color_t color1, color_t color2, UNUSED(double fraction)) { color_t ret; uint8_t dt = cga->double_type - DOUBLE_INTERPOLATE_SRGB; diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index de66a37aa..012a16348 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -166,12 +166,12 @@ static chips_69000_t *reset_state = NULL; /* TODO: Probe timings on real hardware. */ static video_timings_t timing_chips = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 10, .read_w = 10, .read_l = 10 }; -uint8_t chips_69000_readb_linear(uint32_t addr, void *p); -uint16_t chips_69000_readw_linear(uint32_t addr, void *p); -uint32_t chips_69000_readl_linear(uint32_t addr, void *p); -void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p); -void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p); -void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p); +uint8_t chips_69000_readb_linear(uint32_t addr, void *priv); +uint16_t chips_69000_readw_linear(uint32_t addr, void *priv); +uint32_t chips_69000_readl_linear(uint32_t addr, void *priv); +void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *priv); +void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *priv); +void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *priv); /* Multimedia handling. */ uint8_t @@ -1643,9 +1643,9 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) } void -chips_69000_out(uint16_t addr, uint8_t val, void *p) +chips_69000_out(uint16_t addr, uint8_t val, void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; svga_t *svga = &chips->svga; uint8_t old, index; @@ -1750,9 +1750,9 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) } uint8_t -chips_69000_in(uint16_t addr, void *p) +chips_69000_in(uint16_t addr, void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; svga_t *svga = &chips->svga; uint8_t temp = 0, index; @@ -1828,9 +1828,9 @@ chips_69000_in(uint16_t addr, void *p) } static uint8_t -chips_69000_pci_read(int func, int addr, void *p) +chips_69000_pci_read(UNUSED(int func), int addr, void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; { switch (addr) { @@ -1885,9 +1885,9 @@ chips_69000_pci_read(int func, int addr, void *p) } static void -chips_69000_pci_write(int func, int addr, uint8_t val, void *p) +chips_69000_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; { switch (addr) { @@ -2193,71 +2193,71 @@ chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) } uint8_t -chips_69000_readb_linear(uint32_t addr, void *p) +chips_69000_readb_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *) p; + svga_t *svga = (svga_t *) priv; chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readb_mmio(addr, chips); - return svga_readb_linear(addr & 0x1FFFFF, p); + return svga_readb_linear(addr & 0x1FFFFF, priv); } uint16_t -chips_69000_readw_linear(uint32_t addr, void *p) +chips_69000_readw_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *) p; + svga_t *svga = (svga_t *) priv; chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x800000) { if (addr & 0x400000) return bswap16(chips_69000_readw_mmio(addr, chips)); - return bswap16(svga_readw_linear(addr & 0x1FFFFF, p)); + return bswap16(svga_readw_linear(addr & 0x1FFFFF, priv)); } if (addr & 0x400000) return chips_69000_readw_mmio(addr, chips); - return svga_readw_linear(addr & 0x1FFFFF, p); + return svga_readw_linear(addr & 0x1FFFFF, priv); } uint32_t -chips_69000_readl_linear(uint32_t addr, void *p) +chips_69000_readl_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *) p; + svga_t *svga = (svga_t *) priv; chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x800000) { if (addr & 0x400000) return bswap32(chips_69000_readl_mmio(addr, chips)); - return bswap32(svga_readl_linear(addr & 0x1FFFFF, p)); + return bswap32(svga_readl_linear(addr & 0x1FFFFF, priv)); } if (addr & 0x400000) return chips_69000_readl_mmio(addr, chips); - return svga_readl_linear(addr & 0x1FFFFF, p); + return svga_readl_linear(addr & 0x1FFFFF, priv); } void -chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p) +chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *priv) { - svga_t *svga = (svga_t *) p; + svga_t *svga = (svga_t *) priv; chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writeb_mmio(addr, val, chips); - svga_writeb_linear(addr & 0x1FFFFF, val, p); + svga_writeb_linear(addr & 0x1FFFFF, val, priv); } void -chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) +chips_69000_writew_linear(uint32_t addr, uint16_t val, void *priv) { - svga_t *svga = (svga_t *) p; + svga_t *svga = (svga_t *) priv; chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x800000) @@ -2266,13 +2266,13 @@ chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) if (addr & 0x400000) return chips_69000_writew_mmio(addr, val, chips); - svga_writew_linear(addr & 0x1FFFFF, val, p); + svga_writew_linear(addr & 0x1FFFFF, val, priv); } void -chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) +chips_69000_writel_linear(uint32_t addr, uint32_t val, void *priv) { - svga_t *svga = (svga_t *) p; + svga_t *svga = (svga_t *) priv; chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x800000) @@ -2281,7 +2281,7 @@ chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) if (addr & 0x400000) return chips_69000_writel_mmio(addr, val, chips); - svga_writel_linear(addr & 0x1FFFFF, val, p); + svga_writel_linear(addr & 0x1FFFFF, val, priv); } void @@ -2526,9 +2526,9 @@ chips_69000_available(void) } void -chips_69000_close(void *p) +chips_69000_close(void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; chips->quit = 1; // thread_set_event(chips->fifo_event); @@ -2544,17 +2544,17 @@ chips_69000_close(void *p) } void -chips_69000_speed_changed(void *p) +chips_69000_speed_changed(void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; svga_recalctimings(&chips->svga); } void -chips_69000_force_redraw(void *p) +chips_69000_force_redraw(void *priv) { - chips_69000_t *chips = (chips_69000_t *) p; + chips_69000_t *chips = (chips_69000_t *) priv; chips->svga.fullchange = chips->svga.monitor->mon_changeframecount; } diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index a0d92ef9e..9ee74f512 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -6174,7 +6174,7 @@ mystique_hwcursor_draw(svga_t *svga, int displine) } static uint8_t -mystique_tvp3026_gpio_read(uint8_t cntl, void *priv) +mystique_tvp3026_gpio_read(UNUSED(uint8_t cntl), void *priv) { mystique_t *mystique = (mystique_t *) priv; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 4db2737ca..e68e4c1a0 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1467,7 +1467,7 @@ svga_poll(void *priv) } uint32_t -svga_conv_16to32(struct svga_t *svga, uint16_t color, uint8_t bpp) +svga_conv_16to32(UNUSED(struct svga_t *svga), uint16_t color, uint8_t bpp) { return (bpp == 15) ? video_15to32[color] : video_16to32[color]; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 859712357..9ff092161 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -50,206 +50,206 @@ static int was_reset = 0; static const VIDEO_CARD video_cards[] = { // clang-format off - { &device_none }, - { &device_internal }, - { &atiega800p_device }, - { &mach8_vga_isa_device, VIDEO_FLAG_TYPE_8514 }, - { &mach32_isa_device, VIDEO_FLAG_TYPE_8514 }, - { &mach64gx_isa_device }, - { &ati28800k_device }, - { &ati18800_vga88_device }, - { &ati28800_device }, - { &compaq_ati28800_device }, - { &ati28800_wonder1024d_xl_plus_device }, + { .device = &device_none, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &device_internal, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &atiega800p_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mach8_vga_isa_device, .flags = VIDEO_FLAG_TYPE_8514 }, + { .device = &mach32_isa_device, .flags = VIDEO_FLAG_TYPE_8514 }, + { .device = &mach64gx_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ati28800k_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ati18800_vga88_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ati28800_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &compaq_ati28800_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ati28800_wonder1024d_xl_plus_device, .flags = VIDEO_FLAG_TYPE_NONE }, #ifdef USE_XL24 - { &ati28800_wonderxl24_device }, + { .device = &ati28800_wonderxl24_device, .flags = VIDEO_FLAG_TYPE_NONE }, #endif /* USE_XL24 */ - { &ati18800_device }, - { &ati18800_wonder_device }, - { &cga_device }, - { &sega_device }, - { &gd5401_isa_device }, - { &gd5402_isa_device }, - { &gd5420_isa_device }, - { &gd5422_isa_device }, - { &gd5426_isa_device }, - { &gd5426_diamond_speedstar_pro_a1_isa_device }, - { &gd5428_boca_isa_device }, - { &gd5428_isa_device }, - { &gd5429_isa_device }, - { &gd5434_isa_device }, - { &gd5434_diamond_speedstar_64_a3_isa_device }, - { &compaq_cga_device }, - { &compaq_cga_2_device }, - { &cpqega_device }, - { &ega_device }, - { &g2_gc205_device }, - { &hercules_device, VIDEO_FLAG_TYPE_MDA }, - { &herculesplus_device, VIDEO_FLAG_TYPE_MDA }, - { &incolor_device }, - { &inmos_isa_device, VIDEO_FLAG_TYPE_XGA }, - { &im1024_device }, - { &iskra_ega_device }, - { &et4000_kasan_isa_device }, - { &mda_device, VIDEO_FLAG_TYPE_MDA }, - { &genius_device }, - { &nga_device }, - { &ogc_device }, - { &oti037c_device }, - { &oti067_device }, - { &oti077_device }, - { ¶dise_pvga1a_device }, - { ¶dise_wd90c11_device }, - { ¶dise_wd90c30_device }, - { &colorplus_device }, - { &pgc_device }, - { &cga_pravetz_device }, - { &radius_svga_multiview_isa_device }, - { &realtek_rtg3105_device }, - { &realtek_rtg3106_device }, - { &s3_diamond_stealth_vram_isa_device }, - { &s3_orchid_86c911_isa_device }, - { &s3_ami_86c924_isa_device }, - { &s3_metheus_86c928_isa_device }, - { &s3_phoenix_86c801_isa_device }, - { &s3_spea_mirage_86c801_isa_device }, - { &sigma_device }, - { &tvga8900b_device }, - { &tvga8900d_device }, - { &tvga8900dr_device }, - { &tvga9000b_device }, - { &nec_sv9000_device }, - { &et4000k_isa_device }, - { &et2000_device }, - { &et3000_isa_device }, - { &et4000_tc6058af_isa_device }, - { &et4000_isa_device }, - { &et4000w32_device }, - { &et4000w32i_isa_device }, - { &vga_device }, - { &v7_vga_1024i_device }, - { &wy700_device }, - { &mach32_mca_device, VIDEO_FLAG_TYPE_8514 }, - { &gd5426_mca_device }, - { &gd5428_mca_device }, - { &et4000_mca_device }, - { &radius_svga_multiview_mca_device }, - { &mach32_pci_device, VIDEO_FLAG_TYPE_8514 }, - { &mach64gx_pci_device }, - { &mach64vt2_device }, - { &bochs_svga_device }, - { &chips_69000_device }, - { &gd5430_pci_device, }, - { &gd5434_pci_device }, - { &gd5436_pci_device, VIDEO_FLAG_TYPE_SPECIAL }, - { &gd5440_pci_device }, - { &gd5446_pci_device, VIDEO_FLAG_TYPE_SPECIAL }, - { &gd5446_stb_pci_device, VIDEO_FLAG_TYPE_SPECIAL }, - { &gd5480_pci_device }, - { &et4000w32p_videomagic_revb_pci_device }, - { &et4000w32p_revc_pci_device }, - { &et4000w32p_cardex_pci_device }, - { &et4000w32p_noncardex_pci_device }, - { &et4000w32p_pci_device }, - { &s3_spea_mercury_lite_86c928_pci_device }, - { &s3_diamond_stealth64_964_pci_device }, - { &s3_elsa_winner2000_pro_x_964_pci_device }, - { &s3_mirocrystal_20sv_964_pci_device }, - { &s3_bahamas64_pci_device }, - { &s3_phoenix_vision864_pci_device }, - { &s3_diamond_stealth_se_pci_device }, - { &s3_phoenix_trio32_pci_device }, - { &s3_diamond_stealth64_pci_device }, - { &s3_9fx_pci_device }, - { &s3_phoenix_trio64_pci_device }, - { &s3_diamond_stealth64_968_pci_device }, - { &s3_elsa_winner2000_pro_x_pci_device }, - { &s3_mirovideo_40sv_ergo_968_pci_device }, - { &s3_9fx_771_pci_device }, - { &s3_phoenix_vision968_pci_device }, - { &s3_spea_mercury_p64v_pci_device }, - { &s3_9fx_531_pci_device }, - { &s3_phoenix_vision868_pci_device }, - { &s3_cardex_trio64vplus_pci_device }, - { &s3_phoenix_trio64vplus_pci_device }, - { &s3_trio64v2_dx_pci_device }, - { &s3_virge_325_pci_device }, - { &s3_diamond_stealth_2000_pci_device }, - { &s3_mirocrystal_3d_pci_device }, - { &s3_diamond_stealth_3000_pci_device }, - { &s3_stb_velocity_3d_pci_device }, - { &s3_virge_375_pci_device }, - { &s3_diamond_stealth_2000pro_pci_device }, - { &s3_virge_385_pci_device }, - { &s3_virge_357_pci_device }, - { &s3_diamond_stealth_4000_pci_device }, - { &s3_trio3d2x_pci_device }, - { &millennium_device }, - { &millennium_ii_device }, - { &mystique_device }, - { &mystique_220_device }, - { &tgui9440_pci_device }, - { &tgui9660_pci_device }, - { &tgui9680_pci_device }, - { &voodoo_banshee_device }, - { &creative_voodoo_banshee_device }, - { &voodoo_3_1000_device }, - { &voodoo_3_2000_device }, - { &voodoo_3_3000_device }, - { &mach32_vlb_device, VIDEO_FLAG_TYPE_8514 }, - { &mach64gx_vlb_device }, - { &et4000w32i_vlb_device }, - { &et4000w32p_videomagic_revb_vlb_device }, - { &et4000w32p_revc_vlb_device }, - { &et4000w32p_cardex_vlb_device }, - { &et4000w32p_vlb_device }, - { &et4000w32p_noncardex_vlb_device }, - { &gd5424_vlb_device }, - { &gd5426_vlb_device }, - { &gd5428_vlb_device }, - { &gd5428_diamond_speedstar_pro_b1_vlb_device }, - { &gd5429_vlb_device }, - { &gd5430_diamond_speedstar_pro_se_a8_vlb_device }, - { &gd5430_vlb_device }, - { &gd5434_vlb_device }, - { &s3_metheus_86c928_vlb_device }, - { &s3_mirocrystal_8s_805_vlb_device }, - { &s3_mirocrystal_10sd_805_vlb_device }, - { &s3_phoenix_86c805_vlb_device }, - { &s3_spea_mirage_86c805_vlb_device }, - { &s3_diamond_stealth64_964_vlb_device }, - { &s3_mirocrystal_20sv_964_vlb_device }, - { &s3_mirocrystal_20sd_864_vlb_device }, - { &s3_bahamas64_vlb_device }, - { &s3_phoenix_vision864_vlb_device }, - { &s3_diamond_stealth_se_vlb_device }, - { &s3_phoenix_trio32_vlb_device }, - { &s3_diamond_stealth64_vlb_device }, - { &s3_9fx_vlb_device }, - { &s3_phoenix_trio64_vlb_device }, - { &s3_spea_mirage_p64_vlb_device }, - { &s3_diamond_stealth64_968_vlb_device }, - { &s3_stb_powergraph_64_video_vlb_device }, - { &ht216_32_standalone_device }, - { &tgui9400cxi_device }, - { &tgui9440_vlb_device }, - { &s3_virge_357_agp_device }, - { &s3_diamond_stealth_4000_agp_device }, - { &s3_trio3d2x_agp_device }, + { .device = &ati18800_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .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 = &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 }, + { .device = &gd5422_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5426_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5426_diamond_speedstar_pro_a1_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_boca_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5429_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_diamond_speedstar_64_a3_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &compaq_cga_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &compaq_cga_2_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &cpqega_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ega_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &g2_gc205_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &hercules_device, .flags = VIDEO_FLAG_TYPE_MDA }, + { .device = &herculesplus_device, .flags = VIDEO_FLAG_TYPE_MDA }, + { .device = &incolor_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &inmos_isa_device, .flags = VIDEO_FLAG_TYPE_XGA }, + { .device = &im1024_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &iskra_ega_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000_kasan_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mda_device, .flags = VIDEO_FLAG_TYPE_MDA }, + { .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 = &oti037c_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &oti067_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &oti077_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = ¶dise_pvga1a_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = ¶dise_wd90c11_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = ¶dise_wd90c30_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &colorplus_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &pgc_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &cga_pravetz_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &radius_svga_multiview_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &realtek_rtg3105_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &realtek_rtg3106_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_vram_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_orchid_86c911_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_ami_86c924_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_metheus_86c928_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mirage_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &sigma_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tvga8900b_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tvga8900d_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tvga8900dr_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tvga9000b_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &nec_sv9000_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000k_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et2000_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et3000_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000_tc6058af_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32i_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &vga_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &v7_vga_1024i_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &wy700_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mach32_mca_device, .flags = VIDEO_FLAG_TYPE_8514 }, + { .device = &gd5426_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &radius_svga_multiview_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mach32_pci_device, .flags = VIDEO_FLAG_TYPE_8514 }, + { .device = &mach64gx_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mach64vt2_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &bochs_svga_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &chips_69000_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5430_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5436_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5440_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5446_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5446_stb_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5480_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_videomagic_revb_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_revc_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_cardex_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_noncardex_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mercury_lite_86c928_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_964_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_elsa_winner2000_pro_x_964_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_20sv_964_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_bahamas64_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_vision864_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_se_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio32_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_9fx_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio64_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_968_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_elsa_winner2000_pro_x_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirovideo_40sv_ergo_968_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_9fx_771_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_vision968_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mercury_p64v_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_9fx_531_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_vision868_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_cardex_trio64vplus_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio64vplus_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_trio64v2_dx_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_virge_325_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_2000_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_3d_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_3000_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_stb_velocity_3d_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_virge_375_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_2000pro_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_virge_385_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_virge_357_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_4000_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_trio3d2x_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &millennium_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &millennium_ii_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mystique_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mystique_220_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9440_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9660_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9680_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_banshee_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &creative_voodoo_banshee_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_1000_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_2000_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_3000_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mach32_vlb_device, .flags = VIDEO_FLAG_TYPE_8514 }, + { .device = &mach64gx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32i_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_videomagic_revb_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_revc_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_cardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_noncardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5424_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5426_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_diamond_speedstar_pro_b1_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5429_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5430_diamond_speedstar_pro_se_a8_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5430_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_metheus_86c928_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_8s_805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_10sd_805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_86c805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mirage_86c805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_964_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_20sv_964_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_20sd_864_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_bahamas64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_vision864_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_se_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio32_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_9fx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mirage_p64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_968_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_stb_powergraph_64_video_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ht216_32_standalone_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9400cxi_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9440_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_virge_357_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_4000_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_trio3d2x_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, #ifdef USE_G100 - { &productiva_g100_device, VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &productiva_g100_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, #endif /*USE_G100 */ - { &velocity_100_agp_device }, - { &velocity_200_agp_device }, - { &voodoo_3_1000_agp_device }, - { &voodoo_3_2000_agp_device }, - { &voodoo_3_3000_agp_device }, - { &voodoo_3_3500_agp_ntsc_device }, - { &voodoo_3_3500_agp_pal_device }, - { &compaq_voodoo_3_3500_agp_device }, - { &voodoo_3_3500_se_agp_device }, - { &voodoo_3_3500_si_agp_device }, - { NULL } + { .device = &velocity_100_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &velocity_200_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_1000_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_2000_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_3000_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_3500_agp_ntsc_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_3500_agp_pal_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &compaq_voodoo_3_3500_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_3500_se_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &voodoo_3_3500_si_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = NULL, .flags = VIDEO_FLAG_TYPE_NONE } // clang-format on }; diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index efab288de..e9fbe57f2 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -210,7 +210,7 @@ static void tgui_ext_writel(uint32_t addr, uint32_t val, void *priv); /*Remap address for chain-4/doubleword style layout*/ static __inline uint32_t -dword_remap(svga_t *svga, uint32_t in_addr) +dword_remap(UNUSED(svga_t *svga), uint32_t in_addr) { return ((in_addr << 2) & 0x3fff0) | ((in_addr >> 14) & 0xc) | (in_addr & ~0x3fffc); } diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 93b557fec..ebd92d983 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -480,7 +480,7 @@ banshee_updatemapping(banshee_t *banshee) } uint32_t -banshee_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +banshee_conv_16to32(svga_t* svga, uint16_t color, UNUSED(uint8_t bpp)) { banshee_t *banshee = (banshee_t *) svga->priv; uint32_t ret = 0x00000000; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 862dbd1cf..fe72b17c0 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -19,7 +19,7 @@ #include #include #include -#include <86box/bswap.h> +//#include <86box/bswap.h> #include <86box/86box.h> #include <86box/io.h> #include <86box/machine.h> From 47a83d92ea6db0691bb3e74cb8d4e3b858c0f519 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 2 Feb 2025 04:38:06 -0500 Subject: [PATCH 0185/1190] Rename define+device for lotech EMS board --- src/device/isamem.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index 4dc88cc6c..d248e985e 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -102,7 +102,7 @@ #define ISAMEM_BRXT_CARD 13 #define ISAMEM_BRAT_CARD 14 #define ISAMEM_EV165A_CARD 15 -#define ISAMEM_LOTECH_CARD 16 +#define ISAMEM_LOTECH_EMS_CARD 16 #define ISAMEM_DEBUG 0 @@ -578,7 +578,7 @@ isamem_init(const device_t *info) dev->flags |= FLAG_FAST; break; - case ISAMEM_LOTECH_CARD: /* Lotech EMS */ + case ISAMEM_LOTECH_EMS_CARD: /* Lotech EMS */ /* The Lotech EMS cannot have more than 4096KB per board. */ ems_max = EMS_LOTECH_MAXSIZE; fallthrough; @@ -800,7 +800,7 @@ isamem_init(const device_t *info) mem_mapping_disable(&dev->ems[i].mapping); /* Set up an I/O port handler. */ - if (dev->board != ISAMEM_LOTECH_CARD) + if (dev->board != ISAMEM_LOTECH_EMS_CARD) io_sethandler(dev->base_addr[0] + (EMS_PGSIZE * i), 2, ems_in, NULL, NULL, ems_out, NULL, NULL, &(dev->ems[i])); @@ -831,7 +831,7 @@ isamem_init(const device_t *info) } } - if (dev->board == ISAMEM_LOTECH_CARD) + if (dev->board == ISAMEM_LOTECH_EMS_CARD) io_sethandler(dev->base_addr[0], 4, consecutive_ems_in, NULL, NULL, consecutive_ems_out, NULL, NULL, dev); } @@ -1856,11 +1856,11 @@ static const device_config_t lotech_config[] = { // clang-format on }; -static const device_t lotech_device = { +static const device_t lotech_ems_device = { .name = "Lo-tech EMS Board", .internal_name = "lotechems", .flags = DEVICE_ISA, - .local = ISAMEM_LOTECH_CARD, + .local = ISAMEM_LOTECH_EMS_CARD, .init = isamem_init, .close = isamem_close, .reset = NULL, @@ -2071,7 +2071,7 @@ static const struct { #ifdef USE_ISAMEM_IAB { &iab_device }, #endif /* USE_ISAMEM_IAB */ - { &lotech_device }, + { &lotech_ems_device }, { NULL } // clang-format on }; From a3fb32cdc3827ee3d49bcec8ea4ccfe1130a280f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 2 Feb 2025 04:43:14 -0500 Subject: [PATCH 0186/1190] Rename define+device for Realtek 8019AS PNP --- src/include/86box/net_ne2000.h | 2 +- src/include/86box/network.h | 2 +- src/network/net_ne2000.c | 28 ++++++++++++++-------------- src/network/network.c | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/include/86box/net_ne2000.h b/src/include/86box/net_ne2000.h index cb17ef8b1..ecf2612b5 100644 --- a/src/include/86box/net_ne2000.h +++ b/src/include/86box/net_ne2000.h @@ -44,7 +44,7 @@ enum { NE2K_NE2000_COMPAT = 4, /* 16-bit ISA NE2000-Compatible */ NE2K_NE2000_COMPAT_8BIT = 5, /* 8-bit ISA NE2000-Compatible, like: https://github.com/skiselev/isa8_eth */ NE2K_ETHERNEXT_MC = 6, /* 16-bit MCA EtherNext/MC */ - NE2K_RTL8019AS = 7, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_RTL8019AS_PNP = 7, /* 16-bit ISA PnP Realtek 8019AS */ NE2K_DE220P = 8, /* 16-bit ISA PnP D-Link DE-220P */ NE2K_RTL8029AS = 9, /* 32-bit PCI Realtek 8029AS */ /* Check nic_init() if adding items after this point. */ diff --git a/src/include/86box/network.h b/src/include/86box/network.h index fa6408790..2140d62dd 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -213,7 +213,7 @@ extern const device_t ne2000_device; extern const device_t ne2000_compat_device; extern const device_t ne2000_compat_8bit_device; extern const device_t ethernext_mc_device; -extern const device_t rtl8019as_device; +extern const device_t rtl8019as_pnp_device; extern const device_t de220p_device; extern const device_t rtl8029as_device; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 97c2b5de2..2f6c60d51 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -312,7 +312,7 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) static uint32_t page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len)) { - if (dev->board >= NE2K_RTL8019AS) + if (dev->board >= NE2K_RTL8019AS_PNP) switch (off) { case 0x1: /* 9346CR */ return (dev->_9346cr); @@ -327,7 +327,7 @@ page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len)) return (dev->config3 & 0x46); case 0x8: /* CSNSAV */ - return ((dev->board == NE2K_RTL8019AS) ? dev->pnp_csnsav : 0x00); + return ((dev->board == NE2K_RTL8019AS_PNP) ? dev->pnp_csnsav : 0x00); case 0xe: /* 8029ASID0 */ if (dev->board == NE2K_RTL8029AS) @@ -350,7 +350,7 @@ page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len)) static void page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) { - if (dev->board >= NE2K_RTL8019AS) { + if (dev->board >= NE2K_RTL8019AS_PNP) { nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", dev->name, off, len, val); @@ -919,7 +919,7 @@ nic_init(const device_t *info) dev->name = info->name; dev->board = info->local; - if (dev->board >= NE2K_RTL8019AS) { + if (dev->board >= NE2K_RTL8019AS_PNP) { dev->base_address = 0x340; dev->base_irq = 12; if (dev->board == NE2K_RTL8029AS) { @@ -1042,18 +1042,18 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x4000, 0x8000); break; - case NE2K_RTL8019AS: + case NE2K_RTL8019AS_PNP: case NE2K_RTL8029AS: dev->is_pci = (dev->board == NE2K_RTL8029AS) ? 1 : 0; dev->maclocal[0] = 0x00; /* 00:E0:4C (Realtek OID) */ dev->maclocal[1] = 0xE0; dev->maclocal[2] = 0x4C; - rom = (dev->board == NE2K_RTL8019AS) ? ROM_PATH_RTL8019 : ROM_PATH_RTL8029; + rom = (dev->board == NE2K_RTL8019AS_PNP) ? ROM_PATH_RTL8019 : ROM_PATH_RTL8029; if (dev->is_pci) dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC); else dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CLEAR_IRQ); - dp8390_set_id(dev->dp8390, 0x50, (dev->board == NE2K_RTL8019AS) ? 0x70 : 0x43); + dp8390_set_id(dev->dp8390, 0x50, (dev->board == NE2K_RTL8019AS_PNP) ? 0x70 : 0x43); dp8390_mem_alloc(dev->dp8390, 0x4000, 0x8000); break; @@ -1090,13 +1090,13 @@ nic_init(const device_t *info) * Make this device known to the I/O system. * PnP and PCI devices start with address spaces inactive. */ - if ((dev->board < NE2K_RTL8019AS) && (dev->board != NE2K_ETHERNEXT_MC)) + if ((dev->board < NE2K_RTL8019AS_PNP) && (dev->board != NE2K_ETHERNEXT_MC)) nic_ioset(dev, dev->base_address); /* Set up our BIOS ROM space, if any. */ nic_rom_init(dev, rom); - if (dev->board >= NE2K_RTL8019AS) { + if (dev->board >= NE2K_RTL8019AS_PNP) { if (dev->is_pci) { /* * Configure the PCI space registers. @@ -1144,7 +1144,7 @@ nic_init(const device_t *info) pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev, &dev->pci_slot); } - /* Initialize the RTL8029 EEPROM. */ + /* Initialize the RTL80x9 EEPROM. */ memset(dev->eeprom, 0x00, sizeof(dev->eeprom)); if (dev->board == NE2K_RTL8029AS) { @@ -1158,7 +1158,7 @@ nic_init(const device_t *info) const char *pnp_rom_file = NULL; int pnp_rom_len = 0x4a; switch (dev->board) { - case NE2K_RTL8019AS: + case NE2K_RTL8019AS_PNP: pnp_rom_file = "roms/network/rtl8019as/RTL8019A.BIN"; break; @@ -1182,7 +1182,7 @@ nic_init(const device_t *info) } switch (info->local) { - case NE2K_RTL8019AS: + case NE2K_RTL8019AS_PNP: case NE2K_DE220P: dev->pnp_card = isapnp_add_card(pnp_rom, pnp_rom_len, nic_pnp_config_changed, nic_pnp_csn_changed, @@ -1706,11 +1706,11 @@ const device_t ethernext_mc_device = { .config = mca_mac_config }; -const device_t rtl8019as_device = { +const device_t rtl8019as_pnp_device = { .name = "Realtek RTL8019AS", .internal_name = "ne2kpnp", .flags = DEVICE_ISA | DEVICE_AT, - .local = NE2K_RTL8019AS, + .local = NE2K_RTL8019AS_PNP, .init = nic_init, .close = nic_close, .reset = NULL, diff --git a/src/network/network.c b/src/network/network.c index f4b03ee79..66990e51d 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -96,7 +96,7 @@ static const NETWORK_CARD net_cards[] = { { &ne1000_device }, { &ne2000_device }, { &pcnet_am79c960_eb_device }, - { &rtl8019as_device }, + { &rtl8019as_pnp_device }, { &wd8003e_device }, { &wd8003eb_device }, { &wd8013ebt_device }, From cca1b2b293faaa42b5935db818b71333e1394b7f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 2 Feb 2025 04:49:32 -0500 Subject: [PATCH 0187/1190] Trivial EMS cleanups and a few comments --- src/device/isamem.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index d248e985e..5cac31c7f 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -27,16 +27,20 @@ * modern boards even have multiple 'copies' of those registers, * which can be switched very fast, to allow for multitasking. * - * TODO: The EV159 is supposed to support 16b EMS transfers, but the + * TODO: The EV-159 is supposed to support 16b EMS transfers, but the * EMM.sys driver for it doesn't seem to want to do that.. * + * EV-125 (It supports backfill) + * https://theretroweb.com/expansioncard/documentation/50250.pdf * + * EV-158 (RAM 10000) + * http://web.archive.org/web/19961104093221/http://www.everex.com/supp/techlib/memmem.html * * Authors: Fred N. van Kempen, * Jasmine Iwanek * * Copyright 2018 Fred N. van Kempen. - * Copyright 2022-2024 Jasmine Iwanek. + * Copyright 2022-2025 Jasmine Iwanek. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -304,16 +308,13 @@ ems_writew(uint32_t addr, uint16_t val, void *priv) static uint8_t ems_in(uint16_t port, void *priv) { - const emsreg_t *dev = (emsreg_t *) priv; - uint8_t ret = 0xff; -#ifdef ENABLE_ISAMEM_LOG - int vpage; -#endif - + const emsreg_t *dev = (emsreg_t *) priv; + uint8_t ret = 0xff; /* Get the viewport page number. */ #ifdef ENABLE_ISAMEM_LOG - vpage = (port / EMS_PGSIZE); + int vpage = (port / EMS_PGSIZE); #endif + port &= (EMS_PGSIZE - 1); switch (port & 0x0001) { @@ -339,13 +340,11 @@ ems_in(uint16_t port, void *priv) static uint8_t consecutive_ems_in(uint16_t port, void *priv) { - const memdev_t *dev = (memdev_t *) priv; - uint8_t ret = 0xff; - int vpage; - + const memdev_t *dev = (memdev_t *) priv; + uint8_t ret = 0xff; /* Get the viewport page number. */ - vpage = (port - dev->base_addr[0]); - + int vpage = (port - dev->base_addr[0]); + ret = dev->ems[vpage].page; if (dev->ems[vpage].enabled) ret |= 0x80; @@ -359,11 +358,10 @@ consecutive_ems_in(uint16_t port, void *priv) static void ems_out(uint16_t port, uint8_t val, void *priv) { - emsreg_t *dev = (emsreg_t *) priv; - int vpage; - + emsreg_t *dev = (emsreg_t *) priv; /* Get the viewport page number. */ - vpage = (port / EMS_PGSIZE); + int vpage = (port / EMS_PGSIZE); + port &= (EMS_PGSIZE - 1); switch (port & 0x0001) { @@ -433,11 +431,9 @@ ems_out(uint16_t port, uint8_t val, void *priv) static void consecutive_ems_out(uint16_t port, uint8_t val, void *priv) { - memdev_t *dev = (memdev_t *) priv; - int vpage; - + memdev_t *dev = (memdev_t *) priv; /* Get the viewport page number. */ - vpage = (port - dev->base_addr[0]); + int vpage = (port - dev->base_addr[0]); isamem_log("ISAMEM: write(%04x, %02x) to page mapping registers! (page=%d)\n", port, val, vpage); @@ -1030,6 +1026,7 @@ static const device_config_t genericxt_config[] = { // clang-format on }; +// This also nicely accounts for the Everex EV-138 static const device_t genericxt_device = { .name = "Generic PC/XT Memory Expansion", .internal_name = "genericxt", @@ -1236,6 +1233,7 @@ static const device_config_t genericat_config[] = { // clang-format on }; +// This also nicely accounts for the Everex EV-135 static const device_t genericat_device = { .name = "Generic PC/AT Memory Expansion", .internal_name = "genericat", From 4b5162feddc25136eabfdadf2ecc58a10f643694 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 2 Feb 2025 05:01:42 -0500 Subject: [PATCH 0188/1190] Fix for building on msys2 clang found by ANightly --- src/qt/win_cdrom_ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 271f7226f..38c553852 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include <86box/cdrom.h> #include <86box/log.h> From a540012f9a50a08121fde02b799c6d33d49899b7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 3 Feb 2025 00:46:38 +0100 Subject: [PATCH 0189/1190] XGA: Move a variable initialization to IF blocks, fixes segementation fault when pat_src is 8 (eg. in Windows 95 on the MCA XGA). --- src/video/vid_xga.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index fe72b17c0..fb27b8b2c 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -1504,7 +1504,7 @@ xga_bitblt(svga_t *svga) uint32_t old_dest_dat; uint32_t color_cmp = xga->accel.color_cmp; uint32_t plane_mask = xga->accel.plane_mask; - uint32_t patbase = xga->accel.px_map_base[xga->accel.pat_src]; + uint32_t patbase; uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; uint32_t patwidth = xga->accel.px_map_width[xga->accel.pat_src]; @@ -1632,6 +1632,8 @@ xga_bitblt(svga_t *svga) } } } else if (xga->accel.pat_src >= 1) { + patbase = xga->accel.px_map_base[xga->accel.pat_src]; + if (patheight == 7) { if (xga->accel.src_map != 1) xga->accel.pattern = 1; @@ -1741,6 +1743,8 @@ xga_bitblt(svga_t *svga) } } } else { + patbase = xga->accel.px_map_base[xga->accel.pat_src]; + while (xga->accel.y >= 0) { mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, patbase, patwidth + 1); From 1ee954ef83f92996408a94c3945594f89947c4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 3 Feb 2025 02:54:20 +0100 Subject: [PATCH 0190/1190] Update CMakeLists.txt --- src/qt/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index d7ea91f70..a6419ffcb 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -203,7 +203,16 @@ if(WIN32) enable_language(RC) target_sources(86Box PUBLIC 86Box-qt.rc) target_sources(plat PRIVATE win_dynld.c) + if(DINPUT) + target_sources(plat PRIVATE win_joystick.cpp) + target_link_libraries(86Box dinput8) + else() + target_sources(plat PRIVATE win_joystick_rawinput.c) + endif() + target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) + target_link_libraries(86Box hid d3d9 dwmapi) + # REMOVE THE DINPUT STUFF, IT'S FROM CACO'S DARK MODE BRANCH!!!! # CMake 3.22 messed this up for clang/clang++ # See https://gitlab.kitware.com/cmake/cmake/-/issues/22611 if(MSVC OR (NOT MINGW AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.22)) From 79e4386daa47fa218441d85850c7082423688982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 3 Feb 2025 02:55:34 +0100 Subject: [PATCH 0191/1190] Update qt_main.cpp --- src/qt/qt_main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 1c917f517..1271b62c1 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -30,6 +30,9 @@ #include #include #include +#include +#include +/* CACO AGAIN */ #include #ifdef QT_STATIC From 0998f03d6f0150abf5bcd56923b97973686cae43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 3 Feb 2025 02:56:08 +0100 Subject: [PATCH 0192/1190] Update qt_main.cpp --- src/qt/qt_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 1271b62c1..71bb417fb 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -32,6 +32,7 @@ #include #include #include + /* CACO AGAIN */ #include From 11506e740c095abcfd09bd427ba937f6df43143b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 3 Feb 2025 02:56:36 +0100 Subject: [PATCH 0193/1190] Update qt_main.cpp --- src/qt/qt_main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 71bb417fb..f7447f953 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -17,6 +17,8 @@ * Copyright 2021-2022 Cacodemon345 * Copyright 2021-2022 Teemu Korhonen */ +/* CACO AGAIN - MOVE TO THE BOTTOM */ +#include #include #include #include @@ -33,9 +35,6 @@ #include #include -/* CACO AGAIN */ -#include - #ifdef QT_STATIC /* Static builds need plugin imports */ # include From 8eee344adbf7f3af3366cabefc41055b0ab67338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 3 Feb 2025 02:58:00 +0100 Subject: [PATCH 0194/1190] Update qt_main.cpp --- src/qt/qt_main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index b302b9cca..72b0eef53 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -17,8 +17,6 @@ * Copyright 2021-2022 Cacodemon345 * Copyright 2021-2022 Teemu Korhonen */ -/* CACO AGAIN - MOVE TO THE BOTTOM */ -#include #include #include #include @@ -32,6 +30,7 @@ #include #include #include +#include #include #include From af6d8819a519e5501dae2f7cb2e20947139e9db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 3 Feb 2025 02:58:53 +0100 Subject: [PATCH 0195/1190] Update CMakeLists.txt --- src/qt/CMakeLists.txt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 8f1fb39dd..c08a03016 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -204,16 +204,8 @@ if(WIN32) enable_language(RC) target_sources(86Box PUBLIC 86Box-qt.rc) target_sources(plat PRIVATE win_dynld.c) - if(DINPUT) - target_sources(plat PRIVATE win_joystick.cpp) - target_link_libraries(86Box dinput8) - else() - target_sources(plat PRIVATE win_joystick_rawinput.c) - endif() - target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) - target_link_libraries(86Box hid d3d9 dwmapi) + target_link_libraries(86Box dwmapi) - # REMOVE THE DINPUT STUFF, IT'S FROM CACO'S DARK MODE BRANCH!!!! # CMake 3.22 messed this up for clang/clang++ # See https://gitlab.kitware.com/cmake/cmake/-/issues/22611 if(MSVC OR (NOT MINGW AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.22)) From 2d65663ff67857ffe6138f89a70f1babbf98d7e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 3 Feb 2025 03:08:01 +0100 Subject: [PATCH 0196/1190] Fix a warning. --- src/qt/qt_winrawinputfilter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index a44f203e6..24baa257f 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -172,7 +172,9 @@ WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *mess } return true; - } else if (msg && msg->message == WM_SETTINGCHANGE && msg->lParam != NULL && wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0) { + } else if ((msg != nullptr) && (msg->message == WM_SETTINGCHANGE) && + (((void *) msg->lParam) != nullptr) && + (wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0)) { if (!windows_is_light_theme()) { QFile f(":qdarkstyle/dark/darkstyle.qss"); From 35a12e08262835b9a587c2f161961ed8ec1f1b17 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 3 Feb 2025 10:57:19 +0100 Subject: [PATCH 0197/1190] CD-ROM: IOCTL now detects medium changes without having to read the host drive's TOC on every operation, improves performance. --- src/cdrom/cdrom.c | 56 +++++++--- src/cdrom/cdrom_image.c | 3 +- src/include/86box/cdrom.h | 6 +- src/include/86box/scsi_device.h | 2 +- src/qt/dummy_cdrom_ioctl.c | 27 ++++- src/qt/qt_winrawinputfilter.cpp | 187 ++++++++++++++++++++++---------- src/qt/win_cdrom_ioctl.c | 164 ++++++++++++++++------------ src/scsi/scsi_cdrom.c | 60 +++++----- src/unix/dummy_cdrom_ioctl.c | 27 ++++- 9 files changed, 340 insertions(+), 192 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 4ccb81442..2cdcc5a22 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2641,18 +2641,6 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer) return ret; } -int -cdrom_ext_medium_changed(const cdrom_t *dev) -{ - int ret = 0; - - if (dev && dev->ops && dev->ops->ext_medium_changed && - (dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED)) - ret = dev->ops->ext_medium_changed(dev->local); - - return ret; -} - int cdrom_is_empty(const uint8_t id) { @@ -2700,6 +2688,44 @@ cdrom_toc_dump(cdrom_t *dev) } #endif +void +cdrom_set_empty(cdrom_t *dev) +{ + dev->cd_status = CD_STATUS_EMPTY; +} + +void +cdrom_update_status(cdrom_t *dev) +{ + const int was_empty = (dev->cd_status == CD_STATUS_EMPTY); + + if (dev->ops->load != NULL) + dev->ops->load(dev->local); + + /* All good, reset state. */ + 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)) + dev->cd_status = CD_STATUS_DVD; + else + dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED : + CD_STATUS_DATA_ONLY; + + dev->cdrom_capacity = dev->ops->get_last_block(dev->local); + + if (dev->cd_status != CD_STATUS_EMPTY) { + /* Signal media change to the emulated machine. */ + cdrom_insert(dev->id); + + /* The drive was previously empty, transition directly to UNIT ATTENTION. */ + if (was_empty) + cdrom_insert(dev->id); + } +} + int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert) { @@ -2728,10 +2754,12 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert) 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; 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 : + dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED : CD_STATUS_DATA_ONLY; dev->cdrom_capacity = dev->ops->get_last_block(dev->local); @@ -2744,7 +2772,7 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert) cdrom_toc_dump(dev); #endif - if (!skip_insert) { + if (!skip_insert && (dev->cd_status != CD_STATUS_EMPTY)) { /* Signal media change to the emulated machine. */ cdrom_insert(dev->id); diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index afc70bda7..271a290cb 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -1992,7 +1992,8 @@ static const cdrom_ops_t image_ops = { image_is_dvd, image_has_audio, NULL, - image_close + image_close, + NULL }; /* Public functions. */ diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 82d211896..7c028d7d6 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -271,8 +271,9 @@ typedef struct cdrom_ops_t { uint32_t *info); int (*is_dvd)(const void *local); int (*has_audio)(const void *local); - int (*ext_medium_changed)(void *local); + int (*is_empty)(const void *local); void (*close)(void *local); + void (*load)(const void *local); } cdrom_ops_t; typedef struct cdrom { @@ -423,7 +424,8 @@ 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 int cdrom_ext_medium_changed(const 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); extern void cdrom_global_init(void); diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 84abee066..ffe042481 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -219,7 +219,7 @@ #define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 #define ASC_WRITE_PROTECTED 0x27 #define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_CAPACITY_DATA_CHANGED 0x2A +#define ASC_CAPACITY_DATA_CHANGED 0x2a #define ASC_INCOMPATIBLE_FORMAT 0x30 #define ASC_MEDIUM_NOT_PRESENT 0x3a #define ASC_DATA_PHASE_ERROR 0x4b diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index 9efd67ad6..bddfabb5b 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -40,7 +40,6 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; - int toc_valid; void *handle; char path[256]; } ioctl_t; @@ -77,8 +76,6 @@ ioctl_open_handle(UNUSED(ioctl_t *ioctl)) static void ioctl_read_toc(ioctl_t *ioctl) { - if (!ioctl->toc_valid) - ioctl->toc_valid = 1; } /* Shared functions. */ @@ -159,6 +156,12 @@ ioctl_has_audio(UNUSED(const void *local)) return 0; } +static int +ioctl_is_empty(const void *local) +{ + return 1; +} + static int ioctl_ext_medium_changed(UNUSED(void *local)) { @@ -186,6 +189,18 @@ ioctl_close(void *local) ioctl->log = NULL; } +static void +ioctl_load(const void *local) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + + if (ioctl_open_handle((ioctl_t *) ioctl)) { + ioctl_close_handle((ioctl_t *) ioctl); + + ioctl_read_toc((ioctl_t *) ioctl); + } +} + static const cdrom_ops_t ioctl_ops = { ioctl_get_track_info, ioctl_get_raw_track_info, @@ -196,8 +211,9 @@ static const cdrom_ops_t ioctl_ops = { ioctl_read_dvd_structure, ioctl_is_dvd, ioctl_has_audio, - ioctl_ext_medium_changed, - ioctl_close + ioctl_is_empty, + ioctl_close, + ioctl_load }; /* Public functions. */ @@ -218,7 +234,6 @@ ioctl_open(cdrom_t *dev, const char *drv) ioctl_log(ioctl->log, "Path is %s\n", ioctl->path); ioctl->dev = dev; - ioctl->toc_valid = 0; dev->ops = &ioctl_ops; } diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 24baa257f..13e0ec9a7 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -51,7 +51,10 @@ #include <86box/mouse.h> #include <86box/plat.h> #include <86box/86box.h> +#include <86box/cdrom.h> #include <86box/video.h> +#include +#include extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); @@ -151,72 +154,142 @@ WindowsRawInputFilter::~WindowsRawInputFilter() RegisterRawInputDevices(rid, 2, sizeof(rid[0])); } +static void +notify_drives(ULONG unitmask, int empty) +{ + char p[1024] = { 0 }; + + for (int i = 0; i < 26; ++i) { + if (unitmask & 0x1) { + cdrom_t *dev = NULL; + + sprintf(p, "ioctl://\\\\.\\%c:", 'A' + i); + + for (int i = 0; i < CDROM_NUM; i++) + if (!stricmp(cdrom[i].image_path, p)) { + dev = &(cdrom[i]); + if (empty) + cdrom_set_empty(dev); + else + cdrom_update_status(dev); + // pclog("CD-ROM %i : Drive notified of media %s\n", + // dev->id, empty ? "removal" : "change"); + } + } + + unitmask = unitmask >> 1; + } +} + +static void +device_change(WPARAM wParam, LPARAM lParam) +{ + PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam; + + switch(wParam) { + case DBT_DEVICEARRIVAL: + case DBT_DEVICEREMOVECOMPLETE: + /* Check whether a CD or DVD was inserted into a drive. */ + if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) { + PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) lpdb; + + if (lpdbv->dbcv_flags & DBTF_MEDIA) + notify_drives(lpdbv->dbcv_unitmask, + (wParam == DBT_DEVICEREMOVECOMPLETE)); + } + break; + + default: + /* + Process other WM_DEVICECHANGE notifications for other + devices or reasons. + */ + break; + } +} + bool WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) { if (eventType == "windows_generic_MSG") { MSG *msg = static_cast(message); - if (msg->message == WM_INPUT) { - - if (window->isActiveWindow() && menus_open == 0) - handle_input((HRAWINPUT) msg->lParam); - else - { - for (auto &w : window->renderers) { - if (w && w->isActiveWindow()) { - handle_input((HRAWINPUT) msg->lParam); - break; + if (msg != nullptr) switch(msg->message) { + case WM_INPUT: + if (window->isActiveWindow() && (menus_open == 0)) + handle_input((HRAWINPUT) msg->lParam); + else { + for (auto &w : window->renderers) { + if (w && w->isActiveWindow()) { + handle_input((HRAWINPUT) msg->lParam); + break; + } } } - } - - return true; - } else if ((msg != nullptr) && (msg->message == WM_SETTINGCHANGE) && - (((void *) msg->lParam) != nullptr) && - (wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0)) { - if (!windows_is_light_theme()) { - QFile f(":qdarkstyle/dark/darkstyle.qss"); - - if (!f.exists()) { - printf("Unable to set stylesheet, file not found\n"); - } else { - f.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&f); - qApp->setStyleSheet(ts.readAll()); - } - QTimer::singleShot(1000, [this] () { - BOOL DarkMode = TRUE; - DwmSetWindowAttribute((HWND)window->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); - window->ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api); - for (int i = 1; i < MONITORS_NUM; i++) { - if (window->renderers[i] && !window->renderers[i]->isHidden()) - window->renderers[i]->switchRenderer((RendererStack::Renderer) vid_api); - } - }); - } else { - qApp->setStyleSheet(""); - QTimer::singleShot(1000, [this] () { - BOOL DarkMode = FALSE; - DwmSetWindowAttribute((HWND)window->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode)); - }); - } - - QTimer::singleShot(1000, [this] () { - window->resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); - for (int i = 1; i < MONITORS_NUM; i++) { - if (window->renderers[i] && !window->renderers[i]->isHidden()) { - window->resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i); - } - } - }); - } - - /* Stop processing of Alt-F4 */ - if (msg->message == WM_SYSKEYDOWN) { - if (msg->wParam == 0x73) { return true; - } + case WM_SETTINGCHANGE: + if ((((void *) msg->lParam) != nullptr) && + (wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0)) { + + if (!windows_is_light_theme()) { + QFile f(":qdarkstyle/dark/darkstyle.qss"); + + if (!f.exists()) + printf("Unable to set stylesheet, file not found\n"); + else { + f.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&f); + qApp->setStyleSheet(ts.readAll()); + } + QTimer::singleShot(1000, [this] () { + BOOL DarkMode = TRUE; + auto vid_stack = (RendererStack::Renderer) vid_api; + DwmSetWindowAttribute((HWND) window->winId(), + DWMWA_USE_IMMERSIVE_DARK_MODE, + (LPCVOID) &DarkMode, + sizeof(DarkMode)); + window->ui->stackedWidget->switchRenderer(vid_stack); + for (int i = 1; i < MONITORS_NUM; i++) { + if ((window->renderers[i] != nullptr) && + !window->renderers[i]->isHidden()) + window->renderers[i]->switchRenderer(vid_stack); + } + }); + } else { + qApp->setStyleSheet(""); + QTimer::singleShot(1000, [this] () { + BOOL DarkMode = FALSE; + DwmSetWindowAttribute((HWND) window->winId(), + DWMWA_USE_IMMERSIVE_DARK_MODE, + (LPCVOID) &DarkMode, + sizeof(DarkMode)); + }); + } + + QTimer::singleShot(1000, [this] () { + window->resizeContents(monitors[0].mon_scrnsz_x, + monitors[0].mon_scrnsz_y); + for (int i = 1; i < MONITORS_NUM; i++) { + auto mon = &(monitors[i]); + + if ((window->renderers[i] != nullptr) && + !window->renderers[i]->isHidden()) + window->resizeContentsMonitor(mon->mon_scrnsz_x, + mon->mon_scrnsz_y, + i); + } + }); + } + break; + case WM_SYSKEYDOWN: + /* Stop processing of Alt-F4 */ + if (msg->wParam == 0x73) + return true; + break; + case WM_DEVICECHANGE: + if (msg->hwnd == (HWND) window->winId()) + device_change(msg->wParam, msg->lParam); + break; } } diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 38c553852..621cf0b76 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -32,9 +32,11 @@ #include #include #include +#include <86box/86box.h> #include <86box/cdrom.h> #include <86box/log.h> #include <86box/plat_cdrom_ioctl.h> +#include <86box/scsi_device.h> typedef struct ioctl_t { cdrom_t *dev; @@ -42,7 +44,6 @@ typedef struct ioctl_t { int is_dvd; int has_audio; int32_t tracks_num; - int toc_valid; uint8_t cur_toc[65536]; CDROM_READ_TOC_EX cur_read_toc_ex; int blocks_num; @@ -51,9 +52,8 @@ typedef struct ioctl_t { WCHAR path[256]; } ioctl_t; -static void ioctl_read_toc(ioctl_t *ioctl); -static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format, - uint8_t *buffer, uint32_t *info); +static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format, + uint8_t *buffer, uint32_t *info); #ifdef ENABLE_IOCTL_LOG int ioctl_do_log = ENABLE_IOCTL_LOG; @@ -94,25 +94,6 @@ ioctl_open_handle(ioctl_t *ioctl) return (ioctl->handle != INVALID_HANDLE_VALUE); } -static int -ioctl_load(ioctl_t *ioctl) -{ - int ret = 0; - - if (ioctl_open_handle(ioctl)) { - long size; - DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA, - NULL, 0, NULL, 0, - (LPDWORD) &size, NULL); - ret = 1; - ioctl_close_handle(ioctl); - - ioctl_read_toc(ioctl); - } - - return ret; -} - static int ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) { @@ -266,11 +247,8 @@ ioctl_read_raw_toc(ioctl_t *ioctl) static void ioctl_read_toc(ioctl_t *ioctl) { - if (!ioctl->toc_valid) { - ioctl->toc_valid = 1; - (void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc); - ioctl_read_raw_toc(ioctl); - } + (void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc); + ioctl_read_raw_toc(ioctl); } static int @@ -301,8 +279,6 @@ ioctl_is_track_audio(const ioctl_t *ioctl, const uint32_t pos) const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; int ret = 0; - ioctl_read_toc((ioctl_t *) ioctl); - if (ioctl->has_audio && !ioctl->is_dvd) { const int track = ioctl_get_track(ioctl, pos); const int control = rti[track].adr_ctl; @@ -324,8 +300,6 @@ ioctl_get_track_info(const void *local, const uint32_t track, const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc; int ret = 1; - ioctl_read_toc((ioctl_t *) ioctl); - if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 1))) { ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track); ret = 0; @@ -363,8 +337,6 @@ ioctl_is_track_pre(const void *local, const uint32_t sector) const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; int ret = 0; - ioctl_read_toc((ioctl_t *) ioctl); - if (ioctl->has_audio && !ioctl->is_dvd) { const int track = ioctl_get_track(ioctl, sector); const int control = rti[track].adr_ctl; @@ -572,8 +544,6 @@ ioctl_get_last_block(const void *local) const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc; uint32_t lb = 0; - ioctl_read_toc((ioctl_t *) ioctl); - 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], @@ -688,44 +658,80 @@ ioctl_has_audio(const void *local) } static int -ioctl_ext_medium_changed(void *local) +ioctl_is_empty(const void *local) { - ioctl_t * ioctl = (ioctl_t *) local; - const CDROM_TOC *toc = (CDROM_TOC *) ioctl->cur_toc; - const TRACK_DATA *ltd = &toc->TrackData[toc->LastTrack]; - const uint32_t old_addr = *(uint32_t *) ltd->Address; - const int temp = ioctl_read_normal_toc(ioctl, ioctl->cur_toc); - int ret = 0; + typedef struct SCSI_PASS_THROUGH_DIRECT_BUF { + SCSI_PASS_THROUGH_DIRECT spt; + ULONG Filler; + UCHAR SenseBuf[64]; + } SCSI_PASS_THROUGH_DIRECT_BUF; - if (temp == 1) { - if (ioctl->toc_valid && ((*(uint32_t *) ltd->Address) != old_addr)) { - /* The TOC has changed. */ - ioctl->toc_valid = 0; - ret = 1; - } + const ioctl_t * ioctl = (const ioctl_t *) local; + unsigned long int unused = 0; + SCSI_PASS_THROUGH_DIRECT_BUF req; - if (!ioctl->toc_valid) { - ioctl->toc_valid = 1; - ioctl_read_raw_toc(ioctl); - } - } else { - /* There has been some kind of error - not a medium change, but a not ready - condition. */ - ret = -1; - } + ioctl_open_handle((ioctl_t *) ioctl); - if (ret == 1) { - if (ioctl->is_dvd) - ioctl->dev->cd_status = CD_STATUS_DVD; - else - ioctl->dev->cd_status = ioctl->has_audio ? CD_STATUS_STOPPED : - CD_STATUS_DATA_ONLY; + memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF)); + req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); + req.spt.PathId = 0; + req.spt.TargetId = 1; + req.spt.Lun = 0; + req.spt.CdbLength = 12; + req.spt.DataIn = SCSI_IOCTL_DATA_IN; + req.spt.SenseInfoLength = sizeof(req.SenseBuf); + req.spt.DataTransferLength = 0; + req.spt.TimeOutValue = 6; + req.spt.DataBuffer = NULL; + req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf); - ioctl->dev->cdrom_capacity = ioctl_get_last_block(ioctl); - } else if (ret == -1) - ioctl->dev->cd_status = CD_STATUS_EMPTY; + /* Fill in the CDB. */ + req.spt.Cdb[0] = 0x00; + req.spt.Cdb[1] = 0x00; + req.spt.Cdb[2] = 0x00; + req.spt.Cdb[3] = 0x00; + req.spt.Cdb[4] = 0x00; + req.spt.Cdb[5] = 0x00; + req.spt.Cdb[6] = 0x00; + req.spt.Cdb[7] = 0x00; + req.spt.Cdb[8] = 0x00; + req.spt.Cdb[9] = 0x00; + req.spt.Cdb[10] = 0x00; + req.spt.Cdb[11] = 0x00; - ioctl_log(ioctl->log, "ioctl_ext_medium_changed(): %i\n", ret); + DWORD length = sizeof(SCSI_PASS_THROUGH_DIRECT_BUF); + +#ifdef ENABLE_IOCTL_LOG + uint8_t *cdb = (uint8_t *) req.spt.Cdb; + ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); +#endif + + int ret = DeviceIoControl(ioctl->handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, + &req, length, + &req, length, + &unused, NULL); + + ioctl_log(ioctl->log, "ioctl_read_dvd_structure(): ret = %d, " + "req.spt.DataTransferLength = %lu\n", + ret, req.spt.DataTransferLength); + ioctl_log(ioctl->log, "Sense: %08X, %08X\n", req.spt.SenseInfoLength, + req.spt.SenseInfoOffset); + + if (req.spt.SenseInfoLength >= 16) { + uint8_t *sb = (uint8_t *) req.SenseBuf; + /* Return sense to the host as is. */ + ret = ((sb[2] == SENSE_NOT_READY) && (sb[12] == ASC_MEDIUM_NOT_PRESENT)); + ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n", + sb[0], sb[1], sb[ 2], sb[ 3], sb[ 4], sb[ 5], sb[ 6], sb[ 7]); + ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n", + sb[8], sb[9], sb[10], sb[11], sb[12], sb[13], sb[14], sb[15]); + } else + ret = 0; + + ioctl_close_handle((ioctl_t *) ioctl); return ret; } @@ -744,6 +750,22 @@ ioctl_close(void *local) ioctl->log = NULL; } +static void +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); + ioctl_close_handle((ioctl_t *) ioctl); + + ioctl_read_toc((ioctl_t *) ioctl); + } +} + static const cdrom_ops_t ioctl_ops = { ioctl_get_track_info, ioctl_get_raw_track_info, @@ -754,8 +776,9 @@ static const cdrom_ops_t ioctl_ops = { ioctl_read_dvd_structure, ioctl_is_dvd, ioctl_has_audio, - ioctl_ext_medium_changed, - ioctl_close + ioctl_is_empty, + ioctl_close, + ioctl_load }; /* Public functions. */ @@ -776,7 +799,6 @@ ioctl_open(cdrom_t *dev, const char *drv) ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); ioctl->dev = dev; - ioctl->toc_valid = 0; dev->ops = &ioctl_ops; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index ff49aef90..04c6532df 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -678,8 +678,13 @@ 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); @@ -693,7 +698,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: @@ -702,6 +707,11 @@ 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; @@ -730,7 +740,19 @@ 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); - period = period * (double) (dev->packet_len); + 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; + } scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); dev->callback += period; @@ -1181,25 +1203,6 @@ scsi_cdrom_insert(void *priv) } } -static void -scsi_cdrom_ext_insert(void *priv, int ext_medium_changed) -{ - scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; - - if ((dev == NULL) || (dev->drv == NULL)) - return; - - if ((dev->drv->ops == NULL) || (ext_medium_changed == -1)) { - dev->unit_attention = 0; - dev->drv->cd_status = CD_STATUS_EMPTY; - scsi_cdrom_log(dev->log, "External media removal\n"); - } else if (ext_medium_changed == 1) { - dev->unit_attention = 0; - dev->drv->cd_status |= CD_STATUS_TRANSITION; - scsi_cdrom_log(dev->log, "External media transition\n"); - } -} - static int scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb) { @@ -1223,7 +1226,6 @@ static int scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb) { int ready; - const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv); if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { @@ -1257,9 +1259,6 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb) return 0; } - if (ext_medium_changed != 0) - scsi_cdrom_ext_insert((void *) dev, ext_medium_changed); - if ((dev->drv->cd_status == CD_STATUS_PLAYING) || (dev->drv->cd_status == CD_STATUS_PAUSED)) { ready = 1; @@ -1270,13 +1269,10 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb) if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE)) ready = 0; else { - if ((ext_medium_changed != 0) || - !(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - scsi_cdrom_log(dev->log, "(ext_medium_changed != 0): scsi_cdrom_insert()\n"); + if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) scsi_cdrom_insert((void *) dev); - } - ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1); + ready = (dev->drv->cd_status != CD_STATUS_EMPTY); } } else ready = (dev->drv->cd_status != CD_STATUS_EMPTY); @@ -1469,10 +1465,6 @@ void scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv); - - if (ext_medium_changed != 0) - scsi_cdrom_ext_insert((void *) dev, ext_medium_changed); if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) { /* diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index 9efd67ad6..bddfabb5b 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -40,7 +40,6 @@ typedef struct ioctl_t { cdrom_t *dev; void *log; - int toc_valid; void *handle; char path[256]; } ioctl_t; @@ -77,8 +76,6 @@ ioctl_open_handle(UNUSED(ioctl_t *ioctl)) static void ioctl_read_toc(ioctl_t *ioctl) { - if (!ioctl->toc_valid) - ioctl->toc_valid = 1; } /* Shared functions. */ @@ -159,6 +156,12 @@ ioctl_has_audio(UNUSED(const void *local)) return 0; } +static int +ioctl_is_empty(const void *local) +{ + return 1; +} + static int ioctl_ext_medium_changed(UNUSED(void *local)) { @@ -186,6 +189,18 @@ ioctl_close(void *local) ioctl->log = NULL; } +static void +ioctl_load(const void *local) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + + if (ioctl_open_handle((ioctl_t *) ioctl)) { + ioctl_close_handle((ioctl_t *) ioctl); + + ioctl_read_toc((ioctl_t *) ioctl); + } +} + static const cdrom_ops_t ioctl_ops = { ioctl_get_track_info, ioctl_get_raw_track_info, @@ -196,8 +211,9 @@ static const cdrom_ops_t ioctl_ops = { ioctl_read_dvd_structure, ioctl_is_dvd, ioctl_has_audio, - ioctl_ext_medium_changed, - ioctl_close + ioctl_is_empty, + ioctl_close, + ioctl_load }; /* Public functions. */ @@ -218,7 +234,6 @@ ioctl_open(cdrom_t *dev, const char *drv) ioctl_log(ioctl->log, "Path is %s\n", ioctl->path); ioctl->dev = dev; - ioctl->toc_valid = 0; dev->ops = &ioctl_ops; } From 6614a83b340527263aa9e8312b61d41cb71626d9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Feb 2025 20:28:24 +0900 Subject: [PATCH 0198/1190] correct font read address in PS/55 video mode 03 --- src/video/vid_ps55da2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index d75d0aa03..f3b7c7834 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1830,7 +1830,7 @@ static void da2_render_textm3(da2_t* da2) else { // the char code is SBCS (ANK) uint32_t fontbase; - fontbase = DA2_FONTROM_BASESBCS; + fontbase = DA2_GAIJIRAM_SBCS; uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font font <<= 8; font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font From 9aad8dbf9c6bffc313a7da8acdec297f1c58f140 Mon Sep 17 00:00:00 2001 From: The Dax Date: Wed, 5 Feb 2025 17:12:40 -0500 Subject: [PATCH 0199/1190] Add basic support for the Quantum3D Raven. AGP was worked on but found to be unstable (freezing on the first frame whenever entering Direct3D fullscreen), so it was removed. --- src/include/86box/video.h | 1 + src/video/vid_table.c | 1 + src/video/vid_voodoo_banshee.c | 38 ++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 9ee710592..336d656cc 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -575,6 +575,7 @@ extern const device_t ps1vga_mca_device; extern const device_t voodoo_device; extern const device_t voodoo_banshee_device; extern const device_t creative_voodoo_banshee_device; +extern const device_t quantum3d_raven_device; extern const device_t voodoo_3_1000_device; extern const device_t voodoo_3_1000_agp_device; extern const device_t voodoo_3_2000_device; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 9ff092161..756515734 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -193,6 +193,7 @@ video_cards[] = { { .device = &tgui9680_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &voodoo_banshee_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &creative_voodoo_banshee_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &quantum3d_raven_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &voodoo_3_1000_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &voodoo_3_2000_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &voodoo_3_3000_device, .flags = VIDEO_FLAG_TYPE_NONE }, diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index ebd92d983..36bda6cbe 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -49,6 +49,7 @@ #define ROM_BANSHEE "roms/video/voodoo/Pci_sg.rom" #define ROM_CREATIVE_BANSHEE "roms/video/voodoo/BlasterPCI.rom" +#define ROM_QUANTUM3D_RAVEN "roms/video/voodoo/RVPD0224.rom" #define ROM_VOODOO3_1000 "roms/video/voodoo/1k11sg.rom" #define ROM_VOODOO3_2000 "roms/video/voodoo/2k11sd.rom" #define ROM_VOODOO3_3000 "roms/video/voodoo/3k12sd.rom" @@ -75,6 +76,7 @@ static uint8_t vb_filter_bx_g[256][256]; enum { TYPE_BANSHEE = 0, + TYPE_QUANTUM3D_RAVEN, TYPE_V3_1000, TYPE_V3_2000, TYPE_V3_3000, @@ -3463,6 +3465,16 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int } break; + case TYPE_QUANTUM3D_RAVEN: + /* This case basically exists only to set the subsystem ID correctly for SF: Rush, a vendor-locked game. */ + /* We set the type back to TYPE_BANSHEE so the card behaves as a regular Banshee (no 3D glasses emulation). */ + banshee->pci_regs[0x2c] = 0x9c; + banshee->pci_regs[0x2d] = 0x13; + banshee->pci_regs[0x2e] = banshee->agp ? 0x16 : 0x17; + banshee->pci_regs[0x2f] = 0x00; + banshee->type = TYPE_BANSHEE; + break; + case TYPE_V3_1000: banshee->pci_regs[0x2c] = 0x1a; banshee->pci_regs[0x2d] = 0x12; @@ -3540,6 +3552,12 @@ creative_banshee_init(const device_t *info) return banshee_init_common(info, ROM_CREATIVE_BANSHEE, 0, TYPE_BANSHEE, VOODOO_BANSHEE, 0); } +static void * +quantum3d_raven_init(const device_t *info) +{ + return banshee_init_common(info, ROM_QUANTUM3D_RAVEN, 0, TYPE_QUANTUM3D_RAVEN, VOODOO_BANSHEE, 0); +} + static void * v3_1000_init(const device_t *info) { @@ -3636,6 +3654,12 @@ creative_banshee_available(void) return rom_present(ROM_CREATIVE_BANSHEE); } +static int +quantum3d_raven_available(void) +{ + return rom_present(ROM_QUANTUM3D_RAVEN); +} + static int v3_1000_available(void) { @@ -3757,6 +3781,20 @@ const device_t creative_voodoo_banshee_device = { .config = banshee_sdram_config }; +const device_t quantum3d_raven_device = { + .name = "Quantum3D Raven", + .internal_name = "q3d_raven_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = quantum3d_raven_init, + .close = banshee_close, + .reset = NULL, + .available = quantum3d_raven_available, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + const device_t voodoo_3_1000_device = { .name = "3dfx Voodoo3 1000", .internal_name = "voodoo3_1k_pci", From f12b975ebacd8e33cf0c5c29f1e0e984abbb028b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:15:18 +0900 Subject: [PATCH 0200/1190] Added support for PS/55 DA Simplified Chinese font Changed a file path for the PS/55 DA Japanese font ROM. --- src/qt/qt_settingsdisplay.cpp | 13 +++++++ src/qt/qt_settingsdisplay.hpp | 2 + src/qt/qt_settingsdisplay.ui | 9 ++++- src/video/vid_ps55da2.c | 73 ++++++++++++++++++++++++++++------- 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 42617c4be..f6be74cf2 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -139,6 +139,12 @@ SettingsDisplay::on_pushButtonConfigureXga_clicked() } } +void +SettingsDisplay::on_pushButtonConfigureDa2_clicked() +{ + DeviceConfig::ConfigureDevice(&ps55da2_device, 0, qobject_cast(Settings::settings)); +} + void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) { @@ -176,6 +182,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) ui->checkBoxDa2->setChecked(da2_standalone_enabled && machineSupportsDa2); ui->pushButtonConfigureXga->setEnabled(ui->checkBoxXga->isEnabled() && ui->checkBoxXga->isChecked()); + ui->pushButtonConfigureDa2->setEnabled(ui->checkBoxDa2->isEnabled() && ui->checkBoxDa2->isChecked()); int c = 2; @@ -250,6 +257,12 @@ SettingsDisplay::on_checkBoxXga_stateChanged(int state) ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked); } +void +SettingsDisplay::on_checkBoxDa2_stateChanged(int state) +{ + ui->pushButtonConfigureDa2->setEnabled(state == Qt::Checked); +} + void SettingsDisplay::on_comboBoxVideoSecondary_currentIndexChanged(int index) { diff --git a/src/qt/qt_settingsdisplay.hpp b/src/qt/qt_settingsdisplay.hpp index 6297f7eae..f2edb0c8a 100644 --- a/src/qt/qt_settingsdisplay.hpp +++ b/src/qt/qt_settingsdisplay.hpp @@ -30,9 +30,11 @@ private slots: private slots: void on_checkBoxVoodoo_stateChanged(int state); void on_checkBoxXga_stateChanged(int state); + void on_checkBoxDa2_stateChanged(int state); void on_comboBoxVideo_currentIndexChanged(int index); void on_pushButtonConfigureVoodoo_clicked(); void on_pushButtonConfigureXga_clicked(); + void on_pushButtonConfigureDa2_clicked(); void on_pushButtonConfigure_clicked(); private: diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index e3e081848..8be84a17f 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -113,13 +113,20 @@ - + IBM PS/55 Display Adapter Graphics + + + + Configure + + + diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f3b7c7834..a6d55c76a 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -37,8 +37,9 @@ #include <86box/vid_svga_render.h> #include "cpu.h" -#define DA2_FONTROM_PATH "roms/video/da2/PS55FNTJ.BIN" -#define DA2_FONTROM_SIZE 1024*1024 +#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" +#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" +#define DA2_FONTROM_SIZE 1536*1024 #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 @@ -54,6 +55,10 @@ #define DA2_DEBUG_BLTLOG_MAX 256*1024 #define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe +#define DA2_DCONFIG_FONT_JPAN 0 /* for Code page 932 Japanese */ +//#define DA2_DCONFIG_FONT_HANG 1 /* for Code page 934 Hangul */ +//#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ +#define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_BLT_CIDLE 0 #define DA2_BLT_CFILLRECT 1 @@ -100,7 +105,12 @@ #define OldLSI 0x20 /* DA-2 or DA-3,5 */ #define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ -/* IO 3E0/3E1:0Ah Hardware Configuration Value H (imported from OS/2 DDK) */ +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ + +/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ #define AddPage 0x08 /* ? */ #define Mon_ID2 0x04 #define Mon_ID1 0x02 @@ -110,10 +120,6 @@ //#define StarbuckM 0x09 //1001b x grayscale //#define Lark_B 0x02 //0010b IBM 9517 color 1040x768 //#define Dallas 0x0B //1011b IBM 8515, 9515 color 1040x740 B palette -/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ -#define Page_One 0x06 /* 80000h 110b */ -#define Page_Two 0x05 /* 100000h 101b */ -#define Page_Four 0x03 /* 200000h 011b */ /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -1045,6 +1051,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) 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); 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); oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) @@ -1547,7 +1555,7 @@ Bank 5 (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters - The signature 80h, 01h must be placed at Bank 0:1AFFEh to run OS/2 J1.3. + Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) [Gaiji RAM Map (DA2)] Bank 0 00000-1FFFFh placed between A0000h-BFFFFh @@ -2271,8 +2279,9 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM + //if (addr >= 0x180000) addr -= 0x40000; if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; - da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; break; default: @@ -2307,7 +2316,7 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) static uint16_t da2_mmio_readw(uint32_t addr, void* p) { da2_t* da2 = (da2_t*)p; - //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); } @@ -2962,7 +2971,7 @@ da2_reset(void* priv) da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ - /* Set default color palette (Display driver of Win 3.1 won't reset palette) */ + /* Set default color palette (Windows 3.1 display driver won't reset palette) */ da2_out(0x3c8, 0, da2); for (int i = 0; i < 256; i++) { da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); @@ -2991,7 +3000,17 @@ static void *da2_init() da2->cram = malloc(0x1000); da2->vram_display_mask = DA2_MASK_CRAM; da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h - da2_loadfont(DA2_FONTROM_PATH, da2); + + int fonttype = device_get_config_int("font"); + switch(fonttype) + { + case DA2_DCONFIG_FONT_HANT: + da2_loadfont(DA2_FONTROM_PATH_HANT, da2); + break; + case DA2_DCONFIG_FONT_JPAN: + da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + break; + } mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); @@ -3023,7 +3042,7 @@ static void *da2_init() } static int da2_available() { - return rom_present(DA2_FONTROM_PATH); + return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } void da2_close(void *p) @@ -3122,6 +3141,32 @@ void da2_force_redraw(void *p) da2->fullchange = changeframecount; } +static const device_config_t da2_configuration[] = { + // clang-format off + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "CP932 (Japanese)", + .value = DA2_DCONFIG_FONT_JPAN + }, + { + .description = "CP938 (Traditional Chinese)", + .value = DA2_DCONFIG_FONT_HANT + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t ps55da2_device = { .name = "IBM Display Adapter II (MCA)", .internal_name = "ps55da2", @@ -3133,7 +3178,7 @@ const device_t ps55da2_device = { { .available = da2_available }, .speed_changed = da2_speed_changed, .force_redraw = da2_force_redraw, - .config = NULL + .config = da2_configuration }; void From 3bfd2a6b16e19f598ef00dbd2884e5cbc1285fe3 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:20:58 +0900 Subject: [PATCH 0201/1190] Added a configuration to switch monitor types --- src/video/vid_ps55da2.c | 78 +++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a6d55c76a..6d4f43ca6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -59,6 +59,8 @@ //#define DA2_DCONFIG_FONT_HANG 1 /* for Code page 934 Hangul */ //#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ #define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_MONTYPE_COLOR 0x0A +#define DA2_DCONFIG_MONTYPE_MONO 0x09 #define DA2_BLT_CIDLE 0 #define DA2_BLT_CFILLRECT 1 @@ -102,8 +104,10 @@ | EFD8h | Display Adapter /J | | | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ +//2501 +//2500 mono #define OldLSI 0x20 /* DA-2 or DA-3,5 */ -#define Mon_ID3 0x10 +//#define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ /* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ #define Page_One 0x06 /* 80000h 110b */ @@ -112,14 +116,14 @@ /* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ #define AddPage 0x08 /* ? */ -#define Mon_ID2 0x04 -#define Mon_ID1 0x02 -#define Mon_ID0 0x01 +//#define Mon_ID2 0x04 +//#define Mon_ID1 0x02 +//#define Mon_ID0 0x01 /* Monitor ID (imported from OS/2 DDK 1.2) */ -//#define StarbuckC 0x0A //1010b IBM 8514, 9518 color 1040x768 -//#define StarbuckM 0x09 //1001b x grayscale -//#define Lark_B 0x02 //0010b IBM 9517 color 1040x768 -//#define Dallas 0x0B //1011b IBM 8515, 9515 color 1040x740 B palette +//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 +//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale +//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4pp +//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 B palette /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -400,8 +404,7 @@ typedef struct da2_t uint8_t pos_regs[8]; svga_t *mb_vga; - - //int vidsys_ena; + uint8_t monitorid; int old_pos2; } da2_t; @@ -1256,12 +1259,25 @@ uint16_t da2_in(uint16_t addr, void *p) if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ - if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrc[LV_COMPATIBILITY] & 0x08) - temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ - else - temp |= 0x80; /* Active when the RGB output voltage is lowand the cable is connected to the color monitor. - If the cable or the monitor is wrong, it becomes inactive. */ - temp &= 0xf6;//idle + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ + if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { + /* grayscale monitor */ + if ((da2->vgapal[0].r >= 10) || (da2->vgapal[0].g >= 40) || (da2->vgapal[0].b >= 10)) + temp &= 0x7F; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */ + else + temp |= 0x80; /* Active when the RGB output voltage is low and the cable is connected to a color monitor. + If the cable or the monitor is wrong, it becomes inactive. */ + } else { + /* color monitor */ + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 80) + temp &= 0x7F; + else + temp |= 0x80; + } + } else { + temp |= 0x80; + } + temp &= 0xf6;//clear busy bits if (da2->bitblt.indata) /* for OS/2 J1.3 */ da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) @@ -2959,8 +2975,9 @@ da2_reset(void* priv) da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Mon_ID3 | Page_Two; /* Configuration(Low) : DA - 2, Monitor ID 3, 1024 KB */ - da2->ioctl[LS_CONFIG2] = Mon_ID1; /* Configuration (High): Monitor ID 0-2 */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA - 2, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 2); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ da2->fctl[0] = 0x2b; /* 3E3h:0 */ da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ @@ -3000,6 +3017,7 @@ static void *da2_init() da2->cram = malloc(0x1000); da2->vram_display_mask = DA2_MASK_CRAM; da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ int fonttype = device_get_config_int("font"); switch(fonttype) @@ -3145,12 +3163,9 @@ static const device_config_t da2_configuration[] = { // clang-format off { .name = "font", - .description = "Font", + .description = "Charset", .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, + .default_int = DA2_DCONFIG_FONT_JPAN, .selection = { { .description = "CP932 (Japanese)", @@ -3163,6 +3178,23 @@ static const device_config_t da2_configuration[] = { { .description = "" } } }, + { + .name = "montype", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_int = DA2_DCONFIG_MONTYPE_COLOR, + .selection = { + { + .description = "Color", + .value = DA2_DCONFIG_MONTYPE_COLOR + }, + { + .description = "Grayscale", + .value = DA2_DCONFIG_MONTYPE_MONO + }, + { .description = "" } + } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; From ff80b57a8c826669cbfd54dcf386027ee74534d7 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Fri, 7 Feb 2025 11:47:55 +0300 Subject: [PATCH 0202/1190] Fix various errors with the machine table for 586-based machines (Part 1) --- src/machine/machine_table.c | 250 ++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bad86a786..26b42bc5b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11121,9 +11121,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 8192, - .max = 196608, - .step = 8192 + .min = 4096, + .max = 524288, + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -11156,14 +11156,14 @@ const machine_t machines[] = { .min_voltage = 3450, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 2.5 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 8192, + .min = 4096, .max = 524288, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -11201,9 +11201,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 524288, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -11246,7 +11246,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -11470,7 +11470,7 @@ const machine_t machines[] = { /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { - .name = "[i430HX] Acer M3A", + .name = "[i430HX] Acer AcerPower Ultima", .internal_name = "acerm3a", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430HX, @@ -11492,9 +11492,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal SCSI */ .ram = { - .min = 8192, - .max = 196608, - .step = 8192 + .min = 4096, + .max = 524288, + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -11523,18 +11523,18 @@ const machine_t machines[] = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, .min_bus = 50000000, - .max_bus = 83333333, + .max_bus = 75000000, .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 4.0 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 8192, - .max = 262144, - .step = 8192 + .min = 4096, + .max = 524288, + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -11567,14 +11567,14 @@ const machine_t machines[] = { .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Machine has AMB */ .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 524288, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -11603,7 +11603,7 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 50000000, + .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 2800, .max_voltage = 3520, @@ -11613,9 +11613,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { - .min = 8192, - .max = 131072, - .step = 8192 + .min = 4096, + .max = 524288, + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -11633,7 +11633,7 @@ const machine_t machines[] = { PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ { - .name = "[i430HX] Intel TC430HX", + .name = "[i430HX] Intel TC430HX (Tucson)", .internal_name = "tc430hx", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430HX, @@ -11650,14 +11650,14 @@ const machine_t machines[] = { .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, - .max = 131072, - .step = 8192 + .max = 524288, + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -11673,7 +11673,7 @@ const machine_t machines[] = { }, /* OEM version of Intel TC430HX, has AMI MegaKey KBC firmware on the PC87306 Super I/O chip. */ { - .name = "[i430HX] Toshiba Infinia 7200", + .name = "[i430HX] Toshiba Infinia 7201", .internal_name = "infinia7200", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430HX, @@ -11690,14 +11690,14 @@ const machine_t machines[] = { .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, - .max = 131072, - .step = 8192 + .max = 524288, + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -11713,7 +11713,7 @@ const machine_t machines[] = { }, /* OEM-only Intel CU430HX, has AMI MegaKey KBC firmware on the PC87306 Super I/O chip. */ { - .name = "[i430HX] Intel CU430HX", + .name = "[i430HX] Intel CU430HX (Cumberland)", .internal_name = "cu430hx", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430HX, @@ -11730,14 +11730,14 @@ const machine_t machines[] = { .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 196608, - .step = 8192 + .max = 524288, + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -11770,14 +11770,14 @@ const machine_t machines[] = { .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 196608, - .step = 8192 + .max = 524288, + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -11806,18 +11806,18 @@ const machine_t machines[] = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, .min_bus = 50000000, - .max_bus = 83333333, + .max_bus = 66666667, .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 8192, - .max = 262144, - .step = 8192 + .min = 4096, + .max = 524288, + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -11859,8 +11859,8 @@ const machine_t machines[] = { .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, - .max = 196608, - .step = 8192 + .max = 524288, + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -11899,9 +11899,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, - .max = 786432, - .step = 8192 + .min = 4096, + .max = 524288, + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -11941,9 +11941,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -11976,14 +11976,14 @@ const machine_t machines[] = { .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Machine has AMB */ .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -12017,14 +12017,14 @@ const machine_t machines[] = { .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -12062,9 +12062,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -12081,7 +12081,7 @@ const machine_t machines[] = { /* Has a SM(S)C FDC37C932QF Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ { - .name = "[i430VX] Compaq Presario 2240", + .name = "[i430VX] Compaq Presario 224x", .internal_name = "presario2240", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430VX, @@ -12093,19 +12093,19 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 50000000, + .min_bus = 66666667, .max_bus = 66666667, .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, .ram = { - .min = 8192, - .max = 131072, - .step = 8192 + .min = 16384, + .max = 49152, + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12122,7 +12122,7 @@ const machine_t machines[] = { /* Has a SM(S)C FDC37C931APM Super I/O chip with on-chip KBC with Compaq KBC firmware. */ { - .name = "[i430VX] Compaq Presario 4500", + .name = "[i430VX] Compaq Presario 45xx", .internal_name = "presario4500", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430VX, @@ -12134,19 +12134,19 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 50000000, + .min_bus = 66666667, .max_bus = 66666667, .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, .ram = { - .min = 8192, - .max = 131072, - .step = 8192 + .min = 16384, + .max = 49152, + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12163,7 +12163,7 @@ const machine_t machines[] = { /* Has a SM(S)C FDC37C932FR Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ { - .name = "[i430VX] Dell Hannibal+", + .name = "[i430VX] Dell Dimension XPS Pxxxa/Mxxxa", .internal_name = "dellhannibalp", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430VX, @@ -12180,14 +12180,14 @@ const machine_t machines[] = { .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12225,9 +12225,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -12257,7 +12257,7 @@ const machine_t machines[] = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, .min_bus = 50000000, - .max_bus = 66666667, + .max_bus = 75000000, .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, @@ -12266,9 +12266,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12309,7 +12309,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12343,14 +12343,14 @@ const machine_t machines[] = { .min_voltage = 2200, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 16384, + .min = 8192, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12368,7 +12368,7 @@ const machine_t machines[] = { PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ { - .name = "[i430VX] Packard Bell PB680", + .name = "[i430VX] Packard Bell Multimedia C110", .internal_name = "pb680", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430VX, @@ -12392,7 +12392,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -12409,7 +12409,7 @@ const machine_t machines[] = { /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { - .name = "[i430VX] Packard Bell PB810", + .name = "[i430VX] Packard Bell Multimedia M415", .internal_name = "pb810", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430VX, @@ -12426,14 +12426,14 @@ const machine_t machines[] = { .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 4.0 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 511, .kbc_device = NULL, @@ -12467,14 +12467,14 @@ const machine_t machines[] = { .min_voltage = 2600, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -12513,9 +12513,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 131072, - .step = 8192 + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, @@ -12590,7 +12590,7 @@ const machine_t machines[] = { .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, @@ -12613,7 +12613,7 @@ const machine_t machines[] = { }, /* [TEST] Has AMI Megakey '5' KBC firmware on the SM(S)C FDC37C67x Super I/O chip. */ { - .name = "[i430TX] Gateway Tomahawk", + .name = "[i430TX] Gateway E-1000", .internal_name = "tomahawk", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, @@ -12625,12 +12625,12 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 50000000, + .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 2100, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_NIC | MACHINE_USB, @@ -12654,7 +12654,7 @@ const machine_t machines[] = { #ifdef USE_AN430TX /* This has the Phoenix MultiKey KBC firmware. */ { - .name = "[i430TX] Intel AN430TX", + .name = "[i430TX] Intel AN430TX (Anchorage)", .internal_name = "an430tx", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, @@ -12671,7 +12671,7 @@ const machine_t machines[] = { .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, @@ -12695,7 +12695,7 @@ const machine_t machines[] = { #endif /* USE_AN430TX */ /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ { - .name = "[i430TX] Intel YM430TX", + .name = "[i430TX] Intel YM430TX (Yamamoto)", .internal_name = "ym430tx", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, @@ -12712,14 +12712,14 @@ const machine_t machines[] = { .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 262144, - .step = 8192 + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -12733,7 +12733,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* PhoenixBIOS 4.0 Rel 6.0 for 430TX, most likely has AMI KBC of some sort. Also has onboard Yamaha YMF701 which can't be emulated yet. */ + /* PhoenixBIOS 4.0 Rel 6.0 for 430TX, has onboard Yamaha YMF701 which is not emulated yet. */ /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { @@ -12749,12 +12749,12 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2), - .min_bus = 50000000, + .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 2500, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Yamaha YMF701-S */ @@ -12795,13 +12795,13 @@ const machine_t machines[] = { .min_voltage = 2700, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, - .max = 786432, + .max = 262144, .step = 8192 }, .nvrmask = 255, @@ -12836,14 +12836,14 @@ const machine_t machines[] = { .min_voltage = 2700, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 262144, - .step = 8192 + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -12871,8 +12871,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 55000000, - .max_bus = 75000000, + .min_bus = 60000000, + .max_bus = 66666667, .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, @@ -12881,9 +12881,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 262144, - .step = 8192 + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -12912,18 +12912,18 @@ const machine_t machines[] = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, .min_bus = 50000000, - .max_bus = 66666667, + .max_bus = 75000000, .min_voltage = 2100, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { - .min = 8192, + .min = 4096, .max = 262144, - .step = 8192 + .step = 4096 }, .nvrmask = 255, .kbc_device = NULL, @@ -12939,7 +12939,7 @@ const machine_t machines[] = { }, /* [TEST] Has AMIKey 'H' KBC firmware. */ { - .name = "[i430TX] TriGem Richmond", + .name = "[i430TX] TriGem RD535 (Richmond)", .internal_name = "richmond", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, @@ -12951,12 +12951,12 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 50000000, + .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 2100, .max_voltage = 3520, .min_multi = 1.5, - .max_multi = 3.0 + .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, @@ -13108,7 +13108,7 @@ const machine_t machines[] = { /* SiS 5571 */ /* Has the SiS 5571 chipset with on-chip KBC. */ { - .name = "[SiS 5571] Daewoo CB52X-SI", + .name = "[SiS 5571] Daewoo CD520", .internal_name = "cb52xsi", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_SIS_5571, From 34e3f6e8496296975dc8249f6ed2e2ea1835b95a Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 7 Feb 2025 23:34:12 +0100 Subject: [PATCH 0203/1190] No longer list Socket 8 CPU's for Slot 1 machines, closes #5196. --- src/cpu/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 0802fa3ac..808f603b5 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -372,7 +372,7 @@ cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine) if (packages & CPU_PKG_SOCKET3) packages |= CPU_PKG_SOCKET1; else if (packages & CPU_PKG_SLOT1) - packages |= CPU_PKG_SOCKET370 | CPU_PKG_SOCKET8; + packages |= CPU_PKG_SOCKET370; /* Package type. */ if (!(cpu_family->package & packages)) From bc5d2a425e9748a358c3ab7cf45d9a4070c9dc8a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 7 Feb 2025 20:27:49 -0300 Subject: [PATCH 0204/1190] CS423x: Finish implementing the missing chip types --- src/sound/snd_cs423x.c | 95 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 18 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index a7aa04718..4e65c3810 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -90,13 +90,13 @@ static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0 0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2, 0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13, 0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A }; -static const uint8_t cs4236b_default[] = { +static const uint8_t cs4236_default[] = { // clang-format off /* Chip configuration */ 0x00, 0x03, /* CD-ROM and modem decode */ 0x80, /* misc. config */ 0x80, /* global config */ - 0x0b, /* chip ID */ + 0x0b, /* [code base byte (CS4236B+)] / reserved (CS4236) */ 0x20, 0x04, 0x08, 0x10, 0x80, 0x00, 0x00, /* reserved */ 0x00, /* external decode length */ 0x48, /* reserved */ @@ -104,7 +104,7 @@ static const uint8_t cs4236b_default[] = { 0x10, 0x03, /* DMA routing */ /* Default PnP data */ - 0x0e, 0x63, 0x42, 0x35, 0xff, 0xff, 0xff, 0xff, 0x00 /* hinted by documentation to be just the header */ + 0x0e, 0x63, 0x42, 0x36, 0xff, 0xff, 0xff, 0xff, 0x00 /* hinted by documentation to be just the header */ // clang-format on }; @@ -800,6 +800,47 @@ cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv } } +static void +cs423x_load_defaults(cs423x_t *dev, uint8_t *dest) +{ + switch (dev->type) { + case CRYSTAL_CS4236: + case CRYSTAL_CS4236B: + case CRYSTAL_CS4237B: + case CRYSTAL_CS4238B: + case CRYSTAL_CS4235: + case CRYSTAL_CS4239: + memcpy(dest, cs4236_default, sizeof(cs4236_default)); + dev->pnp_size = 9; /* header-only PnP ROM size */ + + switch (dev->type) { + case CRYSTAL_CS4236: + dest[4] = 0x43; /* code base byte */ + break; + + case CRYSTAL_CS4236B: + dest[22] = 0x35; /* default PnP ID */ + break; + + case CRYSTAL_CS4237B: + dest[22] = 0x37; /* default PnP ID */ + break; + + case CRYSTAL_CS4238B: + dest[22] = 0x38; /* default PnP ID */ + break; + + case CRYSTAL_CS4235: + case CRYSTAL_CS4239: + dest[4] = 0x05; /* code base byte */ + dest[12] = 0x08; /* external decode length */ + dest[22] = 0x36; /* default PnP ID - explicitly stated to be the CS4236 non-B one */ + break; + } + break; + } +} + static void cs423x_reset(void *priv) { @@ -809,8 +850,7 @@ cs423x_reset(void *priv) memset(dev->ram_data, 0, sizeof(dev->ram_data)); /* Load default configuration data to RAM. */ - memcpy(&dev->ram_data[0x4000], cs4236b_default, sizeof(cs4236b_default)); - dev->pnp_size = 9; + cs423x_load_defaults(dev, &dev->ram_data[0x4000]); if (dev->eeprom) { /* Load EEPROM data to RAM if the magic bytes are present. */ @@ -858,21 +898,22 @@ cs423x_init(const device_t *info) dev->type = info->local & 0xff; cs423x_log("CS423x: init(%02X)\n", dev->type); switch (dev->type) { + case CRYSTAL_CS4236: case CRYSTAL_CS4236B: case CRYSTAL_CS4237B: case CRYSTAL_CS4238B: case CRYSTAL_CS4235: case CRYSTAL_CS4239: /* Same WSS codec and EEPROM structure. */ - dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236B; + dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : ((dev->type >= CRYSTAL_CS4236B) ? AD1848_TYPE_CS4236B : AD1848_TYPE_CS4236); dev->pnp_offset = 0x4013; - /* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init. */ + /* Different Chip Version and ID registers (N/A on CS4236), which shouldn't be reset by ad1848_init. */ dev->ad1848.xregs[25] = dev->type; if (!(info->local & CRYSTAL_NOEEPROM)) { - /* Copy default configuration data. */ - memcpy(&dev->eeprom_data[4], cs4236b_default, sizeof(cs4236b_default)); + /* Start a new EEPROM with the default configuration data. */ + cs423x_load_defaults(dev, &dev->eeprom_data[4]); /* Load PnP resource data ROM. */ FILE *fp = rom_fopen(PNP_ROM_CS4236B, "rb"); @@ -883,6 +924,8 @@ cs423x_init(const device_t *info) with pretending the whole ROM is PnP data, at least until we can get full EEPROM dumps. */ dev->pnp_size = fread(&dev->eeprom_data[eeprom_pnp_offset], 1, sizeof(dev->eeprom_data) - eeprom_pnp_offset, fp); fclose(fp); + } else { + dev->pnp_size = 0; } /* Populate EEPROM header if the PnP ROM was loaded. */ @@ -895,14 +938,12 @@ cs423x_init(const device_t *info) /* Patch PnP ROM and set EEPROM file name. */ switch (dev->type) { - case CRYSTAL_CS4235: + case CRYSTAL_CS4236: if (dev->pnp_size) { - dev->eeprom_data[8] = 0x05; - dev->eeprom_data[16] = 0x08; - dev->eeprom_data[26] = 0x25; - dev->eeprom_data[44] = '5'; + dev->eeprom_data[26] = 0x36; + dev->eeprom_data[45] = ' '; } - dev->nvr_path = "cs4235.nvr"; + dev->nvr_path = "cs4236.nvr"; break; case CRYSTAL_CS4236B: @@ -914,7 +955,7 @@ cs423x_init(const device_t *info) dev->eeprom_data[26] = 0x37; dev->eeprom_data[44] = '7'; } - dev->nvr_path = "cs4237b.nvr"; + dev->nvr_path = "cs4237b.nvr"; break; case CRYSTAL_CS4238B: @@ -922,7 +963,25 @@ cs423x_init(const device_t *info) dev->eeprom_data[26] = 0x38; dev->eeprom_data[44] = '8'; } - dev->nvr_path = "cs4238b.nvr"; + dev->nvr_path = "cs4238b.nvr"; + break; + + case CRYSTAL_CS4235: + if (dev->pnp_size) { + dev->eeprom_data[26] = 0x25; + dev->eeprom_data[44] = '5'; + dev->eeprom_data[45] = ' '; + } + dev->nvr_path = "cs4235.nvr"; + break; + + case CRYSTAL_CS4239: + if (dev->pnp_size) { + dev->eeprom_data[26] = 0x29; + dev->eeprom_data[44] = '9'; + dev->eeprom_data[45] = ' '; + } + dev->nvr_path = "cs4239.nvr"; break; default: @@ -935,7 +994,7 @@ cs423x_init(const device_t *info) /* Initialize game port. The game port on all B chips only responds to 6 I/O ports; the remaining 2 are reserved. */ - dev->gameport = gameport_add((dev->type == CRYSTAL_CS4235) ? &gameport_pnp_device : &gameport_pnp_6io_device); + dev->gameport = gameport_add((dev->ad1848_type == CRYSTAL_CS4236B) ? &gameport_pnp_6io_device : &gameport_pnp_device); break; From b7f79750549274b5c2c8fe27178911d121937789 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 7 Feb 2025 20:44:21 -0300 Subject: [PATCH 0205/1190] CS423x: Add on-board CS4236 to the VS440FX --- src/include/86box/sound.h | 1 + src/machine/m_at_socket8.c | 6 ++++++ src/machine/machine_table.c | 8 ++++---- src/sound/snd_cs423x.c | 16 +++++++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 645d974dd..ba6ac2f83 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -170,6 +170,7 @@ extern const device_t sb_awe64_gold_device; /* Crystal CS423x */ extern const device_t cs4235_device; extern const device_t cs4235_onboard_device; +extern const device_t cs4236_onboard_device; extern const device_t cs4236b_device; extern const device_t cs4237b_device; extern const device_t cs4238b_device; diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index e6f78f6a2..935a26fb2 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -256,6 +256,9 @@ machine_at_vs440fx_init(const machine_t *model) device_add(&intel_flash_bxt_ami_device); + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + return ret; } @@ -290,6 +293,9 @@ machine_at_gw2kvenus_init(const machine_t *model) device_add(&intel_flash_bxt_ami_device); + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 26b42bc5b..82b0082fe 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14072,7 +14072,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14087,7 +14087,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cs4236_onboard_device, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ @@ -14196,7 +14196,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14211,7 +14211,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cs4236_onboard_device, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 4e65c3810..bef57d992 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -259,7 +259,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv) break; case 3: /* Control Indirect Access Register (CS4236B+) */ - if (dev->type < CRYSTAL_CS4236B) + if (dev->type < CRYSTAL_CS4236) /* must be writable on CS4236 for the aforementioned VS440FX BIOS check */ return; val &= 0x0f; break; @@ -1089,6 +1089,20 @@ const device_t cs4235_onboard_device = { .config = NULL }; +const device_t cs4236_onboard_device = { + .name = "Crystal CS4236 (On-Board)", + .internal_name = "cs4236_onboard", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4236 | CRYSTAL_NOEEPROM, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + .available = cs423x_available, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + const device_t cs4236b_device = { .name = "Crystal CS4236B", .internal_name = "cs4236b", From 34fbecb377a303c58872b50ac9650d93afa63339 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Feb 2025 00:06:54 -0300 Subject: [PATCH 0206/1190] CS423x: Add proper on-board CS4236B to the Intel AP440FX Default PnP ID patches have been removed as the AP440FX BIOS confirms the CSC4236 ID never changed (as later documented on CS4235/9) --- src/include/86box/sound.h | 1 + src/machine/machine_table.c | 2 +- src/sound/snd_cs423x.c | 33 ++++++++++++++++++--------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index ba6ac2f83..a30095c66 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -172,6 +172,7 @@ extern const device_t cs4235_device; extern const device_t cs4235_onboard_device; extern const device_t cs4236_onboard_device; extern const device_t cs4236b_device; +extern const device_t cs4236b_onboard_device; extern const device_t cs4237b_device; extern const device_t cs4238b_device; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 82b0082fe..febdc0e0c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14169,7 +14169,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = &s3_virge_325_onboard_pci_device, - .snd_device = &cs4236b_device, + .snd_device = &cs4236b_onboard_device, .net_device = NULL }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index bef57d992..f6ded130a 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -818,23 +818,10 @@ cs423x_load_defaults(cs423x_t *dev, uint8_t *dest) dest[4] = 0x43; /* code base byte */ break; - case CRYSTAL_CS4236B: - dest[22] = 0x35; /* default PnP ID */ - break; - - case CRYSTAL_CS4237B: - dest[22] = 0x37; /* default PnP ID */ - break; - - case CRYSTAL_CS4238B: - dest[22] = 0x38; /* default PnP ID */ - break; - case CRYSTAL_CS4235: case CRYSTAL_CS4239: dest[4] = 0x05; /* code base byte */ dest[12] = 0x08; /* external decode length */ - dest[22] = 0x36; /* default PnP ID - explicitly stated to be the CS4236 non-B one */ break; } break; @@ -904,13 +891,15 @@ cs423x_init(const device_t *info) case CRYSTAL_CS4238B: case CRYSTAL_CS4235: case CRYSTAL_CS4239: - /* Same WSS codec and EEPROM structure. */ + /* Different WSS codec families. */ dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : ((dev->type >= CRYSTAL_CS4236B) ? AD1848_TYPE_CS4236B : AD1848_TYPE_CS4236); - dev->pnp_offset = 0x4013; /* Different Chip Version and ID registers (N/A on CS4236), which shouldn't be reset by ad1848_init. */ dev->ad1848.xregs[25] = dev->type; + /* Same EEPROM structure. */ + dev->pnp_offset = 0x4013; + if (!(info->local & CRYSTAL_NOEEPROM)) { /* Start a new EEPROM with the default configuration data. */ cs423x_load_defaults(dev, &dev->eeprom_data[4]); @@ -1117,6 +1106,20 @@ const device_t cs4236b_device = { .config = NULL }; +const device_t cs4236b_onboard_device = { + .name = "Crystal CS4236B", + .internal_name = "cs4236b", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4236B | CRYSTAL_NOEEPROM, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + .available = cs423x_available, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + const device_t cs4237b_device = { .name = "Crystal CS4237B", .internal_name = "cs4237b", From 5b894c32e6f516f62223d9e24a721a830eb41304 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 1 Feb 2025 03:29:03 -0500 Subject: [PATCH 0207/1190] Macro Cleaning --- src/codegen_new/codegen.c | 3 +- src/codegen_new/codegen_accumulate.c | 3 +- src/codegen_new/codegen_ops_3dnow.c | 45 +- src/codegen_new/codegen_ops_branch.c | 85 ++-- src/codegen_new/codegen_ops_fpu_arith.c | 528 ++++++++++----------- src/codegen_new/codegen_ops_misc.c | 92 ++-- src/codegen_new/codegen_ops_mmx_arith.c | 43 +- src/codegen_new/codegen_ops_mmx_cmp.c | 43 +- src/codegen_new/codegen_ops_mmx_pack.c | 43 +- src/codegen_new/codegen_ops_stack.c | 110 ++--- src/video/CMakeLists.txt | 96 +++- src/video/vid_8514a.c | 259 ++++++----- src/video/vid_ati_mach64.c | 66 +-- src/video/vid_ati_mach8.c | 414 +++++++++-------- src/video/vid_cga_comp.c | 32 +- src/video/vid_et4000.c | 4 +- src/video/vid_mga.c | 21 +- src/video/vid_paradise.c | 2 +- src/video/vid_s3.c | 34 +- src/video/vid_s3_virge.c | 586 ++++++++++++------------ src/video/vid_tgui9440.c | 29 +- src/video/vid_voodoo_banshee.c | 40 +- src/video/vid_voodoo_render.c | 16 +- src/video/vid_voodoo_setup.c | 4 +- src/video/vid_voodoo_texture.c | 8 +- src/video/vid_xga.c | 14 +- 26 files changed, 1384 insertions(+), 1236 deletions(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index a3f4ede8f..39ab69b3d 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -21,8 +21,7 @@ #define MAX_INSTRUCTION_COUNT 50 -static struct -{ +static struct { uint32_t pc; int op_ssegs; x86seg *op_ea_seg; diff --git a/src/codegen_new/codegen_accumulate.c b/src/codegen_new/codegen_accumulate.c index 29b05ad77..087d9c797 100644 --- a/src/codegen_new/codegen_accumulate.c +++ b/src/codegen_new/codegen_accumulate.c @@ -8,8 +8,7 @@ #include "codegen_accumulate.h" #include "codegen_ir.h" -static struct -{ +static struct { int count; int dest_reg; } acc_regs[] = { diff --git a/src/codegen_new/codegen_ops_3dnow.c b/src/codegen_new/codegen_ops_3dnow.c index 03af718d1..e827d0d27 100644 --- a/src/codegen_new/codegen_ops_3dnow.c +++ b/src/codegen_new/codegen_ops_3dnow.c @@ -16,28 +16,29 @@ #include "codegen_ops_3dnow.h" #include "codegen_ops_helpers.h" -#define ropParith(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) { \ - int src_reg = fetchdat & 7; \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } else { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - codegen_mark_code_present(block, cs + op_pc + 1, 1); \ - return op_pc + 2; \ +#define ropParith(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + codegen_mark_code_present(block, cs + op_pc + 1, 1); \ + return op_pc + 2; \ } // clang-format off diff --git a/src/codegen_new/codegen_ops_branch.c b/src/codegen_new/codegen_ops_branch.c index 1e2589f8b..2039b6d79 100644 --- a/src/codegen_new/codegen_ops_branch.c +++ b/src/codegen_new/codegen_ops_branch.c @@ -815,41 +815,56 @@ ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t n } } -#define ropJ(cond) \ - uint32_t ropJ##cond##_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), uint32_t op_32, uint32_t op_pc) \ - { \ - uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); \ - uint32_t dest_addr = op_pc + 1 + offset; \ - int ret; \ - \ - if (!(op_32 & 0x100)) \ - dest_addr &= 0xffff; \ - ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 1); \ - \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - return ret ? dest_addr : (op_pc + 1); \ - } \ - uint32_t ropJ##cond##_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ - { \ - uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); \ - uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ - int ret; \ - \ - ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 2); \ - \ - codegen_mark_code_present(block, cs + op_pc, 2); \ - return ret ? dest_addr : (op_pc + 2); \ - } \ - uint32_t ropJ##cond##_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ - { \ - uint32_t offset = fastreadl(cs + op_pc); \ - uint32_t dest_addr = op_pc + 4 + offset; \ - int ret; \ - \ - ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 4); \ - \ - codegen_mark_code_present(block, cs + op_pc, 4); \ - return ret ? dest_addr : (op_pc + 4); \ +#define ropJ(cond) \ + uint32_t ropJ##cond##_8(codeblock_t *block, \ + ir_data_t *ir, \ + UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + uint32_t op_32, \ + uint32_t op_pc) \ + { \ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); \ + uint32_t dest_addr = op_pc + 1 + offset; \ + int ret; \ + \ + if (!(op_32 & 0x100)) \ + dest_addr &= 0xffff; \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 1); \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + return ret ? dest_addr : (op_pc + 1); \ + } \ + uint32_t ropJ##cond##_16(codeblock_t *block, \ + ir_data_t *ir, \ + UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc) \ + { \ + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); \ + uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ + int ret; \ + \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 2); \ + \ + codegen_mark_code_present(block, cs + op_pc, 2); \ + return ret ? dest_addr : (op_pc + 2); \ + } \ + uint32_t ropJ##cond##_32(codeblock_t *block, \ + ir_data_t *ir, \ + UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), \ + UNUSED(uint32_t op_32), \ + uint32_t op_pc) \ + { \ + uint32_t offset = fastreadl(cs + op_pc); \ + uint32_t dest_addr = op_pc + 4 + offset; \ + int ret; \ + \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 4); \ + \ + codegen_mark_code_present(block, cs + op_pc, 4); \ + return ret ? dest_addr : (op_pc + 4); \ } // clang-format off diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c index 43d243c0f..1568852df 100644 --- a/src/codegen_new/codegen_ops_fpu_arith.c +++ b/src/codegen_new/codegen_ops_fpu_arith.c @@ -300,131 +300,139 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uin return op_pc; } -#define ropF_arith_mem(name, load_uop) \ - uint32_t ropFADD##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - if ((cpu_state.npxc >> 10) & 3) \ - return 0; \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFCOM##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFCOMP##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(block, ir); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFDIV##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFDIVR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFMUL##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFSUB##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFSUBR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ +#define ropF_arith_mem(name, load_uop) \ + uint32_t ropFADD##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + if ((cpu_state.npxc >> 10) & 3) \ + return 0; \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFCOM##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFCOMP##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(block, ir); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFDIV##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFDIVR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFMUL##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFSUB##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFSUBR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ } // clang-format off @@ -432,137 +440,145 @@ ropF_arith_mem(s, uop_MEM_LOAD_SINGLE) ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) // clang-format on -#define ropFI_arith_mem(name, temp_reg) \ - uint32_t ropFIADD##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFICOM##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFICOMP##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(block, ir); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFIDIV##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFIDIVR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFIMUL##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFISUB##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ - } \ - uint32_t ropFISUBR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc + 1; \ +#define ropFI_arith_mem(name, temp_reg) \ + uint32_t ropFIADD##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFICOM##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFICOMP##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(block, ir); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIDIV##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIDIVR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIMUL##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFISUB##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFISUBR##name(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ } // clang-format off diff --git a/src/codegen_new/codegen_ops_misc.c b/src/codegen_new/codegen_ops_misc.c index c709dffc9..91e0f5d63 100644 --- a/src/codegen_new/codegen_ops_misc.c +++ b/src/codegen_new/codegen_ops_misc.c @@ -519,57 +519,61 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSE return op_pc; } -#define ropLxS(name, seg) \ - uint32_t rop##name##_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg = NULL; \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ - uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ - uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ - \ - if (seg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); \ - \ - return op_pc + 1; \ - } \ - uint32_t rop##name##_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - x86seg *target_seg = NULL; \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ - uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ - uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ - \ - if (seg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); \ - \ - return op_pc + 1; \ +#define ropLxS(name, seg) \ + uint32_t rop##name##_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ + } \ + uint32_t rop##name##_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ } +// clang-format off ropLxS(LDS, &cpu_state.seg_ds) ropLxS(LES, &cpu_state.seg_es) ropLxS(LFS, &cpu_state.seg_fs) ropLxS(LGS, &cpu_state.seg_gs) ropLxS(LSS, &cpu_state.seg_ss) +// clang-format on uint32_t ropCLC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index 8fd1d1651..f01d64273 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -16,27 +16,28 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" -#define ropParith(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) { \ - int src_reg = fetchdat & 7; \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } else { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ +#define ropParith(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ } // clang-format off diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index e00e56472..cf0cededb 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -16,27 +16,28 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" -#define ropPcmp(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) { \ - int src_reg = fetchdat & 7; \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } else { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ +#define ropPcmp(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ } // clang-format off diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index 18377e142..c62aa10d0 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -16,27 +16,28 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" -#define ropPpack(func) \ - uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ - { \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs + op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) { \ - int src_reg = fetchdat & 7; \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } else { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ +#define ropPpack(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ + uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ } // clang-format off diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index 057cccb0f..fca9c9efa 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -196,61 +196,65 @@ ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet return op_pc + 1; } -#define ROP_PUSH_SEG(seg) \ - uint32_t ropPUSH_##seg##_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ - { \ - int sp_reg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_##seg##_seg_W); \ - SUB_SP(ir, 2); \ - \ - return op_pc; \ - } \ - uint32_t ropPUSH_##seg##_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ - { \ - int sp_reg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ - uop_MOVZX(ir, IREG_temp0, IREG_##seg##_seg_W); \ - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ - SUB_SP(ir, 4); \ - \ - return op_pc; \ +#define ROP_PUSH_SEG(seg) \ + uint32_t ropPUSH_##seg##_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ + { \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_##seg##_seg_W); \ + SUB_SP(ir, 2); \ + \ + return op_pc; \ + } \ + uint32_t ropPUSH_##seg##_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ + { \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ + uop_MOVZX(ir, IREG_temp0, IREG_##seg##_seg_W); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ + SUB_SP(ir, 4); \ + \ + return op_pc; \ } -#define ROP_POP_SEG(seg, rseg) \ - uint32_t ropPOP_##seg##_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ - { \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - \ - if (stack32) \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ - else { \ - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ - } \ - uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ - ADD_SP(ir, 2); \ - \ - return op_pc; \ - } \ - uint32_t ropPOP_##seg##_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ - { \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - \ - if (stack32) \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ - else { \ - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ - } \ - uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ - ADD_SP(ir, 4); \ - \ - return op_pc; \ +#define ROP_POP_SEG(seg, rseg) \ + uint32_t ropPOP_##seg##_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ + { \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 2); \ + \ + return op_pc; \ + } \ + uint32_t ropPOP_##seg##_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), \ + UNUSED(uint32_t fetchdat), UNUSED(uint32_t op_32), uint32_t op_pc) \ + { \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 4); \ + \ + return op_pc; \ } // clang-format off diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 3d8e14c5e..41566bf3e 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -13,23 +13,72 @@ # Copyright 2020-2021 David Hrdlička. # -add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c - vid_compaq_cga.c vid_mda.c vid_hercules.c vid_herculesplus.c - vid_incolor.c vid_colorplus.c vid_genius.c vid_pgc.c vid_im1024.c - vid_sigma.c vid_wy700.c vid_ega.c vid_ega_render.c vid_svga.c vid_8514a.c - vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c - vid_ati28800.c vid_ati_mach8.c vid_ati_mach64.c vid_ati68875_ramdac.c - vid_ati68860_ramdac.c vid_bt481_ramdac.c vid_bt48x_ramdac.c vid_chips_69000.c - vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c - vid_et3000.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c - vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c - vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c - vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c - vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c - vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c +add_library(vid OBJECT + agpgart.c + video.c + vid_table.c + vid_cga.c + vid_cga_comp.c + vid_compaq_cga.c + vid_mda.c + vid_hercules.c + vid_herculesplus.c + vid_incolor.c + vid_colorplus.c + vid_genius.c + vid_pgc.c + vid_im1024.c + vid_sigma.c + vid_wy700.c + vid_ega.c + vid_ega_render.c + vid_svga.c + vid_8514a.c + vid_svga_render.c + vid_ddc.c + vid_vga.c + vid_ati_eeprom.c + vid_ati18800.c + vid_ati28800.c + vid_ati_mach8.c + vid_ati_mach64.c + vid_ati68875_ramdac.c + vid_ati68860_ramdac.c + vid_bt481_ramdac.c + vid_bt48x_ramdac.c + vid_chips_69000.c + vid_av9194.c + vid_icd2061.c + vid_ics2494.c + vid_ics2595.c + vid_cl54xx.c + vid_et3000.c + vid_et4000.c + vid_sc1148x_ramdac.c + vid_sc1502x_ramdac.c + vid_et4000w32.c + vid_stg_ramdac.c + vid_ht216.c + vid_oak_oti.c + vid_paradise.c + vid_rtg310x.c + vid_f82c425.c + vid_ti_cf62011.c + vid_tvga.c vid_tgui9440.c + vid_tkd8001_ramdac.c + vid_att20c49x_ramdac.c + vid_s3.c vid_s3_virge.c + vid_ibm_rgb528_ramdac.c + vid_sdac_ramdac.c + vid_ogc.c + vid_mga.c + vid_nga.c + vid_tvp3026_ramdac.c + vid_att2xc498_ramdac.c + vid_xga.c vid_bochs_vbe.c nv/nv_rivatimer.c - ) +) if(G100) target_compile_definitions(vid PRIVATE USE_G100) @@ -39,10 +88,19 @@ if(XL24) target_compile_definitions(vid PRIVATE USE_XL24) endif() -add_library(voodoo OBJECT vid_voodoo.c vid_voodoo_banshee.c - vid_voodoo_banshee_blitter.c vid_voodoo_blitter.c vid_voodoo_display.c - vid_voodoo_fb.c vid_voodoo_fifo.c vid_voodoo_reg.c vid_voodoo_render.c - vid_voodoo_setup.c vid_voodoo_texture.c) +add_library(voodoo OBJECT + vid_voodoo.c + vid_voodoo_banshee.c + vid_voodoo_banshee_blitter.c + vid_voodoo_blitter.c + vid_voodoo_display.c + vid_voodoo_fb.c + vid_voodoo_fifo.c + vid_voodoo_reg.c + vid_voodoo_render.c + vid_voodoo_setup.c + vid_voodoo_texture.c +) if(NOT MSVC AND (ARCH STREQUAL "i386" OR ARCH STREQUAL "x86_64")) target_compile_options(voodoo PRIVATE "-msse2") diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 1c81e8166..73abfe1ed 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -47,7 +47,6 @@ # undef CLAMP #endif - #define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140_4k.BIN" static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); @@ -84,14 +83,14 @@ CLAMP(int16_t in, int16_t min, int16_t max) return in; } -#define WRITE8(addr, var, val) \ - switch ((addr) & 1) { \ - case 0: \ - var = (var & 0xff00) | (val); \ - break; \ - case 1: \ - var = (var & 0x00ff) | ((val) << 8); \ - break; \ +#define WRITE8(addr, var, val) \ + switch ((addr) & 1) { \ + case 0: \ + var = (var & 0xff00) | (val); \ + break; \ + case 1: \ + var = (var & 0x00ff) | ((val) << 8); \ + break; \ } #define READ8(addr, var) \ @@ -105,139 +104,139 @@ CLAMP(int16_t in, int16_t min, int16_t max) } -#define READ_PIXTRANS_WORD(cx, n) \ - if ((cmd <= 1) || (cmd == 5)) { \ +#define READ_PIXTRANS_WORD(cx, n) \ + if ((cmd <= 1) || (cmd == 5)) { \ 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 { \ - temp = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ - temp |= (dev->vram[(dev->accel.dest + (cx) + (n + 1)) & dev->vram_mask] << 8); \ - } \ + } else { \ + temp = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[(dev->accel.dest + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ -#define READ(addr, dat) \ - if (dev->bpp) \ +#define READ(addr, dat) \ + if (dev->bpp) \ dat = vram_w[(addr) & (dev->vram_mask >> 1)]; \ - else \ + else \ dat = (dev->vram[(addr) & (dev->vram_mask)]); \ -#define READ_HIGH(addr, dat) \ +#define READ_HIGH(addr, dat) \ dat |= (dev->vram[(addr) & (dev->vram_mask)] << 8); -#define MIX(mixmode, dest_dat, src_dat) \ - { \ - switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ - case 0x00: \ - dest_dat = ~dest_dat; \ - break; \ - case 0x01: \ - dest_dat = 0; \ - break; \ - case 0x02: \ - dest_dat = ~0; \ - break; \ - case 0x03: \ - dest_dat = dest_dat; \ - break; \ - case 0x04: \ - dest_dat = ~src_dat; \ - break; \ - case 0x05: \ - dest_dat = src_dat ^ dest_dat; \ - break; \ - case 0x06: \ - dest_dat = ~(src_dat ^ dest_dat); \ - break; \ - case 0x07: \ - dest_dat = src_dat; \ - break; \ - case 0x08: \ - dest_dat = ~(src_dat & dest_dat); \ - break; \ - case 0x09: \ - dest_dat = ~src_dat | dest_dat; \ - break; \ - case 0x0a: \ - dest_dat = src_dat | ~dest_dat; \ - break; \ - case 0x0b: \ - dest_dat = src_dat | dest_dat; \ - break; \ - case 0x0c: \ - dest_dat = src_dat & dest_dat; \ - break; \ - case 0x0d: \ - dest_dat = src_dat & ~dest_dat; \ - break; \ - case 0x0e: \ - dest_dat = ~src_dat & dest_dat; \ - break; \ - case 0x0f: \ - dest_dat = ~(src_dat | dest_dat); \ - break; \ - 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; \ - break; \ - case 0x16: \ - dest_dat = (src_dat - dest_dat) >> 1; \ - break; \ - case 0x17: \ - dest_dat = (dest_dat + src_dat) >> 1; \ - break; \ - case 0x18: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ - case 0x19: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ - case 0x1a: \ - dest_dat = MAX(0, (src_dat - dest_dat)); \ - break; \ - case 0x1b: \ - if (dev->bpp) \ - dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ - else \ - dest_dat = MIN(0xff, (dest_dat + src_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; \ - break; \ - case 0x1e: \ - dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ - break; \ - case 0x1f: \ - if (dev->bpp) \ +#define MIX(mixmode, dest_dat, src_dat) \ + { \ + switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ + case 0x00: \ + dest_dat = ~dest_dat; \ + break; \ + case 0x01: \ + dest_dat = 0; \ + break; \ + case 0x02: \ + dest_dat = ~0; \ + break; \ + case 0x03: \ + dest_dat = dest_dat; \ + break; \ + case 0x04: \ + dest_dat = ~src_dat; \ + break; \ + case 0x05: \ + dest_dat = src_dat ^ dest_dat; \ + break; \ + case 0x06: \ + dest_dat = ~(src_dat ^ dest_dat); \ + break; \ + case 0x07: \ + dest_dat = src_dat; \ + break; \ + case 0x08: \ + dest_dat = ~(src_dat & dest_dat); \ + break; \ + case 0x09: \ + dest_dat = ~src_dat | dest_dat; \ + break; \ + case 0x0a: \ + dest_dat = src_dat | ~dest_dat; \ + break; \ + case 0x0b: \ + dest_dat = src_dat | dest_dat; \ + break; \ + case 0x0c: \ + dest_dat = src_dat & dest_dat; \ + break; \ + case 0x0d: \ + dest_dat = src_dat & ~dest_dat; \ + break; \ + case 0x0e: \ + dest_dat = ~src_dat & dest_dat; \ + break; \ + case 0x0f: \ + dest_dat = ~(src_dat | dest_dat); \ + break; \ + 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; \ + break; \ + case 0x16: \ + dest_dat = (src_dat - dest_dat) >> 1; \ + break; \ + case 0x17: \ + dest_dat = (dest_dat + src_dat) >> 1; \ + break; \ + case 0x18: \ + dest_dat = MAX(0, (dest_dat - src_dat)); \ + break; \ + case 0x19: \ + dest_dat = MAX(0, (dest_dat - src_dat)); \ + break; \ + case 0x1a: \ + dest_dat = MAX(0, (src_dat - dest_dat)); \ + break; \ + case 0x1b: \ + if (dev->bpp) \ + dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ + else \ + dest_dat = MIN(0xff, (dest_dat + src_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; \ + break; \ + case 0x1e: \ + dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + break; \ + case 0x1f: \ + if (dev->bpp) \ dest_dat = (0xffff < (src_dat + dest_dat)) ? 0xffff : ((src_dat + dest_dat) / 2); \ - else \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ - break; \ - } \ + else \ + dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + break; \ + } \ } -#define WRITE(addr, dat) \ - if (dev->bpp) { \ - vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ +#define WRITE(addr, dat) \ + if (dev->bpp) { \ + vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ - } else { \ - dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + } else { \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ } int ibm8514_active = 0; diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index b3a544fc1..1d2326192 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -1508,16 +1508,16 @@ mach64_start_line(mach64_t *mach64) mach64->accel.op = OP_LINE; } -#define READ(addr, dat, width) \ - if (width == 0) \ - dat = svga->vram[((addr)) & mach64->vram_mask]; \ - else if (width == 1) \ - dat = *(uint16_t *) &svga->vram[((addr) << 1) & mach64->vram_mask]; \ - else if (width == 2) \ - dat = *(uint32_t *) &svga->vram[((addr) << 2) & mach64->vram_mask]; \ - else if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ - dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> ((addr) &7)) & 1; \ - else \ +#define READ(addr, dat, width) \ + if (width == 0) \ + dat = svga->vram[((addr)) & mach64->vram_mask]; \ + else if (width == 1) \ + dat = *(uint16_t *) &svga->vram[((addr) << 1) & mach64->vram_mask]; \ + else if (width == 2) \ + dat = *(uint32_t *) &svga->vram[((addr) << 2) & mach64->vram_mask]; \ + else if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ + dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> ((addr) &7)) & 1; \ + else \ dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> (7 - ((addr) &7))) & 1; #define MIX \ @@ -1575,29 +1575,29 @@ mach64_start_line(mach64_t *mach64) break; \ } -#define WRITE(addr, width) \ - if (width == 0) { \ - svga->vram[(addr) &mach64->vram_mask] = dest_dat; \ - svga->changedvram[((addr) &mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ - } else if (width == 1) { \ - *(uint16_t *) &svga->vram[((addr) << 1) & mach64->vram_mask] = dest_dat; \ - svga->changedvram[(((addr) << 1) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ - } else if (width == 2) { \ - *(uint32_t *) &svga->vram[((addr) << 2) & mach64->vram_mask] = dest_dat; \ - svga->changedvram[(((addr) << 2) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ - } else { \ - if (dest_dat & 1) { \ - if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ - svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << ((addr) &7); \ - else \ - svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << (7 - ((addr) &7)); \ - } else { \ - if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ - svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << ((addr) &7)); \ - else \ - svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << (7 - ((addr) &7))); \ - } \ - svga->changedvram[(((addr) >> 3) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ +#define WRITE(addr, width) \ + if (width == 0) { \ + svga->vram[(addr) &mach64->vram_mask] = dest_dat; \ + svga->changedvram[((addr) &mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } else if (width == 1) { \ + *(uint16_t *) &svga->vram[((addr) << 1) & mach64->vram_mask] = dest_dat; \ + svga->changedvram[(((addr) << 1) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } else if (width == 2) { \ + *(uint32_t *) &svga->vram[((addr) << 2) & mach64->vram_mask] = dest_dat; \ + svga->changedvram[(((addr) << 2) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } else { \ + if (dest_dat & 1) { \ + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ + svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << ((addr) &7); \ + else \ + svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << (7 - ((addr) &7)); \ + } else { \ + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ + svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << ((addr) &7)); \ + else \ + svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << (7 - ((addr) &7))); \ + } \ + svga->changedvram[(((addr) >> 3) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ } void diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index a923ea7e2..5cd29d814 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -49,10 +49,10 @@ #define BIOS_MACH32_MCA_ROM_PATH "roms/video/mach32/MACH32MCA_Olivetti.BIN" #define BIOS_MACH32_PCI_ROM_PATH "roms/video/mach32/intelopt_00000.rom" -static video_timings_t timing_gfxultra_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; -static video_timings_t timing_mach32_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; -static video_timings_t timing_mach32_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; -static video_timings_t timing_mach32_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; +static video_timings_t timing_gfxultra_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_mach32_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; +static video_timings_t timing_mach32_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_mach32_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; static void mach_accel_outb(uint16_t port, uint8_t val, void *priv); static void mach_accel_outw(uint16_t port, uint16_t val, void *priv); @@ -88,14 +88,14 @@ mach_log(const char *fmt, ...) # define mach_log(fmt, ...) #endif -#define WRITE8(addr, var, val) \ - switch ((addr) & 1) { \ - case 0: \ - var = (var & 0xff00) | (val); \ - break; \ - case 1: \ - var = (var & 0x00ff) | ((val) << 8); \ - break; \ +#define WRITE8(addr, var, val) \ + switch ((addr) & 1) { \ + case 0: \ + var = (var & 0xff00) | (val); \ + break; \ + case 1: \ + var = (var & 0x00ff) | ((val) << 8); \ + break; \ } #define READ8(addr, var) \ @@ -110,166 +110,164 @@ mach_log(const char *fmt, ...) #define READ_PIXTRANS_BYTE_IO(cx, n) \ if ((mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ - if (dev->bpp) { \ - if (n == 0)\ + if (dev->bpp) { \ + if (n == 0) \ mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (dev->vram_mask >> 1)] & 0xff; \ - else \ - mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (dev->vram_mask >> 1)] >> 8; \ - \ - } else \ - mach->accel.pix_trans[(n)] = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ - \ + else \ + mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (dev->vram_mask >> 1)] >> 8; \ + } else \ + mach->accel.pix_trans[(n)] = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ } -#define READ_PIXTRANS_WORD(cx, n) \ - if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ - 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)) { \ - if (dev->bpp) \ - temp = vram_w[((dev->accel.dest) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ - else { \ - temp = dev->vram[((dev->accel.dest) + (cx) + (n)) & dev->vram_mask]; \ - temp |= (dev->vram[((dev->accel.dest) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ - } \ - } else if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { \ - if (dev->bpp) \ - temp = vram_w[((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ - else { \ - temp = dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & dev->vram_mask]; \ +#define READ_PIXTRANS_WORD(cx, n) \ + if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ + 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)) { \ + if (dev->bpp) \ + temp = vram_w[((dev->accel.dest) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ + else { \ + temp = dev->vram[((dev->accel.dest) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((dev->accel.dest) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ + } else if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { \ + if (dev->bpp) \ + temp = vram_w[((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ + else { \ + temp = dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ - } \ + } \ } -#define READ(addr, dat) \ - if (dev->bpp) \ +#define READ(addr, dat) \ + if (dev->bpp) \ dat = vram_w[(addr) & (dev->vram_mask >> 1)]; \ - else \ + else \ dat = (dev->vram[(addr) & (dev->vram_mask)]); -#define READ_HIGH(addr, dat) \ +#define READ_HIGH(addr, dat) \ dat |= (dev->vram[(addr) & (dev->vram_mask)] << 8); -#define MIX(mixmode, dest_dat, src_dat) \ - { \ - switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ - case 0x00: \ - dest_dat = ~dest_dat; \ - break; \ - case 0x01: \ - dest_dat = 0; \ - break; \ - case 0x02: \ - dest_dat = ~0; \ - break; \ - case 0x03: \ - dest_dat = dest_dat; \ - break; \ - case 0x04: \ - dest_dat = ~src_dat; \ - break; \ - case 0x05: \ - dest_dat = src_dat ^ dest_dat; \ - break; \ - case 0x06: \ - dest_dat = ~(src_dat ^ dest_dat); \ - break; \ - case 0x07: \ - dest_dat = src_dat; \ - break; \ - case 0x08: \ - dest_dat = ~(src_dat & dest_dat); \ - break; \ - case 0x09: \ - dest_dat = ~src_dat | dest_dat; \ - break; \ - case 0x0a: \ - dest_dat = src_dat | ~dest_dat; \ - break; \ - case 0x0b: \ - dest_dat = src_dat | dest_dat; \ - break; \ - case 0x0c: \ - dest_dat = src_dat & dest_dat; \ - break; \ - case 0x0d: \ - dest_dat = src_dat & ~dest_dat; \ - break; \ - case 0x0e: \ - dest_dat = ~src_dat & dest_dat; \ - break; \ - case 0x0f: \ - dest_dat = ~(src_dat | dest_dat); \ - break; \ - 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; \ - break; \ - case 0x16: \ - dest_dat = (src_dat - dest_dat) / 2; \ - break; \ - case 0x17: \ - dest_dat = (dest_dat + src_dat) / 2; \ - break; \ - case 0x18: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ - case 0x19: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ - case 0x1a: \ - dest_dat = MAX(0, (src_dat - dest_dat)); \ - break; \ - case 0x1b: \ - if (dev->bpp) \ - dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ - else \ - dest_dat = MIN(0xff, (dest_dat + src_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; \ - break; \ - case 0x1e: \ - dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ - break; \ - case 0x1f: \ - if (dev->bpp) \ +#define MIX(mixmode, dest_dat, src_dat) \ + { \ + switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ + case 0x00: \ + dest_dat = ~dest_dat; \ + break; \ + case 0x01: \ + dest_dat = 0; \ + break; \ + case 0x02: \ + dest_dat = ~0; \ + break; \ + case 0x03: \ + dest_dat = dest_dat; \ + break; \ + case 0x04: \ + dest_dat = ~src_dat; \ + break; \ + case 0x05: \ + dest_dat = src_dat ^ dest_dat; \ + break; \ + case 0x06: \ + dest_dat = ~(src_dat ^ dest_dat); \ + break; \ + case 0x07: \ + dest_dat = src_dat; \ + break; \ + case 0x08: \ + dest_dat = ~(src_dat & dest_dat); \ + break; \ + case 0x09: \ + dest_dat = ~src_dat | dest_dat; \ + break; \ + case 0x0a: \ + dest_dat = src_dat | ~dest_dat; \ + break; \ + case 0x0b: \ + dest_dat = src_dat | dest_dat; \ + break; \ + case 0x0c: \ + dest_dat = src_dat & dest_dat; \ + break; \ + case 0x0d: \ + dest_dat = src_dat & ~dest_dat; \ + break; \ + case 0x0e: \ + dest_dat = ~src_dat & dest_dat; \ + break; \ + case 0x0f: \ + dest_dat = ~(src_dat | dest_dat); \ + break; \ + 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; \ + break; \ + case 0x16: \ + dest_dat = (src_dat - dest_dat) / 2; \ + break; \ + case 0x17: \ + dest_dat = (dest_dat + src_dat) / 2; \ + break; \ + case 0x18: \ + dest_dat = MAX(0, (dest_dat - src_dat)); \ + break; \ + case 0x19: \ + dest_dat = MAX(0, (dest_dat - src_dat)); \ + break; \ + case 0x1a: \ + dest_dat = MAX(0, (src_dat - dest_dat)); \ + break; \ + case 0x1b: \ + if (dev->bpp) \ + dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ + else \ + dest_dat = MIN(0xff, (dest_dat + src_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; \ + break; \ + case 0x1e: \ + dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + break; \ + case 0x1f: \ + if (dev->bpp) \ dest_dat = (0xffff < (src_dat + dest_dat)) ? 0xffff : ((src_dat + dest_dat) / 2); \ - else \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ - break; \ - } \ + else \ + dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + break; \ + } \ } -#define WRITE(addr, dat) \ - if (dev->bpp) { \ - vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ +#define WRITE(addr, dat) \ + if (dev->bpp) { \ + vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ - } else { \ - dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + } else { \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ } static int @@ -338,7 +336,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) - mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", 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("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", + 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); switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ @@ -366,7 +366,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.stepx = (mach->accel.linedraw_opt & 0x20) ? 1 : -1; mach->accel.stepy = (mach->accel.linedraw_opt & 0x80) ? 1 : -1; - mach_log("Extended bresenham, CUR(%d,%d), DEST(%d,%d), width = %d, options = %04x, dpconfig = %04x, opt_ena = %03x.\n", dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.linedraw_opt, mach->accel.dp_config, mach->accel.max_waitstates & 0x100); + mach_log("Extended bresenham, CUR(%d,%d), DEST(%d,%d), width = %d, options = %04x, dpconfig = %04x, opt_ena = %03x.\n", + dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.linedraw_opt, + mach->accel.dp_config, mach->accel.max_waitstates & 0x100); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -853,11 +855,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.stepx = -1; if (dev->accel.dx > 0) dev->accel.dx--; - mach_log("BitBLT: Dst Negative X, dxstart = %d, end = %d, width = %d, dx = %d, dpconfig = %04x.\n", mach->accel.dest_x_start, mach->accel.dest_x_end, mach->accel.width, dev->accel.dx, mach->accel.dp_config); + mach_log("BitBLT: Dst Negative X, dxstart = %d, end = %d, width = %d, dx = %d, dpconfig = %04x.\n", + mach->accel.dest_x_start, mach->accel.dest_x_end, mach->accel.width, dev->accel.dx, + mach->accel.dp_config); } else { mach->accel.stepx = 1; mach->accel.width = 0; - mach_log("BitBLT: Dst Indeterminate X, dpconfig = %04x, destxend = %d, destxstart = %d.\n", mach->accel.dp_config, mach->accel.dest_x_end, mach->accel.dest_x_start); + mach_log("BitBLT: Dst Indeterminate X, dpconfig = %04x, destxend = %d, destxstart = %d.\n", + mach->accel.dp_config, mach->accel.dest_x_end, mach->accel.dest_x_start); } dev->accel.sx = 0; @@ -914,17 +919,23 @@ 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->accel.src_width = (mach->accel.sx_end - mach->accel.sx_start); mach->accel.src_stepx = 1; - mach_log("BitBLT: Src Positive X: wh(%d,%d), srcwidth = %d, coordinates: %d,%d px, start: %d, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", mach->accel.width, mach->accel.height, mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_start, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + mach_log("BitBLT: Src Positive X: wh(%d,%d), srcwidth = %d, coordinates: %d,%d px, start: %d, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", + mach->accel.width, mach->accel.height, mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_start, mach->accel.src_x_end, + mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); } else if (mach->accel.sx_end < mach->accel.sx_start) { mach->accel.src_width = (mach->accel.sx_start - mach->accel.sx_end); mach->accel.src_stepx = -1; if (dev->accel.cx > 0) dev->accel.cx--; - mach_log("BitBLT: Src Negative X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + mach_log("BitBLT: Src Negative X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", + mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config + mach->accel.src_width & 1); } else { mach->accel.src_stepx = 1; mach->accel.src_width = 0; - mach_log("BitBLT: Src Indeterminate X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + mach_log("BitBLT: Src Indeterminate X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", + mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, + mach->accel.dp_config, mach->accel.src_width & 1); } mach->accel.sx = 0; if (mach->accel.patt_data_idx < 16) @@ -996,7 +1007,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (cpu_input) { if (mach->accel.dp_config == 0x3251) { - mach_log("DPCONFIG 3251: monosrc=%d, frgdsel=%d, bkgdsel=%d, pitch=%d.\n", mono_src, frgd_sel, bkgd_sel, dev->pitch); + mach_log("DPCONFIG 3251: monosrc=%d, frgdsel=%d, bkgdsel=%d, pitch=%d.\n", + mono_src, frgd_sel, bkgd_sel, dev->pitch); if (dev->accel.sy == mach->accel.height) { mach_log("No Blit on DPCONFIG=3251.\n"); dev->accel.cmd_back = 1; @@ -1156,7 +1168,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 cpu_dat >>= 8; if (mach->accel.dp_config == 0x2071 || (mach->accel.dp_config == 0x2011)) - mach_log("FontBlit: SX=%d, C(%d,%d), SRCWidth=%d, frgdmix=%d, bkgdmix=%d, rdmask=%04x, D(%d,%d), geoffset=%x, addr=%08x,.\n", mach->accel.sx, dev->accel.cx, dev->accel.cy, mach->accel.src_width, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, rd_mask, dev->accel.dx, dev->accel.dy, dev->accel.ge_offset, (dev->accel.src + dev->accel.cx) & dev->vram_mask); + mach_log("FontBlit: SX=%d, C(%d,%d), SRCWidth=%d, frgdmix=%d, bkgdmix=%d, rdmask=%04x, D(%d,%d), geoffset=%x, addr=%08x,.\n", + mach->accel.sx, dev->accel.cx, dev->accel.cy, mach->accel.src_width, dev->accel.frgd_mix & 0x1f, + dev->accel.bkgd_mix & 0x1f, rd_mask, dev->accel.dx, dev->accel.dy, dev->accel.ge_offset, + (dev->accel.src + dev->accel.cx) & dev->vram_mask); if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) { dev->accel.cx += mach->accel.src_stepx; @@ -1248,7 +1263,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sx = 0; - mach_log("Linedraw: c(%d,%d), d(%d,%d), cend(%d,%d), bounds: l=%d, r=%d, t=%d, b=%d.\n", dev->accel.cur_x, dev->accel.cur_y, dev->accel.dx, dev->accel.dy, mach->accel.cx_end_line, mach->accel.cy_end_line, mach->accel.bleft, mach->accel.bright, mach->accel.btop, mach->accel.bbottom); + mach_log("Linedraw: c(%d,%d), d(%d,%d), cend(%d,%d), bounds: l=%d, r=%d, t=%d, b=%d.\n", + dev->accel.cur_x, dev->accel.cur_y, dev->accel.dx, dev->accel.dy, mach->accel.cx_end_line, + mach->accel.cy_end_line, mach->accel.bleft, mach->accel.bright, mach->accel.btop, mach->accel.bbottom); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -1944,7 +1961,9 @@ 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=%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); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -2197,9 +2216,11 @@ mach_out(uint16_t addr, uint8_t val, void *priv) if (((dev->disp_cntl & 0x60) == 0x20) && ((dev->local & 0xff) >= 0x02)) { if ((addr >= 0x3c6) && (addr <= 0x3c9)) { - mach_log("VGA DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); + mach_log("VGA DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", + addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); } else if ((addr >= 0x2ea) && (addr <= 0x2ed)) - mach_log("8514/A DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); + mach_log("8514/A DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", + addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); } switch (addr) { @@ -2609,7 +2630,8 @@ ati8514_recalctimings(svga_t *svga) dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; - 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); + 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; @@ -2637,7 +2659,9 @@ ati8514_recalctimings(svga_t *svga) if (dev->interlace) dev->dispend >>= 1; - 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, 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); if (dev->vram_512k_8514) { if (dev->h_disp == 640) { dev->ext_pitch = 640; @@ -2713,7 +2737,9 @@ mach_recalctimings(svga_t *svga) dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; - 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); + 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; @@ -2788,7 +2814,9 @@ mach_recalctimings(svga_t *svga) } 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_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); switch (dev->accel_bpp) { case 8: svga->render8514 = ibm8514_render_8bpp; @@ -2814,7 +2842,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, 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); if (dev->vram_512k_8514) { if (dev->h_disp == 640) { dev->ext_pitch = 640; @@ -2829,7 +2859,8 @@ mach_recalctimings(svga_t *svga) } } else { if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { - mach_log("GDCREG5=%02x, ATTR10=%02x, ATI B0 bit 5=%02x, ON=%d.\n", svga->gdcreg[5] & 0x60, svga->attrregs[0x10] & 0x40, mach->regs[0xb0] & 0x20, dev->on); + mach_log("GDCREG5=%02x, ATTR10=%02x, ATI B0 bit 5=%02x, ON=%d.\n", + svga->gdcreg[5] & 0x60, svga->attrregs[0x10] & 0x40, mach->regs[0xb0] & 0x20, dev->on); if ((svga->gdcreg[6] & 0x01) || (svga->attrregs[0x10] & 0x01)) { if ((svga->gdcreg[5] & 0x40) || (svga->attrregs[0x10] & 0x40) || (mach->regs[0xb0] & 0x20)) { svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); @@ -3405,7 +3436,8 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 } 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); + 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; @@ -3475,7 +3507,8 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 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); + 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; @@ -3483,7 +3516,8 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 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); + 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; @@ -3630,8 +3664,10 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 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", port, mach->accel.clock_sel & 0x01, val, dev->hdisp, dev->vdisp); - mach_log("Vendor ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); + mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", + port, mach->accel.clock_sel & 0x01, val, dev->hdisp, dev->vdisp); + mach_log("Vendor ATI mode set %s resolution.\n", + (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); if ((dev->local & 0xff) >= 0x01) mach32_updatemapping(mach, svga); @@ -5160,7 +5196,8 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_accel_outb(0x02e8 + (addr & 1) + (port_dword << 8), 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); + 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 @@ -5186,7 +5223,8 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_accel_outw(0x02e8 + (port_dword << 8), val, mach); } } else { - mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr & dev->vram_mask, 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.\n", + addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) mach32_writew_linear(addr, val, mach); else @@ -5214,7 +5252,8 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); } } else { - mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + mach_log("Linear WORDL Write=%08x, val=%08x, 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_writel_linear(addr, val, mach); else @@ -5354,7 +5393,8 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) } } - 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); + 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) { /*1 MB aperture*/ @@ -5832,7 +5872,8 @@ mach_mca_write(int port, uint8_t val, void *priv) return; mach->pos_regs[port & 7] = val; - mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", CS, port & 7, mach->pos_regs[port & 7], (((mach->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); + mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", + CS, port & 7, mach->pos_regs[port & 7], (((mach->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); mem_mapping_disable(&mach->bios_rom.mapping); mem_mapping_disable(&mach->bios_rom2.mapping); if (mach->pos_regs[2] & 0x01) { @@ -5882,7 +5923,8 @@ ati8514_mca_write(int port, uint8_t val, void *priv) return; dev->pos_regs[port & 7] = val; - mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", CS, port & 7, dev->pos_regs[port & 7], (((dev->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); + mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", + CS, port & 7, dev->pos_regs[port & 7], (((dev->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); mem_mapping_disable(&dev->bios_rom.mapping); if (dev->pos_regs[2] & 0x01) diff --git a/src/video/vid_cga_comp.c b/src/video/vid_cga_comp.c index d580f0c06..6ad6a6b0a 100644 --- a/src/video/vid_cga_comp.c +++ b/src/video/vid_cga_comp.c @@ -44,22 +44,22 @@ static const double tau = 6.28318531; /* == 2*pi */ static unsigned char chroma_multiplexer[256] = { // clang-format off - 2, 2, 2, 2, 114,174, 4, 3, 2, 1,133,135, 2,113,150, 4, - 133, 2, 1, 99, 151,152, 2, 1, 3, 2, 96,136, 151,152,151,152, - 2, 56, 62, 4, 111,250,118, 4, 0, 51,207,137, 1,171,209, 5, - 140, 50, 54,100, 133,202, 57, 4, 2, 50,153,149, 128,198,198,135, - 32, 1, 36, 81, 147,158, 1, 42, 33, 1,210,254, 34,109,169, 77, - 177, 2, 0,165, 189,154, 3, 44, 33, 0, 91,197, 178,142,144,192, - 4, 2, 61, 67, 117,151,112, 83, 4, 0,249,255, 3,107,249,117, - 147, 1, 50,162, 143,141, 52, 54, 3, 0,145,206, 124,123,192,193, - 72, 78, 2, 0, 159,208, 4, 0, 53, 58,164,159, 37,159,171, 1, - 248,117, 4, 98, 212,218, 5, 2, 54, 59, 93,121, 176,181,134,130, - 1, 61, 31, 0, 160,255, 34, 1, 1, 58,197,166, 0,177,194, 2, - 162,111, 34, 96, 205,253, 32, 1, 1, 57,123,125, 119,188,150,112, - 78, 4, 0, 75, 166,180, 20, 38, 78, 1,143,246, 42,113,156, 37, - 252, 4, 1,188, 175,129, 1, 37, 118, 4, 88,249, 202,150,145,200, - 61, 59, 60, 60, 228,252,117, 77, 60, 58,248,251, 81,212,254,107, - 198, 59, 58,169, 250,251, 81, 80, 100, 58,154,250, 251,252,252,252 + 2, 2, 2, 2, 114, 174, 4, 3, 2, 1, 133, 135, 2, 113, 150, 4, + 133, 2, 1, 99, 151, 152, 2, 1, 3, 2, 96, 136, 151, 152, 151, 152, + 2, 56, 62, 4, 111, 250, 118, 4, 0, 51, 207, 137, 1, 171, 209, 5, + 140, 50, 54, 100, 133, 202, 57, 4, 2, 50, 153, 149, 128, 198, 198, 135, + 32, 1, 36, 81, 147, 158, 1, 42, 33, 1, 210, 254, 34, 109, 169, 77, + 177, 2, 0, 165, 189, 154, 3, 44, 33, 0, 91, 197, 178, 142, 144, 192, + 4, 2, 61, 67, 117, 151, 112, 83, 4, 0, 249, 255, 3, 107, 249, 117, + 147, 1, 50, 162, 143, 141, 52, 54, 3, 0, 145, 206, 124, 123, 192, 193, + 72, 78, 2, 0, 159, 208, 4, 0, 53, 58, 164, 159, 37, 159, 171, 1, + 248, 117, 4, 98, 212, 218, 5, 2, 54, 59, 93, 121, 176, 181, 134, 130, + 1, 61, 31, 0, 160, 255, 34, 1, 1, 58, 197, 166, 0, 177, 194, 2, + 162, 111, 34, 96, 205, 253, 32, 1, 1, 57, 123, 125, 119, 188, 150, 112, + 78, 4, 0, 75, 166, 180, 20, 38, 78, 1, 143, 246, 42, 113, 156, 37, + 252, 4, 1, 188, 175, 129, 1, 37, 118, 4, 88, 249, 202, 150, 145, 200, + 61, 59, 60, 60, 228, 252, 117, 77, 60, 58, 248, 251, 81, 212, 254, 107, + 198, 59, 58, 169, 250, 251, 81, 80, 100, 58, 154, 250, 251, 252, 252, 252 // clang-format on }; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 169dc659b..120505dc5 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -82,8 +82,8 @@ typedef struct { rom_t bios_rom; uint8_t banking; - uint32_t vram_size, - vram_mask; + uint32_t vram_size; + uint32_t vram_mask; uint8_t port_22cb_val; uint8_t port_32cb_val; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 9ee74f512..b3cbdd999 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -427,8 +427,7 @@ enum { DMA_STATE_SEC }; -typedef struct -{ +typedef struct { uint32_t addr_type; uint32_t val; } fifo_entry_t; @@ -484,13 +483,11 @@ typedef struct mystique_t { event_t *wake_fifo_thread, *fifo_not_full_event; - struct - { + struct { int m, n, p, s; } xpixpll[3]; - struct - { + struct { uint8_t funcnt : 7, stylelen, dmamod; @@ -521,27 +518,23 @@ typedef struct mystique_t { uint64_t extended_dr[4]; - struct - { + struct { int sdydxl, scanleft, sdxl, sdy, sdxr; } sgn; } dwgreg; - struct - { + struct { uint8_t r, g, b; } lut[256]; - struct - { + struct { uint16_t pos_x, pos_y, addr; uint32_t col[3]; } cursor; - struct - { + struct { atomic_int pri_state, sec_state, iload_state, state; atomic_uint primaddress, primend, secaddress, secend, diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 8e3241efd..89d65a1f8 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -68,7 +68,7 @@ typedef struct paradise_t { } paradise_t; static video_timings_t timing_paradise_pvga1a = { .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_paradise_wd90c = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_paradise_wd90c = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; void paradise_remap(paradise_t *paradise); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7e3b7a2ef..52135b066 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -537,15 +537,15 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define READ_PIXTRANS_BYTE_MM \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; -#define READ_PIXTRANS_WORD \ - if ((s3->bpp == 0) && !s3->color_16bit) { \ - temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ - temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ - } else \ +#define READ_PIXTRANS_WORD \ + if ((s3->bpp == 0) && !s3->color_16bit) { \ + temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ + temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ + } else \ temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx - s3->accel.minus)) & (s3->vram_mask >> 1)]; #define READ_PIXTRANS_LONG \ - if ((s3->bpp == 0) && !s3->color_16bit) { \ + if ((s3->bpp == 0) && !s3->color_16bit) { \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 2)) & s3->vram_mask] << 16); \ @@ -6583,9 +6583,9 @@ polygon_setup(s3_t *s3) #define READ(addr, dat) \ if (((s3->bpp == 0) && !s3->color_16bit) || (s3->bpp == 2)) \ dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ - else if ((s3->bpp == 1) || s3->color_16bit) \ + else if ((s3->bpp == 1) || s3->color_16bit) \ dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ - else \ + else \ dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; #define MIX_READ \ @@ -6642,11 +6642,11 @@ polygon_setup(s3_t *s3) } \ } -#define MIX \ - { \ - old_dest_dat = dest_dat; \ - MIX_READ \ - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); \ +#define MIX \ + { \ + old_dest_dat = dest_dat; \ + MIX_READ \ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); \ } #define ROPMIX_READ(D, P, S) \ @@ -7431,14 +7431,14 @@ polygon_setup(s3_t *s3) } #define WRITE(addr, dat) \ - if (((s3->bpp == 0) && !s3->color_16bit) || (s3->bpp == 2)) { \ - svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ + if (((s3->bpp == 0) && !s3->color_16bit) || (s3->bpp == 2)) { \ + svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ - } else if ((s3->bpp == 1) || s3->color_16bit) { \ + } else if ((s3->bpp == 1) || s3->color_16bit) { \ vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \ svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ } else { \ - vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \ + vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \ svga->changedvram[(dword_remap_l(svga, addr) & (s3->vram_mask >> 2)) >> 10] = svga->monitor->mon_changeframecount; \ } diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 3c61f3a57..86876cd0a 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -2088,127 +2088,127 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) } } -#define READ(addr, val) \ - do { \ - switch (bpp) { \ - case 0: /*8 bpp*/ \ +#define READ(addr, val) \ + do { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ val = vram[addr & virge->vram_mask]; \ - break; \ - case 1: /*16 bpp*/ \ + break; \ + case 1: /*16 bpp*/ \ val = *(uint16_t *)&vram[addr & virge->vram_mask]; \ - break; \ - case 2: /*24 bpp*/ \ + break; \ + case 2: /*24 bpp*/ \ val = (*(uint32_t *)&vram[addr & virge->vram_mask]) & 0xffffff; \ - break; \ - } \ + break; \ + } \ } while (0) #define Z_READ(addr) *(uint16_t *)&vram[addr & virge->vram_mask] -#define Z_WRITE(addr, val) \ - if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ +#define Z_WRITE(addr, val) \ + if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ *(uint16_t *)&vram[addr & virge->vram_mask] = val -#define CLIP(x, y) \ - do { \ - if ((virge->s3d.cmd_set & CMD_SET_HC) && \ - (x < virge->s3d.clip_l || x > virge->s3d.clip_r || \ - y < virge->s3d.clip_t || y > virge->s3d.clip_b)) \ - update = 0; \ +#define CLIP(x, y) \ + do { \ + if ((virge->s3d.cmd_set & CMD_SET_HC) && \ + (x < virge->s3d.clip_l || x > virge->s3d.clip_r || \ + y < virge->s3d.clip_t || y > virge->s3d.clip_b)) \ + update = 0; \ } while (0) -#define CLIP_3D(x, y) \ - do { \ - if ((s3d_tri->cmd_set & CMD_SET_HC) && (x < s3d_tri->clip_l || \ - x > s3d_tri->clip_r || y < s3d_tri->clip_t || \ - y > s3d_tri->clip_b)) \ - update = 0; \ +#define CLIP_3D(x, y) \ + do { \ + if ((s3d_tri->cmd_set & CMD_SET_HC) && (x < s3d_tri->clip_l || \ + x > s3d_tri->clip_r || y < s3d_tri->clip_t || \ + y > s3d_tri->clip_b)) \ + update = 0; \ } while (0) -#define Z_CLIP(Zzb, Zs) \ - do { \ - if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ - switch ((s3d_tri->cmd_set >> 20) & 7) { \ - case 0: \ - update = 0; \ - break; \ - case 1: \ - if (Zs <= Zzb) \ - update = 0; \ - else \ - Zzb = Zs; \ - break; \ - case 2: \ - if (Zs != Zzb) \ - update = 0; \ - else \ - Zzb = Zs; \ - break; \ - case 3: \ - if (Zs < Zzb) \ - update = 0; \ - else \ - Zzb = Zs; \ - break; \ - case 4: \ - if (Zs >= Zzb) \ - update = 0; \ - else \ - Zzb = Zs; \ - break; \ - case 5: \ - if (Zs == Zzb) \ - update = 0; \ - else \ - Zzb = Zs; \ - break; \ - case 6: \ - if (Zs > Zzb) \ - update = 0; \ - else \ - Zzb = Zs; \ - break; \ - case 7: \ - update = 1; \ - Zzb = Zs; \ - break; \ - } \ +#define Z_CLIP(Zzb, Zs) \ + do { \ + if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ + switch ((s3d_tri->cmd_set >> 20) & 7) { \ + case 0: \ + update = 0; \ + break; \ + case 1: \ + if (Zs <= Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 2: \ + if (Zs != Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 3: \ + if (Zs < Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 4: \ + if (Zs >= Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 5: \ + if (Zs == Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 6: \ + if (Zs > Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 7: \ + update = 1; \ + Zzb = Zs; \ + break; \ + } \ } while (0) -#define MIX() \ - do { \ - int c; \ - for (c = 0; c < 24; c++) { \ - int d = (dest & (1 << c)) ? 1 : 0; \ - if (source & (1 << c)) \ - d |= 2; \ - if (pattern & (1 << c)) \ - d |= 4; \ - if (virge->s3d.rop & (1 << d)) \ - out |= (1 << c); \ - } \ +#define MIX() \ + do { \ + int c; \ + for (c = 0; c < 24; c++) { \ + int d = (dest & (1 << c)) ? 1 : 0; \ + if (source & (1 << c)) \ + d |= 2; \ + if (pattern & (1 << c)) \ + d |= 4; \ + if (virge->s3d.rop & (1 << d)) \ + out |= (1 << c); \ + } \ } while (0) -#define WRITE(addr, val) \ - do { \ - switch (bpp) { \ - case 0: /*8 bpp*/ \ - vram[addr & virge->vram_mask] = val; \ - virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ - changeframecount; \ - break; \ - case 1: /*16 bpp*/ \ - *(uint16_t *)&vram[addr & virge->vram_mask] = val; \ - virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ - changeframecount; \ - break; \ - case 2: /*24 bpp*/ \ - *(uint32_t *)&vram[addr & virge->vram_mask] = (val & 0xffffff) |\ - (vram[(addr + 3) & virge->vram_mask] << 24); \ - virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ - changeframecount; \ - break; \ - } \ +#define WRITE(addr, val) \ + do { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ + vram[addr & virge->vram_mask] = val; \ + virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ + changeframecount; \ + break; \ + case 1: /*16 bpp*/ \ + *(uint16_t *)&vram[addr & virge->vram_mask] = val; \ + virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ + changeframecount; \ + break; \ + case 2: /*24 bpp*/ \ + *(uint32_t *)&vram[addr & virge->vram_mask] = (val & 0xffffff) | \ + (vram[(addr + 3) & virge->vram_mask] << 24); \ + virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ + changeframecount; \ + break; \ + } \ } while (0) static void @@ -2573,23 +2573,23 @@ skip_line: g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); -#define RGB24_TO_24(val, r, g, b) \ - b = val & 0xff; \ - g = (val & 0xff00) >> 8; \ +#define RGB24_TO_24(val, r, g, b) \ + b = val & 0xff; \ + g = (val & 0xff00) >> 8; \ r = (val & 0xff0000) >> 16 -#define RGB15(r, g, b, dest) \ - if (virge->dithering_enabled) { \ - int add = dither[_y & 3][_x & 3]; \ - int _r = (r > 248) ? 248 : r + add; \ - int _g = (g > 248) ? 248 : g + add; \ - int _b = (b > 248) ? 248 : b + add; \ - dest = ((_b >> 3) & 0x1f) | \ - (((_g >> 3) & 0x1f) << 5) | \ - (((_r >> 3) & 0x1f) << 10); \ - } else \ - dest = ((b >> 3) & 0x1f) | \ - (((g >> 3) & 0x1f) << 5) | \ +#define RGB15(r, g, b, dest) \ + if (virge->dithering_enabled) { \ + int add = dither[_y & 3][_x & 3]; \ + int _r = (r > 248) ? 248 : r + add; \ + int _g = (g > 248) ? 248 : g + add; \ + int _b = (b > 248) ? 248 : b + add; \ + dest = ((_b >> 3) & 0x1f) | \ + (((_g >> 3) & 0x1f) << 5) | \ + (((_r >> 3) & 0x1f) << 10); \ + } else \ + dest = ((b >> 3) & 0x1f) | \ + (((g >> 3) & 0x1f) << 5) | \ (((r >> 3) & 0x1f) << 10) #define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) @@ -3753,103 +3753,99 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += 16; } -#define DECODE_YCbCr() \ - do { \ - int c; \ - \ - for (c = 0; c < 2; c++) { \ - uint8_t y1, y2; \ - int8_t Cr; \ - int8_t Cb; \ - int dR; \ - int dG; \ - int dB; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359 * Cr) >> 8; \ - dG = (88 * Cb + 183 * Cr) >> 8; \ - dB = (453 * Cb) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write + 1] = y2 + dR; \ - CLAMP(r[x_write + 1]); \ - g[x_write + 1] = y2 - dG; \ - CLAMP(g[x_write + 1]); \ - b[x_write + 1] = y2 + dB; \ - CLAMP(b[x_write + 1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ +#define DECODE_YCbCr() \ + do { \ + for (uint8_t c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t Cr; \ + int8_t Cb; \ + int dR; \ + int dG; \ + int dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ } while (0) /*Both YUV formats are untested*/ -#define DECODE_YUV211() \ - do { \ - uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR; \ - int dG; \ - int dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ - y3 = (298 * (src[4] - 16)) >> 8; \ - y4 = (298 * (src[5] - 16)) >> 8; \ - src += 6; \ - \ - dR = (309 * V) >> 8; \ - dG = (100 * U + 208 * V) >> 8; \ - dB = (516 * U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write + 1] = y2 + dR; \ - CLAMP(r[x_write + 1]); \ - g[x_write + 1] = y2 - dG; \ - CLAMP(g[x_write + 1]); \ - b[x_write + 1] = y2 + dB; \ - CLAMP(b[x_write + 1]); \ - \ - r[x_write + 2] = y3 + dR; \ - CLAMP(r[x_write + 2]); \ - g[x_write + 2] = y3 - dG; \ - CLAMP(g[x_write + 2]); \ - b[x_write + 2] = y3 + dB; \ - CLAMP(b[x_write + 2]); \ - \ - r[x_write + 3] = y4 + dR; \ - CLAMP(r[x_write + 3]); \ - g[x_write + 3] = y4 - dG; \ - CLAMP(g[x_write + 3]); \ - b[x_write + 3] = y4 + dB; \ - CLAMP(b[x_write + 3]); \ - \ - x_write = (x_write + 4) & 7; \ +#define DECODE_YUV211() \ + do { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR; \ + int dG; \ + int dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + r[x_write + 2] = y3 + dR; \ + CLAMP(r[x_write + 2]); \ + g[x_write + 2] = y3 - dG; \ + CLAMP(g[x_write + 2]); \ + b[x_write + 2] = y3 + dB; \ + CLAMP(b[x_write + 2]); \ + \ + r[x_write + 3] = y4 + dR; \ + CLAMP(r[x_write + 3]); \ + g[x_write + 3] = y4 - dG; \ + CLAMP(g[x_write + 3]); \ + b[x_write + 3] = y4 + dB; \ + CLAMP(b[x_write + 3]); \ + \ + x_write = (x_write + 4) & 7; \ } while (0) #define DECODE_YUV422() \ do { \ - int c; \ - \ - for (c = 0; c < 2; c++) { \ + for (uint8_t c = 0; c < 2; c++) { \ uint8_t y1; \ uint8_t y2; \ int8_t U; \ @@ -3886,104 +3882,96 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) } \ } while (0) -#define DECODE_RGB555() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = \ - ((dat & 0x001f) << 3) | \ - ((dat & 0x001f) >> 2); \ - g[x_write + c] = \ - ((dat & 0x03e0) >> 2) | \ - ((dat & 0x03e0) >> 7); \ - b[x_write + c] = \ - ((dat & 0x7c00) >> 7) | \ - ((dat & 0x7c00) >> 12); \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_RGB555() \ + do { \ + for (uint8_t c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = \ + ((dat & 0x001f) << 3) | \ + ((dat & 0x001f) >> 2); \ + g[x_write + c] = \ + ((dat & 0x03e0) >> 2) | \ + ((dat & 0x03e0) >> 7); \ + b[x_write + c] = \ + ((dat & 0x7c00) >> 7) | \ + ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define DECODE_RGB565() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = \ - ((dat & 0x001f) << 3) | \ - ((dat & 0x001f) >> 2); \ - g[x_write + c] = \ - ((dat & 0x07e0) >> 3) | \ - ((dat & 0x07e0) >> 9); \ - b[x_write + c] = \ - ((dat & 0xf800) >> 8) | \ - ((dat & 0xf800) >> 13); \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_RGB565() \ + do { \ + for (uint8_t c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = \ + ((dat & 0x001f) << 3) | \ + ((dat & 0x001f) >> 2); \ + g[x_write + c] = \ + ((dat & 0x07e0) >> 3) | \ + ((dat & 0x07e0) >> 9); \ + b[x_write + c] = \ + ((dat & 0xf800) >> 8) | \ + ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define DECODE_RGB888() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 3; \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_RGB888() \ + do { \ + for (uint8_t c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 3; \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define DECODE_XRGB8888() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 4; \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_XRGB8888() \ + do { \ + for (uint8_t c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 4; \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define OVERLAY_SAMPLE() \ - do { \ - switch (virge->streams.sdif) { \ - case 1: \ - DECODE_YCbCr(); \ - break; \ - case 2: \ - DECODE_YUV422(); \ - break; \ - case 3: \ - DECODE_RGB555(); \ - break; \ - case 4: \ - DECODE_YUV211(); \ - break; \ - case 5: \ - DECODE_RGB565(); \ - break; \ - case 6: \ - DECODE_RGB888(); \ - break; \ - case 7: \ - default: \ - DECODE_XRGB8888(); \ - break; \ - } \ +#define OVERLAY_SAMPLE() \ + do { \ + switch (virge->streams.sdif) { \ + case 1: \ + DECODE_YCbCr(); \ + break; \ + case 2: \ + DECODE_YUV422(); \ + break; \ + case 3: \ + DECODE_RGB555(); \ + break; \ + case 4: \ + DECODE_YUV211(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + case 6: \ + DECODE_RGB888(); \ + break; \ + case 7: \ + default: \ + DECODE_XRGB8888(); \ + break; \ + } \ } while (0) static void diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index e9fbe57f2..88c26437a 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -112,8 +112,7 @@ typedef struct tgui_t { uint8_t int_line; uint8_t pci_regs[256]; - struct - { + struct { int16_t src_x, src_y; int16_t src_x_clip, src_y_clip; int16_t dst_x, dst_y; @@ -350,7 +349,9 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) if (tgui->ramdac_state == 4) { tgui->ramdac_state = 0; tgui->ramdac_ctrl = val; - //pclog("TGUI ramdac ctrl=%02x.\n", (tgui->ramdac_ctrl >> 4) & 0x0f); +#if 0 + pclog("TGUI ramdac ctrl=%02x.\n", (tgui->ramdac_ctrl >> 4) & 0x0f); +#endif svga_recalctimings(svga); return; } @@ -718,7 +719,9 @@ tgui_recalctimings(svga_t *svga) if (((svga->crtc[0x29] & 0x30) && (svga->bpp >= 15)) || !svga->rowoffset) svga->rowoffset |= 0x100; - //pclog("BPP=%d, DataWidth=%02x, CRTC29 bit 4-5=%02x, pixbusmode=%02x, rowoffset=%02x, doublerowoffset=%x.\n", svga->bpp, svga->crtc[0x2a] & 0x40, svga->crtc[0x29] & 0x30, svga->crtc[0x38], svga->rowoffset, svga->gdcreg[0x2f] & 4); +#if 0 + pclog("BPP=%d, DataWidth=%02x, CRTC29 bit 4-5=%02x, pixbusmode=%02x, rowoffset=%02x, doublerowoffset=%x.\n", svga->bpp, svga->crtc[0x2a] & 0x40, svga->crtc[0x29] & 0x30, svga->crtc[0x38], svga->rowoffset, svga->gdcreg[0x2f] & 4); +#endif if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; @@ -1468,15 +1471,15 @@ enum { } \ } while (0) -#define WRITE(addr, dat) \ - if (tgui->accel.bpp == 0) { \ - svga->vram[(addr) &tgui->vram_mask] = dat; \ +#define WRITE(addr, dat) \ + if (tgui->accel.bpp == 0) { \ + svga->vram[(addr) &tgui->vram_mask] = dat; \ svga->changedvram[((addr) & (tgui->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; \ - } else if (tgui->accel.bpp == 1) { \ - vram_w[(addr) & (tgui->vram_mask >> 1)] = dat; \ + } else if (tgui->accel.bpp == 1) { \ + vram_w[(addr) & (tgui->vram_mask >> 1)] = dat; \ svga->changedvram[((addr) & (tgui->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ - } else { \ - vram_l[(addr) & (tgui->vram_mask >> 2)] = dat; \ + } else { \ + vram_l[(addr) & (tgui->vram_mask >> 2)] = dat; \ svga->changedvram[((addr) & (tgui->vram_mask >> 2)) >> 10] = svga->monitor->mon_changeframecount; \ } @@ -2115,7 +2118,9 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *priv) case 0x2123: tgui->accel.ger22 = (tgui->accel.ger22 & 0xff) | (val << 8); - //pclog("Pitch IO23: val = %02x, rowoffset = %x.\n", tgui->accel.ger22, svga->crtc[0x13]); +#if 0 + pclog("Pitch IO23: val = %02x, rowoffset = %x.\n", tgui->accel.ger22, svga->crtc[0x13]); +#endif switch (svga->bpp) { case 8: case 24: diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index ebd92d983..d2c694a4c 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -441,7 +441,9 @@ banshee_updatemapping(banshee_t *banshee) svga_t *svga = &banshee->svga; if (!(banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - // banshee_log("Update mapping - PCI disabled\n"); +#if 0 + banshee_log("Update mapping - PCI disabled\n"); +#endif mem_mapping_disable(&svga->mapping); mem_mapping_disable(&banshee->linear_mapping); mem_mapping_disable(&banshee->reg_mapping_low); @@ -1082,7 +1084,9 @@ banshee_ext_in(uint16_t addr, void *priv) break; } - // banshee_log("banshee_ext_in: addr=%04x val=%02x\n", addr, ret); +#if 0 + banshee_log("banshee_ext_in: addr=%04x val=%02x\n", addr, ret); +#endif return ret; } @@ -1273,7 +1277,9 @@ banshee_ext_inl(uint16_t addr, void *priv) break; default: - // fatal("bad banshee_ext_inl: addr=%04x\n", addr); +#if 0 + fatal("bad banshee_ext_inl: addr=%04x\n", addr); +#endif break; } @@ -1334,17 +1340,23 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) case cmdBaseAddr0: ret = voodoo->cmdfifo_base >> 12; - // banshee_log("Read cmdfifo_base %08x\n", ret); +#if 0 + banshee_log("Read cmdfifo_base %08x\n", ret); +#endif break; case cmdRdPtrL0: ret = voodoo->cmdfifo_rp; - // banshee_log("Read cmdfifo_rp %08x\n", ret); +#if 0 + banshee_log("Read cmdfifo_rp %08x\n", ret); +#endif break; case cmdFifoDepth0: ret = voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd; - // banshee_log("Read cmdfifo_depth %08x\n", ret); +#if 0 + banshee_log("Read cmdfifo_depth %08x\n", ret); +#endif break; case cmdStatus0: @@ -1357,17 +1369,23 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) case cmdBaseAddr1: ret = voodoo->cmdfifo_base_2 >> 12; - // banshee_log("Read cmdfifo_base %08x\n", ret); +#if 0 + banshee_log("Read cmdfifo_base %08x\n", ret); +#endif break; case cmdRdPtrL1: ret = voodoo->cmdfifo_rp_2; - // banshee_log("Read cmdfifo_rp %08x\n", ret); +#if 0 + banshee_log("Read cmdfifo_rp %08x\n", ret); +#endif break; case cmdFifoDepth1: ret = voodoo->cmdfifo_depth_wr_2 - voodoo->cmdfifo_depth_rd_2; - // banshee_log("Read cmdfifo_depth %08x\n", ret); +#if 0 + banshee_log("Read cmdfifo_depth %08x\n", ret); +#endif break; case cmdStatus1: @@ -2833,7 +2851,9 @@ banshee_pci_read(int func, int addr, void *priv) if (func) return 0xff; - // banshee_log("Banshee PCI read %08X ", addr); +#if 0 + banshee_log("Banshee PCI read %08X ", addr); +#endif switch (addr) { case 0x00: ret = 0x1a; diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index d8f812f7f..cc52fc61a 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -43,8 +43,7 @@ typedef struct voodoo_state_t { int xstart, xend, xdir; uint32_t base_r, base_g, base_b, base_a, base_z; - struct - { + struct { int64_t base_s, base_t, base_w; int lod; } tmu[2]; @@ -1424,11 +1423,14 @@ voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) if ((params->vertexAy & 0xf) > 8) dy += 16; - /* voodoo_render_log("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0, - (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, - (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, - (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, - (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode);*/ +#if 0 +voodoo_render_log("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", + odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0, + (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, + (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, + (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, + (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode); +#endif state.base_r = params->startR; state.base_g = params->startG; diff --git a/src/video/vid_voodoo_setup.c b/src/video/vid_voodoo_setup.c index e1d13ba35..11f4ff861 100644 --- a/src/video/vid_voodoo_setup.c +++ b/src/video/vid_voodoo_setup.c @@ -191,8 +191,8 @@ voodoo_triangle_setup(voodoo_t *voodoo) voodoo->params.dWdX = (int64_t) (((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f); voodoo->params.dWdY = (int64_t) (((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f); voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW; - voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; - voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; + voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; + voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; } if (voodoo->sSetupMode & SETUPMODE_W0) { voodoo->params.tmu[0].startW = (int64_t) (verts[va].sW0 * 4294967296.0f); diff --git a/src/video/vid_voodoo_texture.c b/src/video/vid_voodoo_texture.c index 3939db3cd..f6894ec0f 100644 --- a/src/video/vid_voodoo_texture.c +++ b/src/video/vid_voodoo_texture.c @@ -61,10 +61,10 @@ voodoo_texture_log(const char *fmt, ...) void voodoo_recalc_tex12(voodoo_t *voodoo, int tmu) { - int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; - int width = 256; - int height = 256; - int shift = 8; + int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; + int width = 256; + int height = 256; + int shift = 8; uint32_t base = voodoo->params.texBaseAddr[tmu]; uint32_t offset = 0; int tex_lod = 0; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index fb27b8b2c..f5d46f937 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -856,18 +856,18 @@ xga_ext_inb(uint16_t addr, void *priv) return ret; } -#define READ(addr, dat) \ +#define READ(addr, dat) \ dat = xga->vram[(addr) & (xga->vram_mask)]; -#define WRITE(addr, dat) \ - xga->vram[((addr)) & (xga->vram_mask)] = dat; \ +#define WRITE(addr, dat) \ + xga->vram[((addr)) & (xga->vram_mask)] = dat; \ xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; -#define READW(addr, dat) \ +#define READW(addr, dat) \ dat = *(uint16_t *) &xga->vram[(addr) & (xga->vram_mask)]; -#define WRITEW(addr, dat) \ - *(uint16_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \ +#define WRITEW(addr, dat) \ + *(uint16_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \ xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; #define ROP(mix, d, s) \ @@ -928,7 +928,7 @@ xga_ext_inb(uint16_t addr, void *priv) d = MIN(s, d); \ break; \ case 0x12: \ - d = MIN(~0, s + d); \ + d = MIN(~0, s + d); \ break; \ case 0x13: \ d = MAX(0, d - s); \ From d5d1d5c449e013256941cbbe8576b34e85eed426 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 3 Feb 2025 20:00:58 -0500 Subject: [PATCH 0208/1190] More cleanups to device structs --- src/cdrom/cdrom_mitsumi.c | 4 +- src/device.c | 2 +- src/device/isamem.c | 1159 ++++++----- src/device/isartc.c | 70 +- src/device/keyboard_at.c | 21 +- src/device/mouse_bus.c | 133 +- src/device/mouse_microtouch_touchscreen.c | 61 +- src/device/mouse_ps2.c | 19 +- src/device/mouse_serial.c | 161 +- src/device/mouse_wacom_tablet.c | 17 +- src/device/novell_cardkey.c | 18 +- src/device/serial_passthrough.c | 191 +- src/device/unittester.c | 30 +- src/disk/hdc_ide.c | 39 +- src/disk/hdc_st506_xt.c | 399 ++-- src/disk/hdc_xta.c | 87 +- src/disk/hdc_xtide.c | 74 +- src/disk/lba_enhancer.c | 31 +- src/floppy/fdc_compaticard.c | 64 +- src/floppy/fdc_magitronic.c | 19 +- src/floppy/fdc_monster.c | 153 +- src/floppy/fdc_pii15xb.c | 19 +- src/game/gameport.c | 64 +- src/network/net_3c501.c | 61 +- src/network/net_3c503.c | 87 +- src/network/net_modem.c | 83 +- src/network/net_ne2000.c | 383 ++-- src/network/net_pcnet.c | 147 +- src/network/net_rtl8139.c | 14 +- src/network/net_tulip.c | 42 +- src/network/net_wd8003.c | 274 +-- src/scsi/scsi_aha154x.c | 290 +-- src/scsi/scsi_buslogic.c | 82 +- src/scsi/scsi_ncr53c400.c | 203 +- src/scsi/scsi_ncr53c8xx.c | 17 +- src/scsi/scsi_pcscsi.c | 14 +- src/scsi/scsi_spock.c | 17 +- src/scsi/scsi_t128.c | 49 +- src/sound/midi_fluidsynth.c | 235 ++- src/sound/midi_mt32.c | 76 +- src/sound/midi_rtmidi.cpp | 70 +- src/sound/snd_adlibgold.c | 114 +- src/sound/snd_audiopci.c | 155 +- src/sound/snd_azt2316a.c | 415 ++-- src/sound/snd_cmi8x38.c | 42 +- src/sound/snd_cms.c | 53 +- src/sound/snd_gus.c | 127 +- src/sound/snd_mpu401.c | 209 +- src/sound/snd_opl2board.c | 14 +- src/sound/snd_optimc.c | 28 +- src/sound/snd_pas16.c | 42 +- src/sound/snd_pssj.c | 51 +- src/sound/snd_sb.c | 2246 +++++++++------------ src/sound/snd_sn76489.c | 51 +- src/sound/snd_ssi2001.c | 69 +- src/sound/snd_wss.c | 55 +- src/video/vid_8514a.c | 172 +- src/video/vid_ati18800.c | 28 +- src/video/vid_ati28800.c | 70 +- src/video/vid_ati_mach64.c | 65 +- src/video/vid_ati_mach8.c | 140 +- src/video/vid_bochs_vbe.c | 63 +- src/video/vid_cga.c | 163 +- src/video/vid_cl54xx.c | 244 +-- src/video/vid_colorplus.c | 73 +- src/video/vid_ega.c | 93 +- src/video/vid_et3000.c | 22 +- src/video/vid_et4000.c | 183 +- src/video/vid_et4000w32.c | 30 +- src/video/vid_hercules.c | 53 +- src/video/vid_herculesplus.c | 53 +- src/video/vid_ht216.c | 40 +- src/video/vid_mda.c | 40 +- src/video/vid_mga.c | 62 +- src/video/vid_nga.c | 128 +- src/video/vid_oak_oti.c | 130 +- src/video/vid_ogc.c | 53 +- src/video/vid_paradise.c | 65 +- src/video/vid_rtg310x.c | 65 +- src/video/vid_s3.c | 98 +- src/video/vid_s3_virge.c | 191 +- src/video/vid_sigma.c | 139 +- src/video/vid_tgui9440.c | 61 +- src/video/vid_tvga.c | 35 +- src/video/vid_voodoo.c | 184 +- src/video/vid_voodoo_banshee.c | 395 ++-- src/video/vid_xga.c | 183 +- 87 files changed, 5883 insertions(+), 6088 deletions(-) diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c index 19fa06e23..7ef8a04b2 100644 --- a/src/cdrom/cdrom_mitsumi.c +++ b/src/cdrom/cdrom_mitsumi.c @@ -460,11 +460,11 @@ const device_t mitsumi_cdrom_device = { .name = "Mitsumi CD-ROM interface", .internal_name = "mcd", .flags = DEVICE_ISA | DEVICE_AT, - .local = 1, + .local = 0, .init = mitsumi_cdrom_init, .close = mitsumi_cdrom_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device.c b/src/device.c index 55552ead4..1228eedd2 100644 --- a/src/device.c +++ b/src/device.c @@ -883,7 +883,7 @@ machine_get_config_string(char *str) return NULL; } -const device_t* +const device_t * device_context_get_device(void) { return device_current.dev; diff --git a/src/device/isamem.c b/src/device/isamem.c index 5cac31c7f..45a0413be 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -851,32 +851,34 @@ isamem_close(void *priv) static const device_config_t ibmxt_32k_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 32, - .file_filter = "", - .spinner = { - .min = 32, - .max = 576, - .step = 32 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 32, + .file_filter = NULL, + .spinner = { + .min = 32, + .max = 576, + .step = 32 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 0, - .max = 608, - .step = 32 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 608, + .step = 32 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -899,32 +901,34 @@ static const device_t ibmxt_32k_device = { static const device_config_t ibmxt_64k_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 64, - .max = 576, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 64, + .max = 576, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 0, - .max = 576, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 576, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -947,32 +951,34 @@ static const device_t ibmxt_64k_device = { static const device_config_t ibmxt_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 128, - .file_filter = "", - .spinner = { - .min = 64, - .max = 576, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 128, + .file_filter = NULL, + .spinner = { + .min = 64, + .max = 576, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 256, - .file_filter = "", - .spinner = { - .min = 0, - .max = 576, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 576, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -995,32 +1001,34 @@ static const device_t ibmxt_device = { static const device_config_t genericxt_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 16, - .file_filter = "", - .spinner = { - .min = 0, - .max = 640, - .step = 16 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 16, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 640, + .step = 16 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 624, - .step = 16 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 624, + .step = 16 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1044,32 +1052,34 @@ static const device_t genericxt_device = { static const device_config_t msramcard_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 0, - .max = 256, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 256, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 624, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 624, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1092,32 +1102,34 @@ static const device_t msramcard_device = { static const device_config_t mssystemcard_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 0, - .max = 256, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 256, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 624, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 624, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1154,32 +1166,34 @@ static const device_t ibmat_128k_device = { static const device_config_t ibmat_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { - .min = 0, - .max = 12288, - .step = 512 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 12288, + .step = 512 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 1024, - .file_filter = "", - .spinner = { - .min = 0, - .max = 15872, - .step = 512 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 15872, + .step = 512 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1202,32 +1216,34 @@ static const device_t ibmat_device = { static const device_config_t genericat_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { - .min = 0, - .max = 16384, - .step = 128 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 16384, + .step = 128 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 1024, - .file_filter = "", - .spinner = { - .min = 0, - .max = 15872, - .step = 128 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 15872, + .step = 128 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1251,32 +1267,34 @@ static const device_t genericat_device = { static const device_config_t p5pak_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 128, - .file_filter = "", - .spinner = { - .min = 0, - .max = 384, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 128, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 384, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { - .min = 64, - .max = 576, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { + .min = 64, + .max = 576, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1299,32 +1317,34 @@ static const device_t p5pak_device = { static const device_config_t a6pak_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 0, - .max = 384, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 384, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 256, - .file_filter = "", - .spinner = { - .min = 64, - .max = 512, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { + .min = 64, + .max = 512, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1347,28 +1367,29 @@ static const device_t a6pak_device = { static const device_config_t ems5150_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 256, - .file_filter = "", - .spinner = { - .min = 0, - .max = 2048, - .step = 64 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 2048, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x0000 }, { .description = "Board 1", .value = 0x0208 }, { .description = "Board 2", .value = 0x020a }, @@ -1376,6 +1397,7 @@ static const device_config_t ems5150_config[] = { { .description = "Board 4", .value = 0x020e }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1398,98 +1420,104 @@ static const device_t ems5150_device = { static const device_config_t ev159_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { - .min = 0, - .max = 3072, - .step = 512 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 3072, + .step = 512 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 16128, - .step = 128 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 16128, + .step = 128 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "length", - .description = "Contiguous Size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 16384, - .step = 128 + .name = "length", + .description = "Contiguous Size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 16384, + .step = 128 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "width", - .description = "I/O Width", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "8-bit", .value = 0 }, { .description = "16-bit", .value = 1 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "speed", - .description = "Transfer Speed", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Standard (150ns)", .value = 0 }, { .description = "High-Speed (120ns)", .value = 1 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "ems", - .description = "EMS mode", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ems", + .description = "EMS mode", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "Enabled", .value = 1 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0258, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0258, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, @@ -1499,16 +1527,17 @@ static const device_config_t ev159_config[] = { { .description = "2E8H", .value = 0x02E8 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "base2", - .description = "Address for > 2 MB", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0268, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base2", + .description = "Address for > 2 MB", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0268, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, @@ -1518,6 +1547,7 @@ static const device_config_t ev159_config[] = { { .description = "2E8H", .value = 0x02E8 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1540,70 +1570,74 @@ static const device_t ev159_device = { static const device_config_t ev165a_config[] = { // clang-format off { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 256, - .file_filter = "", - .spinner = { - .min = 0, - .max = 2048, - .step = 256 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 2048, + .step = 256 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 64, - .file_filter = "", - .spinner = { - .min = 64, - .max = 640, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { + .min = 64, + .max = 640, + .step = 64 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "length", .description = "Contiguous Size", .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 2048, - .step = 256 + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 2048, + .step = 256 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "ems", - .description = "EMS mode", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ems", + .description = "EMS mode", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "Enabled", .value = 1 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0258, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0258, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, @@ -1613,6 +1647,7 @@ static const device_config_t ev165a_config[] = { { .description = "2E8H", .value = 0x02E8 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1635,48 +1670,51 @@ static const device_t ev165a_device = { static const device_config_t brxt_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0268, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0268, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, { .description = "268H", .value = 0x0268 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "frame", - .description = "Frame Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "D000H", .value = 0xD0000 }, - { .description = "E000H", .value = 0xE0000 }, - { .description = "" } + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "D000H", .value = 0xD0000 }, + { .description = "E000H", .value = 0xE0000 }, + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { - .min = 0, - .max = 2048, - .step = 512 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 2048, + .step = 512 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1700,89 +1738,96 @@ static const device_t brxt_device = { static const device_config_t brat_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0268, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0268, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, { .description = "268H", .value = 0x0268 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "frame", - .description = "Frame Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "D000H", .value = 0xD0000 }, { .description = "E000H", .value = 0xE0000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "width", - .description = "I/O Width", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 8, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 8, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "8-bit", .value = 8 }, { .description = "16-bit", .value = 16 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "speed", - .description = "Transfer Speed", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Standard", .value = 0 }, { .description = "High-Speed", .value = 1 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { - .min = 0, - .max = 4096, - .step = 512 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 4096, + .step = 512 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { - .min = 0, - .max = 14336, - .step = 512 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 14336, + .step = 512 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1806,66 +1851,69 @@ static const device_t brat_device = { static const device_config_t lotech_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0260, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0260, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "260H", .value = 0x0260 }, { .description = "264H", .value = 0x0264 }, { .description = "268H", .value = 0x0268 }, { .description = "26CH", .value = 0x026C }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "frame", - .description = "Frame Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xe0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xe0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C000H", .value = 0xC0000 }, { .description = "D000H", .value = 0xD0000 }, { .description = "E000H", .value = 0xE0000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 2048, - .file_filter = "", - .spinner = { - .min = 512, - .max = 4096, - .step = 512 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 2048, + .file_filter = NULL, + .spinner = { + .min = 512, + .max = 4096, + .step = 512 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; static const device_t lotech_ems_device = { - .name = "Lo-tech EMS Board", + .name = "Lo-tech EMS Board", .internal_name = "lotechems", - .flags = DEVICE_ISA, - .local = ISAMEM_LOTECH_EMS_CARD, - .init = isamem_init, - .close = isamem_close, - .reset = NULL, + .flags = DEVICE_ISA, + .local = ISAMEM_LOTECH_EMS_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, .available = NULL, .speed_changed = NULL, - .force_redraw = NULL, - .config = lotech_config + .force_redraw = NULL, + .config = lotech_config }; #ifdef USE_ISAMEM_RAMPAGE @@ -1874,14 +1922,14 @@ static const device_t lotech_ems_device = { static const device_config_t rampage_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0218, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0218, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, @@ -1891,33 +1939,37 @@ static const device_config_t rampage_config[] = { { .description = "2E8H", .value = 0x02E8 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 256, /* Technically 128k, but banks 2-7 must be 256, headaches elsewise */ - .file_filter = "", - .spinner = { - .min = 256, - .max = 2048, - .step = 256 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 256, /* Technically 128k, but banks 2-7 must be 256, headaches elsewise */ + .file_filter = NULL, + .spinner = { + .min = 256, + .max = 2048, + .step = 256 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "start", - .description = "Start Address", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 640, - .file_filter = "", - .spinner = { - .min = 0, - .max = 640, - .step = 64 + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 640, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 640, + .step = 64 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1942,14 +1994,14 @@ static const device_t rampage_device = { static const device_config_t iab_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0258, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0258, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "208H", .value = 0x0208 }, { .description = "218H", .value = 0x0218 }, { .description = "258H", .value = 0x0258 }, @@ -1959,64 +2011,69 @@ static const device_config_t iab_config[] = { { .description = "2E8H", .value = 0x02E8 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "frame", - .description = "Frame Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C000H", .value = 0xC0000 }, { .description = "D000H", .value = 0xD0000 }, { .description = "E000H", .value = 0xE0000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "width", - .description = "I/O Width", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 8, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 8, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "8-bit", .value = 8 }, { .description = "16-bit", .value = 16 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "speed", - .description = "Transfer Speed", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Standard", .value = 0 }, { .description = "High-Speed", .value = 1 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "size", - .description = "Memory size", - .type = CONFIG_SPINNER, - .default_string = "", - .default_int = 128, - .file_filter = "", - .spinner = { - .min = 0, - .max = 8192, - .step = 128 + .name = "size", + .description = "Memory size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 128, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 8192, + .step = 128 }, - .selection = { { 0 } } + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/isartc.c b/src/device/isartc.c index f24ffb72b..63ce0b065 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -631,23 +631,24 @@ static const device_config_t ev170_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x02C0, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "240H", .value = 0x0240 }, { .description = "2C0H", .value = 0x02c0 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = -1, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "Disabled", .value = -1 }, @@ -656,6 +657,7 @@ static const device_config_t ev170_config[] = { { .description = "IRQ7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -681,15 +683,16 @@ static const device_config_t pii147_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x0240, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "Clock 1", .value = 0x0240 }, { .description = "Clock 2", .value = 0x0340 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -715,9 +718,9 @@ static const device_config_t p5pak_config[] = { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = -1, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "Disabled", -1 }, @@ -726,6 +729,7 @@ static const device_config_t p5pak_config[] = { { .description = "IRQ5", 5 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -751,9 +755,9 @@ static const device_config_t a6pak_config[] = { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = -1, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "Disabled", .value = -1 }, @@ -762,6 +766,7 @@ static const device_config_t a6pak_config[] = { { .description = "IRQ5", .value = 5 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -787,42 +792,44 @@ static const device_config_t mm58167_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x02C0, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { "240H", 0x0240 }, - { "2C0H", 0x02c0 }, - { "340H", 0x0340 }, - { "" } + { .description = "240H", .value = 0x0240 }, + { .description = "2C0H", .value = 0x02c0 }, + { .description = "340H", .value = 0x0340 }, + { .description = "" } }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = -1, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { "Disabled", -1 }, - { "IRQ2", 2 }, - { "IRQ5", 5 }, - { "IRQ7", 7 }, - { "" } + { .description = "Disabled", .value = -1 }, + { .description = "IRQ2", .value = 2 }, + { .description = "IRQ5", .value = 5 }, + { .description = "IRQ7", .value = 7 }, + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xcc000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xcc000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = -1 }, { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, @@ -846,6 +853,7 @@ static const device_config_t mm58167_config[] = { { .description = "EE00H", .value = 0xee000 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index af3d5d5fc..9b3f06098 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2187,14 +2187,14 @@ keyboard_at_close(void *priv) static const device_config_t keyboard_at_config[] = { // clang-format off { - .name = "type", - .description = "Type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "type", + .description = "Type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "AT 84-key", .value = FLAG_AT | KBD_84_KEY }, { .description = "AT 101/102/106-key", .value = FLAG_AT | KBD_101_KEY }, { .description = "AT Korean", .value = FLAG_AT | KBD_KOREAN }, @@ -2203,7 +2203,8 @@ static const device_config_t keyboard_at_config[] = { { .description = "PS/2 106-key JIS", .value = FLAG_PS2 | KBD_JIS }, { .description = "PS/2 Korean", .value = FLAG_PS2 | KBD_KOREAN }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END @@ -2220,7 +2221,7 @@ const device_t keyboard_at_generic_device = { .init = keyboard_at_init, .close = keyboard_at_close, .reset = NULL, - { .poll = NULL }, + .poll = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = keyboard_at_config diff --git a/src/device/mouse_bus.c b/src/device/mouse_bus.c index b56a3cc18..c0f161dbd 100644 --- a/src/device/mouse_bus.c +++ b/src/device/mouse_bus.c @@ -686,66 +686,70 @@ bm_init(const device_t *info) static const device_config_t lt_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x23c, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x23c, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x230", .value = 0x230 }, { .description = "0x234", .value = 0x234 }, { .description = "0x238", .value = 0x238 }, { .description = "0x23C", .value = 0x23c }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "hz", - .description = "Hz", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 45, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "hz", + .description = "Hz", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 45, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Non-timed (original)", .value = 0 }, { .description = "30 Hz (JMP2 = 1)", .value = 30 }, { .description = "45 Hz (JMP2 not populated)", .value = 45 }, { .description = "60 Hz (JMP2 = 2)", .value = 60 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Two", .value = 2 }, { .description = "Three", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -754,50 +758,53 @@ static const device_config_t lt_config[] = { static const device_config_t ms_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x23c, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x23c, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x230", .value = 0x230 }, { .description = "0x234", .value = 0x234 }, { .description = "0x238", .value = 0x238 }, { .description = "0x23C", .value = 0x23c }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Two", .value = 2 }, { .description = "Three", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/mouse_microtouch_touchscreen.c b/src/device/mouse_microtouch_touchscreen.c index 24d5de1fb..15b42bfdd 100644 --- a/src/device/mouse_microtouch_touchscreen.c +++ b/src/device/mouse_microtouch_touchscreen.c @@ -549,42 +549,49 @@ mtouch_close(void *priv) static const device_config_t mtouch_config[] = { // clang-format off { - .name = "port", - .description = "Serial Port", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "COM1", .value = 0 }, { .description = "COM2", .value = 1 }, { .description = "COM3", .value = 2 }, { .description = "COM4", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "identity", - .description = "Controller", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { - { .description = "A3 - SMT2 Serial / SMT3(R)V", .value = 0 }, - { .description = "A4 - SMT2 PCBus", .value = 1 }, - { .description = "P5 - TouchPen 4(+)", .value = 2 }, - { .description = "Q1 - SMT3(R) Serial", .value = 3 } - } + .name = "identity", + .description = "Controller", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "A3 - SMT2 Serial / SMT3(R)V", .value = 0 }, + { .description = "A4 - SMT2 PCBus", .value = 1 }, + { .description = "P5 - TouchPen 4(+)", .value = 2 }, + { .description = "Q1 - SMT3(R) Serial", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "crosshair", - .description = "Show Crosshair", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "crosshair", + .description = "Show Crosshair", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 53af97b78..9afc75410 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -367,20 +367,21 @@ ps2_close(void *priv) static const device_config_t ps2_config[] = { // clang-format off { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Two", .value = 2 }, { .description = "Three", .value = 3 }, { .description = "Wheel", .value = 4 }, { .description = "Five + Wheel", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index c64be5a6d..be9bc62e1 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -916,41 +916,47 @@ sermouse_init(const device_t *info) static const device_config_t msssermouse_config[] = { // clang-format off { - .name = "port", - .description = "Serial Port", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "COM1", .value = 0 }, { .description = "COM2", .value = 1 }, { .description = "COM3", .value = 2 }, { .description = "COM4", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Two", .value = 2 }, { .description = "Three", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "rts_toggle", - .description = "RTS toggle", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "rts_toggle", + .description = "RTS toggle", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -959,35 +965,37 @@ static const device_config_t msssermouse_config[] = { static const device_config_t mssermouse_config[] = { // clang-format off { - .name = "port", - .description = "Serial Port", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "COM1", .value = 0 }, { .description = "COM2", .value = 1 }, { .description = "COM3", .value = 2 }, { .description = "COM4", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Two", .value = 2 }, { .description = "Three", .value = 3 }, { .description = "Wheel", .value = 4 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -996,57 +1004,64 @@ static const device_config_t mssermouse_config[] = { static const device_config_t ltsermouse_config[] = { // clang-format off { - .name = "port", - .description = "Serial Port", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "COM1", .value = 0 }, { .description = "COM2", .value = 1 }, { .description = "COM3", .value = 2 }, { .description = "COM4", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Two", .value = 2 }, { .description = "Three", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "revision", - .description = "Revision", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "revision", + .description = "Revision", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "LOGIMOUSE R7 1.0", .value = 1 }, { .description = "LOGIMOUSE R7 2.0", .value = 2 }, { .description = "LOGIMOUSE C7 3.0", .value = 3 }, { .description = "Logitech MouseMan", .value = 4 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "rts_toggle", - .description = "RTS toggle", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "rts_toggle", + .description = "RTS toggle", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c index d74e58411..79b674e07 100644 --- a/src/device/mouse_wacom_tablet.c +++ b/src/device/mouse_wacom_tablet.c @@ -693,20 +693,21 @@ wacom_close(void *priv) static const device_config_t wacom_config[] = { // clang-format off { - .name = "port", - .description = "Serial Port", - .type = CONFIG_SELECTION, + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { { .description = "COM1", .value = 0 }, { .description = "COM2", .value = 1 }, { .description = "COM3", .value = 2 }, { .description = "COM4", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index 34b6390d1..8820addde 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -27,8 +27,7 @@ #include <86box/plat.h> #include <86box/novell_cardkey.h> -typedef struct novell_cardkey_t -{ +typedef struct novell_cardkey_t { char serial_number_str[13]; } novell_cardkey_t; @@ -95,14 +94,15 @@ void novell_cardkey_close(void* priv) static const device_config_t keycard_config[] = { // clang-format off { - .name = "serial_number", - .description = "Serial Number", - .type = CONFIG_STRING, + .name = "serial_number", + .description = "Serial Number", + .type = CONFIG_STRING, .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { { 0 } } + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index bb2378a22..256f9eaa9 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -231,138 +231,129 @@ const char *serpt_mode_names[SERPT_MODES_MAX] = { // clang-format off static const device_config_t serial_passthrough_config[] = { { - .name = "mode", - .description = "Passthrough Mode", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "mode", + .description = "Passthrough Mode", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { #ifdef _WIN32 - { - .description = "Named Pipe (Server)", - .value = SERPT_MODE_VCON - }, + { .description = "Named Pipe (Server)", .value = SERPT_MODE_VCON }, #if 0 /* TODO */ - { - .description = "Named Pipe (Client)", - .value = SERPT_MODE_VCON - }, -#endif -#else - { - .description = "Pseudo Terminal/Virtual Console", - .value = SERPT_MODE_VCON - }, + { .description = "Named Pipe (Client)", .value = SERPT_MODE_VCON }, #endif +#else /* _WIN32 */ + { .description = "Pseudo Terminal/Virtual Console", .value = SERPT_MODE_VCON }, +#endif /* _WIN32 */ #if 0 /* TODO */ - { - .description = "TCP Server", - .value = SERPT_MODE_TCPSRV - }, - { - .description = "TCP Client", - .value = SERPT_MODE_TCPCLNT - }, + { .description = "TCP Server", .value = SERPT_MODE_TCPSRV }, + { .description = "TCP Client", .value = SERPT_MODE_TCPCLNT }, #endif - { - .description = "Host Serial Passthrough", - .value = SERPT_MODE_HOSTSER - }, - { - .description = "" - } - } + { .description = "Host Serial Passthrough", .value = SERPT_MODE_HOSTSER }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "host_serial_path", - .description = "Host Serial Device", - .type = CONFIG_SERPORT, - .default_string = "", - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } } + .name = "host_serial_path", + .description = "Host Serial Device", + .type = CONFIG_SERPORT, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, #ifdef _WIN32 { - .name = "named_pipe", - .description = "Name of pipe", - .type = CONFIG_STRING, + .name = "named_pipe", + .description = "Name of pipe", + .type = CONFIG_STRING, .default_string = "\\\\.\\pipe\\86Box\\test", - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } } + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, -#endif +#endif /* _WIN32 */ { - .name = "data_bits", - .description = "Data bits", - .type = CONFIG_SELECTION, - .default_string = "8", - .default_int = 8, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { + .name = "data_bits", + .description = "Data bits", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 8, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { #if 0 /* Mentioned by WFW 3.1x, not supported, atleast on Linux */ { .description = "4", .value = 4 }, #endif { .description = "5", .value = 5 }, { .description = "6", .value = 6 }, { .description = "7", .value = 7 }, - { .description = "8", .value = 8 } - } + { .description = "8", .value = 8 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "stop_bits", - .description = "Stop bits", - .type = CONFIG_SELECTION, - .default_string = "1", - .default_int = 1, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { + .name = "stop_bits", + .description = "Stop bits", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "1", .value = 1 }, #if 0 { .description = "1.5", .value = 1.5 }, #endif - { .description = "2", .value = 2 } - } + { .description = "2", .value = 2 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "baudrate", - .description = "Baud Rate of Passthrough", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 115200, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { + .name = "baudrate", + .description = "Baud Rate of Passthrough", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 115200, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { #if 0 - { .description = "256000", .value = 256000 }, - { .description = "128000", .value = 128000 }, + { .description = "256000", .value = 256000 }, + { .description = "128000", .value = 128000 }, #endif - { .description = "115200", .value = 115200 }, - { .description = "57600", .value = 57600 }, - { .description = "56000", .value = 56000 }, - { .description = "38400", .value = 38400 }, - { .description = "19200", .value = 19200 }, - { .description = "14400", .value = 14400 }, - { .description = "9600", .value = 9600 }, - { .description = "7200", .value = 7200 }, - { .description = "4800", .value = 4800 }, - { .description = "2400", .value = 2400 }, - { .description = "1800", .value = 1800 }, - { .description = "1200", .value = 1200 }, - { .description = "600", .value = 600 }, - { .description = "300", .value = 300 }, - { .description = "150", .value = 150 }, + { .description = "115200", .value = 115200 }, + { .description = "57600", .value = 57600 }, + { .description = "56000", .value = 56000 }, + { .description = "38400", .value = 38400 }, + { .description = "19200", .value = 19200 }, + { .description = "14400", .value = 14400 }, + { .description = "9600", .value = 9600 }, + { .description = "7200", .value = 7200 }, + { .description = "4800", .value = 4800 }, + { .description = "2400", .value = 2400 }, + { .description = "1800", .value = 1800 }, + { .description = "1200", .value = 1200 }, + { .description = "600", .value = 600 }, + { .description = "300", .value = 300 }, + { .description = "150", .value = 150 }, #if 0 { .description = "134.5", .value = 134.5 }, #endif - { .description = "110", .value = 110 }, - { .description = "75", .value = 75 } - } + { .description = "110", .value = 110 }, + { .description = "75", .value = 75 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/device/unittester.c b/src/device/unittester.c index 5f0fa5712..0e864aa0b 100644 --- a/src/device/unittester.c +++ b/src/device/unittester.c @@ -114,19 +114,6 @@ static struct unittester_state unittester_defaults = { .cmd_id = UT_CMD_NOOP, }; -static const device_config_t unittester_config[] = { -// clang-format off - { - .name = "exit_enabled", - .description = "Enable 0x04 \"Exit 86Box\" command", - .type = CONFIG_BINARY, - .default_int = 1, - .default_string = "" - }, - { .name = "", .description = "", .type = CONFIG_END } -// clang-format on -}; - /* Kept separate, as we will be reusing this object */ static bitmap_t *unittester_screen_buffer = NULL; @@ -624,6 +611,23 @@ unittester_close(UNUSED(void *priv)) unittester_log("[UT] 86Box Unit Tester closed\n"); } +static const device_config_t unittester_config[] = { + // clang-format off + { + .name = "exit_enabled", + .description = "Enable 0x04 \"Exit 86Box\" command", + .type = CONFIG_BINARY, + .default_int = 1, + .default_string = NULL, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t unittester_device = { .name = "86Box Unit Tester", .internal_name = "unittester", diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 592649c0e..1583d6b9c 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3359,18 +3359,17 @@ const device_t mcide_device = { .config = NULL }; - // clang-format off static const device_config_t ide_ter_config[] = { { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = HDC_TERTIARY_IRQ, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = HDC_TERTIARY_IRQ, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Plug and Play", .value = -1 }, { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, @@ -3382,21 +3381,22 @@ static const device_config_t ide_ter_config[] = { { .description = "IRQ 11", .value = 11 }, { .description = "IRQ 12", .value = 12 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ide_qua_config[] = { { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = HDC_QUATERNARY_IRQ, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = HDC_QUATERNARY_IRQ, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Plug and Play", .value = -1 }, { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, @@ -3408,7 +3408,8 @@ static const device_config_t ide_qua_config[] = { { .description = "IRQ 11", .value = 11 }, { .description = "IRQ 12", .value = 12 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 789e7e6c4..536fd76c0 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1914,335 +1914,356 @@ victor_v86p_available(void) // clang-format off static const device_config_t dtc_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "F400H", .value = 0xf4000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t st11_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "328H", .value = 0x0328 }, { .description = "32CH", .value = 0x032c }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "D000H", .value = 0xd0000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "E000H", .value = 0xe0000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "revision", - .description = "BIOS Revision", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 19, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "revision", + .description = "BIOS Revision", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 19, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "v1.7", .value = 5 }, { .description = "v2.0", .value = 19 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd_nobios_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd_rll_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "translate", - .description = "Translate 26 -> 17", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "translate", + .description = "Translate 26 -> 17", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Off", .value = 0 }, { .description = "On", .value = 1 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd1004a_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd1004_rll_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, { .description = "CC00H", .value = 0xcc000 }, { .description = "CE00H", .value = 0xce000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "328H", .value = 0x0328 }, { .description = "32CH", .value = 0x032c }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 5", .value = 5 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "translate", - .description = "Translate 26 -> 17", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "translate", + .description = "Translate 26 -> 17", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Off", .value = 0 }, { .description = "On", .value = 1 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 553e53b48..b01d80c61 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1107,60 +1107,77 @@ xta_close(void *priv) static const device_config_t wdxt150_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 4", .value = 4 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_rev", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios_rev", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "rev_1", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "Revision 1.0", .internal_name = "rev_1", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_1_BIOS_FILE, "" } }, - { .name = "Revision 2.0", .internal_name = "rev_2", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_2_BIOS_FILE, "" } }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Revision 1.0", + .internal_name = "rev_1", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { WD_REV_1_BIOS_FILE, "" } + }, + { + .name = "Revision 2.0", + .internal_name = "rev_2", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { WD_REV_2_BIOS_FILE, "" } + }, { .files_no = 0 } }, }, diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 7ec7695b3..4c071e596 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -224,18 +224,33 @@ xtide_at_close(void *priv) static const device_config_t xtide_config[] = { // clang-format off { - .name = "bios", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "xt", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } }, - { .name = "XT+ (V20/V30/8018x)", .internal_name = "xt_plus", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XTP, "" } }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Regular XT", + .internal_name = "xt", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { ROM_PATH_XT, "" } + }, + { + .name = "XT+ (V20/V30/8018x)", + .internal_name = "xt_plus", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { ROM_PATH_XTP, "" } + }, { .files_no = 0 } }, }, @@ -246,18 +261,33 @@ static const device_config_t xtide_config[] = { static const device_config_t xtide_at_config[] = { // clang-format off { - .name = "bios", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "at", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } }, - { .name = "386", .internal_name = "at_386", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT_386, "" } }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Regular AT", + .internal_name = "at", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { ROM_PATH_AT, "" } + }, + { + .name = "386", + .internal_name = "at_386", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { ROM_PATH_AT_386, "" } + }, { .files_no = 0 } }, }, diff --git a/src/disk/lba_enhancer.c b/src/disk/lba_enhancer.c index 8e8bc480d..429611b2d 100644 --- a/src/disk/lba_enhancer.c +++ b/src/disk/lba_enhancer.c @@ -63,22 +63,23 @@ lba_enhancer_available(void) // clang-format off static const device_config_t lba_enhancer_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "C800H", .value = 0xc8000 }, - { .description = "CC00H", .value = 0xcc000 }, - { .description = "D000H", .value = 0xd0000 }, - { .description = "D400H", .value = 0xd4000 }, - { .description = "D800H", .value = 0xd8000 }, - { .description = "DC00H", .value = 0xdc000 }, - { .description = "" } + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/floppy/fdc_compaticard.c b/src/floppy/fdc_compaticard.c index 4abc4abac..741105927 100644 --- a/src/floppy/fdc_compaticard.c +++ b/src/floppy/fdc_compaticard.c @@ -157,9 +157,9 @@ static const device_config_t compaticard_i_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x3f0, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "0x3f0", .value = 0x3f0 }, @@ -167,7 +167,8 @@ static const device_config_t compaticard_i_config[] = { { .description = "0x360", .value = 0x360 }, { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -179,9 +180,9 @@ static const device_config_t compaticard_ii_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x3f0, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "0x3f0", .value = 0x3f0 }, @@ -189,15 +190,16 @@ static const device_config_t compaticard_ii_config[] = { { .description = "0x360", .value = 0x360 }, { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 6, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "IRQ 2", .value = 2 }, @@ -207,22 +209,24 @@ static const device_config_t compaticard_ii_config[] = { { .description = "IRQ 6", .value = 6 }, { .description = "IRQ 7", .value = 7 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "dma", .description = "DMA channel", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 2, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "DMA 1", .value = 1 }, { .description = "DMA 2", .value = 2 }, { .description = "DMA 3", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -234,9 +238,9 @@ static const device_config_t compaticard_iv_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x3f0, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "0x3f0", .value = 0x3f0 }, @@ -244,15 +248,16 @@ static const device_config_t compaticard_iv_config[] = { { .description = "0x360", .value = 0x360 }, { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 6, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "IRQ 2", .value = 2 }, @@ -262,30 +267,32 @@ static const device_config_t compaticard_iv_config[] = { { .description = "IRQ 6", .value = 6 }, { .description = "IRQ 7", .value = 7 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "dma", .description = "DMA channel", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 2, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "DMA 1", .value = 1 }, { .description = "DMA 2", .value = 2 }, { .description = "DMA 3", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "bios_addr", .description = "BIOS Address:", .type = CONFIG_HEX20, - .default_string = "", + .default_string = NULL, .default_int = 0xce000, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "Disabled", .value = 0 }, @@ -298,15 +305,20 @@ static const device_config_t compaticard_iv_config[] = { { .description = "E800H", .value = 0xe8000 }, { .description = "EE00H", .value = 0xee000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, #if 0 { .name = "autoboot_enabled", .description = "Enable Autoboot", .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, #endif { .name = "", .description = "", .type = CONFIG_END } diff --git a/src/floppy/fdc_magitronic.c b/src/floppy/fdc_magitronic.c index 2b708a121..17e556e0f 100644 --- a/src/floppy/fdc_magitronic.c +++ b/src/floppy/fdc_magitronic.c @@ -109,18 +109,19 @@ b215_available(void) static const device_config_t b215_config[] = { // clang-format off { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xca000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xca000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "CA00H", .value = 0xca000 }, { .description = "CC00H", .value = 0xcc000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c index 51fb108d6..1b0e2fbac 100644 --- a/src/floppy/fdc_monster.c +++ b/src/floppy/fdc_monster.c @@ -165,82 +165,61 @@ static const device_config_t monster_fdc_config[] = { // clang-format off #if 0 { - .name = "sec_enabled", - .description = "Enable Secondary Controller", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "sec_enabled", + .description = "Enable Secondary Controller", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "sec_irq", - .description = "Secondary Controller IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 6, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 4", - .value = 4 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 6", - .value = 6 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .name = "sec_irq", + .description = "Secondary Controller IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 6, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "sec_dma", - .description = "Secondary Controller DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 2", - .value = 2 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "sec_dma", + .description = "Secondary Controller DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, #endif { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "C000H", .value = 0xc0000 }, { .description = "C800H", .value = 0xc8000 }, @@ -249,30 +228,36 @@ static const device_config_t monster_fdc_config[] = { { .description = "E000H", .value = 0xe0000 }, { .description = "E800H", .value = 0xe8000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, #if 0 { - .name = "bios_size", - .description = "BIOS Size:", - .type = CONFIG_HEX20, - .default_string = "32", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_size", + .description = "BIOS Size:", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 32, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "8K", .value = 8 }, { .description = "32K", .value = 32 }, { .description = "" } - } + }, + .bios = { { 0 } } }, #endif { - .name = "rom_writes_enabled", - .description = "Enable BIOS extension ROM Writes", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/floppy/fdc_pii15xb.c b/src/floppy/fdc_pii15xb.c index 587eb64fa..4e6a8367c 100644 --- a/src/floppy/fdc_pii15xb.c +++ b/src/floppy/fdc_pii15xb.c @@ -122,20 +122,21 @@ pii_158_available(void) static const device_config_t pii_config[] = { // clang-format off { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xce000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xce000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "CA00H", .value = 0xca000 }, { .description = "CC00H", .value = 0xcc000 }, { .description = "CE00H", .value = 0xce000 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/game/gameport.c b/src/game/gameport.c index 39193af88..90986a655 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -88,18 +88,18 @@ 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_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_sw_pad }, + { &joystick_tm_fcs }, + { NULL } }; static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL }; @@ -613,38 +613,40 @@ const device_t gameport_20f_device = { static const device_config_t tmacm_config[] = { // clang-format off { - .name = "port1_addr", - .description = "Port 1 Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0201, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port1_addr", + .description = "Port 1 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0201, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "201h", .value = 0x0201 }, { .description = "203h", .value = 0x0203 }, { .description = "205h", .value = 0x0205 }, { .description = "207h", .value = 0x0207 }, { .description = "Disabled", .value = 0x0000 }, - { "" } - } + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "port2_addr", - .description = "Port 2 Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0209, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port2_addr", + .description = "Port 2 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0209, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "209h", .value = 0x0209 }, { .description = "20Bh", .value = 0x020B }, { .description = "20Dh", .value = 0x020D }, { .description = "20Fh", .value = 0x020F }, { .description = "Disabled", .value = 0x0000 }, - { "" } - } + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c index 73dd5ef62..f5809afb1 100644 --- a/src/network/net_3c501.c +++ b/src/network/net_3c501.c @@ -1154,30 +1154,31 @@ threec501_nic_close(void *priv) static const device_config_t threec501_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x280", .value = 0x280 }, { .description = "0x300", .value = 0x300 }, { .description = "0x310", .value = 0x310 }, { .description = "0x320", .value = 0x320 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2/9", .value = 9 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 4", .value = 4 }, @@ -1186,28 +1187,34 @@ static const device_config_t threec501_config[] = { { .description = "IRQ 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "dma", .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DMA 1", .value = 1 }, { .description = "DMA 2", .value = 2 }, { .description = "DMA 3", .value = 3 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index cd5016147..b35e0d453 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -654,14 +654,14 @@ threec503_nic_close(void *priv) static const device_config_t threec503_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x250", .value = 0x250 }, { .description = "0x280", .value = 0x280 }, { .description = "0x2a0", .value = 0x2a0 }, @@ -672,65 +672,68 @@ static const device_config_t threec503_config[] = { { .description = "0x350", .value = 0x350 }, { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 5", .value = 5 }, { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { { .description = "DMA 1", .value = 1 }, { .description = "DMA 2", .value = 2 }, { .description = "DMA 3", .value = 3 }, { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "", .value = 0 } - }, + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xCC000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xCC000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DC00", .value = 0xDC000 }, { .description = "D800", .value = 0xD8000 }, { .description = "C800", .value = 0xC8000 }, { .description = "CC00", .value = 0xCC000 }, - { .description = "", .value = 0 } + { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format off diff --git a/src/network/net_modem.c b/src/network/net_modem.c index 83dfe04d7..62621391c 100644 --- a/src/network/net_modem.c +++ b/src/network/net_modem.c @@ -1531,30 +1531,31 @@ modem_close(void *priv) // clang-format off static const device_config_t modem_config[] = { { - .name = "port", - .description = "Serial Port", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "COM1", .value = 0 }, { .description = "COM2", .value = 1 }, { .description = "COM3", .value = 2 }, { .description = "COM4", .value = 3 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { - .name = "baudrate", - .description = "Baud Rate", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 115200, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { + .name = "baudrate", + .description = "Baud Rate", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 115200, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "115200", .value = 115200 }, { .description = "57600", .value = 57600 }, { .description = "56000", .value = 56000 }, @@ -1569,32 +1570,44 @@ static const device_config_t modem_config[] = { { .description = "1200", .value = 1200 }, { .description = "600", .value = 600 }, { .description = "300", .value = 300 }, - } + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "listen_port", - .description = "TCP/IP listening port", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, + .name = "listen_port", + .description = "TCP/IP listening port", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, .max = 32767 }, - .default_int = 0 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "phonebook_file", - .description = "Phonebook File", - .type = CONFIG_FNAME, - .default_string = "", - .file_filter = "Text files (*.txt)|*.txt" + .name = "phonebook_file", + .description = "Phonebook File", + .type = CONFIG_FNAME, + .default_string = NULL, + .file_filter = "Text files (*.txt)|*.txt", + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "telnet_mode", - .description = "Telnet emulation", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "telnet_mode", + .description = "Telnet emulation", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 2f6c60d51..dd3a12047 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -1234,14 +1234,14 @@ de220p_available(void) // clang-format off static const device_config_t ne1000_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, @@ -1249,16 +1249,17 @@ static const device_config_t ne1000_config[] = { { .description = "0x360", .value = 0x360 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, @@ -1267,27 +1268,32 @@ static const device_config_t ne1000_config[] = { { .description = "IRQ 9", .value = 9 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ne1000_compat_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "0x200", .value = 0x200 }, { .description = "0x220", .value = 0x220 }, @@ -1307,16 +1313,17 @@ static const device_config_t ne1000_compat_config[] = { { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, @@ -1326,34 +1333,43 @@ static const device_config_t ne1000_compat_config[] = { { .description = "IRQ 9", .value = 9 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "mac_oui", - .description = "MAC Address OUI", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac_oui", + .description = "MAC Address OUI", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ne2000_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, @@ -1361,16 +1377,17 @@ static const device_config_t ne2000_config[] = { { .description = "0x360", .value = 0x360 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, @@ -1379,43 +1396,49 @@ static const device_config_t ne2000_config[] = { { .description = "IRQ 9", .value = 9 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "bios_addr", .description = "BIOS Address", .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "D000", .value = 0xD0000 }, { .description = "D800", .value = 0xD8000 }, { .description = "C800", .value = 0xC8000 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ne2000_compat_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file. */ { .description = "0x200", .value = 0x200 }, { .description = "0x220", .value = 0x220 }, @@ -1435,16 +1458,17 @@ static const device_config_t ne2000_compat_config[] = { { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 10, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 10, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: Windows 95 .INF file - not giving impossible IRQ's such as 6, 8, or 13. */ { .description = "IRQ 3", .value = 3 }, @@ -1459,50 +1483,60 @@ static const device_config_t ne2000_compat_config[] = { { .description = "IRQ 15", .value = 15 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "mac_oui", - .description = "MAC Address OUI", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac_oui", + .description = "MAC Address OUI", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0x00000 }, { .description = "D000", .value = 0xD0000 }, { .description = "D800", .value = 0xD8000 }, { .description = "C800", .value = 0xC8000 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ne2000_compat_8bit_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x320, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x320, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: board docs, https://github.com/skiselev/isa8_eth */ { .description = "0x200", .value = 0x200 }, { .description = "0x220", .value = 0x220 }, @@ -1522,16 +1556,17 @@ static const device_config_t ne2000_compat_8bit_config[] = { { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: board docs, https://github.com/skiselev/isa8_eth */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, @@ -1540,30 +1575,39 @@ static const device_config_t ne2000_compat_8bit_config[] = { { .description = "IRQ 9", .value = 9 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "mac_oui", - .description = "MAC Address OUI", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac_oui", + .description = "MAC Address OUI", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { /* Source: board docs, https://github.com/skiselev/isa8_eth */ { .description = "Disabled", .value = 0x00000 }, { .description = "C000", .value = 0xC0000 }, @@ -1576,6 +1620,7 @@ static const device_config_t ne2000_compat_8bit_config[] = { { .description = "DC00", .value = 0xDC000 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -1583,40 +1628,56 @@ static const device_config_t ne2000_compat_8bit_config[] = { static const device_config_t rtl8019as_config[] = { { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t rtl8029as_config[] = { { - .name = "bios", - .description = "Enable BIOS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t mca_mac_config[] = { { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 5487486b4..3272033cf 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -3088,62 +3088,68 @@ pcnet_close(void *priv) // clang-format off static const device_config_t pcnet_pci_config[] = { { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t pcnet_isa_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, { .description = "0x340", .value = 0x340 }, { .description = "0x360", .value = 0x360 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 4", .value = 4 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, - { .description = "IRQ 9", .value = 9 }, + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, { .description = "IRQ 12", .value = 12 }, { .description = "IRQ 15", .value = 15 }, - { .description = "" } + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DMA 0", .value = 0 }, { .description = "DMA 3", .value = 3 }, { .description = "DMA 5", .value = 5 }, @@ -3151,61 +3157,72 @@ static const device_config_t pcnet_isa_config[] = { { .description = "DMA 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t pcnet_vlb_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, { .description = "0x340", .value = 0x340 }, { .description = "0x360", .value = 0x360 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, .selection = { - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 4", .value = 4 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, - { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, { .description = "IRQ 12", .value = 12 }, { .description = "IRQ 15", .value = 15 }, - { .description = "" } + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, .default_string = "", - .default_int = -1 + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 74b041b35..5138b5168 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -3315,11 +3315,15 @@ nic_close(void *priv) // clang-format off static const device_config_t rtl8139c_config[] = { { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 2c3aab379..7d988368c 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1664,29 +1664,41 @@ nic_close(void *priv) // clang-format off static const device_config_t dec_tulip_21143_config[] = { { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t dec_tulip_21140_config[] = { { - .name = "bios", - .description = "Enable BIOS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 1e5496851..1ca8d8697 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -806,46 +806,48 @@ wd_close(void *priv) // clang-format off static const device_config_t wd8003_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x300, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x240", .value = 0x240 }, { .description = "0x280", .value = 0x280 }, { .description = "0x300", .value = 0x300 }, { .description = "0x380", .value = 0x380 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "ram_addr", - .description = "RAM Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ram_addr", + .description = "RAM Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800", .value = 0xC8000 }, { .description = "CC00", .value = 0xCC000 }, { .description = "D000", .value = 0xD0000 }, @@ -854,27 +856,32 @@ static const device_config_t wd8003_config[] = { { .description = "DC00", .value = 0xDC000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd8003eb_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x280, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x280, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x200", .value = 0x200 }, { .description = "0x220", .value = 0x220 }, { .description = "0x240", .value = 0x240 }, @@ -887,32 +894,34 @@ static const device_config_t wd8003eb_config[] = { { .description = "0x380", .value = 0x380 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2/9", .value = 9 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "ram_addr", - .description = "RAM Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ram_addr", + .description = "RAM Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C000", .value = 0xC0000 }, { .description = "C400", .value = 0xC4000 }, { .description = "C800", .value = 0xC8000 }, @@ -923,27 +932,33 @@ static const device_config_t wd8003eb_config[] = { { .description = "DC00", .value = 0xDC000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "ram_size", - .description = "RAM size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 8192, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ram_size", + .description = "RAM size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "8 KB", .value = 8192 }, { .description = "32 KB", .value = 32768 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -952,14 +967,14 @@ static const device_config_t wd8003eb_config[] = { http://www.stack.nl/~marcolz/network/wd80x3.html#WD8013EBT */ static const device_config_t wd8013_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x280, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x280, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x200", .value = 0x200 }, { .description = "0x220", .value = 0x220 }, { .description = "0x240", .value = 0x240 }, @@ -972,16 +987,17 @@ static const device_config_t wd8013_config[] = { { .description = "0x380", .value = 0x380 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 3, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 2/9", .value = 9 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 4", .value = 4 }, @@ -992,16 +1008,17 @@ static const device_config_t wd8013_config[] = { { .description = "IRQ 15", .value = 15 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "ram_addr", - .description = "RAM Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ram_addr", + .description = "RAM Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C000", .value = 0xC0000 }, { .description = "C400", .value = 0xC4000 }, { .description = "C800", .value = 0xC8000 }, @@ -1012,63 +1029,78 @@ static const device_config_t wd8013_config[] = { { .description = "DC00", .value = 0xDC000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "ram_size", - .description = "RAM size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 16384, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ram_size", + .description = "RAM size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 16384, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "16 KB", .value = 16384 }, { .description = "64 KB", .value = 65536 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd8013epa_config[] = { { - .name = "ram_size", - .description = "Initial RAM size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 16384, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ram_size", + .description = "Initial RAM size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 16384, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "8 KB", .value = 8192 }, { .description = "16 KB", .value = 16384 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t mca_mac_config[] = { { - .name = "mac", - .description = "MAC Address", - .type = CONFIG_MAC, - .default_string = "", - .default_int = -1 + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = NULL, + .default_int = -1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index b6a1698c5..4f3d1d1e7 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1158,14 +1158,14 @@ aha_init(const device_t *info) // clang-format off static const device_config_t aha_154xb_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x334, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x334, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = 0 }, { .description = "0x330", .value = 0x330 }, { .description = "0x334", .value = 0x334 }, @@ -1175,16 +1175,17 @@ static const device_config_t aha_154xb_config[] = { { .description = "0x134", .value = 0x134 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 11, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 11, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, @@ -1193,31 +1194,33 @@ static const device_config_t aha_154xb_config[] = { { .description = "IRQ 15", .value = 15 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 6, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 6, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DMA 5", .value = 5 }, { .description = "DMA 6", .value = 6 }, { .description = "DMA 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "hostid", - .description = "Host ID", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "hostid", + .description = "Host ID", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0", .value = 0 }, { .description = "1", .value = 1 }, { .description = "2", .value = 2 }, @@ -1228,16 +1231,17 @@ static const device_config_t aha_154xb_config[] = { { .description = "7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "C800H", .value = 0xc8000 }, { .description = "D000H", .value = 0xd0000 }, @@ -1245,20 +1249,21 @@ static const device_config_t aha_154xb_config[] = { { .description = "DC00H", .value = 0xdc000 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t aha_154x_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x334, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x334, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = 0 }, { .description = "0x330", .value = 0x330 }, { .description = "0x334", .value = 0x334 }, @@ -1268,16 +1273,17 @@ static const device_config_t aha_154x_config[] = { { .description = "0x134", .value = 0x134 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 11, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 11, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, @@ -1286,52 +1292,55 @@ static const device_config_t aha_154x_config[] = { { .description = "IRQ 15", .value = 15 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 6, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 6, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DMA 5", .value = 5 }, { .description = "DMA 6", .value = 6 }, { .description = "DMA 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "C800H", .value = 0xc8000 }, { .description = "D000H", .value = 0xd0000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "DC00H", .value = 0xdc000 }, { .description = "" } - }, }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t aha_154xcf_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x334, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x334, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = 0 }, { .description = "0x330", .value = 0x330 }, { .description = "0x334", .value = 0x334 }, @@ -1341,16 +1350,17 @@ static const device_config_t aha_154xcf_config[] = { { .description = "0x134", .value = 0x134 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 11, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 11, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, @@ -1359,31 +1369,33 @@ static const device_config_t aha_154xcf_config[] = { { .description = "IRQ 15", .value = 15 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 6, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 6, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DMA 5", .value = 5 }, { .description = "DMA 6", .value = 6 }, { .description = "DMA 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, @@ -1393,44 +1405,64 @@ static const device_config_t aha_154xcf_config[] = { { .description = "DC00H", .value = 0xdc000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "fdc_addr", - .description = "FDC Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "fdc_addr", + .description = "FDC Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = 0 }, { .description = "0x3f0", .value = FDC_PRIMARY_ADDR }, { .description = "0x370", .value = FDC_SECONDARY_ADDR }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t aha_154xcp_config[] = { { - .name = "bios_rev", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios_rev", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "v1_02_en", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "Version 1.02 (English)", .internal_name = "v1_02_en", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp102.bin", - "roms/scsi/adaptec/908301-00_f_mcode_17c9.u12", "" } }, - { .name = "Version 1.02 (German)", .internal_name = "v1_02_de", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/buff_1-0_bios.bin", - "roms/scsi/adaptec/buff_1-0_mcode.bin", "" } }, - { .name = "Version 1.03 (English)", .internal_name = "v1_03_en", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp103.bin", - "roms/scsi/adaptec/908301-00_g_mcode_144c.u12.bin", "" } }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Version 1.02 (English)", + .internal_name = "v1_02_en", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 32768, + .files = { "roms/scsi/adaptec/aha1542cp102.bin", "roms/scsi/adaptec/908301-00_f_mcode_17c9.u12", "" } + }, + { + .name = "Version 1.02 (German)", + .internal_name = "v1_02_de", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 32768, + .files = { "roms/scsi/adaptec/buff_1-0_bios.bin", "roms/scsi/adaptec/buff_1-0_mcode.bin", "" } + }, + { + .name = "Version 1.03 (English)", + .internal_name = "v1_03_en", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 32768, + .files = { "roms/scsi/adaptec/aha1542cp103.bin", "roms/scsi/adaptec/908301-00_g_mcode_144c.u12.bin", "" } + }, { .files_no = 0 } }, }, diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index b235f2c3c..c4745e2df 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1780,14 +1780,14 @@ buslogic_init(const device_t *info) // clang-format off static const device_config_t BT_ISA_Config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x334, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x334, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0x330", .value = 0x330 }, { .description = "0x334", .value = 0x334 }, { .description = "0x230", .value = 0x230 }, @@ -1796,16 +1796,17 @@ static const device_config_t BT_ISA_Config[] = { { .description = "0x134", .value = 0x134 }, { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 11, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 11, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, @@ -1814,48 +1815,55 @@ static const device_config_t BT_ISA_Config[] = { { .description = "IRQ 15", .value = 15 }, { .description = "", 0 } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 6, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 6, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "DMA 5", .value = 5 }, { .description = "DMA 6", .value = 6 }, { .description = "DMA 7", .value = 7 }, { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "C800H", .value = 0xc8000 }, { .description = "D000H", .value = 0xd0000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "", .value = 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t BT958D_Config[] = { { - .name = "bios", - .description = "Enable BIOS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index d8008cf02..10934880f 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -778,14 +778,14 @@ corel_ls2000_available(void) // clang-format off static const device_config_t ncr53c400_mmio_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, { .description = "D000H", .value = 0xd0000 }, @@ -794,36 +794,38 @@ static const device_config_t ncr53c400_mmio_config[] = { { .description = "DC00H", .value = 0xdc000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, - { .description = "" } + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t rt1000b_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, { .description = "D000H", .value = 0xd0000 }, @@ -832,36 +834,53 @@ static const device_config_t rt1000b_config[] = { { .description = "DC00H", .value = 0xdc000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, - { .description = "" } + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "bios_ver", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios_ver", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "v8_10r", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, .bios = { - { .name = "Version 8.10R", .internal_name = "v8_10r", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_810R_ROM, "" } }, - { .name = "Version 8.20R", .internal_name = "v8_20r", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_820R_ROM, "" } }, + { + .name = "Version 8.10R", + .internal_name = "v8_10r", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { RT1000B_810R_ROM, "" } + }, + { + .name = "Version 8.20R", + .internal_name = "v8_20r", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { RT1000B_820R_ROM, "" } + }, { .files_no = 0 } }, }, @@ -870,34 +889,35 @@ static const device_config_t rt1000b_config[] = { static const device_config_t rt1000b_mc_config[] = { { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, - { .description = "" } + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t t130b_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, @@ -905,38 +925,41 @@ static const device_config_t t130b_config[] = { { .description = "DC00H", .value = 0xdc000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0350, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0350, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "240H", .value = 0x0240 }, { .description = "250H", .value = 0x0250 }, { .description = "340H", .value = 0x0340 }, { .description = "350H", .value = 0x0350 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, - { .description = "" } + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index d26da3bb3..f87f22452 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -2663,19 +2663,20 @@ ncr53c8xx_close(void *priv) static const device_config_t ncr53c8xx_pci_config[] = { // clang-format off { - .name = "bios", - .description = "BIOS Revision", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios", + .description = "BIOS Revision", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "SDMS 4.x BIOS", .value = 2 }, { .description = "SDMS 3.x BIOS", .value = 1 }, { .description = "Disable BIOS", .value = 0 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 012d5524b..7c991bdb1 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -2458,11 +2458,15 @@ esp_close(void *priv) static const device_config_t bios_enable_config[] = { // clang-format off { - .name = "bios", - .description = "Enable BIOS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index cbf6ff205..d6a26b7d0 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1231,18 +1231,19 @@ spock_available(void) static const device_config_t spock_rom_config[] = { // clang-format off { - .name = "bios_ver", - .description = "BIOS Revision", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_ver", + .description = "BIOS Revision", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "1991 BIOS (>1GB)", .value = 1 }, { .description = "1990 BIOS", .value = 0 }, { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index ff5f584f1..77c2302cc 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -554,43 +554,49 @@ t128_available(void) // clang-format off static const device_config_t t128_config[] = { { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xD8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xD8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "DC00H", .value = 0xdc000 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "None", .value = -1 }, { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 7", .value = 7 }, { .description = "" } }, + .bios = { { 0 } } }, { - .name = "boot", - .description = "Enable BIOS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "boot", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -618,6 +624,7 @@ const device_t scsi_t228_device = { .local = 0, .init = t128_init, .close = t128_close, + .close = t128_close, .reset = NULL, .available = t128_available, .speed_changed = NULL, diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 6ba017cd1..027c85b79 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -319,153 +319,195 @@ fluidsynth_close(void *priv) static const device_config_t fluidsynth_config[] = { // clang-format off { - .name = "sound_font", - .description = "SoundFont", - .type = CONFIG_FNAME, - .default_string = "", - .file_filter = "SF2 Sound Fonts (*.sf2)|*.sf2" + .name = "sound_font", + .description = "SoundFont", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = "SF2 Sound Fonts (*.sf2)|*.sf2", + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "output_gain", - .description = "Output Gain", - .type = CONFIG_SPINNER, - .spinner = { - .min = 0, + .name = "output_gain", + .description = "Output Gain", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 100, + .file_filter = NULL, + .spinner = { + .min = 0, .max = 100 }, - .default_int = 100 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "chorus", - .description = "Chorus", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "chorus", + .description = "Chorus", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "chorus_voices", - .description = "Chorus Voices", - .type = CONFIG_SPINNER, + .name = "chorus_voices", + .description = "Chorus Voices", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 3, + .file_filter = NULL, .spinner = { - .min = 0, + .min = 0, .max = 99 }, - .default_int = 3 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "chorus_level", - .description = "Chorus Level", - .type = CONFIG_SPINNER, - .spinner = { - .min = 0, + .name = "chorus_level", + .description = "Chorus Level", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 20, + .file_filter = NULL, + .spinner = { + .min = 0, .max = 100 }, - .default_int = 20 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "chorus_speed", - .description = "Chorus Speed", - .type = CONFIG_SPINNER, + .name = "chorus_speed", + .description = "Chorus Speed", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 30, + .file_filter = NULL, .spinner = { - .min = 10, + .min = 10, .max = 500 }, - .default_int = 30 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "chorus_depth", - .description = "Chorus Depth", - .type = CONFIG_SPINNER, + .name = "chorus_depth", + .description = "Chorus Depth", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 80, + .file_filter = NULL, .spinner = { - .min = 0, + .min = 0, .max = 2560 }, - .default_int = 80 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "chorus_waveform", - .description = "Chorus Waveform", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "Sine", - .value = 0 - }, - { - .description = "Triangle", - .value = 1 - } + .name = "chorus_waveform", + .description = "Chorus Waveform", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Sine", .value = 0 }, + { .description = "Triangle", .value = 1 }, + { .description = "" } }, - .default_int = 0 + .bios = { { 0 } } }, { - .name = "reverb", - .description = "Reverb", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "reverb", + .description = "Reverb", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "reverb_room_size", - .description = "Reverb Room Size", - .type = CONFIG_SPINNER, + .name = "reverb_room_size", + .description = "Reverb Room Size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 20, + .file_filter = NULL, .spinner = { - .min = 0, + .min = 0, .max = 100 }, - .default_int = 20 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "reverb_damping", - .description = "Reverb Damping", - .type = CONFIG_SPINNER, + .name = "reverb_damping", + .description = "Reverb Damping", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, .spinner = { - .min = 0, + .min = 0, .max = 100 }, - .default_int = 0 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "reverb_width", - .description = "Reverb Width", - .type = CONFIG_SPINNER, - .spinner = { - .min = 0, + .name = "reverb_width", + .description = "Reverb Width", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { + .min = 0, .max = 1000 }, - .default_int = 5 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "reverb_level", - .description = "Reverb Level", - .type = CONFIG_SPINNER, - .spinner = { - .min = 0, + .name = "reverb_level", + .description = "Reverb Level", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 90, + .file_filter = NULL, + .spinner = { + .min = 0, .max = 100 }, - .default_int = 90 + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "interpolation", - .description = "Interpolation Method", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "None", - .value = 0 - }, - { - .description = "Linear", - .value = 1 - }, - { - .description = "4th Order", - .value = 2 - }, - { - .description = "7th Order", - .value = 3 - } + .name = "interpolation", + .description = "Interpolation Method", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "Linear", .value = 1 }, + { .description = "4th Order", .value = 2 }, + { .description = "7th Order", .value = 3 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -484,4 +526,3 @@ const device_t fluidsynth_device = { .force_redraw = NULL, .config = fluidsynth_config }; - diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index ab2165c52..67f1d26c8 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -377,42 +377,60 @@ mt32_close(void *priv) static const device_config_t mt32_config[] = { // clang-format off { - .name = "output_gain", - .description = "Output Gain", - .type = CONFIG_SPINNER, - .spinner = { + .name = "output_gain", + .description = "Output Gain", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 100, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 100 + }, + .selection = { { 0 } } + }, + { + .name = "reverb", + .description = "Reverb", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } } + }, + { + .name = "reverb_output_gain", + .description = "Reverb Output Gain", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 100, + .file_filter = NULL, + .spinner = { .min = 0, .max = 100 }, - .default_int = 100 + .selection = { { 0 } } }, { - .name = "reverb", - .description = "Reverb", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "reversed_stereo", + .description = "Reversed stereo", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } } }, { - .name = "reverb_output_gain", - .description = "Reverb Output Gain", - .type = CONFIG_SPINNER, - .spinner = { - .min = 0, - .max = 100 - }, - .default_int = 100 - }, - { - .name = "reversed_stereo", - .description = "Reversed stereo", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "nice_ramp", - .description = "Nice ramp", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "nice_ramp", + .description = "Nice ramp", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/midi_rtmidi.cpp b/src/sound/midi_rtmidi.cpp index 9da3fdb91..11203c3f2 100644 --- a/src/sound/midi_rtmidi.cpp +++ b/src/sound/midi_rtmidi.cpp @@ -231,11 +231,15 @@ rtmidi_in_get_dev_name(int num, char *s) static const device_config_t system_midi_config[] = { // clang-format off { - .name = "midi", - .description = "MIDI Output Device", - .type = CONFIG_MIDI_OUT, - .default_string = "", - .default_int = 0 + .name = "midi", + .description = "MIDI Output Device", + .type = CONFIG_MIDI_OUT, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -244,32 +248,48 @@ static const device_config_t system_midi_config[] = { static const device_config_t midi_input_config[] = { // clang-format off { - .name = "midi_input", - .description = "MIDI Input Device", - .type = CONFIG_MIDI_IN, - .default_string = "", - .default_int = 0 + .name = "midi_input", + .description = "MIDI Input Device", + .type = CONFIG_MIDI_IN, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "realtime", - .description = "MIDI Real time", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "realtime", + .description = "MIDI Real time", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "thruchan", - .description = "MIDI Thru", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "thruchan", + .description = "MIDI Thru", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "clockout", - .description = "MIDI Clockout", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "clockout", + .description = "MIDI Clockout", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 8a809803d..360da3fec 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -1192,73 +1192,69 @@ adgold_close(void *priv) static const device_config_t adgold_config[] = { // clang-format off { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 4", - .value = 4 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "Low DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "dma", + .description = "Low DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "gameport", - .description = "Enable Game port", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "surround", - .description = "Surround module", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "surround", + .description = "Surround module", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 9e520bcf5..f8a6e4153 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -2737,11 +2737,15 @@ es137x_speed_changed(void *priv) static const device_config_t es1370_config[] = { // clang-format off { - .name = "receive_input", - .description = "Receive input (MIDI)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -2750,28 +2754,30 @@ static const device_config_t es1370_config[] = { static const device_config_t es1371_config[] = { // clang-format off { - .name = "codec", - .description = "Codec", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "Asahi Kasei AK4540", - .value = AC97_CODEC_AK4540 - }, - { - .description = "TriTech TR28023 / Creative CT1297", - .value = AC97_CODEC_TR28023 - }, - { .description = "" } + .name = "codec", + .description = "Codec", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = AC97_CODEC_TR28023, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Asahi Kasei AK4540", .value = AC97_CODEC_AK4540 }, + { .description = "TriTech TR28023 / Creative CT1297", .value = AC97_CODEC_TR28023 }, + { .description = "" } }, - .default_int = AC97_CODEC_TR28023 + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -2780,32 +2786,31 @@ static const device_config_t es1371_config[] = { static const device_config_t es1373_config[] = { // clang-format off { - .name = "codec", - .description = "Codec", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "Crystal CS4297A", - .value = AC97_CODEC_CS4297A - }, - { - .description = "SigmaTel STAC9721T", - .value = AC97_CODEC_STAC9721 - }, - { - .description = "TriTech TR28023 / Creative CT1297", - .value = AC97_CODEC_TR28023 - }, + .name = "codec", + .description = "Codec", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = AC97_CODEC_CS4297A, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Crystal CS4297A", .value = AC97_CODEC_CS4297A }, + { .description = "SigmaTel STAC9721T", .value = AC97_CODEC_STAC9721 }, + { .description = "TriTech TR28023 / Creative CT1297", .value = AC97_CODEC_TR28023 }, { .description = "" } }, - .default_int = AC97_CODEC_CS4297A + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -2814,32 +2819,31 @@ static const device_config_t es1373_config[] = { static const device_config_t ct5880_config[] = { // clang-format off { - .name = "codec", - .description = "Codec", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "SigmaTel STAC9708T", - .value = AC97_CODEC_STAC9708 - }, - { - .description = "SigmaTel STAC9721T (stereo)", - .value = AC97_CODEC_STAC9721 - }, - { - .description = "TriTech TR28023 / Creative CT1297", - .value = AC97_CODEC_TR28023 - }, - { .description = "" } + .name = "codec", + .description = "Codec", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = AC97_CODEC_STAC9708, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "SigmaTel STAC9708T", .value = AC97_CODEC_STAC9708 }, + { .description = "SigmaTel STAC9721T (stereo)", .value = AC97_CODEC_STAC9721 }, + { .description = "TriTech TR28023 / Creative CT1297", .value = AC97_CODEC_TR28023 }, + { .description = "" } }, - .default_int = AC97_CODEC_STAC9708 + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -2848,11 +2852,14 @@ static const device_config_t ct5880_config[] = { static const device_config_t es1371_onboard_config[] = { // clang-format off { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index dfbab2bd3..ea682a82c 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1315,142 +1315,127 @@ azt_speed_changed(void *priv) static const device_config_t azt1605_config[] = { // clang-format off { - .name = "codec", - .description = "CODEC", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "CS4248", - .value = AD1848_TYPE_CS4248 - }, - { - .description = "CS4231", - .value = AD1848_TYPE_CS4231 - }, + .name = "codec", + .description = "CODEC", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = AD1848_TYPE_CS4248, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "CS4248", .value = AD1848_TYPE_CS4248 }, + { .description = "CS4231", .value = AD1848_TYPE_CS4231 }, + { .description = "" } }, - .default_int = AD1848_TYPE_CS4248 + .bios = { { 0 } } }, { - .name = "wss_interrupt_after_config", - .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", - .type = CONFIG_BINARY, - .default_int = 0 + .name = "wss_interrupt_after_config", + .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "addr", - .description = "SB Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "Use EEPROM setting", - .value = 0 - }, - { - .description = "" - } - } - }, - { - .name = "sb_dma8", - .description = "SB low DMA", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { - .description = "" - } + .name = "addr", + .description = "SB Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "Use EEPROM setting", .value = 0 }, + { .description = "" } }, - .default_int = 1 + .bios = { { 0 } } }, { - .name = "wss_irq", - .description = "WSS IRQ", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "IRQ 11", - .value = 11 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "" - } + .name = "sb_dma8", + .description = "SB low DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } }, - .default_int = 10 + .bios = { { 0 } } }, - { - .name = "wss_dma", - .description = "WSS DMA", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { - .description = "" - } - }, - .default_int = 0 + { + .name = "wss_irq", + .description = "WSS IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 10, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, - { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "wss_dma", + .description = "WSS DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1459,119 +1444,111 @@ static const device_config_t azt1605_config[] = { static const device_config_t azt2316a_config[] = { // clang-format off { - .name = "codec", - .description = "CODEC", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "CS4248", - .value = AD1848_TYPE_CS4248 - }, - { - .description = "CS4231", - .value = AD1848_TYPE_CS4231 - }, + .name = "codec", + .description = "CODEC", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = AD1848_TYPE_CS4248, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "CS4248", .value = AD1848_TYPE_CS4248 }, + { .description = "CS4231", .value = AD1848_TYPE_CS4231 }, + { .description = "" } }, - .default_int = AD1848_TYPE_CS4248 + .bios = { { 0 } } }, { - .name = "wss_interrupt_after_config", - .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", - .type = CONFIG_BINARY, - .default_int = 0 + .name = "wss_interrupt_after_config", + .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "addr", - .description = "SB Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "Use EEPROM setting", - .value = 0 - }, - { - .description = "" - } - } - }, - { - .name = "wss_irq", - .description = "WSS IRQ", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "IRQ 11", - .value = 11 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "" - } + .name = "addr", + .description = "SB Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "Use EEPROM setting", .value = 0 }, + { .description = "" } }, - .default_int = 10 + .bios = { { 0 } } }, { - .name = "wss_dma", - .description = "WSS DMA", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { - .description = "" - } + .name = "wss_irq", + .description = "WSS IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 10, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, - .default_int = 0 + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "wss_dma", + .description = "WSS DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "receive_input401", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index 5f75d0dc3..a41f53865 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -1508,11 +1508,15 @@ cmi8x38_close(void *priv) static const device_config_t cmi8x38_config[] = { // clang-format off { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1521,18 +1525,26 @@ static const device_config_t cmi8x38_config[] = { static const device_config_t cmi8738_config[] = { // clang-format off { - .name = "six_channel", - .description = "6CH variant (6-channel)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "six_channel", + .description = "6CH variant (6-channel)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index f8db04fed..66dff80f3 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -200,42 +200,23 @@ cms_close(void *priv) static const device_config_t cms_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x210", - .value = 0x210 - }, - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x230", - .value = 0x230 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x250", - .value = 0x250 - }, - { - .description = "0x260", - .value = 0x260 - }, - { - .description = "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x210", .value = 0x210 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "0x260", .value = 0x260 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 9dcf0f00b..f2651c72f 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1431,92 +1431,67 @@ gus_speed_changed(void *priv) static const device_config_t gus_config[] = { // clang-format off { - .name = "type", - .description = "GUS type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "Classic", - .value = GUS_CLASSIC - }, + .name = "type", + .description = "GUS type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Classic", .value = GUS_CLASSIC }, #ifdef USE_GUSMAX - { - .description = "MAX", - .value = GUS_MAX - }, + { .description = "MAX", .value = GUS_MAX }, #endif /*USE_GUSMAX */ - { NULL } + { NULL } }, + .bios = { { 0 } } }, { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "210H", - .value = 0x210 - }, - { - .description = "220H", - .value = 0x220 - }, - { - .description = "230H", - .value = 0x230 - }, - { - .description = "240H", - .value = 0x240 - }, - { - .description = "250H", - .value = 0x250 - }, - { - .description = "260H", - .value = 0x260 - }, + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "210H", .value = 0x210 }, + { .description = "220H", .value = 0x220 }, + { .description = "230H", .value = 0x230 }, + { .description = "240H", .value = 0x240 }, + { .description = "250H", .value = 0x250 }, + { .description = "260H", .value = 0x260 }, + { NULL } }, + .bios = { { 0 } } }, { - .name = "gus_ram", - "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "256 KB", - .value = 0 - }, - { - .description = "512 KB", - .value = 1 - }, - { - .description = "1 MB", - .value = 2 - }, - { NULL } - } + .name = "gus_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 0 }, + { .description = "512 KB", .value = 1 }, + { .description = "1 MB", .value = 2 }, + { NULL } + }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format off diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 09d1757eb..bec2ed39c 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -1804,106 +1804,59 @@ mpu401_standalone_close(void *priv) static const device_config_t mpu401_standalone_config[] = { // clang-format off { - .name = "base", - .description = "MPU-401 Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x330, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x230", - .value = 0x230 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x250", - .value = 0x250 - }, - { - .description = "0x300", - .value = 0x300 - }, - { - .description = "0x320", - .value = 0x320 - }, - { - .description = "0x330", - .value = 0x330 - }, - { - .description = "0x332", - .value = 0x332 - }, - { - .description = "0x334", - .value = 0x334 - }, - { - .description = "0x336", - .value = 0x336 - }, - { - .description = "0x340", - .value = 0x340 - }, - { - .description = "0x350", - .value = 0x350 - }, - { .description = "" } - } + .name = "base", + .description = "MPU-401 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x330, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x330", .value = 0x330 }, + { .description = "0x332", .value = 0x332 }, + { .description = "0x334", .value = 0x334 }, + { .description = "0x336", .value = 0x336 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x350", .value = 0x350 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "MPU-401 IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 4", - .value = 4 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 6", - .value = 6 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .name = "irq", + .description = "MPU-401 IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1912,46 +1865,34 @@ static const device_config_t mpu401_standalone_config[] = { static const device_config_t mpu401_standalone_mca_config[] = { // clang-format off { - .name = "irq", - .description = "MPU-401 IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 9, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 4", - .value = 4 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 6", - .value = 6 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 9", - .value = 9 - }, - { .description = "" } - } + .name = "irq", + .description = "MPU-401 IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 9, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_opl2board.c b/src/sound/snd_opl2board.c index a76b6bf4d..632ad85f1 100644 --- a/src/sound/snd_opl2board.c +++ b/src/sound/snd_opl2board.c @@ -167,13 +167,15 @@ opl2board_device_close(void *priv) static const device_config_t opl2board_config[] = { { - .name = "host_serial_path", - .description = "Host Serial Device", - .type = CONFIG_SERPORT, + .name = "host_serial_path", + .description = "Host Serial Device", + .type = CONFIG_SERPORT, .default_string = "", - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } } + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index 7058d918c..d5c01dbaf 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -456,18 +456,26 @@ mirosound_pcm10_available(void) static const device_config_t optimc_config[] = { // clang-format off { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 05df32322..ddb135357 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -2401,25 +2401,37 @@ pas16_close(void *priv) static const device_config_t pas16_config[] = { { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 0b09a7b2e..7de8ec824 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -245,40 +245,23 @@ pssj_close(void *priv) static const device_config_t pssj_isa_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x2C0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x0C0", - .value = 0x0C0 - }, - { - .description = "0x0E0", - .value = 0x0E0 - }, - { - .description = "0x1C0", - .value = 0x1C0 - }, - { - .description = "0x1E0", - .value = 0x1E0 - }, - { - .description = "0x2C0", - .value = 0x2C0 - }, - { - .description = "0x2E0", - .value = 0x2E0 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x2C0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x0C0", .value = 0x0C0 }, + { .description = "0x0E0", .value = 0x0E0 }, + { .description = "0x1C0", .value = 0x1C0 }, + { .description = "0x1E0", .value = 0x1E0 }, + { .description = "0x2C0", .value = 0x2C0 }, + { .description = "0x2E0", .value = 0x2E0 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index ea961a6d3..ca233b252 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -4081,211 +4081,165 @@ sb_speed_changed(void *priv) // clang-format off static const device_config_t sb_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x210", - .value = 0x210 - }, - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x230", - .value = 0x230 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x250", - .value = 0x250 - }, - { - .description = "0x260", - .value = 0x260 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x210", .value = 0x210 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "0x260", .value = 0x260 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 - }, + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb15_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x210", - .value = 0x210 - }, - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x230", - .value = 0x230 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x250", - .value = 0x250 - }, - { - .description = "0x260", - .value = 0x260 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x210", .value = 0x210 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "0x260", .value = 0x260 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "cms", - .description = "Enable CMS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "cms", + .description = "Enable CMS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -4294,1064 +4248,888 @@ static const device_config_t sb2_config[] = { { .name = "base", .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, - { .description = "" } - } + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "mixaddr", - .description = "Mixer", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "Disabled", - .value = 0 - }, - { - .description = "0x250", - .value = 0x250 - }, - { - .description = "0x260", - .value = 0x260 - }, - { .description = "" } - } + .name = "mixaddr", + .description = "Mixer", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "0x250", .value = 0x250 }, + { .description = "0x260", .value = 0x260 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "cms", - .description = "Enable CMS", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "cms", + .description = "Enable CMS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_mcv_config[] = { { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_pro_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_pro_mcv_config[] = { { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_16_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x260", - .value = 0x260 - }, - { - .description = "0x280", - .value = 0x280 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "base401", - .description = "MPU-401 Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x330, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "Disabled", - .value = 0 - }, - { - .description = "0x300", - .value = 0x300 - }, - { - .description = "0x330", - .value = 0x330 - }, - { .description = "" } - } + .name = "base401", + .description = "MPU-401 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x330, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x330", .value = 0x330 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "Low DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "dma", + .description = "Low DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma16", - .description = "High DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 5", - .value = 5 - }, - { - .description = "DMA 6", - .value = 6 - }, - { - .description = "DMA 7", - .value = 7 - }, - { .description = "" } - } + .name = "dma16", + .description = "High DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_16_pnp_config[] = { { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_goldfinch_config[] = { { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "None", - .value = 0 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "4 MB", - .value = 4096 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "16 MB", - .value = 16384 - }, - { - .description = "28 MB", - .value = 28672 - }, - { .description = "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "4 MB", .value = 4096 }, + { .description = "8 MB", .value = 8192 }, + { .description = "16 MB", .value = 16384 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_32_pnp_config[] = { { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "None", - .value = 0 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "28 MB", - .value = 28672 - }, - { .description = "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "512 KB", .value = 512 }, + { .description = "2 MB", .value = 2048 }, + { .description = "8 MB", .value = 8192 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_awe32_config[] = { { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x220, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x260", - .value = 0x260 - }, - { - .description = "0x280", - .value = 0x280 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "emu_base", - .description = "EMU8000 Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x620, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x620", - .value = 0x620 - }, - { - .description = "0x640", - .value = 0x640 - }, - { - .description = "0x660", - .value = 0x660 - }, - { - .description = "0x680", - .value = 0x680 - }, - { .description = ""} - } + .name = "emu_base", + .description = "EMU8000 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x620, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x620", .value = 0x620 }, + { .description = "0x640", .value = 0x640 }, + { .description = "0x660", .value = 0x660 }, + { .description = "0x680", .value = 0x680 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "base401", - .description = "MPU-401 Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x330, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "Disabled", - .value = 0 - }, - { - .description = "0x300", - .value = 0x300 - }, - { - .description = "0x330", - .value = 0x330 - }, - { .description = "" } - } + .name = "base401", + .description = "MPU-401 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x330, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x330", .value = 0x330 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { .description = "" } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "Low DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + .name = "dma", + .description = "Low DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "dma16", - .description = "High DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 5, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "DMA 5", - .value = 5 - }, - { - .description = "DMA 6", - .value = 6 - }, - { - .description = "DMA 7", - .value = 7 - }, - { .description = "" } - } + .name = "dma16", + .description = "High DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "None", - .value = 0 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "28 MB", - .value = 28672 - }, - { "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "512 KB", .value = 512 }, + { .description = "2 MB", .value = 2048 }, + { .description = "8 MB", .value = 8192 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_awe32_pnp_config[] = { { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "None", - .value = 0 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "28 MB", - .value = 28672 - }, - { .description = "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "512 KB", .value = 512 }, + { .description = "2 MB", .value = 2048 }, + { .description = "8 MB", .value = 8192 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_awe64_value_config[] = { { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 512, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "4 MB", - .value = 4096 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "12 MB", - .value = 12288 - }, - { - .description = "16 MB", - .value = 16384 - }, - { - .description = "20 MB", - .value = 20480 - }, - { - .description = "24 MB", - .value = 24576 - }, - { - .description = "28 MB", - .value = 28672 - }, - { .description = "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "4 MB", .value = 4096 }, + { .description = "8 MB", .value = 8192 }, + { .description = "12 MB", .value = 12288 }, + { .description = "16 MB", .value = 16384 }, + { .description = "20 MB", .value = 20480 }, + { .description = "24 MB", .value = 24576 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_awe64_config[] = { { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1024, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "4 MB", - .value = 4096 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "12 MB", - .value = 12288 - }, - { - .description = "16 MB", - .value = 16384 - }, - { - .description = "20 MB", - .value = 20480 - }, - { - .description = "24 MB", - .value = 24576 - }, - { - .description = "28 MB", - .value = 28672 - }, - { .description = "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "4 MB", .value = 4096 }, + { .description = "8 MB", .value = 8192 }, + { .description = "12 MB", .value = 12288 }, + { .description = "16 MB", .value = 16384 }, + { .description = "20 MB", .value = 20480 }, + { .description = "24 MB", .value = 24576 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t sb_awe64_gold_config[] = { { - .name = "onboard_ram", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 4096, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "4 MB", - .value = 4096 - }, - { - .description = "8 MB", - .value = 8192 - }, - { - .description = "12 MB", - .value = 12288 - }, - { - .description = "16 MB", - .value = 16384 - }, - { - .description = "20 MB", - .value = 20480 - }, - { - .description = "24 MB", - .value = 24576 - }, - { - .description = "28 MB", - .value = 28672 - }, - { .description = "" } - } + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4096, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "4 MB", .value = 4096 }, + { .description = "8 MB", .value = 8192 }, + { .description = "12 MB", .value = 12288 }, + { .description = "16 MB", .value = 16384 }, + { .description = "20 MB", .value = 20480 }, + { .description = "24 MB", .value = 24576 }, + { .description = "28 MB", .value = 28672 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -5361,120 +5139,80 @@ static const device_config_t ess_688_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x220, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x230", - .value = 0x230 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x250", - .value = 0x250 - }, - { .description = "" } - } + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 5, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { .description = "" } - } + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "dma", .description = "DMA", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 1, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "ide_ctrl", .description = "IDE Controller", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x0000, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "Disabled", - .value = 0x0000 - }, - { - .description = "0x170, IRQ 15", - .value = 0xf170 - }, - { - .description = "0x1E8, IRQ 11", - .value = 0xb1e8 - }, - { - .description = "0x168, IRQ 9", - .value = 0x9168 - }, - { - .description = "0x168, IRQ 10", - .value = 0xa168 - }, - { .description = "" } - } + { .description = "Disabled", .value = 0x0000 }, + { .description = "0x170, IRQ 15", .value = 0xf170 }, + { .description = "0x1E8, IRQ 11", .value = 0xb1e8 }, + { .description = "0x168, IRQ 9", .value = 0x9168 }, + { .description = "0x168, IRQ 10", .value = 0xa168 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "receive_input", .description = "Receive MIDI input", .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -5484,170 +5222,154 @@ static const device_config_t ess_1688_config[] = { .name = "base", .description = "Address", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x220, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x230", - .value = 0x230 - }, - { - .description = "0x240", - .value = 0x240 - }, - { - .description = "0x250", - .value = 0x250 - }, - { .description = "" } - } + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "irq", .description = "IRQ", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 5, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "IRQ 2", - .value = 2 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { .description = "" } - } + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "dma", .description = "DMA", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 1, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { .description = "" } - } + { .description = "DMA 0", .value = 0 }, + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "ide_ctrl", .description = "IDE Controller", .type = CONFIG_HEX16, - .default_string = "", + .default_string = NULL, .default_int = 0x0000, - .file_filter = "", + .file_filter = NULL, .spinner = { 0 }, .selection = { - { - .description = "Disabled", - .value = 0x0000 - }, - { - .description = "0x170, IRQ 15", - .value = 0xf170 - }, - { - .description = "0x1E8, IRQ 11", - .value = 0xb1e8 - }, - { - .description = "0x168, IRQ 9", - .value = 0x9168 - }, - { - .description = "0x168, IRQ 10", - .value = 0xa168 - }, - { .description = "" } - } + { .description = "Disabled", .value = 0x0000 }, + { .description = "0x170, IRQ 15", .value = 0xf170 }, + { .description = "0x1E8, IRQ 11", .value = 0xb1e8 }, + { .description = "0x168, IRQ 9", .value = 0x9168 }, + { .description = "0x168, IRQ 10", .value = 0xa168 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 0 + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ess_688_pnp_config[] = { { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ess_1688_pnp_config[] = { { - .name = "control_pc_speaker", - .description = "Control PC speaker", - .type = CONFIG_BINARY, + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, .default_string = "", - .default_int = 0 + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input", - .description = "Receive MIDI input", - .type = CONFIG_BINARY, + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, .default_string = "", - .default_int = 1 + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "receive_input401", - .description = "Receive MIDI input (MPU-401)", - .type = CONFIG_BINARY, + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, .default_string = "", - .default_int = 0 + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 89064bea4..569d698d5 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -268,40 +268,23 @@ sn76489_device_close(void *priv) static const device_config_t tndy_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x0C0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x0C0", - .value = 0x0C0 - }, - { - .description = "0x0E0", - .value = 0x0E0 - }, - { - .description = "0x1C0", - .value = 0x1C0 - }, - { - .description = "0x1E0", - .value = 0x1E0 - }, - { - .description = "0x2C0", - .value = 0x2C0 - }, - { - .description = "0x2E0", - .value = 0x2E0 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x0C0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x0C0", .value = 0x0C0 }, + { .description = "0x0E0", .value = 0x0E0 }, + { .description = "0x1C0", .value = 0x1C0 }, + { .description = "0x1E0", .value = 0x1E0 }, + { .description = "0x2C0", .value = 0x2C0 }, + { .description = "0x2E0", .value = 0x2E0 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index 0e1bbd96c..f1620b817 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -136,39 +136,32 @@ entertainer_close(void *priv) static const device_config_t ssi2001_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x280, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x280", - .value = 0x280 - }, - { - .description = "0x2A0", - .value = 0x2A0 - }, - { - .description = "0x2C0", - .value = 0x2C0 - }, - { - .description = "0x2E0", - .value = 0x2E0 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x280, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x280", .value = 0x280 }, + { .description = "0x2A0", .value = 0x2A0 }, + { .description = "0x2C0", .value = 0x2C0 }, + { .description = "0x2E0", .value = 0x2E0 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "gameport", - .description = "Enable Game port", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format off @@ -177,11 +170,15 @@ static const device_config_t ssi2001_config[] = { static const device_config_t entertainer_config[] = { // clang-format off { - .name = "gameport", - .description = "Enable Game port", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format off diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index 0f37cbf27..c55e5f57b 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -245,39 +245,32 @@ wss_speed_changed(void *priv) static const device_config_t wss_config[] = { // clang-format off { - .name = "base", - .description = "Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x530, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "0x530", - .value = 0x530 - }, - { - .description = "0x604", - .value = 0x604 - }, - { - .description = "0xe80", - .value = 0xe80 - }, - { - .description = "0xf40", - .value = 0xf40 - }, - { .description = "" } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x530, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x530", .value = 0x530 }, + { .description = "0x604", .value = 0x604 }, + { .description = "0xe80", .value = 0xe80 }, + { .description = "0xf40", .value = 0xf40 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "opl", - .description = "Enable OPL", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 73abfe1ed..09b054895 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -3976,52 +3976,44 @@ ibm8514_force_redraw(void *priv) // clang-format off static const device_config_t isa_ext8514_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "extensions", - .description = "Vendor", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "IBM", - .value = 0 - }, - { - .description = "ATI", - .value = 1 - }, - { - .description = "" - } - } + .name = "extensions", + .description = "Vendor", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IBM", .value = 0 }, + { .description = "ATI", .value = 1 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc8000, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc8000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800h", .value = 0xc8000 }, { .description = "CA00h", .value = 0xca000 }, { .description = "CC00h", .value = 0xcc000 }, @@ -4034,8 +4026,9 @@ static const device_config_t isa_ext8514_config[] = { { .description = "DA00h", .value = 0xda000 }, { .description = "DC00h", .value = 0xdc000 }, { .description = "DE00h", .value = 0xde000 }, - { .description = "" } + { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -4043,76 +4036,67 @@ static const device_config_t isa_ext8514_config[] = { // clang-format off static const device_config_t mca_ext8514_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "extensions", - .description = "Vendor", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "IBM", - .value = 0 - }, - { - .description = "ATI", - .value = 1 - }, - { - .description = "" - } - } + .name = "extensions", + .description = "Vendor", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IBM", .value = 0 }, + { .description = "ATI", .value = 1 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; // clang-format off const device_t gen8514_isa_device = { - .name = "IBM 8514/A clone (ISA)", + .name = "IBM 8514/A clone (ISA)", .internal_name = "8514_isa", - .flags = DEVICE_AT | DEVICE_ISA, - .local = 0, - .init = ibm8514_init, - .close = ibm8514_close, - .reset = NULL, + .flags = DEVICE_AT | DEVICE_ISA, + .local = 0, + .init = ibm8514_init, + .close = ibm8514_close, + .reset = NULL, .available = NULL, .speed_changed = ibm8514_speed_changed, - .force_redraw = ibm8514_force_redraw, - .config = isa_ext8514_config + .force_redraw = ibm8514_force_redraw, + .config = isa_ext8514_config }; const device_t ibm8514_mca_device = { - .name = "IBM 8514/A (MCA)", + .name = "IBM 8514/A (MCA)", .internal_name = "8514_mca", - .flags = DEVICE_MCA, - .local = 0, - .init = ibm8514_init, - .close = ibm8514_close, - .reset = NULL, + .flags = DEVICE_MCA, + .local = 0, + .init = ibm8514_init, + .close = ibm8514_close, + .reset = NULL, .available = NULL, .speed_changed = ibm8514_speed_changed, - .force_redraw = ibm8514_force_redraw, - .config = mca_ext8514_config + .force_redraw = ibm8514_force_redraw, + .config = mca_ext8514_config }; - void ibm8514_device_add(void) { diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 59688087f..9a9be6ff6 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -329,23 +329,19 @@ ati18800_force_redraw(void *priv) static const device_config_t ati18800_wonder_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "" - } - } + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 4c039d9e6..156e95425 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -744,27 +744,20 @@ ati28800_force_redraw(void *priv) // clang-format off static const device_config_t ati28800_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -772,27 +765,20 @@ static const device_config_t ati28800_config[] = { #ifdef USE_XL24 static const device_config_t ati28800_wonderxl_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 1d2326192..9b7a67f31 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -4711,50 +4711,39 @@ mach64_force_redraw(void *priv) // clang-format off static const device_config_t mach64gx_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t mach64vt2_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 5cd29d814..06a60449f 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -6353,104 +6353,76 @@ mach_force_redraw(void *priv) // clang-format off static const device_config_t mach8_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t mach32_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2048, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "4 MB", - .value = 4096 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2048, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "4 MB", .value = 4096 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t mach32_pci_config[] = { { - .name = "ramdac", - .description = "RAMDAC type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "ATI 68860", - .value = 0 - }, - { - .description = "ATI 68875", - .value = 1 - }, - { - .description = "" - } - } + .name = "ramdac", + .description = "RAMDAC type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "ATI 68860", .value = 0 }, + { .description = "ATI 68875", .value = 1 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2048, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "4 MB", - .value = 4096 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2048, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "4 MB", .value = 4096 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index 473b10983..84fb110c6 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -921,46 +921,35 @@ bochs_vbe_force_redraw(void *priv) static const device_config_t bochs_vbe_config[] = { // clang-format off { - .name = "revision", - .description = "Revision", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "VirtualBox", - .value = VBE_DISPI_ID4 - }, - { - .description = "Bochs latest", - .value = VBE_DISPI_ID5 - }, - { - .description = "" - } + .name = "revision", + .description = "Revision", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = VBE_DISPI_ID5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "VirtualBox", .value = VBE_DISPI_ID4 }, + { .description = "Bochs latest", .value = VBE_DISPI_ID5 }, + { .description = "" } }, - .default_int = VBE_DISPI_ID5 + .bios = { { 0 } } }, { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "16 MB", - .value = 16 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 16, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "4 MB", .value = 4 }, + { .description = "8 MB", .value = 8 }, + { .description = "16 MB", .value = 16 }, + { .description = "" } }, - .default_int = 16 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -974,7 +963,7 @@ const device_t bochs_svga_device = { .init = bochs_vbe_init, .close = bochs_vbe_close, .reset = bochs_vbe_reset, - .available = bochs_vbe_available, + .available = bochs_vbe_available, .speed_changed = bochs_vbe_speed_changed, .force_redraw = bochs_vbe_force_redraw, .config = bochs_vbe_config diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index d324368ab..f439cb1d8 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -809,110 +809,81 @@ cga_speed_changed(void *priv) // clang-format off const device_config_t cga_config[] = { { - .name = "display_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = CGA_RGB, - .selection = { - { - .description = "RGB", - .value = CGA_RGB - }, - { - .description = "Composite", - .value = CGA_COMPOSITE - }, - { - .description = "" - } - } + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = CGA_RGB, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = CGA_RGB }, + { .description = "Composite", .value = CGA_COMPOSITE }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "composite_type", - .description = "Composite type", - .type = CONFIG_SELECTION, - .default_int = COMPOSITE_OLD, - .selection = { - { - .description = "Old", - .value = COMPOSITE_OLD - }, - { - .description = "New", - .value = COMPOSITE_NEW - }, - { - .description = "" - } - } + .name = "composite_type", + .description = "Composite type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = COMPOSITE_OLD, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Old", .value = COMPOSITE_OLD }, + { .description = "New", .value = COMPOSITE_NEW }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, - .default_int = 5, - .selection = { - { - .description = "Color (generic)", - .value = 0 - }, - { - .description = "Green Monochrome", - .value = 1 - }, - { - .description = "Amber Monochrome", - .value = 2 - }, - { - .description = "Gray Monochrome", - .value = 3 - }, - { - .description = "Color (no brown)", - .value = 4 - }, - { - .description = "Color (IBM 5153)", - .value = 5 - }, - { - .description = "" - } - } + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Color (generic)", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "Color (no brown)", .value = 4 }, + { .description = "Color (IBM 5153)", .value = 5 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "double_type", - .description = "Line doubling type", - .type = CONFIG_SELECTION, - .default_int = DOUBLE_NONE, - .selection = { - { - .description = "None", - .value = DOUBLE_NONE - }, - { - .description = "Simple doubling", - .value = DOUBLE_SIMPLE - }, - { - .description = "sRGB interpolation", - .value = DOUBLE_INTERPOLATE_SRGB - }, - { - .description = "Linear interpolation", - .value = DOUBLE_INTERPOLATE_LINEAR - }, - { - .description = "" - } - } + .name = "double_type", + .description = "Line doubling type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = DOUBLE_NONE, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "None", .value = DOUBLE_NONE }, + { .description = "Simple doubling", .value = DOUBLE_SIMPLE }, + { .description = "sRGB interpolation", .value = DOUBLE_INTERPOLATE_SRGB }, + { .description = "Linear interpolation", .value = DOUBLE_INTERPOLATE_LINEAR }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "snow_enabled", - .description = "Snow emulation", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 51e4ba335..19f51bd9d 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4701,200 +4701,156 @@ gd54xx_force_redraw(void *priv) // clang-format off static const device_config_t gd542x_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } }, - .default_int = 512 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5426_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2048, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "" } }, - .default_int = 2048 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5428_onboard_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2048, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "2 MB", .value = 2048 }, + { .description = "" } }, - .default_int = 2048 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5429_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5440_onboard_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5434_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } }, - .default_int = 4 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5434_onboard_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } }, - .default_int = 4 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t gd5480_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } }, - .default_int = 4 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 98d6adea7..958375f4e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -382,48 +382,45 @@ colorplus_speed_changed(void *priv) static const device_config_t colorplus_config[] = { // clang-format off { - .name = "display_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = CGA_RGB, - .selection = { - { - .description = "RGB", - .value = CGA_RGB - }, - { - .description = "Composite", - .value = CGA_COMPOSITE - }, - { - .description = "" - } - } + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = CGA_RGB, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = CGA_RGB }, + { .description = "Composite", .value = CGA_COMPOSITE }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "composite_type", - .description = "Composite type", - .type = CONFIG_SELECTION, - .default_int = COMPOSITE_OLD, - .selection = { - { - .description = "Old", - .value = COMPOSITE_OLD - }, - { - .description = "New", - .value = COMPOSITE_NEW - }, - { - .description = "" - } - } + .name = "composite_type", + .description = "Composite type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = COMPOSITE_OLD, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Old", .value = COMPOSITE_OLD }, + { .description = "New", .value = COMPOSITE_NEW }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "snow_enabled", - .description = "Snow emulation", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index faf4b9066..10df85c79 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1590,70 +1590,41 @@ ega_speed_changed(void *priv) static const device_config_t ega_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 256, - .selection = { - { - .description = "32 KB", - .value = 32 - }, - { - .description = "64 KB", - .value = 64 - }, - { - .description = "128 KB", - .value = 128 - }, - { - .description = "256 KB", - .value = 256 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "32 KB", .value = 32 }, + { .description = "64 KB", .value = 64 }, + { .description = "128 KB", .value = 128 }, + { .description = "256 KB", .value = 256 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "monitor_type", - .description = "Monitor type", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "Monochrome (5151/MDA) (white)", - .value = 0x0B | (DISPLAY_WHITE << 4) - }, - { - .description = "Monochrome (5151/MDA) (green)", - .value = 0x0B | (DISPLAY_GREEN << 4) - }, - { - .description = "Monochrome (5151/MDA) (amber)", - .value = 0x0B | (DISPLAY_AMBER << 4) - }, - { - .description = "Color 40x25 (5153/CGA)", - .value = 0x06 - }, - { - .description = "Color 80x25 (5153/CGA)", - .value = 0x07 - }, - { - .description = "Enhanced Color - Normal Mode (5154/ECD)", - .value = 0x08 - }, - { - .description = "Enhanced Color - Enhanced Mode (5154/ECD)", - .value = 0x09 - }, - { - .description = "" - } + .name = "monitor_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 9, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Monochrome (5151/MDA) (white)", .value = 0x0B | (DISPLAY_WHITE << 4) }, + { .description = "Monochrome (5151/MDA) (green)", .value = 0x0B | (DISPLAY_GREEN << 4) }, + { .description = "Monochrome (5151/MDA) (amber)", .value = 0x0B | (DISPLAY_AMBER << 4) }, + { .description = "Color 40x25 (5153/CGA)", .value = 0x06 }, + { .description = "Color 80x25 (5153/CGA)", .value = 0x07 }, + { .description = "Enhanced Color - Normal Mode (5154/ECD)", .value = 0x08 }, + { .description = "Enhanced Color - Enhanced Mode (5154/ECD)", .value = 0x09 }, + { .description = "" } }, - .default_int = 9 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index 8585fedff..193fed3c7 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -550,15 +550,19 @@ et3000_available(void) static const device_config_t et3000_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { .description = "256 KB", .value = 256 }, - { .description = "512 KB", .value = 512 }, - { .description = "" } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 120505dc5..064d79230 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -943,43 +943,51 @@ et4000_kasan_available(void) static const device_config_t et4000_tc6058af_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "bios_ver", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios_ver", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "v1_10", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "Version 1.10", .internal_name = "v1_10", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 32768, .files = { TC6058AF_BIOS_ROM_PATH, "" } }, - { .name = "Version 1.21", .internal_name = "v1_21", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 32768, .files = { V1_21_BIOS_ROM_PATH, "" } }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Version 1.10", + .internal_name = "v1_10", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 32768, + .files = { TC6058AF_BIOS_ROM_PATH, "" } + }, + { + .name = "Version 1.21", + .internal_name = "v1_21", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 32768, + .files = { V1_21_BIOS_ROM_PATH, "" } + }, { .files_no = 0 } - }, + } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -988,43 +996,51 @@ static const device_config_t et4000_tc6058af_config[] = { static const device_config_t et4000_bios_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "bios_ver", - .description = "BIOS Revision", - .type = CONFIG_BIOS, + .name = "bios_ver", + .description = "BIOS Revision", + .type = CONFIG_BIOS, .default_string = "v8_01", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "Version 8.01", .internal_name = "v8_01", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 32768, .files = { BIOS_ROM_PATH, "" } }, - { .name = "Version 8.06", .internal_name = "v8_06", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 32768, .files = { V8_06_BIOS_ROM_PATH, "" } }, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Version 8.01", + .internal_name = "v8_01", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 32768, + .files = { BIOS_ROM_PATH, "" } + }, + { + .name = "Version 8.06", + .internal_name = "v8_06", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 32768, + .files = { V8_06_BIOS_ROM_PATH, "" } + }, { .files_no = 0 } - }, + } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -1033,27 +1049,20 @@ static const device_config_t et4000_bios_config[] = { static const device_config_t et4000_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 351dfba5d..6ff34cbb1 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -2943,23 +2943,19 @@ et4000w32p_force_redraw(void *priv) static const device_config_t et4000w32p_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 8d99e9c7b..d50e8ba37 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -615,37 +615,32 @@ speed_changed(void *priv) static const device_config_t hercules_config[] = { // clang-format off { - .name = "rgb_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Default", - .value = 0 - }, - { - .description = "Green", - .value = 1 - }, - { - .description = "Amber", - .value = 2 - }, - { - .description = "Gray", - .value = 3 - }, - { - .description = "" - } - } + .name = "rgb_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Default", .value = 0 }, + { .description = "Green", .value = 1 }, + { .description = "Amber", .value = 2 }, + { .description = "Gray", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "blend", - .description = "Blend", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "blend", + .description = "Blend", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 1b6b74033..99c614259 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -700,37 +700,32 @@ speed_changed(void *priv) static const device_config_t herculesplus_config[] = { // clang-format off { - .name = "rgb_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Default", - .value = 0 - }, - { - .description = "Green", - .value = 1 - }, - { - .description = "Amber", - .value = 2 - }, - { - .description = "Gray", - .value = 3 - }, - { - .description = "" - } - } + .name = "rgb_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Default", .value = 0 }, + { .description = "Green", .value = 1 }, + { .description = "Amber", .value = 2 }, + { .description = "Gray", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "blend", - .description = "Blend", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "blend", + .description = "Blend", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 3ed9e2bce..ce756f7d8 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1721,32 +1721,40 @@ ht216_force_redraw(void *priv) // clang-format off static const device_config_t v7_vga_1024i_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { .description = "256 KB", .value = 256 }, - { .description = "512 KB", .value = 512 }, - { .description = "" } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t ht216_32_standalone_config[] = { { - .name = "monitor_type", - .description = "Monitor type", - .type = CONFIG_SELECTION, - .default_int = 0x18, - .selection = { + .name = "monitor_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0x18, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Mono Interlaced", .value = 0x00 }, { .description = "Mono Non-Interlaced", .value = 0x08 }, { .description = "Color Interlaced", .value = 0x10 }, { .description = "Color Non-Interlaced", .value = 0x18 }, - { .description = "" } - } + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index edadb4e46..975b9ead1 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -353,31 +353,21 @@ mda_speed_changed(void *priv) static const device_config_t mda_config[] = { // clang-format off { - .name = "rgb_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Default", - .value = 0 - }, - { - .description = "Green", - .value = 1 - }, - { - .description = "Amber", - .value = 2 - }, - { - .description = "Gray", - .value = 3 - }, - { - .description = "" - } - } + .name = "rgb_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Default", .value = 0 }, + { .description = "Green", .value = 1 }, + { .description = "Amber", .value = 2 }, + { .description = "Gray", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index b3cbdd999..3937c2a7d 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -6845,25 +6845,20 @@ mystique_force_redraw(void *priv) static const device_config_t mystique_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { .description = "" } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 8, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "8 MB", .value = 8 }, + { .description = "" } }, - .default_int = 8 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -6872,25 +6867,20 @@ static const device_config_t mystique_config[] = { static const device_config_t millennium_ii_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "16 MB", - .value = 16 - }, - { .description = "" } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 8, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "4 MB", .value = 4 }, + { .description = "8 MB", .value = 8 }, + { .description = "16 MB", .value = 16 }, + { .description = "" } }, - .default_int = 8 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 3cb7426b8..3640e5106 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -600,87 +600,65 @@ nga_init(UNUSED(const device_t *info)) const device_config_t nga_config[] = { // clang-format off { - .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Color", - .value = 0 - }, - { - .description = "Green Monochrome", - .value = 1 - }, - { - .description = "Amber Monochrome", - .value = 2 - }, - { - .description = "Gray Monochrome", - .value = 3 - }, - { - .description = "Color (no brown)", - .value = 4 - }, - { - .description = "" - } - } + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Color", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "Color (no brown)", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "snow_enabled", - .description = "Snow emulation", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 64, - .selection = { - { - .description = "32 KB", - .value = 32 - }, - { - .description = "64 KB", - .value = 64 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 64, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "32 KB", .value = 32 }, + { .description = "64 KB", .value = 64 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "charset", - .description = "Character set", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "U.S. English", - .value = 0 - }, - { - .description = "Scandinavian", - .value = 1 - }, - { - .description = "Other languages", - .value = 2 - }, - { - .description = "E.F. Hutton", - .value = 3 - }, - { - .description = "" - } - } + .name = "charset", + .description = "Character set", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "U.S. English", .value = 0 }, + { .description = "Scandinavian", .value = 1 }, + { .description = "Other languages", .value = 2 }, + { .description = "E.F. Hutton", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index c7d42275d..ce44ef890 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -571,100 +571,78 @@ oti067_m300_available(void) // clang-format off static const device_config_t oti067_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t oti067_ama932j_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 256, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t oti077_acer100t_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t oti077_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index d430d2e14..7fe5fbbeb 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -634,37 +634,32 @@ const device_config_t ogc_m24_config[] = { // clang-format off { /* Olivetti / ATT compatible displays */ - .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, - .default_int = CGA_RGB, - .selection = { - { - .description = "Color", - .value = 0 - }, - { - .description = "Green Monochrome", - .value = 1 - }, - { - .description = "Amber Monochrome", - .value = 2 - }, - { - .description = "Gray Monochrome", - .value = 3 - }, - { - .description = "" - } - } + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = CGA_RGB, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Color", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "snow_enabled", - .description = "Snow emulation", - .type = CONFIG_BINARY, - .default_int = 1, + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 89d65a1f8..d0acaf276 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -735,23 +735,19 @@ const device_t paradise_pvga1a_pc3086_device = { static const device_config_t paradise_pvga1a_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -816,27 +812,20 @@ const device_t paradise_wd90c11_device = { static const device_config_t paradise_wd90c30_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index b6e0085f8..ae9475d96 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -387,23 +387,19 @@ rtg3106_available(void) static const device_config_t rtg3105_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -412,27 +408,20 @@ static const device_config_t rtg3105_config[] = { static const device_config_t rtg3106_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 52135b066..aecc898c4 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -10543,100 +10543,126 @@ s3_force_redraw(void *priv) s3->svga.fullchange = s3->svga.monitor->mon_changeframecount; } +// clang-format off static const device_config_t s3_orchid_86c911_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1, - .selection = { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "512 KB", .value = 0 }, { .description = "1 MB", .value = 1 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_9fx_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "1 MB", .value = 1 }, { .description = "2 MB", .value = 2 }, /* Trio64 also supports 4 MB, however the Number Nine BIOS does not */ { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_phoenix_trio32_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "512 KB", .value = 0 }, { .description = "1 MB", .value = 1 }, { .description = "2 MB", .value = 2 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_standard_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "1 MB", .value = 1 }, { .description = "2 MB", .value = 2 }, { .description = "4 MB", .value = 4 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_968_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "1 MB", .value = 1 }, { .description = "2 MB", .value = 2 }, { .description = "4 MB", .value = 4 }, { .description = "8 MB", .value = 8 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t s3_standard_config2[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "2 MB", .value = 2 }, { .description = "4 MB", .value = 4 }, { .description = "" } - } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; +// clang-format on const device_t s3_orchid_86c911_isa_device = { .name = "S3 86c911 ISA (Orchid Fahrenheit 1280)", diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 86876cd0a..91b186240 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -4692,35 +4692,38 @@ s3_virge_force_redraw(void *priv) static const device_config_t s3_virge_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "dithering", - .description = "Dithering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -4729,39 +4732,39 @@ static const device_config_t s3_virge_config[] = { static const device_config_t s3_virge_stb_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "8 MB", .value = 8 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "dithering", - .description = "Dithering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -4770,16 +4773,24 @@ static const device_config_t s3_virge_stb_config[] = { static const device_config_t s3_virge_357_config[] = { // clang-format off { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "dithering", - .description = "Dithering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -4788,35 +4799,41 @@ static const device_config_t s3_virge_357_config[] = { static const device_config_t s3_trio3d2x_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 4, - .selection = { - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "4 MB", .value = 4 }, + { .description = "8 MB", .value = 8 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "dithering", - .description = "Dithering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 161331918..d771260ed 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -860,96 +860,57 @@ sigma_speed_changed(void *priv) device_config_t sigma_config[] = { // clang-format off { - .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Color", - .value = 0 - }, - { - .description = "Green Monochrome", - .value = 1 - }, - { - .description = "Amber Monochrome", - .value = 2 - }, - { - .description = "Gray Monochrome", - .value = 3 - }, - { - .description = "Color (no brown)", - .value = 4 - }, - { - .description = "" - } - } - }, - { - .name = "enable_nmi", - .description = "Enable NMI for CGA emulation", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "bios_addr", - .description = "BIOS Address", - .type = CONFIG_HEX20, - .default_int = 0xc0000, - .selection = { - { - .description = "C000H", - .value = 0xc0000 - }, - { - .description = "C800H", - .value = 0xc8000 - }, - { - .description = "CC00H", - .value = 0xcc000 - }, - { - .description = "D000H", - .value = 0xd0000 - }, - { - .description = "D400H", - .value = 0xd4000 - }, - { - .description = "D800H", - .value = 0xd8000 - }, - { - .description = "DC00H", - .value = 0xdc000 - }, - { - .description = "E000H", - .value = 0xe0000 - }, - { - .description = "E400H", - .value = 0xe4000 - }, - { - .description = "E800H", - .value = 0xe8000 - }, - { - .description = "EC00H", - .value = 0xec000 - }, - { - .description = "" - } + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Color", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "Color (no brown)", .value = 4 }, + { .description = "" } }, + .bios = { { 0 } } + }, + { + .name = "enable_nmi", + .description = "Enable NMI for CGA emulation", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xc0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "C000H", .value = 0xc0000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "E000H", .value = 0xe0000 }, + { .description = "E400H", .value = 0xe4000 }, + { .description = "E800H", .value = 0xe8000 }, + { .description = "EC00H", .value = 0xec000 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 88c26437a..d1391f1d1 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -3369,50 +3369,39 @@ tgui_force_redraw(void *priv) // clang-format off static const device_config_t tgui9440_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t tgui96xx_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } }, - .default_int = 4 + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index 9f329a604..9dd7e424d 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -521,28 +521,21 @@ tvga_force_redraw(void *priv) static const device_config_t tvga_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 KB", - .value = 256 - }, - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, /*Chip supports 2mb, but drivers are buggy*/ - { - .description = "" - } - } + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format off diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index bf3b63736..e45f112ed 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -1308,119 +1308,121 @@ voodoo_close(void *priv) static const device_config_t voodoo_config[] = { // clang-format off { - .name = "type", - .description = "Voodoo type", - .type = CONFIG_SELECTION, + .name = "type", + .description = "Voodoo type", + .type = CONFIG_SELECTION, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, .selection = { - { - .description = "3Dfx Voodoo Graphics", - .value = VOODOO_1 - }, - { - .description = "Obsidian SB50 + Amethyst (2 TMUs)", - .value = VOODOO_SB50 - }, - { - .description = "3Dfx Voodoo 2", - .value = VOODOO_2 - }, - { - .description = "" - } + { .description = "3Dfx Voodoo Graphics", .value = VOODOO_1 }, + { .description = "Obsidian SB50 + Amethyst (2 TMUs)", .value = VOODOO_SB50 }, + { .description = "3Dfx Voodoo 2", .value = VOODOO_2 }, + { .description = "" } }, - .default_int = 0 + .bios = { { 0 } } }, { - .name = "framebuffer_memory", - .description = "Framebuffer memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } + .name = "framebuffer_memory", + .description = "Framebuffer memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { - .name = "texture_memory", - .description = "Texture memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } + .name = "texture_memory", + .description = "Texture memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "4", .value = 4 }, + { .description = "" } }, - .default_int = 2 + .bios = { { 0 } } }, { - .name = "sli", - .description = "SLI", - .type = CONFIG_BINARY, - .default_int = 0 + .name = "sli", + .description = "SLI", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, #ifndef NO_CODEGEN { - .name = "recompiler", - .description = "Dynamic Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 + .name = "recompiler", + .description = "Dynamic Recompiler", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } }, #endif { .name = "", .description = "", .type = CONFIG_END } diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index d2c694a4c..fadd782a5 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -3178,186 +3178,6 @@ banshee_pci_write(int func, int addr, uint8_t val, void *priv) } } -// clang-format off -static const device_config_t banshee_sgram_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "8 MB", - .value = 8 - }, - { - .description = "16 MB", - .value = 16 - }, - { - .description = "" - } - }, - .default_int = 16 - }, - { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 - }, -#ifndef NO_CODEGEN - { - .name = "recompiler", - .description = "Dynamic Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 - }, -#endif - { .name = "", .description = "", .type = CONFIG_END } -}; - -static const device_config_t banshee_sgram_16mbonly_config[] = { - { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 - }, -#ifndef NO_CODEGEN - { - .name = "recompiler", - .description = "Dynamic Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 - }, -#endif - { .name = "", .description = "", .type = CONFIG_END } -}; - -static const device_config_t banshee_sdram_config[] = { - { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 - }, -#ifndef NO_CODEGEN - { - .name = "recompiler", - .description = "Dynamic Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 - }, -#endif - { .name = "", .description = "", .type = CONFIG_END } -}; -// clang-format on - static void * banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int voodoo_type, int agp) { @@ -3749,6 +3569,221 @@ banshee_force_redraw(void *priv) banshee->svga.fullchange = changeframecount; } +// clang-format off +static const device_config_t banshee_sgram_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 16, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "8 MB", .value = 8 }, + { .description = "16 MB", .value = 16 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "4", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, +#ifndef NO_CODEGEN + { + .name = "recompiler", + .description = "Dynamic Recompiler", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t banshee_sgram_16mbonly_config[] = { + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "4", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, +#ifndef NO_CODEGEN + { + .name = "recompiler", + .description = "Dynamic Recompiler", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t banshee_sdram_config[] = { + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "4", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, +#ifndef NO_CODEGEN + { + .name = "recompiler", + .description = "Dynamic Recompiler", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + const device_t voodoo_banshee_device = { .name = "3Dfx Voodoo Banshee", .internal_name = "voodoo_banshee_pci", diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index f5d46f937..a469330af 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -41,7 +41,7 @@ #define XGA2_BIOS_PATH "roms/video/xga/xga2_v300.bin" #define INMOS_XGA_BIOS_PATH "roms/video/xga/InMOS XGA - Fairchild NM27C256Q-150.BIN" -static video_timings_t timing_xga_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_xga_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; static video_timings_t timing_xga_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; static void xga_ext_outb(uint16_t addr, uint8_t val, void *priv); @@ -3660,24 +3660,19 @@ xga_force_redraw(void *priv) static const device_config_t xga_mca_configuration[] = { // clang-format off { - .name = "type", - .description = "XGA type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "XGA-1", - .value = 0 - }, - { - .description = "XGA-2", - .value = 1 - }, - { .description = "" } - } + .name = "type", + .description = "XGA type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "XGA-1", .value = 0 }, + { .description = "XGA-2", .value = 1 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -3686,34 +3681,29 @@ static const device_config_t xga_mca_configuration[] = { static const device_config_t xga_isa_configuration[] = { // clang-format off { - .name = "type", - .description = "XGA type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "XGA-1", - .value = 0 - }, - { - .description = "XGA-2", - .value = 1 - }, - { .description = "" } - } + .name = "type", + .description = "XGA type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "XGA-1", .value = 0 }, + { .description = "XGA-2", .value = 1 }, + { .description = "" } + }, + .bios = { { 0 } } }, { - .name = "instance", - .description = "Instance", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 6, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "instance", + .description = "Instance", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 6, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "0 (2100h-210Fh)", .value = 0 }, { .description = "1 (2110h-211Fh)", .value = 1 }, { .description = "2 (2120h-212Fh)", .value = 2 }, @@ -3722,18 +3712,19 @@ static const device_config_t xga_isa_configuration[] = { { .description = "5 (2150h-215Fh)", .value = 5 }, { .description = "6 (2160h-216Fh)", .value = 6 }, { .description = "7 (2170h-217Fh)", .value = 7 }, - { .description = "" } + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "ext_mem_addr", - .description = "MMIO Address", - .type = CONFIG_HEX16, - .default_string = "", - .default_int = 0x00f0, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "ext_mem_addr", + .description = "MMIO Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x00f0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "C800h", .value = 0x0040 }, { .description = "CA00h", .value = 0x0050 }, { .description = "CC00h", .value = 0x0060 }, @@ -3746,23 +3737,25 @@ static const device_config_t xga_isa_configuration[] = { { .description = "DA00h", .value = 0x00d0 }, { .description = "DC00h", .value = 0x00e0 }, { .description = "DE00h", .value = 0x00f0 }, - { .description = "" } + { .description = "" } }, + .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { .description = "Disabled", .value = 0 }, - { .description = "DMA 6", .value = 6 }, - { .description = "DMA 7", .value = 7 }, - { .description = "" } + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -3771,39 +3764,35 @@ static const device_config_t xga_isa_configuration[] = { static const device_config_t xga_inmos_isa_configuration[] = { // clang-format off { - .name = "type", - .description = "XGA type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { - .description = "XGA-1", - .value = 0 - }, - { - .description = "XGA-2", - .value = 1 - }, - { .description = "" } - } - }, - { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 7, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "Disabled", .value = 0 }, - { .description = "DMA 6", .value = 6 }, - { .description = "DMA 7", .value = 7 }, + .name = "type", + .description = "XGA type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "XGA-1", .value = 0 }, + { .description = "XGA-2", .value = 1 }, { .description = "" } }, + .bios = { { 0 } } + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on From 03c74f8bb6cce2b92aa85be7cbadc43e5a61168c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 8 Feb 2025 16:10:26 +0100 Subject: [PATCH 0209/1190] Fix the AC flag on 8-bit and 16-bit ADC and SBB instructions. --- src/cpu/x86_flags.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpu/x86_flags.h b/src/cpu/x86_flags.h index e82041783..7d5c41ca8 100644 --- a/src/cpu/x86_flags.h +++ b/src/cpu/x86_flags.h @@ -741,7 +741,7 @@ setadc8(uint8_t a, uint8_t b) cpu_state.flags |= C_FLAG; if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) cpu_state.flags |= V_FLAG; - if (((a & 0xF) + (b & 0xF)) & 0x10) + if (((a & 0xF) + (b & 0xF) + tempc) & 0x10) cpu_state.flags |= A_FLAG; } static __inline void @@ -755,7 +755,7 @@ setadc16(uint16_t a, uint16_t b) cpu_state.flags |= C_FLAG; if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) cpu_state.flags |= V_FLAG; - if (((a & 0xF) + (b & 0xF)) & 0x10) + if (((a & 0xF) + (b & 0xF) + tempc) & 0x10) cpu_state.flags |= A_FLAG; } static __inline void @@ -785,7 +785,7 @@ setsbc8(uint8_t a, uint8_t b) cpu_state.flags |= C_FLAG; if ((a ^ b) & (a ^ c) & 0x80) cpu_state.flags |= V_FLAG; - if (((a & 0xF) - (b & 0xF)) & 0x10) + if (((a & 0xF) - ((b & 0xF) + tempc)) & 0x10) cpu_state.flags |= A_FLAG; } static __inline void @@ -800,7 +800,7 @@ setsbc16(uint16_t a, uint16_t b) cpu_state.flags |= C_FLAG; if ((a ^ b) & (a ^ c) & 0x8000) cpu_state.flags |= V_FLAG; - if (((a & 0xF) - (b & 0xF)) & 0x10) + if (((a & 0xF) - ((b & 0xF) + tempc)) & 0x10) cpu_state.flags |= A_FLAG; } From b86e459e78a388c9698ab05019dcaeda1695d220 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Feb 2025 19:23:57 -0500 Subject: [PATCH 0210/1190] A couple of cleanups in hdc_ide.c --- src/disk/hdc_ide.c | 11 +++++------ src/include/86box/hdc.h | 1 - src/include/86box/hdc_ide.h | 10 +++++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 1583d6b9c..c5f776b3e 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -2920,9 +2920,8 @@ ide_ter_init(const device_t *info) if (irq == -1) isapnp_add_card(ide_ter_pnp_rom, sizeof(ide_ter_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 2); - } else { + } else ide_board_init(2, irq, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0, 0); - } return (ide_boards[2]); } @@ -3004,10 +3003,10 @@ ide_init(const device_t *info) switch (info->local) { case 0 ... 5: - ide_board_init(0, 14, 0x1f0, 0x3f6, info->local, info->flags); + ide_board_init(0, HDC_PRIMARY_IRQ, HDC_PRIMARY_BASE, HDC_PRIMARY_SIDE, info->local, info->flags); if (info->local & 1) - ide_board_init(1, 15, 0x170, 0x376, info->local, info->flags); + ide_board_init(1, HDC_SECONDARY_IRQ, HDC_SECONDARY_BASE, HDC_SECONDARY_SIDE, info->local, info->flags); break; default: @@ -3122,8 +3121,8 @@ static void mcide_mca_write(const int port, const uint8_t val, void *priv) { mcide_t *dev = (mcide_t *) priv; - uint16_t bases[4] = { 0x01f0, 0x0170, 0x01e8, 0x0168 }; - int irqs[4] = { 10, 11, 14, 15 }; + uint16_t bases[4] = { HDC_PRIMARY_BASE, HDC_SECONDARY_BASE, HDC_TERTIARY_BASE, HDC_QUATERNARY_BASE }; + int irqs[4] = { HDC_QUATERNARY_IRQ, HDC_TERTIARY_IRQ, HDC_PRIMARY_IRQ, HDC_SECONDARY_IRQ }; if ((port >= 0x102) && (dev->pos_regs[port & 7] != val)) { ide_log("IDE: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 110804244..5e09c2242 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -51,7 +51,6 @@ extern const device_t esdi_ps2_device; /* esdi_mca */ extern const device_t ide_isa_device; /* isa_ide */ extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ -extern const device_t ide_isa_2ch_opt_device; /* isa_ide_2ch_opt */ extern const device_t ide_vlb_device; /* vlb_ide */ extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ extern const device_t ide_pci_device; /* pci_ide */ diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 0280cf301..6af4d92e6 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -25,17 +25,17 @@ #define IDE_BUS_MAX 4 #define IDE_CHAN_MAX 2 -#define HDC_PRIMARY_BASE 0x01F0 -#define HDC_PRIMARY_SIDE 0x03F6 +#define HDC_PRIMARY_BASE 0x01f0 +#define HDC_PRIMARY_SIDE 0x03f6 #define HDC_PRIMARY_IRQ 14 #define HDC_SECONDARY_BASE 0x0170 #define HDC_SECONDARY_SIDE 0x0376 #define HDC_SECONDARY_IRQ 15 -#define HDC_TERTIARY_BASE 0x01E8 -#define HDC_TERTIARY_SIDE 0x03EE +#define HDC_TERTIARY_BASE 0x01e8 +#define HDC_TERTIARY_SIDE 0x03ee #define HDC_TERTIARY_IRQ 11 #define HDC_QUATERNARY_BASE 0x0168 -#define HDC_QUATERNARY_SIDE 0x036E +#define HDC_QUATERNARY_SIDE 0x036e #define HDC_QUATERNARY_IRQ 10 enum { From 0c997cc4eb922a09a3f3dbacf7b472d26b681085 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Feb 2025 19:28:37 -0500 Subject: [PATCH 0211/1190] Add ISA, VLB & PCI second channel IDE devs --- src/disk/hdc_ide.c | 61 +++++++++++++++++++++++++++++++++++++++++ src/include/86box/hdc.h | 3 ++ 2 files changed, 64 insertions(+) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index c5f776b3e..3e1ce39f8 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -2902,6 +2902,25 @@ ide_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) } } +static void * +ide_sec_init(const device_t *info) +{ + /* Don't claim this channel again if it was already claimed. */ + if (ide_boards[1]) + return (NULL); + + ide_board_init(1, HDC_SECONDARY_IRQ, HDC_SECONDARY_BASE, HDC_SECONDARY_SIDE, info->local, info->flags); + + return (ide_boards[1]); +} + +/* Close a standalone IDE unit. */ +static void +ide_sec_close(UNUSED(void *priv)) +{ + ide_board_close(1); +} + static void * ide_ter_init(const device_t *info) { @@ -3274,6 +3293,20 @@ const device_t ide_isa_device = { .config = NULL }; +const device_t ide_isa_sec_device = { + .name = "ISA PC/AT IDE Controller (Secondary)", + .internal_name = "ide_isa_sec", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t ide_isa_2ch_device = { .name = "ISA PC/AT IDE Controller (Dual-Channel)", .internal_name = "ide_isa_2ch", @@ -3302,6 +3335,20 @@ const device_t ide_vlb_device = { .config = NULL }; +const device_t ide_vlb_sec_device = { + .name = "VLB IDE Controller (Secondary)", + .internal_name = "ide_vlb_sec", + .flags = DEVICE_VLB | DEVICE_AT, + .local = 2, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t ide_vlb_2ch_device = { .name = "VLB IDE Controller (Dual-Channel)", .internal_name = "ide_vlb_2ch", @@ -3330,6 +3377,20 @@ const device_t ide_pci_device = { .config = NULL }; +const device_t ide_pci_sec_device = { + .name = "PCI IDE Controller (Secondary)", + .internal_name = "ide_pci_sec", + .flags = DEVICE_PCI | DEVICE_AT, + .local = 4, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t ide_pci_2ch_device = { .name = "PCI IDE Controller (Dual-Channel)", .internal_name = "ide_pci_2ch", diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 5e09c2242..7731d60d4 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -50,10 +50,13 @@ extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ extern const device_t esdi_ps2_device; /* esdi_mca */ extern const device_t ide_isa_device; /* isa_ide */ +extern const device_t ide_isa_sec_device; /* isa_ide sec*/ extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ extern const device_t ide_vlb_device; /* vlb_ide */ +extern const device_t ide_vlb_sec_device; /* vlb_ide sec */ extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ extern const device_t ide_pci_device; /* pci_ide */ +extern const device_t ide_pci_sec_device; /* pci_ide sec */ extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ extern const device_t ide_ali1489_device; /* ALi M1489 */ From 61d583425501f9e3b0d9ce2700a2c2c2058f0526 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Feb 2025 23:23:47 -0300 Subject: [PATCH 0212/1190] CS423x: Add some more missing CS4235 features and locks --- src/sound/snd_ad1848.c | 58 ++++++++++++++++++++++++------------------ src/sound/snd_cs423x.c | 4 +++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index d870b4588..f78bc841b 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -303,30 +303,35 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 18: case 19: if (ad1848->type >= AD1848_TYPE_CS4236B) { - if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */ - ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */ - temp = 1; + if (ad1848->type >= AD1848_TYPE_CS4235) { + if (ad1848->xregs[18] & 0x20) /* AUX1 remapping */ + ad1848->regs[ad1848->index & 3] = val; /* also controls AUX1 on registers 2 and 3 */ + } else { + if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */ + ad1848->xregs[6 | (ad1848->index & 1)] = val; /* real FM volume on extended registers 6 and 7 */ + temp = 1; - if (ad1848->index == 18) { - if (val & 0x80) - ad1848->fm_vol_l = 0; - else - ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f]; - } else { - if (val & 0x80) - ad1848->fm_vol_r = 0; - else - ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f]; + if (ad1848->index == 18) { + if (val & 0x80) + ad1848->fm_vol_l = 0; + else + ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f]; + } else { + if (val & 0x80) + ad1848->fm_vol_r = 0; + else + ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f]; + } + } + if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */ + ad1848->xregs[16 | (ad1848->index & 1)] = val; /* real wavetable volume on extended registers 16 and 17 */ + temp = 1; } - } - if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */ - ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */ - temp = 1; - } - /* Stop here if any remapping is enabled. */ - if (temp) - return; + /* Stop here if any remapping is enabled. */ + if (temp) + return; + } /* HACK: the Windows 9x driver's "Synth" control writes to this register with no remapping, even if internal FM is enabled. */ @@ -366,9 +371,11 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) switch (ad1848->xindex) { case 0 ... 1: - /* Remapped line volume. */ - ad1848->regs[18 + ad1848->xindex] = val; - return; + if (ad1848->type < AD1848_TYPE_CS4235) { + /* Remapped line volume. */ + ad1848->regs[18 | ad1848->xindex] = val; + } + break; case 6: if (val & 0x80) @@ -747,7 +754,8 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) ad1848->regs[30] = ad1848->regs[31] = 0; if (type >= AD1848_TYPE_CS4236B) { - ad1848->xregs[0] = ad1848->xregs[1] = 0xe8; + if (type < AD1848_TYPE_CS4235) + ad1848->xregs[0] = ad1848->xregs[1] = 0xe8; ad1848->xregs[2] = ad1848->xregs[3] = 0xcf; ad1848->xregs[4] = 0x84; ad1848->xregs[5] = 0; diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index f6ded130a..4f9050924 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -692,6 +692,10 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) dev->regs[4] &= ~0x40; } + /* Update X18 bits. */ + if (dev->type >= CRYSTAL_CS4235) + dev->ad1848.xregs[18] = (dev->ad1848.xregs[18] & ~0x3e) | (dev->ram_data[0x400b] & 0x3e); + /* Inform WSS codec of the changes. */ ad1848_updatevolmask(&dev->ad1848); } From 8d2150777cf885197ec0d4de15592b0aa04e5b60 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Feb 2025 23:28:50 -0300 Subject: [PATCH 0213/1190] CS423x: Add one more missing CS4235 hardware config byte --- src/sound/snd_cs423x.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 4f9050924..cf38ccb4b 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -654,9 +654,10 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) Disable the PnP key disabling mechanism until someone figures something out. */ #if 0 isapnp_enable_card(dev->pnp_card, ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) ? ISAPNP_CARD_NO_KEY : ISAPNP_CARD_ENABLE); -#endif +#else if ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) pclog("CS423x: Attempted to disable PnP key\n"); +#endif } /* Update some register bits based on the config data in RAM if requested. */ @@ -684,17 +685,19 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) else dev->ad1848.xregs[4] &= ~0x10; - /* Update VCEN. */ if (dev->type == CRYSTAL_CS4236) { + /* Update VCEN. */ if (dev->ram_data[0x4002] & 0x04) dev->regs[4] |= 0x40; else dev->regs[4] &= ~0x40; } - /* Update X18 bits. */ - if (dev->type >= CRYSTAL_CS4235) + if (dev->type >= CRYSTAL_CS4235) { + /* Update X18 and X19 values. */ dev->ad1848.xregs[18] = (dev->ad1848.xregs[18] & ~0x3e) | (dev->ram_data[0x400b] & 0x3e); + dev->ad1848.xregs[19] = dev->ram_data[0x4005]; + } /* Inform WSS codec of the changes. */ ad1848_updatevolmask(&dev->ad1848); @@ -898,7 +901,7 @@ cs423x_init(const device_t *info) /* Different WSS codec families. */ dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : ((dev->type >= CRYSTAL_CS4236B) ? AD1848_TYPE_CS4236B : AD1848_TYPE_CS4236); - /* Different Chip Version and ID registers (N/A on CS4236), which shouldn't be reset by ad1848_init. */ + /* Different Chip Version and ID values (N/A on CS4236), which shouldn't be reset by ad1848_init. */ dev->ad1848.xregs[25] = dev->type; /* Same EEPROM structure. */ From 83b3b322ac8a549bc40b3501e498ba46164d56b8 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Feb 2025 23:46:26 -0300 Subject: [PATCH 0214/1190] CS423x: Playback powerdown check fixes --- src/sound/snd_cs423x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index cf38ccb4b..f5458eaf0 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -606,8 +606,8 @@ cs423x_get_buffer(int32_t *buffer, int len, void *priv) /* Output audio from the WSS codec, and also the OPL if we're in charge of it. */ ad1848_update(&dev->ad1848); - /* Don't output anything if the analog section is powered down. */ - if (!(dev->indirect_regs[2] & 0xa4) && !(dev->indirect_regs[9] & 0x04)) { + /* Don't output anything if the analog section or DAC is powered down. */ + if (!(dev->regs[2] & 0xb4) && !(dev->indirect_regs[9] & 0x04)) { for (int c = 0; c < len * 2; c += 2) { buffer[c] += dev->ad1848.buffer[c] / 2; buffer[c + 1] += dev->ad1848.buffer[c + 1] / 2; @@ -626,8 +626,9 @@ cs423x_get_music_buffer(int32_t *buffer, int len, void *priv) if (dev->opl_wss) { const int32_t *opl_buf = dev->sb->opl.update(dev->sb->opl.priv); - /* Don't output anything if the analog section or DAC2 (CS4235+) is powered down. */ - if (!(dev->indirect_regs[2] & 0xa4) && !(dev->indirect_regs[9] & 0x06)) { + /* Don't output anything if the analog section, DAC (DAC2 instead on CS4235+) or FM synth is powered down. */ + uint8_t bpd_mask = (dev->type >= CRYSTAL_CS4235) ? 0xb1 : 0xb5; + if (!(dev->regs[2] & bpd_mask) && !(dev->indirect_regs[9] & 0x06)) { for (int c = 0; c < len * 2; c += 2) { buffer[c] += (opl_buf[c] * dev->ad1848.fm_vol_l) >> 16; buffer[c + 1] += (opl_buf[c + 1] * dev->ad1848.fm_vol_r) >> 16; From bb51c324e2ebc955f7711063d83926f053a2760f Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 9 Feb 2025 00:03:25 -0300 Subject: [PATCH 0215/1190] CS423x: Add remaining CS4235 extended->control register access paths --- src/sound/snd_ad1848.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index f78bc841b..87755a96c 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -167,6 +167,7 @@ ad1848_read(uint16_t addr, void *priv) { ad1848_t *ad1848 = (ad1848_t *) priv; uint8_t ret = 0xff; + uint8_t temp = 0; switch (addr & 3) { case 0: /* Index */ @@ -207,10 +208,22 @@ ad1848_read(uint16_t addr, void *priv) ret = ad1848->regs[18 + ad1848->xindex]; break; - case 26: - /* Backdoor to the Joystick Control register on CS4235+. */ + case 23 ... 24: + case 29: + /* Backdoor to control indirect registers on CS4235+. */ + if (ad1848->type >= AD1848_TYPE_CS4235) { + temp = ad1848->cram_read(3, ad1848->cram_priv); + ad1848->cram_write(3, (ad1848->xindex == 23) ? 2 : ((ad1848->xindex == 24) ? 8 : 9), ad1848->cram_priv); + ret = ad1848->cram_read(4, ad1848->cram_priv); + ad1848->cram_write(3, temp, ad1848->cram_priv); + } + break; + + case 26 ... 28: + case 30: + /* Backdoor to control registers on CS4235+. */ if (ad1848->type >= AD1848_TYPE_CS4235) - ret = ad1848->cram_read(0, ad1848->cram_priv); + ret = ad1848->cram_read((ad1848->xindex == 30) ? 7 : (ad1848->xindex - 26), ad1848->cram_priv); break; default: @@ -396,13 +409,25 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) updatefreq = 1; break; + case 23 ... 24: + case 29: + /* Backdoor to control indirect registers on CS4235+. */ + if (ad1848->type >= AD1848_TYPE_CS4235) { + temp = ad1848->cram_read(3, ad1848->cram_priv); + ad1848->cram_write(3, (ad1848->xindex == 23) ? 2 : ((ad1848->xindex == 24) ? 8 : 9), ad1848->cram_priv); + ad1848->cram_write(4, val, ad1848->cram_priv); + ad1848->cram_write(3, temp, ad1848->cram_priv); + } + break; + case 25: return; - case 26: - /* Backdoor to the Joystick Control register on CS4235+. */ + case 26 ... 28: + case 30: + /* Backdoor to control registers on CS4235+. */ if (ad1848->type >= AD1848_TYPE_CS4235) - ad1848->cram_write(0, val, ad1848->cram_priv); + ad1848->cram_write((ad1848->xindex == 30) ? 7 : (ad1848->xindex - 26), val, ad1848->cram_priv); break; default: From 1936c05c8829f9e6e052861e89309a1339b4c65d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 9 Feb 2025 00:58:57 -0500 Subject: [PATCH 0216/1190] Fix warnings in ide_sec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča --- src/disk/hdc_ide.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 3e1ce39f8..3683c8671 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3298,8 +3298,8 @@ const device_t ide_isa_sec_device = { .internal_name = "ide_isa_sec", .flags = DEVICE_ISA | DEVICE_AT, .local = 0, - .init = ide_init, - .close = ide_close, + .init = ide_sec_init, + .close = ide_sec_close, .reset = ide_reset, .available = NULL, .speed_changed = NULL, @@ -3340,8 +3340,8 @@ const device_t ide_vlb_sec_device = { .internal_name = "ide_vlb_sec", .flags = DEVICE_VLB | DEVICE_AT, .local = 2, - .init = ide_init, - .close = ide_close, + .init = ide_sec_init, + .close = ide_sec_close, .reset = ide_reset, .available = NULL, .speed_changed = NULL, @@ -3382,8 +3382,8 @@ const device_t ide_pci_sec_device = { .internal_name = "ide_pci_sec", .flags = DEVICE_PCI | DEVICE_AT, .local = 4, - .init = ide_init, - .close = ide_close, + .init = ide_sec_init, + .close = ide_sec_close, .reset = ide_reset, .available = NULL, .speed_changed = NULL, From d00f80d3ce85546c170187cc1ef9ae1402a6bdf6 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 9 Sep 2024 00:43:14 -0400 Subject: [PATCH 0217/1190] General changes from the obattler_202406 branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča --- CMakeLists.txt | 2 +- CMakePresets.json | 8 + cmake/flags-gcc.cmake | 4 +- src/acpi.c | 3 +- src/chipset/stpc.c | 33 +-- src/chipset/umc_8886.c | 2 + src/chipset/wd76c10.c | 12 +- src/device.c | 7 + src/device/CMakeLists.txt | 44 +-- src/disk/hdc_ide_w83769f.c | 2 +- src/include/86box/hdc.h | 2 +- src/include/86box/keyboard.h | 22 +- src/include/86box/lpt.h | 14 +- src/include/86box/sio.h | 62 +++- src/io.c | 4 +- src/lpt.c | 4 +- src/machine/m_at_286_386sx.c | 8 +- src/machine/m_at_386dx_486.c | 5 +- src/machine/m_at_commodore.c | 6 +- src/machine/m_ps1.c | 8 +- src/machine/m_ps2_isa.c | 8 +- src/machine/m_ps2_mca.c | 26 +- src/machine/m_xt_compaq.c | 4 +- src/machine/m_xt_zenith.c | 4 +- src/network/net_plip.c | 2 +- src/printer/prt_ps.c | 2 +- src/sio/sio_82091aa.c | 2 +- src/sio/sio_acc3221.c | 4 +- src/sio/sio_ali5123.c | 8 +- src/sio/sio_f82c710.c | 4 +- src/sio/sio_fdc37c669.c | 2 +- src/sio/sio_fdc37c67x.c | 2 +- src/sio/sio_fdc37c6xx.c | 14 +- src/sio/sio_fdc37c93x.c | 533 +++++++++++++++++------------------ src/sio/sio_fdc37m60x.c | 2 +- src/sio/sio_it86x1f.c | 2 +- src/sio/sio_pc87306.c | 26 +- src/sio/sio_pc87307.c | 2 +- src/sio/sio_pc87309.c | 2 +- src/sio/sio_pc87310.c | 2 +- src/sio/sio_pc87311.c | 2 +- src/sio/sio_pc87332.c | 2 +- src/sio/sio_prime3b.c | 2 +- src/sio/sio_prime3c.c | 2 +- src/sio/sio_um8663f.c | 10 +- src/sio/sio_um8669f.c | 2 +- src/sio/sio_vt82c686.c | 2 +- src/sio/sio_w83787f.c | 4 +- src/sio/sio_w83877f.c | 2 +- src/sio/sio_w83977f.c | 4 +- src/sound/snd_lpt_dac.c | 2 +- src/sound/snd_lpt_dss.c | 2 +- src/video/vid_colorplus.c | 4 +- src/video/vid_hercules.c | 4 +- src/video/vid_herculesplus.c | 6 +- src/video/vid_incolor.c | 4 +- src/video/vid_mda.c | 4 +- 57 files changed, 493 insertions(+), 468 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d7b3f6f0..aa687222a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ # Authors: David Hrdlička, # # Copyright 2020-2021 David Hrdlička. -# Copyright 2021-2024 Jasmine Iwanek. +# Copyright 2021-2025 Jasmine Iwanek. # cmake_minimum_required(VERSION 3.16) diff --git a/CMakePresets.json b/CMakePresets.json index d4af8e6cb..be6615088 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -55,6 +55,14 @@ }, "inherits": "base" }, + { + "name": "ultra_debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "UltraDebug", + "DEV_BRANCH": "ON" + }, + "inherits": "base" + }, { "name": "llvm-macos-aarch64.cmake", "displayName": "MacOS clang regular", diff --git a/cmake/flags-gcc.cmake b/cmake/flags-gcc.cmake index 885353b87..90eb52cd1 100644 --- a/cmake/flags-gcc.cmake +++ b/cmake/flags-gcc.cmake @@ -20,6 +20,8 @@ string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -g0 -O3") string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -g0 -O3") string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " -ggdb -Og") string(APPEND CMAKE_CXX_FLAGS_DEBUG_INIT " -ggdb -Og") +string(APPEND CMAKE_C_FLAGS_ULTRADEBUG_INIT " -O0 -ggdb -g3") +string(APPEND CMAKE_CXX_FLAGS_ULTRADEBUG_INIT " -O0 -ggdb -g3") string(APPEND CMAKE_C_FLAGS_OPTIMIZED_INIT " -march=native -mtune=native -O3 -ffp-contract=fast -flto") string(APPEND CMAKE_CXX_FLAGS_OPTIMIZED_INIT " -march=native -mtune=native -O3 -ffp-contract=fast -flto") @@ -28,7 +30,7 @@ foreach(LANG C;CXX) set(CMAKE_${LANG}_FLAGS "$ENV{${LANG}FLAGS} ${CMAKE_${LANG}_FLAGS_INIT}" CACHE STRING "Flags used by the ${LANG} compiler during all build types.") mark_as_advanced(CMAKE_${LANG}_FLAGS) - foreach(CONFIG RELEASE;DEBUG;OPTIMIZED) + foreach(CONFIG RELEASE;DEBUG;ULTRADEBUG;OPTIMIZED) set(CMAKE_${LANG}_FLAGS_${CONFIG} "${CMAKE_${LANG}_FLAGS_${CONFIG}_INIT}" CACHE STRING "Flags used by the ${LANG} compiler during ${CONFIG} builds.") mark_as_advanced(CMAKE_${LANG}_FLAGS_${CONFIG}) endforeach() diff --git a/src/acpi.c b/src/acpi.c index 2850a340d..b33653663 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -2473,10 +2473,9 @@ acpi_init(const device_t *info) { acpi_t *dev; - dev = (acpi_t *) malloc(sizeof(acpi_t)); + dev = (acpi_t *) calloc(1, sizeof(acpi_t)); if (dev == NULL) return NULL; - memset(dev, 0x00, sizeof(acpi_t)); cpu_to_acpi = ACPI_TIMER_FREQ / cpuclock; dev->vendor = info->local; diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index 23cc56bd3..13dbd97e9 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -975,39 +975,24 @@ stpc_serial_init(UNUSED(const device_t *info)) static void stpc_lpt_handlers(stpc_lpt_t *dev, uint8_t val) { - uint8_t old_addr = (dev->reg1 & 0x03); - uint8_t new_addr = (val & 0x03); + const uint8_t new_addr = (val & 0x03); - switch (old_addr) { - case 0x1: - lpt3_remove(); - break; - - case 0x2: - lpt1_remove(); - break; - - case 0x3: - lpt2_remove(); - break; - default: - break; - } + lpt1_remove(); switch (new_addr) { case 0x1: stpc_log("STPC: Remapping parallel port to LPT3\n"); - lpt3_init(0x3bc); + lpt1_setup(LPT_MDA_ADDR); break; case 0x2: stpc_log("STPC: Remapping parallel port to LPT1\n"); - lpt1_init(0x378); + lpt1_setup(LPT1_ADDR); break; case 0x3: stpc_log("STPC: Remapping parallel port to LPT2\n"); - lpt2_init(0x278); + lpt1_setup(LPT2_ADDR); break; default: @@ -1015,9 +1000,11 @@ stpc_lpt_handlers(stpc_lpt_t *dev, uint8_t val) break; } - dev->reg1 = (val & 0x08); - dev->reg1 |= new_addr; - dev->reg1 |= 0x84; /* reserved bits that default to 1; hardwired? */ + if (dev != NULL) { + dev->reg1 = (val & 0x08); + dev->reg1 |= new_addr; + dev->reg1 |= 0x84; /* reserved bits that default to 1; hardwired? */ + } } static void diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index f96480c2c..0ed062450 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -82,6 +82,8 @@ #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/keyboard.h> +#include <86box/machine.h> #include <86box/pic.h> #include <86box/pci.h> #include <86box/port_92.h> diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index d7d8b0fe2..a375c8eb6 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -542,16 +542,16 @@ wd76c10_ser_par_cs_recalc(wd76c10_t *dev) lpt1_remove(); switch ((dev->ser_par_cs >> 9) & 0x03) { case 1: - lpt1_init(0x3bc); - lpt1_irq(7); + lpt1_setup(LPT_MDA_ADDR); + lpt1_irq(LPT1_IRQ); break; case 2: - lpt1_init(0x378); - lpt1_irq(7); + lpt1_setup(LPT1_ADDR); + lpt1_irq(LPT1_IRQ); break; case 3: - lpt1_init(0x278); - lpt1_irq(7); + lpt1_setup(LPT2_ADDR); + lpt1_irq(LPT1_IRQ); break; } } diff --git a/src/device.c b/src/device.c index 1228eedd2..d7c80be7a 100644 --- a/src/device.c +++ b/src/device.c @@ -158,6 +158,13 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) void *priv = NULL; int16_t c; + /* + IMPORTANT: This is needed to gracefully handle machine + device addition if the relevant device is NULL. + */ + if (dev == NULL) + return NULL; + if (!device_available(dev)) { wchar_t temp[512] = { 0 }; swprintf(temp, sizeof_w(temp), diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index c9da627ef..678c700a5 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -13,48 +13,48 @@ # # Copyright 2020-2021 David Hrdlička. # Copyright 2021 Andreas J. Reichel. -# Copyright 2021-2024 Jasmine Iwanek. +# Copyright 2021-2025 Jasmine Iwanek. # add_library(dev OBJECT bugger.c - cassette.c cartridge.c + cassette.c + clock_ics9xxx.c hasp.c hwm.c + hwm_gl518sm.c hwm_lm75.c hwm_lm78.c - hwm_gl518sm.c hwm_vt82c686.c + i2c.c + i2c_gpio.c ibm_5161.c isamem.c isartc.c - ../lpt.c - pci_bridge.c - postcard.c - serial.c - unittester.c - clock_ics9xxx.c isapnp.c - i2c.c - i2c_gpio.c - smbus_piix4.c - smbus_ali7101.c - smbus_sis5595.c - keyboard.c - keyboard_xt.c kbc_at.c kbc_at_dev.c + keyboard.c keyboard_at.c + keyboard_xt.c + ../lpt.c mouse.c mouse_bus.c - mouse_serial.c - mouse_ps2.c - nec_mate_unk.c - phoenix_486_jumper.c - serial_passthrough.c - novell_cardkey.c mouse_microtouch_touchscreen.c + mouse_ps2.c + mouse_serial.c + nec_mate_unk.c + novell_cardkey.c + pci_bridge.c + phoenix_486_jumper.c + postcard.c + serial.c + serial_passthrough.c + smbus_ali7101.c + smbus_piix4.c + smbus_sis5595.c + unittester.c ) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC) diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c index 9c0f744b2..7829c5b92 100644 --- a/src/disk/hdc_ide_w83769f.c +++ b/src/disk/hdc_ide_w83769f.c @@ -10,7 +10,7 @@ * * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020-2025 Miran Grca. */ #include #include diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 7731d60d4..e798f2464 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -13,7 +13,7 @@ * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2025 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_HDC_H diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 225ab3936..ec5c05775 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -15,7 +15,7 @@ * Fred N. van Kempen, * * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2025 Miran Grca. * Copyright 2017-2019 Fred N. van Kempen. */ @@ -194,8 +194,8 @@ typedef struct scancode { extern "C" { #endif -extern uint8_t keyboard_mode; -extern int keyboard_scan; +extern uint8_t keyboard_mode; +extern int keyboard_scan; extern uint16_t scancode_map[768]; @@ -232,26 +232,26 @@ extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_xt_hyundai_device; extern const device_t keyboard_xtclone_device; extern const device_t keyboard_at_device; -extern const device_t keyboard_at_siemens_device; extern const device_t keyboard_at_ami_device; +extern const device_t keyboard_at_compaq_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; extern const device_t keyboard_at_tg_ami_device; extern const device_t keyboard_at_toshiba_device; -extern const device_t keyboard_at_olivetti_device; -extern const device_t keyboard_at_ncr_device; -extern const device_t keyboard_at_compaq_device; extern const device_t keyboard_ps2_device; extern const device_t keyboard_ps2_ps1_device; extern const device_t keyboard_ps2_ps1_pci_device; extern const device_t keyboard_ps2_xi8088_device; extern const device_t keyboard_ps2_ami_device; extern const device_t keyboard_ps2_holtek_device; -extern const device_t keyboard_ps2_tg_ami_device; -extern const device_t keyboard_ps2_tg_ami_green_device; -extern const device_t keyboard_ps2_olivetti_device; -extern const device_t keyboard_ps2_phoenix_device; extern const device_t keyboard_ps2_mca_1_device; extern const device_t keyboard_ps2_mca_2_device; +extern const device_t keyboard_ps2_olivetti_device; +extern const device_t keyboard_ps2_phoenix_device; extern const device_t keyboard_ps2_quadtel_device; +extern const device_t keyboard_ps2_tg_ami_device; +extern const device_t keyboard_ps2_tg_ami_green_device; extern const device_t keyboard_ps2_pci_device; extern const device_t keyboard_ps2_ami_pci_device; extern const device_t keyboard_ps2_intel_ami_pci_device; diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index 4e95b64c3..674d6340f 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -31,33 +31,33 @@ typedef struct lpt_device_t { } lpt_device_t; extern void lpt_init(void); -extern void lpt_port_init(int i, uint16_t port); +extern void lpt_port_setup(int i, uint16_t port); extern void lpt_port_irq(int i, uint8_t irq); extern void lpt_port_remove(int i); extern void lpt1_remove_ams(void); -#define lpt1_init(a) lpt_port_init(0, a) +#define lpt1_setup(a) lpt_port_setup(0, a) #define lpt1_irq(a) lpt_port_irq(0, a) #define lpt1_remove() lpt_port_remove(0) -#define lpt2_init(a) lpt_port_init(1, a) +#define lpt2_setup(a) lpt_port_setup(1, a) #define lpt2_irq(a) lpt_port_irq(1, a) #define lpt2_remove() lpt_port_remove(1) -#define lpt3_init(a) lpt_port_init(2, a) +#define lpt3_setup(a) lpt_port_setup(2, a) #define lpt3_irq(a) lpt_port_irq(2, a) #define lpt3_remove() lpt_port_remove(2) -#define lpt4_init(a) lpt_port_init(3, a) +#define lpt4_setup(a) lpt_port_setup(3, a) #define lpt4_irq(a) lpt_port_irq(3, a) #define lpt4_remove() lpt_port_remove(3) #if 0 -#define lpt5_init(a) lpt_port_init(4, a) +#define lpt5_setup(a) lpt_port_setup(4, a) #define lpt5_irq(a) lpt_port_irq(4, a) #define lpt5_remove() lpt_port_remove(4) -#define lpt6_init(a) lpt_port_init(5, a) +#define lpt6_setup(a) lpt_port_setup(5, a) #define lpt6_irq(a) lpt_port_irq(5, a) #define lpt6_remove() lpt_port_remove(5) #endif diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 2dbe97ab0..7fcb376b9 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -16,13 +16,20 @@ #ifndef EMU_SIO_H #define EMU_SIO_H -extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); - +/* ACC Micro */ extern const device_t acc3221_device; + +/* Acer / ALi */ extern const device_t ali5105_device; + extern const device_t ali5123_device; -extern const device_t f82c710_device; + +/* Chips & Technologies */ extern const device_t f82c606_device; + +extern const device_t f82c710_device; + +/* SM(S)C */ extern const device_t fdc37c651_device; extern const device_t fdc37c651_ide_device; extern const device_t fdc37c661_device; @@ -35,9 +42,12 @@ extern const device_t fdc37c665_ide_device; extern const device_t fdc37c665_ide_pri_device; extern const device_t fdc37c665_ide_sec_device; extern const device_t fdc37c666_device; -extern const device_t fdc37c67x_device; + extern const device_t fdc37c669_device; extern const device_t fdc37c669_370_device; + +extern const device_t fdc37c67x_device; + extern const device_t fdc37c931apm_device; extern const device_t fdc37c931apm_compaq_device; extern const device_t fdc37c932fr_device; @@ -46,22 +56,23 @@ extern const device_t fdc37c932_device; extern const device_t fdc37c935_device; extern const device_t fdc37c935_370_device; extern const device_t fdc37c935_no_nvr_device; + extern const device_t fdc37m60x_device; extern const device_t fdc37m60x_370_device; + +/* ITE */ extern const device_t it8661f_device; extern const device_t it8671f_device; extern const device_t i82091aa_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_pri_device; extern const device_t i82091aa_ide_device; -extern const device_t pc87306_device; -extern const device_t pc87307_device; -extern const device_t pc87307_15c_device; -extern const device_t pc87307_both_device; -extern const device_t pc87309_device; -extern const device_t pc87309_15c_device; + +/* National Semiconductors */ extern const device_t pc87310_device; extern const device_t pc87310_ide_device; + +extern const device_t pc87306_device; extern const device_t pc87311_device; extern const device_t pc87311_ide_device; extern const device_t pc87332_device; @@ -69,35 +80,66 @@ extern const device_t pc87332_398_device; extern const device_t pc87332_398_ide_device; extern const device_t pc87332_398_ide_sec_device; extern const device_t pc87332_398_ide_fdcon_device; + +extern const device_t pc87307_device; +extern const device_t pc87307_15c_device; +extern const device_t pc87307_both_device; extern const device_t pc97307_device; + +extern const device_t pc87309_device; +extern const device_t pc87309_15c_device; + +/* LG Prime */ extern const device_t prime3b_device; extern const device_t prime3b_ide_device; extern const device_t prime3c_device; extern const device_t prime3c_ide_device; + +/* IBM PS/1 */ extern const device_t ps1_m2133_sio; + +/* Super I/O Detect */ #ifdef USE_SIO_DETECT extern const device_t sio_detect_device; #endif /* USE_SIO_DETECT */ + +/* UMC */ extern const device_t um8663af_device; extern const device_t um8663af_ide_device; extern const device_t um8663af_sec_device; extern const device_t um8663bf_device; extern const device_t um8663bf_ide_device; extern const device_t um8663bf_sec_device; + extern const device_t um8669f_device; extern const device_t um8669f_ide_device; extern const device_t um8669f_ide_sec_device; + +/* VIA */ +extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); + extern const device_t via_vt82c686_sio_device; + +/* VLSI */ extern const device_t vl82c113_device; + +/* Winbond */ extern const device_t w83787f_88h_device; extern const device_t w83787f_device; extern const device_t w83787f_ide_device; extern const device_t w83787f_ide_en_device; extern const device_t w83787f_ide_sec_device; + extern const device_t w83877f_device; extern const device_t w83877f_president_device; extern const device_t w83877tf_device; extern const device_t w83877tf_acorp_device; + +#define TYPE_W83977EF 0x52F0 +#define TYPE_W83977F 0x9771 +#define TYPE_W83977TF 0x9773 +#define TYPE_W83977ATF 0x9774 + extern const device_t w83977f_device; extern const device_t w83977f_370_device; extern const device_t w83977tf_device; diff --git a/src/io.c b/src/io.c index fd87089d0..27f8503b0 100644 --- a/src/io.c +++ b/src/io.c @@ -15,7 +15,7 @@ * Fred N. van Kempen, * * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ #include #include @@ -145,6 +145,8 @@ io_sethandler_common(uint16_t base, int size, q->next = NULL; io_last[base + c] = q; + + q = NULL; } } diff --git a/src/lpt.c b/src/lpt.c index 3f1c5eb7b..26174d96b 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -219,14 +219,14 @@ lpt_init(void) lpt_ports[i].enable_irq = 0x10; if (lpt_ports[i].enabled) { - lpt_port_init(i, default_ports[i]); + lpt_port_setup(i, default_ports[i]); lpt_port_irq(i, default_irqs[i]); } } } void -lpt_port_init(int i, uint16_t port) +lpt_port_setup(int i, uint16_t port) { if (lpt_ports[i].enabled) { if (lpt_ports[i].addr != 0xffff) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index c3dc5c772..cb2a04d07 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -66,7 +66,7 @@ machine_at_mr286_init(const machine_t *model) } static void -machine_at_headland_common_init(int type) +machine_at_headland_common_init(const machine_t *model, int type) { device_add(&keyboard_at_ami_device); @@ -94,7 +94,7 @@ machine_at_tg286m_init(const machine_t *model) machine_at_common_ide_init(model); - machine_at_headland_common_init(1); + machine_at_headland_common_init(model, 1); return ret; } @@ -115,7 +115,7 @@ machine_at_ama932j_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&oti067_ama932j_device); - machine_at_headland_common_init(2); + machine_at_headland_common_init(model, 2); device_add(&ali5105_device); @@ -755,7 +755,7 @@ machine_at_acer100t_init(const machine_t *model) device_add(&ali1409_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&oti077_acer100t_device); + device_add(&oti077_acer100t_device); device_add(&ali5105_device); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 656db503b..3d152065b 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -50,6 +50,7 @@ #include <86box/plat_unused.h> #include <86box/sound.h> +/* 386DX */ int machine_at_acc386_init(const machine_t *model) { @@ -252,7 +253,7 @@ machine_at_ecs386v_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/ecs386v/PANDA_386V.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) return ret; @@ -1412,7 +1413,7 @@ machine_at_amis76_init(const machine_t *model) { int ret; - ret = bios_load_linear_inverted("roms/machines/s76p/S76P.ROM", + ret = bios_load_linear_inverted("roms/machines/s76p/S76P.ROM", 0x000e0000, 131072, 0); if (bios_only || !ret) diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index 0b45fe60c..b9615c064 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -64,13 +64,13 @@ cbm_io_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) switch (val & 3) { case 1: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 2: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 3: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 92846c401..130481394 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -146,13 +146,13 @@ ps1_write(uint16_t port, uint8_t val, void *priv) if (val & 0x10) { switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: @@ -316,7 +316,7 @@ ps1_setup(int model) ps->uart = device_add_inst(&ns16450_device, 1); lpt1_remove(); - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); mem_remap_top(384); diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 7d024c335..8a2760f15 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -64,13 +64,13 @@ ps2_write(uint16_t port, uint8_t val, void *priv) if (val & 0x10) { switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: @@ -167,7 +167,7 @@ ps2_isa_setup(int model, int cpu_type) ps2->uart = device_add_inst(&ns16450_device, 1); lpt1_remove(); - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); device_add(&port_92_device); diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 632381ca1..35f3ed125 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -374,13 +374,13 @@ model_50_write(uint16_t port, uint8_t val) if (val & 0x10) { switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: @@ -506,13 +506,13 @@ model_55sx_write(uint16_t port, uint8_t val) if (val & 0x10) { switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: @@ -565,13 +565,13 @@ model_70_type3_write(uint16_t port, uint8_t val) if (val & 0x10) { switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: @@ -619,13 +619,13 @@ model_80_write(uint16_t port, uint8_t val) if (val & 0x10) { switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: @@ -846,7 +846,7 @@ ps2_mca_board_common_init(void) ps2.setup = 0xff; - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); } static uint8_t diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index ed1b3e26c..f8c0b6a19 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -59,7 +59,7 @@ machine_xt_compaq_deskpro_init(const machine_t *model) standalone_gameport_type = &gameport_device; lpt1_remove(); - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); return ret; } @@ -87,7 +87,7 @@ machine_xt_compaq_portable_init(const machine_t *model) device_add(&gameport_device); lpt1_remove(); - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); return ret; } diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 833529ffb..6c5d556f2 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -144,7 +144,7 @@ machine_xt_z184_init(const machine_t *model) lpt1_remove(); /* only one parallel port */ lpt2_remove(); - lpt1_init(0x278); + lpt1_setup(LPT2_ADDR); device_add(&ns8250_device); serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ @@ -198,7 +198,7 @@ machine_xt_z159_init(const machine_t *model) /* parallel port is on the memory board */ lpt1_remove(); /* only one parallel port */ lpt2_remove(); - lpt1_init(0x278); + lpt1_setup(LPT2_ADDR); return ret; } diff --git a/src/network/net_plip.c b/src/network/net_plip.c index f80effeec..8c46213c6 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -26,12 +26,12 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/timer.h> #include <86box/lpt.h> #include <86box/timer.h> #include <86box/pit.h> #include <86box/device.h> #include <86box/thread.h> -#include <86box/timer.h> #include <86box/network.h> #include <86box/plat_unused.h> diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 1a9d5c0e8..1298018ee 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -26,8 +26,8 @@ #include #include #include <86box/86box.h> -#include <86box/lpt.h> #include <86box/timer.h> +#include <86box/lpt.h> #include <86box/pit.h> #include <86box/path.h> #include <86box/plat.h> diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index 76c7ba3f5..d3cd5017a 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -78,7 +78,7 @@ lpt1_handler(i82091aa_t *dev) } if ((dev->regs[0x20] & 0x01) && lpt_port) - lpt1_init(lpt_port); + lpt1_setup(lpt_port); lpt1_irq((dev->regs[0x20] & 0x08) ? LPT1_IRQ : LPT2_IRQ); } diff --git a/src/sio/sio_acc3221.c b/src/sio/sio_acc3221.c index d52949d46..203b1c1f1 100644 --- a/src/sio/sio_acc3221.c +++ b/src/sio/sio_acc3221.c @@ -305,7 +305,7 @@ acc3221_lpt_handle(acc3221_t *dev) lpt1_remove(); if (!(dev->regs[0xbe] & REG_BE_LPT1_DISABLE)) - lpt1_init(dev->regs[0xbf] << 2); + lpt1_setup(dev->regs[0xbf] << 2); } static void @@ -437,7 +437,7 @@ acc3221_reset(acc3221_t *dev) serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); lpt1_remove(); - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); lpt1_irq(LPT1_IRQ); fdc_reset(dev->fdc); diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c index 5380e065a..398d00839 100644 --- a/src/sio/sio_ali5123.c +++ b/src/sio/sio_ali5123.c @@ -93,7 +93,7 @@ ali5123_lpt_handler(ali5123_t *dev) if (global_enable && local_enable) { ld_port = make_port(dev, 3) & 0xFFFC; if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - lpt1_init(ld_port); + lpt1_setup(ld_port); } lpt1_irq(lpt_irq); } @@ -133,8 +133,10 @@ ali5123_serial_handler(ali5123_t *dev, int uart) } static void -ali5123_reset(ali5123_t *dev) +ali5123_reset(void *priv) { + ali5123_t *dev = (ali5123_t *) priv; + memset(dev->regs, 0, 48); dev->regs[0x20] = 0x43; @@ -490,7 +492,7 @@ const device_t ali5123_device = { .local = 0x40, .init = ali5123_init, .close = ali5123_close, - .reset = NULL, + .reset = ali5123_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index 8882f16e0..a7aa101c6 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -104,7 +104,7 @@ f82c710_update_ports(upc_t *dev, int set) if (dev->regs[0] & 8) { lpt_addr = dev->regs[6] * 4; - lpt1_init(lpt_addr); + lpt1_setup(lpt_addr); if ((lpt_addr == LPT1_ADDR) || (lpt_addr == LPT_MDA_ADDR)) lpt1_irq(LPT1_IRQ); else if (lpt_addr == LPT2_ADDR) @@ -215,7 +215,7 @@ f82c606_update_ports(upc_t *dev, int set) } if (dev->regs[0] & 8) { - lpt1_init(((uint16_t) dev->regs[6]) << 2); + lpt1_setup(((uint16_t) dev->regs[6]) << 2); lpt1_irq(lpt1_int); f82c710_log("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); } diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index 7f97e79b0..3be28c6ba 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -107,7 +107,7 @@ fdc37c669_lpt_handler(fdc37c669_t *dev) lpt_port_remove(dev->id); if ((dev->regs[0x01] & 0x04) && (dev->regs[0x23] >= 0x40)) - lpt_port_init(dev->id, ((uint16_t) (dev->regs[0x23] & mask)) << 2); + lpt_port_setup(dev->id, ((uint16_t) (dev->regs[0x23] & mask)) << 2); } static void diff --git a/src/sio/sio_fdc37c67x.c b/src/sio/sio_fdc37c67x.c index f0fb8cd64..931734048 100644 --- a/src/sio/sio_fdc37c67x.c +++ b/src/sio/sio_fdc37c67x.c @@ -134,7 +134,7 @@ fdc37c67x_lpt_handler(fdc37c67x_t *dev) if (global_enable && local_enable) { ld_port = make_port(dev, 3) & 0xFFFC; if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - lpt1_init(ld_port); + lpt1_setup(ld_port); } lpt1_irq(lpt_irq); } diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 530fff216..0f3460565 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -111,16 +111,16 @@ lpt1_handler(fdc37c6xx_t *dev) lpt1_remove(); switch (dev->regs[1] & 3) { case 1: - lpt1_init(LPT_MDA_ADDR); - lpt1_irq(7); + lpt1_setup(LPT_MDA_ADDR); + lpt1_irq(LPT_MDA_IRQ); break; case 2: - lpt1_init(LPT1_ADDR); - lpt1_irq(7 /*5*/); + lpt1_setup(LPT1_ADDR); + lpt1_irq(LPT1_IRQ /*LPT2_IRQ*/); break; case 3: - lpt1_init(LPT2_ADDR); - lpt1_irq(7 /*5*/); + lpt1_setup(LPT2_ADDR); + lpt1_irq(LPT1_IRQ /*LPT2_IRQ*/); break; default: @@ -252,7 +252,7 @@ fdc37c6xx_reset(fdc37c6xx_t *dev) serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); lpt1_remove(); - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); fdc_reset(dev->fdc); fdc_remove(dev->fdc); diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 42908ecaf..8d8f76cb6 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -35,24 +35,15 @@ #include <86box/machine.h> #include <86box/nvr.h> #include <86box/apm.h> +#include <86box/access_bus.h> #include <86box/acpi.h> #include <86box/sio.h> #include <86box/plat_unused.h> -#define AB_RST 0x80 - -typedef struct access_bus_t { - uint8_t control; - uint8_t status; - uint8_t own_addr; - uint8_t data; - uint8_t clock; - uint16_t base; -} access_bus_t; - typedef struct fdc37c93x_t { uint8_t chip_id; uint8_t is_apm; + uint8_t is_compaq; uint8_t has_nvr; uint8_t tries; uint8_t port_370; @@ -61,51 +52,56 @@ typedef struct fdc37c93x_t { uint8_t regs[48]; uint8_t ld_regs[11][256]; uint16_t superio_base; + uint16_t fdc_base; + uint16_t lpt_base; + uint16_t nvr_pri_base; + uint16_t nvr_sec_base; + uint16_t kbc_base; uint16_t gpio_base; /* Set to EA */ uint16_t auxio_base; - uint16_t nvr_sec_base; + uint16_t uart_base[2]; int locked; int cur_reg; fdc_t *fdc; - serial_t *uart[2]; access_bus_t *access_bus; nvr_t *nvr; acpi_t *acpi; void *kbc; + serial_t *uart[2]; } fdc37c93x_t; static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv); static uint8_t fdc37c93x_read(uint16_t port, void *priv); static uint16_t -make_port_superio(fdc37c93x_t *dev) +make_port_superio(const fdc37c93x_t *dev) { - uint16_t r0 = dev->regs[0x26]; - uint16_t r1 = dev->regs[0x27]; + const uint16_t r0 = dev->regs[0x26]; + const uint16_t r1 = dev->regs[0x27]; - uint16_t p = (r1 << 8) + r0; + const uint16_t p = (r1 << 8) + r0; return p; } static uint16_t -make_port(fdc37c93x_t *dev, uint8_t ld) +make_port(const fdc37c93x_t *dev, const uint8_t ld) { - uint16_t r0 = dev->ld_regs[ld][0x60]; - uint16_t r1 = dev->ld_regs[ld][0x61]; + const uint16_t r0 = dev->ld_regs[ld][0x60]; + const uint16_t r1 = dev->ld_regs[ld][0x61]; - uint16_t p = (r0 << 8) + r1; + const uint16_t p = (r0 << 8) + r1; return p; } static uint16_t -make_port_sec(fdc37c93x_t *dev, uint8_t ld) +make_port_sec(const fdc37c93x_t *dev, const uint8_t ld) { - uint16_t r0 = dev->ld_regs[ld][0x62]; - uint16_t r1 = dev->ld_regs[ld][0x63]; + const uint16_t r0 = dev->ld_regs[ld][0x62]; + const uint16_t r1 = dev->ld_regs[ld][0x63]; - uint16_t p = (r0 << 8) + r1; + const uint16_t p = (r0 << 8) + r1; return p; } @@ -150,66 +146,91 @@ fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv) static void fdc37c93x_superio_handler(fdc37c93x_t *dev) { - io_removehandler(dev->superio_base, 0x0002, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); - dev->superio_base = make_port_superio(dev); - io_sethandler(dev->superio_base, 0x0002, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + if (!dev->is_compaq) { + if (dev->superio_base != 0x0000) + io_removehandler(dev->superio_base, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + dev->superio_base = make_port_superio(dev); + if (dev->superio_base != 0x0000) + io_sethandler(dev->superio_base, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + } } static void fdc37c93x_fdc_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); - uint8_t local_enable = !!dev->ld_regs[0][0x30]; + const uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); + const uint8_t local_enable = !!dev->ld_regs[0][0x30]; + const uint16_t old_base = dev->fdc_base; - fdc_remove(dev->fdc); - if (global_enable && local_enable) { - ld_port = make_port(dev, 0) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - fdc_set_base(dev->fdc, ld_port); + dev->fdc_base = 0x0000; + + if (global_enable && local_enable) + dev->fdc_base = make_port(dev, 0) & 0xfff8; + + if (dev->fdc_base != old_base) { + if ((old_base >= 0x0100) && (old_base <= 0x0ff8)) + fdc_remove(dev->fdc); + + if ((dev->fdc_base >= 0x0100) && (dev->fdc_base <= 0x0ff8)) + fdc_set_base(dev->fdc, dev->fdc_base); } } static void fdc37c93x_lpt_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); - uint8_t local_enable = !!dev->ld_regs[3][0x30]; - uint8_t lpt_irq = dev->ld_regs[3][0x70]; + const uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); + const uint8_t local_enable = !!dev->ld_regs[3][0x30]; + uint8_t lpt_irq = dev->ld_regs[3][0x70]; + const uint16_t old_base = dev->lpt_base; if (lpt_irq > 15) lpt_irq = 0xff; - lpt1_remove(); - if (global_enable && local_enable) { - ld_port = make_port(dev, 3) & 0xFFFC; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - lpt1_init(ld_port); + dev->lpt_base = 0x0000; + + if (global_enable && local_enable) + dev->lpt_base = make_port(dev, 3) & 0xfffc; + + if (dev->lpt_base != old_base) { + if ((old_base >= 0x0100) && (old_base <= 0x0ffc)) + lpt1_remove(); + + if ((dev->lpt_base >= 0x0100) && (dev->lpt_base <= 0x0ffc)) + lpt1_setup(dev->lpt_base); } + lpt1_irq(lpt_irq); } static void -fdc37c93x_serial_handler(fdc37c93x_t *dev, int uart) +fdc37c93x_serial_handler(fdc37c93x_t *dev, const int uart) { - uint16_t ld_port = 0; - uint8_t uart_no = 4 + uart; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); - uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; + const uint8_t uart_no = 4 + uart; + const uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); + const uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; + const uint16_t old_base = dev->uart_base[uart]; - serial_remove(dev->uart[uart]); - if (global_enable && local_enable) { - ld_port = make_port(dev, uart_no) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); + dev->uart_base[uart] = 0x0000; + + if (global_enable && local_enable) + dev->uart_base[uart] = make_port(dev, uart_no) & 0xfff8; + + if (dev->uart_base[uart] != old_base) { + if ((old_base >= 0x0100) && (old_base <= 0x0ff8)) + serial_remove(dev->uart[uart]); + + if ((dev->uart_base[uart] >= 0x0100) && (dev->uart_base[uart] <= 0x0ff8)) + serial_setup(dev->uart[uart], dev->uart_base[uart], dev->ld_regs[uart_no][0x70]); } + + serial_irq(dev->uart[uart], dev->ld_regs[uart_no][0x70]); } static void -fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) +fdc37c93x_nvr_pri_handler(const fdc37c93x_t *dev) { uint8_t local_enable = !!dev->ld_regs[6][0x30]; @@ -224,18 +245,24 @@ fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) static void fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[6][0x30]; + uint8_t local_enable = !!dev->ld_regs[6][0x30]; + const uint16_t old_base = dev->nvr_sec_base; local_enable &= (((dev->ld_regs[6][0xf0] & 0xe0) == 0x80) || ((dev->ld_regs[6][0xf0] & 0xe0) == 0xe0)); - nvr_at_sec_handler(0, dev->nvr_sec_base, dev->nvr); - if (local_enable) { - dev->nvr_sec_base = ld_port = make_port_sec(dev, 6) & 0xFFFE; + dev->nvr_sec_base = 0x0000; + + if (local_enable) + dev->nvr_sec_base = make_port_sec(dev, 6) & 0xfffe; + + if (dev->nvr_sec_base != old_base) { + if ((old_base > 0x0000) && (old_base <= 0x0ffe)) + nvr_at_sec_handler(0, dev->nvr_sec_base, dev->nvr); + /* Datasheet erratum: First it says minimum address is 0x0100, but later implies that it's 0x0000 and that default is 0x0070, same as (unrelocatable) primary NVR. */ - if (ld_port <= 0x0FFE) + if ((dev->nvr_sec_base > 0x0000) && (dev->nvr_sec_base <= 0x0ffe)) nvr_at_sec_handler(1, dev->nvr_sec_base, dev->nvr); } } @@ -243,22 +270,32 @@ fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) static void fdc37c93x_kbc_handler(fdc37c93x_t *dev) { - uint8_t local_enable = !!dev->ld_regs[7][0x30]; + const uint8_t local_enable = !!dev->ld_regs[7][0x30]; + const uint16_t old_base = dev->kbc_base; - kbc_at_handler(local_enable, dev->kbc); + dev->kbc_base = local_enable ? 0x0060 : 0x0000; + + if (dev->kbc_base != old_base) + kbc_at_handler(local_enable, dev->kbc); } static void fdc37c93x_auxio_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[8][0x30]; + const uint8_t local_enable = !!dev->ld_regs[8][0x30]; + const uint16_t old_base = dev->auxio_base; - io_removehandler(dev->auxio_base, 0x0001, - fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); - if (local_enable) { - dev->auxio_base = ld_port = make_port(dev, 8); - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) + if (local_enable) + dev->auxio_base = make_port(dev, 8); + else + dev->auxio_base = 0x0000; + + if (dev->auxio_base != old_base) { + if ((old_base >= 0x0100) && (old_base <= 0x0fff)) + io_removehandler(old_base, 0x0001, + fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); + + if ((dev->auxio_base >= 0x0100) && (dev->auxio_base <= 0x0fff)) io_sethandler(dev->auxio_base, 0x0001, fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); } @@ -267,113 +304,55 @@ fdc37c93x_auxio_handler(fdc37c93x_t *dev) static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable; + const uint8_t local_enable = !dev->locked && !!(dev->regs[0x03] & 0x80); + const uint16_t old_base = dev->gpio_base; - local_enable = !!(dev->regs[0x03] & 0x80); + dev->gpio_base = 0x0000; - io_removehandler(dev->gpio_base, 0x0002, - fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); - if (local_enable) { - switch (dev->regs[0x03] & 0x03) { - case 0: - ld_port = 0xe0; - break; - case 1: - ld_port = 0xe2; - break; - case 2: - ld_port = 0xe4; - break; - case 3: - ld_port = 0xea; /* Default */ - break; + if (local_enable) switch (dev->regs[0x03] & 0x03) { + default: + break; + case 0: + dev->gpio_base = 0x00e0; + break; + case 1: + dev->gpio_base = 0x00e2; + break; + case 2: + dev->gpio_base = 0x00e4; + break; + case 3: + dev->gpio_base = 0x00ea; /* Default */ + break; + } - default: - break; - } - dev->gpio_base = ld_port; - if (ld_port > 0x0000) + if (dev->gpio_base != old_base) { + if (old_base != 0x0000) + io_removehandler(old_base, 0x0002, + fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); + + if (dev->gpio_base > 0x0000) io_sethandler(dev->gpio_base, 0x0002, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); } } -static uint8_t -fdc37c93x_access_bus_read(uint16_t port, void *priv) -{ - const access_bus_t *dev = (access_bus_t *) priv; - uint8_t ret = 0xff; - - switch (port & 3) { - case 0: - ret = (dev->status & 0xBF); - break; - case 1: - ret = (dev->own_addr & 0x7F); - break; - case 2: - ret = dev->data; - break; - case 3: - ret = (dev->clock & 0x87); - break; - - default: - break; - } - - return ret; -} - -static void -fdc37c93x_access_bus_write(uint16_t port, uint8_t val, void *priv) -{ - access_bus_t *dev = (access_bus_t *) priv; - - switch (port & 3) { - case 0: - dev->control = (val & 0xCF); - break; - case 1: - dev->own_addr = (val & 0x7F); - break; - case 2: - dev->data = val; - break; - case 3: - dev->clock &= 0x80; - dev->clock |= (val & 0x07); - break; - - default: - break; - } -} - static void fdc37c93x_access_bus_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 6)); - uint8_t local_enable = !!dev->ld_regs[9][0x30]; + const uint8_t global_enable = !!(dev->regs[0x22] & (1 << 6)); + const uint8_t local_enable = !!dev->ld_regs[9][0x30]; + const uint16_t ld_port = dev->access_bus->base = make_port(dev, 9); - io_removehandler(dev->access_bus->base, 0x0004, - fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); - if (global_enable && local_enable) { - dev->access_bus->base = ld_port = make_port(dev, 9); - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - io_sethandler(dev->access_bus->base, 0x0004, - fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); - } + access_bus_handler(dev->access_bus, global_enable && local_enable, ld_port); } static void fdc37c93x_acpi_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[0x0a][0x30]; - uint8_t sci_irq = dev->ld_regs[0x0a][0x70]; + uint16_t ld_port; + const uint8_t local_enable = !!dev->ld_regs[0x0a][0x30]; + const uint8_t sci_irq = dev->ld_regs[0x0a][0x70]; acpi_update_io_mapping(dev->acpi, 0x0000, local_enable); if (local_enable) { @@ -392,41 +371,49 @@ fdc37c93x_acpi_handler(fdc37c93x_t *dev) acpi_set_irq_line(dev->acpi, sci_irq); } +static void +fdc37c93x_state_change(fdc37c93x_t *dev, const uint8_t locked) +{ + dev->locked = locked; + fdc_3f1_enable(dev->fdc, !locked); + fdc37c93x_gpio_handler(dev); +} + static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv) { fdc37c93x_t *dev = (fdc37c93x_t *) priv; uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0x00; - uint8_t keep = 0x00; + uint8_t valxor; /* Compaq Presario 4500: Unlock at FB, Register at EA, Data at EB, Lock at F9. */ - if ((port == 0xea) || (port == 0xf9) || (port == 0xfb)) + if (port == 0xea) index = 1; else if (port == 0xeb) index = 0; - if (index) { - if ((val == 0x55) && !dev->locked) { + if (port == 0xfb) { + fdc37c93x_state_change(dev, 1); + dev->tries = 0; + return; + } else if (port == 0xf9) { + fdc37c93x_state_change(dev, 0); + return; + } else if (index) { + if ((!dev->is_compaq) && (val == 0x55) && !dev->locked) { if (dev->tries) { - dev->locked = 1; - fdc_3f1_enable(dev->fdc, 0); + fdc37c93x_state_change(dev, 1); dev->tries = 0; } else dev->tries++; - } else { - if (dev->locked) { - if (val == 0xaa) { - dev->locked = 0; - fdc_3f1_enable(dev->fdc, 1); - return; - } - dev->cur_reg = val; - } else { - if (dev->tries) - dev->tries = 0; + } else if (dev->locked) { + if ((!dev->is_compaq) && (val == 0xaa)) { + fdc37c93x_state_change(dev, 0); + return; } - } + dev->cur_reg = val; + } else if ((!dev->is_compaq) && dev->tries) + dev->tries = 0; return; } else { if (dev->locked) { @@ -436,6 +423,8 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) return; dev->regs[dev->cur_reg] = val; } else { + uint8_t keep = 0x00; + valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) return; @@ -479,9 +468,11 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if (dev->cur_reg < 48) { switch (dev->cur_reg) { + case 0x02: + if (val == 0x02) + fdc37c93x_state_change(dev, 0); + break; case 0x03: - if (valxor & 0x83) - fdc37c93x_gpio_handler(dev); dev->regs[0x03] &= 0x83; break; case 0x22: @@ -788,91 +779,95 @@ fdc37c93x_read(uint16_t port, void *priv) static void fdc37c93x_reset(fdc37c93x_t *dev) { - memset(dev->regs, 0, 48); + memset(dev->regs, 0x00, sizeof(dev->regs)); dev->regs[0x03] = 0x03; dev->regs[0x20] = dev->chip_id; dev->regs[0x21] = 0x01; dev->regs[0x22] = 0x39; dev->regs[0x24] = 0x04; - if (dev->chip_id != 0x02) { - dev->regs[0x26] = dev->port_370 ? 0x70 : 0xF0; - dev->regs[0x27] = 0x03; - } + dev->regs[0x26] = dev->port_370 ? 0x70 : 0xf0; + dev->regs[0x27] = 0x03; - for (uint8_t i = 0; i < 11; i++) - memset(dev->ld_regs[i], 0, 256); + memset(dev->ld_regs, 0x00, sizeof(dev->ld_regs)); /* Logical device 0: FDD */ - dev->ld_regs[0][0x30] = 0; - dev->ld_regs[0][0x60] = 3; - dev->ld_regs[0][0x61] = 0xF0; - dev->ld_regs[0][0x70] = 6; - dev->ld_regs[0][0x74] = 2; - dev->ld_regs[0][0xF0] = 0xE; - dev->ld_regs[0][0xF2] = 0xFF; + dev->ld_regs[0x00][0x30] = 0x00; + dev->ld_regs[0x00][0x60] = 0x03; + dev->ld_regs[0x00][0x61] = 0xf0; + dev->ld_regs[0x00][0x70] = 0x06; + dev->ld_regs[0x00][0x74] = 0x02; + dev->ld_regs[0x00][0xf0] = 0x0e; + dev->ld_regs[0x00][0xf2] = 0xff; /* Logical device 1: IDE1 */ - dev->ld_regs[1][0x30] = 0; - dev->ld_regs[1][0x60] = 1; - dev->ld_regs[1][0x61] = 0xF0; - dev->ld_regs[1][0x62] = 3; - dev->ld_regs[1][0x63] = 0xF6; - dev->ld_regs[1][0x70] = 0xE; - dev->ld_regs[1][0xF0] = 0xC; + dev->ld_regs[0x01][0x30] = 0x00; + dev->ld_regs[0x01][0x60] = 0x01; + dev->ld_regs[0x01][0x61] = 0xf0; + dev->ld_regs[0x01][0x62] = 0x03; + dev->ld_regs[0x01][0x63] = 0xf6; + dev->ld_regs[0x01][0x70] = 0x0e; + dev->ld_regs[0x01][0xf0] = 0x0c; /* Logical device 2: IDE2 */ - dev->ld_regs[2][0x30] = 0; - dev->ld_regs[2][0x60] = 1; - dev->ld_regs[2][0x61] = 0x70; - dev->ld_regs[2][0x62] = 3; - dev->ld_regs[2][0x63] = 0x76; - dev->ld_regs[2][0x70] = 0xF; + dev->ld_regs[0x02][0x30] = 0x00; + dev->ld_regs[0x02][0x60] = 0x01; + dev->ld_regs[0x02][0x61] = 0x70; + dev->ld_regs[0x02][0x62] = 0x03; + dev->ld_regs[0x02][0x63] = 0x76; + dev->ld_regs[0x02][0x70] = 0x0f; /* Logical device 3: Parallel Port */ - dev->ld_regs[3][0x30] = 0; - dev->ld_regs[3][0x60] = 3; - dev->ld_regs[3][0x61] = 0x78; - dev->ld_regs[3][0x70] = 7; - dev->ld_regs[3][0x74] = 4; - dev->ld_regs[3][0xF0] = 0x3C; + dev->ld_regs[0x03][0x30] = 0x00; + dev->ld_regs[0x03][0x60] = 0x03; + dev->ld_regs[0x03][0x61] = 0x78; + dev->ld_regs[0x03][0x70] = 0x07; + dev->ld_regs[0x03][0x74] = 0x04; + dev->ld_regs[0x03][0xf0] = 0x3c; /* Logical device 4: Serial Port 1 */ - dev->ld_regs[4][0x30] = 0; - dev->ld_regs[4][0x60] = 3; - dev->ld_regs[4][0x61] = 0xf8; - dev->ld_regs[4][0x70] = 4; - dev->ld_regs[4][0xF0] = 3; - serial_setup(dev->uart[0], COM1_ADDR, dev->ld_regs[4][0x70]); + dev->ld_regs[0x04][0x30] = 0x00; + dev->ld_regs[0x04][0x60] = 0x03; + dev->ld_regs[0x04][0x61] = 0xf8; + dev->ld_regs[0x04][0x70] = 0x04; + dev->ld_regs[0x04][0xf0] = 0x03; + serial_irq(dev->uart[0], dev->ld_regs[4][0x70]); /* Logical device 5: Serial Port 2 */ - dev->ld_regs[5][0x30] = 0; - dev->ld_regs[5][0x60] = 2; - dev->ld_regs[5][0x61] = 0xf8; - dev->ld_regs[5][0x70] = 3; - dev->ld_regs[5][0x74] = 4; - dev->ld_regs[5][0xF1] = 2; - dev->ld_regs[5][0xF2] = 3; - serial_setup(dev->uart[1], COM2_ADDR, dev->ld_regs[5][0x70]); + dev->ld_regs[0x05][0x30] = 0x00; + dev->ld_regs[0x05][0x60] = 0x02; + dev->ld_regs[0x05][0x61] = 0xf8; + dev->ld_regs[0x05][0x70] = 0x03; + dev->ld_regs[0x05][0x74] = 0x04; + dev->ld_regs[0x05][0xf1] = 0x02; + dev->ld_regs[0x05][0xf2] = 0x03; + serial_irq(dev->uart[1], dev->ld_regs[5][0x70]); /* Logical device 6: RTC */ - dev->ld_regs[6][0x30] = 0; - dev->ld_regs[6][0x60] = 0x70; - if (dev->chip_id != 0x02) - dev->ld_regs[6][0x63] = (dev->has_nvr) ? 0x70 : 0x00; - dev->ld_regs[6][0xF0] = 0; - dev->ld_regs[6][0xF4] = 3; + dev->ld_regs[0x06][0x30] = 0x00; + dev->ld_regs[0x06][0x63] = (dev->has_nvr) ? 0x70 : 0x00; + dev->ld_regs[0x06][0xf0] = 0x00; + dev->ld_regs[0x06][0xf4] = 0x03; /* Logical device 7: Keyboard */ - dev->ld_regs[7][0x30] = 0; - dev->ld_regs[7][0x61] = 0x60; - dev->ld_regs[7][0x70] = 1; + dev->ld_regs[0x07][0x30] = 0x00; + dev->ld_regs[0x07][0x61] = 0x60; + dev->ld_regs[0x07][0x70] = 0x01; /* Logical device 8: Auxiliary I/O */ + dev->ld_regs[0x08][0x30] = 0x00; + dev->ld_regs[0x08][0x60] = 0x00; + dev->ld_regs[0x08][0x61] = 0x00; /* Logical device 9: ACCESS.bus */ + dev->ld_regs[0x09][0x30] = 0x00; + dev->ld_regs[0x09][0x60] = 0x00; + dev->ld_regs[0x09][0x61] = 0x00; /* Logical device A: ACPI */ + dev->ld_regs[0x0a][0x30] = 0x00; + dev->ld_regs[0x0a][0x60] = 0x00; + dev->ld_regs[0x0a][0x61] = 0x00; fdc37c93x_gpio_handler(dev); fdc37c93x_lpt_handler(dev); @@ -907,36 +902,6 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->locked = 0; } -static void -access_bus_close(void *priv) -{ - access_bus_t *dev = (access_bus_t *) priv; - - free(dev); -} - -static void * -access_bus_init(UNUSED(const device_t *info)) -{ - access_bus_t *dev = (access_bus_t *) calloc(1, sizeof(access_bus_t)); - - return dev; -} - -static const device_t access_bus_device = { - .name = "SMC FDC37C932FR ACCESS.bus", - .internal_name = "access_bus", - .flags = 0, - .local = 0x03, - .init = access_bus_init, - .close = access_bus_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static void fdc37c93x_close(void *priv) { @@ -948,19 +913,18 @@ fdc37c93x_close(void *priv) static void * fdc37c93x_init(const device_t *info) { - int is_compaq; fdc37c93x_t *dev = (fdc37c93x_t *) calloc(1, sizeof(fdc37c93x_t)); dev->fdc = device_add(&fdc_at_smc_device); - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); - dev->chip_id = info->local & 0xff; - dev->is_apm = (info->local >> 8) & 0x01; - is_compaq = (info->local >> 8) & 0x02; - dev->has_nvr = !((info->local >> 8) & 0x04); - dev->port_370 = ((info->local >> 8) & 0x08); + dev->chip_id = info->local & 0xff; + dev->is_apm = (info->local >> 8) & 0x01; + dev->is_compaq = (info->local >> 8) & 0x02; + dev->has_nvr = !((info->local >> 8) & 0x04); + dev->port_370 = ((info->local >> 8) & 0x08); dev->gpio_regs[0] = 0xff; #if 0 @@ -981,7 +945,7 @@ fdc37c93x_init(const device_t *info) if (dev->is_apm) dev->acpi = device_add(&acpi_smc_device); - if (is_compaq) { + if (dev->is_compaq) { io_sethandler(0x0ea, 0x0002, fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); io_sethandler(0x0f9, 0x0001, @@ -992,6 +956,16 @@ fdc37c93x_init(const device_t *info) dev->kbc = device_add(&keyboard_ps2_ami_pci_device); + /* Set the defaults here so the ports can be removed by fdc37c93x_reset(). */ + dev->fdc_base = 0x03f0; + dev->lpt_base = 0x0378; + dev->uart_base[0] = 0x03f8; + dev->uart_base[1] = 0x02f8; + dev->nvr_pri_base = 0x0070; + dev->nvr_sec_base = 0x0070; + dev->kbc_base = 0x0060; + dev->gpio_base = 0x00ea; + fdc37c93x_reset(dev); if (dev->chip_id == 0x02) { @@ -1115,4 +1089,3 @@ const device_t fdc37c935_no_nvr_device = { .force_redraw = NULL, .config = NULL }; - diff --git a/src/sio/sio_fdc37m60x.c b/src/sio/sio_fdc37m60x.c index 671b3581b..11d2f3349 100644 --- a/src/sio/sio_fdc37m60x.c +++ b/src/sio/sio_fdc37m60x.c @@ -216,7 +216,7 @@ fdc37m60x_lpt_handler(fdc37m60x_t *dev) lpt1_remove(); if (ENABLED(3) || (POWER_CONTROL & 0x08)) { - lpt1_init(BASE_ADDRESS(3)); + lpt1_setup(BASE_ADDRESS(3)); lpt1_irq(IRQ(3) & 0xf); fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf); } diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index 1cde8657e..b3553bf54 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -294,7 +294,7 @@ it8661f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { it86x1f_log("IT86x1F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); - lpt1_init(config->io[0].base); + lpt1_setup(config->io[0].base); } else { it86x1f_log("IT86x1F: LPT disabled\n"); } diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index 33cb0d865..41d69b0cc 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -154,7 +154,7 @@ lpt1_handler(pc87306_t *dev) lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5; if (lpt_port) - lpt1_init(lpt_port); + lpt1_setup(lpt_port); lpt1_irq(lpt_irq); } @@ -303,26 +303,26 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) } break; case 0x02: - if (valxor & 1) { + if (valxor & 0x01) { lpt1_remove(); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + serial_remove(dev->uart[0x00]); + serial_remove(dev->uart[0x01]); fdc_remove(dev->fdc); if (!(val & 1)) { - if (dev->regs[0] & 1) + if (dev->regs[0x00] & 0x01) lpt1_handler(dev); - if (dev->regs[0] & 2) + if (dev->regs[0x00] & 0x02) serial_handler(dev, 0); - if (dev->regs[0] & 4) + if (dev->regs[0x00] & 0x04) serial_handler(dev, 1); - if (dev->regs[0] & 8) - fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + if (dev->regs[0x00] & 0x08) + fdc_set_base(dev->fdc, (dev->regs[0x00] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } } - if (valxor & 8) { + if (valxor & 0x08) { lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } break; @@ -359,7 +359,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) lpt1_handler(dev); } break; - case 0x1B: + case 0x1b: if (valxor & 0x70) { lpt1_remove(); if (!(val & 0x40)) @@ -368,7 +368,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) lpt1_handler(dev); } break; - case 0x1C: + case 0x1c: if (valxor) { serial_remove(dev->uart[0]); serial_remove(dev->uart[1]); diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index eba0748c9..ae21d34af 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -200,7 +200,7 @@ lpt1_handler(pc87307_t *dev) irq = (dev->ld_regs[0x04][0x40] & 0x0f); if (active && (addr <= 0xfffc)) { - lpt1_init(addr); + lpt1_setup(addr); lpt1_irq(irq); } } diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index 1b790bc6b..da53802c1 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -137,7 +137,7 @@ lpt1_handler(pc87309_t *dev) irq = (dev->ld_regs[0x01][0x40] & 0x0f); if (active) { - lpt1_init(addr); + lpt1_setup(addr); lpt1_irq(irq); } } diff --git a/src/sio/sio_pc87310.c b/src/sio/sio_pc87310.c index 674db6364..5bd595f05 100644 --- a/src/sio/sio_pc87310.c +++ b/src/sio/sio_pc87310.c @@ -106,7 +106,7 @@ lpt1_handler(pc87310_t *dev) } if (lpt_port) - lpt1_init(lpt_port); + lpt1_setup(lpt_port); lpt1_irq(lpt_irq); } diff --git a/src/sio/sio_pc87311.c b/src/sio/sio_pc87311.c index 1f38e6aa8..b560ef425 100644 --- a/src/sio/sio_pc87311.c +++ b/src/sio/sio_pc87311.c @@ -220,7 +220,7 @@ pc87311_lpt_handler(pc87311_t *dev) default: break; } - lpt1_init(dev->base); + lpt1_setup(dev->base); lpt1_irq(dev->irq); pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq); } diff --git a/src/sio/sio_pc87332.c b/src/sio/sio_pc87332.c index f746306bd..d9fb0b211 100644 --- a/src/sio/sio_pc87332.c +++ b/src/sio/sio_pc87332.c @@ -77,7 +77,7 @@ lpt1_handler(pc87332_t *dev) } if (lpt_port) - lpt1_init(lpt_port); + lpt1_setup(lpt_port); lpt1_irq(lpt_irq); } diff --git a/src/sio/sio_prime3b.c b/src/sio/sio_prime3b.c index 2cadda2ab..1cc0be3aa 100644 --- a/src/sio/sio_prime3b.c +++ b/src/sio/sio_prime3b.c @@ -176,7 +176,7 @@ prime3b_lpt_handler(prime3b_t *dev) { uint16_t lpt_base = (ASR & 2) ? LPT_MDA_ADDR : (!(ASR & 1) ? LPT1_ADDR : LPT2_ADDR); lpt1_remove(); - lpt1_init(lpt_base); + lpt1_setup(lpt_base); lpt1_irq(LPT1_IRQ); prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base); } diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c index e646a3653..f70f9f372 100644 --- a/src/sio/sio_prime3c.c +++ b/src/sio/sio_prime3c.c @@ -241,7 +241,7 @@ prime3c_lpt_handler(prime3c_t *dev) lpt1_remove(); if (!(FUNCTION_SELECT & 0x03)) { - lpt1_init(LPT_BASE_ADDRESS << 2); + lpt1_setup(LPT_BASE_ADDRESS << 2); lpt1_irq(FDC_LPT_IRQ & 0xf); prime3c_log("Prime3C-LPT: BASE %04x IRQ %02x\n", LPT_BASE_ADDRESS << 2, FDC_LPT_IRQ & 0xf); } diff --git a/src/sio/sio_um8663f.c b/src/sio/sio_um8663f.c index 79cb37da4..54f12dda6 100644 --- a/src/sio/sio_um8663f.c +++ b/src/sio/sio_um8663f.c @@ -106,12 +106,12 @@ um8663f_lpt_handler(um8663f_t *dev) if (dev->regs[0] & 0x08) { switch ((dev->regs[1] >> 3) & 0x01) { case 0x01: - lpt1_init(LPT1_ADDR); - lpt1_irq(7); + lpt1_setup(LPT1_ADDR); + lpt1_irq(LPT1_IRQ); break; case 0x00: - lpt1_init(LPT2_ADDR); - lpt1_irq(5); + lpt1_setup(LPT2_ADDR); + lpt1_irq(LPT2_IRQ); break; default: @@ -231,7 +231,7 @@ um8663f_reset(void *priv) serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); lpt1_remove(); - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); fdc_reset(dev->fdc); fdc_remove(dev->fdc); diff --git a/src/sio/sio_um8669f.c b/src/sio/sio_um8669f.c index b3d5259a2..6da9ef6e9 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -207,7 +207,7 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); - lpt1_init(config->io[0].base); + lpt1_setup(config->io[0].base); } else { um8669f_log("UM8669F: LPT disabled\n"); } diff --git a/src/sio/sio_vt82c686.c b/src/sio/sio_vt82c686.c index fa0bf3c63..0e874210d 100644 --- a/src/sio/sio_vt82c686.c +++ b/src/sio/sio_vt82c686.c @@ -86,7 +86,7 @@ vt82c686_lpt_handler(vt82c686_t *dev) lpt1_remove(); if (((dev->regs[0x02] & 0x03) != 0x03) && !(dev->regs[0x0f] & 0x11) && (io_base >= 0x100) && (io_base <= io_mask)) - lpt1_init(io_base); + lpt1_setup(io_base); if (dev->lpt_irq) { lpt1_irq(dev->lpt_irq); diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index ea5169afc..f4971ddce 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -197,7 +197,7 @@ w83787f_lpt_handler(w83787f_t *dev) lpt1_remove(); if (enable) { - lpt1_init(addr); + lpt1_setup(addr); lpt1_irq(irq); } } @@ -378,7 +378,7 @@ w83787f_reset(w83787f_t *dev) uint16_t hefere = dev->reg_init & 0x0100; lpt1_remove(); - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); lpt1_irq(LPT1_IRQ); memset(dev->regs, 0, 0x2A); diff --git a/src/sio/sio_w83877f.c b/src/sio/sio_w83877f.c index 90a3dba1b..7c92d6e71 100644 --- a/src/sio/sio_w83877f.c +++ b/src/sio/sio_w83877f.c @@ -168,7 +168,7 @@ w83877f_lpt_handler(w83877f_t *dev) lpt1_remove(); if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0)) - lpt1_init(make_port(dev, 0x23)); + lpt1_setup(make_port(dev, 0x23)); lpt_irq = 0xff; diff --git a/src/sio/sio_w83977f.c b/src/sio/sio_w83977f.c index 1d743cc64..fd177bc19 100644 --- a/src/sio/sio_w83977f.c +++ b/src/sio/sio_w83977f.c @@ -112,14 +112,14 @@ w83977f_lpt_handler(w83977f_t *dev) lpt2_remove(); if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) - lpt2_init(io_base); + lpt2_setup(io_base); lpt2_irq(dev->dev_regs[1][0x40] & 0x0f); } else { lpt1_remove(); if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) - lpt1_init(io_base); + lpt1_setup(io_base); lpt1_irq(dev->dev_regs[1][0x40] & 0x0f); } diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index 812a649a8..0462818a0 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -7,10 +7,10 @@ #include "cpu.h" #include <86box/86box.h> #include <86box/filters.h> +#include <86box/timer.h> #include <86box/lpt.h> #include <86box/machine.h> #include <86box/sound.h> -#include <86box/timer.h> #include <86box/plat_unused.h> typedef struct lpt_dac_t { diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 06160ce4c..875230518 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -7,10 +7,10 @@ #include "cpu.h" #include <86box/86box.h> #include <86box/filters.h> +#include <86box/timer.h> #include <86box/lpt.h> #include <86box/machine.h> #include <86box/sound.h> -#include <86box/timer.h> #include <86box/plat_unused.h> typedef struct dss_t { diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 958375f4e..6c66175c1 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -14,7 +14,7 @@ * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ #include #include @@ -357,7 +357,7 @@ colorplus_standalone_init(UNUSED(const device_t *info)) mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus); io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus); - lpt3_init(0x3BC); + lpt3_setup(LPT_MDA_ADDR); return colorplus; } diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index d50e8ba37..00374d08f 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -14,7 +14,7 @@ * Miran Grca, * * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ #include #include @@ -585,7 +585,7 @@ hercules_init(UNUSED(const device_t *info)) video_inform(VIDEO_FLAG_TYPE_MDA, &timing_hercules); /* Force the LPT3 port to be enabled. */ - lpt3_init(0x3BC); + lpt3_setup(LPT_MDA_ADDR); return dev; } diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 99c614259..fb42c3022 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -14,7 +14,7 @@ * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ #include #include @@ -23,8 +23,8 @@ #include #include <86box/86box.h> #include <86box/io.h> -#include <86box/lpt.h> #include <86box/timer.h> +#include <86box/lpt.h> #include <86box/pit.h> #include <86box/mem.h> #include <86box/rom.h> @@ -670,7 +670,7 @@ herculesplus_init(UNUSED(const device_t *info)) video_inform(VIDEO_FLAG_TYPE_MDA, &timing_herculesplus); /* Force the LPT3 port to be enabled. */ - lpt3_init(0x3BC); + lpt3_setup(LPT_MDA_ADDR); return dev; } diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 0abb4a6c2..d9b48f43a 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -14,7 +14,7 @@ * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ #include #include @@ -1018,7 +1018,7 @@ incolor_init(UNUSED(const device_t *info)) video_inform(VIDEO_FLAG_TYPE_MDA, &timing_incolor); /* Force the LPT3 port to be enabled. */ - lpt3_init(0x3BC); + lpt3_setup(LPT_MDA_ADDR); return dev; } diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 975b9ead1..66a0fbb71 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -14,7 +14,7 @@ * Miran Grca, * * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2025 Miran Grca. */ #include #include @@ -322,7 +322,7 @@ mda_standalone_init(UNUSED(const device_t *info)) mda_init(mda); - lpt3_init(0x3BC); + lpt3_setup(LPT_MDA_ADDR); return mda; } From dd24d0329c91fc7415829bb6b642932e5057f6b5 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Feb 2025 21:48:57 -0500 Subject: [PATCH 0218/1190] FIFO tagged functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča --- src/fifo.c | 137 ++++++++++++++++++++++++++++++++++++++- src/include/86box/fifo.h | 13 ++-- 2 files changed, 145 insertions(+), 5 deletions(-) diff --git a/src/fifo.c b/src/fifo.c index f51809fd8..8afb5640f 100644 --- a/src/fifo.c +++ b/src/fifo.c @@ -10,7 +10,7 @@ * * Authors: Miran Grca, * - * Copyright 2023 Miran Grca. + * Copyright 2023-2025 Miran Grca. */ #include #include @@ -84,6 +84,31 @@ fifo_write(uint8_t val, void *priv) } } +void +fifo_write_tagged(uint8_t tag, uint8_t val, void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_full = fifo->d_empty = 0; + fifo->d_ready = fifo->d_overrun = 0; + + if (fifo->full) + fifo->overrun = 1; + else { + fifo->buf[fifo->end] = val; + fifo->tag[fifo->end] = tag; + fifo->end = (fifo->end + 1) % fifo->len; + + if (fifo->end == fifo->start) + fifo->full = 1; + + fifo->empty = 0; + + if (fifo_get_count(fifo) >= fifo->trigger_len) + fifo->ready = 1; + } +} + void fifo_write_evt(uint8_t val, void *priv) { @@ -122,6 +147,45 @@ fifo_write_evt(uint8_t val, void *priv) } } +void +fifo_write_evt_tagged(uint8_t tag, uint8_t val, void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_full = fifo->d_empty = 0; + fifo->d_ready = fifo->d_overrun = 0; + + if (fifo->full) { + fifo->d_overrun = (fifo->overrun != 1); + fifo->overrun = 1; + if (fifo->d_overrun && (fifo->d_overrun_evt != NULL)) + fifo->d_overrun_evt(fifo->priv); + } else { + fifo->buf[fifo->end] = val; + fifo->tag[fifo->end] = tag; + fifo->end = (fifo->end + 1) % fifo->len; + + if (fifo->end == fifo->start) { + fifo->d_full = (fifo->full != 1); + fifo->full = 1; + if (fifo->d_full && (fifo->d_full_evt != NULL)) + fifo->d_full_evt(fifo->priv); + } + + fifo->d_empty = (fifo->empty != 0); + fifo->empty = 0; + if (fifo->d_empty && (fifo->d_empty_evt != NULL)) + fifo->d_empty_evt(fifo->priv); + + if (fifo_get_count(fifo) >= fifo->trigger_len) { + fifo->d_ready = (fifo->ready != 1); + fifo->ready = 1; + if (fifo->d_ready && (fifo->d_ready_evt != NULL)) + fifo->d_ready_evt(fifo->priv); + } + } +} + uint8_t fifo_read(void *priv) { @@ -148,6 +212,35 @@ fifo_read(void *priv) return ret; } +uint8_t +fifo_read_tagged(uint8_t *tag, void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + uint8_t ret = 0x00; + int count; + + if (!fifo->empty) { + ret = fifo->buf[fifo->start]; + *tag = fifo->tag[fifo->start]; + + fifo->start = (fifo->start + 1) % fifo->len; + + fifo->full = 0; + + count = fifo_get_count(fifo); + + if (count < fifo->trigger_len) { + fifo->ready = 0; + + if (count == 0) + fifo->empty = 1; + } + } else + *tag = 0x00; + + return ret; +} + uint8_t fifo_read_evt(void *priv) { @@ -187,6 +280,48 @@ fifo_read_evt(void *priv) return ret; } +uint8_t +fifo_read_evt_tagged(uint8_t *tag, void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + uint8_t ret = 0x00; + int count; + + fifo->d_full = fifo->d_empty = 0; + fifo->d_ready = 0; + + if (!fifo->empty) { + ret = fifo->buf[fifo->start]; + *tag = fifo->tag[fifo->start]; + + fifo->start = (fifo->start + 1) % fifo->len; + + fifo->d_full = (fifo->full != 0); + fifo->full = 0; + if (fifo->d_full && (fifo->d_full_evt != NULL)) + fifo->d_full_evt(fifo->priv); + + count = fifo_get_count(fifo); + + if (count < fifo->trigger_len) { + fifo->d_ready = (fifo->ready != 0); + fifo->ready = 0; + if (fifo->d_ready && (fifo->d_ready_evt != NULL)) + fifo->d_ready_evt(fifo->priv); + + if (count == 0) { + fifo->d_empty = (fifo->empty != 1); + fifo->empty = 1; + if (fifo->d_empty && (fifo->d_empty_evt != NULL)) + fifo->d_empty_evt(fifo->priv); + } + } + } else + *tag = 0x00; + + return ret; +} + void fifo_clear_overrun(void *priv) { diff --git a/src/include/86box/fifo.h b/src/include/86box/fifo.h index f87f932e0..f8f07d9b5 100644 --- a/src/include/86box/fifo.h +++ b/src/include/86box/fifo.h @@ -1,6 +1,3 @@ -#ifndef FIFO_H -#define FIFO_H - /* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM @@ -13,8 +10,11 @@ * * Authors: Miran Grca, * - * Copyright 2023 Miran Grca. + * Copyright 2023-2025 Miran Grca. */ +#ifndef FIFO_H +#define FIFO_H + #define FIFO(size) \ typedef struct { \ int start; \ @@ -37,6 +37,7 @@ void (*d_full_evt)(void *); \ void (*d_ready_evt)(void *); \ \ + uint8_t tag[64]; \ uint8_t buf[size]; \ } fifo## size ##_t; @@ -50,9 +51,13 @@ FIFO(64) extern int fifo_get_count(void *priv); extern void fifo_write(uint8_t val, void *priv); +extern void fifo_write_tagged(uint8_t tag, uint8_t val, void *priv); extern void fifo_write_evt(uint8_t val, void *priv); +extern void fifo_write_evt_tagged(uint8_t tag, uint8_t val, void *priv); extern uint8_t fifo_read(void *priv); +extern uint8_t fifo_read_tagged(uint8_t *tag, void *priv); extern uint8_t fifo_read_evt(void *priv); +extern uint8_t fifo_read_evt_tagged(uint8_t *tag, void *priv); extern void fifo_clear_overrun(void *priv); extern int fifo_get_full(void *priv); extern int fifo_get_d_full(void *priv); From 370481ceed0920bc7993a1334c1e51068ee283a0 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Feb 2025 22:29:56 -0500 Subject: [PATCH 0219/1190] Serial IRQ function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča --- src/device/serial.c | 16 +++++++++++++++- src/include/86box/serial.h | 3 ++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/device/serial.c b/src/device/serial.c index 0ba60551c..823d07c1f 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -15,7 +15,7 @@ * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2025 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. */ #include @@ -782,6 +782,20 @@ serial_setup(serial_t *dev, uint16_t addr, uint8_t irq) dev->irq = irq; } +void +serial_irq(serial_t *dev, const uint8_t irq) +{ + if (dev == NULL) + return; + + if (com_ports[dev->inst].enabled) + dev->irq = irq; + else + dev->irq = 0xff; + + serial_log("Port %i IRQ = %02X\n", dev->inst, irq); +} + static void serial_rcvr_d_empty_evt(void *priv) { diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index a205c7cec..31c77ce5a 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -16,7 +16,7 @@ * Fred N. van Kempen, * * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2025 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. */ @@ -137,6 +137,7 @@ extern serial_t *serial_attach_ex_2(int port, extern void serial_remove(serial_t *dev); extern void serial_set_type(serial_t *dev, int type); extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq); +extern void serial_irq(serial_t *dev, uint8_t irq); extern void serial_clear_fifo(serial_t *dev); extern void serial_write_fifo(serial_t *dev, uint8_t dat); extern void serial_set_next_inst(int ni); From e592ab5505766311cb4165df45dbd60ba238f002 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Feb 2025 22:32:50 -0500 Subject: [PATCH 0220/1190] ACCESS.bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča --- src/device/CMakeLists.txt | 1 + src/device/access_bus.c | 122 +++++++++++++++++++++++++++++++++ src/include/86box/access_bus.h | 37 ++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/device/access_bus.c create mode 100644 src/include/86box/access_bus.h diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 678c700a5..bbbab22fd 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -17,6 +17,7 @@ # add_library(dev OBJECT + access_bus.c bugger.c cartridge.c cassette.c diff --git a/src/device/access_bus.c b/src/device/access_bus.c new file mode 100644 index 000000000..951454e19 --- /dev/null +++ b/src/device/access_bus.c @@ -0,0 +1,122 @@ +/* + * 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. + * + * Implementation of the ACCESS.bus. + * + * Authors: Miran Grca, + * + * Copyright 2024-2025 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/access_bus.h> +#include <86box/plat_unused.h> + +static uint8_t +access_bus_in(uint16_t port, void *priv) +{ + const access_bus_t *dev = (access_bus_t *) priv; + uint8_t ret = 0xff; + + switch (port & 3) { + case 0: + ret = (dev->status & 0xbf); + break; + case 1: + ret = (dev->own_addr & 0x7f); + break; + case 2: + ret = dev->data; + break; + case 3: + ret = (dev->clock & 0x87); + break; + + default: + break; + } + + return ret; +} + +static void +access_bus_out(uint16_t port, uint8_t val, void *priv) +{ + access_bus_t *dev = (access_bus_t *) priv; + + switch (port & 3) { + case 0: + dev->control = (val & 0xcf); + break; + case 1: + dev->own_addr = (val & 0x7f); + break; + case 2: + dev->data = val; + break; + case 3: + dev->clock &= 0x80; + dev->clock |= (val & 0x07); + break; + + default: + break; + } +} + +void +access_bus_handler(access_bus_t *dev, uint8_t enable, uint16_t base) +{ + if (dev->enable && (dev->base >= 0x0100) && (dev->base <= 0x0ffc)) + io_removehandler(dev->base, 0x0004, + access_bus_in, NULL, NULL, access_bus_out, NULL, NULL, dev); + + dev->enable = enable; + dev->base = base; + + if (dev->enable && (dev->base >= 0x0100) && (dev->base <= 0x0ffc)) + io_sethandler(dev->base, 0x0004, + access_bus_in, NULL, NULL, access_bus_out, NULL, NULL, dev); +} + + +static void +access_bus_close(void *priv) +{ + access_bus_t *dev = (access_bus_t *) priv; + + free(dev); +} + +static void * +access_bus_init(UNUSED(const device_t *info)) +{ + access_bus_t *dev = (access_bus_t *) calloc(1, sizeof(access_bus_t)); + + return dev; +} + +const device_t access_bus_device = { + .name = "ACCESS.bus", + .internal_name = "access_bus", + .flags = 0, + .local = 0, + .init = access_bus_init, + .close = access_bus_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/access_bus.h b/src/include/86box/access_bus.h new file mode 100644 index 000000000..333a1d4a5 --- /dev/null +++ b/src/include/86box/access_bus.h @@ -0,0 +1,37 @@ +/* + * 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 ACPI emulation. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020-2025 Miran Grca. + */ +#ifndef ACCESS_BUS_H +#define ACCESS_BUS_H + +#define AB_RST 0x80 + +typedef struct access_bus_t { + uint8_t control; + uint8_t status; + uint8_t own_addr; + uint8_t data; + uint8_t clock; + uint8_t enable; + uint16_t base; +} access_bus_t; + +extern const device_t access_bus_device; + +/* Functions */ +extern void access_bus_handler(access_bus_t *dev, uint8_t enable, uint16_t base); + +#endif /*ACCESS_BUS_H*/ From a4fd6a0895acf6938eb9f1e9067544193d94cab5 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Feb 2025 23:47:24 -0500 Subject: [PATCH 0221/1190] Seperate Socket 3 and Socket 3 PCI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča --- src/include/86box/machine.h | 65 ++++++++++++++++--------------- src/machine/machine_table.c | 77 +++++++++++++++++++------------------ 2 files changed, 74 insertions(+), 68 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f4f3f8834..f39187dd9 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -173,20 +173,21 @@ enum { MACHINE_TYPE_486 = 8, MACHINE_TYPE_486_S2 = 9, MACHINE_TYPE_486_S3 = 10, - MACHINE_TYPE_486_MISC = 11, - MACHINE_TYPE_SOCKET4 = 12, - MACHINE_TYPE_SOCKET5 = 13, - MACHINE_TYPE_SOCKET7_3V = 14, - MACHINE_TYPE_SOCKET7 = 15, - MACHINE_TYPE_SOCKETS7 = 16, - MACHINE_TYPE_SOCKET8 = 17, - MACHINE_TYPE_SLOT1 = 18, - MACHINE_TYPE_SLOT1_2 = 19, - MACHINE_TYPE_SLOT1_370 = 20, - MACHINE_TYPE_SLOT2 = 21, - MACHINE_TYPE_SOCKET370 = 22, - MACHINE_TYPE_MISC = 23, - MACHINE_TYPE_MAX = 24 + MACHINE_TYPE_486_S3_PCI = 11, + MACHINE_TYPE_486_MISC = 12, + MACHINE_TYPE_SOCKET4 = 13, + MACHINE_TYPE_SOCKET5 = 14, + MACHINE_TYPE_SOCKET7_3V = 15, + MACHINE_TYPE_SOCKET7 = 16, + MACHINE_TYPE_SOCKETS7 = 17, + MACHINE_TYPE_SOCKET8 = 18, + MACHINE_TYPE_SLOT1 = 19, + MACHINE_TYPE_SLOT1_2 = 20, + MACHINE_TYPE_SLOT1_370 = 21, + MACHINE_TYPE_SLOT2 = 22, + MACHINE_TYPE_SOCKET370 = 23, + MACHINE_TYPE_MISC = 24, + MACHINE_TYPE_MAX = 25 }; enum { @@ -320,27 +321,29 @@ typedef struct _machine_ { int ram_granularity; int nvrmask; #ifdef EMU_DEVICE_H - const device_t *kbc_device; + const device_t *kbc_device; #else - void *kbc_device; + void *kbc_device; #endif /* EMU_DEVICE_H */ - uint8_t kbc_p1; - uint32_t gpio; - uint32_t gpio_acpi; + uintptr_t kbc_params; + /* Bits 23-16: XOR mask, bits 15-8: OR mask, bits 7-0: AND mask. */ + uint32_t kbc_p1; + uint32_t gpio; + uint32_t gpio_acpi; #ifdef EMU_DEVICE_H - const device_t *device; - const device_t *fdc_device; - const device_t *sio_device; - const device_t *vid_device; - const device_t *snd_device; - const device_t *net_device; + const device_t *device; + const device_t *fdc_device; + const device_t *sio_device; + const device_t *vid_device; + const device_t *snd_device; + const device_t *net_device; #else - void *device; - void *fdc_device; - void *sio_device; - void *vid_device; - void *snd_device; - void *net_device; + void *device; + void *fdc_device; + void *sio_device; + void *vid_device; + void *snd_device; + void *net_device; #endif } machine_t; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index febdc0e0c..f5cc30782 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -31,12 +31,14 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/machine.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> #include <86box/keyboard.h> #include <86box/sound.h> #include <86box/video.h> #include <86box/plat_unused.h> #include <86box/thread.h> -#include <86box/timer.h> #include <86box/network.h> // Temporarily here till we move everything out into the right files @@ -79,6 +81,7 @@ const machine_filter_t machine_types[] = { { "[1992] i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, { "[1992] i486 (Socket 2)", MACHINE_TYPE_486_S2 }, { "[1994] i486 (Socket 3)", MACHINE_TYPE_486_S3 }, + { "[1994] i486 (Socket 3 PCI)", MACHINE_TYPE_486_S3_PCI }, { "[1992] i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, { "[1993] Socket 4", MACHINE_TYPE_SOCKET4 }, { "[1994] Socket 5", MACHINE_TYPE_SOCKET5 }, @@ -7427,7 +7430,7 @@ const machine_t machines[] = { { .name = "[ALi M1429G] TriGem 486GP", .internal_name = "tg486gp", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1429G, .init = machine_at_tg486gp_init, .p1_handler = NULL, @@ -7467,7 +7470,7 @@ const machine_t machines[] = { { .name = "[ALi M1489] AAEON SBC-490", .internal_name = "sbc490", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1489, .init = machine_at_sbc490_init, .p1_handler = NULL, @@ -7508,7 +7511,7 @@ const machine_t machines[] = { { .name = "[ALi M1489] ABIT AB-PB4", .internal_name = "abpb4", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1489, .init = machine_at_abpb4_init, .p1_handler = NULL, @@ -7596,7 +7599,7 @@ const machine_t machines[] = { { .name = "[ALi M1489] MSI MS-4145", .internal_name = "ms4145", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1489, .init = machine_at_ms4145_init, .p1_handler = NULL, @@ -7636,7 +7639,7 @@ const machine_t machines[] = { { .name = "[ALi M1489] ESA TF-486", .internal_name = "tf486", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1489, .init = machine_at_tf486_init, .p1_handler = NULL, @@ -7676,7 +7679,7 @@ const machine_t machines[] = { { .name = "[ALi M1489] Acrosser AR-B1476", .internal_name = "arb1476", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1489, .init = machine_at_arb1476_init, .p1_handler = NULL, @@ -7716,7 +7719,7 @@ const machine_t machines[] = { { .name = "[OPTi 802G] IBM Aptiva 510/710/Vision", .internal_name = "aptiva510", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_OPTI_895_802G, .init = machine_at_aptiva510_init, .p1_handler = NULL, @@ -7756,7 +7759,7 @@ const machine_t machines[] = { { .name = "[OPTi 802G] IBM PC 330 (type 6573)", .internal_name = "pc330_6573", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_OPTI_895_802G, .init = machine_at_pc330_6573_init, .p1_handler = NULL, @@ -7796,7 +7799,7 @@ const machine_t machines[] = { { .name = "[i420EX] ASUS PVI-486AP4", .internal_name = "486ap4", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420EX, .init = machine_at_486ap4_init, .p1_handler = NULL, @@ -7836,7 +7839,7 @@ const machine_t machines[] = { { .name = "[i420EX] Intel Classic/PCI ED", .internal_name = "ninja", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420EX, .init = machine_at_ninja_init, .p1_handler = NULL, @@ -7876,7 +7879,7 @@ const machine_t machines[] = { { .name = "[i420EX] Anigma BAT4IP3e", .internal_name = "bat4ip3e", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420EX, .init = machine_at_bat4ip3e_init, .p1_handler = NULL, @@ -7916,7 +7919,7 @@ const machine_t machines[] = { { .name = "[i420EX] Advanced Integration Research 486PI", .internal_name = "486pi", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420EX, .init = machine_at_486pi_init, .p1_handler = NULL, @@ -7956,7 +7959,7 @@ const machine_t machines[] = { { .name = "[i420EX] ICS SB486P", .internal_name = "sb486p", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420EX, .init = machine_at_sb486p_init, .p1_handler = NULL, @@ -7996,7 +7999,7 @@ const machine_t machines[] = { { .name = "[i420TX] ASUS PCI/I-486SP3", .internal_name = "486sp3", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420TX, .init = machine_at_486sp3_init, .p1_handler = NULL, @@ -8036,7 +8039,7 @@ const machine_t machines[] = { { .name = "[i420TX] Intel Classic/PCI", .internal_name = "alfredo", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420TX, .init = machine_at_alfredo_init, .p1_handler = NULL, @@ -8076,7 +8079,7 @@ const machine_t machines[] = { { .name = "[i420TX] AMI Super Voyager PCI", .internal_name = "amis76", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420TX, .init = machine_at_amis76_init, .p1_handler = NULL, @@ -8117,7 +8120,7 @@ const machine_t machines[] = { { .name = "[i420ZX] ASUS PCI/I-486SP3G", .internal_name = "486sp3g", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_INTEL_420ZX, .init = machine_at_486sp3g_init, .p1_handler = NULL, @@ -8157,7 +8160,7 @@ const machine_t machines[] = { { .name = "[IMS 8848] J-Bond PCI400C-B", .internal_name = "pci400cb", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_IMS_8848, .init = machine_at_pci400cb_init, .p1_handler = NULL, @@ -8197,7 +8200,7 @@ const machine_t machines[] = { { .name = "[SiS 496] ASUS PVI-486SP3C", .internal_name = "486sp3c", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_486sp3c_init, .p1_handler = NULL, @@ -8237,7 +8240,7 @@ const machine_t machines[] = { { .name = "[SiS 496] Lucky Star LS-486E", .internal_name = "ls486e", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_ls486e_init, .p1_handler = NULL, @@ -8277,7 +8280,7 @@ const machine_t machines[] = { { .name = "[SiS 496] Micronics M4Li", .internal_name = "m4li", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_m4li_init, .p1_handler = NULL, @@ -8317,7 +8320,7 @@ const machine_t machines[] = { { .name = "[SiS 496] Rise Computer R418", .internal_name = "r418", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_r418_init, .p1_handler = NULL, @@ -8358,7 +8361,7 @@ const machine_t machines[] = { { .name = "[SiS 496] Soyo 4SAW2", .internal_name = "4saw2", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_4saw2_init, .p1_handler = NULL, @@ -8399,7 +8402,7 @@ const machine_t machines[] = { { .name = "[SiS 496] Zida Tomato 4DP", .internal_name = "4dps", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_4dps_init, .p1_handler = NULL, @@ -8439,7 +8442,7 @@ const machine_t machines[] = { { .name = "[SiS 496] MSI MS-4144", .internal_name = "ms4144", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_SIS_496, .init = machine_at_ms4144_init, .p1_handler = NULL, @@ -8479,7 +8482,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] A-Trend ATC-1415", .internal_name = "atc1415", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_atc1415_init, .p1_handler = NULL, @@ -8519,7 +8522,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] ECS Elite UM8810P-AIO", .internal_name = "ecs486", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_ecs486_init, .p1_handler = NULL, @@ -8559,7 +8562,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] Epson ActionPC 2600", .internal_name = "actionpc2600", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_actionpc2600_init, .p1_handler = NULL, @@ -8600,7 +8603,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] Epson ActionTower 8400", .internal_name = "actiontower8400", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_actiontower8400_init, .p1_handler = NULL, @@ -8641,7 +8644,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] PC Chips M919", .internal_name = "m919", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_m919_init, .p1_handler = NULL, @@ -8681,7 +8684,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] Samsung SPC7700P-LW", .internal_name = "spc7700plw", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_spc7700plw_init, .p1_handler = NULL, @@ -8721,7 +8724,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] Shuttle HOT-433A", .internal_name = "hot433a", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_hot433a_init, .p1_handler = NULL, @@ -8802,7 +8805,7 @@ const machine_t machines[] = { { .name = "[VIA VT82C496G] DFI G486VPA", .internal_name = "g486vpa", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_VIA_VT82C496G, .init = machine_at_g486vpa_init, .p1_handler = NULL, @@ -8842,7 +8845,7 @@ const machine_t machines[] = { { .name = "[VIA VT82C496G] FIC VIP-IO2", .internal_name = "486vipio2", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_VIA_VT82C496G, .init = machine_at_486vipio2_init, .p1_handler = NULL, @@ -16222,8 +16225,8 @@ const machine_t machines[] = { /* Saved copies - jumpers get applied to these. We use also machine_gpio to store IBM PC/XT jumpers as they need more than one byte. */ -static uint8_t machine_p1_default; -static uint8_t machine_p1; +static uint32_t machine_p1_default; +static uint32_t machine_p1; static uint32_t machine_gpio_default; static uint32_t machine_gpio; From 729e8080b6b886effa4068d64c35f2ee049e302d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 9 Feb 2025 12:59:08 -0500 Subject: [PATCH 0222/1190] More Socket 3 PCI --- src/machine/machine_table.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f5cc30782..458b54013 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6865,7 +6865,7 @@ const machine_t machines[] = { { .name = "[OPTi 895] Packard Bell PB450", .internal_name = "pb450", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_OPTI_895_802G, .init = machine_at_pb450_init, .p1_handler = NULL, @@ -7390,7 +7390,7 @@ const machine_t machines[] = { { .name = "[ALi M1429G] MSI MS-4134", .internal_name = "ms4134", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1429G, .init = machine_at_ms4134_init, .p1_handler = NULL, @@ -7555,7 +7555,7 @@ const machine_t machines[] = { { .name = "[ALi M1489] AMI WinBIOS 486 PCI", .internal_name = "win486pci", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_ALI_M1489, .init = machine_at_win486pci_init, .p1_handler = NULL, @@ -8765,7 +8765,7 @@ const machine_t machines[] = { { .name = "[UMC 8881] Compaq Presario 7100/7200 Series 486", .internal_name = "pl4600c", - .type = MACHINE_TYPE_486_S3, + .type = MACHINE_TYPE_486_S3_PCI, .chipset = MACHINE_CHIPSET_UMC_UM8881, .init = machine_at_pl4600c_init, .p1_handler = NULL, From 74e04082017b35e284be40de36be45878baa8430 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 9 Feb 2025 20:06:15 +0100 Subject: [PATCH 0223/1190] 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 0224/1190] 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 ab3d849c76c5e6a29a5615ddd02833c39deaa937 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 10 Feb 2025 13:58:22 -0300 Subject: [PATCH 0225/1190] Jenkins: Revise MacPorts OpenAL hack for 1.24.2 and hopefully later updates, fixes #5218 --- .ci/build.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.ci/build.sh b/.ci/build.sh index 326952186..0af94132a 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -542,11 +542,12 @@ then sudo sed -i -e 's/configure.env-append MAKE=/configure.env-append VULKAN_SDK=${prefix} MAKE=/g' "$qt5_portfile" fi - # Patch openal-soft to use 1.23.1 on all targets instead of 1.24.1 on >=10.15 only, + # Patch openal-soft to use 1.23.1 on all targets instead of 1.24.2 on >=10.13 only, # to prevent a symlink mismatch from having different versions on x86_64 and arm64. # See: https://github.com/macports/macports-ports/commit/9b4903fc9c76769d476079e404c9a3b8a225f8aa + # https://github.com/macports/macports-ports/commit/788deb64dc0695e8d04afb32ed904947f2a7591b openal_portfile="$macports/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/audio/openal-soft/Portfile" - sudo sed -i -e 's/if {${os.platform} ne "darwin" || ${os.major} >= 19}/if {0}/g' "$openal_portfile" + sudo sed -i -e 's/if {${os.platform} ne "darwin" ||/if {0 \&\&/g' "$openal_portfile" # Patch wget to remove libproxy support, as it depends on shared-mime-info which # fails to build for a 10.13 target, which we have to do despite wget only being From cdc381b6192dca8c1e3a0be3607d72b28eba743e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:27:41 +0900 Subject: [PATCH 0226/1190] Added a new machine: IBM PS/55 model 5551-V0,V1 --- src/machine/m_ps2_mca.c | 174 +++++++++++++++++++++++++++++++++++- src/machine/machine_table.c | 40 +++++++++ src/video/vid_ps55da2.c | 44 ++++----- 3 files changed, 231 insertions(+), 27 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 72776b22d..103badf61 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -418,6 +418,50 @@ ps55_model_50t_read(uint16_t port) return 0xff; } +static uint8_t +ps55_model_50v_read(uint16_t port) +{ + switch (port) + { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Reserved + Bit 3-0: Memory Card ID (Connector 3 or 1) + + Memory Card ID: 8h = 4 MB Memory Card IV Installed + Fh = No Card Installed + */ + switch (mem_size / 1024) + { + case 4: + if (ps2.option[1] & 0x04) val = 0xff; + else val = 0xf8; + break; + case 8: + default: + if (ps2.option[1] & 0x04) val = 0xf8; + else val = 0xf8; + break; + } + return val; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + } + return 0xff; +} static void model_50_write(uint16_t port, uint8_t val) { @@ -716,7 +760,7 @@ model_80_write(uint16_t port, uint8_t val) } static void -ps55_model_50t_write(uint16_t port, uint8_t val)//pcem55 +ps55_model_50tv_write(uint16_t port, uint8_t val) { ps2_mca_log(" Write SysBrd %04X %02X %04X:%04X\n", port, val, cs >> 4, cpu_state.pc); switch (port) @@ -1382,6 +1426,62 @@ mem_encoding_write_cached(uint16_t addr, uint8_t val, UNUSED(void *priv)) } } +static void +mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + uint8_t old; + + switch (addr) { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + case 0xe2: + old = ps2.mem_regs[2]; + ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); + if (val & 2) { + ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); + if (ps2.pending_cache_miss) + ps2.mem_regs[2] |= 0x80; + else + ps2.mem_regs[2] &= ~0x80; + ps2.pending_cache_miss = 0; + } + + if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) + ps2.pending_cache_miss = 1; + if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) + ps2_cache_clean(); +#if 1 + // FIXME: Look into this!!! + if (val & 0x01) + ram_mid_mapping.flags |= MEM_MAPPING_ROM_WS; + else + ram_mid_mapping.flags &= ~MEM_MAPPING_ROM_WS; +#endif + break; + + default: + break; + } + ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS, cpu_state.pc, ps2.mem_regs[1], ps2.mem_regs[2]); + mem_encoding_update(); + if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { + mem_mapping_disable(&ram_low_mapping); + mem_mapping_enable(&ps2.cache_mapping); + flushmmucache(); + } else { + mem_mapping_disable(&ps2.cache_mapping); + mem_mapping_enable(&ram_low_mapping); + flushmmucache(); + } + if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ + { + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } +} static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) { @@ -1750,7 +1850,7 @@ ps55_mca_board_model_50t_init() device_add(&keyboard_ps2_mca_1_device); ps2.planar_read = ps55_model_50t_read; - ps2.planar_write = ps55_model_50t_write; + ps2.planar_write = ps55_model_50tv_write; device_add(&ps2_nvr_device); @@ -1790,6 +1890,51 @@ ps55_mca_board_model_50t_init() ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); } +void +ps55_mca_board_model_50v_init() +{ + ps2_mca_board_common_init(); + + //mem_remap_top(256); + ps2.split_addr = mem_size * 1024; + /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ + mca_init(5); + device_add(&keyboard_ps2_mca_1_device); + + ps2.planar_read = ps55_model_50v_read; + ps2.planar_write = ps55_model_50tv_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 0x0002, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); + + ps2.mem_regs[1] = 2; + ps2.option[2] &= 0xf2; /* Bit 3-2: -Cache IDs, Bit 1: Reserved + Bit 0: Disable E0000-E0FFFh (4 KB) */ + + mem_mapping_add(&ps2.split_mapping, + (mem_size + 256) * 1024, + 256 * 1024, + ps2_read_split_ram, + ps2_read_split_ramw, + ps2_read_split_raml, + ps2_write_split_ram, + ps2_write_split_ramw, + ps2_write_split_raml, + &ram[0xa0000], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.split_mapping); + + if (mem_size > 8192) { + /* Only 8 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(8); + } + + if (gfxcard[0] == VID_INTERNAL) + ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); +} + int machine_ps55_model_50t_init(const machine_t* model) { @@ -1814,3 +1959,28 @@ machine_ps55_model_50t_init(const machine_t* model) return ret; } + +int +machine_ps55_model_50v_init(const machine_t* model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ibmps55_m50v/56F7416.BIN", + "roms/machines/ibmps55_m50v/56F7417.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_ps2_common_init(model); + + /* + * Planar ID + * F1FFh - PS/55 model 5551-V0x, V1x + * POST (P/N 38F6933) determination: FBxx -> 5 slots (ok), F1xx -> 5 slots (ok), others -> 8 (error) + */ + ps2.planar_id = 0xf1ff; + ps55_mca_board_model_50v_init(); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c005c9282..bb0f0cd80 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5508,6 +5508,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has IBM PS/55 5551-V0x, V1x firmware. */ + { + .name = "[MCA] IBM PS/55 model 5550-V0", + .internal_name = "ibmps55_m50v", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps55_model_50v_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL, + .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_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 4096, + .max = 16384, + .step = 4096 + }, + .nvrmask = 63, + .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 + }, /* 386DX/486 machines */ /* Has AMIKey F KBC firmware. */ diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 6d4f43ca6..610e272fb 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -60,6 +60,7 @@ //#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ #define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A +#define DA2_DCONFIG_MONTYPE_8515 0x0B #define DA2_DCONFIG_MONTYPE_MONO 0x09 #define DA2_BLT_CIDLE 0 @@ -104,9 +105,7 @@ | EFD8h | Display Adapter /J | | | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ -//2501 -//2500 mono -#define OldLSI 0x20 /* DA-2 or DA-3,5 */ +#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ //#define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ /* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ @@ -122,8 +121,8 @@ /* Monitor ID (imported from OS/2 DDK 1.2) */ //#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 //#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale -//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4pp -//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 B palette +//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp +//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -277,8 +276,6 @@ typedef struct da2_t int fctladdr; int crtcaddr; - uint8_t miscout; - uint32_t decode_mask; uint32_t vram_max; uint32_t vram_mask; @@ -319,8 +316,6 @@ typedef struct da2_t pc_timer_t timer; uint64_t da2const; - //uint8_t scrblank; - int dispon; int hdisp_on; @@ -346,7 +341,6 @@ typedef struct da2_t uint8_t *changedvram; /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; - uint32_t banked_mask; //uint32_t write_bank, read_bank; @@ -364,16 +358,9 @@ typedef struct da2_t int enable; mem_mapping_t mapping; uint8_t ram[256 * 1024]; - uint8_t font[DA2_FONTROM_SIZE]; + uint8_t *font; } mmio; - //mem_mapping_t linear_mapping; - - //uint32_t bank[2]; - //uint32_t mask; - - //int type; - struct { int bitshift_destr; int raster_op; @@ -2295,7 +2282,8 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM - //if (addr >= 0x180000) addr -= 0x40000; + if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; + if (addr >= 0x180000) addr -= 0x40000; if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; @@ -2975,8 +2963,8 @@ da2_reset(void* priv) da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA - 2, 1024 KB */ - da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 2); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ da2->fctl[0] = 0x2b; /* 3E3h:0 */ da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ @@ -3019,7 +3007,8 @@ static void *da2_init() da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - int fonttype = device_get_config_int("font"); + int fonttype = device_get_config_int("charset"); + da2->mmio.font= malloc(DA2_FONTROM_SIZE); switch(fonttype) { case DA2_DCONFIG_FONT_HANT: @@ -3142,6 +3131,7 @@ void da2_close(void *p) free(da2->cram); free(da2->vram); free(da2->changedvram); + free(da2->mmio.font); free(da2); } @@ -3162,17 +3152,17 @@ void da2_force_redraw(void *p) static const device_config_t da2_configuration[] = { // clang-format off { - .name = "font", + .name = "charset", .description = "Charset", .type = CONFIG_SELECTION, .default_int = DA2_DCONFIG_FONT_JPAN, .selection = { { - .description = "CP932 (Japanese)", + .description = "932 (Japanese)", .value = DA2_DCONFIG_FONT_JPAN }, { - .description = "CP938 (Traditional Chinese)", + .description = "938 (Traditional Chinese)", .value = DA2_DCONFIG_FONT_HANT }, { .description = "" } @@ -3188,6 +3178,10 @@ static const device_config_t da2_configuration[] = { .description = "Color", .value = DA2_DCONFIG_MONTYPE_COLOR }, + { + .description = "IBM 8515", + .value = DA2_DCONFIG_MONTYPE_8515 + }, { .description = "Grayscale", .value = DA2_DCONFIG_MONTYPE_MONO From eeb10651da407af167026ac7f47235a5c7af7684 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 11 Feb 2025 12:08:45 +0900 Subject: [PATCH 0227/1190] the prev change must be restricted in CN fontset --- src/video/vid_ps55da2.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 610e272fb..011a9633f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -55,10 +55,10 @@ #define DA2_DEBUG_BLTLOG_MAX 256*1024 #define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe -#define DA2_DCONFIG_FONT_JPAN 0 /* for Code page 932 Japanese */ -//#define DA2_DCONFIG_FONT_HANG 1 /* for Code page 934 Hangul */ -//#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ -#define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ +//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ +//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A #define DA2_DCONFIG_MONTYPE_8515 0x0B #define DA2_DCONFIG_MONTYPE_MONO 0x09 @@ -359,6 +359,7 @@ typedef struct da2_t mem_mapping_t mapping; uint8_t ram[256 * 1024]; uint8_t *font; + int charset; } mmio; struct { @@ -2282,8 +2283,11 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM - if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; - if (addr >= 0x180000) addr -= 0x40000; + if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { + if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; + if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, + but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ + } if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; @@ -3007,14 +3011,14 @@ static void *da2_init() da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - int fonttype = device_get_config_int("charset"); + da2->mmio.charset = device_get_config_int("charset"); da2->mmio.font= malloc(DA2_FONTROM_SIZE); - switch(fonttype) + switch(da2->mmio.charset) { - case DA2_DCONFIG_FONT_HANT: + case DA2_DCONFIG_CHARSET_HANT: da2_loadfont(DA2_FONTROM_PATH_HANT, da2); break; - case DA2_DCONFIG_FONT_JPAN: + case DA2_DCONFIG_CHARSET_JPAN: da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); break; } @@ -3155,15 +3159,15 @@ static const device_config_t da2_configuration[] = { .name = "charset", .description = "Charset", .type = CONFIG_SELECTION, - .default_int = DA2_DCONFIG_FONT_JPAN, + .default_int = DA2_DCONFIG_CHARSET_JPAN, .selection = { { .description = "932 (Japanese)", - .value = DA2_DCONFIG_FONT_JPAN + .value = DA2_DCONFIG_CHARSET_JPAN }, { .description = "938 (Traditional Chinese)", - .value = DA2_DCONFIG_FONT_HANT + .value = DA2_DCONFIG_CHARSET_HANT }, { .description = "" } } From 109a913bf58cedae4c4010b0dca4953fed4ea430 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 11 Feb 2025 12:02:47 -0500 Subject: [PATCH 0228/1190] Remove duplicate .close in scsi_t228_device --- src/scsi/scsi_t128.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 77c2302cc..a40d803f1 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -616,7 +616,6 @@ const device_t scsi_t128_device = { .config = t128_config }; - const device_t scsi_t228_device = { .name = "Trantor T228", .internal_name = "t228", @@ -624,7 +623,6 @@ const device_t scsi_t228_device = { .local = 0, .init = t128_init, .close = t128_close, - .close = t128_close, .reset = NULL, .available = t128_available, .speed_changed = NULL, From d075d0d3c9c9976798c5ed9b6eee6daf9fa23773 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 12 Feb 2025 03:20:12 +0100 Subject: [PATCH 0229/1190] Default host_serial_path to empty string instead of NULL, fixes segmentation fault on initilization of serial passthrough with non-initialized string. --- src/device/serial_passthrough.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index 256f9eaa9..3da2e09ff 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -260,7 +260,7 @@ static const device_config_t serial_passthrough_config[] = { .name = "host_serial_path", .description = "Host Serial Device", .type = CONFIG_SERPORT, - .default_string = NULL, + .default_string = "", .default_int = 0, .file_filter = NULL, .spinner = { 0 }, From 90ba9eda084b942c28a7ffe631819dafd1a09f55 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 12 Feb 2025 05:18:12 +0100 Subject: [PATCH 0230/1190] Fixes to the device and machine configuration string getters and accordingly reverted the serial passthrough fix as well as it's no longer needed. --- src/device.c | 47 +++++++++++++++++++++------------ src/device/serial_passthrough.c | 2 +- src/include/86box/device.h | 33 ++++++++--------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/device.c b/src/device.c index d7c80be7a..fa7378c1a 100644 --- a/src/device.c +++ b/src/device.c @@ -637,16 +637,24 @@ device_get_instance(void) const char * device_get_config_string(const char *str) { - const device_config_t *cfg = device_current.dev->config; + const char *ret = ""; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_string((char *) device_current.name, (char *) str, (char *) cfg->default_string)); + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - cfg++; + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) { + const char *s = (config_get_string((char *) device_current.name, + (char *) str, (char *) cfg->default_string)); + ret = (s == NULL) ? "" : s; + break; + } + + cfg++; + } } - return (NULL); + return ret; } int @@ -870,24 +878,29 @@ machine_get_config_int(char *str) return 0; } -char * +const char * machine_get_config_string(char *str) { - const device_t *dev = machine_get_device(machine); - const device_config_t *cfg; + const device_t *dev = machine_get_device(machine); + const char *ret = ""; - if (dev == NULL) - return 0; + if (dev != NULL) { + const device_config_t *cfg; - cfg = dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_string((char *) dev->name, str, (char *) cfg->default_string)); + cfg = dev->config; + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) { + const char *s = config_get_string((char *) dev->name, str, + (char *) cfg->default_string); + ret = (s == NULL) ? "" : s; + break; + } - cfg++; + cfg++; + } } - return NULL; + return ret; } const device_t * diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index 3da2e09ff..256f9eaa9 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -260,7 +260,7 @@ static const device_config_t serial_passthrough_config[] = { .name = "host_serial_path", .description = "Host Serial Device", .type = CONFIG_SERPORT, - .default_string = "", + .default_string = NULL, .default_int = 0, .file_filter = NULL, .spinner = { 0 }, diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 1c2ec5203..b5a4c1925 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_ { @@ -242,8 +231,8 @@ extern int device_get_instance(void); extern const char *device_get_internal_name(const device_t *dev); -extern int machine_get_config_int(char *str); -extern char *machine_get_config_string(char *str); +extern int machine_get_config_int(char *str); +extern const char *machine_get_config_string(char *str); extern const device_t device_none; extern const device_t device_internal; From af476f957c4c109927eaff390c83fb31598e1ff7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 00:09:03 +0100 Subject: [PATCH 0231/1190] Some const changes in the FDD code. --- src/floppy/fdd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index a381f67f1..f0a32df75 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -100,10 +100,10 @@ d86f_handler_t d86f_handler[FDD_NUM]; static const struct { - char *ext; - void (*load)(int drive, char *fn); - void (*close)(int drive); - int size; + const char *ext; + void (*load)(int drive, char *fn); + void (*close)(int drive); + int size; } loaders[] = { { "001", img_load, img_close, -1}, { "002", img_load, img_close, -1}, From 48065193884b075f68edecd3dfc7e05c11556f6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 00:23:35 +0100 Subject: [PATCH 0232/1190] The device_t available/poll union is now gone, mouse poll is now set using mouse_set_poll(), and mouse_curr is now also gone. --- src/cdrom/cdrom.c | 2 +- src/device/mouse.c | 32 +++++------------------ src/device/mouse_bus.c | 8 +++--- src/device/mouse_microtouch_touchscreen.c | 3 ++- src/device/mouse_ps2.c | 4 ++- src/device/mouse_serial.c | 8 +++--- src/device/mouse_wacom_tablet.c | 10 ++++--- src/device/serial_passthrough.c | 2 +- src/include/86box/device.h | 6 ++--- src/network/net_modem.c | 2 +- 10 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 2cdcc5a22..8ebcfea1f 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -103,7 +103,7 @@ static const device_t cdrom_interface_none_device = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/mouse.c b/src/device/mouse.c index 604109668..f0446d781 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -61,7 +61,7 @@ static const device_t mouse_none_device = { .init = NULL, .close = NULL, .reset = NULL, - { .poll = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -75,7 +75,7 @@ static const device_t mouse_internal_device = { .init = NULL, .close = NULL, .reset = NULL, - { .poll = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -111,7 +111,6 @@ static atomic_int mouse_buttons; static int mouse_delta_b; static int mouse_old_b; -static const device_t *mouse_curr; static void *mouse_priv; static int mouse_nbut; static int mouse_raw; @@ -537,17 +536,10 @@ mouse_get_abs_coords(double *x_abs, double *y_abs) void mouse_process(void) { - if (mouse_curr == NULL) - return; - if ((mouse_input_mode >= 1) && mouse_poll_ex) mouse_poll_ex(); - else if ((mouse_input_mode == 0) && ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL))) { - if (mouse_curr->poll != NULL) - mouse_curr->poll(mouse_priv); - else - mouse_dev_poll(mouse_priv); - } + else if ((mouse_input_mode == 0) && (mouse_dev_poll != NULL)) + mouse_dev_poll(mouse_priv); } void @@ -559,9 +551,6 @@ mouse_set_poll_ex(void (*poll_ex)(void)) void mouse_set_poll(int (*func)(void *), void *arg) { - if (mouse_type != MOUSE_TYPE_INTERNAL) - return; - mouse_dev_poll = func; mouse_priv = arg; } @@ -629,7 +618,7 @@ mouse_set_raw(int raw) void mouse_reset(void) { - if (mouse_curr != NULL) + if (mouse_priv != NULL) return; /* Mouse already initialized. */ mouse_log("MOUSE: reset(type=%d, '%s')\n", @@ -651,19 +640,13 @@ mouse_reset(void) sample_rate = 100.0; timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); - mouse_curr = mouse_devices[mouse_type].device; - - if ((mouse_type > 1) && (mouse_curr != NULL)) - mouse_priv = device_add(mouse_curr); + if ((mouse_type > 1) && (mouse_devices[mouse_type].device != NULL)) + mouse_priv = device_add(mouse_devices[mouse_type].device); } void mouse_close(void) { - if (mouse_curr == NULL) - return; - - mouse_curr = NULL; mouse_priv = NULL; mouse_nbut = 0; mouse_dev_poll = NULL; @@ -680,7 +663,6 @@ mouse_init(void) mouse_clear_buttons(); mouse_type = MOUSE_TYPE_NONE; - mouse_curr = NULL; mouse_priv = NULL; mouse_nbut = 0; mouse_dev_poll = NULL; diff --git a/src/device/mouse_bus.c b/src/device/mouse_bus.c index c0f161dbd..7074a71ac 100644 --- a/src/device/mouse_bus.c +++ b/src/device/mouse_bus.c @@ -680,6 +680,8 @@ bm_init(const device_t *info) mouse_set_sample_rate(0.0); + mouse_set_poll(bm_poll, dev); + return dev; } @@ -818,7 +820,7 @@ const device_t mouse_logibus_device = { .init = bm_init, .close = bm_close, .reset = NULL, - .poll = bm_poll, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = lt_config @@ -832,7 +834,7 @@ const device_t mouse_logibus_onboard_device = { .init = bm_init, .close = bm_close, .reset = NULL, - .poll = bm_poll, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -846,7 +848,7 @@ const device_t mouse_msinport_device = { .init = bm_init, .close = bm_close, .reset = NULL, - .poll = bm_poll, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ms_config diff --git a/src/device/mouse_microtouch_touchscreen.c b/src/device/mouse_microtouch_touchscreen.c index 15b42bfdd..512fcc0df 100644 --- a/src/device/mouse_microtouch_touchscreen.c +++ b/src/device/mouse_microtouch_touchscreen.c @@ -525,6 +525,7 @@ mtouch_init(UNUSED(const device_t *info)) mouse_input_mode = device_get_config_int("crosshair") + 1; mouse_set_buttons(2); + mouse_set_poll(mtouch_poll, dev); mouse_set_poll_ex(mtouch_poll_global); mtouch_inst = dev; @@ -605,7 +606,7 @@ const device_t mouse_mtouch_device = { .init = mtouch_init, .close = mtouch_close, .reset = NULL, - .poll = mtouch_poll, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = mtouch_config diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 9afc75410..8d98b07ce 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -352,6 +352,8 @@ mouse_ps2_init(const device_t *info) if (dev->port != NULL) kbc_at_dev_reset(dev, 0); + mouse_set_poll(ps2_poll, dev); + /* Return our private data to the I/O layer. */ return dev; } @@ -397,7 +399,7 @@ const device_t mouse_ps2_device = { .init = mouse_ps2_init, .close = ps2_close, .reset = NULL, - .poll = ps2_poll, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = ps2_config diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index be9bc62e1..96d3a867c 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -909,6 +909,8 @@ sermouse_init(const device_t *info) /* Tell them how many buttons we have. */ mouse_set_buttons(dev->but); + mouse_set_poll(sermouse_poll, dev); + /* Return our private data to the I/O layer. */ return dev; } @@ -1075,7 +1077,7 @@ const device_t mouse_mssystems_device = { .init = sermouse_init, .close = sermouse_close, .reset = NULL, - .poll = sermouse_poll, + .available = NULL, .speed_changed = sermouse_speed_changed, .force_redraw = NULL, .config = msssermouse_config @@ -1089,7 +1091,7 @@ const device_t mouse_msserial_device = { .init = sermouse_init, .close = sermouse_close, .reset = NULL, - .poll = sermouse_poll, + .available = NULL, .speed_changed = sermouse_speed_changed, .force_redraw = NULL, .config = mssermouse_config @@ -1103,7 +1105,7 @@ const device_t mouse_ltserial_device = { .init = sermouse_init, .close = sermouse_close, .reset = NULL, - .poll = sermouse_poll, + .available = NULL, .speed_changed = sermouse_speed_changed, .force_redraw = NULL, .config = ltsermouse_config diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c index 79b674e07..3b50882ab 100644 --- a/src/device/mouse_wacom_tablet.c +++ b/src/device/mouse_wacom_tablet.c @@ -662,8 +662,10 @@ wacom_init(const device_t *info) if (dev->tablet_type->type == WACOM_TYPE_IV) { wacom_reset_artpad(dev); wacom_process_settings_dword(dev, 0xE2018000); - } - else wacom_reset(dev); + } else + wacom_reset(dev); + + mouse_set_poll(wacom_poll, dev); return dev; } @@ -721,7 +723,7 @@ const device_t mouse_wacom_device = { .init = wacom_init, .close = wacom_close, .reset = NULL, - .poll = wacom_poll, + .available = NULL, .speed_changed = wacom_speed_changed, .force_redraw = NULL, .config = wacom_config @@ -735,7 +737,7 @@ const device_t mouse_wacom_artpad_device = { .init = wacom_init, .close = wacom_close, .reset = NULL, - .poll = wacom_poll, + .available = NULL, .speed_changed = wacom_speed_changed, .force_redraw = NULL, .config = wacom_config diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index 256f9eaa9..3ad969006 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -366,7 +366,7 @@ const device_t serial_passthrough_device = { .init = serial_passthrough_dev_init, .close = serial_passthrough_dev_close, .reset = NULL, - .poll = NULL, + .available = NULL, .speed_changed = serial_passthrough_speed_changed, .force_redraw = NULL, .config = serial_passthrough_config diff --git a/src/include/86box/device.h b/src/include/86box/device.h index b5a4c1925..479e4cbb6 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -165,10 +165,8 @@ typedef struct _device_ { }; void (*close)(void *priv); void (*reset)(void *priv); - union { - int (*available)(void); - int (*poll)(void *priv); - }; + int (*available)(void); + int (*poll)(void *priv); void (*speed_changed)(void *priv); void (*force_redraw)(void *priv); diff --git a/src/network/net_modem.c b/src/network/net_modem.c index 62621391c..a8eab4290 100644 --- a/src/network/net_modem.c +++ b/src/network/net_modem.c @@ -1621,7 +1621,7 @@ const device_t modem_device = { .init = modem_init, .close = modem_close, .reset = NULL, - .poll = NULL, + .available = NULL, .speed_changed = modem_speed_changed, .force_redraw = NULL, .config = modem_config From 187a1ca416eb49673cc7a56442d70cb9c992ac68 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 00:45:10 +0100 Subject: [PATCH 0233/1190] The NVR name is now obtained from the selected machine BIOS type if applicable. --- src/86box.c | 6 +++--- src/chipset/sis_5513_p2i.c | 4 ++-- src/device/hwm_lm78.c | 4 ++-- src/include/86box/machine.h | 2 ++ src/machine/m_at_386dx_486.c | 2 +- src/machine/machine_table.c | 23 +++++++++++++++++++++++ src/mem/catalyst_flash.c | 2 +- src/mem/intel_flash.c | 2 +- src/mem/sst_flash.c | 2 +- src/nvr.c | 4 ++-- src/nvr_ps2.c | 4 ++-- 11 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/86box.c b/src/86box.c index 246d06b16..3ade3c4e2 100644 --- a/src/86box.c +++ b/src/86box.c @@ -457,7 +457,7 @@ delete_nvr_file(uint8_t flash) int c; /* Set up the NVR file's name. */ - c = strlen(machine_get_internal_name()) + 5; + c = strlen(machine_get_nvr_name()) + 5; fn = (char *) malloc(c + 1); if (fn == NULL) @@ -465,9 +465,9 @@ delete_nvr_file(uint8_t flash) flash ? "BIOS flash" : "CMOS"); if (flash) - sprintf(fn, "%s.bin", machine_get_internal_name()); + sprintf(fn, "%s.bin", machine_get_nvr_name()); else - sprintf(fn, "%s.nvr", machine_get_internal_name()); + sprintf(fn, "%s.nvr", machine_get_nvr_name()); remove(nvr_path(fn)); diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index 3655ccc3f..95a890fcf 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -1287,9 +1287,9 @@ sis_5513_pci_to_isa_init(UNUSED(const device_t *info)) acpi_set_nvr(dev->sis->acpi, dev->nvr); /* Set up the NVR file's name. */ - c = strlen(machine_get_internal_name()) + 9; + c = strlen(machine_get_nvr_name()) + 9; dev->fn = (char *) malloc(c + 1); - sprintf(dev->fn, "%s_apc.nvr", machine_get_internal_name()); + sprintf(dev->fn, "%s_apc.nvr", machine_get_nvr_name()); fp = nvr_fopen(dev->fn, "rb"); diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index 1e61168ac..909713833 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -102,9 +102,9 @@ lm78_log(const char *fmt, ...) void lm78_nvram(lm78_t *dev, uint8_t save) { - size_t l = strlen(machine_get_internal_name_ex(machine)) + 14; + size_t l = strlen(machine_get_nvr_name_ex(machine)) + 14; char *nvr_path = (char *) malloc(l); - sprintf(nvr_path, "%s_as99127f.nvr", machine_get_internal_name_ex(machine)); + sprintf(nvr_path, "%s_as99127f.nvr", machine_get_nvr_name_ex(machine)); FILE *fp = nvr_fopen(nvr_path, save ? "wb" : "rb"); if (fp) { diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f39187dd9..1ce46de9b 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -361,6 +361,7 @@ extern int machine_available(int m); extern const char *machine_getname(void); extern const char *machine_getname_ex(int m); extern const char *machine_get_internal_name(void); +extern const char *machine_get_nvr_name(void); extern int machine_get_machine_from_internal_name(const char *s); extern void machine_init(void); #ifdef EMU_DEVICE_H @@ -373,6 +374,7 @@ extern const device_t *machine_get_snd_device(int m); extern const device_t *machine_get_net_device(int m); #endif extern const char *machine_get_internal_name_ex(int m); +extern const char *machine_get_nvr_name_ex(int m); extern int machine_get_nvrmask(int m); extern int machine_has_flags(int m, int flags); extern int machine_has_bus(int m, int bus_flags); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 3d152065b..19c4b535e 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -696,7 +696,7 @@ static const device_config_t pb450_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "PCI 1.0A", .internal_name = "pci10a", .bios_type = BIOS_NORMAL, + { .name = "PCI 1.0A", .internal_name = "pb450" /*"pci10a"*/, .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/OPTI802.bin", "" } }, { .name = "PNP 1.1A", .internal_name = "pnp11a", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/PNP11A.bin", "" } }, diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 458b54013..e6198541e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -16565,3 +16565,26 @@ machine_is_sony(void) { return (!strcmp(machines[machine].internal_name, "pcv90")); } + +const char * +machine_get_nvr_name_ex(int m) +{ + const char *ret = machines[m].internal_name; + const device_t *dev = machine_get_device(m); + + if (dev != NULL) { + device_context(dev); + const char *bios = device_get_config_string("bios"); + if ((bios != NULL) && (strcmp(bios, "") != 0)) + ret = bios; + device_context_restore(); + } + + return ret; +} + +const char * +machine_get_nvr_name(void) +{ + return machine_get_nvr_name_ex(machine); +} diff --git a/src/mem/catalyst_flash.c b/src/mem/catalyst_flash.c index fd2bb739f..00e2422a3 100644 --- a/src/mem/catalyst_flash.c +++ b/src/mem/catalyst_flash.c @@ -194,7 +194,7 @@ catalyst_flash_init(UNUSED(const device_t *info)) dev = calloc(1, sizeof(flash_t)); - sprintf(flash_path, "%s.bin", machine_get_internal_name_ex(machine)); + sprintf(flash_path, "%s.bin", machine_get_nvr_name_ex(machine)); mem_mapping_disable(&bios_mapping); mem_mapping_disable(&bios_high_mapping); diff --git a/src/mem/intel_flash.c b/src/mem/intel_flash.c index 7375b1f42..e193f3545 100644 --- a/src/mem/intel_flash.c +++ b/src/mem/intel_flash.c @@ -353,7 +353,7 @@ intel_flash_init(const device_t *info) dev = calloc(1, sizeof(flash_t)); - sprintf(flash_path, "%s.bin", machine_get_internal_name_ex(machine)); + sprintf(flash_path, "%s.bin", machine_get_nvr_name_ex(machine)); dev->flags = info->local & 0xff; diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 5a9c9c877..b41e0f2e2 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -507,7 +507,7 @@ sst_init(const device_t *info) FILE *fp; sst_t *dev = calloc(1, sizeof(sst_t)); - sprintf(flash_path, "%s.bin", machine_get_internal_name_ex(machine)); + sprintf(flash_path, "%s.bin", machine_get_nvr_name_ex(machine)); mem_mapping_disable(&bios_mapping); mem_mapping_disable(&bios_high_mapping); diff --git a/src/nvr.c b/src/nvr.c index d0b05b93a..7f43a76c1 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -161,9 +161,9 @@ nvr_init(nvr_t *nvr) int c; /* Set up the NVR file's name. */ - c = strlen(machine_get_internal_name()) + 5; + c = strlen(machine_get_nvr_name()) + 5; nvr->fn = (char *) malloc(c + 1); - sprintf(nvr->fn, "%s.nvr", machine_get_internal_name()); + sprintf(nvr->fn, "%s.nvr", machine_get_nvr_name()); /* Initialize the internal clock as needed. */ memset(&intclk, 0x00, sizeof(intclk)); diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 3ca0b0ba5..febf6c165 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -122,9 +122,9 @@ ps2_nvr_init(const device_t *info) nvr->size = 8192; /* Set up the NVR file's name. */ - c = strlen(machine_get_internal_name()) + 9; + c = strlen(machine_get_nvr_name()) + 9; nvr->fn = (char *) malloc(c + 1); - sprintf(nvr->fn, "%s_sec.nvr", machine_get_internal_name()); + sprintf(nvr->fn, "%s_sec.nvr", machine_get_nvr_name()); io_sethandler(0x0074, 3, ps2_nvr_read, NULL, NULL, ps2_nvr_write, NULL, NULL, nvr); From 8ffdff2bd4825f2a09c53d23d9e1778b80eb7812 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 00:52:34 +0100 Subject: [PATCH 0234/1190] Generic Xt memory expansion: Allow starting at 640k. --- src/device/isamem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index 45a0413be..62fb96f5d 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -1024,7 +1024,7 @@ static const device_config_t genericxt_config[] = { .file_filter = NULL, .spinner = { .min = 0, - .max = 624, + .max = 640, .step = 16 }, .selection = { { 0 } }, From 30ca057519af1995cfc07c81d28cf5676f7d2ad8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 01:06:40 +0100 Subject: [PATCH 0235/1190] Removed the last remnants of device_t.poll(). --- src/device.c | 15 --------------- src/device/keyboard_at.c | 2 +- src/include/86box/device.h | 2 -- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/device.c b/src/device.c index fa7378c1a..dad583cdc 100644 --- a/src/device.c +++ b/src/device.c @@ -484,21 +484,6 @@ device_has_config(const device_t *dev) return (c > 0) ? 1 : 0; } -int -device_poll(const device_t *dev) -{ - for (uint16_t c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c] == dev) { - if (devices[c]->poll) - return (devices[c]->poll(device_priv[c])); - } - } - } - - return 0; -} - void device_get_name(const device_t *dev, int bus, char *name) { diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 9b3f06098..589ec7ded 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2221,7 +2221,7 @@ const device_t keyboard_at_generic_device = { .init = keyboard_at_init, .close = keyboard_at_close, .reset = NULL, - .poll = NULL, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = keyboard_at_config diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 479e4cbb6..d92a387e9 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -166,7 +166,6 @@ typedef struct _device_ { void (*close)(void *priv); void (*reset)(void *priv); int (*available)(void); - int (*poll)(void *priv); void (*speed_changed)(void *priv); void (*force_redraw)(void *priv); @@ -203,7 +202,6 @@ extern void device_reset_all(uint32_t match_flags); extern void *device_find_first_priv(uint32_t match_flags); extern void *device_get_priv(const device_t *dev); extern int device_available(const device_t *dev); -extern int device_poll(const device_t *dev); extern void device_speed_changed(void); extern void device_force_redraw(void); extern void device_get_name(const device_t *dev, int bus, char *name); From 9a1ae5997fe3d63941aed2ecbb9cc771fc95604c Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 01:44:10 +0100 Subject: [PATCH 0236/1190] 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 0237/1190] 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 0238/1190] 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 0239/1190] 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 0240/1190] 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 91ba20fbd08355de79e601040646d5f70d09d501 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 05:10:55 +0100 Subject: [PATCH 0241/1190] Added the test mode entry point requested by gloriouscow. --- src/86box.c | 24 ++++++++++++++++++++++++ src/cpu/808x.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/cpu/cpu.h | 8 ++++++++ 3 files changed, 74 insertions(+) diff --git a/src/86box.c b/src/86box.c index 3ade3c4e2..e1cf61b64 100644 --- a/src/86box.c +++ b/src/86box.c @@ -210,6 +210,7 @@ int video_fullscreen_scale_maximized = 0; /* (C) Whether int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus loss */ int hook_enabled = 1; /* (C) Keyboard hook is enabled */ +int test_mode = 0; /* (C) Test mode */ char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */ int other_ide_present = 0; /* IDE controllers from non-IDE cards are @@ -585,6 +586,7 @@ usage: #ifndef USE_SDL_UI printf("-S or --settings - show only the settings dialog\n"); #endif + printf("-T or --testmode - test mode: execute the test mode entry point on init/hard reset\n"); printf("-V or --vmname name - overrides the name of the running VM\n"); printf("-W or --nohook - disables keyboard hook (compatibility-only outside Windows)\n"); printf("-X or --clear what - clears the 'what' (cmos/flash/both)\n"); @@ -656,6 +658,8 @@ usage: } else if (!strcasecmp(argv[c], "--settings") || !strcasecmp(argv[c], "-S")) { settings_only = 1; #endif + } else if (!strcasecmp(argv[c], "--testmode") || !strcasecmp(argv[c], "-T")) { + test_mode = 1; } else if (!strcasecmp(argv[c], "--noconfirm") || !strcasecmp(argv[c], "-N")) { confirm_exit_cmdl = 0; } else if (!strcasecmp(argv[c], "--missing") || !strcasecmp(argv[c], "-M")) { @@ -1112,6 +1116,23 @@ pc_send_cae(void) pc_send_ca(1); } +/* + Currently available API: + + extern void prefetch_queue_set_pos(int pos); + extern void prefetch_queue_set_ip(uint16_t ip); + extern void prefetch_queue_set_prefetching(int p); + extern int prefetch_queue_get_pos(void); + extern uint16_t prefetch_queue_get_ip(void); + extern int prefetch_queue_get_prefetching(void); + extern int prefetch_queue_get_size(void); + */ +static void +pc_test_mode_entry_point(void) +{ + pclog("Test mode entry point\n=====================\n"); +} + void pc_reset_hard_close(void) { @@ -1313,6 +1334,9 @@ pc_reset_hard_init(void) update_mouse_msg(); + if (test_mode) + pc_test_mode_entry_point(); + ui_hard_reset_completed(); } diff --git a/src/cpu/808x.c b/src/cpu/808x.c index a74cf84ab..e3a326503 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -154,6 +154,48 @@ x808x_log(const char *fmt, ...) static void pfq_add(int c, int add); static void set_pzs(int bits); +void +prefetch_queue_set_pos(int pos) +{ + pfq_pos = pos; +} + +void +prefetch_queue_set_ip(uint16_t ip) +{ + pfq_ip = ip; +} + +void +prefetch_queue_set_prefetching(int p) +{ + prefetching = p; +} + +int +prefetch_queue_get_pos(void) +{ + return pfq_pos; +} + +uint16_t +prefetch_queue_get_ip(void) +{ + return pfq_ip; +} + +int +prefetch_queue_get_prefetching(void) +{ + return prefetching; +} + +int +prefetch_queue_get_size(void) +{ + return pfq_size; +} + uint16_t get_last_addr(void) { diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index bd841ccc6..ab4bad8b0 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -821,4 +821,12 @@ extern int cpu_override_interpreter; extern int is_lock_legal(uint32_t fetchdat); +extern void prefetch_queue_set_pos(int pos); +extern void prefetch_queue_set_ip(uint16_t ip); +extern void prefetch_queue_set_prefetching(int p); +extern int prefetch_queue_get_pos(void); +extern uint16_t prefetch_queue_get_ip(void); +extern int prefetch_queue_get_prefetching(void); +extern int prefetch_queue_get_size(void); + #endif /*EMU_CPU_H*/ From 63fbe6ab4faab499a1bdb04d92f41f3d1a14b8d8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 05:27:10 +0100 Subject: [PATCH 0242/1190] Documented three more functions. --- src/86box.c | 4 ++++ src/cpu/cpu.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/86box.c b/src/86box.c index e1cf61b64..f8d632e11 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1119,6 +1119,10 @@ pc_send_cae(void) /* Currently available API: + extern void resetx86(void); + extern void softresetx86(void); + extern void hardresetx86(void); + extern void prefetch_queue_set_pos(int pos); extern void prefetch_queue_set_ip(uint16_t ip); extern void prefetch_queue_set_prefetching(int p); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index ab4bad8b0..1d003ddc9 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -829,4 +829,7 @@ extern uint16_t prefetch_queue_get_ip(void); extern int prefetch_queue_get_prefetching(void); extern int prefetch_queue_get_size(void); +#define prefetch_queue_set_suspended(s) prefetch_queue_set_prefetching(!s) +#define prefetch_queue_get_suspended !prefetch_queue_get_prefetching + #endif /*EMU_CPU_H*/ From 44c6daad1c3e8189222d4aa1a1a06a3656228acf Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 08:36:36 +0100 Subject: [PATCH 0243/1190] 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 7c422a4d507222b00c8f1edc1ce1cdff77dd9a88 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Thu, 13 Feb 2025 12:07:13 +0300 Subject: [PATCH 0244/1190] Block AMD and Cyrix CPUs from Intel Socket 5/7 motherboards with stock BIOS --- src/machine/machine_table.c | 48 ++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e6198541e..e55d9b494 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9762,7 +9762,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3520, @@ -9802,7 +9802,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3520, @@ -9843,7 +9843,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -10087,7 +10087,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -10741,7 +10741,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -10824,7 +10824,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -10908,7 +10908,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -10989,7 +10989,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -11236,7 +11236,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_Cx6x86), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 3380, @@ -11647,7 +11647,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2800, @@ -11687,7 +11688,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2800, @@ -11727,7 +11729,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2800, @@ -11767,7 +11770,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2800, @@ -11850,7 +11854,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2800, @@ -12177,7 +12182,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2500, @@ -12299,7 +12305,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2200, @@ -12382,7 +12389,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 50000000, .max_bus = 66666667, .min_voltage = 2800, @@ -12668,7 +12676,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 2800, @@ -12709,7 +12718,8 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 2800, From 48f42af74575144d19a1cb7d005dad25a6cfe332 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 10:31:12 +0100 Subject: [PATCH 0245/1190] 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 9ab1e35b16679c4d5870e4fb250d4b9df888e5f5 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 13 Feb 2025 20:10:23 +0900 Subject: [PATCH 0246/1190] added a Traditional Chinese font ROM info --- src/video/vid_ps55da2.c | 44 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 011a9633f..a19965f6f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1533,34 +1533,32 @@ The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. -[Font ROM Map (DA2)] -The Font ROM is accessed via 128 KB memory window located on A0000-BFFFFh. -I don't know how much data the actual Font ROM has. -Here information, I researched it by disassembling J-DOS. +[Font ROM Map (DA2, Japanese)] +The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. -Bank 0 + Bank 0 4800- * -Bank 1, 2, 3 - * - * -Bank 4 - * -0DB6Fh ( 4800-8DB6Fh;IBMJ 100-1F7Dh) : JIS X 0208 DBCS (24 x 24) -10000-16D1Fh (90000-96D1Fh;IBMJ 2000-2183h) : IBM Extended Characters -18000-1BFCFh (98000-9BFCFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) -1C000-1FFFFh (9C000-9FFFFh;around IBMJ 22AA-238Eh) : Codepage 437 characters (13 x 30) -Bank 5 -00000-0C68Fh (A0000-AC68Fh;around IBMJ 238E-2650h) : Gaiji (24 x 24) - - * -0D09Fh (9FD20-AD09Fh;IBMJ 2384-2673h) : Gaiji 752 chs (maybe blank) -10000-13FFFh (B0000-B3FFFh;around IBMJ 271C-27FFh) : Extended SBCS (13 x 30) - -14000-147FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho -16000-17FFFh (B6000-B7FFFh;around IBMJ h) : Codepage 850 characters (13 x 30) -18000-1A3FFh (B8000-BA3FFh;around IBMJ h) : Shape Icons? (32 x 32) - - (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters + Bank 1, 2, 3 + * - * + Bank 4 + * -0DB6Fh ( 4800-8DB6Fh) : JIS X 0208 DBCS (24 x 24) (IBMJ code: 100-1F7Dh) + 10000-16D1Fh (90000-96D1Fh) : IBM Extended Characters (IBMJ code: 2ADC-2C5Fh) + 18000-1BFCFh (98000-9BFCFh) : JIS X 0201 SBCS (13 x 30) + 1C000-1FFFFh (9C000-9FFFFh) : Codepage 437 characters (13 x 30) + Bank 5 + 00000-0C68Fh (A0000-AC68Fh) : Gaiji used by DOS Bunsho + 10000-13FFFh (B0000-B3FFFh) : Extended SBCS (13 x 30) + 14000-1477Fh (B4000-B477Fh) : Half-width box drawing characters used by DOS Bunsho + 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) + 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) +[Font ROM Map (DA3, Traditional Chinese)] + Bank 0 - 11 : Valid Font ROM data + Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) + Bank 13 : All addresses return 0xFF + [Gaiji RAM Map (DA2)] Bank 0 00000-1FFFFh placed between A0000h-BFFFFh 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes From 6362351987b3170a7a5f84de81211b38dd6c9f09 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Thu, 13 Feb 2025 19:14:36 +0100 Subject: [PATCH 0247/1190] bring back the Slot 1 to Socket 8 adapter --- src/cpu/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 808f603b5..0802fa3ac 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -372,7 +372,7 @@ cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine) if (packages & CPU_PKG_SOCKET3) packages |= CPU_PKG_SOCKET1; else if (packages & CPU_PKG_SLOT1) - packages |= CPU_PKG_SOCKET370; + packages |= CPU_PKG_SOCKET370 | CPU_PKG_SOCKET8; /* Package type. */ if (!(cpu_family->package & packages)) From f5d65f2e66da32e335b3032b58ce164ccb882e63 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Thu, 13 Feb 2025 19:21:19 +0100 Subject: [PATCH 0248/1190] Just block Pentium Pro on incompatibile machines, instead of removing the Slot 1-to-Socket 8 adapter altogether (part 2) --- 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 e55d9b494..72271ee7e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15278,7 +15278,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SLOT1, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_PENTIUMPRO), .min_bus = 66666667, .max_bus = 150000000, .min_voltage = 1300, @@ -16163,7 +16163,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SLOT1, - .block = CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), + .block = CPU_BLOCK(CPU_PENTIUMPRO, CPU_PENTIUM2, CPU_CYRIX3S), .min_bus = 0, .max_bus = 66666667, .min_voltage = 0, From 1a33a2bd099763d577d0178d25240374184494c1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 19:47:21 +0100 Subject: [PATCH 0249/1190] 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 0250/1190] 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 0251/1190] 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 0252/1190] 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 5b6a965900fe49f1cfb96104d983a279d15680e3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 07:10:55 +0100 Subject: [PATCH 0253/1190] Bring machine flags on par with device flag and clean up device_is_valid() accordingly. --- src/device.c | 84 ++++++++++--------------------------- src/device/kbc_at.c | 31 +++++--------- src/include/86box/device.h | 26 ++++++++---- src/include/86box/machine.h | 64 ++++++++++++++-------------- src/machine/machine_table.c | 42 ++++++++++++++----- src/pic.c | 2 +- 6 files changed, 112 insertions(+), 137 deletions(-) diff --git a/src/device.c b/src/device.c index dad583cdc..7cfa1d70e 100644 --- a/src/device.c +++ b/src/device.c @@ -490,7 +490,7 @@ device_get_name(const device_t *dev, int bus, char *name) const char *sbus = NULL; const char *fbus; char *tname; - char pbus[8] = { 0 }; + char pbus[11] = { 0 }; if (dev == NULL) return; @@ -498,8 +498,21 @@ device_get_name(const device_t *dev, int bus, char *name) name[0] = 0x00; if (bus) { - if (dev->flags & DEVICE_ISA) - sbus = (dev->flags & DEVICE_AT) ? "ISA16" : "ISA"; + if ((dev->flags & (DEVICE_PCJR | DEVICE_ISA)) == + (DEVICE_PCJR | DEVICE_ISA)) + sbus = "ISA/PCJR"; + else if (dev->flags & DEVICE_SIDECAR) + sbus = "Sidecar"; + else if (dev->flags & DEVICE_XT_KBC) + sbus = "XT KBC"; + else if (dev->flags & DEVICE_ISA16) + sbus = "ISA16"; + else if (dev->flags & DEVICE_AT_KBC) + sbus = "AT KBC"; + else if (dev->flags & DEVICE_PS2_KBC) + sbus = "PS/2 KBC"; + else if (dev->flags & DEVICE_ISA) + sbus = "ISA"; else if (dev->flags & DEVICE_CBUS) sbus = "C-BUS"; else if (dev->flags & DEVICE_PCMCIA) @@ -519,7 +532,7 @@ device_get_name(const device_t *dev, int bus, char *name) else if (dev->flags & DEVICE_PCI) sbus = "PCI"; else if (dev->flags & DEVICE_CARDBUS) - sbus = "CARDBUS"; + sbus = "CardBus"; else if (dev->flags & DEVICE_USB) sbus = "USB"; else if (dev->flags & DEVICE_AGP) @@ -780,67 +793,12 @@ device_set_config_mac(const char *str, int val) int device_is_valid(const device_t *device, int mch) { - if (device == NULL) - return 1; + int ret = 1; - if ((device->flags & DEVICE_PCJR) && !machine_has_bus(mch, MACHINE_BUS_PCJR)) - return 0; + if (device != NULL) + ret = machine_has_bus(mch, device->flags & DEVICE_BUS); - if ((device->flags & DEVICE_XTKBC) && machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) - return 0; - - if ((device->flags & DEVICE_AT) && !machine_has_bus(mch, MACHINE_BUS_ISA16)) - return 0; - - if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) - return 0; - - if ((device->flags & DEVICE_PS2) && !machine_has_bus(mch, MACHINE_BUS_PS2_PORTS)) - return 0; - - if ((device->flags & DEVICE_ISA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) - return 0; - - if ((device->flags & DEVICE_CBUS) && !machine_has_bus(mch, MACHINE_BUS_CBUS)) - return 0; - - if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) - return 0; - - if ((device->flags & DEVICE_MCA) && !machine_has_bus(mch, MACHINE_BUS_MCA)) - return 0; - - if ((device->flags & DEVICE_HIL) && !machine_has_bus(mch, MACHINE_BUS_HIL)) - return 0; - - if ((device->flags & DEVICE_EISA) && !machine_has_bus(mch, MACHINE_BUS_EISA)) - return 0; - - if ((device->flags & DEVICE_AT32) && !machine_has_bus(mch, MACHINE_BUS_AT32)) - return 0; - - if ((device->flags & DEVICE_OLB) && !machine_has_bus(mch, MACHINE_BUS_OLB)) - return 0; - - if ((device->flags & DEVICE_VLB) && !machine_has_bus(mch, MACHINE_BUS_VLB)) - return 0; - - if ((device->flags & DEVICE_PCI) && !machine_has_bus(mch, MACHINE_BUS_PCI)) - return 0; - - if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_PCI)) - return 0; - - if ((device->flags & DEVICE_USB) && !machine_has_bus(mch, MACHINE_BUS_USB)) - return 0; - - if ((device->flags & DEVICE_AGP) && !machine_has_bus(mch, MACHINE_BUS_AGP)) - return 0; - - if ((device->flags & DEVICE_AC97) && !machine_has_bus(mch, MACHINE_BUS_AC97)) - return 0; - - return 1; + return ret; } int diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index ad1625873..09855a387 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -810,27 +810,18 @@ write_p2(atkbc_t *dev, uint8_t val) if (!(val & 0x01)) { /* Pin 0 selected. */ /* Pin 0 selected. */ kbc_at_log("write_p2(): Pulse reset!\n"); - if (machines[machine].flags & MACHINE_COREBOOT) { - /* The SeaBIOS hard reset code attempts a KBC reset if ACPI RESET_REG - is not available. However, the KBC reset is normally a soft reset, so - SeaBIOS gets caught in a soft reset loop as it tries to hard reset the - machine. Hack around this by making the KBC reset a hard reset only on - coreboot machines. */ - pc_reset_hard(); - } else { - softresetx86(); /* Pulse reset! */ - cpu_set_edx(); - flushmmucache(); - if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw")) - smbase = 0x00030000; + softresetx86(); /* Pulse reset! */ + cpu_set_edx(); + flushmmucache(); + if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw")) + smbase = 0x00030000; - /* Yes, this is a hack, but until someone gets ahold of the real PCD-2L - and can find out what they actually did to make it boot from FFFFF0 - correctly despite A20 being gated when the CPU is reset, this will - have to do. */ - if ((kbc_ven == KBC_VEN_SIEMENS) || !strcmp(machine_get_internal_name(), "acera1g")) - is486 ? loadcs(0xf000) : loadcs_2386(0xf000); - } + /* Yes, this is a hack, but until someone gets ahold of the real PCD-2L + and can find out what they actually did to make it boot from FFFFF0 + correctly despite A20 being gated when the CPU is reset, this will + have to do. */ + if ((kbc_ven == KBC_VEN_SIEMENS) || !strcmp(machine_get_internal_name(), "acera1g")) + is486 ? loadcs(0xf000) : loadcs_2386(0xf000); } } diff --git a/src/include/86box/device.h b/src/include/86box/device.h index d92a387e9..d074cc2fc 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -79,15 +79,15 @@ // #define CONFIG_STANDALONE 257 /* not available on the on-board variant */ enum { - DEVICE_PCJR = 2, /* requires an IBM PCjr */ - DEVICE_XTKBC = 4, /* requires an XT-compatible keyboard controller */ - DEVICE_AT = 8, /* requires an AT-compatible system */ - DEVICE_ATKBC = 0x10, /* requires an AT-compatible keyboard controller */ - DEVICE_PS2 = 0x20, /* requires a PS/1 or PS/2 system */ - DEVICE_ISA = 0x40, /* requires the ISA bus */ - DEVICE_CBUS = 0x80, /* requires the C-BUS bus */ - DEVICE_PCMCIA = 0x100, /* requires the PCMCIA bus */ - DEVICE_MCA = 0x200, /* requires the MCA bus */ + DEVICE_SIDECAR = 2, /* requires an IBM PCjr */ + DEVICE_ISA = 4, /* requires the ISA bus */ + DEVICE_XT_KBC = 8, /* requires an XT-compatible keyboard controller */ + DEVICE_CBUS = 0x10, /* requires the C-BUS bus */ + DEVICE_ISA16 = 0x20, /* requires an AT-compatible system */ + DEVICE_AT_KBC = 0x40, /* requires an AT-compatible keyboard controller */ + DEVICE_MCA = 0x80, /* requires the MCA bus */ + DEVICE_PS2_KBC = 0x100, /* requires a PS/1 or PS/2 system */ + DEVICE_PCMCIA = 0x200, /* requires the PCMCIA bus */ DEVICE_HIL = 0x400, /* requires the HP HIL bus */ DEVICE_EISA = 0x800, /* requires the EISA bus */ DEVICE_AT32 = 0x1000, /* requires the Mylex AT/32 local bus */ @@ -98,8 +98,11 @@ enum { DEVICE_USB = 0x20000, /* requires the USB bus */ DEVICE_AGP = 0x40000, /* requires the AGP bus */ DEVICE_AC97 = 0x80000, /* requires the AC'97 bus */ + DEVICE_BUS = 0xfffff, /* requires a machine bus */ + DEVICE_COM = 0x100000, /* requires a serial port */ DEVICE_LPT = 0x200000, /* requires a parallel port */ + DEVICE_KBC = 0x400000, /* is a keyboard controller */ DEVICE_SOFTRESET = 0x800000, /* requires to be reset on soft reset */ @@ -109,6 +112,11 @@ enum { DEVICE_ALL = 0xffffffff /* match all devices */ }; +/* TODO: Remove this once all the devices' flags have been updated. */ +#define DEVICE_AT DEVICE_ISA16 +#define DEVICE_PCJR DEVICE_SIDECAR +#define DEVICE_PS2 DEVICE_PS2_KBC + #define BIOS_NORMAL 0 #define BIOS_INTERLEAVED 1 #define BIOS_INTERLEAVED_SINGLEFILE 2 diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 1ce46de9b..2c5440438 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -23,34 +23,31 @@ #define EMU_MACHINE_H /* Machine feature flags. */ -#define MACHINE_BUS_NONE 0x00000000 /* sys has no bus */ +#define MACHINE_BUS_NONE 0x00000000 /* sys has no bus */ /* Feature flags for BUS'es. */ -#define MACHINE_BUS_ISA 0x00000001 /* sys has ISA bus */ -#define MACHINE_BUS_CASSETTE 0x00000002 /* sys has cassette port */ -#define MACHINE_BUS_CARTRIDGE 0x00000004 /* sys has two cartridge bays */ -#define MACHINE_BUS_PCJR 0x00000008 /* sys has PCjr sidecar bus */ -#define MACHINE_BUS_DM_KBC 0x00000010 /* system has keyboard controller that supports - both XT and AT keyboards */ +#define MACHINE_BUS_CASSETTE 0x00000001 /* sys has cassette port */ +#define MACHINE_BUS_ISA 0x00000002 /* sys has ISA bus */ +#define MACHINE_BUS_SIDECAR 0x00000004 /* sys has PCjr sidecar bus */ +#define MACHINE_BUS_XT_KBD 0x00000008 /* sys has an XT keyboard port */ +#define MACHINE_BUS_CBUS 0x00000010 /* sys has C-BUS bus */ #define MACHINE_BUS_ISA16 0x00000020 /* sys has ISA16 bus - PC/AT architecture */ -#define MACHINE_BUS_CBUS 0x00000040 /* sys has C-BUS bus */ -#define MACHINE_BUS_PCMCIA 0x00000080 /* sys has PCMCIA bus */ -#define MACHINE_BUS_PS2_LATCH 0x00000100 /* system has PS/2 keyboard controller IRQ latch */ -#define MACHINE_BUS_PS2_PORTS 0x00000200 /* system has PS/2 keyboard and mouse ports */ -#define MACHINE_BUS_PS2 (MACHINE_BUS_PS2_LATCH | MACHINE_BUS_PS2_PORTS) +#define MACHINE_BUS_AT_KBD 0x00000040 /* sys has an AT keyboard port */ +#define MACHINE_BUS_MCA 0x00000080 /* sys has MCA bus */ +#define MACHINE_BUS_PS2_PORTS 0x00000100 /* system has PS/2 keyboard and mouse ports */ +#define MACHINE_BUS_PS2 MACHINE_BUS_PS2_PORTS +#define MACHINE_BUS_PCMCIA 0x00000200 /* sys has PCMCIA bus */ #define MACHINE_BUS_HIL 0x00000400 /* system has HP HIL keyboard and mouse ports */ #define MACHINE_BUS_EISA 0x00000800 /* sys has EISA bus */ #define MACHINE_BUS_AT32 0x00001000 /* sys has Mylex AT/32 local bus */ #define MACHINE_BUS_OLB 0x00002000 /* sys has OPTi local bus */ #define MACHINE_BUS_VLB 0x00004000 /* sys has VL bus */ -#define MACHINE_BUS_MCA 0x00008000 /* sys has MCA bus */ -#define MACHINE_BUS_PCI 0x00010000 /* sys has PCI bus */ -#define MACHINE_BUS_CARDBUS 0x00020000 /* sys has CardBus bus */ -#define MACHINE_BUS_USB 0x00040000 /* sys has USB bus */ -#define MACHINE_BUS_AGP 0x00080000 /* sys has AGP bus */ -#define MACHINE_BUS_AC97 0x00100000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ +#define MACHINE_BUS_PCI 0x00008000 /* sys has PCI bus */ +#define MACHINE_BUS_CARDBUS 0x00010000 /* sys has CardBus bus */ +#define MACHINE_BUS_USB 0x00020000 /* sys has USB bus */ +#define MACHINE_BUS_AGP 0x00040000 /* sys has AGP bus */ +#define MACHINE_BUS_AC97 0x00080000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ /* Aliases. */ #define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ -#define MACHINE_CARTRIDGE (MACHINE_BUS_CARTRIDGE) /* sys has two cartridge bays */ /* Combined flags. */ #define MACHINE_PC (MACHINE_BUS_ISA) /* sys is PC/XT-compatible (ISA) */ #define MACHINE_AT (MACHINE_BUS_ISA | MACHINE_BUS_ISA16) /* sys is AT-compatible (ISA + ISA16) */ @@ -69,18 +66,18 @@ #define MACHINE_AGP (MACHINE_BUS_AGP | MACHINE_PCI) /* sys is AT-compatible with AGP */ #define MACHINE_AGP98 (MACHINE_BUS_AGP | MACHINE_PCI98) /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ -#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ -#define MACHINE_PCJR (MACHINE_PC | MACHINE_CASSETTE | MACHINE_CARTRIDGE) /* sys is PCjr */ -#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ -#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ -#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ -#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ -#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ -#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ -#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ -#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ -#define MACHINE_PS2_PCIONLY (MACHINE_PS2_NOISA & ~MACHINE_BUS_AGP) /* sys is PCI PS/2 without ISA */ -#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ +#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ +#define MACHINE_PCJR (MACHINE_PC | MACHINE_CASSETTE | MACHINE_BUS_SIDECAR) /* sys is PCjr */ +#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ +#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ +#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ +#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ +#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ +#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ +#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ +#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ +#define MACHINE_PS2_PCIONLY (MACHINE_PS2_NOISA & ~MACHINE_BUS_AGP) /* sys is PCI PS/2 without ISA */ +#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ /* Feature flags for miscellaneous internal devices. */ #define MACHINE_FLAGS_NONE 0x00000000 /* sys has no int devices */ #define MACHINE_SOFTFLOAT_ONLY 0x00000001 /* sys requires SoftFloat FPU */ @@ -93,7 +90,8 @@ #define MACHINE_LPT_PRI 0x00000080 /* sys has int pri LPT */ #define MACHINE_LPT_SEC 0x00000100 /* sys has int sec LPT */ #define MACHINE_LPT_TER 0x00000200 /* sys has int ter LPT */ -#define MACHINE_LPT_QUA 0x00000400 /* sys has int qua LPT */ +#define MACHINE_PS2_KBC 0x00000400 /* sys has a PS/2 keyboard controller */ + /* this is separate from having PS/2 ports */ #define MACHINE_UART_PRI 0x00000800 /* sys has int pri UART */ #define MACHINE_UART_SEC 0x00001000 /* sys has int sec UART */ #define MACHINE_UART_TER 0x00002000 /* sys has int ter UART */ @@ -106,7 +104,7 @@ #define MACHINE_APM 0x00080000 /* sys has APM */ #define MACHINE_ACPI 0x00100000 /* sys has ACPI */ #define MACHINE_HWM 0x00200000 /* sys has hw monitor */ -#define MACHINE_COREBOOT 0x00400000 /* sys has coreboot BIOS */ +#define MACHINE_CARTRIDGE 0x00400000 /* sys has cartridge bays */ /* Feature flags for internal storage controllers. */ #define MACHINE_MFM 0x00800000 /* sys has int MFM/RLL */ #define MACHINE_XTA 0x01000000 /* sys has int XTA */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e6198541e..765943fba 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8257,8 +8257,8 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_BUS_PS2_LATCH | MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -8337,8 +8337,8 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_BUS_PS2_LATCH | MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, .max = 261120, @@ -8539,8 +8539,8 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI | MACHINE_BUS_PS2_LATCH, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -9198,8 +9198,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_BUS_PS2_LATCH | MACHINE_PCI, - .flags = MACHINE_APM, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_APM, .ram = { .min = 2048, .max = 196608, @@ -16497,19 +16497,39 @@ machine_get_nvrmask(int m) int machine_has_flags(int m, int flags) { - return (machines[m].flags & flags); + int ret = machines[m].flags & flags; + + /* Can't have PS/2 ports with an AT KBC. */ + if ((flags & MACHINE_PS2_KBC) && + (machines[m].bus_flags & MACHINE_BUS_PS2_PORTS)) + ret |= MACHINE_PS2_KBC; + + return ret; } int machine_has_bus(int m, int bus_flags) { - return (machines[m].bus_flags & bus_flags); + int ret = machines[m].bus_flags & bus_flags; + + /* TODO: Move the KBD flags to the machine table! */ + if ((bus_flags & MACHINE_BUS_XT_KBD) && + !(machines[m].bus_flags & MACHINE_BUS_ISA16) && + !(machines[m].bus_flags & MACHINE_BUS_PS2_PORTS)) + ret |= MACHINE_BUS_XT_KBD; + + if ((bus_flags & MACHINE_BUS_AT_KBD) && + (IS_AT(m)) && + !(machines[m].bus_flags & MACHINE_BUS_PS2_PORTS)) + ret |= MACHINE_BUS_AT_KBD; + + return ret; } int machine_has_cartridge(int m) { - return (machine_has_bus(m, MACHINE_CARTRIDGE) ? 1 : 0); + return (machine_has_flags(m, MACHINE_CARTRIDGE) ? 1 : 0); } int diff --git a/src/pic.c b/src/pic.c index 7f6eda40d..cf17e8205 100644 --- a/src/pic.c +++ b/src/pic.c @@ -629,7 +629,7 @@ pic_reset_hard(void) /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, to the point that there's even boards with board-level latched that get used in place of the latches on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ - if (machine_has_bus(machine, MACHINE_BUS_PS2_LATCH)) { + if (machine_has_flags(machine, MACHINE_PS2_KBC)) { pic_kbd_latch(0x01); pic_mouse_latch(0x01); } else { From a72b3884b578bcb8d304ceac3da77c7fc30420a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 07:26:22 +0100 Subject: [PATCH 0254/1190] Fixed (S)VGA memory access bitness stuff. --- src/video/vid_svga.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index e68e4c1a0..7c674e00a 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1528,7 +1528,11 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->translate_address = NULL; svga->ksc5601_english_font_type = 0; - if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { + /* TODO: Move DEVICE_MCA to 16-bit once the device flags have been appropriately corrected. */ + if ((info->flags & DEVICE_MCA) || (info->flags & DEVICE_MCA32) || + (info->flags & DEVICE_EISA) || (info->flags & DEVICE_AT32) || + (info->flags & DEVICE_OLB) || (info->flags & DEVICE_VLB) || + (info->flags & DEVICE_PCI) || (info->flags & DEVICE_AGP)) { svga->read = svga_read; svga->readw = svga_readw; svga->readl = svga_readl; @@ -1539,7 +1543,8 @@ 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); - } else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_AT)) { + /* 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)) { svga->read = svga_read; svga->readw = svga_readw; svga->readl = NULL; From 2c197000ea78f0f6a20043febf89ea93e5ee34c4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 07:39:21 +0100 Subject: [PATCH 0255/1190] Removed the legacy #defines in device.h. --- src/cdrom/cdrom_mitsumi.c | 2 +- src/chipset/ali6117.c | 4 ++-- src/device.c | 10 +++++---- src/device/bugger.c | 2 +- src/device/keyboard_at.c | 2 +- src/device/mouse_ps2.c | 2 +- src/device/serial.c | 4 ++-- src/device/smbus_ali7101.c | 2 +- src/device/smbus_piix4.c | 4 ++-- src/device/smbus_sis5595.c | 2 +- src/disk/hdc_esdi_at.c | 2 +- src/disk/hdc_ide.c | 26 +++++++++++----------- src/disk/hdc_st506_at.c | 2 +- src/disk/hdc_xtide.c | 4 ++-- src/disk/lba_enhancer.c | 2 +- src/include/86box/device.h | 32 ++++++++++++--------------- src/include/86box/machine.h | 25 +++++++++++---------- src/ioapic.c | 2 +- src/machine/m_ps1_hdc.c | 2 +- src/mem/row.c | 2 +- src/network/net_ne2000.c | 8 +++---- src/network/net_pcnet.c | 8 +++---- src/nvr_at.c | 30 ++++++++++++------------- src/scsi/scsi_aha154x.c | 10 ++++----- src/scsi/scsi_buslogic.c | 8 +++---- src/sound/snd_azt2316a.c | 4 ++-- src/sound/snd_cs423x.c | 14 ++++++------ src/sound/snd_gus.c | 2 +- src/sound/snd_optimc.c | 4 ++-- src/sound/snd_pas16.c | 4 ++-- src/sound/snd_sb.c | 44 ++++++++++++++++++------------------- src/sound/snd_wss.c | 2 +- src/video/vid_8514a.c | 2 +- src/video/vid_ati_mach64.c | 2 +- src/video/vid_cl54xx.c | 22 +++++++++---------- src/video/vid_et4000w32.c | 6 ++--- src/video/vid_ht216.c | 2 +- src/video/vid_s3.c | 12 +++++----- src/video/vid_xga.c | 4 ++-- 39 files changed, 160 insertions(+), 161 deletions(-) diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c index 7ef8a04b2..e27faab94 100644 --- a/src/cdrom/cdrom_mitsumi.c +++ b/src/cdrom/cdrom_mitsumi.c @@ -459,7 +459,7 @@ mitsumi_cdrom_close(void *priv) const device_t mitsumi_cdrom_device = { .name = "Mitsumi CD-ROM interface", .internal_name = "mcd", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = mitsumi_cdrom_init, .close = mitsumi_cdrom_close, diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index c351a0cfa..707b528b2 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -493,7 +493,7 @@ ali6117_init(const device_t *info) const device_t ali1217_device = { .name = "ALi M1217", .internal_name = "ali1217", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x8, .init = ali6117_init, .close = ali6117_close, @@ -507,7 +507,7 @@ const device_t ali1217_device = { const device_t ali6117d_device = { .name = "ALi M6117D", .internal_name = "ali6117d", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x2, .init = ali6117_init, .close = ali6117_close, diff --git a/src/device.c b/src/device.c index 7cfa1d70e..ff81fe5e5 100644 --- a/src/device.c +++ b/src/device.c @@ -490,7 +490,7 @@ device_get_name(const device_t *dev, int bus, char *name) const char *sbus = NULL; const char *fbus; char *tname; - char pbus[11] = { 0 }; + char pbus[12] = { 0 }; if (dev == NULL) return; @@ -498,9 +498,9 @@ device_get_name(const device_t *dev, int bus, char *name) name[0] = 0x00; if (bus) { - if ((dev->flags & (DEVICE_PCJR | DEVICE_ISA)) == - (DEVICE_PCJR | DEVICE_ISA)) - sbus = "ISA/PCJR"; + if ((dev->flags & (DEVICE_SIDECAR | DEVICE_ISA)) == + (DEVICE_SIDECAR | DEVICE_ISA)) + sbus = "ISA/Sidecar"; else if (dev->flags & DEVICE_SIDECAR) sbus = "Sidecar"; else if (dev->flags & DEVICE_XT_KBC) @@ -519,6 +519,8 @@ device_get_name(const device_t *dev, int bus, char *name) sbus = "PCMCIA"; else if (dev->flags & DEVICE_MCA) sbus = "MCA"; + else if (dev->flags & DEVICE_MCA32) + sbus = "MCA32"; else if (dev->flags & DEVICE_HIL) sbus = "HP HIL"; else if (dev->flags & DEVICE_EISA) diff --git a/src/device/bugger.c b/src/device/bugger.c index 56cac91bc..b56937a43 100644 --- a/src/device/bugger.c +++ b/src/device/bugger.c @@ -346,7 +346,7 @@ bug_close(UNUSED(void *priv)) const device_t bugger_device = { .name = "ISA/PCI Bus Bugger", .internal_name = "bugger", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = bug_init, .close = bug_close, diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 589ec7ded..c3cc29b78 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2216,7 +2216,7 @@ static const device_config_t keyboard_at_config[] = { const device_t keyboard_at_generic_device = { .name = "Standard AT or PS/2 Keyboard", .internal_name = "ps2", - .flags = DEVICE_PS2, + .flags = DEVICE_PS2_KBC, .local = 0, .init = keyboard_at_init, .close = keyboard_at_close, diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 8d98b07ce..79d7afc96 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -394,7 +394,7 @@ static const device_config_t ps2_config[] = { const device_t mouse_ps2_device = { .name = "PS/2 Mouse", .internal_name = "ps2", - .flags = DEVICE_PS2, + .flags = DEVICE_PS2_KBC, .local = MOUSE_TYPE_PS2, .init = mouse_ps2_init, .close = ps2_close, diff --git a/src/device/serial.c b/src/device/serial.c index 823d07c1f..c25da0070 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -948,7 +948,7 @@ serial_init(const device_t *info) serial_setup(dev, COM4_ADDR, COM4_IRQ); else if (next_inst == 2) serial_setup(dev, COM3_ADDR, COM3_IRQ); - else if ((next_inst == 1) || (info->flags & DEVICE_PCJR)) + else if ((next_inst == 1) || (info->local == SERIAL_8250_PCJR)) serial_setup(dev, COM2_ADDR, COM2_IRQ); else if (next_inst == 0) serial_setup(dev, COM1_ADDR, COM1_IRQ); @@ -1018,7 +1018,7 @@ const device_t ns8250_device = { const device_t ns8250_pcjr_device = { .name = "National Semiconductor 8250(-compatible) UART for PCjr", .internal_name = "ns8250_pcjr", - .flags = DEVICE_PCJR, + .flags = 0, .local = SERIAL_8250_PCJR, .init = serial_init, .close = serial_close, diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index 3907a065e..49eb44bc6 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -302,7 +302,7 @@ smbus_ali7101_close(void *priv) const device_t ali7101_smbus_device = { .name = "ALi M7101-compatible SMBus Host Controller", .internal_name = "ali7101_smbus", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = smbus_ali7101_init, .close = smbus_ali7101_close, diff --git a/src/device/smbus_piix4.c b/src/device/smbus_piix4.c index a9ffcd847..ae37c72c4 100644 --- a/src/device/smbus_piix4.c +++ b/src/device/smbus_piix4.c @@ -386,7 +386,7 @@ smbus_piix4_close(void *priv) const device_t piix4_smbus_device = { .name = "PIIX4-compatible SMBus Host Controller", .internal_name = "piix4_smbus", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = SMBUS_PIIX4, .init = smbus_piix4_init, .close = smbus_piix4_close, @@ -400,7 +400,7 @@ const device_t piix4_smbus_device = { const device_t via_smbus_device = { .name = "VIA VT82C686B SMBus Host Controller", .internal_name = "via_smbus", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = SMBUS_VIA, .init = smbus_piix4_init, .close = smbus_piix4_close, diff --git a/src/device/smbus_sis5595.c b/src/device/smbus_sis5595.c index 0a24d2355..42d1452ad 100644 --- a/src/device/smbus_sis5595.c +++ b/src/device/smbus_sis5595.c @@ -373,7 +373,7 @@ smbus_sis5595_close(void *priv) const device_t sis5595_smbus_device = { .name = "SiS 5595-compatible SMBus Host Controller", .internal_name = "sis5595_smbus", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = smbus_sis5595_init, .close = smbus_sis5595_close, diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index adc39d509..ab24aa6fa 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -984,7 +984,7 @@ wd1007vse1_available(void) const device_t esdi_at_wd1007vse1_device = { .name = "Western Digital WD1007V-SE1 (ESDI)", .internal_name = "esdi_at", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = wd1007vse1_init, .close = wd1007vse1_close, diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 3683c8671..b69ddf128 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3282,7 +3282,7 @@ mcide_close(void *priv) const device_t ide_isa_device = { .name = "ISA PC/AT IDE Controller", .internal_name = "ide_isa", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = ide_init, .close = ide_close, @@ -3296,7 +3296,7 @@ const device_t ide_isa_device = { const device_t ide_isa_sec_device = { .name = "ISA PC/AT IDE Controller (Secondary)", .internal_name = "ide_isa_sec", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = ide_sec_init, .close = ide_sec_close, @@ -3310,7 +3310,7 @@ const device_t ide_isa_sec_device = { const device_t ide_isa_2ch_device = { .name = "ISA PC/AT IDE Controller (Dual-Channel)", .internal_name = "ide_isa_2ch", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 1, .init = ide_init, .close = ide_close, @@ -3324,7 +3324,7 @@ const device_t ide_isa_2ch_device = { const device_t ide_vlb_device = { .name = "VLB IDE Controller", .internal_name = "ide_vlb", - .flags = DEVICE_VLB | DEVICE_AT, + .flags = DEVICE_VLB | DEVICE_ISA16, .local = 2, .init = ide_init, .close = ide_close, @@ -3338,7 +3338,7 @@ const device_t ide_vlb_device = { const device_t ide_vlb_sec_device = { .name = "VLB IDE Controller (Secondary)", .internal_name = "ide_vlb_sec", - .flags = DEVICE_VLB | DEVICE_AT, + .flags = DEVICE_VLB | DEVICE_ISA16, .local = 2, .init = ide_sec_init, .close = ide_sec_close, @@ -3352,7 +3352,7 @@ const device_t ide_vlb_sec_device = { const device_t ide_vlb_2ch_device = { .name = "VLB IDE Controller (Dual-Channel)", .internal_name = "ide_vlb_2ch", - .flags = DEVICE_VLB | DEVICE_AT, + .flags = DEVICE_VLB | DEVICE_ISA16, .local = 3, .init = ide_init, .close = ide_close, @@ -3366,7 +3366,7 @@ const device_t ide_vlb_2ch_device = { const device_t ide_pci_device = { .name = "PCI IDE Controller", .internal_name = "ide_pci", - .flags = DEVICE_PCI | DEVICE_AT, + .flags = DEVICE_PCI | DEVICE_ISA16, .local = 4, .init = ide_init, .close = ide_close, @@ -3380,7 +3380,7 @@ const device_t ide_pci_device = { const device_t ide_pci_sec_device = { .name = "PCI IDE Controller (Secondary)", .internal_name = "ide_pci_sec", - .flags = DEVICE_PCI | DEVICE_AT, + .flags = DEVICE_PCI | DEVICE_ISA16, .local = 4, .init = ide_sec_init, .close = ide_sec_close, @@ -3394,7 +3394,7 @@ const device_t ide_pci_sec_device = { const device_t ide_pci_2ch_device = { .name = "PCI IDE Controller (Dual-Channel)", .internal_name = "ide_pci_2ch", - .flags = DEVICE_PCI | DEVICE_AT, + .flags = DEVICE_PCI | DEVICE_ISA16, .local = 5, .init = ide_init, .close = ide_close, @@ -3478,7 +3478,7 @@ static const device_config_t ide_qua_config[] = { const device_t ide_ter_device = { .name = "Tertiary IDE Controller", .internal_name = "ide_ter", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = ide_ter_init, .close = ide_ter_close, @@ -3492,7 +3492,7 @@ const device_t ide_ter_device = { const device_t ide_ter_pnp_device = { .name = "Tertiary IDE Controller (Plug and Play only)", .internal_name = "ide_ter_pnp", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 1, .init = ide_ter_init, .close = ide_ter_close, @@ -3506,7 +3506,7 @@ const device_t ide_ter_pnp_device = { const device_t ide_qua_device = { .name = "Quaternary IDE Controller", .internal_name = "ide_qua", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = ide_qua_init, .close = ide_qua_close, @@ -3520,7 +3520,7 @@ const device_t ide_qua_device = { const device_t ide_qua_pnp_device = { .name = "Quaternary IDE Controller (Plug and Play only)", .internal_name = "ide_qua_pnp", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 1, .init = ide_qua_init, .close = ide_qua_close, diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index eeb242a94..07c57b2ca 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -795,7 +795,7 @@ mfm_close(void *priv) const device_t st506_at_wd1003_device = { .name = "WD1003 AT MFM/RLL Controller", .internal_name = "st506_at", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = mfm_init, .close = mfm_close, diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 4c071e596..c18a24c4e 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -312,7 +312,7 @@ const device_t xtide_device = { const device_t xtide_at_device = { .name = "PC/AT XTIDE", .internal_name = "xtide_at", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = xtide_at_init, .close = xtide_at_close, @@ -340,7 +340,7 @@ const device_t xtide_acculogic_device = { const device_t xtide_at_ps2_device = { .name = "PS/2 AT XTIDE (1.1.5)", .internal_name = "xtide_at_ps2", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = xtide_at_ps2_init, .close = xtide_at_close, diff --git a/src/disk/lba_enhancer.c b/src/disk/lba_enhancer.c index 429611b2d..ef9e167d3 100644 --- a/src/disk/lba_enhancer.c +++ b/src/disk/lba_enhancer.c @@ -88,7 +88,7 @@ static const device_config_t lba_enhancer_config[] = { const device_t lba_enhancer_device = { .name = "Vision Systems LBA Enhancer", .internal_name = "lba_enhancer", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = lba_enhancer_init, .close = lba_enhancer_close, diff --git a/src/include/86box/device.h b/src/include/86box/device.h index d074cc2fc..584f0f069 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -86,19 +86,20 @@ enum { DEVICE_ISA16 = 0x20, /* requires an AT-compatible system */ DEVICE_AT_KBC = 0x40, /* requires an AT-compatible keyboard controller */ DEVICE_MCA = 0x80, /* requires the MCA bus */ - DEVICE_PS2_KBC = 0x100, /* requires a PS/1 or PS/2 system */ - DEVICE_PCMCIA = 0x200, /* requires the PCMCIA bus */ - DEVICE_HIL = 0x400, /* requires the HP HIL bus */ - DEVICE_EISA = 0x800, /* requires the EISA bus */ - DEVICE_AT32 = 0x1000, /* requires the Mylex AT/32 local bus */ - DEVICE_OLB = 0x2000, /* requires the OPTi local bus */ - DEVICE_VLB = 0x4000, /* requires the VLB bus */ - DEVICE_PCI = 0x8000, /* requires the PCI bus */ - DEVICE_CARDBUS = 0x10000, /* requires the CardBus bus */ - DEVICE_USB = 0x20000, /* requires the USB bus */ - DEVICE_AGP = 0x40000, /* requires the AGP bus */ - DEVICE_AC97 = 0x80000, /* requires the AC'97 bus */ - DEVICE_BUS = 0xfffff, /* requires a machine bus */ + DEVICE_MCA32 = 0x100, /* requires the MCA bus */ + DEVICE_PS2_KBC = 0x200, /* requires a PS/1 or PS/2 system */ + DEVICE_PCMCIA = 0x400, /* requires the PCMCIA bus */ + DEVICE_HIL = 0x800, /* requires the HP HIL bus */ + DEVICE_EISA = 0x1000, /* requires the EISA bus */ + DEVICE_AT32 = 0x2000, /* requires the Mylex AT/32 local bus */ + DEVICE_OLB = 0x4000, /* requires the OPTi local bus */ + DEVICE_VLB = 0x8000, /* requires the VLB bus */ + DEVICE_PCI = 0x10000, /* requires the PCI bus */ + DEVICE_CARDBUS = 0x20000, /* requires the CardBus bus */ + DEVICE_USB = 0x40000, /* requires the USB bus */ + DEVICE_AGP = 0x80000, /* requires the AGP bus */ + DEVICE_AC97 = 0x100000, /* requires the AC'97 bus */ + DEVICE_BUS = 0xffffff, /* requires a machine bus */ DEVICE_COM = 0x100000, /* requires a serial port */ DEVICE_LPT = 0x200000, /* requires a parallel port */ @@ -112,11 +113,6 @@ enum { DEVICE_ALL = 0xffffffff /* match all devices */ }; -/* TODO: Remove this once all the devices' flags have been updated. */ -#define DEVICE_AT DEVICE_ISA16 -#define DEVICE_PCJR DEVICE_SIDECAR -#define DEVICE_PS2 DEVICE_PS2_KBC - #define BIOS_NORMAL 0 #define BIOS_INTERLEAVED 1 #define BIOS_INTERLEAVED_SINGLEFILE 2 diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 2c5440438..bf4954ae9 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -33,19 +33,20 @@ #define MACHINE_BUS_ISA16 0x00000020 /* sys has ISA16 bus - PC/AT architecture */ #define MACHINE_BUS_AT_KBD 0x00000040 /* sys has an AT keyboard port */ #define MACHINE_BUS_MCA 0x00000080 /* sys has MCA bus */ -#define MACHINE_BUS_PS2_PORTS 0x00000100 /* system has PS/2 keyboard and mouse ports */ +#define MACHINE_BUS_MCA32 0x00000100 /* sys has MCA32 bus */ +#define MACHINE_BUS_PS2_PORTS 0x00000200 /* system has PS/2 keyboard and mouse ports */ #define MACHINE_BUS_PS2 MACHINE_BUS_PS2_PORTS -#define MACHINE_BUS_PCMCIA 0x00000200 /* sys has PCMCIA bus */ -#define MACHINE_BUS_HIL 0x00000400 /* system has HP HIL keyboard and mouse ports */ -#define MACHINE_BUS_EISA 0x00000800 /* sys has EISA bus */ -#define MACHINE_BUS_AT32 0x00001000 /* sys has Mylex AT/32 local bus */ -#define MACHINE_BUS_OLB 0x00002000 /* sys has OPTi local bus */ -#define MACHINE_BUS_VLB 0x00004000 /* sys has VL bus */ -#define MACHINE_BUS_PCI 0x00008000 /* sys has PCI bus */ -#define MACHINE_BUS_CARDBUS 0x00010000 /* sys has CardBus bus */ -#define MACHINE_BUS_USB 0x00020000 /* sys has USB bus */ -#define MACHINE_BUS_AGP 0x00040000 /* sys has AGP bus */ -#define MACHINE_BUS_AC97 0x00080000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ +#define MACHINE_BUS_PCMCIA 0x00000400 /* sys has PCMCIA bus */ +#define MACHINE_BUS_HIL 0x00000800 /* system has HP HIL keyboard and mouse ports */ +#define MACHINE_BUS_EISA 0x00001000 /* sys has EISA bus */ +#define MACHINE_BUS_AT32 0x00002000 /* sys has Mylex AT/32 local bus */ +#define MACHINE_BUS_OLB 0x00004000 /* sys has OPTi local bus */ +#define MACHINE_BUS_VLB 0x00008000 /* sys has VL bus */ +#define MACHINE_BUS_PCI 0x00010000 /* sys has PCI bus */ +#define MACHINE_BUS_CARDBUS 0x00020000 /* sys has CardBus bus */ +#define MACHINE_BUS_USB 0x00040000 /* sys has USB bus */ +#define MACHINE_BUS_AGP 0x00080000 /* sys has AGP bus */ +#define MACHINE_BUS_AC97 0x00100000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ /* Aliases. */ #define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ /* Combined flags. */ diff --git a/src/ioapic.c b/src/ioapic.c index b5ca4c7a7..ea0811f91 100644 --- a/src/ioapic.c +++ b/src/ioapic.c @@ -117,7 +117,7 @@ ioapic_init(UNUSED(const device_t *info)) const device_t ioapic_device = { .name = "I/O Advanced Programmable Interrupt Controller", .internal_name = "ioapic", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = ioapic_init, .close = ioapic_close, diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index d407953b4..18792ded7 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -1380,7 +1380,7 @@ ps1_hdc_close(void *priv) const device_t ps1_hdc_device = { .name = "PS/1 2011 Fixed Disk Controller", .internal_name = "ps1_hdc", - .flags = DEVICE_ISA | DEVICE_PS2, + .flags = DEVICE_ISA, .local = 0, .init = ps1_hdc_init, .close = ps1_hdc_close, diff --git a/src/mem/row.c b/src/mem/row.c index 633d0e31a..c3e10841f 100644 --- a/src/mem/row.c +++ b/src/mem/row.c @@ -336,7 +336,7 @@ row_init(const device_t *info) device_t row_device = { .name = "DRAM Rows", .internal_name = "dram_rows", - .flags = DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x0000, .init = row_init, .close = row_close, diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index dd3a12047..71e5c2ca7 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -1714,7 +1714,7 @@ const device_t ne1000_compat_device = { const device_t ne2000_device = { .name = "Novell NE2000", .internal_name = "novell_ne2k", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = NE2K_NE2000, .init = nic_init, .close = nic_close, @@ -1728,7 +1728,7 @@ const device_t ne2000_device = { const device_t ne2000_compat_device = { .name = "NE2000 Compatible", .internal_name = "ne2k", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = NE2K_NE2000_COMPAT, .init = nic_init, .close = nic_close, @@ -1770,7 +1770,7 @@ const device_t ethernext_mc_device = { const device_t rtl8019as_pnp_device = { .name = "Realtek RTL8019AS", .internal_name = "ne2kpnp", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = NE2K_RTL8019AS_PNP, .init = nic_init, .close = nic_close, @@ -1784,7 +1784,7 @@ const device_t rtl8019as_pnp_device = { const device_t de220p_device = { .name = "D-Link DE-220P", .internal_name = "de220p", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = NE2K_DE220P, .init = nic_init, .close = nic_close, diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 3272033cf..b13fd8438 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -2922,7 +2922,7 @@ pcnet_init(const device_t *info) dev->is_pci = !!(info->flags & DEVICE_PCI); dev->is_vlb = !!(info->flags & DEVICE_VLB); - dev->is_isa = !!(info->flags & (DEVICE_ISA | DEVICE_AT)); + dev->is_isa = !!(info->flags & (DEVICE_ISA16)); if (dev->is_pci || dev->is_vlb) dev->transfer_size = 4; @@ -3231,7 +3231,7 @@ static const device_config_t pcnet_vlb_config[] = { const device_t pcnet_am79c960_device = { .name = "AMD PCnet-ISA", .internal_name = "pcnetisa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = DEV_AM79C960, .init = pcnet_init, .close = pcnet_close, @@ -3245,7 +3245,7 @@ const device_t pcnet_am79c960_device = { const device_t pcnet_am79c960_eb_device = { .name = "Racal Interlan EtherBlaster", .internal_name = "pcnetracal", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = DEV_AM79C960_EB, .init = pcnet_init, .close = pcnet_close, @@ -3273,7 +3273,7 @@ const device_t pcnet_am79c960_vlb_device = { const device_t pcnet_am79c961_device = { .name = "AMD PCnet-ISA+", .internal_name = "pcnetisaplus", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = DEV_AM79C961, .init = pcnet_init, .close = pcnet_close, diff --git a/src/nvr_at.c b/src/nvr_at.c index 147795f8e..bde80b434 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -1219,7 +1219,7 @@ nvr_at_close(void *priv) const device_t at_nvr_old_device = { .name = "PC/AT NVRAM (No century)", .internal_name = "at_nvr_old", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = nvr_at_init, .close = nvr_at_close, @@ -1233,7 +1233,7 @@ const device_t at_nvr_old_device = { const device_t at_nvr_device = { .name = "PC/AT NVRAM", .internal_name = "at_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 1, .init = nvr_at_init, .close = nvr_at_close, @@ -1247,7 +1247,7 @@ const device_t at_nvr_device = { const device_t at_mb_nvr_device = { .name = "PC/AT NVRAM", .internal_name = "at_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x40 | 0x20 | 1, .init = nvr_at_init, .close = nvr_at_close, @@ -1261,7 +1261,7 @@ const device_t at_mb_nvr_device = { const device_t ps_nvr_device = { .name = "PS/1 or PS/2 NVRAM", .internal_name = "ps_nvr", - .flags = DEVICE_PS2, + .flags = DEVICE_ISA16, .local = 2, .init = nvr_at_init, .close = nvr_at_close, @@ -1275,7 +1275,7 @@ const device_t ps_nvr_device = { const device_t amstrad_nvr_device = { .name = "Amstrad NVRAM", .internal_name = "amstrad_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 3, .init = nvr_at_init, .close = nvr_at_close, @@ -1289,7 +1289,7 @@ const device_t amstrad_nvr_device = { const device_t ibmat_nvr_device = { .name = "IBM AT NVRAM", .internal_name = "ibmat_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 4, .init = nvr_at_init, .close = nvr_at_close, @@ -1303,7 +1303,7 @@ const device_t ibmat_nvr_device = { const device_t piix4_nvr_device = { .name = "Intel PIIX4 PC/AT NVRAM", .internal_name = "piix4_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x10 | 1, .init = nvr_at_init, .close = nvr_at_close, @@ -1317,7 +1317,7 @@ const device_t piix4_nvr_device = { const device_t ps_no_nmi_nvr_device = { .name = "PS/1 or PS/2 NVRAM (No NMI)", .internal_name = "ps1_nvr", - .flags = DEVICE_PS2, + .flags = DEVICE_ISA16, .local = 0x10 | 2, .init = nvr_at_init, .close = nvr_at_close, @@ -1331,7 +1331,7 @@ const device_t ps_no_nmi_nvr_device = { const device_t amstrad_no_nmi_nvr_device = { .name = "Amstrad NVRAM (No NMI)", .internal_name = "amstrad_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x10 | 3, .init = nvr_at_init, .close = nvr_at_close, @@ -1345,7 +1345,7 @@ const device_t amstrad_no_nmi_nvr_device = { const device_t ami_1992_nvr_device = { .name = "AMI Color 1992 PC/AT NVRAM", .internal_name = "ami_1992_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x10 | 4, .init = nvr_at_init, .close = nvr_at_close, @@ -1359,7 +1359,7 @@ const device_t ami_1992_nvr_device = { const device_t ami_1994_nvr_device = { .name = "AMI WinBIOS 1994 PC/AT NVRAM", .internal_name = "ami_1994_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x10 | 5, .init = nvr_at_init, .close = nvr_at_close, @@ -1373,7 +1373,7 @@ const device_t ami_1994_nvr_device = { const device_t ami_1995_nvr_device = { .name = "AMI WinBIOS 1995 PC/AT NVRAM", .internal_name = "ami_1995_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x10 | 6, .init = nvr_at_init, .close = nvr_at_close, @@ -1387,7 +1387,7 @@ const device_t ami_1995_nvr_device = { const device_t via_nvr_device = { .name = "VIA PC/AT NVRAM", .internal_name = "via_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x10 | 7, .init = nvr_at_init, .close = nvr_at_close, @@ -1401,7 +1401,7 @@ const device_t via_nvr_device = { const device_t p6rp4_nvr_device = { .name = "ASUS P/I-P6RP4 PC/AT NVRAM", .internal_name = "p6rp4_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 32, .init = nvr_at_init, .close = nvr_at_close, @@ -1415,7 +1415,7 @@ const device_t p6rp4_nvr_device = { const device_t amstrad_megapc_nvr_device = { .name = "Amstrad MegaPC NVRAM", .internal_name = "amstrad_megapc_nvr", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 36, .init = nvr_at_init, .close = nvr_at_close, diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 4f3d1d1e7..7c887e28b 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1473,7 +1473,7 @@ static const device_config_t aha_154xcp_config[] = { const device_t aha154xa_device = { .name = "Adaptec AHA-154xA", .internal_name = "aha154xa", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = AHA_154xA, .init = aha_init, .close = x54x_close, @@ -1487,7 +1487,7 @@ const device_t aha154xa_device = { const device_t aha154xb_device = { .name = "Adaptec AHA-154xB", .internal_name = "aha154xb", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = AHA_154xB, .init = aha_init, .close = x54x_close, @@ -1501,7 +1501,7 @@ const device_t aha154xb_device = { const device_t aha154xc_device = { .name = "Adaptec AHA-154xC", .internal_name = "aha154xc", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = AHA_154xC, .init = aha_init, .close = x54x_close, @@ -1515,7 +1515,7 @@ const device_t aha154xc_device = { const device_t aha154xcf_device = { .name = "Adaptec AHA-154xCF", .internal_name = "aha154xcf", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = AHA_154xCF, .init = aha_init, .close = x54x_close, @@ -1529,7 +1529,7 @@ const device_t aha154xcf_device = { const device_t aha154xcp_device = { .name = "Adaptec AHA-154xCP", .internal_name = "aha154xcp", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = AHA_154xCP, .init = aha_init, .close = aha1542cp_close, diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index c4745e2df..9fe34380b 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1872,7 +1872,7 @@ static const device_config_t BT958D_Config[] = { const device_t buslogic_542b_device = { .name = "BusLogic BT-542B ISA", .internal_name = "bt542b", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CHIP_BUSLOGIC_ISA_542B_1991_12_14, .init = buslogic_init, .close = x54x_close, @@ -1886,7 +1886,7 @@ const device_t buslogic_542b_device = { const device_t buslogic_545s_device = { .name = "BusLogic BT-545S ISA", .internal_name = "bt545s", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CHIP_BUSLOGIC_ISA_545S_1992_10_05, .init = buslogic_init, .close = x54x_close, @@ -1900,7 +1900,7 @@ const device_t buslogic_545s_device = { const device_t buslogic_542bh_device = { .name = "BusLogic BT-542BH ISA", .internal_name = "bt542bh", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CHIP_BUSLOGIC_ISA_542BH_1993_05_23, .init = buslogic_init, .close = x54x_close, @@ -1914,7 +1914,7 @@ const device_t buslogic_542bh_device = { const device_t buslogic_545c_device = { .name = "BusLogic BT-545C ISA", .internal_name = "bt545c", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CHIP_BUSLOGIC_ISA_545C_1994_12_01, .init = buslogic_init, .close = x54x_close, diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index ea682a82c..76bf1b24f 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1557,7 +1557,7 @@ static const device_config_t azt2316a_config[] = { const device_t azt2316a_device = { .name = "Aztech Sound Galaxy Pro 16 AB (Washington)", .internal_name = "azt2316a", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_SUBTYPE_CLONE_AZT2316A_0X11, .init = azt_init, .close = azt_close, @@ -1571,7 +1571,7 @@ const device_t azt2316a_device = { const device_t azt1605_device = { .name = "Aztech Sound Galaxy Nova 16 Extra (Clinton)", .internal_name = "azt1605", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_SUBTYPE_CLONE_AZT1605_0X0C, .init = azt_init, .close = azt_close, diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index f5458eaf0..17ea48dd3 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -1061,7 +1061,7 @@ cs423x_speed_changed(void *priv) const device_t cs4235_device = { .name = "Crystal CS4235", .internal_name = "cs4235", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4235, .init = cs423x_init, .close = cs423x_close, @@ -1075,7 +1075,7 @@ const device_t cs4235_device = { const device_t cs4235_onboard_device = { .name = "Crystal CS4235 (On-Board)", .internal_name = "cs4235_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4235 | CRYSTAL_NOEEPROM, .init = cs423x_init, .close = cs423x_close, @@ -1089,7 +1089,7 @@ const device_t cs4235_onboard_device = { const device_t cs4236_onboard_device = { .name = "Crystal CS4236 (On-Board)", .internal_name = "cs4236_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4236 | CRYSTAL_NOEEPROM, .init = cs423x_init, .close = cs423x_close, @@ -1103,7 +1103,7 @@ const device_t cs4236_onboard_device = { const device_t cs4236b_device = { .name = "Crystal CS4236B", .internal_name = "cs4236b", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4236B, .init = cs423x_init, .close = cs423x_close, @@ -1117,7 +1117,7 @@ const device_t cs4236b_device = { const device_t cs4236b_onboard_device = { .name = "Crystal CS4236B", .internal_name = "cs4236b", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4236B | CRYSTAL_NOEEPROM, .init = cs423x_init, .close = cs423x_close, @@ -1131,7 +1131,7 @@ const device_t cs4236b_onboard_device = { const device_t cs4237b_device = { .name = "Crystal CS4237B", .internal_name = "cs4237b", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4237B, .init = cs423x_init, .close = cs423x_close, @@ -1145,7 +1145,7 @@ const device_t cs4237b_device = { const device_t cs4238b_device = { .name = "Crystal CS4238B", .internal_name = "cs4238b", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = CRYSTAL_CS4238B, .init = cs423x_init, .close = cs423x_close, diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index f2651c72f..43638473c 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1500,7 +1500,7 @@ static const device_config_t gus_config[] = { const device_t gus_device = { .name = "Gravis UltraSound", .internal_name = "gus", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = gus_init, .close = gus_close, diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index d5c01dbaf..d0b05741a 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -484,7 +484,7 @@ static const device_config_t optimc_config[] = { const device_t acermagic_s20_device = { .name = "AcerMagic S20", .internal_name = "acermagic_s20", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0xE3 | OPTIMC_CS4231, .init = optimc_init, .close = optimc_close, @@ -498,7 +498,7 @@ const device_t acermagic_s20_device = { const device_t mirosound_pcm10_device = { .name = "miroSOUND PCM10", .internal_name = "mirosound_pcm10", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0xE3 | OPTIMC_OPL4, .init = optimc_init, .close = optimc_close, diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index ddb135357..353f9a3d5 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -2453,7 +2453,7 @@ const device_t pasplus_device = { const device_t pas16_device = { .name = "Pro Audio Spectrum 16", .internal_name = "pas16", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x0f, .init = pas16_init, .close = pas16_close, @@ -2467,7 +2467,7 @@ const device_t pas16_device = { const device_t pas16d_device = { .name = "Pro Audio Spectrum 16D", .internal_name = "pas16d", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x0c, .init = pas16_init, .close = pas16_close, diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index ca233b252..4f8b8a0bd 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -5476,7 +5476,7 @@ const device_t sb_pro_mcv_device = { const device_t sb_pro_compat_device = { .name = "Sound Blaster Pro (Compatibility)", .internal_name = "sbpro_compat", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = sb_pro_compat_init, .close = sb_close, @@ -5490,7 +5490,7 @@ const device_t sb_pro_compat_device = { const device_t sb_16_device = { .name = "Sound Blaster 16", .internal_name = "sb16", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = FM_YMF262, .init = sb_16_init, .close = sb_close, @@ -5504,7 +5504,7 @@ const device_t sb_16_device = { const device_t sb_vibra16c_onboard_device = { .name = "Sound Blaster ViBRA 16C (On-Board)", .internal_name = "sb_vibra16c_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_VIBRA16C, .init = sb_vibra16_pnp_init, .close = sb_close, @@ -5518,7 +5518,7 @@ const device_t sb_vibra16c_onboard_device = { const device_t sb_vibra16c_device = { .name = "Sound Blaster ViBRA 16C", .internal_name = "sb_vibra16c", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_VIBRA16C, .init = sb_vibra16_pnp_init, .close = sb_close, @@ -5532,7 +5532,7 @@ const device_t sb_vibra16c_device = { const device_t sb_vibra16cl_onboard_device = { .name = "Sound Blaster ViBRA 16CL (On-Board)", .internal_name = "sb_vibra16cl_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_VIBRA16CL, .init = sb_vibra16_pnp_init, .close = sb_close, @@ -5546,7 +5546,7 @@ const device_t sb_vibra16cl_onboard_device = { const device_t sb_vibra16cl_device = { .name = "Sound Blaster ViBRA 16CL", .internal_name = "sb_vibra16cl", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_VIBRA16CL, .init = sb_vibra16_pnp_init, .close = sb_close, @@ -5560,7 +5560,7 @@ const device_t sb_vibra16cl_device = { const device_t sb_vibra16s_onboard_device = { .name = "Sound Blaster ViBRA 16S (On-Board)", .internal_name = "sb_vibra16s_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = FM_YMF289B, .init = sb_16_init, .close = sb_close, @@ -5574,7 +5574,7 @@ const device_t sb_vibra16s_onboard_device = { const device_t sb_vibra16s_device = { .name = "Sound Blaster ViBRA 16S", .internal_name = "sb_vibra16s", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = FM_YMF289B, .init = sb_16_init, .close = sb_close, @@ -5588,7 +5588,7 @@ const device_t sb_vibra16s_device = { const device_t sb_vibra16xv_onboard_device = { .name = "Sound Blaster ViBRA 16XV (On-Board)", .internal_name = "sb_vibra16xv_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_VIBRA16XV, .init = sb_vibra16_pnp_init, .close = sb_close, @@ -5602,7 +5602,7 @@ const device_t sb_vibra16xv_onboard_device = { const device_t sb_vibra16xv_device = { .name = "Sound Blaster ViBRA 16XV", .internal_name = "sb_vibra16xv", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_VIBRA16XV, .init = sb_vibra16_pnp_init, .close = sb_close, @@ -5630,7 +5630,7 @@ const device_t sb_16_reply_mca_device = { const device_t sb_16_pnp_device = { .name = "Sound Blaster 16 PnP", .internal_name = "sb16_pnp", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_16_PNP_NOIDE, .init = sb_16_pnp_init, .close = sb_close, @@ -5644,7 +5644,7 @@ const device_t sb_16_pnp_device = { const device_t sb_16_pnp_ide_device = { .name = "Sound Blaster 16 PnP (IDE)", .internal_name = "sb16_pnp_ide", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_16_PNP_IDE, .init = sb_16_pnp_init, .close = sb_close, @@ -5658,7 +5658,7 @@ const device_t sb_16_pnp_ide_device = { const device_t sb_16_compat_device = { .name = "Sound Blaster 16 (Compatibility)", .internal_name = "sb16_compat", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 1, .init = sb_16_compat_init, .close = sb_close, @@ -5672,7 +5672,7 @@ const device_t sb_16_compat_device = { const device_t sb_16_compat_nompu_device = { .name = "Sound Blaster 16 (Compatibility - MPU-401 Off)", .internal_name = "sb16_compat", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = sb_16_compat_init, .close = sb_close, @@ -5686,7 +5686,7 @@ const device_t sb_16_compat_nompu_device = { const device_t sb_goldfinch_device = { .name = "Creative EMU8000 PnP (Goldfinch)", .internal_name = "sb_goldfinch", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = sb_goldfinch_init, .close = sb_goldfinch_close, @@ -5700,7 +5700,7 @@ const device_t sb_goldfinch_device = { const device_t sb_32_pnp_device = { .name = "Sound Blaster 32 PnP", .internal_name = "sb32_pnp", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_32_PNP, .init = sb_awe32_pnp_init, .close = sb_awe32_close, @@ -5714,7 +5714,7 @@ const device_t sb_32_pnp_device = { const device_t sb_awe32_device = { .name = "Sound Blaster AWE32", .internal_name = "sbawe32", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = sb_awe32_init, .close = sb_awe32_close, @@ -5728,7 +5728,7 @@ const device_t sb_awe32_device = { const device_t sb_awe32_pnp_device = { .name = "Sound Blaster AWE32 PnP", .internal_name = "sbawe32_pnp", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_AWE32_PNP, .init = sb_awe32_pnp_init, .close = sb_awe32_close, @@ -5742,7 +5742,7 @@ const device_t sb_awe32_pnp_device = { const device_t sb_awe64_value_device = { .name = "Sound Blaster AWE64 Value", .internal_name = "sbawe64_value", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_AWE64_VALUE, .init = sb_awe32_pnp_init, .close = sb_awe32_close, @@ -5756,7 +5756,7 @@ const device_t sb_awe64_value_device = { const device_t sb_awe64_device = { .name = "Sound Blaster AWE64", .internal_name = "sbawe64", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_AWE64_NOIDE, .init = sb_awe32_pnp_init, .close = sb_awe32_close, @@ -5770,7 +5770,7 @@ const device_t sb_awe64_device = { const device_t sb_awe64_ide_device = { .name = "Sound Blaster AWE64 (IDE)", .internal_name = "sbawe64_ide", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_AWE64_IDE, .init = sb_awe32_pnp_init, .close = sb_awe32_close, @@ -5784,7 +5784,7 @@ const device_t sb_awe64_ide_device = { const device_t sb_awe64_gold_device = { .name = "Sound Blaster AWE64 Gold", .internal_name = "sbawe64_gold", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = SB_AWE64_GOLD, .init = sb_awe32_pnp_init, .close = sb_awe32_close, diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index c55e5f57b..874638a80 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -279,7 +279,7 @@ static const device_config_t wss_config[] = { const device_t wss_device = { .name = "Windows Sound System", .internal_name = "wss", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = wss_init, .close = wss_close, diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 09b054895..379772820 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -4072,7 +4072,7 @@ static const device_config_t mca_ext8514_config[] = { const device_t gen8514_isa_device = { .name = "IBM 8514/A clone (ISA)", .internal_name = "8514_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = 0, .init = ibm8514_init, .close = ibm8514_close, diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 9b7a67f31..9499f4ecc 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -4752,7 +4752,7 @@ static const device_config_t mach64vt2_config[] = { const device_t mach64gx_isa_device = { .name = "ATI Mach64GX ISA", .internal_name = "mach64gx_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = 0, .init = mach64gx_init, .close = mach64_close, diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 19f51bd9d..73be7cd76 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4887,7 +4887,7 @@ const device_t gd5402_isa_device = { const device_t gd5402_onboard_device = { .name = "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2) (On-Board)", .internal_name = "cl_gd5402_onboard", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5402 | 0x200, .init = gd54xx_init, .close = gd54xx_close, @@ -4901,7 +4901,7 @@ const device_t gd5402_onboard_device = { const device_t gd5420_isa_device = { .name = "Cirrus Logic GD5420 (ISA)", .internal_name = "cl_gd5420_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5420, .init = gd54xx_init, .close = gd54xx_close, @@ -4915,7 +4915,7 @@ const device_t gd5420_isa_device = { const device_t gd5422_isa_device = { .name = "Cirrus Logic GD5422 (ISA)", .internal_name = "cl_gd5422_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5422, .init = gd54xx_init, .close = gd54xx_close, @@ -4943,7 +4943,7 @@ const device_t gd5424_vlb_device = { const device_t gd5426_isa_device = { .name = "Cirrus Logic GD5426 (ISA)", .internal_name = "cl_gd5426_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5426, .init = gd54xx_init, .close = gd54xx_close, @@ -4958,7 +4958,7 @@ const device_t gd5426_isa_device = { const device_t gd5426_diamond_speedstar_pro_a1_isa_device = { .name = "Cirrus Logic GD5426 (ISA) (Diamond SpeedStar Pro Rev. A1)", .internal_name = "cl_gd5426_diamond_a1_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5426 | 0x100, .init = gd54xx_init, .close = gd54xx_close, @@ -5000,7 +5000,7 @@ const device_t gd5426_onboard_device = { const device_t gd5428_isa_device = { .name = "Cirrus Logic GD5428 (ISA)", .internal_name = "cl_gd5428_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5428, .init = gd54xx_init, .close = gd54xx_close, @@ -5043,7 +5043,7 @@ const device_t gd5428_diamond_speedstar_pro_b1_vlb_device = { const device_t gd5428_boca_isa_device = { .name = "Cirrus Logic GD5428 (ISA) (BOCA Research 4610)", .internal_name = "cl_gd5428_boca_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5428 | 0x100, .init = gd54xx_init, .close = gd54xx_close, @@ -5085,7 +5085,7 @@ const device_t gd5426_mca_device = { const device_t gd5428_onboard_device = { .name = "Cirrus Logic GD5428 (ISA) (On-Board)", .internal_name = "cl_gd5428_onboard", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5428, .init = gd54xx_init, .close = gd54xx_close, @@ -5113,7 +5113,7 @@ const device_t gd5428_vlb_onboard_device = { const device_t gd5429_isa_device = { .name = "Cirrus Logic GD5429 (ISA)", .internal_name = "cl_gd5429_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5429, .init = gd54xx_init, .close = gd54xx_close, @@ -5212,7 +5212,7 @@ const device_t gd5430_onboard_pci_device = { const device_t gd5434_isa_device = { .name = "Cirrus Logic GD5434 (ISA)", .internal_name = "cl_gd5434_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5434, .init = gd54xx_init, .close = gd54xx_close, @@ -5227,7 +5227,7 @@ const device_t gd5434_isa_device = { const device_t gd5434_diamond_speedstar_64_a3_isa_device = { .name = "Cirrus Logic GD5434 (ISA) (Diamond SpeedStar 64 Rev. A3)", .internal_name = "cl_gd5434_diamond_a3_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5434 | 0x100, .init = gd54xx_init, .close = gd54xx_close, diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 6ff34cbb1..246decb9c 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -2964,7 +2964,7 @@ static const device_config_t et4000w32p_config[] = { const device_t et4000w32_device = { .name = "Tseng Labs ET4000/w32 ISA", .internal_name = "et4000w32", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = ET4000W32, .init = et4000w32p_init, .close = et4000w32p_close, @@ -2978,7 +2978,7 @@ const device_t et4000w32_device = { const device_t et4000w32_onboard_device = { .name = "Tseng Labs ET4000/w32 (ISA) (On-Board)", .internal_name = "et4000w32_onboard", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = ET4000W32, .init = et4000w32p_init, .close = et4000w32p_close, @@ -2992,7 +2992,7 @@ const device_t et4000w32_onboard_device = { const device_t et4000w32i_isa_device = { .name = "Tseng Labs ET4000/w32i Rev. B ISA", .internal_name = "et4000w32i", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = ET4000W32I, .init = et4000w32p_init, .close = et4000w32p_close, diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index ce756f7d8..57b0f303c 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1819,7 +1819,7 @@ const device_t ht216_32_standalone_device = { const device_t radius_svga_multiview_isa_device = { .name = "Radius SVGA Multiview ISA (HT209)", .internal_name = "radius_isa", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0x7152, /*HT209*/ .init = radius_svga_multiview_init, .close = ht216_close, diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index aecc898c4..769cd0001 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -10667,7 +10667,7 @@ static const device_config_t s3_standard_config2[] = { const device_t s3_orchid_86c911_isa_device = { .name = "S3 86c911 ISA (Orchid Fahrenheit 1280)", .internal_name = "orchid_s3_911", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = S3_ORCHID_86C911, .init = s3_init, .close = s3_close, @@ -10681,7 +10681,7 @@ const device_t s3_orchid_86c911_isa_device = { const device_t s3_diamond_stealth_vram_isa_device = { .name = "S3 86c911 ISA (Diamond Stealth VRAM)", .internal_name = "stealthvram_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = S3_DIAMOND_STEALTH_VRAM, .init = s3_init, .close = s3_close, @@ -10695,7 +10695,7 @@ const device_t s3_diamond_stealth_vram_isa_device = { const device_t s3_ami_86c924_isa_device = { .name = "S3 86c924 ISA (AMI)", .internal_name = "ami_s3_924", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = S3_AMI_86C924, .init = s3_init, .close = s3_close, @@ -10709,7 +10709,7 @@ const device_t s3_ami_86c924_isa_device = { const device_t s3_spea_mirage_86c801_isa_device = { .name = "S3 86c801 ISA (SPEA Mirage ISA)", .internal_name = "px_s3_v7_801_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = S3_SPEA_MIRAGE_86C801, .init = s3_init, .close = s3_close, @@ -10779,7 +10779,7 @@ const device_t s3_mirocrystal_10sd_805_vlb_device = { const device_t s3_phoenix_86c801_isa_device = { .name = "S3 86c801 ISA (Phoenix)", .internal_name = "px_86c801_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = S3_PHOENIX_86C801, .init = s3_init, .close = s3_close, @@ -10807,7 +10807,7 @@ const device_t s3_phoenix_86c805_vlb_device = { const device_t s3_metheus_86c928_isa_device = { .name = "S3 86c928 ISA (Metheus Premier 928)", .internal_name = "metheus928_isa", - .flags = DEVICE_AT | DEVICE_ISA, + .flags = DEVICE_ISA16, .local = S3_METHEUS_86C928, .init = s3_init, .close = s3_close, diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index a469330af..2cc20044a 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -3815,7 +3815,7 @@ const device_t xga_device = { const device_t xga_isa_device = { .name = "XGA (ISA)", .internal_name = "xga_isa", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = xga_init, .close = xga_close, @@ -3829,7 +3829,7 @@ const device_t xga_isa_device = { const device_t inmos_isa_device = { .name = "INMOS XGA (ISA)", .internal_name = "inmos_xga_isa", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA16, .local = 0, .init = svga_xga_init, .close = xga_close, From a8cbb4deef63495159f28045ad95125353721011 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 08:03:15 +0100 Subject: [PATCH 0256/1190] Corrected the ISA and Sidecar flags. --- src/include/86box/machine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index bf4954ae9..8676fa5f1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -26,8 +26,8 @@ #define MACHINE_BUS_NONE 0x00000000 /* sys has no bus */ /* Feature flags for BUS'es. */ #define MACHINE_BUS_CASSETTE 0x00000001 /* sys has cassette port */ -#define MACHINE_BUS_ISA 0x00000002 /* sys has ISA bus */ -#define MACHINE_BUS_SIDECAR 0x00000004 /* sys has PCjr sidecar bus */ +#define MACHINE_BUS_SIDECAR 0x00000002 /* sys has PCjr sidecar bus */ +#define MACHINE_BUS_ISA 0x00000004 /* sys has ISA bus */ #define MACHINE_BUS_XT_KBD 0x00000008 /* sys has an XT keyboard port */ #define MACHINE_BUS_CBUS 0x00000010 /* sys has C-BUS bus */ #define MACHINE_BUS_ISA16 0x00000020 /* sys has ISA16 bus - PC/AT architecture */ From 32f2153f56dada8531df0eb20a771cae95edc15d Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 08:57:30 +0100 Subject: [PATCH 0257/1190] Assume device valid if it has no bus flags set. --- src/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device.c b/src/device.c index ff81fe5e5..8b2ddf35e 100644 --- a/src/device.c +++ b/src/device.c @@ -797,7 +797,7 @@ device_is_valid(const device_t *device, int mch) { int ret = 1; - if (device != NULL) + if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) ret = machine_has_bus(mch, device->flags & DEVICE_BUS); return ret; From 58089997a4a2e845052cbdeb3109f9cd8cb537a0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:03:57 +0100 Subject: [PATCH 0258/1190] Machine status: initialize it for the two cartridge bays as well. --- src/machine_status.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/machine_status.c b/src/machine_status.c index 16976fa83..3eb2762bc 100644 --- a/src/machine_status.c +++ b/src/machine_status.c @@ -45,11 +45,13 @@ machine_status_init(void) machine_status.mo[i].active = false; } + for (size_t i = 0; i < 2; i++) + machine_status.cartridge[i].empty = (strlen(cart_fns[i]) == 0); + machine_status.cassette.empty = (strlen(cassette_fname) == 0); - for (size_t i = 0; i < HDD_BUS_USB; i++) { + for (size_t i = 0; i < HDD_BUS_USB; i++) machine_status.hdd[i].active = false; - } for (size_t i = 0; i < NET_CARD_MAX; i++) { machine_status.net[i].active = false; From 51185745648813c1e07feaf178b325ce691af9b0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:06:20 +0100 Subject: [PATCH 0259/1190] 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 0260/1190] 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 549df9af7f841f99285ba9ccd882e3f2daf757fd Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:09:51 +0100 Subject: [PATCH 0261/1190] Updated a header. --- src/include/86box/fdd_86f.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/include/86box/fdd_86f.h b/src/include/86box/fdd_86f.h index cc8035965..de7bb7dcb 100644 --- a/src/include/86box/fdd_86f.h +++ b/src/include/86box/fdd_86f.h @@ -8,13 +8,11 @@ * * Definitions for the 86F floppy image format. * - * - * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018-2019 Fred N. van Kempen. + * Copyright 2016-2025 Miran Grca. + * Copyright 2018-2025 Fred N. van Kempen. */ #ifndef EMU_FLOPPY_86F_H #define EMU_FLOPPY_86F_H From 4e1926f954fb5a6dd033dffa209405b181de1d58 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:11:49 +0100 Subject: [PATCH 0262/1190] 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 9236856ad5131ee9c70fdc66af6d0606c1ff68c7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 16:39:42 +0100 Subject: [PATCH 0263/1190] Fixed the DEVICE_COM flags onwards, should fix serial mice. --- src/include/86box/device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 584f0f069..af546c64d 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -101,11 +101,11 @@ enum { DEVICE_AC97 = 0x100000, /* requires the AC'97 bus */ DEVICE_BUS = 0xffffff, /* requires a machine bus */ - DEVICE_COM = 0x100000, /* requires a serial port */ - DEVICE_LPT = 0x200000, /* requires a parallel port */ + DEVICE_COM = 0x200000, /* requires a serial port */ + DEVICE_LPT = 0x400000, /* requires a parallel port */ - DEVICE_KBC = 0x400000, /* is a keyboard controller */ - DEVICE_SOFTRESET = 0x800000, /* requires to be reset on soft reset */ + DEVICE_KBC = 0x800000, /* is a keyboard controller */ + DEVICE_SOFTRESET = 0x1000000, /* requires to be reset on soft reset */ DEVICE_ONBOARD = 0x40000000, /* is on-board */ DEVICE_PIT = 0x80000000, /* device is a PIT */ From 1d87a200e1f685e307c913f1ba5bc619ecab7132 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 16:42:53 +0100 Subject: [PATCH 0264/1190] Fixed DEVICE_BUS as well. --- src/include/86box/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/device.h b/src/include/86box/device.h index af546c64d..1c3ef1ef3 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -99,7 +99,7 @@ enum { DEVICE_USB = 0x40000, /* requires the USB bus */ DEVICE_AGP = 0x80000, /* requires the AGP bus */ DEVICE_AC97 = 0x100000, /* requires the AC'97 bus */ - DEVICE_BUS = 0xffffff, /* requires a machine bus */ + DEVICE_BUS = 0x1fffff, /* requires a machine bus */ DEVICE_COM = 0x200000, /* requires a serial port */ DEVICE_LPT = 0x400000, /* requires a parallel port */ From 466bcc68b40328e13d236f4973f0592c7894115a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 08:09:43 +0900 Subject: [PATCH 0265/1190] update header files I forgot updating header files --- src/include/86box/fdc.h | 4 ++-- src/include/86box/machine.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 0d71dd374..0c2e5ce06 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -52,7 +52,7 @@ #define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ #define FDC_FLAG_NO_DSR_RESET 0x1000 /* Has no DSR reset */ #define FDC_FLAG_NEC 0x2000 /* Is NEC upd765-compatible */ -#define FDC_FLAG_PS55 0x4000 /* PS/55 */ +#define FDC_FLAG_PS2 0x4000 /* PS/2, PS/55 */ #define FDC_FLAG_SEC 0x10000 /* Is Secondary */ #define FDC_FLAG_TER 0x20000 /* Is Tertiary */ #define FDC_FLAG_QUA 0x40000 /* Is Quaternary */ @@ -253,7 +253,7 @@ extern const device_t fdc_at_qua_device; extern const device_t fdc_at_actlow_device; extern const device_t fdc_at_ps1_device; extern const device_t fdc_at_ps1_2121_device; -extern const device_t fdc_at_ps55_device; +extern const device_t fdc_at_ps2_device; extern const device_t fdc_at_smc_device; extern const device_t fdc_at_ali_device; extern const device_t fdc_at_winbond_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fe867a4dc..3efb5a8e8 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -887,7 +887,8 @@ extern int machine_ps2_model_70_type3_init(const machine_t *); extern int machine_ps2_model_80_init(const machine_t *); extern int machine_ps2_model_80_axx_init(const machine_t *); extern int machine_ps2_model_70_type4_init(const machine_t *); -extern int machine_ps55_model_50t_init(const machine_t*); +extern int machine_ps55_model_50t_init(const machine_t*);; +extern int machine_ps55_model_50v_init(const machine_t*); /* m_tandy.c */ extern int tandy1k_eeprom_read(void); From cb67a389b17ec1aa03be9a0fa51e631b2160e659 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 08:14:31 +0900 Subject: [PATCH 0266/1190] modified ps/55 configuration, added a mca func I forgot updating some files --- src/86box.c | 2 +- src/config.c | 6 ++++++ src/mca.c | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index 82eedbd78..9b77263a2 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1062,7 +1062,7 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { - /* Use R-Alt because 5576-002 keyboard assigns L-Alt as */ + /* Use R-Alt because PS/55 DOS assigns L-Alt as Kanji */ keyboard_input(1, 0x1D); /* Ctrl key pressed */ keyboard_input(1, 0x138); /* R-Alt key pressed */ keyboard_input(1, sc); diff --git a/src/config.c b/src/config.c index 2c0781028..7a5d76465 100644 --- a/src/config.c +++ b/src/config.c @@ -456,6 +456,7 @@ load_video(void) ibm8514_active = ibm8514_standalone_enabled; xga_standalone_enabled = !!ini_section_get_int(cat, "xga", 0); xga_active = xga_standalone_enabled; + da2_standalone_enabled = !!ini_section_get_int(cat, "da2", 0); show_second_monitors = !!ini_section_get_int(cat, "show_second_monitors", 1); video_fullscreen_scale_maximized = !!ini_section_get_int(cat, "video_fullscreen_scale_maximized", 0); @@ -2013,6 +2014,11 @@ save_video(void) else ini_section_set_int(cat, "xga", xga_standalone_enabled); + if (da2_standalone_enabled == 0) + ini_section_delete_var(cat, "da2"); + else + ini_section_set_int(cat, "da2", da2_standalone_enabled); + // TODO for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if (gfxcard[i] == 0) diff --git a/src/mca.c b/src/mca.c index 871060bb4..a14fea6fa 100644 --- a/src/mca.c +++ b/src/mca.c @@ -101,3 +101,19 @@ mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t v } } } + +void +mca_add_to_slot(uint8_t (*read)(int addr, void* priv), void (*write)(int addr, uint8_t val, void* priv), uint8_t(*feedb)(void* priv), void (*reset)(void* priv), void* priv, int c) +{ + if (mca_card_read[c] || mca_card_write[c]) + { + //pclog("cannot add the device to slot %d\n", num); + return; + } + mca_card_read[c] = read; + mca_card_write[c] = write; + mca_card_feedb[c] = feedb; + mca_card_reset[c] = reset; + mca_priv[c] = priv; + return; +} From bfac770b4e19cb1bc23396a98263e6f1fd097208 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 08:27:17 +0900 Subject: [PATCH 0267/1190] reupload without code modification --- src/include/86box/vid_ps55da2.h | 48 +- src/video/vid_ps55da2.c | 6444 +++++++++++++++---------------- 2 files changed, 3246 insertions(+), 3246 deletions(-) diff --git a/src/include/86box/vid_ps55da2.h b/src/include/86box/vid_ps55da2.h index 70007be19..f029b5751 100644 --- a/src/include/86box/vid_ps55da2.h +++ b/src/include/86box/vid_ps55da2.h @@ -1,24 +1,24 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * IBM PS/55 Display Adapter II emulation. - * - * - * - * Authors: Akamaki. - * - * Copyright 2024 Akamaki. - */ - -#ifndef VIDEO_DA2_DEVICE_H -#define VIDEO_DA2_DEVICE_H - -#ifdef EMU_DEVICE_H -extern const device_t ps55da2_device; -#endif -#endif /*VIDEO_DA2_DEVICE_H*/ +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#ifndef VIDEO_DA2_DEVICE_H +#define VIDEO_DA2_DEVICE_H + +#ifdef EMU_DEVICE_H +extern const device_t ps55da2_device; +#endif +#endif /*VIDEO_DA2_DEVICE_H*/ diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a19965f6f..0ac136630 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1,3222 +1,3222 @@ -/* - * 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. - * - * IBM PS/55 Display Adapter II emulation. - * - * Authors: Akamaki. - * - * Copyright 2024 Akamaki. - */ - -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/io.h> -#include <86box/machine.h> -#include <86box/mem.h> -#include <86box/timer.h> -#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> -#include <86box/vid_svga_render.h> -#include "cpu.h" - -#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" -#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" -#define DA2_FONTROM_SIZE 1536*1024 -#define DA2_FONTROM_BASESBCS 0x98000 -#define DA2_GAIJIRAM_SBCS 0x34000 -#define DA2_GAIJIRAM_SBEX 0x3c000 -#define DA2_INVALIDACCESS8 0xff -#define DA2_MASK_MMIO 0x1ffff -#define DA2_MASK_GRAM 0x1ffff -#define DA2_MASK_CRAM 0xfff -#define DA2_MASK_GAIJIRAM 0x3ffff -#define DA2_PIXELCLOCK 58000000.0 -#define DA2_BLT_MEMSIZE 0x100 -#define DA2_BLT_REGSIZE 0x40 -#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256*1024 -#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe -#define DA2_DEBUG_BLT_USEDRESET 0xfefefe -#define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ -//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ -//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ -#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ -#define DA2_DCONFIG_MONTYPE_COLOR 0x0A -#define DA2_DCONFIG_MONTYPE_8515 0x0B -#define DA2_DCONFIG_MONTYPE_MONO 0x09 - -#define DA2_BLT_CIDLE 0 -#define DA2_BLT_CFILLRECT 1 -#define DA2_BLT_CFILLTILE 2 -#define DA2_BLT_CCOPYF 3 -#define DA2_BLT_CCOPYR 4 -#define DA2_BLT_CPUTCHAR 5 -#define DA2_BLT_CDONE 6 -#define DA2_BLT_CLOAD 7 -/* POS ID = 0xeffe : Display Adapter II, III, V */ -#define DA2_POSID_H 0xef -#define DA2_POSID_L 0xfe -/* - [Identification] - POS ID SYS ID - EFFFh * Display Adapter (PS/55 Model 5571-S0A) [Toledo] - E013h * Layout Display Terminal (PS/55-5571 RPQ model) [LDT] - EFFEh * Display Adapter II (I/O 3E0:0A = xx0x xxxx) [Atlas] - |- FFF2h Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5530Z-SX) - |- FDFEh Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5550-V2) - |- * Display Adapter III,V (I/O 3E0:0A = xx1x xxxx) - ECECh FF4Fh Display Adapter B1 (PS/55 Model 5531Z-SX) [Atlas-KENT] - |- * Display Adapter IV - ECCEh * Display Adapter IV - 901Fh * Display Adapter A2 - 901Dh * Display Adapter A1 [Atlas II] - 901Eh * Plasma Display Adapter - EFD8h * Display Adapter/J [Atlas-SP2] - - [Japanese DOS and Display Adapter compatibility] - | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | - |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| - | EFFFh | Display Adapter | X | | | ? | | - | FFEDh | ? [Atlas EVT] | X | | | ? | | - | FFFDh | ? [LDT EVT] | X | | | ? | | - | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | - | E013h | ? [LDT] | X | X | X | X | | - | ECCEh | Display Adapter IV | | X | X | X | | - | ECECh | Display Adapter IV,B1 | | X | X | X | X | - | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | - | EFD8h | Display Adapter /J | | | X | X | X | -*/ -/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ -#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ -//#define Mon_ID3 0x10 -#define FontCard 0x08 /* ? */ -/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ -#define Page_One 0x06 /* 80000h 110b */ -#define Page_Two 0x05 /* 100000h 101b */ -#define Page_Four 0x03 /* 200000h 011b */ - -/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ -#define AddPage 0x08 /* ? */ -//#define Mon_ID2 0x04 -//#define Mon_ID1 0x02 -//#define Mon_ID0 0x01 -/* Monitor ID (imported from OS/2 DDK 1.2) */ -//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 -//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale -//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp -//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B - -/* DA2 Registers (imported from OS/2 DDK) */ -#define AC_REG 0x3EE -#define AC_DMAE 0x80 -#define AC_FONT_SEL 0x40 -#define FONT_BANK 0x3EF -#define LS_INDEX 0x3E0 -#define LS_DATA 0x3E1 -#define LS_RESET 0x00 -#define LS_MODE 0x02 -#define LS_STATUS 0x03 /* added */ -#define LS_MMIO 0x08 /* added */ -#define LS_CONFIG1 0x0a -#define LS_CONFIG2 0x0b /* added */ -#define LF_INDEX 0x3e2 -#define LF_DATA 0x3e3 -#define LF_MMIO_SEL 0x08 /* added */ -#define LF_MMIO_ADDR 0x0A /* added */ -#define LF_MMIO_MODE 0x0B /* added */ -#define LC_INDEX 0x3E4 -#define LC_DATA 0x3E5 -#define LC_HORIZONTAL_TOTAL 0x00 -#define LC_H_DISPLAY_ENABLE_END 0x01 -#define LC_START_H_BLANKING 0x02 -#define LC_END_H_BLANKING 0x03 -#define LC_START_HSYNC_PULSE 0x04 -#define LC_END_HSYNC_PULSE 0x05 -#define LC_VERTICAL_TOTALJ 0x06 -#define LC_CRTC_OVERFLOW 0x07 -#define LC_PRESET_ROW_SCANJ 0x08 -#define LC_MAXIMUM_SCAN_LINE 0x09 -#define LC_CURSOR_ROW_START 0x0A -#define LC_CURSOR_ROW_END 0x0B -#define LC_START_ADDRESS_HIGH 0x0C -#define LC_START_ADDRESS_LOW 0x0D -#define LC_CURSOR_LOC_HIGH 0x0E -#define LC_ROW_CURSOR_LOC 0x0E -#define LC_CURSOR_LOC_LOWJ 0x0F -#define LC_COLUMN_CURSOR_LOC 0x0F -#define LC_VERTICAL_SYNC_START 0x10 -#define LC_LIGHT_PEN_HIGH 0x10 -#define LC_VERTICAL_SYNC_END 0x11 -#define LC_LIGHT_PEN_LOW 0x11 -#define LC_V_DISPLAY_ENABLE_END 0x12 -#define LC_OFFSET 0x13 -#define LC_UNDERLINE_LOCATION 0x14 -#define LC_START_VERTICAL_BLANK 0x15 -#define LC_END_VERTICAL_BLANK 0x16 -#define LC_LC_MODE_CONTROL 0x17 -#define LC_LINE_COMPAREJ 0x18 -#define LC_START_H_DISPLAY_ENAB 0x19 -#define LC_START_V_DISPLAY_ENAB 0x1A -#define LC_VIEWPORT_COMMAND 0x1B -#define LC_VIEWPORT_SELECT 0x1C -#define LC_VIEWPORT_PRIORITY 0x1D -#define LC_COMMAND 0x1E -#define LC_COMPATIBILITY 0x1F -#define LC_VIEWPORT_NUMBER 0x1F -#define LV_PORT 0x3E8 -#define LV_PALETTE_0 0x00 -#define LV_MODE_CONTROL 0x10 -#define LV_OVERSCAN_COLOR 0x11 -#define LV_COLOR_PLANE_ENAB 0x12 -#define LV_PANNING 0x13 -#define LV_VIEWPORT1_BG 0x14 -#define LV_VIEWPORT2_BG 0x15 -#define LV_VIEWPORT3_BG 0x16 -#define LV_BLINK_COLOR 0x17 -#define LV_BLINK_CODE 0x18 -#define LV_GR_CURSOR_ROTATION 0x19 -#define LV_GR_CURSOR_COLOR 0x1A -#define LV_GR_CURSOR_CONTROL 0x1B -#define LV_COMMAND 0x1C -#define LV_VP_BORDER_LINE 0x1D -#define LV_SYNC_POLARITY 0x1F -#define LV_CURSOR_CODE_0 0x20 -#define LV_GRID_COLOR_0 0x34 -#define LV_GRID_COLOR_1 0x35 -#define LV_GRID_COLOR_2 0x36 -#define LV_GRID_COLOR_3 0x37 -#define LV_ATTRIBUTE_CNTL 0x38 -#define LV_CURSOR_COLOR 0x3A -#define LV_CURSOR_CONTROL 0x3B -#define LV_RAS_STATUS_VIDEO 0x3C -#define LV_PAS_STATUS_CNTRL 0x3D -#define LV_IDENTIFICATION 0x3E -#define LV_OUTPUT 0x3E -#define LV_COMPATIBILITY 0x3F -#define LG_INDEX 0x3EA -#define LG_DATA 0x3EB -#define LG_SET_RESETJ 0x00 -#define LG_ENABLE_SRJ 0x01 -#define LG_COLOR_COMPAREJ 0x02 -#define LG_DATA_ROTATION 0x03 -#define LG_READ_MAP_SELECT 0x04 -#define LG_MODE 0x05 -#define LG_COMPLEMENT 0x06 -#define LG_COLOR_DONT_CARE 0x07 -#define LG_BIT_MASK_LOW 0x08 -#define LG_BIT_MASK_HIGH 0x09 -#define LG_MAP_MASKJ 0x0A -#define LG_COMMAND 0x0B -#define LG_SET_RESET_2 0x10 - -#ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 -#endif - -#ifdef ENABLE_DA2_LOG -int da2_do_log = ENABLE_DA2_LOG; - -static void -da2_log(const char* fmt, ...) -{ - va_list ap; - - if (da2_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define da2_log(fmt, ...) -#endif -#ifndef RELEASE_BUILD -# define ENABLE_DA2_DEBUGBLT 1 -#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]; - uint8_t gdcreg[64]; - uint8_t reg3ee[16]; - int gdcaddr; - uint8_t attrc[0x40]; - int attraddr, attrff; - int attr_palette_enable; - //uint8_t seqregs[64]; - int outflipflop; - int inflipflop; - int iolatch; - - int ioctladdr; - int fctladdr; - int crtcaddr; - - uint32_t decode_mask; - uint32_t vram_max; - uint32_t vram_mask; - - 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; - int dac_r, dac_g; - - uint8_t cgastat; - - uint8_t plane_mask; - - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - uint8_t writemask; - uint32_t charseta, charsetb; - - uint8_t egapal[16]; - uint32_t pallook[512]; - PALETTE vgapal; - - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int rowcount; - double clock; - uint32_t ma_latch, ca_adj; - - uint64_t dispontime, dispofftime; - pc_timer_t timer; - uint64_t da2const; - - int dispon; - int hdisp_on; - - uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink, blinkconf; - int scrollcache; - int char_width; - - int firstline, lastline; - int firstline_draw, lastline_draw; - int displine; - - /* 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; - /* addr >> 12 = xx000h */ - uint8_t *changedvram; - /* (vram size - 1) >> 3 = 0x1FFFF */ - uint32_t vram_display_mask; - - //uint32_t write_bank, read_bank; - - int fullchange; - - void (*render)(struct da2_t* da2); - - /*If set then another device is driving the monitor output and the SVGA - card should not attempt to display anything */ - int override; - - /* end VGA compatible regs*/ - struct - { - int enable; - mem_mapping_t mapping; - uint8_t ram[256 * 1024]; - uint8_t *font; - int charset; - } mmio; - - struct { - int bitshift_destr; - int raster_op; - uint8_t payload[DA2_BLT_MEMSIZE]; - int32_t reg[DA2_BLT_REGSIZE];//must be signed int - int32_t* debug_reg;//for debug - int debug_reg_ip;//for debug - int payload_addr; - pc_timer_t timer; - int64_t timerspeed; - int exec; - int indata; - int32_t destaddr; - int32_t srcaddr; - int32_t size_x, tile_w; - int32_t size_y; - int16_t destpitch; - int16_t srcpitch; - int32_t fcolor; - int32_t maskl, maskr; - int x, y; - } bitblt; - - FILE* mmdbg_fp; - FILE* mmrdbg_fp; - uint32_t mmdbg_vidaddr; - uint32_t mmrdbg_vidaddr; - - uint8_t pos_regs[8]; - svga_t *mb_vga; - uint8_t monitorid; - - 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); - -typedef union { - uint32_t d; - uint8_t b[4]; -} DA2_VidSeq32; - -typedef struct { - uint32_t p8[8]; -} pixel32; - -/* safety read for internal functions */ -uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) -{ - if (addr & ~da2->vram_mask) return -1; - return da2->vram[addr]; -} - -void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) -{ - uint32_t writepx[8]; - destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ - //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; - da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; - destaddr <<= 3; - /* read destination data with big endian order */ - for (int i = 0; i < 8; i++) - writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) - | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); - - DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; - DA2_VidSeq32 mask32; mask32.d = 0; - mask32.b[3] = mask32in.b[0]; - mask32.b[2] = mask32in.b[1]; - mask32.d &= 0xffff0000; - for (int i = 0; i < 8; i++) - { - if (da2->bitblt.bitshift_destr > 0) - srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; - switch (da2->bitblt.raster_op) { - case 0x00: /* None */ - writepx[i] &= ~mask32.d; - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x01: /* AND */ - writepx[i] &= srcpx->p8[i] | ~mask32.d; - break; - case 0x02: /* OR */ - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x03: /* XOR */ - writepx[i] ^= srcpx->p8[i] & mask32.d; - break; - } - } - for (int i = 0; i < 8; i++) { - da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; - da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; - } -} - -void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) -{ - pixel32 srcpx; - //fill data with input color - for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} -/* -Param Desc -01 Color -03 Bit Shift -04 Select plane? -05 Dir(10 or 11) + Command?(40 or 48) -08 Mask Left -09 Mask Right -0A Plane Mask? -0B ROP?(8h or 200h + 0-3h) -0D -20 Exec (1) -21 ? -22 ? -23 Tile W -28 Tile H -29 Dest Addr -2A Src Addr -2B Tile Addr -33 Size W -35 Size H - -*/ -void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) -{ - pixel32 srcpx; - srcaddr &= 0xfffffffe; - srcaddr <<= 3; - for (int i = 0; i < 8; i++) - srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) - | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} -void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) -{ - pixel32 srcpx; - if (srcaddr >= DA2_FONTROM_SIZE) { - da2_log("DA2 Putchar Addr Error %x\n", srcaddr); - return; - } - for (int i = 0; i < 8; i++) - srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) - | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) - | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} -#ifdef ENABLE_DA2_DEBUGBLT -uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { - uint8_t pixeldata = 0; - for (int j = 0; j < 8; j++) { - if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; - } - return pixeldata; -} -void print_pixelbyte(uint32_t addr, da2_t* da2) { - for (int i = 0; i < 8; i++) - { - pclog("%X", pixel1tohex(addr, i, da2)); - } -} -void print_bytetobin(uint8_t b) { - for (int i = 0; i < 8; i++) - { - if(b & 0x80) - pclog("1"); - else - pclog("0"); - b <<= 1; - } -} -//Convert internal char code to Shift JIS code -inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } -inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } -uint16_t IBMJtoSJIS(uint16_t knj) -{ - if (knj < 0x100) return 0xffff; - knj -= 0x100; - if (knj <= 0x1f7d) - ;/* do nothing */ - else if (knj >= 0xb700 && knj <= 0xb75f) { - knj -= 0x90ec; - } - else if (knj >= 0xb3f0 && knj <= 0xb67f) { - knj -= 0x906c; - } - else if (knj >= 0x8000 && knj <= 0x8183) - { - knj -= 0x5524; - } - else - return 0xffff; - uint32_t knj1 = knj / 0xBC; - uint32_t knj2 = knj - (knj1 * 0xBC); - knj1 += 0x81; - if (knj1 > 0x9F) knj1 += 0x40; - knj2 += 0x40; - if (knj2 > 0x7E) knj2++; - //if (!isKanji1(knj1)) return 0xffff; - //if (!isKanji2(knj2)) return 0xffff; - knj = knj1 << 8; - knj |= knj2; - return knj; -} -#endif -void da2_bitblt_load(da2_t* da2) -{ - uint32_t value32; - uint64_t value64; - da2_log("BITBLT loading params\n"); - //da2_log("BitBlt memory:\n"); - //if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - // { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - // } - int i = 0; - while (i < DA2_BLT_MEMSIZE) - { - if (da2->bitblt.reg[0x20] & 0x1) - break; - switch (da2->bitblt.payload[i]) { - case 0x88: - case 0x89: - case 0x95: - value32 = da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 3; - break; - case 0x91: - value32 = da2->bitblt.payload[i + 5]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 4]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 5; - break; - case 0x99: - value64 = da2->bitblt.payload[i + 7]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 6]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 5]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 4]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 3]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 2]; - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - i += 7; - break; - case 0x00: - break; - default: - da2_log("da2_ParseBLT: Unknown PreOP!\n"); - break; - } - i++; - } - da2->bitblt.exec = DA2_BLT_CIDLE; - /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; - /* [89] 20: 0001 (1) then execute payload */ - if (da2->bitblt.reg[0x20] & 0x1) - { -#ifdef ENABLE_DA2_DEBUGBLT - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); - } - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; - } - da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; - da2->bitblt.debug_reg_ip++; - if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; -#endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR - da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - for (int i = 0; i <= 0xb; i++) - da2_log("%02x ", da2->gdcreg[i]); - da2_log("\n"); - - da2->bitblt.destaddr = da2->bitblt.reg[0x29]; - da2->bitblt.size_x = da2->bitblt.reg[0x33]; - da2->bitblt.size_y = da2->bitblt.reg[0x35]; - da2->bitblt.destpitch = da2->bitblt.reg[0x21]; - da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; - if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; - { - da2->bitblt.destaddr -= 2; - da2->bitblt.size_x += 1; - da2->bitblt.destpitch -= 2; - da2->bitblt.srcpitch -= 2; - } - da2->bitblt.fcolor = da2->bitblt.reg[0x0]; - da2->bitblt.maskl = da2->bitblt.reg[0x8]; - da2->bitblt.maskr = da2->bitblt.reg[0x9]; - da2->bitblt.x = 0; - da2->bitblt.y = 0; - da2->bitblt.exec = DA2_BLT_CDONE; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - - if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode - { - da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); - da2->bitblt.exec = DA2_BLT_CDONE; - } - else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ - da2->bitblt.exec = DA2_BLT_CPUTCHAR; - /* Todo: addressing */ - //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; - //{ - // da2->bitblt.destaddr += 2; - // da2->bitblt.size_x -= 1; - // da2->bitblt.destpitch += 2; - // da2->bitblt.srcpitch += 2; - //} - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; - da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ - da2->bitblt.bitshift_destr += 1; - da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); - } - else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { - da2->bitblt.exec = DA2_BLT_CPUTCHAR; - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; - da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ - da2->bitblt.bitshift_destr += 1; - da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ - da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); - da2->bitblt.exec = DA2_BLT_CFILLRECT; - da2->bitblt.destaddr += 2; - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ - da2->bitblt.exec = DA2_BLT_CFILLTILE; - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; - da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ - da2->bitblt.exec = DA2_BLT_CFILLTILE; - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; - da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ - da2->bitblt.exec = DA2_BLT_CCOPYF; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; - da2->bitblt.destaddr += 2; - da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ - da2->bitblt.exec = DA2_BLT_CCOPYR; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); - } - } -} -void da2_bitblt_exec(void* p) -{ - da2_t* da2 = (da2_t*)p; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - switch (da2->bitblt.exec) - { - case DA2_BLT_CIDLE: - timer_disable(&da2->bitblt.timer); - break; - case DA2_BLT_CLOAD: - da2->bitblt.indata = 0; - da2_bitblt_load(da2); - break; - case DA2_BLT_CFILLRECT: - //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CFILLTILE: - int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CCOPYF: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr += 2; - break; - case DA2_BLT_CCOPYR: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr -= da2->bitblt.destpitch; - da2->bitblt.srcaddr -= da2->bitblt.srcpitch; - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - break; - case DA2_BLT_CPUTCHAR: - //da2->bitblt.y += 2; - da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); - //da2->bitblt.srcaddr += 2; - if(da2->bitblt.reg[0x12] < 0x100) - da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; - else - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - pclog("\n"); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - //if (1) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 3) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += 130; - //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - //da2->bitblt.srcaddr += -1; - } - else if (da2->bitblt.x == 0) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; - ////da2->bitblt.srcaddr += 2; - //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; - break; - case DA2_BLT_CDONE: - /* initialize regs for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } - if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; - else da2->bitblt.exec = DA2_BLT_CIDLE; - break; - } -} -void da2_bitblt_dopayload(da2_t* da2) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) - { - da2->bitblt.exec = DA2_BLT_CLOAD; - //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ - da2_log("da2 Do bitblt\n"); - while (da2->bitblt.exec != DA2_BLT_CIDLE) - { - da2_bitblt_exec(da2); - } - da2_log("da2 End bitblt %x\n", da2->bitblt.exec); - } -} - -void da2_out(uint16_t addr, uint16_t val, void *p) -{ - da2_t *da2 = (da2_t *)p; - int oldval; -/* -3E0 3E1 Sequencer Registers (undoc) -3E2 3E3 Font Registers (undoc) -3E4 3E5 CRT Control Registers (undoc) -3E8 3E9 Attribute Controller Registers (undoc) -3EA 3EB 3EC Graphics Contoller Registers -*/ - switch (addr) - { - case 0x3c6: /* PEL Mask */ - da2->dac_mask = val; - break; - case 0x3C7: /* Read Address */ - da2->dac_read = val; - da2->dac_pos = 0; - break; - case 0x3C8: /* Write Address */ - da2->dac_write = val; - da2->dac_read = val - 1; - 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->dac_status = 0; - da2->fullchange = changeframecount; - switch (da2->dac_pos) - { - case 0: - da2->dac_r = val; - da2->dac_pos++; - break; - case 1: - da2->dac_g = val; - da2->dac_pos++; - break; - case 2: - da2->vgapal[da2->dac_write].r = da2->dac_r; - da2->vgapal[da2->dac_write].g = da2->dac_g; - da2->vgapal[da2->dac_write].b = val; - //if (da2->ramdac_type == RAMDAC_8BIT) - // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); - //else - da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); - da2->dac_pos = 0; - da2->dac_write = (da2->dac_write + 1) & 255; - break; - } - break; - case LS_INDEX: - 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); - 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); - oldval = da2->ioctl[da2->ioctladdr]; - da2->ioctl[da2->ioctladdr] = val; - if (oldval != val) { - if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ - da2_reset_ioctl(da2); - else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ - { - da2->fullchange = changeframecount; - da2_recalctimings(da2); - da2_updatevidselector(da2); - } - else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ - { - //da2->bitblt.indata = 1; - } - } - break; - case LF_INDEX: - 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); - 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); - oldval = da2->fctl[da2->fctladdr]; - da2->fctl[da2->fctladdr] = val; - if (da2->fctladdr == 0 && oldval != val) - { - da2->fullchange = changeframecount; - da2_recalctimings(da2); - } - break; - case LC_INDEX: - da2->crtcaddr = val; - break; - case LC_DATA: - 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); - if (!(da2->crtc[da2->crtcaddr] ^ val)) return; - switch (da2->crtcaddr) { - case LC_CRTC_OVERFLOW: - //return; - break; - case LC_MAXIMUM_SCAN_LINE: - if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; - break; - case LC_START_ADDRESS_HIGH: - //if (da2->crtc[0x1c] & 0x40) return; - break; - case LC_VERTICAL_TOTALJ: /* Vertical Total */ - case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ - case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ - case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ - //val = 0x400; //for debugging bitblt - break; - case LC_VIEWPORT_SELECT: /* ViewPort Select? */ - //return; - break; - case LC_VIEWPORT_NUMBER: /* Compatibility? */ - break; - } - da2->crtc[da2->crtcaddr] = val; - switch (da2->crtcaddr) { - case LC_H_DISPLAY_ENABLE_END: - case LC_VERTICAL_TOTALJ: - case LC_MAXIMUM_SCAN_LINE: - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: - case LC_VERTICAL_SYNC_START: - case LC_V_DISPLAY_ENABLE_END: - case LC_START_VERTICAL_BLANK: - case LC_END_VERTICAL_BLANK: - case LC_VIEWPORT_PRIORITY: - da2->fullchange = changeframecount; - da2_recalctimings(da2); - break; - default: - break; - } - 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); - if (!da2->attrff) - { - // da2->attraddr = val & 31; - da2->attraddr = val & 0x3f; - if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) - { - da2->fullchange = 3; - da2->attr_palette_enable = val & 0x20; - da2_recalctimings(da2); - } - //da2_log("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->attrc[da2->attraddr & 0x3f] = val; - //da2_log("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) - { - for (int c = 0; c < 16; c++) - { - //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); - //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); - if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; - else da2->egapal[c] = da2->attrc[c] & 0x3f; - } - } - switch (da2->attraddr) - { - case LV_COLOR_PLANE_ENAB: - if ((val & 0xff) != da2->plane_mask) - da2->fullchange = changeframecount; - da2->plane_mask = val & 0xff; - break; - case LV_CURSOR_CONTROL: - switch (val & 0x18) { - case 0x08://fast blink - da2->blinkconf = 0x10; - break; - case 0x18://slow blink - da2->blinkconf = 0x20; - break; - default://no blink - da2->blinkconf = 0xff; - break; - } - break; - case LV_MODE_CONTROL: - case LV_ATTRIBUTE_CNTL: - case LV_COMPATIBILITY: - da2_recalctimings(da2); - break; - default: - break; - } - } - da2->attrff ^= 1; - break; - case 0x3E9: - /* VZ Editor's CURSOR.COM writes data via this port */ - da2->attrc[da2->attraddr & 0x3f] = val; - break; - case LG_INDEX: - da2->gdcaddr = val; - break; - case LG_DATA: - //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); - //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); - switch (da2->gdcaddr & 0x1f) - { - case LG_READ_MAP_SELECT: - da2->readplane = val & 0x7; - break; - case LG_MODE: - da2->writemode = val & 3; - break; - case LG_MAP_MASKJ: - da2->writemask = val & 0xff; - break; - case LG_COMMAND: - break; - case LG_SET_RESET_2: - da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); - return; - } - da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; - break; - //case 0x3ed: /* used by Windows 3.1 display driver */ - // da2->gdcreg[5] = val & 0xff; - // break; - default: - da2_log("DA2? Out addr %03X val %02X\n", addr, val); - break; - } -} - -uint16_t da2_in(uint16_t addr, void *p) -{ - da2_t * da2 = (da2_t *)p; - uint16_t temp; - - switch (addr) - { - case 0x3c3: - temp = 0; - break; - case 0x3c6: temp = da2->dac_mask; - break; - case 0x3c7: temp = da2->dac_status; - break; - case 0x3c8: temp = da2->dac_write; - break; - case 0x3c9: - da2->dac_status = 3; - switch (da2->dac_pos) - { - case 0: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].r & 0x3f; - break; - case 1: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].g & 0x3f; - break; - case 2: - da2->dac_pos = 0; - da2->dac_read = (da2->dac_read + 1) & 255; - temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; - break; - } - break; - case LS_INDEX: - temp = da2->ioctladdr; - break; - case LS_DATA: - //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) - if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; - temp = da2->ioctl[da2->ioctladdr]; - if (da2->ioctladdr == LS_STATUS) { /* Status register */ - if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ - if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { - /* grayscale monitor */ - if ((da2->vgapal[0].r >= 10) || (da2->vgapal[0].g >= 40) || (da2->vgapal[0].b >= 10)) - temp &= 0x7F; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */ - else - temp |= 0x80; /* Active when the RGB output voltage is low and the cable is connected to a color monitor. - If the cable or the monitor is wrong, it becomes inactive. */ - } else { - /* color monitor */ - if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 80) - temp &= 0x7F; - else - temp |= 0x80; - } - } else { - temp |= 0x80; - } - temp &= 0xf6;//clear busy bits - if (da2->bitblt.indata) /* for OS/2 J1.3 */ - da2_bitblt_dopayload(da2); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - { - //da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x08;//wait(bit 3 + bit 0) - //if (!da2->bitblt.timer.enabled) - //{ - // da2_log("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 |= 0x01; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); - } - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); - break; - case LF_INDEX: - temp = da2->fctladdr; - break; - case LF_DATA: - if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; - temp = da2->fctl[da2->fctladdr]; - break; - case LC_INDEX: - temp = da2->crtcaddr; - break; - case LC_DATA: - if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; - temp = da2->crtc[da2->crtcaddr]; - break; - case LV_PORT: - temp = da2->attraddr | da2->attr_palette_enable; - break; - case 0x3E9: - if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ - { - if (da2->cgastat & 0x01) - da2->cgastat &= ~0x30; - else - da2->cgastat ^= 0x30; - 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->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ - break; - case LG_INDEX: - temp = da2->gdcaddr; - 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); - break; - } - //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - return temp; -} -/* -* Write I/O -* out b(idx), out b(data), out b(data) -* out b(idx), out w(data) -* out b(idx), out w(data), out b(data) -* out w(idx) -* Read I/O -* out b(idx), in b(data) -* out b(idx), in b, in b(data) -* out b(idx), in w(data) -*/ -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->inflipflop = 0; - switch (addr) - { - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - if (da2->outflipflop) - { - /* out b(idx), out b(data), out b(data) */ - da2->iolatch |= (uint16_t)val << 8; - da2->outflipflop = 0; - } - else - {// - da2->iolatch = val; - da2->outflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - default: - da2->iolatch = val; - da2->outflipflop = 0; - break; - } - da2_out(addr, da2->iolatch, da2); -} -void da2_outw(uint16_t addr, uint16_t val, void* p) -{ - //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_t* da2 = (da2_t*)p; - da2->inflipflop = 0; - switch (addr) - { - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - da2_out(addr, val & 0xff, da2); - da2->iolatch = val >> 8; - da2_out(addr + 1, da2->iolatch, da2); - da2->outflipflop = 1; - break; - case LV_PORT: - da2->attrff = 0; - da2_out(addr, val & 0xff, da2); - da2_out(addr, val >> 8, da2); - 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_out(LG_DATA, val >> 8, da2); - break; - case 0x3ED: - da2->gdcaddr = LG_MODE; - da2_out(LG_DATA, val, da2); - break; - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - default: - da2_out(addr, val, da2); - da2->outflipflop = 0; - break; - case 0x3EE: - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2->reg3ee[val & 0xff] = val >> 8; - break; - } -} -uint8_t da2_inb(uint16_t addr, void* p) -{ - uint8_t temp; - da2_t* da2 = (da2_t*)p; - da2->outflipflop = 0; - switch (addr) - { - case LC_DATA: - if (da2->inflipflop) - { - /* out b(idx), in b(low data), in b(high data) */ - temp = da2->iolatch >> 8; - da2->inflipflop = 0; - } - else - {// - da2->iolatch = da2_in(addr, da2); - temp = da2->iolatch & 0xff; - da2->inflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - case LS_DATA: - case LF_DATA: - case LG_DATA: - default: - temp = da2_in(addr, da2) & 0xff; - da2->inflipflop = 0; - break; - } - //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - return temp; -} -uint16_t da2_inw(uint16_t addr, void* p) -{ - //uint16_t temp; - da2_t* da2 = (da2_t*)p; - da2->inflipflop = 0; - da2->outflipflop = 0; - return da2_in(addr, da2); -} -/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ -uint8_t da2_in_ISR(uint16_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - uint8_t temp = 0; - if (addr == 0x3da) { - if (da2->cgastat & 0x01) - da2->cgastat &= ~0x30; - else - da2->cgastat ^= 0x30; - temp = da2->cgastat; - } - //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - return temp; -} - -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); -} - -/* -The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. - [Character drawing] - SBCS: - 1 2 ... 13 - 1 | H.Grid - |---------------- - 2 | Space - 3 V| - .| - G| Font Pattern - r| (12x24 pixels) - i| - d| -26 |________________ -27 Space - ---------------- -28 Underscore ] - ---------------- >Cursor Position -29 ] - - DBCS: - 1 2 ... 13 1 2 ... 12 13 - 1 | H.Grid | H.Grid | - -|--------------------------|- - 2 | Space | Space | - -|--------------------------|- - 3 V| | |S - .| | |p - G| Font Pattern |a - r| (24x24 pixels) |c - i| | |e - d| | | -26 |_____________|____________| -27 | Space | Space - ------------------------------ -28 | Underscore | Underscore ] - ------------------------------ >Cursor Position -29 | | ] - - [Attributes] - Video mode 08h: - 7 6 5 4 3 2 1 0 - Blink |Under |HGrid |VGrid |Bright|Revers|FntSet|DBCS/SBCS| - - Video mode 0Eh: - -Blue |-Green|HGrid |VGrid |-Red |Revers|FntSet|DBCS/SBCS| - - Bit 1 switches the font bank to the Extended SBCS. DOS K3.x loads APL characters from $SYSEX24.FNT into it. - DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. - This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. - -[Font ROM Map (DA2, Japanese)] -The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. - - Bank 0 - 4800- * - Bank 1, 2, 3 - * - * - Bank 4 - * -0DB6Fh ( 4800-8DB6Fh) : JIS X 0208 DBCS (24 x 24) (IBMJ code: 100-1F7Dh) - 10000-16D1Fh (90000-96D1Fh) : IBM Extended Characters (IBMJ code: 2ADC-2C5Fh) - 18000-1BFCFh (98000-9BFCFh) : JIS X 0201 SBCS (13 x 30) - 1C000-1FFFFh (9C000-9FFFFh) : Codepage 437 characters (13 x 30) - Bank 5 - 00000-0C68Fh (A0000-AC68Fh) : Gaiji used by DOS Bunsho - 10000-13FFFh (B0000-B3FFFh) : Extended SBCS (13 x 30) - 14000-1477Fh (B4000-B477Fh) : Half-width box drawing characters used by DOS Bunsho - 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) - 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) - - Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) - -[Font ROM Map (DA3, Traditional Chinese)] - Bank 0 - 11 : Valid Font ROM data - Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) - Bank 13 : All addresses return 0xFF - -[Gaiji RAM Map (DA2)] - Bank 0 00000-1FFFFh placed between A0000h-BFFFFh - 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes - 1F800-1FFFFh(BF800-BFFFFh): Gaiji Resident (SJIS: F040-F04Fh, IBM: 2384-2393h) 16 chs - - Bank 1 20000-3FFFFh placed between A0000h-BFFFFh - 20000-33FFFh(A0000-B3FFFh): Gaiji Resident (SJIS: F050-F39Ch, IBM: 2394-2613h) 640 chs - 34000-37FFFh(B4000-B7FFFh): Basic SBCS(00-FFh, ATTR bit 1 = off) - 38000-3AFFFh(B8000-BAFFFh): Gaiji Resident (SJIS: F39D-F3FCh, IBM: 2614-2673h) 96 chs - 3C000-3FFFFh(BC000-BFFFFh): Extended SBCS(00-FFh, ATTR bit 1 = on) - -[IBMJ code to Gaiji address conv tbl from DOS K3.3] - A B C - 2ADC, 2C5F, +5524 --> 8000 - 2614, 2673, +90EC --> B700 - 2384, 2613, +906C --> B3F0 - 0682, 1F7D, +0000 - - 8000 - 8183h 184h(388 characters) IBM Extended Characters - B3F0 - B75Fh 370h(880 characters) User-defined Characters -*/ - -/* Get character line pattern from jfont rom or gaiji volatile memory */ -uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { - da2_t* da2 = (da2_t*)p; - uint32_t font = 0; - int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) - if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) - if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 - font <<= 8; //1111 1111 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 - font >>= 1; //0111 1111 1222 2000 - font <<= 4; //0111 1111 1222 2000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 - font <<= 8; //0111 1111 1222 2000 2222 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 - font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 - //font >>= 1;//put blank at column 1 (and 26) - } - else if (code >= 0xb000 && code <= 0xb75f) - { - //convert code->address in gaiji memory - code -= 0xb000; - code *= 0x80; - //code += 0xf800; - font = da2->mmio.ram[code + line * 4]; - font <<= 8; - font |= da2->mmio.ram[code + line * 4 + 1]; - font <<= 8; - font |= da2->mmio.ram[code + line * 4 + 2]; - font <<= 8; - font |= da2->mmio.ram[code + line * 4 + 3]; - } - else if (code > DA2_FONTROM_SIZE) - font = 0xffffffff; - else - font = 0; - return font; -} - -/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ -uint8_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 getPS55ForeColor(uint8_t attr, da2_t* da2) -{ - uint8_t foreground = ~attr & 0x08;// 0000 1000 - foreground <<= 2; //0010 0000 - foreground |= ~attr & 0xc0;// 1110 0000 - foreground >>= 4;//0000 1110 - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette - return foreground; -} - -void da2_render_blank(da2_t* da2) -{ - int x, xx; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - - for (x = 0; x < da2->hdisp; x++) - { - for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; - } -} -/* Display Adapter Mode 8, E Drawing */ -static void da2_render_text(da2_t* da2) -{ - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //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->vram_display_mask]; - attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; - //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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); - if (attr & 0x04) {//reverse 0000 0100 - bg = fg; - fg = 0; - } - } - else - {//--Parse attribute byte in monochrome mode-- - if (attr & 0x08) fg = 3;//Highlight 0000 1000 - else fg = 2; - bg = 0;//Background is always color #0 (default is black) - if (!(~attr & 0xCC))//Invisible 11xx 11xx -> 00xx 00xx - { - fg = bg; - attr &= 0x33;//disable blinkking, underscore, highlight and reverse - } - if (attr & 0x04) {//reverse 0000 0100 - bg = fg; - fg = 0; - } - // Blinking 1000 0000 - fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; - //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); - } - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half - if (chr_wide == 0) { - if (attr & 0x01) chr_wide = 1; - //chr_wide = 0; - // Stay drawing If the char code is DBCS and not at last column. - if (chr_wide) { - //Get high DBCS code from the next video address - chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; - chr_dbcs <<= 8; - chr_dbcs |= chr; - // Get the font pattern - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; - font <<= 1; - } - } - else { - // the char code is SBCS (ANK) - uint32_t fontbase; - if (attr & 0x02)//second map of SBCS font - fontbase = DA2_GAIJIRAM_SBEX; - else - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font - font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - } - } - // right half of DBCS - else - { - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - 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 - 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) - } - 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) - } - //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); - bg = 0; - if (attr & 0x04) {//Color 0 if reverse - bg = fg; - fg = 0; - } - for (uint32_t n = 0; n < cursorwidth; n++) - if (p[n] == da2->pallook[da2->egapal[cursorcolor]] || da2->egapal[bg] == da2->egapal[cursorcolor]) - p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[fg]] : da2->pallook[da2->egapal[bg]]; - else - p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; - } - da2->ma += 2; - p += 13; - } - da2->ma &= da2->vram_display_mask; - //da2->writelines++; - } -} - -/* Display Adapter Mode 3 Drawing */ -static void da2_render_textm3(da2_t* da2) -{ - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr, extattr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); - for (x = 0; x < da2->hdisp; x += 13) - { - chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; - extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; - //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); - bg = attr >> 4; - //if (da2->blink) bg &= ~0x8; - //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; - fg = attr & 0xf; - fg = IRGBtoBGRI(fg); - bg = IRGBtoBGRI(bg); - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half - if (chr_wide == 0) { - if (extattr & 0x01) chr_wide = 1; - // Stay drawing if the char code is DBCS and not at last column. - if (chr_wide) { - //Get high DBCS code from the next video address - chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; - chr_dbcs <<= 8; - chr_dbcs |= chr; - // Get the font pattern - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; - font <<= 1; - } - } - else { - // the char code is SBCS (ANK) - uint32_t fontbase; - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font - font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - } - } - // right half of DBCS - else - { - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - chr_wide = 0; - } - //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[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; - //bg = 0; - //if (attr & 0x04) {//Color 0 if reverse - // bg = fg; - // fg = 0; - //} - for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]]; - } - da2->ma += 2; - p += 13; - } - da2->ma &= da2->vram_display_mask; - //da2->writelines++; - } -} - -void da2_render_color_4bpp(da2_t* da2) -{ - int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - da2->plane_mask &= 0x0f;//safety - - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); - - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 - { - uint8_t edat[8]; - uint8_t dat; - - //get 8 pixels from vram - da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - da2->ma += 1; - - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); - p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); - p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); - p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); - p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); - p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); - p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); - p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); - p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - p += 8; - } - //da2->writelines++; - } -} - -void da2_render_color_8bpp(da2_t* da2) -{ - int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); - - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 - { - uint8_t edat[8]; - uint8_t dat; - - //get 8 pixels from vram - da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); - da2->ma += 1; - - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | - ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); - p[0] = da2->pallook[dat]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | - ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); - p[1] = da2->pallook[dat]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | - ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); - p[2] = da2->pallook[dat]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | - ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); - p[3] = da2->pallook[dat]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | - ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); - p[4] = da2->pallook[dat]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | - ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); - p[5] = da2->pallook[dat]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | - ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); - p[6] = da2->pallook[dat]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | - ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); - p[7] = da2->pallook[dat]; - p += 8; - } - //da2->writelines++; - } -} - -void da2_updatevidselector(da2_t* da2) { - /* if VGA passthrough mode */ - da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); - if (da2->ioctl[LS_MODE] & 0x02) - { - da2->override = 1; - svga_set_override(da2->mb_vga, 0); - } - else - { - svga_set_override(da2->mb_vga, 1); - da2->override = 0; - } -} - -void da2_recalctimings(da2_t* da2) -{ - double crtcconst; - double _dispontime, _dispofftime, disptime; - - da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w - da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w - da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w - da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare - da2->split = 0xfff; - da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w - da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; - - if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { - da2->hdisp--; - da2->dispend -= 29; - } - else { - //da2->vtotal += 2; - da2->dispend--; - //da2->vsyncstart++; - //da2->split++; - //da2->vblankstart++; - //da2->hdisp--; - } - - da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; - da2->htotal += 1; - - da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline - - da2->clock = da2->da2const; - - //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - - //da2->interlace = 0; - - //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b - da2->ca_adj = 0; - - da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; - - da2->hdisp_time = da2->hdisp; - da2->render = da2_render_blank; - //determine display mode - //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - if (da2->attrc[LV_COMPATIBILITY] & 0x08) - { - if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode - 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_GRAM; - } - else {//PS/55 8-color - da2_log("Set videomode to PS/55 4 bpp graphics.\n"); - da2->vram_display_mask = DA2_MASK_GRAM; - da2->render = da2_render_color_4bpp; - } - } - else {//text mode - if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { - da2_log("Set videomode to PS/55 Mode 03 text.\n"); - da2->render = da2_render_textm3; - da2->vram_display_mask = DA2_MASK_CRAM; - } - else {//PS/55 text(color/mono) - da2_log("Set videomode to PS/55 Mode 8/E text.\n"); - da2->render = da2_render_text; - da2->vram_display_mask = DA2_MASK_CRAM; - } - da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; - da2->char_width = 13; - } - } - else - { - da2_log("Set videomode to blank.\n"); - } - //if (!da2->scrblank && da2->attr_palette_enable) - //{ - //da2->render = da2_draw_text; - //} - - // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - - //if (da2->recalctimings_ex) - // da2->recalctimings_ex(da2); - - if (da2->vblankstart < da2->dispend) - da2->dispend = da2->vblankstart; - - crtcconst = da2->clock * da2->char_width; - - disptime = da2->htotal; - _dispontime = da2->hdisp_time; - - da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); - //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } - _dispofftime = disptime - _dispontime; - _dispontime *= crtcconst; - _dispofftime *= crtcconst; - - da2->dispontime = (uint64_t)_dispontime; - da2->dispofftime = (uint64_t)_dispofftime; - if (da2->dispontime < TIMER_USEC) - da2->dispontime = TIMER_USEC; - if (da2->dispofftime < TIMER_USEC) - 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->render %08X\n", da2->render); -} - -uint8_t da2_mca_read(int port, void *p) -{ - da2_t *da2 = (da2_t *)p; - return da2->pos_regs[port & 7]; -} - -static void da2_mapping_update(da2_t *da2) -{ - if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; - da2->old_pos2 = da2->pos_regs[2]; - //da2_recalc_mapping(da2); - if (da2->pos_regs[2] & 0x01) - { - da2_log("DA2 enable registers\n"); - for (int i = 0; i < 8; i++) - da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); - io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, 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); - } - else - { - da2_log("DA2 disable registers\n"); - 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); - io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); - } -} - -void da2_mca_write(int port, uint8_t val, void *p) -{ - da2_t *da2 = (da2_t *)p; - - da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); - - if (port < 0x102) - return; - da2->pos_regs[port & 7] = val; - - da2_mapping_update(da2); -} - -static uint8_t da2_mca_feedb(void* priv) -{ - const da2_t* da2 = (da2_t*)priv; - - return da2->pos_regs[2] & 0x01; -} - -static void da2_mca_reset(void *p) -{ - da2_t *da2 = (da2_t *)p; - da2_reset(da2); - da2_mca_write(0x102, 0, da2); -} -// -static void da2_gdcropB(uint32_t addr, da2_t* da2) { - for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - } - } - } -} -static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { - uint8_t bitmask_l = bitmask & 0xff; - uint8_t bitmask_h = bitmask >> 8; - for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - } - } - } -} - -static uint8_t da2_mmio_read(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - addr &= DA2_MASK_MMIO; - - if (da2->ioctl[LS_MMIO] & 0x10) { - if (da2->fctl[LF_MMIO_SEL] == 0x80) - //linear access - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); - else - { - //64k bank switch access - uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; - index <<= 8; - index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x40; - } - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); - switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { - case 0xb0://Gaiji RAM - addr &= DA2_MASK_GAIJIRAM;//safety access - //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); - return da2->mmio.ram[addr]; - break; - case 0x10://Font ROM - if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { - if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; - if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, - but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ - } - if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); - return da2->mmio.font[addr]; - break; - default: - return DA2_INVALIDACCESS8;//invalid memory access - break; - } - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode - { - cycles -= video_timing_read_b; - for (int i = 0; i < 8; i++) - da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte - //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 - uint8_t ret = 0; - - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register - ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); - } - return ~ret; - } - else return da2->gdcla[da2->readplane]; - } - else //text mode 3 - { - cycles -= video_timing_read_b; - return da2->vram[addr]; - } -} -static uint16_t da2_mmio_readw(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); - if (da2->ioctl[LS_MMIO] & 0x10) { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode - { - cycles -= video_timing_read_w; - addr &= DA2_MASK_MMIO; - for (int i = 0; i < 8; i++) - da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch - -#ifdef ENABLE_DA2_DEBUGBLT - ////debug - //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) - //{ - // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 16; i++) - //{ - // int pixeldata = 0; - // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; - // fprintf(da2->mmrdbg_fp, "%X", pixeldata); - //} - //da2->mmrdbg_vidaddr = addr; -#endif - - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 - uint16_t ret = 0; - - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register - ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); - } - return ~ret; - } - else - { - //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); - return da2->gdcla[da2->readplane]; - } - } - else { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); - } -} - -static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //da2_log("da2_mmio_write %x %x\n", addr, val); - if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; - addr &= DA2_MASK_MMIO; - - if (da2->ioctl[LS_MMIO] & 0x10) { - //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); - //Gaiji RAM - if (da2->fctl[LF_MMIO_SEL] == 0x80) - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy - else - { - uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; - index <<= 8; - index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x40; - } - switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0://Gaiji RAM 1011 0000 - addr &= DA2_MASK_GAIJIRAM;//safety access - da2->mmio.ram[addr] = val; - break; - case 0x10://Font ROM 0001 0000 - //Read-Only - break; - case 0x00: - //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx - //if (addr >= DA2_BLT_MEMSIZE) - //{ - // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - // return; - //} - da2->bitblt.indata = 1; - if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) - da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - break; - default: - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - break; - } - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode - { - uint8_t wm = da2->writemask; - //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); -#ifdef ENABLE_DA2_DEBUGBLT - //debug - //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, "\nB %x ", addr); - for (int i = 0; i <= 0xb; i++) - fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - } - for (int i = 0; i < 8; i++) - { - int pixeldata = 0; - if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); - fprintf(da2->mmdbg_fp, "%X", pixeldata); - } - da2->mmdbg_vidaddr = addr; - //} -#endif - - cycles -= video_timing_write_b; - - da2->changedvram[addr >> 12] = changeframecount; - addr <<= 3; - - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - - //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); - //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; - da2_gdcropB(addr, da2); - return; - } - - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) 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, 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], da2->gdcreg[LG_BIT_MASK_LOW], 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: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); - da2_gdcropB(addr, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = da2->gdcreg[LG_BIT_MASK_LOW]; - da2->gdcreg[LG_BIT_MASK_LOW] &= val; - - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - da2_gdcropB(addr, da2); - da2->gdcreg[LG_BIT_MASK_LOW] = wm; - 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[addr] = val; - da2->fullchange = 2; - } -} -uint16_t rightRotate(uint16_t data, uint8_t count) -{ - return (data >> count) | (data << (sizeof(data) * 8 - count)); -} -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - uint8_t wm = da2->writemask; - uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - bitmask <<= 8; - bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; -#ifdef ENABLE_DA2_DEBUGBLT - //debug - //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 ", addr); - for (int i = 0; i <= 0xb; i++) - fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - } - for (int i = 0; i < 16; i++) - { - int pixeldata = 0; - if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); - fprintf(da2->mmdbg_fp, "%X", pixeldata); - } - da2->mmdbg_vidaddr = addr; - //} -#endif - cycles -= video_timing_write_w; - //cycles_lost += video_timing_write_w; - - //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); - //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 >> 12] = changeframecount; - da2->changedvram[(addr + 1) >> 12] = changeframecount; - addr <<= 3; - - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; - da2_gdcropW(addr, bitmask, da2); - return; - } - //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; - da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; - } - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work - if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = val & 0xff; - da2->vram[(addr + 8) | i] = val >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else da2->gdcinput[i] = val; - da2_gdcropW(addr, bitmask, da2); - // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - da2->vram[addr | i] = wdata & 0xff; - da2->vram[(addr + 8) | i] = wdata >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work - wm = bitmask; - bitmask &= val; - - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - da2_gdcropW(addr, bitmask, da2); - bitmask = wm; - break; - } - //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); -} -static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0x1ffff) != 0xA0000) return; - if (da2->ioctl[LS_MMIO] & 0x10) { - //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); - da2_mmio_write(addr, val & 0xff, da2); - da2_mmio_write(addr + 1, val >> 8, da2); - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode - { - addr &= DA2_MASK_MMIO; - //return; - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); - da2_mmio_gc_writeW(addr, val, da2); - } - else {//mode 3h text - //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); - da2_mmio_write(addr, val & 0xff, da2); - da2_mmio_write(addr + 1, val >> 8, da2); - } -} - -static void da2_code_write(uint32_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0xfff) != 0xE0000) return; - addr &= DA2_MASK_CRAM; - da2->cram[addr] = val; - da2->fullchange = 2; -} -static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); - cycles -= video_timing_write_b; - da2_code_write(addr, val, da2); -} -static void da2_code_writew(uint32_t addr, uint16_t val, void* p) -{ - //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); - da2_t* da2 = (da2_t*)p; - cycles -= video_timing_write_w; - da2_code_write(addr, val & 0xff, da2); - da2_code_write(addr + 1, val >> 8, da2); -} - -static uint8_t da2_code_read(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; - addr &= DA2_MASK_CRAM; - return da2->cram[addr]; -} -static uint8_t da2_code_readb(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - cycles -= video_timing_read_b; - return da2_code_read(addr, da2); -} -static uint16_t da2_code_readw(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - cycles -= video_timing_read_w; - return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); - //return 0; -} - -void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) -{ - if (wx != xsize || wy != ysize) { - xsize = wx; - ysize = wy; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(32, 0, xsize, ysize); - frames++; - - video_res_x = wx; - video_res_y = wy; - video_bpp = 8; -} - -void da2_poll(void* priv) -{ - da2_t* da2 = (da2_t*)priv; - int x; - - if (!da2->linepos) - { - timer_advance_u64(&da2->timer, da2->dispofftime); - // if (output) printf("Display off %f\n",vidtime); - da2->cgastat |= 1; - da2->linepos = 1; - - if (da2->dispon) - { - da2->hdisp_on = 1; - - da2->ma &= da2->vram_display_mask; - if (da2->firstline == 2000) - { - da2->firstline = da2->displine; - video_wait_for_buffer(); - } - - if (!da2->override) - da2->render(da2); - - if (da2->lastline < da2->displine) - da2->lastline = da2->displine; - } - - //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); - da2->displine++; - //if (da2->interlace) - // da2->displine++; - if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) - { - //da2_log("Vsync off at line %i\n",displine); - da2->cgastat &= ~8; - } - da2->vslines++; - if (da2->displine > 1200) - da2->displine = 0; - // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - // displine, vc, ma); - } - else - { - // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); - timer_advance_u64(&da2->timer, da2->dispontime); - - // if (output) printf("Display on %f\n",vidtime); - if (da2->dispon) - da2->cgastat &= ~1; - da2->hdisp_on = 0; - - da2->linepos = 0; - if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) - da2->con = 0; - if (da2->dispon) - { - if (da2->sc == da2->rowcount) - { - da2->linecountff = 0; - da2->sc = 0; - - da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) - if (da2->interlace) - da2->maback += (da2->rowoffset << 1); - da2->maback &= da2->vram_display_mask; - da2->ma = da2->maback; - } - else - { - da2->sc++; - da2->sc &= 31; - da2->ma = da2->maback; - } - } - - da2->vc++; - da2->vc &= 2047; - - if (da2->vc == da2->dispend) - { - da2->dispon = 0; - //if (da2->crtc[10] & 0x20) da2->cursoron = 0; - //else da2->cursoron = da2->blink & 16; - if (da2->ioctl[LS_MODE] & 1) {//in text mode - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking - { - da2->cursoron = (da2->blink | 1) & da2->blinkconf; - } - else - { - da2->cursoron = 0; - } - if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute - da2->fullchange = 2; - } - da2->blink++; - - for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) - { - if (da2->changedvram[x]) - da2->changedvram[x]--; - } - // memset(changedvram,0,2048); del - if (da2->fullchange) - { - da2->fullchange--; - } - } - if (da2->vc == da2->vsyncstart) - { - int wx, wy; - // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); - da2->dispon = 0; - 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; - - da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); - - da2->firstline = 2000; - da2->lastline = 0; - - da2->firstline_draw = 2000; - da2->lastline_draw = 0; - - da2->oddeven ^= 1; - - 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 %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); - } - if (da2->vc == da2->vtotal) - { - // da2_log("VC vtotal\n"); - - - // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); - da2->vc = 0; - da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; - da2->dispon = 1; - da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; - da2->scrollcache = da2->attrc[LV_PANNING] & 7; - } - 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 da2_loadfont(char* fname, void* p) { - da2_t* da2 = (da2_t*)p; - uint8_t buf; - //uint32_t code = 0; - uint64_t fsize; - if (!fname) return; - if (*fname == '\0') return; - FILE* mfile = rom_fopen(fname, "rb"); - if (!mfile) { - //da2_log("MSG: Can't open binary ROM font file: %s\n", fname); - return; - } - fseek(mfile, 0, SEEK_END); - fsize = ftell(mfile);//get filesize - fseek(mfile, 0, SEEK_SET); - if (fsize > DA2_FONTROM_SIZE) { - fsize = DA2_FONTROM_SIZE;//truncate read data - //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); - //fclose(mfile); - //return 1; - } - uint32_t j = 0; - while (ftell(mfile) < fsize) { - fread(&buf, sizeof(uint8_t), 1, mfile); - da2->mmio.font[j] = buf; - j++; - } - fclose(mfile); - return; -} - -/* 12-bit DAC color palette for IBMJ Display Adapter with color monitor */ -static uint8_t ps55_palette_color[64][3] = -{ -{0x00,0x00,0x00},{0x00,0x00,0x2A},{0x00,0x2A,0x00},{0x00,0x2A,0x2A},{0x2A,0x00,0x00},{0x2A,0x00,0x2A},{0x2A,0x2A,0x00},{0x2A,0x2A,0x2A}, -{0x00,0x00,0x15},{0x00,0x00,0x3F},{0x00,0x2A,0x15},{0x00,0x2A,0x3F},{0x2A,0x00,0x15},{0x2A,0x00,0x3F},{0x2A,0x2A,0x15},{0x2A,0x2A,0x3F}, -{0x00,0x15,0x00},{0x00,0x15,0x2A},{0x00,0x3F,0x00},{0x00,0x3F,0x2A},{0x2A,0x15,0x00},{0x2A,0x15,0x2A},{0x2A,0x3F,0x00},{0x2A,0x3F,0x2A}, -{0x00,0x15,0x15},{0x00,0x15,0x3F},{0x00,0x3F,0x15},{0x00,0x3F,0x3F},{0x2A,0x15,0x15},{0x2A,0x15,0x3F},{0x2A,0x3F,0x15},{0x2A,0x3F,0x3F}, -{0x15,0x00,0x00},{0x15,0x00,0x2A},{0x15,0x2A,0x00},{0x15,0x2A,0x2A},{0x3F,0x00,0x00},{0x3F,0x00,0x2A},{0x3F,0x2A,0x00},{0x3F,0x2A,0x2A}, -{0x15,0x00,0x15},{0x15,0x00,0x3F},{0x15,0x2A,0x15},{0x15,0x2A,0x3F},{0x3F,0x00,0x15},{0x3F,0x00,0x3F},{0x3F,0x2A,0x15},{0x3F,0x2A,0x3F}, -{0x15,0x15,0x00},{0x15,0x15,0x2A},{0x15,0x3F,0x00},{0x15,0x3F,0x2A},{0x3F,0x15,0x00},{0x3F,0x15,0x2A},{0x3F,0x3F,0x00},{0x3F,0x3F,0x2A}, -{0x15,0x15,0x15},{0x15,0x15,0x3F},{0x15,0x3F,0x15},{0x15,0x3F,0x3F},{0x3F,0x15,0x15},{0x3F,0x15,0x3F},{0x3F,0x3F,0x15},{0x3F,0x3F,0x3F} -}; - -void da2_reset_ioctl(da2_t* da2) -{ - da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ - da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ - da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ -} - -static void -da2_reset(void* priv) -{ - da2_t* da2 = (da2_t*)priv; - - /* Initialize drawing */ - da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; - da2_reset_ioctl(da2); - - da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ - da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ - da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ - da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ - da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ - da2->fctl[0] = 0x2b; /* 3E3h:0 */ - da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ - da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ - da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ - da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->ma_latch = 0; - da2->interlace = 0; - da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ - da2->attr_palette_enable = 0; /* disable attribute generator */ - - /* Set default color palette (Windows 3.1 display driver won't reset palette) */ - da2_out(0x3c8, 0, da2); - for (int i = 0; i < 256; i++) { - da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); - } -} - -static void *da2_init() -{ - //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM - - if (svga_get_pri() == NULL) - return NULL; - svga_t *mb_vga = svga_get_pri(); - mb_vga->cable_connected = 0; - - da2_t* da2 = malloc(sizeof(da2_t)); - da2->mb_vga = mb_vga; - - da2->dispontime = 1000ull << 32; - da2->dispofftime = 1000ull << 32; - int memsize = 1024 * 1024; - da2->vram = malloc(memsize); - da2->vram_mask = memsize - 1; - da2->cram = malloc(0x1000); - da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h - da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - - da2->mmio.charset = device_get_config_int("charset"); - da2->mmio.font= malloc(DA2_FONTROM_SIZE); - switch(da2->mmio.charset) - { - case DA2_DCONFIG_CHARSET_HANT: - da2_loadfont(DA2_FONTROM_PATH_HANT, da2); - break; - case DA2_DCONFIG_CHARSET_JPAN: - da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); - break; - } - - mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ -#ifdef ENABLE_DA2_DEBUGBLT - da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); - da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); - da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); - da2->bitblt.debug_reg_ip = 0; -#endif - da2->bitblt.payload_addr = 0; - da2_reset(da2); - - mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); - - mem_mapping_disable(&da2->mmio.mapping); - - mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - - mem_mapping_disable(&da2->cmapping); - - timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ - timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); - - return da2; -} -static int da2_available() -{ - return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); -} - -void da2_close(void *p) -{ - da2_t *da2 = (da2_t *)p; - - /* dump mem for debug */ -#ifndef RELEASE_BUILD - FILE* f; - f = fopen("da2_cram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->cram, 0x1000, 1, f); - fclose(f); - } - f = fopen("da2_vram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vram, 1024*1024, 1, f); - fclose(f); - } - f = fopen("da2_gram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->mmio.ram, 256*1024, 1, f); - fclose(f); - } - f = fopen("da2_attrpal.dmp", "wb"); - if (f != NULL) { - fwrite(da2->attrc, 32, 1, f); - fclose(f); - } - f = fopen("da2_dacrgb.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vgapal, 3*256, 1, f); - fclose(f); - } - f = fopen("da2_daregs.txt", "w"); - if (f != NULL) { - for (int i=0;i<0x10;i++) - fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); - for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); - fclose(f); - } -#endif -#ifdef ENABLE_DA2_DEBUGBLT - f = fopen("da2_bltdump.csv", "w"); - if (f != NULL && da2->bitblt.debug_reg_ip > 0) { - /* print header */ - for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) - fprintf(f, "\"%02X\"\t", y); - } - fprintf(f, "\n"); - /* print data */ - for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { - for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) - ; - else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) - fprintf(f, "\"\"\t"); - else - fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); - } - fprintf(f, "\n"); - } - fclose(f); - } - if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); - if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); -#endif - free(da2->cram); - free(da2->vram); - free(da2->changedvram); - free(da2->mmio.font); - free(da2); -} - -void da2_speed_changed(void *p) -{ - da2_t* da2 = (da2_t*)p; - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - da2_recalctimings(da2); -} - -void da2_force_redraw(void *p) -{ - da2_t* da2 = (da2_t*)p; - - da2->fullchange = changeframecount; -} - -static const device_config_t da2_configuration[] = { - // clang-format off - { - .name = "charset", - .description = "Charset", - .type = CONFIG_SELECTION, - .default_int = DA2_DCONFIG_CHARSET_JPAN, - .selection = { - { - .description = "932 (Japanese)", - .value = DA2_DCONFIG_CHARSET_JPAN - }, - { - .description = "938 (Traditional Chinese)", - .value = DA2_DCONFIG_CHARSET_HANT - }, - { .description = "" } - } - }, - { - .name = "montype", - .description = "Monitor type", - .type = CONFIG_SELECTION, - .default_int = DA2_DCONFIG_MONTYPE_COLOR, - .selection = { - { - .description = "Color", - .value = DA2_DCONFIG_MONTYPE_COLOR - }, - { - .description = "IBM 8515", - .value = DA2_DCONFIG_MONTYPE_8515 - }, - { - .description = "Grayscale", - .value = DA2_DCONFIG_MONTYPE_MONO - }, - { .description = "" } - } - }, - { .name = "", .description = "", .type = CONFIG_END } - // clang-format on -}; - -const device_t ps55da2_device = { - .name = "IBM Display Adapter II (MCA)", - .internal_name = "ps55da2", - .flags = DEVICE_MCA, - .local = 0, - .init = da2_init, - .close = da2_close, - .reset = da2_reset, - { .available = da2_available }, - .speed_changed = da2_speed_changed, - .force_redraw = da2_force_redraw, - .config = da2_configuration -}; - -void -da2_device_add(void) -{ - if (!da2_standalone_enabled) - return; - - if (machine_has_bus(machine, MACHINE_BUS_MCA)) - device_add(&ps55da2_device); - else - return; -} +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/timer.h> +#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> +#include <86box/vid_svga_render.h> +#include "cpu.h" + +#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" +#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" +#define DA2_FONTROM_SIZE 1536*1024 +#define DA2_FONTROM_BASESBCS 0x98000 +#define DA2_GAIJIRAM_SBCS 0x34000 +#define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_INVALIDACCESS8 0xff +#define DA2_MASK_MMIO 0x1ffff +#define DA2_MASK_GRAM 0x1ffff +#define DA2_MASK_CRAM 0xfff +#define DA2_MASK_GAIJIRAM 0x3ffff +#define DA2_PIXELCLOCK 58000000.0 +#define DA2_BLT_MEMSIZE 0x100 +#define DA2_BLT_REGSIZE 0x40 +#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) +#define DA2_DEBUG_BLTLOG_MAX 256*1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLT_USEDRESET 0xfefefe +#define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ +//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ +//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_MONTYPE_COLOR 0x0A +#define DA2_DCONFIG_MONTYPE_8515 0x0B +#define DA2_DCONFIG_MONTYPE_MONO 0x09 + +#define DA2_BLT_CIDLE 0 +#define DA2_BLT_CFILLRECT 1 +#define DA2_BLT_CFILLTILE 2 +#define DA2_BLT_CCOPYF 3 +#define DA2_BLT_CCOPYR 4 +#define DA2_BLT_CPUTCHAR 5 +#define DA2_BLT_CDONE 6 +#define DA2_BLT_CLOAD 7 +/* POS ID = 0xeffe : Display Adapter II, III, V */ +#define DA2_POSID_H 0xef +#define DA2_POSID_L 0xfe +/* + [Identification] + POS ID SYS ID + EFFFh * Display Adapter (PS/55 Model 5571-S0A) [Toledo] + E013h * Layout Display Terminal (PS/55-5571 RPQ model) [LDT] + EFFEh * Display Adapter II (I/O 3E0:0A = xx0x xxxx) [Atlas] + |- FFF2h Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5530Z-SX) + |- FDFEh Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5550-V2) + |- * Display Adapter III,V (I/O 3E0:0A = xx1x xxxx) + ECECh FF4Fh Display Adapter B1 (PS/55 Model 5531Z-SX) [Atlas-KENT] + |- * Display Adapter IV + ECCEh * Display Adapter IV + 901Fh * Display Adapter A2 + 901Dh * Display Adapter A1 [Atlas II] + 901Eh * Plasma Display Adapter + EFD8h * Display Adapter/J [Atlas-SP2] + + [Japanese DOS and Display Adapter compatibility] + | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | + |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| + | EFFFh | Display Adapter | X | | | ? | | + | FFEDh | ? [Atlas EVT] | X | | | ? | | + | FFFDh | ? [LDT EVT] | X | | | ? | | + | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | + | E013h | ? [LDT] | X | X | X | X | | + | ECCEh | Display Adapter IV | | X | X | X | | + | ECECh | Display Adapter IV,B1 | | X | X | X | X | + | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | + | EFD8h | Display Adapter /J | | | X | X | X | +*/ +/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ +#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ +//#define Mon_ID3 0x10 +#define FontCard 0x08 /* ? */ +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ + +/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ +#define AddPage 0x08 /* ? */ +//#define Mon_ID2 0x04 +//#define Mon_ID1 0x02 +//#define Mon_ID0 0x01 +/* Monitor ID (imported from OS/2 DDK 1.2) */ +//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 +//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale +//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp +//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B + +/* DA2 Registers (imported from OS/2 DDK) */ +#define AC_REG 0x3EE +#define AC_DMAE 0x80 +#define AC_FONT_SEL 0x40 +#define FONT_BANK 0x3EF +#define LS_INDEX 0x3E0 +#define LS_DATA 0x3E1 +#define LS_RESET 0x00 +#define LS_MODE 0x02 +#define LS_STATUS 0x03 /* added */ +#define LS_MMIO 0x08 /* added */ +#define LS_CONFIG1 0x0a +#define LS_CONFIG2 0x0b /* added */ +#define LF_INDEX 0x3e2 +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_MMIO_MODE 0x0B /* added */ +#define LC_INDEX 0x3E4 +#define LC_DATA 0x3E5 +#define LC_HORIZONTAL_TOTAL 0x00 +#define LC_H_DISPLAY_ENABLE_END 0x01 +#define LC_START_H_BLANKING 0x02 +#define LC_END_H_BLANKING 0x03 +#define LC_START_HSYNC_PULSE 0x04 +#define LC_END_HSYNC_PULSE 0x05 +#define LC_VERTICAL_TOTALJ 0x06 +#define LC_CRTC_OVERFLOW 0x07 +#define LC_PRESET_ROW_SCANJ 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 +#define LC_CURSOR_ROW_START 0x0A +#define LC_CURSOR_ROW_END 0x0B +#define LC_START_ADDRESS_HIGH 0x0C +#define LC_START_ADDRESS_LOW 0x0D +#define LC_CURSOR_LOC_HIGH 0x0E +#define LC_ROW_CURSOR_LOC 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_COLUMN_CURSOR_LOC 0x0F +#define LC_VERTICAL_SYNC_START 0x10 +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_VERTICAL_SYNC_END 0x11 +#define LC_LIGHT_PEN_LOW 0x11 +#define LC_V_DISPLAY_ENABLE_END 0x12 +#define LC_OFFSET 0x13 +#define LC_UNDERLINE_LOCATION 0x14 +#define LC_START_VERTICAL_BLANK 0x15 +#define LC_END_VERTICAL_BLANK 0x16 +#define LC_LC_MODE_CONTROL 0x17 +#define LC_LINE_COMPAREJ 0x18 +#define LC_START_H_DISPLAY_ENAB 0x19 +#define LC_START_V_DISPLAY_ENAB 0x1A +#define LC_VIEWPORT_COMMAND 0x1B +#define LC_VIEWPORT_SELECT 0x1C +#define LC_VIEWPORT_PRIORITY 0x1D +#define LC_COMMAND 0x1E +#define LC_COMPATIBILITY 0x1F +#define LC_VIEWPORT_NUMBER 0x1F +#define LV_PORT 0x3E8 +#define LV_PALETTE_0 0x00 +#define LV_MODE_CONTROL 0x10 +#define LV_OVERSCAN_COLOR 0x11 +#define LV_COLOR_PLANE_ENAB 0x12 +#define LV_PANNING 0x13 +#define LV_VIEWPORT1_BG 0x14 +#define LV_VIEWPORT2_BG 0x15 +#define LV_VIEWPORT3_BG 0x16 +#define LV_BLINK_COLOR 0x17 +#define LV_BLINK_CODE 0x18 +#define LV_GR_CURSOR_ROTATION 0x19 +#define LV_GR_CURSOR_COLOR 0x1A +#define LV_GR_CURSOR_CONTROL 0x1B +#define LV_COMMAND 0x1C +#define LV_VP_BORDER_LINE 0x1D +#define LV_SYNC_POLARITY 0x1F +#define LV_CURSOR_CODE_0 0x20 +#define LV_GRID_COLOR_0 0x34 +#define LV_GRID_COLOR_1 0x35 +#define LV_GRID_COLOR_2 0x36 +#define LV_GRID_COLOR_3 0x37 +#define LV_ATTRIBUTE_CNTL 0x38 +#define LV_CURSOR_COLOR 0x3A +#define LV_CURSOR_CONTROL 0x3B +#define LV_RAS_STATUS_VIDEO 0x3C +#define LV_PAS_STATUS_CNTRL 0x3D +#define LV_IDENTIFICATION 0x3E +#define LV_OUTPUT 0x3E +#define LV_COMPATIBILITY 0x3F +#define LG_INDEX 0x3EA +#define LG_DATA 0x3EB +#define LG_SET_RESETJ 0x00 +#define LG_ENABLE_SRJ 0x01 +#define LG_COLOR_COMPAREJ 0x02 +#define LG_DATA_ROTATION 0x03 +#define LG_READ_MAP_SELECT 0x04 +#define LG_MODE 0x05 +#define LG_COMPLEMENT 0x06 +#define LG_COLOR_DONT_CARE 0x07 +#define LG_BIT_MASK_LOW 0x08 +#define LG_BIT_MASK_HIGH 0x09 +#define LG_MAP_MASKJ 0x0A +#define LG_COMMAND 0x0B +#define LG_SET_RESET_2 0x10 + +#ifndef RELEASE_BUILD +#define ENABLE_DA2_LOG 1 +#endif + +#ifdef ENABLE_DA2_LOG +int da2_do_log = ENABLE_DA2_LOG; + +static void +da2_log(const char* fmt, ...) +{ + va_list ap; + + if (da2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define da2_log(fmt, ...) +#endif +#ifndef RELEASE_BUILD +# define ENABLE_DA2_DEBUGBLT 1 +#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]; + uint8_t gdcreg[64]; + uint8_t reg3ee[16]; + int gdcaddr; + uint8_t attrc[0x40]; + int attraddr, attrff; + int attr_palette_enable; + //uint8_t seqregs[64]; + int outflipflop; + int inflipflop; + int iolatch; + + int ioctladdr; + int fctladdr; + int crtcaddr; + + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; + + 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; + int dac_r, dac_g; + + uint8_t cgastat; + + uint8_t plane_mask; + + int fb_only; + + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + uint8_t writemask; + uint32_t charseta, charsetb; + + uint8_t egapal[16]; + uint32_t pallook[512]; + PALETTE vgapal; + + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int rowcount; + double clock; + uint32_t ma_latch, ca_adj; + + uint64_t dispontime, dispofftime; + pc_timer_t timer; + uint64_t da2const; + + int dispon; + int hdisp_on; + + uint32_t ma, maback, ca; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink, blinkconf; + int scrollcache; + int char_width; + + int firstline, lastline; + int firstline_draw, lastline_draw; + int displine; + + /* 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; + /* addr >> 12 = xx000h */ + uint8_t *changedvram; + /* (vram size - 1) >> 3 = 0x1FFFF */ + uint32_t vram_display_mask; + + //uint32_t write_bank, read_bank; + + int fullchange; + + void (*render)(struct da2_t* da2); + + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + + /* end VGA compatible regs*/ + struct + { + int enable; + mem_mapping_t mapping; + uint8_t ram[256 * 1024]; + uint8_t *font; + int charset; + } mmio; + + struct { + int bitshift_destr; + int raster_op; + uint8_t payload[DA2_BLT_MEMSIZE]; + int32_t reg[DA2_BLT_REGSIZE];//must be signed int + int32_t* debug_reg;//for debug + int debug_reg_ip;//for debug + int payload_addr; + pc_timer_t timer; + int64_t timerspeed; + int exec; + int indata; + int32_t destaddr; + int32_t srcaddr; + int32_t size_x, tile_w; + int32_t size_y; + int16_t destpitch; + int16_t srcpitch; + int32_t fcolor; + int32_t maskl, maskr; + int x, y; + } bitblt; + + FILE* mmdbg_fp; + FILE* mmrdbg_fp; + uint32_t mmdbg_vidaddr; + uint32_t mmrdbg_vidaddr; + + uint8_t pos_regs[8]; + svga_t *mb_vga; + uint8_t monitorid; + + 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); + +typedef union { + uint32_t d; + uint8_t b[4]; +} DA2_VidSeq32; + +typedef struct { + uint32_t p8[8]; +} pixel32; + +/* safety read for internal functions */ +uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) +{ + if (addr & ~da2->vram_mask) return -1; + return da2->vram[addr]; +} + +void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) +{ + uint32_t writepx[8]; + destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ + //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; + da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; + destaddr <<= 3; + /* read destination data with big endian order */ + for (int i = 0; i < 8; i++) + writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) + | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + + DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; + DA2_VidSeq32 mask32; mask32.d = 0; + mask32.b[3] = mask32in.b[0]; + mask32.b[2] = mask32in.b[1]; + mask32.d &= 0xffff0000; + for (int i = 0; i < 8; i++) + { + if (da2->bitblt.bitshift_destr > 0) + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; + switch (da2->bitblt.raster_op) { + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; + } + } + for (int i = 0; i < 8; i++) { + da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; + da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; + } +} + +void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + //fill data with input color + for (int i = 0; i < 8; i++) + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +/* +Param Desc +01 Color +03 Bit Shift +04 Select plane? +05 Dir(10 or 11) + Command?(40 or 48) +08 Mask Left +09 Mask Right +0A Plane Mask? +0B ROP?(8h or 200h + 0-3h) +0D +20 Exec (1) +21 ? +22 ? +23 Tile W +28 Tile H +29 Dest Addr +2A Src Addr +2B Tile Addr +33 Size W +35 Size H + +*/ +void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + srcaddr &= 0xfffffffe; + srcaddr <<= 3; + for (int i = 0; i < 8; i++) + srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) + | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + if (srcaddr >= DA2_FONTROM_SIZE) { + da2_log("DA2 Putchar Addr Error %x\n", srcaddr); + return; + } + for (int i = 0; i < 8; i++) + srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) + | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) + | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) + | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +#ifdef ENABLE_DA2_DEBUGBLT +uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { + uint8_t pixeldata = 0; + for (int j = 0; j < 8; j++) { + if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; + } + return pixeldata; +} +void print_pixelbyte(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) + { + pclog("%X", pixel1tohex(addr, i, da2)); + } +} +void print_bytetobin(uint8_t b) { + for (int i = 0; i < 8; i++) + { + if(b & 0x80) + pclog("1"); + else + pclog("0"); + b <<= 1; + } +} +//Convert internal char code to Shift JIS code +inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } +inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } +uint16_t IBMJtoSJIS(uint16_t knj) +{ + if (knj < 0x100) return 0xffff; + knj -= 0x100; + if (knj <= 0x1f7d) + ;/* do nothing */ + else if (knj >= 0xb700 && knj <= 0xb75f) { + knj -= 0x90ec; + } + else if (knj >= 0xb3f0 && knj <= 0xb67f) { + knj -= 0x906c; + } + else if (knj >= 0x8000 && knj <= 0x8183) + { + knj -= 0x5524; + } + else + return 0xffff; + uint32_t knj1 = knj / 0xBC; + uint32_t knj2 = knj - (knj1 * 0xBC); + knj1 += 0x81; + if (knj1 > 0x9F) knj1 += 0x40; + knj2 += 0x40; + if (knj2 > 0x7E) knj2++; + //if (!isKanji1(knj1)) return 0xffff; + //if (!isKanji2(knj2)) return 0xffff; + knj = knj1 << 8; + knj |= knj2; + return knj; +} +#endif +void da2_bitblt_load(da2_t* da2) +{ + uint32_t value32; + uint64_t value64; + da2_log("BITBLT loading params\n"); + //da2_log("BitBlt memory:\n"); + //if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + // { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + // } + int i = 0; + while (i < DA2_BLT_MEMSIZE) + { + if (da2->bitblt.reg[0x20] & 0x1) + break; + switch (da2->bitblt.payload[i]) { + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 3; + break; + case 0x91: + value32 = da2->bitblt.payload[i + 5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 5; + break; + case 0x99: + value64 = da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + i += 7; + break; + case 0x00: + break; + default: + da2_log("da2_ParseBLT: Unknown PreOP!\n"); + break; + } + i++; + } + da2->bitblt.exec = DA2_BLT_CIDLE; + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; + /* [89] 20: 0001 (1) then execute payload */ + if (da2->bitblt.reg[0x20] & 0x1) + { +#ifdef ENABLE_DA2_DEBUGBLT + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); + } + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; + } + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; + da2->bitblt.debug_reg_ip++; + if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR + da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); + for (int i = 0; i <= 0xb; i++) + da2_log("%02x ", da2->gdcreg[i]); + da2_log("\n"); + + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destpitch = da2->bitblt.reg[0x21]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + { + da2->bitblt.destaddr -= 2; + da2->bitblt.size_x += 1; + da2->bitblt.destpitch -= 2; + da2->bitblt.srcpitch -= 2; + } + da2->bitblt.fcolor = da2->bitblt.reg[0x0]; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + + if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode + { + da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); + da2->bitblt.exec = DA2_BLT_CDONE; + } + else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + /* Todo: addressing */ + //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + //{ + // da2->bitblt.destaddr += 2; + // da2->bitblt.size_x -= 1; + // da2->bitblt.destpitch += 2; + // da2->bitblt.srcpitch += 2; + //} + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ + da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.exec = DA2_BLT_CFILLRECT; + da2->bitblt.destaddr += 2; + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ + da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr += 2; + da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ + da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); + } + } +} +void da2_bitblt_exec(void* p) +{ + da2_t* da2 = (da2_t*)p; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + switch (da2->bitblt.exec) + { + case DA2_BLT_CIDLE: + timer_disable(&da2->bitblt.timer); + break; + case DA2_BLT_CLOAD: + da2->bitblt.indata = 0; + da2_bitblt_load(da2); + break; + case DA2_BLT_CFILLRECT: + //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CFILLTILE: + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CCOPYF: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr += 2; + break; + case DA2_BLT_CCOPYR: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr -= da2->bitblt.destpitch; + da2->bitblt.srcaddr -= da2->bitblt.srcpitch; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + break; + case DA2_BLT_CPUTCHAR: + //da2->bitblt.y += 2; + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; + pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + //da2->bitblt.srcaddr += 2; + if(da2->bitblt.reg[0x12] < 0x100) + da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + else + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + pclog("\n"); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + //if (1) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 3) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += 130; + //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + //da2->bitblt.srcaddr += -1; + } + else if (da2->bitblt.x == 0) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; + ////da2->bitblt.srcaddr += 2; + //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + break; + case DA2_BLT_CDONE: + /* initialize regs for debug dump */ + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; + else da2->bitblt.exec = DA2_BLT_CIDLE; + break; + } +} +void da2_bitblt_dopayload(da2_t* da2) { + if (da2->bitblt.exec == DA2_BLT_CIDLE) + { + da2->bitblt.exec = DA2_BLT_CLOAD; + //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ + da2_log("da2 Do bitblt\n"); + while (da2->bitblt.exec != DA2_BLT_CIDLE) + { + da2_bitblt_exec(da2); + } + da2_log("da2 End bitblt %x\n", da2->bitblt.exec); + } +} + +void da2_out(uint16_t addr, uint16_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + int oldval; +/* +3E0 3E1 Sequencer Registers (undoc) +3E2 3E3 Font Registers (undoc) +3E4 3E5 CRT Control Registers (undoc) +3E8 3E9 Attribute Controller Registers (undoc) +3EA 3EB 3EC Graphics Contoller Registers +*/ + switch (addr) + { + case 0x3c6: /* PEL Mask */ + da2->dac_mask = val; + break; + case 0x3C7: /* Read Address */ + da2->dac_read = val; + da2->dac_pos = 0; + break; + case 0x3C8: /* Write Address */ + da2->dac_write = val; + da2->dac_read = val - 1; + 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->dac_status = 0; + da2->fullchange = changeframecount; + switch (da2->dac_pos) + { + case 0: + da2->dac_r = val; + da2->dac_pos++; + break; + case 1: + da2->dac_g = val; + da2->dac_pos++; + break; + case 2: + da2->vgapal[da2->dac_write].r = da2->dac_r; + da2->vgapal[da2->dac_write].g = da2->dac_g; + da2->vgapal[da2->dac_write].b = val; + //if (da2->ramdac_type == RAMDAC_8BIT) + // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); + //else + da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); + da2->dac_pos = 0; + da2->dac_write = (da2->dac_write + 1) & 255; + break; + } + break; + case LS_INDEX: + 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); + 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); + oldval = da2->ioctl[da2->ioctladdr]; + da2->ioctl[da2->ioctladdr] = val; + if (oldval != val) { + if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ + da2_reset_ioctl(da2); + else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + da2_updatevidselector(da2); + } + else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ + { + //da2->bitblt.indata = 1; + } + } + break; + case LF_INDEX: + 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); + 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); + oldval = da2->fctl[da2->fctladdr]; + da2->fctl[da2->fctladdr] = val; + if (da2->fctladdr == 0 && oldval != val) + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + } + break; + case LC_INDEX: + da2->crtcaddr = val; + break; + case LC_DATA: + 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); + if (!(da2->crtc[da2->crtcaddr] ^ val)) return; + switch (da2->crtcaddr) { + case LC_CRTC_OVERFLOW: + //return; + break; + case LC_MAXIMUM_SCAN_LINE: + if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; + break; + case LC_START_ADDRESS_HIGH: + //if (da2->crtc[0x1c] & 0x40) return; + break; + case LC_VERTICAL_TOTALJ: /* Vertical Total */ + case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ + case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ + case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ + //val = 0x400; //for debugging bitblt + break; + case LC_VIEWPORT_SELECT: /* ViewPort Select? */ + //return; + break; + case LC_VIEWPORT_NUMBER: /* Compatibility? */ + break; + } + da2->crtc[da2->crtcaddr] = val; + switch (da2->crtcaddr) { + case LC_H_DISPLAY_ENABLE_END: + case LC_VERTICAL_TOTALJ: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + case LC_VERTICAL_SYNC_START: + case LC_V_DISPLAY_ENABLE_END: + case LC_START_VERTICAL_BLANK: + case LC_END_VERTICAL_BLANK: + case LC_VIEWPORT_PRIORITY: + da2->fullchange = changeframecount; + da2_recalctimings(da2); + break; + default: + break; + } + 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); + if (!da2->attrff) + { + // da2->attraddr = val & 31; + da2->attraddr = val & 0x3f; + if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) + { + da2->fullchange = 3; + da2->attr_palette_enable = val & 0x20; + da2_recalctimings(da2); + } + //da2_log("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->attrc[da2->attraddr & 0x3f] = val; + //da2_log("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) + { + for (int c = 0; c < 16; c++) + { + //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); + //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); + if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; + else da2->egapal[c] = da2->attrc[c] & 0x3f; + } + } + switch (da2->attraddr) + { + case LV_COLOR_PLANE_ENAB: + if ((val & 0xff) != da2->plane_mask) + da2->fullchange = changeframecount; + da2->plane_mask = val & 0xff; + break; + case LV_CURSOR_CONTROL: + switch (val & 0x18) { + case 0x08://fast blink + da2->blinkconf = 0x10; + break; + case 0x18://slow blink + da2->blinkconf = 0x20; + break; + default://no blink + da2->blinkconf = 0xff; + break; + } + break; + case LV_MODE_CONTROL: + case LV_ATTRIBUTE_CNTL: + case LV_COMPATIBILITY: + da2_recalctimings(da2); + break; + default: + break; + } + } + da2->attrff ^= 1; + break; + case 0x3E9: + /* VZ Editor's CURSOR.COM writes data via this port */ + da2->attrc[da2->attraddr & 0x3f] = val; + break; + case LG_INDEX: + da2->gdcaddr = val; + break; + case LG_DATA: + //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + //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); + switch (da2->gdcaddr & 0x1f) + { + case LG_READ_MAP_SELECT: + da2->readplane = val & 0x7; + break; + case LG_MODE: + da2->writemode = val & 3; + break; + case LG_MAP_MASKJ: + da2->writemask = val & 0xff; + break; + case LG_COMMAND: + break; + case LG_SET_RESET_2: + da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + return; + } + da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; + break; + //case 0x3ed: /* used by Windows 3.1 display driver */ + // da2->gdcreg[5] = val & 0xff; + // break; + default: + da2_log("DA2? Out addr %03X val %02X\n", addr, val); + break; + } +} + +uint16_t da2_in(uint16_t addr, void *p) +{ + da2_t * da2 = (da2_t *)p; + uint16_t temp; + + switch (addr) + { + case 0x3c3: + temp = 0; + break; + case 0x3c6: temp = da2->dac_mask; + break; + case 0x3c7: temp = da2->dac_status; + break; + case 0x3c8: temp = da2->dac_write; + break; + case 0x3c9: + da2->dac_status = 3; + switch (da2->dac_pos) + { + case 0: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].r & 0x3f; + break; + case 1: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].g & 0x3f; + break; + case 2: + da2->dac_pos = 0; + da2->dac_read = (da2->dac_read + 1) & 255; + temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; + break; + } + break; + case LS_INDEX: + temp = da2->ioctladdr; + break; + case LS_DATA: + //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) + if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; + temp = da2->ioctl[da2->ioctladdr]; + if (da2->ioctladdr == LS_STATUS) { /* Status register */ + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ + if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { + /* grayscale monitor */ + if ((da2->vgapal[0].r >= 10) || (da2->vgapal[0].g >= 40) || (da2->vgapal[0].b >= 10)) + temp &= 0x7F; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */ + else + temp |= 0x80; /* Active when the RGB output voltage is low and the cable is connected to a color monitor. + If the cable or the monitor is wrong, it becomes inactive. */ + } else { + /* color monitor */ + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 80) + temp &= 0x7F; + else + temp |= 0x80; + } + } else { + temp |= 0x80; + } + temp &= 0xf6;//clear busy bits + if (da2->bitblt.indata) /* for OS/2 J1.3 */ + da2_bitblt_dopayload(da2); + if (da2->bitblt.exec != DA2_BLT_CIDLE) + { + //da2_log("exec:%x\n", da2->bitblt.exec); + temp |= 0x08;//wait(bit 3 + bit 0) + //if (!da2->bitblt.timer.enabled) + //{ + // da2_log("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 |= 0x01; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + } + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + break; + case LF_INDEX: + temp = da2->fctladdr; + break; + case LF_DATA: + if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; + temp = da2->fctl[da2->fctladdr]; + break; + case LC_INDEX: + temp = da2->crtcaddr; + break; + case LC_DATA: + if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; + temp = da2->crtc[da2->crtcaddr]; + break; + case LV_PORT: + temp = da2->attraddr | da2->attr_palette_enable; + break; + case 0x3E9: + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ + { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + 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->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ + break; + case LG_INDEX: + temp = da2->gdcaddr; + 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); + break; + } + //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +/* +* Write I/O +* out b(idx), out b(data), out b(data) +* out b(idx), out w(data) +* out b(idx), out w(data), out b(data) +* out w(idx) +* Read I/O +* out b(idx), in b(data) +* out b(idx), in b, in b(data) +* out b(idx), in w(data) +*/ +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->inflipflop = 0; + switch (addr) + { + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + if (da2->outflipflop) + { + /* out b(idx), out b(data), out b(data) */ + da2->iolatch |= (uint16_t)val << 8; + da2->outflipflop = 0; + } + else + {// + da2->iolatch = val; + da2->outflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + default: + da2->iolatch = val; + da2->outflipflop = 0; + break; + } + da2_out(addr, da2->iolatch, da2); +} +void da2_outw(uint16_t addr, uint16_t val, void* p) +{ + //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + switch (addr) + { + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + da2_out(addr, val & 0xff, da2); + da2->iolatch = val >> 8; + da2_out(addr + 1, da2->iolatch, da2); + da2->outflipflop = 1; + break; + case LV_PORT: + da2->attrff = 0; + da2_out(addr, val & 0xff, da2); + da2_out(addr, val >> 8, da2); + 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_out(LG_DATA, val >> 8, da2); + break; + case 0x3ED: + da2->gdcaddr = LG_MODE; + da2_out(LG_DATA, val, da2); + break; + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + default: + da2_out(addr, val, da2); + da2->outflipflop = 0; + break; + case 0x3EE: + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2->reg3ee[val & 0xff] = val >> 8; + break; + } +} +uint8_t da2_inb(uint16_t addr, void* p) +{ + uint8_t temp; + da2_t* da2 = (da2_t*)p; + da2->outflipflop = 0; + switch (addr) + { + case LC_DATA: + if (da2->inflipflop) + { + /* out b(idx), in b(low data), in b(high data) */ + temp = da2->iolatch >> 8; + da2->inflipflop = 0; + } + else + {// + da2->iolatch = da2_in(addr, da2); + temp = da2->iolatch & 0xff; + da2->inflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + case LS_DATA: + case LF_DATA: + case LG_DATA: + default: + temp = da2_in(addr, da2) & 0xff; + da2->inflipflop = 0; + break; + } + //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +uint16_t da2_inw(uint16_t addr, void* p) +{ + //uint16_t temp; + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + da2->outflipflop = 0; + return da2_in(addr, da2); +} +/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ +uint8_t da2_in_ISR(uint16_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t temp = 0; + if (addr == 0x3da) { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} + +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); +} + +/* +The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. + [Character drawing] + SBCS: + 1 2 ... 13 + 1 | H.Grid + |---------------- + 2 | Space + 3 V| + .| + G| Font Pattern + r| (12x24 pixels) + i| + d| +26 |________________ +27 Space + ---------------- +28 Underscore ] + ---------------- >Cursor Position +29 ] + + DBCS: + 1 2 ... 13 1 2 ... 12 13 + 1 | H.Grid | H.Grid | + -|--------------------------|- + 2 | Space | Space | + -|--------------------------|- + 3 V| | |S + .| | |p + G| Font Pattern |a + r| (24x24 pixels) |c + i| | |e + d| | | +26 |_____________|____________| +27 | Space | Space + ------------------------------ +28 | Underscore | Underscore ] + ------------------------------ >Cursor Position +29 | | ] + + [Attributes] + Video mode 08h: + 7 6 5 4 3 2 1 0 + Blink |Under |HGrid |VGrid |Bright|Revers|FntSet|DBCS/SBCS| + + Video mode 0Eh: + -Blue |-Green|HGrid |VGrid |-Red |Revers|FntSet|DBCS/SBCS| + + Bit 1 switches the font bank to the Extended SBCS. DOS K3.x loads APL characters from $SYSEX24.FNT into it. + DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. + This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. + +[Font ROM Map (DA2, Japanese)] +The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. + + Bank 0 + 4800- * + Bank 1, 2, 3 + * - * + Bank 4 + * -0DB6Fh ( 4800-8DB6Fh) : JIS X 0208 DBCS (24 x 24) (IBMJ code: 100-1F7Dh) + 10000-16D1Fh (90000-96D1Fh) : IBM Extended Characters (IBMJ code: 2ADC-2C5Fh) + 18000-1BFCFh (98000-9BFCFh) : JIS X 0201 SBCS (13 x 30) + 1C000-1FFFFh (9C000-9FFFFh) : Codepage 437 characters (13 x 30) + Bank 5 + 00000-0C68Fh (A0000-AC68Fh) : Gaiji used by DOS Bunsho + 10000-13FFFh (B0000-B3FFFh) : Extended SBCS (13 x 30) + 14000-1477Fh (B4000-B477Fh) : Half-width box drawing characters used by DOS Bunsho + 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) + 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) + + Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) + +[Font ROM Map (DA3, Traditional Chinese)] + Bank 0 - 11 : Valid Font ROM data + Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) + Bank 13 : All addresses return 0xFF + +[Gaiji RAM Map (DA2)] + Bank 0 00000-1FFFFh placed between A0000h-BFFFFh + 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes + 1F800-1FFFFh(BF800-BFFFFh): Gaiji Resident (SJIS: F040-F04Fh, IBM: 2384-2393h) 16 chs + + Bank 1 20000-3FFFFh placed between A0000h-BFFFFh + 20000-33FFFh(A0000-B3FFFh): Gaiji Resident (SJIS: F050-F39Ch, IBM: 2394-2613h) 640 chs + 34000-37FFFh(B4000-B7FFFh): Basic SBCS(00-FFh, ATTR bit 1 = off) + 38000-3AFFFh(B8000-BAFFFh): Gaiji Resident (SJIS: F39D-F3FCh, IBM: 2614-2673h) 96 chs + 3C000-3FFFFh(BC000-BFFFFh): Extended SBCS(00-FFh, ATTR bit 1 = on) + +[IBMJ code to Gaiji address conv tbl from DOS K3.3] + A B C + 2ADC, 2C5F, +5524 --> 8000 + 2614, 2673, +90EC --> B700 + 2384, 2613, +906C --> B3F0 + 0682, 1F7D, +0000 + + 8000 - 8183h 184h(388 characters) IBM Extended Characters + B3F0 - B75Fh 370h(880 characters) User-defined Characters +*/ + +/* Get character line pattern from jfont rom or gaiji volatile memory */ +uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { + da2_t* da2 = (da2_t*)p; + uint32_t font = 0; + int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) + if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) + if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { + font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 + font <<= 8; //1111 1111 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 + font >>= 1; //0111 1111 1222 2000 + font <<= 4; //0111 1111 1222 2000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 + font <<= 8; //0111 1111 1222 2000 2222 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 + font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 + //font >>= 1;//put blank at column 1 (and 26) + } + else if (code >= 0xb000 && code <= 0xb75f) + { + //convert code->address in gaiji memory + code -= 0xb000; + code *= 0x80; + //code += 0xf800; + font = da2->mmio.ram[code + line * 4]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 1]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 2]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 3]; + } + else if (code > DA2_FONTROM_SIZE) + font = 0xffffffff; + else + font = 0; + return font; +} + +/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ +uint8_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 getPS55ForeColor(uint8_t attr, da2_t* da2) +{ + uint8_t foreground = ~attr & 0x08;// 0000 1000 + foreground <<= 2; //0010 0000 + foreground |= ~attr & 0xc0;// 1110 0000 + foreground >>= 4;//0000 1110 + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + return foreground; +} + +void da2_render_blank(da2_t* da2) +{ + int x, xx; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + for (x = 0; x < da2->hdisp; x++) + { + for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + } +} +/* Display Adapter Mode 8, E Drawing */ +static void da2_render_text(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //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->vram_display_mask]; + attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; + //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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); + if (attr & 0x04) {//reverse 0000 0100 + bg = fg; + fg = 0; + } + } + else + {//--Parse attribute byte in monochrome mode-- + if (attr & 0x08) fg = 3;//Highlight 0000 1000 + else fg = 2; + bg = 0;//Background is always color #0 (default is black) + if (!(~attr & 0xCC))//Invisible 11xx 11xx -> 00xx 00xx + { + fg = bg; + attr &= 0x33;//disable blinkking, underscore, highlight and reverse + } + if (attr & 0x04) {//reverse 0000 0100 + bg = fg; + fg = 0; + } + // Blinking 1000 0000 + fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; + //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); + } + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + // SBCS or DBCS left half + if (chr_wide == 0) { + if (attr & 0x01) chr_wide = 1; + //chr_wide = 0; + // Stay drawing If the char code is DBCS and not at last column. + if (chr_wide) { + //Get high DBCS code from the next video address + chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } + else { + // the char code is SBCS (ANK) + uint32_t fontbase; + if (attr & 0x02)//second map of SBCS font + fontbase = DA2_GAIJIRAM_SBEX; + else + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + 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 + 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) + } + 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) + } + //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); + bg = 0; + if (attr & 0x04) {//Color 0 if reverse + bg = fg; + fg = 0; + } + for (uint32_t n = 0; n < cursorwidth; n++) + if (p[n] == da2->pallook[da2->egapal[cursorcolor]] || da2->egapal[bg] == da2->egapal[cursorcolor]) + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[fg]] : da2->pallook[da2->egapal[bg]]; + else + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +/* Display Adapter Mode 3 Drawing */ +static void da2_render_textm3(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr, extattr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) + { + chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; + extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; + //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + bg = attr >> 4; + //if (da2->blink) bg &= ~0x8; + //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; + fg = attr & 0xf; + fg = IRGBtoBGRI(fg); + bg = IRGBtoBGRI(bg); + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + // SBCS or DBCS left half + if (chr_wide == 0) { + if (extattr & 0x01) chr_wide = 1; + // Stay drawing if the char code is DBCS and not at last column. + if (chr_wide) { + //Get high DBCS code from the next video address + chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } + else { + // the char code is SBCS (ANK) + uint32_t fontbase; + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //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[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; + //bg = 0; + //if (attr & 0x04) {//Color 0 if reverse + // bg = fg; + // fg = 0; + //} + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[fg]]; + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +void da2_render_color_4bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + da2->plane_mask &= 0x0f;//safety + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); + p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); + p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); + p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); + p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); + p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); + p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); + p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); + p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_render_color_8bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | + ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); + p[0] = da2->pallook[dat]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | + ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); + p[1] = da2->pallook[dat]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | + ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); + p[2] = da2->pallook[dat]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | + ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); + p[3] = da2->pallook[dat]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | + ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); + p[4] = da2->pallook[dat]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | + ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); + p[5] = da2->pallook[dat]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | + ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); + p[6] = da2->pallook[dat]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | + ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); + p[7] = da2->pallook[dat]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_updatevidselector(da2_t* da2) { + /* if VGA passthrough mode */ + da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); + if (da2->ioctl[LS_MODE] & 0x02) + { + da2->override = 1; + svga_set_override(da2->mb_vga, 0); + } + else + { + svga_set_override(da2->mb_vga, 1); + da2->override = 0; + } +} + +void da2_recalctimings(da2_t* da2) +{ + double crtcconst; + double _dispontime, _dispofftime, disptime; + + da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w + da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w + da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w + da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare + da2->split = 0xfff; + da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w + da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + + if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { + da2->hdisp--; + da2->dispend -= 29; + } + else { + //da2->vtotal += 2; + da2->dispend--; + //da2->vsyncstart++; + //da2->split++; + //da2->vblankstart++; + //da2->hdisp--; + } + + da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; + da2->htotal += 1; + + da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline + + da2->clock = da2->da2const; + + //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; + + //da2->interlace = 0; + + //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + da2->ca_adj = 0; + + da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; + + da2->hdisp_time = da2->hdisp; + da2->render = da2_render_blank; + //determine display mode + //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + if (da2->attrc[LV_COMPATIBILITY] & 0x08) + { + if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode + 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_GRAM; + } + else {//PS/55 8-color + da2_log("Set videomode to PS/55 4 bpp graphics.\n"); + da2->vram_display_mask = DA2_MASK_GRAM; + da2->render = da2_render_color_4bpp; + } + } + else {//text mode + if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { + da2_log("Set videomode to PS/55 Mode 03 text.\n"); + da2->render = da2_render_textm3; + da2->vram_display_mask = DA2_MASK_CRAM; + } + else {//PS/55 text(color/mono) + da2_log("Set videomode to PS/55 Mode 8/E text.\n"); + da2->render = da2_render_text; + da2->vram_display_mask = DA2_MASK_CRAM; + } + da2->hdisp *= 13; + da2->hdisp_old = da2->hdisp; + da2->char_width = 13; + } + } + else + { + da2_log("Set videomode to blank.\n"); + } + //if (!da2->scrblank && da2->attr_palette_enable) + //{ + //da2->render = da2_draw_text; + //} + + // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + + //if (da2->recalctimings_ex) + // da2->recalctimings_ex(da2); + + if (da2->vblankstart < da2->dispend) + da2->dispend = da2->vblankstart; + + crtcconst = da2->clock * da2->char_width; + + disptime = da2->htotal; + _dispontime = da2->hdisp_time; + + da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); + //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + da2->dispontime = (uint64_t)_dispontime; + da2->dispofftime = (uint64_t)_dispofftime; + if (da2->dispontime < TIMER_USEC) + da2->dispontime = TIMER_USEC; + if (da2->dispofftime < TIMER_USEC) + 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->render %08X\n", da2->render); +} + +uint8_t da2_mca_read(int port, void *p) +{ + da2_t *da2 = (da2_t *)p; + return da2->pos_regs[port & 7]; +} + +static void da2_mapping_update(da2_t *da2) +{ + if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; + da2->old_pos2 = da2->pos_regs[2]; + //da2_recalc_mapping(da2); + if (da2->pos_regs[2] & 0x01) + { + da2_log("DA2 enable registers\n"); + for (int i = 0; i < 8; i++) + da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); + io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, 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); + } + else + { + da2_log("DA2 disable registers\n"); + 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); + io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + } +} + +void da2_mca_write(int port, uint8_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + + da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); + + if (port < 0x102) + return; + da2->pos_regs[port & 7] = val; + + da2_mapping_update(da2); +} + +static uint8_t da2_mca_feedb(void* priv) +{ + const da2_t* da2 = (da2_t*)priv; + + return da2->pos_regs[2] & 0x01; +} + +static void da2_mca_reset(void *p) +{ + da2_t *da2 = (da2_t *)p; + da2_reset(da2); + da2_mca_write(0x102, 0, da2); +} +// +static void da2_gdcropB(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + } + } + } +} +static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { + uint8_t bitmask_l = bitmask & 0xff; + uint8_t bitmask_h = bitmask >> 8; + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + } + } + } +} + +static uint8_t da2_mmio_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + if (da2->fctl[LF_MMIO_SEL] == 0x80) + //linear access + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); + else + { + //64k bank switch access + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { + case 0xb0://Gaiji RAM + addr &= DA2_MASK_GAIJIRAM;//safety access + //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); + return da2->mmio.ram[addr]; + break; + case 0x10://Font ROM + if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { + if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; + if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, + but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ + } + if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + return da2->mmio.font[addr]; + break; + default: + return DA2_INVALIDACCESS8;//invalid memory access + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode + { + cycles -= video_timing_read_b; + for (int i = 0; i < 8; i++) + da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte + //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint8_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); + } + return ~ret; + } + else return da2->gdcla[da2->readplane]; + } + else //text mode 3 + { + cycles -= video_timing_read_b; + return da2->vram[addr]; + } +} +static uint16_t da2_mmio_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + if (da2->ioctl[LS_MMIO] & 0x10) { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + cycles -= video_timing_read_w; + addr &= DA2_MASK_MMIO; + for (int i = 0; i < 8; i++) + da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch + +#ifdef ENABLE_DA2_DEBUGBLT + ////debug + //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) + //{ + // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 16; i++) + //{ + // int pixeldata = 0; + // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; + // fprintf(da2->mmrdbg_fp, "%X", pixeldata); + //} + //da2->mmrdbg_vidaddr = addr; +#endif + + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint16_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); + } + return ~ret; + } + else + { + //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + return da2->gdcla[da2->readplane]; + } + } + else { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } +} + +static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("da2_mmio_write %x %x\n", addr, val); + if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); + //Gaiji RAM + if (da2->fctl[LF_MMIO_SEL] == 0x80) + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy + else + { + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + switch (da2->fctl[LF_MMIO_MODE]) { + case 0xb0://Gaiji RAM 1011 0000 + addr &= DA2_MASK_GAIJIRAM;//safety access + da2->mmio.ram[addr] = val; + break; + case 0x10://Font ROM 0001 0000 + //Read-Only + break; + case 0x00: + //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + //if (addr >= DA2_BLT_MEMSIZE) + //{ + // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + // return; + //} + da2->bitblt.indata = 1; + if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + break; + default: + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + uint8_t wm = da2->writemask; + //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); +#ifdef ENABLE_DA2_DEBUGBLT + //debug + //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, "\nB %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 8; i++) + { + int pixeldata = 0; + if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; + //} +#endif + + cycles -= video_timing_write_b; + + da2->changedvram[addr >> 12] = changeframecount; + addr <<= 3; + + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + + //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); + //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropB(addr, da2); + return; + } + + switch (da2->writemode) + { + case 2: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) 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, 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], da2->gdcreg[LG_BIT_MASK_LOW], 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: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); + da2_gdcropB(addr, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + wm = da2->gdcreg[LG_BIT_MASK_LOW]; + da2->gdcreg[LG_BIT_MASK_LOW] &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + da2_gdcropB(addr, da2); + da2->gdcreg[LG_BIT_MASK_LOW] = wm; + 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[addr] = val; + da2->fullchange = 2; + } +} +uint16_t rightRotate(uint16_t data, uint8_t count) +{ + return (data >> count) | (data << (sizeof(data) * 8 - count)); +} +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t wm = da2->writemask; + uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + bitmask <<= 8; + bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; +#ifdef ENABLE_DA2_DEBUGBLT + //debug + //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 ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 16; i++) + { + int pixeldata = 0; + if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; + //} +#endif + cycles -= video_timing_write_w; + //cycles_lost += video_timing_write_w; + + //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); + //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 >> 12] = changeframecount; + da2->changedvram[(addr + 1) >> 12] = changeframecount; + addr <<= 3; + + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + return; + } + //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + switch (da2->writemode) + { + case 2: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; + da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + } + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = val & 0xff; + da2->vram[(addr + 8) | i] = val >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + da2->vram[addr | i] = wdata & 0xff; + da2->vram[(addr + 8) | i] = wdata >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + wm = bitmask; + bitmask &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2_gdcropW(addr, bitmask, da2); + bitmask = wm; + break; + } + //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); +} +static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0x1ffff) != 0xA0000) return; + if (da2->ioctl[LS_MMIO] & 0x10) { + //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + addr &= DA2_MASK_MMIO; + //return; + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_gc_writeW(addr, val, da2); + } + else {//mode 3h text + //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } +} + +static void da2_code_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0xfff) != 0xE0000) return; + addr &= DA2_MASK_CRAM; + da2->cram[addr] = val; + da2->fullchange = 2; +} +static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); + cycles -= video_timing_write_b; + da2_code_write(addr, val, da2); +} +static void da2_code_writew(uint32_t addr, uint16_t val, void* p) +{ + //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_write_w; + da2_code_write(addr, val & 0xff, da2); + da2_code_write(addr + 1, val >> 8, da2); +} + +static uint8_t da2_code_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; + addr &= DA2_MASK_CRAM; + return da2->cram[addr]; +} +static uint8_t da2_code_readb(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_b; + return da2_code_read(addr, da2); +} +static uint16_t da2_code_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_w; + return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); + //return 0; +} + +void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) +{ + if (wx != xsize || wy != ysize) { + xsize = wx; + ysize = wy; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(32, 0, xsize, ysize); + frames++; + + video_res_x = wx; + video_res_y = wy; + video_bpp = 8; +} + +void da2_poll(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + int x; + + if (!da2->linepos) + { + timer_advance_u64(&da2->timer, da2->dispofftime); + // if (output) printf("Display off %f\n",vidtime); + da2->cgastat |= 1; + da2->linepos = 1; + + if (da2->dispon) + { + da2->hdisp_on = 1; + + da2->ma &= da2->vram_display_mask; + if (da2->firstline == 2000) + { + da2->firstline = da2->displine; + video_wait_for_buffer(); + } + + if (!da2->override) + da2->render(da2); + + if (da2->lastline < da2->displine) + da2->lastline = da2->displine; + } + + //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + da2->displine++; + //if (da2->interlace) + // da2->displine++; + if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) + { + //da2_log("Vsync off at line %i\n",displine); + da2->cgastat &= ~8; + } + da2->vslines++; + if (da2->displine > 1200) + da2->displine = 0; + // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + // displine, vc, ma); + } + else + { + // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + timer_advance_u64(&da2->timer, da2->dispontime); + + // if (output) printf("Display on %f\n",vidtime); + if (da2->dispon) + da2->cgastat &= ~1; + da2->hdisp_on = 0; + + da2->linepos = 0; + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) + da2->con = 0; + if (da2->dispon) + { + if (da2->sc == da2->rowcount) + { + da2->linecountff = 0; + da2->sc = 0; + + da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) + if (da2->interlace) + da2->maback += (da2->rowoffset << 1); + da2->maback &= da2->vram_display_mask; + da2->ma = da2->maback; + } + else + { + da2->sc++; + da2->sc &= 31; + da2->ma = da2->maback; + } + } + + da2->vc++; + da2->vc &= 2047; + + if (da2->vc == da2->dispend) + { + da2->dispon = 0; + //if (da2->crtc[10] & 0x20) da2->cursoron = 0; + //else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) {//in text mode + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + { + da2->cursoron = (da2->blink | 1) & da2->blinkconf; + } + else + { + da2->cursoron = 0; + } + if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute + da2->fullchange = 2; + } + da2->blink++; + + for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) + { + if (da2->changedvram[x]) + da2->changedvram[x]--; + } + // memset(changedvram,0,2048); del + if (da2->fullchange) + { + da2->fullchange--; + } + } + if (da2->vc == da2->vsyncstart) + { + int wx, wy; + // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + da2->dispon = 0; + 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; + + da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); + + da2->firstline = 2000; + da2->lastline = 0; + + da2->firstline_draw = 2000; + da2->lastline_draw = 0; + + da2->oddeven ^= 1; + + 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 %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + } + if (da2->vc == da2->vtotal) + { + // da2_log("VC vtotal\n"); + + + // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + da2->vc = 0; + da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->dispon = 1; + da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + da2->scrollcache = da2->attrc[LV_PANNING] & 7; + } + 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 da2_loadfont(char* fname, void* p) { + da2_t* da2 = (da2_t*)p; + uint8_t buf; + //uint32_t code = 0; + uint64_t fsize; + if (!fname) return; + if (*fname == '\0') return; + FILE* mfile = rom_fopen(fname, "rb"); + if (!mfile) { + //da2_log("MSG: Can't open binary ROM font file: %s\n", fname); + return; + } + fseek(mfile, 0, SEEK_END); + fsize = ftell(mfile);//get filesize + fseek(mfile, 0, SEEK_SET); + if (fsize > DA2_FONTROM_SIZE) { + fsize = DA2_FONTROM_SIZE;//truncate read data + //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); + //fclose(mfile); + //return 1; + } + uint32_t j = 0; + while (ftell(mfile) < fsize) { + fread(&buf, sizeof(uint8_t), 1, mfile); + da2->mmio.font[j] = buf; + j++; + } + fclose(mfile); + return; +} + +/* 12-bit DAC color palette for IBMJ Display Adapter with color monitor */ +static uint8_t ps55_palette_color[64][3] = +{ +{0x00,0x00,0x00},{0x00,0x00,0x2A},{0x00,0x2A,0x00},{0x00,0x2A,0x2A},{0x2A,0x00,0x00},{0x2A,0x00,0x2A},{0x2A,0x2A,0x00},{0x2A,0x2A,0x2A}, +{0x00,0x00,0x15},{0x00,0x00,0x3F},{0x00,0x2A,0x15},{0x00,0x2A,0x3F},{0x2A,0x00,0x15},{0x2A,0x00,0x3F},{0x2A,0x2A,0x15},{0x2A,0x2A,0x3F}, +{0x00,0x15,0x00},{0x00,0x15,0x2A},{0x00,0x3F,0x00},{0x00,0x3F,0x2A},{0x2A,0x15,0x00},{0x2A,0x15,0x2A},{0x2A,0x3F,0x00},{0x2A,0x3F,0x2A}, +{0x00,0x15,0x15},{0x00,0x15,0x3F},{0x00,0x3F,0x15},{0x00,0x3F,0x3F},{0x2A,0x15,0x15},{0x2A,0x15,0x3F},{0x2A,0x3F,0x15},{0x2A,0x3F,0x3F}, +{0x15,0x00,0x00},{0x15,0x00,0x2A},{0x15,0x2A,0x00},{0x15,0x2A,0x2A},{0x3F,0x00,0x00},{0x3F,0x00,0x2A},{0x3F,0x2A,0x00},{0x3F,0x2A,0x2A}, +{0x15,0x00,0x15},{0x15,0x00,0x3F},{0x15,0x2A,0x15},{0x15,0x2A,0x3F},{0x3F,0x00,0x15},{0x3F,0x00,0x3F},{0x3F,0x2A,0x15},{0x3F,0x2A,0x3F}, +{0x15,0x15,0x00},{0x15,0x15,0x2A},{0x15,0x3F,0x00},{0x15,0x3F,0x2A},{0x3F,0x15,0x00},{0x3F,0x15,0x2A},{0x3F,0x3F,0x00},{0x3F,0x3F,0x2A}, +{0x15,0x15,0x15},{0x15,0x15,0x3F},{0x15,0x3F,0x15},{0x15,0x3F,0x3F},{0x3F,0x15,0x15},{0x3F,0x15,0x3F},{0x3F,0x3F,0x15},{0x3F,0x3F,0x3F} +}; + +void da2_reset_ioctl(da2_t* da2) +{ + da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ + da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ + da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ +} + +static void +da2_reset(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + + /* Initialize drawing */ + da2->bitblt.exec = DA2_BLT_CIDLE; + da2->render = da2_render_blank; + da2_reset_ioctl(da2); + + da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ + da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ + da2->fctl[0] = 0x2b; /* 3E3h:0 */ + da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ + da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ + da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ + da2->ma_latch = 0; + da2->interlace = 0; + da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attr_palette_enable = 0; /* disable attribute generator */ + + /* Set default color palette (Windows 3.1 display driver won't reset palette) */ + da2_out(0x3c8, 0, da2); + for (int i = 0; i < 256; i++) { + da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); + } +} + +static void *da2_init() +{ + //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM + + if (svga_get_pri() == NULL) + return NULL; + svga_t *mb_vga = svga_get_pri(); + mb_vga->cable_connected = 0; + + da2_t* da2 = malloc(sizeof(da2_t)); + da2->mb_vga = mb_vga; + + da2->dispontime = 1000ull << 32; + da2->dispofftime = 1000ull << 32; + int memsize = 1024 * 1024; + da2->vram = malloc(memsize); + da2->vram_mask = memsize - 1; + da2->cram = malloc(0x1000); + da2->vram_display_mask = DA2_MASK_CRAM; + da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ + + da2->mmio.charset = device_get_config_int("charset"); + da2->mmio.font= malloc(DA2_FONTROM_SIZE); + switch(da2->mmio.charset) + { + case DA2_DCONFIG_CHARSET_HANT: + da2_loadfont(DA2_FONTROM_PATH_HANT, da2); + break; + case DA2_DCONFIG_CHARSET_JPAN: + da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + break; + } + + mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ +#ifdef ENABLE_DA2_DEBUGBLT + da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); + da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); + da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.payload_addr = 0; + da2_reset(da2); + + mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); + + mem_mapping_disable(&da2->mmio.mapping); + + mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + + mem_mapping_disable(&da2->cmapping); + + timer_add(&da2->timer, da2_poll, da2, 0); + da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + + return da2; +} +static int da2_available() +{ + return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); +} + +void da2_close(void *p) +{ + da2_t *da2 = (da2_t *)p; + + /* dump mem for debug */ +#ifndef RELEASE_BUILD + FILE* f; + f = fopen("da2_cram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->cram, 0x1000, 1, f); + fclose(f); + } + f = fopen("da2_vram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vram, 1024*1024, 1, f); + fclose(f); + } + f = fopen("da2_gram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->mmio.ram, 256*1024, 1, f); + fclose(f); + } + f = fopen("da2_attrpal.dmp", "wb"); + if (f != NULL) { + fwrite(da2->attrc, 32, 1, f); + fclose(f); + } + f = fopen("da2_dacrgb.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vgapal, 3*256, 1, f); + fclose(f); + } + f = fopen("da2_daregs.txt", "w"); + if (f != NULL) { + for (int i=0;i<0x10;i++) + fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (int i = 0; i < 0x40; i++) + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + fclose(f); + } +#endif +#ifdef ENABLE_DA2_DEBUGBLT + f = fopen("da2_bltdump.csv", "w"); + if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + /* print header */ + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) + fprintf(f, "\"%02X\"\t", y); + } + fprintf(f, "\n"); + /* print data */ + for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) + ; + else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) + fprintf(f, "\"\"\t"); + else + fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); + } + fprintf(f, "\n"); + } + fclose(f); + } + if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); + if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); + free(da2->bitblt.debug_reg); +#endif + free(da2->cram); + free(da2->vram); + free(da2->changedvram); + free(da2->mmio.font); + free(da2); +} + +void da2_speed_changed(void *p) +{ + da2_t* da2 = (da2_t*)p; + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + da2_recalctimings(da2); +} + +void da2_force_redraw(void *p) +{ + da2_t* da2 = (da2_t*)p; + + da2->fullchange = changeframecount; +} + +static const device_config_t da2_configuration[] = { + // clang-format off + { + .name = "charset", + .description = "Charset", + .type = CONFIG_SELECTION, + .default_int = DA2_DCONFIG_CHARSET_JPAN, + .selection = { + { + .description = "932 (Japanese)", + .value = DA2_DCONFIG_CHARSET_JPAN + }, + { + .description = "938 (Traditional Chinese)", + .value = DA2_DCONFIG_CHARSET_HANT + }, + { .description = "" } + } + }, + { + .name = "montype", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_int = DA2_DCONFIG_MONTYPE_COLOR, + .selection = { + { + .description = "Color", + .value = DA2_DCONFIG_MONTYPE_COLOR + }, + { + .description = "IBM 8515", + .value = DA2_DCONFIG_MONTYPE_8515 + }, + { + .description = "Grayscale", + .value = DA2_DCONFIG_MONTYPE_MONO + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ps55da2_device = { + .name = "IBM Display Adapter II (MCA)", + .internal_name = "ps55da2", + .flags = DEVICE_MCA, + .local = 0, + .init = da2_init, + .close = da2_close, + .reset = da2_reset, + { .available = da2_available }, + .speed_changed = da2_speed_changed, + .force_redraw = da2_force_redraw, + .config = da2_configuration +}; + +void +da2_device_add(void) +{ + if (!da2_standalone_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&ps55da2_device); + else + return; +} From dc7e6c2d7fb2851f06d4a01847870f4fda05e600 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:05:16 +0900 Subject: [PATCH 0268/1190] Disabled DA2 debug logging by default --- src/video/vid_ps55da2.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 0ac136630..abbc3de16 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -228,10 +228,11 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 +//#define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG +#define ENABLE_DA2_DEBUGBLT 1 int da2_do_log = ENABLE_DA2_LOG; static void @@ -248,9 +249,6 @@ da2_log(const char* fmt, ...) #else # define da2_log(fmt, ...) #endif -#ifndef RELEASE_BUILD -# define ENABLE_DA2_DEBUGBLT 1 -#endif typedef struct da2_t { @@ -710,31 +708,35 @@ void da2_bitblt_load(da2_t* da2) // da2->bitblt.destpitch += 2; // da2->bitblt.srcpitch += 2; //} - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; +#ifdef ENABLE_DA2_DEBUGBLT + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); +#endif } else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; +#ifdef ENABLE_DA2_DEBUGBLT + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); +#endif } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", @@ -898,15 +900,15 @@ void da2_bitblt_exec(void* p) case DA2_BLT_CPUTCHAR: //da2->bitblt.y += 2; da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + //pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); //da2->bitblt.srcaddr += 2; if(da2->bitblt.reg[0x12] < 0x100) da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; else da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - pclog("\n"); + //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + //pclog("\n"); if (da2->bitblt.x >= da2->bitblt.size_x - 1) { //if (1) { DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); @@ -3059,7 +3061,7 @@ void da2_close(void *p) da2_t *da2 = (da2_t *)p; /* dump mem for debug */ -#ifndef RELEASE_BUILD +#ifdef ENABLE_DA2_LOG FILE* f; f = fopen("da2_cram.dmp", "wb"); if (f != NULL) { From a850821ecb5a01d73fbcb9e9225b6185a67586e7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:29:44 +0900 Subject: [PATCH 0269/1190] updated comment in monitor detection (vid_svga .c) --- src/video/vid_svga.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index ef6381598..5d0db103b 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -511,10 +511,12 @@ svga_in(uint16_t addr, void *priv) } else { - // The Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). - // When the monitor cable is connected to the Display Adapter, this port returns the value as no cable connection. - // The Power-on Self Test of PS/55 tries detecting the monitor on the planar VGA. - // If it fails, then the POST reads the NVRAM set by the reference diskette, and sets the BIOS Data Area (Mem 487h, 489h). + /* + The IBM PS/55 Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). + When the monitor cable is connected to the Display Adapter, this port returns the value as 'no cable connection'. + The POST of PS/55 has an extra code that tries detecting the monitor on the planar VGA. + If it fails, then the POST reads the NVRAM set by the reference diskette, and updates the BIOS Data Area (Mem 487h, 489h). + */ if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) ret = 0; else From aa7d5d2dc2c4cd7b58dfdf1d478c176a63f41f0d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:49:26 +0900 Subject: [PATCH 0270/1190] removed unused device decl --- src/floppy/fdc.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 75c2c10af..243df4ca5 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -722,7 +722,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if ((val & 4) && !(fdc->dor & 4)) fdc_soft_reset(fdc); /* We can now simplify this since each motor now spins separately. */ - for (int i = 0; i < FDD_NUM; i++) { + for (i = 0; i < FDD_NUM; i++) { drive_num = real_drive(fdc, i); if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) val &= ~(0x10 << drive_num); @@ -2612,20 +2612,6 @@ const device_t fdc_at_actlow_device = { .config = NULL }; -const device_t fdc_at_ps2_device = { - .name = "PC/AT Floppy Drive Controller (PS/2 internal)", - .internal_name = "fdc_at_ps55", - .flags = 0, - .local = FDC_FLAG_AT | FDC_FLAG_PS2, - .init = fdc_init, - .close = fdc_close, - .reset = fdc_reset, - {.available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - const device_t fdc_at_smc_device = { .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .internal_name = "fdc_at_smc", From 16fc5e79020a2b65f3126d6a80d8c65dbe7e1aba Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 12:08:50 +0900 Subject: [PATCH 0271/1190] corrected compile errors, removed garbage --- src/disk/hdc_esdi_mca.c | 2 +- src/floppy/fdc.c | 21 +-------------------- src/machine/m_ps2_mca.c | 6 +++--- src/video/vid_ps55da2.c | 2 +- 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 5656181f0..5b471b754 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1514,7 +1514,7 @@ esdi_integrated_device = { .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - {.available = NULL }, + .available = esdi_available, .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 243df4ca5..1692a7aaa 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -722,7 +722,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if ((val & 4) && !(fdc->dor & 4)) fdc_soft_reset(fdc); /* We can now simplify this since each motor now spins separately. */ - for (i = 0; i < FDD_NUM; i++) { + for (int i = 0; i < FDD_NUM; i++) { drive_num = real_drive(fdc, i); if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) val &= ~(0x10 << drive_num); @@ -1284,25 +1284,6 @@ fdc_read(uint16_t addr, void *priv) if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; } - else if (fdc->flags & FDC_FLAG_PS2) { - /* Status Register A (PS/2, PS/55) */ - /* | INT PEND | nDRV2 | STEP | nTRK0 | HDSEL | nIDX | nWP | DIR | */ - ret = 0x04; - if (!fdc->seek_dir) /* DIRECTION */ - ret |= 0x01; - if (!writeprot[drive]) /* nWRITEPROT */ - ret |= 0x02; - if (fdd_get_head(drive)) /* HDSEL */ - ret |= 0x08; - if (!fdd_track0(drive)) /* nTRK0 */ - ret |= 0x10; - if (fdc->step) /* STEP */ - ret |= 0x20; - if (!fdd_get_type(1)) /* -Drive 2 Installed */ - ret |= 0x40; - if (fdc->fintr || fdc->reset_stat) /* INTR */ - ret |= 0x80; - } else ret = 0xff; break; diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index c355ba4b2..b948c984c 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -780,13 +780,13 @@ ps55_model_50tv_write(uint16_t port, uint8_t val) switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: break; diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index abbc3de16..98b827421 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -3205,7 +3205,7 @@ const device_t ps55da2_device = { .init = da2_init, .close = da2_close, .reset = da2_reset, - { .available = da2_available }, + .available = da2_available, .speed_changed = da2_speed_changed, .force_redraw = da2_force_redraw, .config = da2_configuration From c6dfd688f4dd8516e611b388fc5c53740deddefd Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 15 Feb 2025 07:09:14 +0100 Subject: [PATCH 0272/1190] 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 db056e0b66ee0262c8db06aada25b39829a98720 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 16:44:07 +0900 Subject: [PATCH 0273/1190] fixed a floppy drive access issue It took a few hours that I noticed fdc.c decides the floppy drive type by the machine name. --- src/floppy/fdc.c | 10 ++++------ src/floppy/fdd.c | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 1692a7aaa..7f025df2d 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -743,7 +743,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ - if (fdc->flags & FDC_FLAG_PS2) { + if (fdc->flags & FDC_FLAG_PS2_MCA) { if (val & 0x04) { fdc->tfifo = 8; @@ -769,6 +769,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 5: /*Command register*/ if (fdc->fifointest) { + /* Write FIFO buffer in the test mode (PS/55) */ fdc_log("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); fifo_write(val, fdc->fifo_p); if (fifo_get_full(fdc->fifo_p)) @@ -1358,10 +1359,7 @@ fdc_read(uint16_t addr, void *priv) ret = 0x10; else ret = 0x00; - } - else if (fdc->flags & FDC_FLAG_PS2) { - /* error when ret = 1, 2*/ - ret = (fdc->fifointest) ? 4 : 0; + /* PS/55 POST throws an error and halt if ret = 1 or 2, somehow. */ } else if (!fdc->enh_mode) ret = 0x20; @@ -1374,6 +1372,7 @@ fdc_read(uint16_t addr, void *priv) case 5: /*Data*/ if (fdc->fifointest) { + /* Read FIFO buffer in the test mode (PS/55) */ ret = fifo_read(fdc->fifo_p); break; } @@ -1698,7 +1697,6 @@ fdc_callback(void *priv) else if (fdc->params[5] == 0) fdc->sector++; ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); - //fdc_log("cb_rwsect: %d %d %d %d %d %xh\n", real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); switch (fdc->interrupt) { case 5: case 9: diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index f0a32df75..d3d513b9f 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -294,7 +294,7 @@ fdd_type_invert_densel(int type) int ret; if (drive_types[type].flags & FLAG_PS2) - ret = (!!strstr(machine_getname(), "PS/1")) || (!!strstr(machine_getname(), "PS/2")); + ret = (!!strstr(machine_getname(), "PS/1")) || (!!strstr(machine_getname(), "PS/2")) || (!!strstr(machine_getname(), "PS/55")); else ret = drive_types[type].flags & FLAG_INVERT_DENSEL; From 75ccfc6e2dfccde089a8b47476c24fcc6f94eb0b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 16:58:11 +0900 Subject: [PATCH 0274/1190] Integrated ESDI doesn't need an external ROM --- src/disk/hdc.c | 2 +- src/disk/hdc_esdi_mca.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 3ec6358d8..f09a9a430 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -77,7 +77,7 @@ static const struct { { &xtide_acculogic_device }, { &xtide_device }, { &esdi_ps2_device }, - { &esdi_integrated_device }, + { &esdi_integrated_device }, { &ide_pci_device }, { &ide_pci_2ch_device }, { &ide_vlb_device }, diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 5b471b754..df2a26349 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1514,7 +1514,7 @@ esdi_integrated_device = { .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - .available = esdi_available, + .available = NULL, /* The Disk BIOS is included in the System ROM */ .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config From 3a09622a91c6b25d7f10425f731a07926873cdb9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 17:36:00 +0900 Subject: [PATCH 0275/1190] added switching ca keys by kbd scancode set --- src/86box.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/86box.c b/src/86box.c index 764f707ba..1cd0ffec8 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1094,14 +1094,24 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { - /* Use R-Alt because PS/55 DOS assigns L-Alt as Kanji */ - keyboard_input(1, 0x1D); /* Ctrl key pressed */ - keyboard_input(1, 0x138); /* R-Alt key pressed */ - keyboard_input(1, sc); - usleep(50000); - keyboard_input(0, sc); - keyboard_input(0, 0x138); /* R-Alt key released */ - keyboard_input(0, 0x1D); /* Ctrl key released */ + if (keyboard_mode == 0x8A) { + /* Use R-Alt because PS/55 DOS assigns L-Alt Kanji */ + keyboard_input(1, 0x1D); /* Ctrl key pressed */ + keyboard_input(1, 0x138); /* R-Alt key pressed */ + keyboard_input(1, sc); + usleep(50000); + keyboard_input(0, sc); + keyboard_input(0, 0x138); /* R-Alt key released */ + keyboard_input(0, 0x1D); /* Ctrl key released */ + } else { + keyboard_input(1, 0x1D); /* Ctrl key pressed */ + keyboard_input(1, 0x38); /* Alt key pressed */ + keyboard_input(1, sc); + usleep(50000); + keyboard_input(0, sc); + keyboard_input(0, 0x38); /* Alt key released */ + keyboard_input(0, 0x1D); /* Ctrl key released */ + } } /* Send the machine a Control-Alt-DEL sequence. */ From dbeaa2a56b122d175202721ba8efd8cea3a6212e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 17:38:24 +0900 Subject: [PATCH 0276/1190] minor update in comparison table --- src/device/keyboard_at.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index b78fbd653..5c66029ad 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1648,14 +1648,14 @@ static const scancode scancode_set3[512] = { Currently, scancode set 81h and 82h are not implemented yet. Also, the key layout is designed to match with the Japanese keyboard. - [Japanese DOS and keyboard scancode set] - | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | PC DOS 5 | + [Japanese DOS and keyboard scancode set comparison] + | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | DOS 5(US)| |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| | IBM 101-key | n/a | n/a | n/a | n/a | 2 | n/a | 2 | - | IBM-J 5576-00x (obsolete) | 8A | 8A | 8A | 82 | 82 | 82 | 2 | - | OADG (modern JA standard) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ + | IBM-J 5576-00x (obsolete) | 8Ah | 8Ah | 8Ah | 82h | 82h | 82h | 2 | + | OADG (modern Japanese) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ -/* Scancode set 8Ah : 5556 keyboard compatible scancode set used by J-DOS */ +/* Scancode set 8Ah : IBM 5556 keyboard compatible scancode set used by J-DOS */ static scancode scancode_set8a[512] = { // clang-format off From 1c7a8e5bbba516fc50b4c91f81fde3521bad3994 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:32:12 +0900 Subject: [PATCH 0277/1190] updated comments, modified format --- src/video/vid_ps55da2.c | 336 ++++++++++++++++++++-------------------- 1 file changed, 170 insertions(+), 166 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 98b827421..5098fa64d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -6,11 +6,11 @@ * * This file is part of the 86Box distribution. * - * IBM PS/55 Display Adapter II emulation. + * IBM PS/55 Display Adapter II (and its successors) emulation. * * Authors: Akamaki. * - * Copyright 2024 Akamaki. + * Copyright 2024-2025 Akamaki. */ #include @@ -58,6 +58,8 @@ #define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ //#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ //#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +/* These ROMs are currently not found. + At least, IBM-J released a Korean and PRC version of PS/55 for each market. */ #define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A #define DA2_DCONFIG_MONTYPE_8515 0x0B @@ -108,21 +110,23 @@ #define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ //#define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ -/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ #define Page_One 0x06 /* 80000h 110b */ #define Page_Two 0x05 /* 100000h 101b */ #define Page_Four 0x03 /* 200000h 011b */ +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode unsupported). */ /* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ #define AddPage 0x08 /* ? */ //#define Mon_ID2 0x04 //#define Mon_ID1 0x02 //#define Mon_ID0 0x01 -/* Monitor ID (imported from OS/2 DDK 1.2) */ -//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 -//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale -//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp -//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B + +/* Monitor ID (imported from OS/2 DDK 1.2) +#define StarbuckC 0x0A // 1 010b IBM 8514, 9518 color 1040x768 +#define StarbuckM 0x09 // 1 001b IBM 8507, 8604 grayscale +#define Lark_B 0x02 // 0 010b IBM 9517 color 1040x768 but 4bpp +#define Dallas 0x0B // 1 011b IBM 8515, 9515 color 1040x740 another palette +*/ /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -467,9 +471,9 @@ void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) { pixel32 srcpx; - //fill data with input color + /* fill data with input color */ for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;/* read in word */ DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -494,7 +498,6 @@ Param Desc 2B Tile Addr 33 Size W 35 Size H - */ void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) { @@ -505,7 +508,7 @@ void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word + | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -520,7 +523,7 @@ void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word + | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -666,8 +669,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.debug_reg_ip++; if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);/* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;/* 01 AND, 03 XOR */ da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); for (int i = 0; i <= 0xb; i++) da2_log("%02x ", da2->gdcreg[i]); @@ -678,7 +681,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.size_y = da2->bitblt.reg[0x35]; da2->bitblt.destpitch = da2->bitblt.reg[0x21]; da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; - if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; da2->bitblt.size_x += 1; @@ -693,7 +696,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode + if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ { da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); da2->bitblt.exec = DA2_BLT_CDONE; @@ -701,7 +704,7 @@ void da2_bitblt_load(da2_t* da2) else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ - //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + //if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ //{ // da2->bitblt.destaddr += 2; // da2->bitblt.size_x -= 1; @@ -738,14 +741,16 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ + /* Fill a rectangle(or draw a line) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + /* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -756,7 +761,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ + /* Tiling a rectangle (transfer tile data multiple times) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -767,7 +773,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ + /* Block transfer (range copy) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; @@ -777,7 +784,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ + /* Block copy but reversed direction */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; @@ -1245,7 +1253,7 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->ioctladdr; break; case LS_DATA: - //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) + //da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ @@ -1304,7 +1312,7 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->attraddr | da2->attr_palette_enable; break; case 0x3E9: - if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this maybe equivalent to 3ba / 3da Input Status Register 1 */ { if (da2->cgastat & 0x01) da2->cgastat &= ~0x30; @@ -1587,23 +1595,23 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { da2_t* da2 = (da2_t*)p; uint32_t font = 0; - int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) - if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) + int32_t fline = line - 2;/* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ + if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) */ if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 - font <<= 8; //1111 1111 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 - font >>= 1; //0111 1111 1222 2000 - font <<= 4; //0111 1111 1222 2000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 - font <<= 8; //0111 1111 1222 2000 2222 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 - font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 - //font >>= 1;//put blank at column 1 (and 26) + font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ + font <<= 8; /* 1111 1111 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ + font >>= 1; /* 0111 1111 1222 2000 */ + font <<= 4; /* 0111 1111 1222 2000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ + font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ + font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ + /* font >>= 1;//put blank at column 1 (and 26) */ } else if (code >= 0xb000 && code <= 0xb75f) { - //convert code->address in gaiji memory + /* convert code->address in gaiji memory */ code -= 0xb000; code *= 0x80; //code += 0xf800; @@ -1631,11 +1639,11 @@ uint8_t IRGBtoBGRI(uint8_t attr) /* Get the foreground color from the attribute byte */ uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) { - uint8_t foreground = ~attr & 0x08;// 0000 1000 - foreground <<= 2; //0010 0000 - foreground |= ~attr & 0xc0;// 1110 0000 - foreground >>= 4;//0000 1110 - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + uint8_t foreground = ~attr & 0x08;// 0000 1000 */ + foreground <<= 2; /* 0010 0000 */ + foreground |= ~attr & 0xc0;/* 1110 0000 */ + foreground >>= 4;/* 0000 1110 */ + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;/* bright color palette */ return foreground; } @@ -1675,104 +1683,104 @@ static void da2_render_text(da2_t* da2) chr = da2->cram[(da2->ma) & da2->vram_display_mask]; attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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) + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)/* 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); - if (attr & 0x04) {//reverse 0000 0100 + if (attr & 0x04) {/* reverse 0000 0100 */ bg = fg; fg = 0; } } else - {//--Parse attribute byte in monochrome mode-- - if (attr & 0x08) fg = 3;//Highlight 0000 1000 + {/* --Parse attribute byte in monochrome mode-- */ + if (attr & 0x08) fg = 3;/* Highlight 0000 1000 */ else fg = 2; - bg = 0;//Background is always color #0 (default is black) - if (!(~attr & 0xCC))//Invisible 11xx 11xx -> 00xx 00xx + bg = 0;/* Background is always color #0 (default is black) */ + if (!(~attr & 0xCC))/* Invisible 11xx 11xx -> 00xx 00xx */ { fg = bg; - attr &= 0x33;//disable blinkking, underscore, highlight and reverse + attr &= 0x33;/* disable blinkking, underscore, highlight and reverse */ } - if (attr & 0x04) {//reverse 0000 0100 + if (attr & 0x04) {/* reverse 0000 0100 */ bg = fg; fg = 0; } - // Blinking 1000 0000 + /* Blinking 1000 0000 */ fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); } - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half + /* Draw character */ + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + /* SBCS or DBCS left half */ if (chr_wide == 0) { if (attr & 0x01) chr_wide = 1; //chr_wide = 0; - // Stay drawing If the char code is DBCS and not at last column. + /* Stay drawing If the char code is DBCS and not at last column. */ if (chr_wide) { - //Get high DBCS code from the next video address + /* Get high DBCS code from the next video address */ chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; chr_dbcs <<= 8; chr_dbcs |= chr; - // Get the font pattern + /* Get the font pattern */ uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } } else { - // the char code is SBCS (ANK) + /* the char code is SBCS (ANK) */ uint32_t fontbase; - if (attr & 0x02)//second map of SBCS font + if (attr & 0x02)/* second map of SBCS font */ fontbase = DA2_GAIJIRAM_SBEX; else fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } } } - // right half of DBCS + /* right half of DBCS */ else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } 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 + /* 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 */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + p[n] = da2->pallook[da2->egapal[fg]];/* under line (white) */ } - //Column 1 (Vertical Line) + /* 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[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];/* vertical line (white) */ } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {//HGrid + 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[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];/* horizontal line (white) */ } - //Drawing text cursor + /* 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 + 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); bg = 0; - if (attr & 0x04) {//Color 0 if reverse + if (attr & 0x04) {/* Color 0 if reverse */ bg = fg; fg = 0; } @@ -1820,32 +1828,32 @@ static void da2_render_textm3(da2_t* da2) fg = attr & 0xf; fg = IRGBtoBGRI(fg); bg = IRGBtoBGRI(bg); - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half + /* Draw character */ + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + /* BCS or DBCS left half */ if (chr_wide == 0) { if (extattr & 0x01) chr_wide = 1; - // Stay drawing if the char code is DBCS and not at last column. + /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { - //Get high DBCS code from the next video address + /* Get high DBCS code from the next video address */ chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; chr_dbcs <<= 8; chr_dbcs |= chr; - // Get the font pattern + /* Get the font pattern */ uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } } else { - // the char code is SBCS (ANK) + /* the char code is SBCS (ANK) */ uint32_t fontbase; fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -1853,26 +1861,25 @@ static void da2_render_textm3(da2_t* da2) } } } - // right half of DBCS + /* right half of DBCS */ else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } chr_wide = 0; } - //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[0x1f] & 0x20 ? 26 : 13); - //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;//Choose color 2 if mode 8 + //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; //bg = 0; - //if (attr & 0x04) {//Color 0 if reverse + //if (attr & 0x04) {/* Color 0 if reverse */ // bg = fg; // fg = 0; //} @@ -1891,7 +1898,7 @@ void da2_render_color_4bpp(da2_t* da2) { int changed_offset = da2->ma >> 12; //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - da2->plane_mask &= 0x0f;//safety + da2->plane_mask &= 0x0f; /*safety */ if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { @@ -1904,12 +1911,12 @@ void da2_render_color_4bpp(da2_t* da2) da2->lastline_draw = da2->displine; //da2_log("d %X\n", da2->ma); - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + for (x = 0; x <= da2->hdisp; x += 8)/* hdisp = 1024 */ { uint8_t edat[8]; uint8_t dat; - //get 8 pixels from vram + /* get 8 pixels from vram */ da2->ma &= da2->vram_display_mask; *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); da2->ma += 1; @@ -1952,7 +1959,7 @@ void da2_render_color_8bpp(da2_t* da2) da2->lastline_draw = da2->displine; //da2_log("d %X\n", da2->ma); - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ { uint8_t edat[8]; uint8_t dat; @@ -2037,7 +2044,7 @@ void da2_recalctimings(da2_t* da2) da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; - da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline + da2->rowoffset = da2->crtc[LC_OFFSET];/* number of bytes in a scanline */ da2->clock = da2->da2const; @@ -2052,11 +2059,12 @@ void da2_recalctimings(da2_t* da2) da2->hdisp_time = da2->hdisp; da2->render = da2_render_blank; - //determine display mode + /* determine display mode */ //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) if (da2->attrc[LV_COMPATIBILITY] & 0x08) { - if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode + /* 16 color graphics mode */ + if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; da2->hdisp_old = da2->hdisp; @@ -2065,19 +2073,21 @@ void da2_recalctimings(da2_t* da2) da2->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_GRAM; } - else {//PS/55 8-color + else {/* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); da2->vram_display_mask = DA2_MASK_GRAM; da2->render = da2_render_color_4bpp; } } - else {//text mode + else { + /* text mode */ if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; } - else {//PS/55 text(color/mono) + /* PS/55 text(color/mono) */ + else { da2_log("Set videomode to PS/55 Mode 8/E text.\n"); da2->render = da2_render_text; da2->vram_display_mask = DA2_MASK_CRAM; @@ -2096,7 +2106,7 @@ void da2_recalctimings(da2_t* da2) //da2->render = da2_draw_text; //} - // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + //da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); //if (da2->recalctimings_ex) // da2->recalctimings_ex(da2); @@ -2122,10 +2132,10 @@ void da2_recalctimings(da2_t* da2) if (da2->dispofftime < TIMER_USEC) 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 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->render %08X\n", da2->render); + //da2_log("da2->render %08X\n", da2->render); } uint8_t da2_mca_read(int port, void *p) @@ -2189,7 +2199,7 @@ static void da2_mca_reset(void *p) da2_reset(da2); da2_mca_write(0x102, 0, da2); } -// + static void da2_gdcropB(uint32_t addr, da2_t* da2) { for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { @@ -2265,11 +2275,11 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) - //linear access + /* linear access */ addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); else { - //64k bank switch access + /* 64k bank switch access */ uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; @@ -2277,12 +2287,12 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) } //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { - case 0xb0://Gaiji RAM - addr &= DA2_MASK_GAIJIRAM;//safety access + case 0xb0:/* Gaiji RAM */ + addr &= DA2_MASK_GAIJIRAM;/* safety access */ //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); return da2->mmio.ram[addr]; break; - case 0x10://Font ROM + case 0x10:/* Font ROM */ if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, @@ -2293,29 +2303,29 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.font[addr]; break; default: - return DA2_INVALIDACCESS8;//invalid memory access + return DA2_INVALIDACCESS8;/* invalid memory access */ break; } } - else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 or 256 color mode */ { cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) - da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte + da2->gdcla[i] = da2->vram[(addr << 3) | i];/* read in byte */ //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; for (int i = 0; i < 8; i++) { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); } return ~ret; } else return da2->gdcla[da2->readplane]; } - else //text mode 3 + else /* text mode 3 */ { cycles -= video_timing_read_b; return da2->vram[addr]; @@ -2328,12 +2338,12 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ { cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) - da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch + da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);/* read vram into latch */ #ifdef ENABLE_DA2_DEBUGBLT ////debug @@ -2352,12 +2362,12 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) //da2->mmrdbg_vidaddr = addr; #endif - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint16_t ret = 0; for (int i = 0; i < 8; i++) { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); } return ~ret; @@ -2382,9 +2392,9 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) if (da2->ioctl[LS_MMIO] & 0x10) { //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); - //Gaiji RAM + /* Gaiji RAM */ if (da2->fctl[LF_MMIO_SEL] == 0x80) - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);/* xxxy yyyy yyyy yyyy yyyy */ else { uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; @@ -2393,16 +2403,16 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr += index * 0x40; } switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0://Gaiji RAM 1011 0000 - addr &= DA2_MASK_GAIJIRAM;//safety access + case 0xb0:/* Gaiji RAM 1011 0000 */ + addr &= DA2_MASK_GAIJIRAM;/* safety access */ da2->mmio.ram[addr] = val; break; - case 0x10://Font ROM 0001 0000 - //Read-Only + case 0x10:/* Font ROM 0001 0000 */ + /* Read-Only */ break; case 0x00: //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + //addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ //if (addr >= DA2_BLT_MEMSIZE) //{ // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); @@ -2419,12 +2429,11 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) break; } } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ { uint8_t wm = da2->writemask; //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT - //debug //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) @@ -2449,7 +2458,7 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch + da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2485,11 +2494,11 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) else da2->gdcinput[i] = val; for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i];//use latch + da2->debug_vramold[i] = da2->vram[addr | i];/* use latch */ da2_gdcropB(addr, 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], da2->gdcreg[LG_BIT_MASK_LOW], 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); + ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; case 1: @@ -2519,7 +2528,7 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) } //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 + else/* mode 3h text */ { cycles -= video_timing_write_b; da2->vram[addr] = val; @@ -2538,7 +2547,6 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) bitmask <<= 8; bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGBLT - //debug //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) @@ -2567,7 +2575,7 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch + da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { @@ -2608,7 +2616,7 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; else da2->gdcinput[i] = val; da2_gdcropW(addr, bitmask, da2); - // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + //da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; case 1: @@ -2653,14 +2661,14 @@ static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ { addr &= DA2_MASK_MMIO; //return; //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); } - else {//mode 3h text + else {/* mode 3h text */ //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); @@ -2739,7 +2747,7 @@ void da2_poll(void* priv) if (!da2->linepos) { timer_advance_u64(&da2->timer, da2->dispofftime); - // if (output) printf("Display off %f\n",vidtime); + //if (output) printf("Display off %f\n",vidtime); da2->cgastat |= 1; da2->linepos = 1; @@ -2767,21 +2775,21 @@ void da2_poll(void* priv) // da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { - //da2_log("Vsync off at line %i\n",displine); + //da2_log("Vsync off at line %i\n",displine); da2->cgastat &= ~8; } da2->vslines++; if (da2->displine > 1200) da2->displine = 0; - // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - // displine, vc, ma); + //da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + //displine, vc, ma); } else { - // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + //da2_log("VC %i ma %05X\n", da2->vc, da2->ma); timer_advance_u64(&da2->timer, da2->dispontime); - // if (output) printf("Display on %f\n",vidtime); + //if (output) printf("Display on %f\n",vidtime); if (da2->dispon) da2->cgastat &= ~1; da2->hdisp_on = 0; @@ -2796,7 +2804,7 @@ void da2_poll(void* priv) da2->linecountff = 0; da2->sc = 0; - da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) + da2->maback += (da2->rowoffset << 1);/* color = 0x50(80), mono = 0x40(64) */ if (da2->interlace) da2->maback += (da2->rowoffset << 1); da2->maback &= da2->vram_display_mask; @@ -2817,9 +2825,9 @@ void da2_poll(void* priv) { da2->dispon = 0; //if (da2->crtc[10] & 0x20) da2->cursoron = 0; - //else da2->cursoron = da2->blink & 16; - if (da2->ioctl[LS_MODE] & 1) {//in text mode - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + //else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) {/* in text mode */ + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)/* cursor blinking */ { da2->cursoron = (da2->blink | 1) & da2->blinkconf; } @@ -2827,7 +2835,7 @@ void da2_poll(void* priv) { da2->cursoron = 0; } - if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute + if (!(da2->blink & (0x10 - 1)))/* force redrawing for cursor and blink attribute */ da2->fullchange = 2; } da2->blink++; @@ -2837,7 +2845,7 @@ void da2_poll(void* priv) if (da2->changedvram[x]) da2->changedvram[x]--; } - // memset(changedvram,0,2048); del + //memset(changedvram,0,2048); del if (da2->fullchange) { da2->fullchange--; @@ -2846,7 +2854,7 @@ void da2_poll(void* priv) if (da2->vc == da2->vsyncstart) { int wx, wy; - // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + //da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); da2->dispon = 0; da2->cgastat |= 8; x = da2->hdisp; @@ -2881,14 +2889,12 @@ void da2_poll(void* priv) da2->maback <<= 1; da2->ca <<= 1; - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + //da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); } if (da2->vc == da2->vtotal) { - // da2_log("VC vtotal\n"); - - - // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + //da2_log("VC vtotal\n"); + //printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); da2->vc = 0; da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; @@ -2898,9 +2904,9 @@ void da2_poll(void* priv) if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } - // printf("2 %i\n",da2_vsyncstart); + //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"); + //da2_log("r"); } static void da2_loadfont(char* fname, void* p) { @@ -2916,10 +2922,10 @@ static void da2_loadfont(char* fname, void* p) { return; } fseek(mfile, 0, SEEK_END); - fsize = ftell(mfile);//get filesize + fsize = ftell(mfile); /* get filesize */ fseek(mfile, 0, SEEK_SET); if (fsize > DA2_FONTROM_SIZE) { - fsize = DA2_FONTROM_SIZE;//truncate read data + fsize = DA2_FONTROM_SIZE; /* truncate read data */ //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); //fclose(mfile); //return 1; @@ -2991,8 +2997,6 @@ da2_reset(void* priv) static void *da2_init() { - //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM - if (svga_get_pri() == NULL) return NULL; svga_t *mb_vga = svga_get_pri(); @@ -3008,7 +3012,7 @@ static void *da2_init() da2->vram_mask = memsize - 1; da2->cram = malloc(0x1000); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12); /* XX000h */ da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ da2->mmio.charset = device_get_config_int("charset"); From 33b149e521d12da64e27580af1900f3f16ff563c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:53:44 +0900 Subject: [PATCH 0278/1190] changed debug message output in keyboard.c --- src/device/keyboard.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 3fa7760c5..de97592bf 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -190,7 +190,7 @@ key_process(uint16_t scan, int down) oldkey[scan] = down; - pclog("keyboard : %04X,%d in process\n", scan, down); + kbc_at_log("Key %04X,%d in process\n", scan, down); c = 0; /* According to Japanese DOS K3.3 manual (N:SC18-2194-1), @@ -206,7 +206,7 @@ key_process(uint16_t scan, int down) if (scan != 0x1d && scan != 0x2a && scan != 0x138) { key5576mode = 0; - pclog("keyboard : 5576-001 key emulation disabled.\n"); + kbc_at_log("5576-001 key emulation disabled.\n"); } } while (scconv55_8a[i].sc != 0) @@ -251,7 +251,7 @@ key_process(uint16_t scan, int down) if (keyboard_mode == 0x8a && down && ((keyboard_get_shift() & 0x43) == 0x43)) { key5576mode = 1; - pclog("keyboard : 5576-001 key emulation enabled.\n"); + kbc_at_log("5576-001 key emulation enabled.\n"); } } @@ -348,7 +348,7 @@ keyboard_input(int down, uint16_t scan) } } - /* pclog("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */ + /* kbc_at_log("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */ recv_key_ui[scan & 0x1ff] = down; if (mouse_capture || !kbd_req_capture || video_fullscreen) { From 59c3bb794f6acf9f02e5eaff786b8ca4d7b29835 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 19:03:42 +0900 Subject: [PATCH 0279/1190] revert wrapping changed in recent edits --- src/floppy/fdc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 7f025df2d..a8d2e6520 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1284,8 +1284,7 @@ fdc_read(uint16_t addr, void *priv) ret |= 0x40; if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; - } - else + } else ret = 0xff; break; case 1: /* STB */ @@ -1360,8 +1359,7 @@ fdc_read(uint16_t addr, void *priv) else ret = 0x00; /* PS/55 POST throws an error and halt if ret = 1 or 2, somehow. */ - } - else if (!fdc->enh_mode) + } else if (!fdc->enh_mode) ret = 0x20; else ret = fdc->rwc[drive] << 4; From 6c5e8897de7a5a0899c9e3230979a1fda8741750 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 19:49:03 +0900 Subject: [PATCH 0280/1190] update comments --- src/video/vid_ps55da2.c | 6 +++--- src/video/vid_svga.c | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 5098fa64d..c7c989c5e 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1562,12 +1562,12 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) - Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) + Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. It disables Bitblt text drawing in OS/2 J1.3. [Font ROM Map (DA3, Traditional Chinese)] Bank 0 - 11 : Valid Font ROM data - Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) - Bank 13 : All addresses return 0xFF + Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose to obtain the SBCS font.) + Bank 13 : Filled by 0xFFh [Gaiji RAM Map (DA2)] Bank 0 00000-1FFFFh placed between A0000h-BFFFFh diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5d0db103b..db378b754 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -502,20 +502,19 @@ svga_in(uint16_t addr, void *priv) ret = svga->attrregs[svga->attraddr]; break; case 0x3c2: - if (svga->cable_connected) - { + if (svga->cable_connected) { if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) ret = 0; else ret = 0x10; - } - else - { + /* Monitor is not connected to the planar VGA if the PS/55 Display Adapter is installed. */ + } else { /* The IBM PS/55 Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). - When the monitor cable is connected to the Display Adapter, this port returns the value as 'no cable connection'. + When the monitor cable is connected to the Display Adapter, the port 3C2h returns the value as 'no cable connection'. The POST of PS/55 has an extra code that tries detecting the monitor on the planar VGA. - If it fails, then the POST reads the NVRAM set by the reference diskette, and updates the BIOS Data Area (Mem 487h, 489h). + If it fails, then the POST reads the NVRAM set by the reference diskette, and writes the BIOS Data Area (Mem 487h, 489h). + MONCHK.EXE in the reference diskette uses both I/O ports to determine the monitor type, and writes the BDA. */ if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) ret = 0; From bbc237866bff2458fdfae2bcd2da16902fb14728 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:14:07 +0900 Subject: [PATCH 0281/1190] changed palette initialization method --- src/video/vid_ps55da2.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index c7c989c5e..b4a85bd74 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2987,11 +2987,11 @@ da2_reset(void* priv) da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Windows 3.1 display driver won't reset palette) */ - da2_out(0x3c8, 0, da2); for (int i = 0; i < 256; i++) { - da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); + da2->vgapal[i].r = ps55_palette_color[i & 0x3F][0]; + da2->vgapal[i].g = ps55_palette_color[i & 0x3F][1]; + da2->vgapal[i].b = ps55_palette_color[i & 0x3F][2]; + da2->pallook[i] = makecol32((da2->vgapal[i].r & 0x3f) * 4, (da2->vgapal[i].g & 0x3f) * 4, (da2->vgapal[i].b & 0x3f) * 4); } } @@ -3147,14 +3147,13 @@ void da2_speed_changed(void *p) { da2_t* da2 = (da2_t*)p; da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - da2_recalctimings(da2); + da2_recalctimings(da2); } void da2_force_redraw(void *p) { da2_t* da2 = (da2_t*)p; - - da2->fullchange = changeframecount; + da2->fullchange = changeframecount; } static const device_config_t da2_configuration[] = { From 5f831603e930bf2e462f72567a7d3aaf44c0fba4 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:15:10 +0900 Subject: [PATCH 0282/1190] fixed cache memory encoding for 5550-V --- src/machine/m_ps2_mca.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index b948c984c..62a5e41cd 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -145,7 +145,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; static void mem_encoding_update(void); - +#define ENABLE_PS2_MCA_LOG 1 #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -452,7 +452,7 @@ ps55_model_50v_read(uint16_t port) } return val; case 0x104: - return ps2.option[2]; + return ps2.option[2] & 0xf3; case 0x105: return ps2.option[3]; case 0x106: @@ -1472,10 +1472,12 @@ mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) mem_mapping_disable(&ram_low_mapping); mem_mapping_enable(&ps2.cache_mapping); flushmmucache(); + ps2_mca_log("mem_encoding_write: low ram mapping disabled\n"); } else { mem_mapping_disable(&ps2.cache_mapping); mem_mapping_enable(&ram_low_mapping); flushmmucache(); + ps2_mca_log("mem_encoding_write: low ram mapping enabled\n"); } if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ { @@ -1906,7 +1908,7 @@ ps55_mca_board_model_50v_init() device_add(&ps2_nvr_device); - io_sethandler(0x00e0, 0x0002, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); + io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); ps2.mem_regs[1] = 2; ps2.option[2] &= 0xf2; /* Bit 3-2: -Cache IDs, Bit 1: Reserved @@ -1926,6 +1928,20 @@ ps55_mca_board_model_50v_init() NULL); mem_mapping_disable(&ps2.split_mapping); + mem_mapping_add(&ps2.cache_mapping, + 0, + 64 * 1024, + ps2_read_cache_ram, + ps2_read_cache_ramw, + ps2_read_cache_raml, + ps2_write_cache_ram, + NULL, + NULL, + ps2_cache, + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.cache_mapping); + if (mem_size > 8192) { /* Only 8 MB supported on planar, create a memory expansion card for the rest */ ps2_mca_mem_fffc_init(8); From 0a7c3294059aa58a3286a4a4e175ce375907a02c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:25:57 +0900 Subject: [PATCH 0283/1190] cleanup --- src/machine/m_ps2_mca.c | 333 ++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 170 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 62a5e41cd..e89d88f91 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -145,7 +145,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; static void mem_encoding_update(void); -#define ENABLE_PS2_MCA_LOG 1 + #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -367,53 +367,59 @@ static uint8_t ps55_model_50t_read(uint16_t port) { ps2_mca_log(" Read SysBrd %04X xx %04X:%04X\n", port, cs >> 4, cpu_state.pc); - switch (port) - { - case 0x100: - return ps2.planar_id & 0xff; - case 0x101: - return ps2.planar_id >> 8; - case 0x102: - return ps2.option[0]; - case 0x103: - uint8_t val = 0xff; - /* - I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) - Bit 3-0: Memory Card ID (Connector 2) + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) + Bit 3-0: Memory Card ID (Connector 2) - Memory Card ID: 7h = 2 MB Memory Card 2 or 3 Installed - 5h = 4 MB Memory Card 2 Installed - */ - switch (mem_size / 1024) - { - case 2: - if (ps2.option[1] & 0x04) val = 0xff; - else val = 0x7f; - break; - case 4: - if (ps2.option[1] & 0x04) val = 0xff; - else val = 0x77; - break; - case 6: - if (ps2.option[1] & 0x04) val = 0x7f; - else val = 0x77; - break; - case 8: - default: - if (ps2.option[1] & 0x04) val = 0x5f; - else val = 0x77; - break; - } - ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); - return val; - case 0x104: - return ps2.option[2]; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; + Memory Card ID: 7h = 2 MB Memory Card 2 or 3 Installed + 5h = 4 MB Memory Card 2 Installed + */ + switch (mem_size / 1024) { + case 2: + if (ps2.option[1] & 0x04) + val = 0xff; + else + val = 0x7f; + break; + case 4: + if (ps2.option[1] & 0x04) + val = 0xff; + else + val = 0x77; + break; + case 6: + if (ps2.option[1] & 0x04) + val = 0x7f; + else + val = 0x77; + break; + case 8: + default: + if (ps2.option[1] & 0x04) + val = 0x5f; + else + val = 0x77; + break; + } + ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); + return val; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; } return 0xff; } @@ -421,44 +427,47 @@ ps55_model_50t_read(uint16_t port) static uint8_t ps55_model_50v_read(uint16_t port) { - switch (port) - { - case 0x100: - return ps2.planar_id & 0xff; - case 0x101: - return ps2.planar_id >> 8; - case 0x102: - return ps2.option[0]; - case 0x103: - uint8_t val = 0xff; - /* - I/O 103h - Bit 7-4: Reserved - Bit 3-0: Memory Card ID (Connector 3 or 1) + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Reserved + Bit 3-0: Memory Card ID (Connector 3 or 1) - Memory Card ID: 8h = 4 MB Memory Card IV Installed - Fh = No Card Installed - */ - switch (mem_size / 1024) - { - case 4: - if (ps2.option[1] & 0x04) val = 0xff; - else val = 0xf8; - break; - case 8: - default: - if (ps2.option[1] & 0x04) val = 0xf8; - else val = 0xf8; - break; - } - return val; - case 0x104: - return ps2.option[2] & 0xf3; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; + Memory Card ID: 8h = 4 MB Memory Card IV Installed + Fh = No Card Installed + */ + switch (mem_size / 1024) { + case 4: + if (ps2.option[1] & 0x04) + val = 0xff; + else + val = 0xf8; + break; + case 8: + default: + if (ps2.option[1] & 0x04) + val = 0xf8; + else + val = 0xf8; + break; + } + return val; + case 0x104: + /* Reading cache ID (bit 3-2) always returns zero */ + return ps2.option[2] & 0xf3; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; } return 0xff; } @@ -763,71 +772,66 @@ static void ps55_model_50tv_write(uint16_t port, uint8_t val) { ps2_mca_log(" Write SysBrd %04X %02X %04X:%04X\n", port, val, cs >> 4, cpu_state.pc); - switch (port) - { - case 0x102: - lpt1_remove(); - serial_remove(ps2.uart); - if (val & 0x04) - { - if (val & 0x08) - serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); - else - serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); - } - if (val & 0x10) - { - switch ((val >> 5) & 3) - { - case 0: - lpt1_setup(LPT_MDA_ADDR); - break; - case 1: - lpt1_setup(LPT1_ADDR); - break; - case 2: - lpt1_setup(LPT2_ADDR); - break; - default: - break; + switch (port) { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); } - } - ps2.option[0] = val; - break; - case 0x103: - ps2.option[1] = val; - break; - case 0x104: - if ((ps2.option[2] ^ val) & 1) { - mem_encoding_update(); - if (val & 1)/* Disable E0000 - E0FFF(Make 2 KB hole for Display Adapter) */ - { - ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); - //mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - //mem_mapping_disable(&bios_mapping[0]); + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_setup(LPT_MDA_ADDR); + break; + case 1: + lpt1_setup(LPT1_ADDR); + break; + case 2: + lpt1_setup(LPT2_ADDR); + break; + default: + break; + } } - else/* Enable E0000 - E0FFF for BIOS */ - { - ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); - //mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); - //mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); - //mem_mapping_enable(&bios_mapping[0]); + ps2.option[0] = val; + break; + case 0x103: + ps2.option[1] = val; + break; + case 0x104: + if ((ps2.option[2] ^ val) & 1) { + mem_encoding_update(); + if (val & 1) { + /* Disable E0000 - E0FFF (Make 2 KB hole for Display Adapter) */ + ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); + // mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + // mem_mapping_disable(&bios_mapping[0]); + } else { + /* Enable E0000 - E0FFF for BIOS */ + ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); + // mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); + // mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); + // mem_mapping_enable(&bios_mapping[0]); + } } - } - ps2.option[2] = val; - break; - case 0x105: - ps2.option[3] = val; - break; - case 0x106: - ps2.subaddr_lo = val; - break; - case 0x107: - ps2.subaddr_hi = val; - break; - default: - break; + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + default: + break; } } @@ -1339,20 +1343,19 @@ static void mem_encoding_write_ps55(uint16_t addr, uint8_t val, void* p) { //ps2_mca_log(" Write Memory Encoding %04X %02X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - switch (addr) - { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - default: - break; + switch (addr) { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + default: + break; } mem_encoding_update(); - if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ - { + if (ps2.option[2] & 1) { + /* reset memstate for E0000 - E0FFFh hole */ mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } } @@ -1479,8 +1482,8 @@ mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) flushmmucache(); ps2_mca_log("mem_encoding_write: low ram mapping enabled\n"); } - if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ - { + if (ps2.option[2] & 1) { + /* reset memstate for E0000 - E0FFFh hole */ mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } } @@ -1845,7 +1848,6 @@ ps55_mca_board_model_50t_init() { ps2_mca_board_common_init(); - //mem_remap_top(256); ps2.split_addr = mem_size * 1024; /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ mca_init(5); @@ -1861,14 +1863,6 @@ ps55_mca_board_model_50t_init() ps2.mem_regs[1] = 2; ps2.option[2] &= 0xfe; /* Bit 0: Disable E0000-E0FFFh (4 KB) */ - //resize bios_mapping 0,1 - //mem_mapping_set_addr(&bios_mapping[0], 0xe0000, 0x1000); - //mem_mapping_set_exec(&bios_mapping[0], rom + (0x20000 & biosmask)); - //mem_mapping_set_addr(&bios_mapping[1], 0xe1000, 0x7000); - //mem_mapping_set_exec(&bios_mapping[1], rom + (0x21000 & biosmask)); - //mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); - //mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x23000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); - mem_mapping_add(&ps2.split_mapping, (mem_size + 256) * 1024, 256 * 1024, @@ -1897,7 +1891,6 @@ ps55_mca_board_model_50v_init() { ps2_mca_board_common_init(); - //mem_remap_top(256); ps2.split_addr = mem_size * 1024; /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ mca_init(5); From 4768b3b6fbbc49c5a006524af32c13b86ddd4a1f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 15 Feb 2025 20:02:05 +0100 Subject: [PATCH 0284/1190] Fixed some bus checks in some (S)VGA graphics cards, fixes #5229. --- src/video/vid_ati_mach64.c | 4 ++-- src/video/vid_cl54xx.c | 2 +- src/video/vid_ht216.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 9499f4ecc..2df7782ff 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -4595,7 +4595,7 @@ mach64gx_init(const device_t *info) { mach64_t *mach64 = mach64_common_init(info); - if (info->flags & DEVICE_ISA) + if (info->flags & DEVICE_ISA16) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_isa); else if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); @@ -4617,7 +4617,7 @@ mach64gx_init(const device_t *info) mach64->config_stat0 |= 6; /*VLB, 256Kx16 DRAM*/ ati_eeprom_load(&mach64->eeprom, "mach64_vlb.nvr", 1); rom_init(&mach64->bios_rom, BIOS_VLB_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } else if (info->flags & DEVICE_ISA) { + } else if (info->flags & DEVICE_ISA16) { mach64->config_stat0 |= 0; /*ISA 16-bit, 256k16 DRAM*/ ati_eeprom_load(&mach64->eeprom, "mach64.nvr", 1); rom_init(&mach64->bios_rom, BIOS_ISA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 73be7cd76..21d9b21d8 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4382,7 +4382,7 @@ gd54xx_init(const device_t *info) rom_init_interleaved(&gd54xx->bios_rom, BIOS_GD5428_BOCA_ISA_PATH_1, BIOS_GD5428_BOCA_ISA_PATH_2, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_ISA) + if ((info->flags & DEVICE_ISA) || (info->flags & DEVICE_ISA16)) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_isa); else if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_pci); diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 57b0f303c..b650cb53b 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1604,7 +1604,7 @@ ht216_init(const device_t *info, uint32_t mem_size, int has_rom) mem_mapping_disable(&ht216->linear_mapping); ht216->id = info->local; - ht216->isabus = (info->flags & DEVICE_ISA); + ht216->isabus = (info->flags & DEVICE_ISA) || (info->flags & DEVICE_ISA16); ht216->mca = (info->flags & DEVICE_MCA); io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); From 5dfbef2374a11c77cf77407eb109f816ee6944a6 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 16 Feb 2025 11:11:44 +0900 Subject: [PATCH 0285/1190] fixed PS/55 5550-V hangs in warm boot * Fixed PS/55 5550-V hangs in warm boot because it doesn't reset E0000-E0FFFh hole (for video RAM of DA) * Merge code that enable/disable E0000-E0FFFh hole --- src/machine/m_ps2_mca.c | 119 ++++++++-------------------------------- 1 file changed, 24 insertions(+), 95 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index e89d88f91..1edff2991 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -107,6 +107,7 @@ static struct ps2_t { serial_t *uart; vga_t* mb_vga; + int has_e0000_hole; } ps2; /*The model 70 type 3/4 BIOS performs cache testing. Since 86Box doesn't have any @@ -145,7 +146,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; static void mem_encoding_update(void); - +// #define ENABLE_PS2_MCA_LOG 1 #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -804,20 +805,9 @@ ps55_model_50tv_write(uint16_t port, uint8_t val) break; case 0x104: if ((ps2.option[2] ^ val) & 1) { + /* Disable/Enable E0000 - E0FFF (Make 2 KB hole for Display Adapter) */ + ps2.option[2] = val; mem_encoding_update(); - if (val & 1) { - /* Disable E0000 - E0FFF (Make 2 KB hole for Display Adapter) */ - ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); - // mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - // mem_mapping_disable(&bios_mapping[0]); - } else { - /* Enable E0000 - E0FFF for BIOS */ - ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); - // mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); - // mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); - // mem_mapping_enable(&bios_mapping[0]); - } } ps2.option[2] = val; break; @@ -952,8 +942,15 @@ ps2_mca_write(uint16_t port, uint8_t val, UNUSED(void *priv)) ps2.setup = val; break; case 0x96: - if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) + if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) { mca_reset(); + if (ps2.has_e0000_hole) { + /* Reset memstate for E0000 - E0FFFh hole (for PS/55 5550-V) + 5550-T does this in POST, but 5550-V doesn't. */ + ps2.option[2] &= 0xFE; + mem_encoding_update(); + } + } ps2.adapter_setup = val; mca_set_index(val & 7); break; @@ -1306,6 +1303,11 @@ mem_encoding_update(void) ps2_mca_log("PS/2 Model 80-111: Split memory block disabled\n"); } + if (ps2.has_e0000_hole && (ps2.option[2] & 1)) { + /* Set memstate for E0000 - E0FFFh hole (PS/55 only) */ + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + flushmmucache_nopc(); } @@ -1339,26 +1341,7 @@ mem_encoding_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) } mem_encoding_update(); } -static void -mem_encoding_write_ps55(uint16_t addr, uint8_t val, void* p) -{ - //ps2_mca_log(" Write Memory Encoding %04X %02X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - switch (addr) { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - default: - break; - } - mem_encoding_update(); - if (ps2.option[2] & 1) { - /* reset memstate for E0000 - E0FFFh hole */ - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } -} + static uint8_t mem_encoding_read_cached(uint16_t addr, UNUSED(void *priv)) { @@ -1429,64 +1412,6 @@ mem_encoding_write_cached(uint16_t addr, uint8_t val, UNUSED(void *priv)) } } -static void -mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) -{ - uint8_t old; - - switch (addr) { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - case 0xe2: - old = ps2.mem_regs[2]; - ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); - if (val & 2) { - ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); - if (ps2.pending_cache_miss) - ps2.mem_regs[2] |= 0x80; - else - ps2.mem_regs[2] &= ~0x80; - ps2.pending_cache_miss = 0; - } - - if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) - ps2.pending_cache_miss = 1; - if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) - ps2_cache_clean(); -#if 1 - // FIXME: Look into this!!! - if (val & 0x01) - ram_mid_mapping.flags |= MEM_MAPPING_ROM_WS; - else - ram_mid_mapping.flags &= ~MEM_MAPPING_ROM_WS; -#endif - break; - - default: - break; - } - ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS, cpu_state.pc, ps2.mem_regs[1], ps2.mem_regs[2]); - mem_encoding_update(); - if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { - mem_mapping_disable(&ram_low_mapping); - mem_mapping_enable(&ps2.cache_mapping); - flushmmucache(); - ps2_mca_log("mem_encoding_write: low ram mapping disabled\n"); - } else { - mem_mapping_disable(&ps2.cache_mapping); - mem_mapping_enable(&ram_low_mapping); - flushmmucache(); - ps2_mca_log("mem_encoding_write: low ram mapping enabled\n"); - } - if (ps2.option[2] & 1) { - /* reset memstate for E0000 - E0FFFh hole */ - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } -} static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) { @@ -1675,6 +1600,8 @@ machine_ps2_common_init(const machine_t *model) nmi_mask = 0x80; ps2.uart = device_add_inst(&ns16550_device, 1); + + ps2.has_e0000_hole = 0; } int @@ -1858,10 +1785,11 @@ ps55_mca_board_model_50t_init() device_add(&ps2_nvr_device); - io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write_ps55, NULL, NULL, NULL); + io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write, NULL, NULL, NULL); ps2.mem_regs[1] = 2; ps2.option[2] &= 0xfe; /* Bit 0: Disable E0000-E0FFFh (4 KB) */ + ps2.has_e0000_hole = 1; mem_mapping_add(&ps2.split_mapping, (mem_size + 256) * 1024, @@ -1901,11 +1829,12 @@ ps55_mca_board_model_50v_init() device_add(&ps2_nvr_device); - io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); + io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached, NULL, NULL, NULL); ps2.mem_regs[1] = 2; ps2.option[2] &= 0xf2; /* Bit 3-2: -Cache IDs, Bit 1: Reserved Bit 0: Disable E0000-E0FFFh (4 KB) */ + ps2.has_e0000_hole = 1; mem_mapping_add(&ps2.split_mapping, (mem_size + 256) * 1024, From 3f3d77310e769ab52d78b7cf63bd8e20cab433ba Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 16 Feb 2025 12:21:16 +0900 Subject: [PATCH 0286/1190] cleanup format --- src/video/vid_ps55da2.c | 3436 +++++++++++++++++++-------------------- 1 file changed, 1715 insertions(+), 1721 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index b4a85bd74..9ed099f19 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -37,42 +37,42 @@ #include <86box/vid_svga_render.h> #include "cpu.h" -#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" -#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" -#define DA2_FONTROM_SIZE 1536*1024 -#define DA2_FONTROM_BASESBCS 0x98000 -#define DA2_GAIJIRAM_SBCS 0x34000 -#define DA2_GAIJIRAM_SBEX 0x3c000 -#define DA2_INVALIDACCESS8 0xff -#define DA2_MASK_MMIO 0x1ffff -#define DA2_MASK_GRAM 0x1ffff -#define DA2_MASK_CRAM 0xfff -#define DA2_MASK_GAIJIRAM 0x3ffff -#define DA2_PIXELCLOCK 58000000.0 -#define DA2_BLT_MEMSIZE 0x100 -#define DA2_BLT_REGSIZE 0x40 -#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256*1024 -#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe -#define DA2_DEBUG_BLT_USEDRESET 0xfefefe +#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" +#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" +#define DA2_FONTROM_SIZE 1536 * 1024 +#define DA2_FONTROM_BASESBCS 0x98000 +#define DA2_GAIJIRAM_SBCS 0x34000 +#define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_INVALIDACCESS8 0xff +#define DA2_MASK_MMIO 0x1ffff +#define DA2_MASK_GRAM 0x1ffff +#define DA2_MASK_CRAM 0xfff +#define DA2_MASK_GAIJIRAM 0x3ffff +#define DA2_PIXELCLOCK 58000000.0 +#define DA2_BLT_MEMSIZE 0x100 +#define DA2_BLT_REGSIZE 0x40 +#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) +#define DA2_DEBUG_BLTLOG_MAX 256 * 1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLT_USEDRESET 0xfefefe #define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ -//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ -//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +// #define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ +// #define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ /* These ROMs are currently not found. At least, IBM-J released a Korean and PRC version of PS/55 for each market. */ -#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A -#define DA2_DCONFIG_MONTYPE_8515 0x0B -#define DA2_DCONFIG_MONTYPE_MONO 0x09 +#define DA2_DCONFIG_MONTYPE_8515 0x0B +#define DA2_DCONFIG_MONTYPE_MONO 0x09 -#define DA2_BLT_CIDLE 0 -#define DA2_BLT_CFILLRECT 1 -#define DA2_BLT_CFILLTILE 2 -#define DA2_BLT_CCOPYF 3 -#define DA2_BLT_CCOPYR 4 -#define DA2_BLT_CPUTCHAR 5 -#define DA2_BLT_CDONE 6 -#define DA2_BLT_CLOAD 7 +#define DA2_BLT_CIDLE 0 +#define DA2_BLT_CFILLRECT 1 +#define DA2_BLT_CFILLTILE 2 +#define DA2_BLT_CCOPYF 3 +#define DA2_BLT_CCOPYR 4 +#define DA2_BLT_CPUTCHAR 5 +#define DA2_BLT_CDONE 6 +#define DA2_BLT_CLOAD 7 /* POS ID = 0xeffe : Display Adapter II, III, V */ #define DA2_POSID_H 0xef #define DA2_POSID_L 0xfe @@ -94,7 +94,7 @@ EFD8h * Display Adapter/J [Atlas-SP2] [Japanese DOS and Display Adapter compatibility] - | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | + | POS ID | Adapter Name | K3.31 | J4.04 | J4.08 | OS2 J1.3 | Win3 | |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| | EFFFh | Display Adapter | X | | | ? | | | FFEDh | ? [Atlas EVT] | X | | | ? | | @@ -107,21 +107,21 @@ | EFD8h | Display Adapter /J | | | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ -#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ -//#define Mon_ID3 0x10 -#define FontCard 0x08 /* ? */ -#define Page_One 0x06 /* 80000h 110b */ -#define Page_Two 0x05 /* 100000h 101b */ -#define Page_Four 0x03 /* 200000h 011b */ +#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ +// #define Mon_ID3 0x10 +#define FontCard 0x08 /* ? */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ /* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode unsupported). */ /* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ -#define AddPage 0x08 /* ? */ -//#define Mon_ID2 0x04 -//#define Mon_ID1 0x02 -//#define Mon_ID0 0x01 +#define AddPage 0x08 /* ? */ +// #define Mon_ID2 0x04 +// #define Mon_ID1 0x02 +// #define Mon_ID0 0x01 -/* Monitor ID (imported from OS/2 DDK 1.2) +/* Monitor ID (imported from OS/2 DDK 1.2) #define StarbuckC 0x0A // 1 010b IBM 8514, 9518 color 1040x768 #define StarbuckM 0x09 // 1 001b IBM 8507, 8604 grayscale #define Lark_B 0x02 // 0 010b IBM 9517 color 1040x768 but 4bpp @@ -133,114 +133,114 @@ #define AC_DMAE 0x80 #define AC_FONT_SEL 0x40 #define FONT_BANK 0x3EF -#define LS_INDEX 0x3E0 -#define LS_DATA 0x3E1 +#define LS_INDEX 0x3E0 +#define LS_DATA 0x3E1 #define LS_RESET 0x00 #define LS_MODE 0x02 #define LS_STATUS 0x03 /* added */ #define LS_MMIO 0x08 /* added */ -#define LS_CONFIG1 0x0a -#define LS_CONFIG2 0x0b /* added */ -#define LF_INDEX 0x3e2 -#define LF_DATA 0x3e3 -#define LF_MMIO_SEL 0x08 /* added */ -#define LF_MMIO_ADDR 0x0A /* added */ -#define LF_MMIO_MODE 0x0B /* added */ -#define LC_INDEX 0x3E4 -#define LC_DATA 0x3E5 -#define LC_HORIZONTAL_TOTAL 0x00 -#define LC_H_DISPLAY_ENABLE_END 0x01 -#define LC_START_H_BLANKING 0x02 -#define LC_END_H_BLANKING 0x03 -#define LC_START_HSYNC_PULSE 0x04 -#define LC_END_HSYNC_PULSE 0x05 -#define LC_VERTICAL_TOTALJ 0x06 -#define LC_CRTC_OVERFLOW 0x07 -#define LC_PRESET_ROW_SCANJ 0x08 -#define LC_MAXIMUM_SCAN_LINE 0x09 -#define LC_CURSOR_ROW_START 0x0A -#define LC_CURSOR_ROW_END 0x0B -#define LC_START_ADDRESS_HIGH 0x0C -#define LC_START_ADDRESS_LOW 0x0D -#define LC_CURSOR_LOC_HIGH 0x0E -#define LC_ROW_CURSOR_LOC 0x0E -#define LC_CURSOR_LOC_LOWJ 0x0F -#define LC_COLUMN_CURSOR_LOC 0x0F -#define LC_VERTICAL_SYNC_START 0x10 -#define LC_LIGHT_PEN_HIGH 0x10 -#define LC_VERTICAL_SYNC_END 0x11 -#define LC_LIGHT_PEN_LOW 0x11 -#define LC_V_DISPLAY_ENABLE_END 0x12 -#define LC_OFFSET 0x13 -#define LC_UNDERLINE_LOCATION 0x14 -#define LC_START_VERTICAL_BLANK 0x15 -#define LC_END_VERTICAL_BLANK 0x16 -#define LC_LC_MODE_CONTROL 0x17 -#define LC_LINE_COMPAREJ 0x18 -#define LC_START_H_DISPLAY_ENAB 0x19 -#define LC_START_V_DISPLAY_ENAB 0x1A -#define LC_VIEWPORT_COMMAND 0x1B -#define LC_VIEWPORT_SELECT 0x1C -#define LC_VIEWPORT_PRIORITY 0x1D -#define LC_COMMAND 0x1E -#define LC_COMPATIBILITY 0x1F -#define LC_VIEWPORT_NUMBER 0x1F +#define LS_CONFIG1 0x0a +#define LS_CONFIG2 0x0b /* added */ +#define LF_INDEX 0x3e2 +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_MMIO_MODE 0x0B /* added */ +#define LC_INDEX 0x3E4 +#define LC_DATA 0x3E5 +#define LC_HORIZONTAL_TOTAL 0x00 +#define LC_H_DISPLAY_ENABLE_END 0x01 +#define LC_START_H_BLANKING 0x02 +#define LC_END_H_BLANKING 0x03 +#define LC_START_HSYNC_PULSE 0x04 +#define LC_END_HSYNC_PULSE 0x05 +#define LC_VERTICAL_TOTALJ 0x06 +#define LC_CRTC_OVERFLOW 0x07 +#define LC_PRESET_ROW_SCANJ 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 +#define LC_CURSOR_ROW_START 0x0A +#define LC_CURSOR_ROW_END 0x0B +#define LC_START_ADDRESS_HIGH 0x0C +#define LC_START_ADDRESS_LOW 0x0D +#define LC_CURSOR_LOC_HIGH 0x0E +#define LC_ROW_CURSOR_LOC 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_COLUMN_CURSOR_LOC 0x0F +#define LC_VERTICAL_SYNC_START 0x10 +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_VERTICAL_SYNC_END 0x11 +#define LC_LIGHT_PEN_LOW 0x11 +#define LC_V_DISPLAY_ENABLE_END 0x12 +#define LC_OFFSET 0x13 +#define LC_UNDERLINE_LOCATION 0x14 +#define LC_START_VERTICAL_BLANK 0x15 +#define LC_END_VERTICAL_BLANK 0x16 +#define LC_LC_MODE_CONTROL 0x17 +#define LC_LINE_COMPAREJ 0x18 +#define LC_START_H_DISPLAY_ENAB 0x19 +#define LC_START_V_DISPLAY_ENAB 0x1A +#define LC_VIEWPORT_COMMAND 0x1B +#define LC_VIEWPORT_SELECT 0x1C +#define LC_VIEWPORT_PRIORITY 0x1D +#define LC_COMMAND 0x1E +#define LC_COMPATIBILITY 0x1F +#define LC_VIEWPORT_NUMBER 0x1F #define LV_PORT 0x3E8 -#define LV_PALETTE_0 0x00 -#define LV_MODE_CONTROL 0x10 -#define LV_OVERSCAN_COLOR 0x11 -#define LV_COLOR_PLANE_ENAB 0x12 -#define LV_PANNING 0x13 -#define LV_VIEWPORT1_BG 0x14 -#define LV_VIEWPORT2_BG 0x15 -#define LV_VIEWPORT3_BG 0x16 -#define LV_BLINK_COLOR 0x17 -#define LV_BLINK_CODE 0x18 -#define LV_GR_CURSOR_ROTATION 0x19 -#define LV_GR_CURSOR_COLOR 0x1A -#define LV_GR_CURSOR_CONTROL 0x1B -#define LV_COMMAND 0x1C -#define LV_VP_BORDER_LINE 0x1D -#define LV_SYNC_POLARITY 0x1F -#define LV_CURSOR_CODE_0 0x20 -#define LV_GRID_COLOR_0 0x34 -#define LV_GRID_COLOR_1 0x35 -#define LV_GRID_COLOR_2 0x36 -#define LV_GRID_COLOR_3 0x37 -#define LV_ATTRIBUTE_CNTL 0x38 -#define LV_CURSOR_COLOR 0x3A -#define LV_CURSOR_CONTROL 0x3B -#define LV_RAS_STATUS_VIDEO 0x3C -#define LV_PAS_STATUS_CNTRL 0x3D -#define LV_IDENTIFICATION 0x3E -#define LV_OUTPUT 0x3E -#define LV_COMPATIBILITY 0x3F -#define LG_INDEX 0x3EA -#define LG_DATA 0x3EB -#define LG_SET_RESETJ 0x00 -#define LG_ENABLE_SRJ 0x01 -#define LG_COLOR_COMPAREJ 0x02 -#define LG_DATA_ROTATION 0x03 -#define LG_READ_MAP_SELECT 0x04 -#define LG_MODE 0x05 -#define LG_COMPLEMENT 0x06 -#define LG_COLOR_DONT_CARE 0x07 -#define LG_BIT_MASK_LOW 0x08 -#define LG_BIT_MASK_HIGH 0x09 -#define LG_MAP_MASKJ 0x0A -#define LG_COMMAND 0x0B -#define LG_SET_RESET_2 0x10 +#define LV_PALETTE_0 0x00 +#define LV_MODE_CONTROL 0x10 +#define LV_OVERSCAN_COLOR 0x11 +#define LV_COLOR_PLANE_ENAB 0x12 +#define LV_PANNING 0x13 +#define LV_VIEWPORT1_BG 0x14 +#define LV_VIEWPORT2_BG 0x15 +#define LV_VIEWPORT3_BG 0x16 +#define LV_BLINK_COLOR 0x17 +#define LV_BLINK_CODE 0x18 +#define LV_GR_CURSOR_ROTATION 0x19 +#define LV_GR_CURSOR_COLOR 0x1A +#define LV_GR_CURSOR_CONTROL 0x1B +#define LV_COMMAND 0x1C +#define LV_VP_BORDER_LINE 0x1D +#define LV_SYNC_POLARITY 0x1F +#define LV_CURSOR_CODE_0 0x20 +#define LV_GRID_COLOR_0 0x34 +#define LV_GRID_COLOR_1 0x35 +#define LV_GRID_COLOR_2 0x36 +#define LV_GRID_COLOR_3 0x37 +#define LV_ATTRIBUTE_CNTL 0x38 +#define LV_CURSOR_COLOR 0x3A +#define LV_CURSOR_CONTROL 0x3B +#define LV_RAS_STATUS_VIDEO 0x3C +#define LV_PAS_STATUS_CNTRL 0x3D +#define LV_IDENTIFICATION 0x3E +#define LV_OUTPUT 0x3E +#define LV_COMPATIBILITY 0x3F +#define LG_INDEX 0x3EA +#define LG_DATA 0x3EB +#define LG_SET_RESETJ 0x00 +#define LG_ENABLE_SRJ 0x01 +#define LG_COLOR_COMPAREJ 0x02 +#define LG_DATA_ROTATION 0x03 +#define LG_READ_MAP_SELECT 0x04 +#define LG_MODE 0x05 +#define LG_COMPLEMENT 0x06 +#define LG_COLOR_DONT_CARE 0x07 +#define LG_BIT_MASK_LOW 0x08 +#define LG_BIT_MASK_HIGH 0x09 +#define LG_MAP_MASKJ 0x0A +#define LG_COMMAND 0x0B +#define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -//#define ENABLE_DA2_LOG 1 +// #define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG -#define ENABLE_DA2_DEBUGBLT 1 +# define ENABLE_DA2_DEBUGBLT 1 int da2_do_log = ENABLE_DA2_LOG; static void -da2_log(const char* fmt, ...) +da2_log(const char *fmt, ...) { va_list ap; @@ -254,22 +254,21 @@ da2_log(const char* fmt, ...) # define da2_log(fmt, ...) #endif -typedef struct da2_t -{ - //mem_mapping_t vmapping; +typedef struct da2_t { + // mem_mapping_t vmapping; mem_mapping_t cmapping; - //uint8_t crtcreg; - uint8_t ioctl[16]; - uint8_t fctl[32]; + // uint8_t crtcreg; + uint8_t ioctl[16]; + uint8_t fctl[32]; uint16_t crtc[128]; - uint8_t gdcreg[64]; - uint8_t reg3ee[16]; - int gdcaddr; - uint8_t attrc[0x40]; - int attraddr, attrff; - int attr_palette_enable; - //uint8_t seqregs[64]; + uint8_t gdcreg[64]; + uint8_t reg3ee[16]; + int gdcaddr; + uint8_t attrc[0x40]; + int attraddr, attrff; + int attr_palette_enable; + // uint8_t seqregs[64]; int outflipflop; int inflipflop; int iolatch; @@ -288,8 +287,8 @@ typedef struct da2_t uint32_t debug_vramold[8]; uint8_t dac_mask, dac_status; - int dac_read, dac_write, dac_pos; - int dac_r, dac_g; + int dac_read, dac_write, dac_pos; + int dac_r, dac_g; uint8_t cgastat; @@ -297,37 +296,37 @@ typedef struct da2_t int fb_only; - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - uint8_t writemask; + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + uint8_t writemask; uint32_t charseta, charsetb; - uint8_t egapal[16]; + uint8_t egapal[16]; uint32_t pallook[512]; - PALETTE vgapal; + PALETTE vgapal; - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int rowcount; - double clock; + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int rowcount; + double clock; uint32_t ma_latch, ca_adj; - uint64_t dispontime, dispofftime; + uint64_t dispontime, dispofftime; pc_timer_t timer; - uint64_t da2const; + uint64_t da2const; int dispon; int hdisp_on; uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink, blinkconf; - int scrollcache; - int char_width; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink, blinkconf; + int scrollcache; + int char_width; int firstline, lastline; int firstline_draw, lastline_draw; @@ -336,7 +335,7 @@ typedef struct da2_t /* Attribute Buffer E0000-E0FFFh (4 KB) */ uint8_t *cram; /* (cram size - 1) >> 3 = 0xFFF */ - //uint32_t cram_display_mask; + // uint32_t cram_display_mask; /* APA Buffer A0000-BFFFFh (128 KB) */ uint8_t *vram; /* addr >> 12 = xx000h */ @@ -344,11 +343,11 @@ typedef struct da2_t /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; - //uint32_t write_bank, read_bank; + // uint32_t write_bank, read_bank; int fullchange; - void (*render)(struct da2_t* da2); + void (*render)(struct da2_t *da2); /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ @@ -357,41 +356,41 @@ typedef struct da2_t /* end VGA compatible regs*/ struct { - int enable; + int enable; mem_mapping_t mapping; - uint8_t ram[256 * 1024]; - uint8_t *font; - int charset; + uint8_t ram[256 * 1024]; + uint8_t *font; + int charset; } mmio; struct { - int bitshift_destr; - int raster_op; - uint8_t payload[DA2_BLT_MEMSIZE]; - int32_t reg[DA2_BLT_REGSIZE];//must be signed int - int32_t* debug_reg;//for debug - int debug_reg_ip;//for debug - int payload_addr; + int bitshift_destr; + int raster_op; + uint8_t payload[DA2_BLT_MEMSIZE]; + int32_t reg[DA2_BLT_REGSIZE]; // must be signed int + int32_t *debug_reg; // for debug + int debug_reg_ip; // for debug + int payload_addr; pc_timer_t timer; - int64_t timerspeed; - int exec; - int indata; - int32_t destaddr; - int32_t srcaddr; - int32_t size_x, tile_w; - int32_t size_y; - int16_t destpitch; - int16_t srcpitch; - int32_t fcolor; - int32_t maskl, maskr; - int x, y; + int64_t timerspeed; + int exec; + int indata; + int32_t destaddr; + int32_t srcaddr; + int32_t size_x, tile_w; + int32_t size_y; + int16_t destpitch; + int16_t srcpitch; + int32_t fcolor; + int32_t maskl, maskr; + int x, y; } bitblt; - FILE* mmdbg_fp; - FILE* mmrdbg_fp; + FILE *mmdbg_fp; + FILE *mmrdbg_fp; uint32_t mmdbg_vidaddr; uint32_t mmrdbg_vidaddr; - + uint8_t pos_regs[8]; svga_t *mb_vga; uint8_t monitorid; @@ -399,16 +398,16 @@ 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); +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); typedef union { uint32_t d; - uint8_t b[4]; + uint8_t b[4]; } DA2_VidSeq32; typedef struct { @@ -416,64 +415,69 @@ typedef struct { } pixel32; /* safety read for internal functions */ -uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) +uint32_t +DA2_readvram_s(uint32_t addr, da2_t *da2) { - if (addr & ~da2->vram_mask) return -1; + if (addr & ~da2->vram_mask) + return -1; return da2->vram[addr]; } -void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) +void +DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) { uint32_t writepx[8]; - destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ - //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; - da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; + destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ + // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; + da2->changedvram[(da2->vram_display_mask & (destaddr + 1)) >> 12] = changeframecount; destaddr <<= 3; /* read destination data with big endian order */ for (int i = 0; i < 8; i++) writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) - | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); - DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; - DA2_VidSeq32 mask32; mask32.d = 0; + DA2_VidSeq32 mask32in; + mask32in.d = (uint32_t) mask; + DA2_VidSeq32 mask32; + mask32.d = 0; mask32.b[3] = mask32in.b[0]; mask32.b[2] = mask32in.b[1]; mask32.d &= 0xffff0000; - for (int i = 0; i < 8; i++) - { + for (int i = 0; i < 8; i++) { if (da2->bitblt.bitshift_destr > 0) - srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; switch (da2->bitblt.raster_op) { - case 0x00: /* None */ - writepx[i] &= ~mask32.d; - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x01: /* AND */ - writepx[i] &= srcpx->p8[i] | ~mask32.d; - break; - case 0x02: /* OR */ - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x03: /* XOR */ - writepx[i] ^= srcpx->p8[i] & mask32.d; - break; + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; } } for (int i = 0; i < 8; i++) { - da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; + da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; } } -void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) +void +DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2) { pixel32 srcpx; /* fill data with input color */ for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;/* read in word */ + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0; /* read in word */ DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -487,7 +491,7 @@ Param Desc 09 Mask Right 0A Plane Mask? 0B ROP?(8h or 200h + 0-3h) -0D +0D 20 Exec (1) 21 ? 22 ? @@ -499,20 +503,22 @@ Param Desc 33 Size W 35 Size H */ -void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +void +DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; srcaddr &= 0xfffffffe; srcaddr <<= 3; for (int i = 0; i < 8; i++) srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) - | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } -void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +void +DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; if (srcaddr >= DA2_FONTROM_SIZE) { @@ -520,134 +526,147 @@ void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, return; } for (int i = 0; i < 8; i++) - srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) - | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) - | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0); + srcpx.p8[i] = ((uint32_t) da2->mmio.font[srcaddr] << 24) + | ((uint32_t) da2->mmio.font[srcaddr + 1] << 16) + | ((uint32_t) da2->mmio.font[srcaddr + 2] << 8) + | ((uint32_t) da2->mmio.font[srcaddr + 3] << 0); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } #ifdef ENABLE_DA2_DEBUGBLT -uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { +uint8_t +pixel1tohex(uint32_t addr, int index, da2_t *da2) +{ uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { - if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; + if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) + pixeldata++; } return pixeldata; } -void print_pixelbyte(uint32_t addr, da2_t* da2) { - for (int i = 0; i < 8; i++) - { +void +print_pixelbyte(uint32_t addr, da2_t *da2) +{ + for (int i = 0; i < 8; i++) { pclog("%X", pixel1tohex(addr, i, da2)); } } -void print_bytetobin(uint8_t b) { - for (int i = 0; i < 8; i++) - { - if(b & 0x80) +void +print_bytetobin(uint8_t b) +{ + for (int i = 0; i < 8; i++) { + if (b & 0x80) pclog("1"); else pclog("0"); b <<= 1; } } -//Convert internal char code to Shift JIS code -inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } -inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } -uint16_t IBMJtoSJIS(uint16_t knj) +// Convert internal char code to Shift JIS code +inline int +isKanji1(uint8_t chr) { - if (knj < 0x100) return 0xffff; + return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); +} +inline int +isKanji2(uint8_t chr) +{ + return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); +} +uint16_t +IBMJtoSJIS(uint16_t knj) +{ + if (knj < 0x100) + return 0xffff; knj -= 0x100; if (knj <= 0x1f7d) - ;/* do nothing */ + ; /* do nothing */ else if (knj >= 0xb700 && knj <= 0xb75f) { knj -= 0x90ec; - } - else if (knj >= 0xb3f0 && knj <= 0xb67f) { + } else if (knj >= 0xb3f0 && knj <= 0xb67f) { knj -= 0x906c; - } - else if (knj >= 0x8000 && knj <= 0x8183) - { + } else if (knj >= 0x8000 && knj <= 0x8183) { knj -= 0x5524; - } - else + } else return 0xffff; uint32_t knj1 = knj / 0xBC; uint32_t knj2 = knj - (knj1 * 0xBC); knj1 += 0x81; - if (knj1 > 0x9F) knj1 += 0x40; + if (knj1 > 0x9F) + knj1 += 0x40; knj2 += 0x40; - if (knj2 > 0x7E) knj2++; - //if (!isKanji1(knj1)) return 0xffff; - //if (!isKanji2(knj2)) return 0xffff; + if (knj2 > 0x7E) + knj2++; + // if (!isKanji1(knj1)) return 0xffff; + // if (!isKanji2(knj2)) return 0xffff; knj = knj1 << 8; knj |= knj2; return knj; } #endif -void da2_bitblt_load(da2_t* da2) +void +da2_bitblt_load(da2_t *da2) { uint32_t value32; uint64_t value64; da2_log("BITBLT loading params\n"); - //da2_log("BitBlt memory:\n"); - //if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - // { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - // } + // da2_log("BitBlt memory:\n"); + // if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + // { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + // } int i = 0; - while (i < DA2_BLT_MEMSIZE) - { + while (i < DA2_BLT_MEMSIZE) { if (da2->bitblt.reg[0x20] & 0x1) break; switch (da2->bitblt.payload[i]) { - case 0x88: - case 0x89: - case 0x95: - value32 = da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 3; - break; - case 0x91: - value32 = da2->bitblt.payload[i + 5]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 4]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 5; - break; - case 0x99: - value64 = da2->bitblt.payload[i + 7]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 6]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 5]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 4]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 3]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 2]; - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - i += 7; - break; - case 0x00: - break; - default: - da2_log("da2_ParseBLT: Unknown PreOP!\n"); - break; + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 3; + break; + case 0x91: + value32 = da2->bitblt.payload[i + 5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 5; + break; + case 0x99: + value64 = da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + i += 7; + break; + case 0x00: + break; + default: + da2_log("da2_ParseBLT: Unknown PreOP!\n"); + break; } i++; } @@ -656,31 +675,31 @@ void da2_bitblt_load(da2_t* da2) memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ - if (da2->bitblt.reg[0x20] & 0x1) - { + if (da2->bitblt.reg[0x20] & 0x1) { #ifdef ENABLE_DA2_DEBUGBLT for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); + // if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); } for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; } da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; da2->bitblt.debug_reg_ip++; - if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; + if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) + da2->bitblt.debug_reg_ip = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);/* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;/* 01 AND, 03 XOR */ + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); for (int i = 0; i <= 0xb; i++) da2_log("%02x ", da2->gdcreg[i]); da2_log("\n"); - da2->bitblt.destaddr = da2->bitblt.reg[0x29]; - da2->bitblt.size_x = da2->bitblt.reg[0x33]; - da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; da2->bitblt.destpitch = da2->bitblt.reg[0x21]; - da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; @@ -689,63 +708,61 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.srcpitch -= 2; } da2->bitblt.fcolor = da2->bitblt.reg[0x0]; - da2->bitblt.maskl = da2->bitblt.reg[0x8]; - da2->bitblt.maskr = da2->bitblt.reg[0x9]; - da2->bitblt.x = 0; - da2->bitblt.y = 0; - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ { da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); da2->bitblt.exec = DA2_BLT_CDONE; - } - else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + } else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ - //if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ + // if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ //{ - // da2->bitblt.destaddr += 2; - // da2->bitblt.size_x -= 1; - // da2->bitblt.destpitch += 2; - // da2->bitblt.srcpitch += 2; - //} + // da2->bitblt.destaddr += 2; + // da2->bitblt.size_x -= 1; + // da2->bitblt.destpitch += 2; + // da2->bitblt.srcpitch += 2; + // } da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; + da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif - } - else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { - da2->bitblt.exec = DA2_BLT_CPUTCHAR; + } else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; + da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif } /* Fill a rectangle(or draw a line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; } @@ -754,282 +771,270 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); } /* Tiling a rectangle (transfer tile data multiple times) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); } /* Block transfer (range copy) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { - da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); } /* Block copy but reversed direction */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { - da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; - da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); - //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); + // da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); } } } -void da2_bitblt_exec(void* p) +void +da2_bitblt_exec(void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - switch (da2->bitblt.exec) - { - case DA2_BLT_CIDLE: - timer_disable(&da2->bitblt.timer); - break; - case DA2_BLT_CLOAD: - da2->bitblt.indata = 0; - da2_bitblt_load(da2); - break; - case DA2_BLT_CFILLRECT: - //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + switch (da2->bitblt.exec) { + case DA2_BLT_CIDLE: + timer_disable(&da2->bitblt.timer); + break; + case DA2_BLT_CLOAD: + da2->bitblt.indata = 0; + da2_bitblt_load(da2); + break; + case DA2_BLT_CFILLRECT: + // da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } else if (da2->bitblt.x == 0) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CFILLTILE: - int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CFILLTILE: + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CCOPYF: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CCOPYF: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; + } else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr += 2; - break; - case DA2_BLT_CCOPYR: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr += 2; + break; + case DA2_BLT_CCOPYR: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr -= da2->bitblt.destpitch; + da2->bitblt.srcaddr -= da2->bitblt.srcpitch; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + } else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr -= da2->bitblt.destpitch; - da2->bitblt.srcaddr -= da2->bitblt.srcpitch; da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - break; - case DA2_BLT_CPUTCHAR: - //da2->bitblt.y += 2; - da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - //pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); - //da2->bitblt.srcaddr += 2; - if(da2->bitblt.reg[0x12] < 0x100) - da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; - else - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - //pclog("\n"); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - //if (1) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 3) - { - da2->bitblt.exec = DA2_BLT_CDONE; + break; + case DA2_BLT_CPUTCHAR: + // da2->bitblt.y += 2; + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; + // pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + // da2->bitblt.srcaddr += 2; + if (da2->bitblt.reg[0x12] < 0x100) + da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + else + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + // print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + // print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + // pclog("\n"); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + // if (1) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 3) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += 130; + // da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + // da2->bitblt.srcaddr += -1; + } else if (da2->bitblt.x == 0) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + // da2->bitblt.x++; + } else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + // da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += 130; - //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - //da2->bitblt.srcaddr += -1; - } - else if (da2->bitblt.x == 0) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; - ////da2->bitblt.srcaddr += 2; - //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; - break; - case DA2_BLT_CDONE: - /* initialize regs for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } - if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; - else da2->bitblt.exec = DA2_BLT_CIDLE; - break; + // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; + ////da2->bitblt.srcaddr += 2; + // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + break; + case DA2_BLT_CDONE: + /* initialize regs for debug dump */ + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) + da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + if (da2->bitblt.indata) + da2->bitblt.exec = DA2_BLT_CLOAD; + else + da2->bitblt.exec = DA2_BLT_CIDLE; + break; } } -void da2_bitblt_dopayload(da2_t* da2) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) - { +void +da2_bitblt_dopayload(da2_t *da2) +{ + if (da2->bitblt.exec == DA2_BLT_CIDLE) { da2->bitblt.exec = DA2_BLT_CLOAD; - //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ da2_log("da2 Do bitblt\n"); - while (da2->bitblt.exec != DA2_BLT_CIDLE) - { + while (da2->bitblt.exec != DA2_BLT_CIDLE) { da2_bitblt_exec(da2); } da2_log("da2 End bitblt %x\n", da2->bitblt.exec); } } -void da2_out(uint16_t addr, uint16_t val, void *p) +void +da2_out(uint16_t addr, uint16_t val, void *p) { - da2_t *da2 = (da2_t *)p; - int oldval; -/* -3E0 3E1 Sequencer Registers (undoc) -3E2 3E3 Font Registers (undoc) -3E4 3E5 CRT Control Registers (undoc) -3E8 3E9 Attribute Controller Registers (undoc) -3EA 3EB 3EC Graphics Contoller Registers -*/ - switch (addr) - { + da2_t *da2 = (da2_t *) p; + int oldval; + /* + 3E0 3E1 Sequencer Registers (undoc) + 3E2 3E3 Font Registers (undoc) + 3E4 3E5 CRT Control Registers (undoc) + 3E8 3E9 Attribute Controller Registers (undoc) + 3EA 3EB 3EC Graphics Contoller Registers + */ + switch (addr) { case 0x3c6: /* PEL Mask */ da2->dac_mask = val; break; case 0x3C7: /* Read Address */ da2->dac_read = val; - da2->dac_pos = 0; + da2->dac_pos = 0; break; case 0x3C8: /* Write Address */ da2->dac_write = val; - da2->dac_read = val - 1; - da2->dac_pos = 0; + da2->dac_read = val - 1; + 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_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->dac_status = 0; da2->fullchange = changeframecount; - switch (da2->dac_pos) - { - case 0: - da2->dac_r = val; - da2->dac_pos++; - break; - case 1: - da2->dac_g = val; - da2->dac_pos++; - break; - case 2: - da2->vgapal[da2->dac_write].r = da2->dac_r; - da2->vgapal[da2->dac_write].g = da2->dac_g; - da2->vgapal[da2->dac_write].b = val; - //if (da2->ramdac_type == RAMDAC_8BIT) - // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); - //else + switch (da2->dac_pos) { + case 0: + da2->dac_r = val; + da2->dac_pos++; + break; + case 1: + da2->dac_g = val; + da2->dac_pos++; + break; + case 2: + da2->vgapal[da2->dac_write].r = da2->dac_r; + da2->vgapal[da2->dac_write].g = da2->dac_g; + da2->vgapal[da2->dac_write].b = val; + // if (da2->ramdac_type == RAMDAC_8BIT) + // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); + // else da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); - da2->dac_pos = 0; - da2->dac_write = (da2->dac_write + 1) & 255; - break; + da2->dac_pos = 0; + da2->dac_write = (da2->dac_write + 1) & 255; + break; } break; case LS_INDEX: 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); - if (da2->ioctladdr > 0xf) return; + // da2_log("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); - oldval = da2->ioctl[da2->ioctladdr]; + oldval = da2->ioctl[da2->ioctladdr]; da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ @@ -1039,10 +1044,9 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->fullchange = changeframecount; da2_recalctimings(da2); da2_updatevidselector(da2); - } - else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ + } else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ { - //da2->bitblt.indata = 1; + // da2->bitblt.indata = 1; } } break; @@ -1050,14 +1054,14 @@ void 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); - if (da2->fctladdr > 0x1f) return; + // da2_log("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); - oldval = da2->fctl[da2->fctladdr]; + oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; - if (da2->fctladdr == 0 && oldval != val) - { + if (da2->fctladdr == 0 && oldval != val) { da2->fullchange = changeframecount; da2_recalctimings(da2); } @@ -1066,87 +1070,85 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->crtcaddr = val; break; case LC_DATA: - 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); - if (!(da2->crtc[da2->crtcaddr] ^ val)) return; + 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); + if (!(da2->crtc[da2->crtcaddr] ^ val)) + return; switch (da2->crtcaddr) { - case LC_CRTC_OVERFLOW: - //return; - break; - case LC_MAXIMUM_SCAN_LINE: - if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; - break; - case LC_START_ADDRESS_HIGH: - //if (da2->crtc[0x1c] & 0x40) return; - break; - case LC_VERTICAL_TOTALJ: /* Vertical Total */ - case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ - case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ - case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ - //val = 0x400; //for debugging bitblt - break; - case LC_VIEWPORT_SELECT: /* ViewPort Select? */ - //return; - break; - case LC_VIEWPORT_NUMBER: /* Compatibility? */ - break; + case LC_CRTC_OVERFLOW: + // return; + break; + case LC_MAXIMUM_SCAN_LINE: + if (!(da2->ioctl[LS_MODE] & 0x01)) + val = 0; + break; + case LC_START_ADDRESS_HIGH: + // if (da2->crtc[0x1c] & 0x40) return; + break; + case LC_VERTICAL_TOTALJ: /* Vertical Total */ + case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ + case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ + case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ + // val = 0x400; /* for debugging bitblt in Win 3.x */ + break; + case LC_VIEWPORT_SELECT: /* ViewPort Select? */ + // return; + break; + case LC_VIEWPORT_NUMBER: /* Compatibility? */ + break; } da2->crtc[da2->crtcaddr] = val; switch (da2->crtcaddr) { - case LC_H_DISPLAY_ENABLE_END: - case LC_VERTICAL_TOTALJ: - case LC_MAXIMUM_SCAN_LINE: - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: - case LC_VERTICAL_SYNC_START: - case LC_V_DISPLAY_ENABLE_END: - case LC_START_VERTICAL_BLANK: - case LC_END_VERTICAL_BLANK: - case LC_VIEWPORT_PRIORITY: - da2->fullchange = changeframecount; - da2_recalctimings(da2); - break; - default: - break; + case LC_H_DISPLAY_ENABLE_END: + case LC_VERTICAL_TOTALJ: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + case LC_VERTICAL_SYNC_START: + case LC_V_DISPLAY_ENABLE_END: + case LC_START_VERTICAL_BLANK: + case LC_END_VERTICAL_BLANK: + case LC_VIEWPORT_PRIORITY: + da2->fullchange = changeframecount; + da2_recalctimings(da2); + break; + default: + break; } 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); - if (!da2->attrff) - { + // da2_log("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; - if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) - { - da2->fullchange = 3; + if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) { + da2->fullchange = 3; da2->attr_palette_enable = val & 0x20; da2_recalctimings(da2); } - //da2_log("set attraddr: %X\n", da2->attraddr); - } - else - { + // da2_log("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->attrc[da2->attraddr & 0x3f] = val; - //da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); + // da2_log("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) - { - for (int c = 0; c < 16; c++) - { - //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); - //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); - if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; - else da2->egapal[c] = da2->attrc[c] & 0x3f; + if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { + for (int c = 0; c < 16; c++) { + // if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); + // else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); + if (da2->attrc[LV_MODE_CONTROL] & 0x80) + da2->egapal[c] = da2->attrc[c] & 0xf; + else + da2->egapal[c] = da2->attrc[c] & 0x3f; } } - switch (da2->attraddr) - { + switch (da2->attraddr) { case LV_COLOR_PLANE_ENAB: if ((val & 0xff) != da2->plane_mask) da2->fullchange = changeframecount; @@ -1154,15 +1156,15 @@ void da2_out(uint16_t addr, uint16_t val, void *p) break; case LV_CURSOR_CONTROL: switch (val & 0x18) { - case 0x08://fast blink - da2->blinkconf = 0x10; - break; - case 0x18://slow blink - da2->blinkconf = 0x20; - break; - default://no blink - da2->blinkconf = 0xff; - break; + case 0x08: /* fast blink */ + da2->blinkconf = 0x10; + break; + case 0x18: /* slow blink */ + da2->blinkconf = 0x20; + break; + default: /* no blink */ + da2->blinkconf = 0xff; + break; } break; case LV_MODE_CONTROL: @@ -1184,79 +1186,81 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->gdcaddr = val; break; case LG_DATA: - //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); - //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); - switch (da2->gdcaddr & 0x1f) - { - case LG_READ_MAP_SELECT: - da2->readplane = val & 0x7; - break; - case LG_MODE: - da2->writemode = val & 3; - break; - case LG_MAP_MASKJ: - da2->writemask = val & 0xff; - break; - case LG_COMMAND: - break; - case LG_SET_RESET_2: - da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); - return; + // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + // 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); + switch (da2->gdcaddr & 0x1f) { + case LG_READ_MAP_SELECT: + da2->readplane = val & 0x7; + break; + case LG_MODE: + da2->writemode = val & 3; + break; + case LG_MAP_MASKJ: + da2->writemask = val & 0xff; + break; + case LG_COMMAND: + break; + case LG_SET_RESET_2: + da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + return; } da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; break; - //case 0x3ed: /* used by Windows 3.1 display driver */ - // da2->gdcreg[5] = val & 0xff; - // break; + // case 0x3ed: /* used by Windows 3.1 display driver */ + // da2->gdcreg[5] = val & 0xff; + // break; default: da2_log("DA2? Out addr %03X val %02X\n", addr, val); break; - } + } } -uint16_t da2_in(uint16_t addr, void *p) +uint16_t +da2_in(uint16_t addr, void *p) { - da2_t * da2 = (da2_t *)p; - uint16_t temp; + da2_t *da2 = (da2_t *) p; + uint16_t temp; - switch (addr) - { + switch (addr) { case 0x3c3: temp = 0; break; - case 0x3c6: temp = da2->dac_mask; + case 0x3c6: + temp = da2->dac_mask; break; - case 0x3c7: temp = da2->dac_status; + case 0x3c7: + temp = da2->dac_status; break; - case 0x3c8: temp = da2->dac_write; + case 0x3c8: + temp = da2->dac_write; break; case 0x3c9: da2->dac_status = 3; - switch (da2->dac_pos) - { - case 0: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].r & 0x3f; - break; - case 1: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].g & 0x3f; - break; - case 2: - da2->dac_pos = 0; - da2->dac_read = (da2->dac_read + 1) & 255; - temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; - break; + switch (da2->dac_pos) { + case 0: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].r & 0x3f; + break; + case 1: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].g & 0x3f; + break; + case 2: + da2->dac_pos = 0; + da2->dac_read = (da2->dac_read + 1) & 255; + temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; + break; } break; case LS_INDEX: temp = da2->ioctladdr; break; case LS_DATA: - //da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ - if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; + // da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ + if (da2->ioctladdr > 0xf) + return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; - if (da2->ioctladdr == LS_STATUS) { /* Status register */ + if (da2->ioctladdr == LS_STATUS) { /* Status register */ if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { /* grayscale monitor */ @@ -1275,54 +1279,54 @@ uint16_t da2_in(uint16_t addr, void *p) } else { temp |= 0x80; } - temp &= 0xf6;//clear busy bits + temp &= 0xf6; /* clear busy bit */ if (da2->bitblt.indata) /* for OS/2 J1.3 */ da2_bitblt_dopayload(da2); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - { - //da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x08;//wait(bit 3 + bit 0) - //if (!da2->bitblt.timer.enabled) + if (da2->bitblt.exec != DA2_BLT_CIDLE) { + // da2_log("exec:%x\n", da2->bitblt.exec); + temp |= 0x08; // wait(bit 3 + bit 0) + // if (!da2->bitblt.timer.enabled) //{ - // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); - // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //} + // da2_log("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 |= 0x01; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); } - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); break; case LF_INDEX: temp = da2->fctladdr; break; case LF_DATA: - if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; + if (da2->fctladdr > 0x1f) + return DA2_INVALIDACCESS8; temp = da2->fctl[da2->fctladdr]; break; case LC_INDEX: temp = da2->crtcaddr; break; case LC_DATA: - if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; + if (da2->crtcaddr > 0x1f) + return DA2_INVALIDACCESS8; temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: temp = da2->attraddr | da2->attr_palette_enable; break; case 0x3E9: - if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this maybe equivalent to 3ba / 3da Input Status Register 1 */ + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this maybe equivalent to 3ba / 3da ISR1 */ { if (da2->cgastat & 0x01) da2->cgastat &= ~0x30; else da2->cgastat ^= 0x30; temp = da2->cgastat; - } - else + } 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_log("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: @@ -1330,149 +1334,145 @@ uint16_t 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_log("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); - return temp; + } + // da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; } /* -* Write I/O -* out b(idx), out b(data), out b(data) -* out b(idx), out w(data) -* out b(idx), out w(data), out b(data) -* out w(idx) -* Read I/O -* out b(idx), in b(data) -* out b(idx), in b, in b(data) -* out b(idx), in w(data) -*/ -void da2_outb(uint16_t addr, uint8_t val, void* p) + * Write I/O + * out b(idx), out b(data), out b(data) + * out b(idx), out w(data) + * out b(idx), out w(data), out b(data) + * out w(idx) + * Read I/O + * out b(idx), in b(data) + * out b(idx), in b, in b(data) + * out b(idx), in w(data) + */ +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_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->inflipflop = 0; - switch (addr) - { - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - if (da2->outflipflop) - { - /* out b(idx), out b(data), out b(data) */ - da2->iolatch |= (uint16_t)val << 8; + switch (addr) { + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + if (da2->outflipflop) { + /* out b(idx), out b(data), out b(data) */ + da2->iolatch |= (uint16_t) val << 8; + da2->outflipflop = 0; + } else { // + da2->iolatch = val; + da2->outflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + default: + da2->iolatch = val; da2->outflipflop = 0; - } - else - {// - da2->iolatch = val; - da2->outflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - default: - da2->iolatch = val; - da2->outflipflop = 0; - break; + break; } da2_out(addr, da2->iolatch, da2); } -void da2_outw(uint16_t addr, uint16_t val, void* p) +void +da2_outw(uint16_t addr, uint16_t val, void *p) { - //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_t* da2 = (da2_t*)p; + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; - switch (addr) - { - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - da2_out(addr, val & 0xff, da2); - da2->iolatch = val >> 8; - da2_out(addr + 1, da2->iolatch, da2); - da2->outflipflop = 1; - break; - case LV_PORT: - da2->attrff = 0; + switch (addr) { + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + da2_out(addr, val & 0xff, da2); + da2->iolatch = val >> 8; + da2_out(addr + 1, da2->iolatch, da2); + da2->outflipflop = 1; + break; + case LV_PORT: + da2->attrff = 0; da2_out(addr, val & 0xff, da2); da2_out(addr, val >> 8, da2); 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_out(LG_DATA, val >> 8, da2); - break; - case 0x3ED: - da2->gdcaddr = LG_MODE; - da2_out(LG_DATA, val, da2); - break; - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - default: - da2_out(addr, val, da2); - da2->outflipflop = 0; - break; - case 0x3EE: - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2->reg3ee[val & 0xff] = val >> 8; - break; + break; + case 0x3EC: + // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_out(LG_DATA, val >> 8, da2); + break; + case 0x3ED: + da2->gdcaddr = LG_MODE; + da2_out(LG_DATA, val, da2); + break; + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + default: + da2_out(addr, val, da2); + da2->outflipflop = 0; + break; + case 0x3EE: + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2->reg3ee[val & 0xff] = val >> 8; + break; } } -uint8_t da2_inb(uint16_t addr, void* p) +uint8_t +da2_inb(uint16_t addr, void *p) { uint8_t temp; - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; da2->outflipflop = 0; - switch (addr) - { - case LC_DATA: - if (da2->inflipflop) - { - /* out b(idx), in b(low data), in b(high data) */ - temp = da2->iolatch >> 8; + switch (addr) { + case LC_DATA: + if (da2->inflipflop) { + /* out b(idx), in b(low data), in b(high data) */ + temp = da2->iolatch >> 8; + da2->inflipflop = 0; + } else { // + da2->iolatch = da2_in(addr, da2); + temp = da2->iolatch & 0xff; + da2->inflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + case LS_DATA: + case LF_DATA: + case LG_DATA: + default: + temp = da2_in(addr, da2) & 0xff; da2->inflipflop = 0; - } - else - {// - da2->iolatch = da2_in(addr, da2); - temp = da2->iolatch & 0xff; - da2->inflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - case LS_DATA: - case LF_DATA: - case LG_DATA: - default: - temp = da2_in(addr, da2) & 0xff; - da2->inflipflop = 0; - break; + break; } - //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -uint16_t da2_inw(uint16_t addr, void* p) +uint16_t +da2_inw(uint16_t addr, void *p) { - //uint16_t temp; - da2_t* da2 = (da2_t*)p; - da2->inflipflop = 0; + // uint16_t temp; + da2_t *da2 = (da2_t *) p; + da2->inflipflop = 0; da2->outflipflop = 0; return da2_in(addr, da2); } -/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ -uint8_t da2_in_ISR(uint16_t addr, void* p) +/* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */ +uint8_t +da2_in_ISR(uint16_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; uint8_t temp = 0; if (addr == 0x3da) { if (da2->cgastat & 0x01) @@ -1481,13 +1481,14 @@ uint8_t 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_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -void da2_out_ISR(uint16_t addr, uint8_t val, void* p) +void +da2_out_ISR(uint16_t addr, uint8_t val, void *p) { - //da2_t* da2 = (da2_t*)p; + // da2_t* da2 = (da2_t*)p; da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); } @@ -1592,29 +1593,30 @@ 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 getfont_ps55dbcs(int32_t code, int32_t line, void* p) { - da2_t* da2 = (da2_t*)p; - uint32_t font = 0; - int32_t fline = line - 2;/* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ - if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) */ +uint32_t +getfont_ps55dbcs(int32_t code, int32_t line, void *p) +{ + da2_t *da2 = (da2_t *) p; + uint32_t font = 0; + int32_t fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ + if (code >= 0x8000 && code <= 0x8183) + code -= 0x6000; /* shift for IBM extended characters (I don't know how the real card works.) */ if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ - font <<= 8; /* 1111 1111 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ - font >>= 1; /* 0111 1111 1222 2000 */ - font <<= 4; /* 0111 1111 1222 2000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ - font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ - font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ + font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ + font <<= 8; /* 1111 1111 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ + font >>= 1; /* 0111 1111 1222 2000 */ + font <<= 4; /* 0111 1111 1222 2000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ + font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ + font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ /* font >>= 1;//put blank at column 1 (and 26) */ - } - else if (code >= 0xb000 && code <= 0xb75f) - { + } else if (code >= 0xb000 && code <= 0xb75f) { /* convert code->address in gaiji memory */ code -= 0xb000; code *= 0x80; - //code += 0xf800; + // code += 0xf800; font = da2->mmio.ram[code + line * 4]; font <<= 8; font |= da2->mmio.ram[code + line * 4 + 1]; @@ -1622,8 +1624,7 @@ uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { font |= da2->mmio.ram[code + line * 4 + 2]; font <<= 8; font |= da2->mmio.ram[code + line * 4 + 3]; - } - else if (code > DA2_FONTROM_SIZE) + } else if (code > DA2_FONTROM_SIZE) font = 0xffffffff; else font = 0; @@ -1631,23 +1632,27 @@ uint32_t 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 IRGBtoBGRI(uint8_t attr) +uint8_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 getPS55ForeColor(uint8_t attr, da2_t* da2) +uint8_t +getPS55ForeColor(uint8_t attr, da2_t *da2) { - uint8_t foreground = ~attr & 0x08;// 0000 1000 */ - foreground <<= 2; /* 0010 0000 */ - foreground |= ~attr & 0xc0;/* 1110 0000 */ - foreground >>= 4;/* 0000 1110 */ - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;/* bright color palette */ + uint8_t foreground = ~attr & 0x08; /* 0000 1000 */ + foreground <<= 2; /* 0010 0000 */ + foreground |= ~attr & 0xc0; /* 1110 0000 */ + foreground >>= 4; /* 0000 1110 */ + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) + foreground |= 0x01; /* bright color palette */ return foreground; } -void da2_render_blank(da2_t* da2) +void +da2_render_blank(da2_t *da2) { int x, xx; @@ -1655,67 +1660,68 @@ void da2_render_blank(da2_t* da2) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - for (x = 0; x < da2->hdisp; x++) - { - for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + for (x = 0; x < da2->hdisp; x++) { + for (xx = 0; xx < 13; xx++) + ((uint32_t *) buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; } } /* Display Adapter Mode 8, E Drawing */ -static void da2_render_text(da2_t* da2) +static void +da2_render_text(da2_t *da2) { if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //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->vram_display_mask]; + if (da2->fullchange) { + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + // 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->vram_display_mask]; attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; - //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)/* 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) */ + // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* 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); - if (attr & 0x04) {/* reverse 0000 0100 */ + if (attr & 0x04) { /* reverse 0000 0100 */ bg = fg; fg = 0; } - } - else - {/* --Parse attribute byte in monochrome mode-- */ - if (attr & 0x08) fg = 3;/* Highlight 0000 1000 */ - else fg = 2; - bg = 0;/* Background is always color #0 (default is black) */ - if (!(~attr & 0xCC))/* Invisible 11xx 11xx -> 00xx 00xx */ + } else { /* --Parse attribute byte in monochrome mode-- */ + if (attr & 0x08) + fg = 3; /* Highlight 0000 1000 */ + else + fg = 2; + bg = 0; /* Background is always color #0 (default is black) */ + if (!(~attr & 0xCC)) /* Invisible 11xx 11xx -> 00xx 00xx */ { fg = bg; - attr &= 0x33;/* disable blinkking, underscore, highlight and reverse */ + attr &= 0x33; /* disable blinkking, underscore, highlight and reverse */ } - if (attr & 0x04) {/* reverse 0000 0100 */ + if (attr & 0x04) { /* reverse 0000 0100 */ bg = fg; fg = 0; } /* Blinking 1000 0000 */ fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; - //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); + // if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); } /* Draw character */ - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[bg]]; /* draw blank */ /* SBCS or DBCS left half */ if (chr_wide == 0) { - if (attr & 0x01) chr_wide = 1; - //chr_wide = 0; + if (attr & 0x01) + chr_wide = 1; + // chr_wide = 0; /* Stay drawing If the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ @@ -1729,18 +1735,17 @@ static void da2_render_text(da2_t* da2) p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } - } - else { + } else { /* the char code is SBCS (ANK) */ uint32_t fontbase; - if (attr & 0x02)/* second map of SBCS font */ + if (attr & 0x02) /* second map of SBCS font */ fontbase = DA2_GAIJIRAM_SBEX; else fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -1749,8 +1754,7 @@ static void da2_render_text(da2_t* da2) } } /* right half of DBCS */ - else - { + else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { @@ -1760,27 +1764,26 @@ static void 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 == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) { /* Underscore only in monochrome mode */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];/* under line (white) */ + 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[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */ } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {/* HGrid */ + 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[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? 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]) - { + 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); - bg = 0; - if (attr & 0x04) {/* Color 0 if reverse */ + 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); + bg = 0; + if (attr & 0x04) { /* Color 0 if reverse */ bg = fg; fg = 0; } @@ -1794,45 +1797,46 @@ static void da2_render_text(da2_t* da2) p += 13; } da2->ma &= da2->vram_display_mask; - //da2->writelines++; + // da2->writelines++; } } /* Display Adapter Mode 3 Drawing */ -static void da2_render_textm3(da2_t* da2) +static void +da2_render_textm3(da2_t *da2) { if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr, extattr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); - for (x = 0; x < da2->hdisp; x += 13) - { - chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; + if (da2->fullchange) { + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr, extattr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) { + chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; - //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; - //if (da2->blink) bg &= ~0x8; - //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; + // if (da2->blink) bg &= ~0x8; + // fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; fg = attr & 0xf; fg = IRGBtoBGRI(fg); bg = IRGBtoBGRI(bg); /* Draw character */ - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[bg]]; /* draw blank */ /* BCS or DBCS left half */ if (chr_wide == 0) { - if (extattr & 0x01) chr_wide = 1; + if (extattr & 0x01) + chr_wide = 1; /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ @@ -1846,15 +1850,14 @@ static void da2_render_textm3(da2_t* da2) p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } - } - else { + } else { /* the char code is SBCS (ANK) */ uint32_t fontbase; - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; @@ -1862,8 +1865,7 @@ static void da2_render_textm3(da2_t* da2) } } /* right half of DBCS */ - else - { + else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { @@ -1873,16 +1875,15 @@ static void da2_render_textm3(da2_t* da2) chr_wide = 0; } 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; - //bg = 0; - //if (attr & 0x04) {/* Color 0 if reverse */ - // bg = fg; - // fg = 0; - //} + 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; + // bg = 0; + // if (attr & 0x04) {/* Color 0 if reverse */ + // bg = fg; + // fg = 0; + // } for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[fg]]; } @@ -1890,562 +1891,550 @@ static void da2_render_textm3(da2_t* da2) p += 13; } da2->ma &= da2->vram_display_mask; - //da2->writelines++; + // da2->writelines++; } } -void da2_render_color_4bpp(da2_t* da2) +void +da2_render_color_4bpp(da2_t *da2) { int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + // da2_log("ma %x cf %x\n", da2->ma, changed_offset); da2->plane_mask &= 0x0f; /*safety */ - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); - - for (x = 0; x <= da2->hdisp; x += 8)/* hdisp = 1024 */ - { - uint8_t edat[8]; - uint8_t dat; - - /* get 8 pixels from vram */ - da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - da2->ma += 1; - - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); - p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); - p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); - p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); - p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); - p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); - p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); - p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); - p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - p += 8; - } - //da2->writelines++; - } -} - -void da2_render_color_8bpp(da2_t* da2) -{ - int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); + // da2_log("d %X\n", da2->ma); for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ { uint8_t edat[8]; uint8_t dat; - //get 8 pixels from vram + /* get 8 pixels from vram */ da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]); da2->ma += 1; - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | - ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); - p[0] = da2->pallook[dat]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | - ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); - p[1] = da2->pallook[dat]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | - ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); - p[2] = da2->pallook[dat]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | - ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); - p[3] = da2->pallook[dat]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | - ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); - p[4] = da2->pallook[dat]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | - ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); - p[5] = da2->pallook[dat]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | - ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); - p[6] = da2->pallook[dat]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | - ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); - p[7] = da2->pallook[dat]; + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); + p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); + p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); + p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); + p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); + p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); + p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); + p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); + p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; p += 8; } - //da2->writelines++; + // da2->writelines++; } } -void da2_updatevidselector(da2_t* da2) { - /* if VGA passthrough mode */ +void +da2_render_color_8bpp(da2_t *da2) +{ + int changed_offset = da2->ma >> 12; + // da2_log("ma %x cf %x\n", da2->ma, changed_offset); + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + // da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ + { + uint8_t edat[8]; + uint8_t dat; + + /* get 8 pixels from vram */ + da2->ma &= da2->vram_display_mask; + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]); + *(uint32_t *) (&edat[4]) = *(uint32_t *) (&da2->vram[(da2->ma << 3) + 4]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); + p[0] = da2->pallook[dat]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); + p[1] = da2->pallook[dat]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); + p[2] = da2->pallook[dat]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); + p[3] = da2->pallook[dat]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); + p[4] = da2->pallook[dat]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); + p[5] = da2->pallook[dat]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); + p[6] = da2->pallook[dat]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); + p[7] = da2->pallook[dat]; + p += 8; + } + // da2->writelines++; + } +} + +void +da2_updatevidselector(da2_t *da2) +{ da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); - if (da2->ioctl[LS_MODE] & 0x02) - { + if (da2->ioctl[LS_MODE] & 0x02) { + /* VGA passthrough mode */ da2->override = 1; svga_set_override(da2->mb_vga, 0); - } - else - { + } else { svga_set_override(da2->mb_vga, 1); da2->override = 0; } } -void da2_recalctimings(da2_t* da2) +void +da2_recalctimings(da2_t *da2) { double crtcconst; double _dispontime, _dispofftime, disptime; - da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w - da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w - da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w - da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare - da2->split = 0xfff; - da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w - da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; + da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; + da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff; + da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff; + da2->split = 0xfff; + 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; - } - else { - //da2->vtotal += 2; + } else { + // da2->vtotal += 2; da2->dispend--; - //da2->vsyncstart++; - //da2->split++; - //da2->vblankstart++; - //da2->hdisp--; + // da2->vsyncstart++; + // da2->split++; + // da2->vblankstart++; + // da2->hdisp--; } da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; - da2->rowoffset = da2->crtc[LC_OFFSET];/* number of bytes in a scanline */ + da2->rowoffset = da2->crtc[LC_OFFSET]; /* number of bytes in a scanline */ da2->clock = da2->da2const; - //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; + // da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - //da2->interlace = 0; + // da2->interlace = 0; - //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + // da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b da2->ca_adj = 0; da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; da2->hdisp_time = da2->hdisp; - da2->render = da2_render_blank; + da2->render = da2_render_blank; /* determine display mode */ - //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - if (da2->attrc[LV_COMPATIBILITY] & 0x08) - { + // if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* 16 color graphics mode */ if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; - da2->hdisp_old = da2->hdisp; + 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->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_GRAM; - } - else {/* PS/55 8-color */ + } else { /* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); da2->vram_display_mask = DA2_MASK_GRAM; - da2->render = da2_render_color_4bpp; + da2->render = da2_render_color_4bpp; } - } - else { + } else { /* text mode */ if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); - da2->render = da2_render_textm3; + da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; } /* PS/55 text(color/mono) */ else { da2_log("Set videomode to PS/55 Mode 8/E text.\n"); - da2->render = da2_render_text; + da2->render = da2_render_text; da2->vram_display_mask = DA2_MASK_CRAM; } da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; + da2->hdisp_old = da2->hdisp; da2->char_width = 13; } - } - else - { + } else { da2_log("Set videomode to blank.\n"); } - //if (!da2->scrblank && da2->attr_palette_enable) + // if (!da2->scrblank && da2->attr_palette_enable) //{ - //da2->render = da2_draw_text; + // da2->render = da2_draw_text; //} - //da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - //if (da2->recalctimings_ex) - // da2->recalctimings_ex(da2); + // if (da2->recalctimings_ex) + // da2->recalctimings_ex(da2); if (da2->vblankstart < da2->dispend) da2->dispend = da2->vblankstart; crtcconst = da2->clock * da2->char_width; - disptime = da2->htotal; + disptime = da2->htotal; _dispontime = da2->hdisp_time; da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); - //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + // if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; _dispofftime *= crtcconst; - da2->dispontime = (uint64_t)_dispontime; - da2->dispofftime = (uint64_t)_dispofftime; + da2->dispontime = (uint64_t) _dispontime; + da2->dispofftime = (uint64_t) _dispofftime; if (da2->dispontime < TIMER_USEC) da2->dispontime = TIMER_USEC; if (da2->dispofftime < TIMER_USEC) 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 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->render %08X\n", da2->render); + // da2_log("da2->render %08X\n", da2->render); } -uint8_t da2_mca_read(int port, void *p) +static void +da2_mapping_update(da2_t *da2) { - da2_t *da2 = (da2_t *)p; - return da2->pos_regs[port & 7]; + /* Has the CardEnable bit been changed? */ + if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) + return; + da2->old_pos2 = da2->pos_regs[2]; + // da2_recalc_mapping(da2); + if (da2->pos_regs[2] & 0x01) { + da2_log("DA2 enable registers\n"); + for (int i = 0; i < 8; i++) + da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); + io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, 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); + } else { + da2_log("DA2 disable registers\n"); + 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); + io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + } } -static void da2_mapping_update(da2_t *da2) +uint8_t +da2_mca_read(int port, void *p) { - if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; - da2->old_pos2 = da2->pos_regs[2]; - //da2_recalc_mapping(da2); - if (da2->pos_regs[2] & 0x01) - { - da2_log("DA2 enable registers\n"); - for (int i = 0; i < 8; i++) - da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); - io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, 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); - } - else - { - da2_log("DA2 disable registers\n"); - 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); - io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); - } + da2_t *da2 = (da2_t *) p; + return da2->pos_regs[port & 7]; } -void da2_mca_write(int port, uint8_t val, void *p) +void +da2_mca_write(int port, uint8_t val, void *p) { - da2_t *da2 = (da2_t *)p; + da2_t *da2 = (da2_t *) p; - da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); - - if (port < 0x102) - return; - da2->pos_regs[port & 7] = val; + da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); - da2_mapping_update(da2); + if (port < 0x102) + return; + da2->pos_regs[port & 7] = val; + + da2_mapping_update(da2); } -static uint8_t da2_mca_feedb(void* priv) +static uint8_t +da2_mca_feedb(void *priv) { - const da2_t* da2 = (da2_t*)priv; + const da2_t *da2 = (da2_t *) priv; - return da2->pos_regs[2] & 0x01; + return da2->pos_regs[2] & 0x01; } -static void da2_mca_reset(void *p) +static void +da2_mca_reset(void *p) { - da2_t *da2 = (da2_t *)p; - da2_reset(da2); - da2_mca_write(0x102, 0, da2); + da2_t *da2 = (da2_t *) p; + da2_log("da2_mca_reset called.\n"); + da2_reset(da2); + da2_mca_write(0x102, 0, da2); } -static void da2_gdcropB(uint32_t addr, da2_t* da2) { +static void +da2_gdcropB(uint32_t addr, da2_t *da2) +{ for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; + // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) { + case 0: /*Set*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 1: /*AND*/ + // da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 2: /*OR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 3: /*XOR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; } } } } -static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { +static void +da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) +{ uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; + // da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) { + case 0: /*Set*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 1: /*AND*/ + // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 2: /*OR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 3: /*XOR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; } } } } -static uint8_t da2_mmio_read(uint32_t addr, void* p) +static uint8_t +da2_mmio_read(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) /* linear access */ - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); - else - { + addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); + else { /* 64k bank switch access */ uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; addr += index * 0x40; } - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + // da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { - case 0xb0:/* Gaiji RAM */ - addr &= DA2_MASK_GAIJIRAM;/* safety access */ - //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); - return da2->mmio.ram[addr]; - break; - case 0x10:/* Font ROM */ - if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { - if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; - if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, - but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ - } - if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); - return da2->mmio.font[addr]; - break; - default: - return DA2_INVALIDACCESS8;/* invalid memory access */ - break; + case 0xb0: /* Gaiji RAM */ + addr &= DA2_MASK_GAIJIRAM; /* safety access */ + // da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); + return da2->mmio.ram[addr]; + break; + case 0x10: /* Font ROM */ + if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { + if (addr >= 0x1a0000) + return DA2_INVALIDACCESS8; + if (addr >= 0x180000) + addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, + but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ + } + if (addr >= DA2_FONTROM_SIZE) + return DA2_INVALIDACCESS8; + // da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + return da2->mmio.font[addr]; + break; + default: + return DA2_INVALIDACCESS8; /* invalid memory access */ + break; } - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 or 256 color mode */ { cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) - da2->gdcla[i] = da2->vram[(addr << 3) | i];/* read in byte */ - //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); - if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ + da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ + // da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ + for (int i = 0; i < 8; i++) { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); } return ~ret; - } - else return da2->gdcla[da2->readplane]; - } - else /* text mode 3 */ + } else + return da2->gdcla[da2->readplane]; + } else /* text mode 3 */ { cycles -= video_timing_read_b; return da2->vram[addr]; } } -static uint16_t da2_mmio_readw(uint32_t addr, void* p) +static uint16_t +da2_mmio_readw(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ + return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ { cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) - da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);/* read vram into latch */ + da2->gdcla[i] = (uint16_t) (da2->vram[(addr << 3) | i]) | ((uint16_t) (da2->vram[((addr << 3) + 8) | i]) << 8); /* read vram into latch */ #ifdef ENABLE_DA2_DEBUGBLT ////debug - //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) + // if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ - // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 16; i++) + // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); + // } + // for (int i = 0; i < 16; i++) //{ - // int pixeldata = 0; - // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; - // fprintf(da2->mmrdbg_fp, "%X", pixeldata); - //} - //da2->mmrdbg_vidaddr = addr; + // int pixeldata = 0; + // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; + // fprintf(da2->mmrdbg_fp, "%X", pixeldata); + // } + // da2->mmrdbg_vidaddr = addr; #endif - if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ + if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint16_t ret = 0; - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ + for (int i = 0; i < 8; i++) { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); } return ~ret; - } - else - { - //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + } else { + // da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); return da2->gdcla[da2->readplane]; } - } - else { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } else { + return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } } -static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) +static void +da2_mmio_write(uint32_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //da2_log("da2_mmio_write %x %x\n", addr, val); - if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; + da2_t *da2 = (da2_t *) p; + // da2_log("da2_mmio_write %x %x\n", addr, val); + if ((addr & ~DA2_MASK_MMIO) != 0xA0000) + return; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { - //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); + // if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); /* Gaiji RAM */ if (da2->fctl[LF_MMIO_SEL] == 0x80) - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);/* xxxy yyyy yyyy yyyy yyyy */ - else - { + addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); /* xxxy yyyy yyyy yyyy yyyy */ + else { uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; addr += index * 0x40; } switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0:/* Gaiji RAM 1011 0000 */ - addr &= DA2_MASK_GAIJIRAM;/* safety access */ - da2->mmio.ram[addr] = val; - break; - case 0x10:/* Font ROM 0001 0000 */ - /* Read-Only */ - break; - case 0x00: - //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ - //if (addr >= DA2_BLT_MEMSIZE) - //{ - // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - // return; - //} - da2->bitblt.indata = 1; - if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) - da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - break; - default: - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - break; + case 0xb0: /* Gaiji RAM 1011 0000 */ + addr &= DA2_MASK_GAIJIRAM; /* safety access */ + da2->mmio.ram[addr] = val; + break; + case 0x10: /* Font ROM 0001 0000 */ + /* Read-Only */ + break; + case 0x00: + // da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + // addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ + // if (addr >= DA2_BLT_MEMSIZE) + //{ + // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + // return; + // } + da2->bitblt.indata = 1; + if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + break; + default: + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + break; } - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ { uint8_t wm = da2->writemask; - //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); + // da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT - //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + // 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) - { + if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { fprintf(da2->mmdbg_fp, "\nB %x ", addr); for (int i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } - for (int i = 0; i < 8; i++) - { + for (int i = 0; i < 8; i++) { int pixeldata = 0; - if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + if (val & (1 << (7 - i))) + pixeldata = (da2->writemask & 0xf); fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; @@ -2458,270 +2447,270 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ + da2->gdcsrc[i] = da2->gdcla[i]; /* use latch */ - //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); - //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + // da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); + // da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) + da2->gdcinput[i] = ~val; + else + da2->gdcinput[i] = val; da2_gdcropB(addr, da2); return; } - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { + switch (da2->writemode) { + case 2: for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else da2->gdcinput[i] = val; + if (da2->writemask & (1 << i)) + da2->vram[addr | i] = da2->gdcsrc[i]; + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + da2->vram[addr | i] = val; + } else { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + 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, 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], da2->gdcreg[LG_BIT_MASK_LOW], 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: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + } else { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); + da2_gdcropB(addr, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + wm = da2->gdcreg[LG_BIT_MASK_LOW]; + da2->gdcreg[LG_BIT_MASK_LOW] &= val; for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i];/* use latch */ + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, 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], da2->gdcreg[LG_BIT_MASK_LOW], 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: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); - da2_gdcropB(addr, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = da2->gdcreg[LG_BIT_MASK_LOW]; - da2->gdcreg[LG_BIT_MASK_LOW] &= val; - - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - da2_gdcropB(addr, da2); - da2->gdcreg[LG_BIT_MASK_LOW] = wm; - break; + da2->gdcreg[LG_BIT_MASK_LOW] = wm; + 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 */ + // 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[addr] = val; da2->fullchange = 2; } } -uint16_t rightRotate(uint16_t data, uint8_t count) +uint16_t +rightRotate(uint16_t data, uint8_t count) { return (data >> count) | (data << (sizeof(data) * 8 - count)); } -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) +static void +da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { - da2_t* da2 = (da2_t*)p; - uint8_t wm = da2->writemask; + da2_t *da2 = (da2_t *) p; + uint8_t wm = da2->writemask; uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; - bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; + bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGBLT - //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + // 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 ", addr); - for (int i = 0; i <= 0xb; i++) - fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - } - for (int i = 0; i < 16; i++) - { - int pixeldata = 0; - if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); - fprintf(da2->mmdbg_fp, "%X", pixeldata); - } - da2->mmdbg_vidaddr = addr; + 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 ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 16; i++) { + int pixeldata = 0; + if (val & (1 << (15 - i))) + pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; //} #endif cycles -= video_timing_write_w; - //cycles_lost += video_timing_write_w; + // cycles_lost += video_timing_write_w; - //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); - //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_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); + // 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 >> 12] = changeframecount; + da2->changedvram[addr >> 12] = changeframecount; da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ + da2->gdcsrc[i] = da2->gdcla[i]; /* use latch */ - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) + da2->gdcinput[i] = ~val; + else + da2->gdcinput[i] = val; da2_gdcropW(addr, bitmask, da2); return; } - //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; - da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + // da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + switch (da2->writemode) { + case 2: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) { + da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; + da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + } + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) { + da2->vram[addr | i] = val & 0xff; + da2->vram[(addr + 8) | i] = val >> 8; + } + } else { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else + da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work - if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = val & 0xff; - da2->vram[(addr + 8) | i] = val >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else da2->gdcinput[i] = val; - da2_gdcropW(addr, bitmask, da2); - //da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - da2->vram[addr | i] = wdata & 0xff; - da2->vram[(addr + 8) | i] = wdata >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work - wm = bitmask; - bitmask &= val; + break; + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) { + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + da2->vram[addr | i] = wdata & 0xff; + da2->vram[(addr + 8) | i] = wdata >> 8; + } + } else { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + wm = bitmask; + bitmask &= val; - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - da2_gdcropW(addr, bitmask, da2); - bitmask = wm; - break; + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2_gdcropW(addr, bitmask, da2); + bitmask = wm; + break; } - //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + // da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); } -static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) +static void +da2_mmio_writew(uint32_t addr, uint16_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0x1ffff) != 0xA0000) return; + da2_t *da2 = (da2_t *) p; + // if ((addr & ~0x1ffff) != 0xA0000) return; if (da2->ioctl[LS_MMIO] & 0x10) { - //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ { addr &= DA2_MASK_MMIO; - //return; - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + // return; + // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); - } - else {/* mode 3h text */ - //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + } else { /* mode 3h text */ + // if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } } -static void da2_code_write(uint32_t addr, uint8_t val, void* p) +static void +da2_code_write(uint32_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0xfff) != 0xE0000) return; + da2_t *da2 = (da2_t *) p; + // if ((addr & ~0xfff) != 0xE0000) return; addr &= DA2_MASK_CRAM; da2->cram[addr] = val; da2->fullchange = 2; } -static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) +static void +da2_code_writeb(uint32_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); + da2_t *da2 = (da2_t *) p; + // da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); cycles -= video_timing_write_b; da2_code_write(addr, val, da2); } -static void da2_code_writew(uint32_t addr, uint16_t val, void* p) +static void +da2_code_writew(uint32_t addr, uint16_t val, void *p) { - //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); - da2_t* da2 = (da2_t*)p; + // da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + da2_t *da2 = (da2_t *) p; cycles -= video_timing_write_w; da2_code_write(addr, val & 0xff, da2); da2_code_write(addr + 1, val >> 8, da2); } -static uint8_t da2_code_read(uint32_t addr, void* p) +static uint8_t +da2_code_read(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; + da2_t *da2 = (da2_t *) p; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) + return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } -static uint8_t da2_code_readb(uint32_t addr, void* p) +static uint8_t +da2_code_readb(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; cycles -= video_timing_read_b; return da2_code_read(addr, da2); } -static uint16_t da2_code_readw(uint32_t addr, void* p) +static uint16_t +da2_code_readw(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; cycles -= video_timing_read_w; return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); - //return 0; } -void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) +void +da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) { if (wx != xsize || wy != ysize) { xsize = wx; @@ -2736,28 +2725,26 @@ void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) video_res_x = wx; video_res_y = wy; - video_bpp = 8; + video_bpp = 8; } -void da2_poll(void* priv) +void +da2_poll(void *priv) { - da2_t* da2 = (da2_t*)priv; - int x; + da2_t *da2 = (da2_t *) priv; + int x; - if (!da2->linepos) - { + if (!da2->linepos) { timer_advance_u64(&da2->timer, da2->dispofftime); - //if (output) printf("Display off %f\n",vidtime); + // if (output) printf("Display off %f\n",vidtime); da2->cgastat |= 1; da2->linepos = 1; - if (da2->dispon) - { + if (da2->dispon) { da2->hdisp_on = 1; da2->ma &= da2->vram_display_mask; - if (da2->firstline == 2000) - { + if (da2->firstline == 2000) { da2->firstline = da2->displine; video_wait_for_buffer(); } @@ -2769,27 +2756,24 @@ void da2_poll(void* priv) da2->lastline = da2->displine; } - //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + // da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); da2->displine++; - //if (da2->interlace) - // da2->displine++; - if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) - { - //da2_log("Vsync off at line %i\n",displine); + // if (da2->interlace) + // da2->displine++; + if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { + // da2_log("Vsync off at line %i\n",displine); da2->cgastat &= ~8; } da2->vslines++; if (da2->displine > 1200) da2->displine = 0; - //da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - //displine, vc, ma); - } - else - { - //da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + // displine, vc, ma); + } else { + // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); timer_advance_u64(&da2->timer, da2->dispontime); - //if (output) printf("Display on %f\n",vidtime); + // if (output) printf("Display on %f\n",vidtime); if (da2->dispon) da2->cgastat &= ~1; da2->hdisp_on = 0; @@ -2797,21 +2781,17 @@ void da2_poll(void* priv) da2->linepos = 0; if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) da2->con = 0; - if (da2->dispon) - { - if (da2->sc == da2->rowcount) - { + if (da2->dispon) { + if (da2->sc == da2->rowcount) { da2->linecountff = 0; - da2->sc = 0; + da2->sc = 0; - da2->maback += (da2->rowoffset << 1);/* color = 0x50(80), mono = 0x40(64) */ + da2->maback += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */ if (da2->interlace) da2->maback += (da2->rowoffset << 1); da2->maback &= da2->vram_display_mask; da2->ma = da2->maback; - } - else - { + } else { da2->sc++; da2->sc &= 31; da2->ma = da2->maback; @@ -2821,46 +2801,40 @@ void da2_poll(void* priv) da2->vc++; da2->vc &= 2047; - if (da2->vc == da2->dispend) - { + if (da2->vc == da2->dispend) { da2->dispon = 0; - //if (da2->crtc[10] & 0x20) da2->cursoron = 0; - //else da2->cursoron = da2->blink & 16; - if (da2->ioctl[LS_MODE] & 1) {/* in text mode */ - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)/* cursor blinking */ + // if (da2->crtc[10] & 0x20) da2->cursoron = 0; + // else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) { /* in text mode */ + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ { da2->cursoron = (da2->blink | 1) & da2->blinkconf; - } - else - { + } else { da2->cursoron = 0; } - if (!(da2->blink & (0x10 - 1)))/* force redrawing for cursor and blink attribute */ + if (!(da2->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ da2->fullchange = 2; } da2->blink++; - for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) - { + for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) { if (da2->changedvram[x]) da2->changedvram[x]--; } - //memset(changedvram,0,2048); del - if (da2->fullchange) - { + // memset(changedvram,0,2048); del + if (da2->fullchange) { da2->fullchange--; } } - if (da2->vc == da2->vsyncstart) - { + if (da2->vc == da2->vsyncstart) { int wx, wy; - //da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); da2->dispon = 0; da2->cgastat |= 8; x = da2->hdisp; - //if (da2->interlace && !da2->oddeven) da2->lastline++; - //if (da2->interlace && da2->oddeven) da2->firstline--; + // if (da2->interlace && !da2->oddeven) da2->lastline++; + // if (da2->interlace && da2->oddeven) da2->firstline--; wx = x; wy = da2->lastline - da2->firstline; @@ -2868,57 +2842,62 @@ void da2_poll(void* priv) da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); da2->firstline = 2000; - da2->lastline = 0; + da2->lastline = 0; da2->firstline_draw = 2000; - da2->lastline_draw = 0; + da2->lastline_draw = 0; da2->oddeven ^= 1; changeframecount = da2->interlace ? 3 : 2; - da2->vslines = 0; + 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; + // 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 %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); } - if (da2->vc == da2->vtotal) - { - //da2_log("VC vtotal\n"); - //printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); - da2->vc = 0; - da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; - da2->dispon = 1; - da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + if (da2->vc == da2->vtotal) { + // da2_log("VC vtotal\n"); + // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + da2->vc = 0; + da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->dispon = 1; + da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; da2->scrollcache = da2->attrc[LV_PANNING] & 7; } 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"); + // 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 da2_loadfont(char* fname, void* p) { - da2_t* da2 = (da2_t*)p; +static void +da2_loadfont(char *fname, void *p) +{ + da2_t *da2 = (da2_t *) p; uint8_t buf; - //uint32_t code = 0; + // uint32_t code = 0; uint64_t fsize; - if (!fname) return; - if (*fname == '\0') return; - FILE* mfile = rom_fopen(fname, "rb"); + if (!fname) + return; + if (*fname == '\0') + return; + FILE *mfile = rom_fopen(fname, "rb"); if (!mfile) { - //da2_log("MSG: Can't open binary ROM font file: %s\n", fname); + // da2_log("MSG: Can't open binary ROM font file: %s\n", fname); return; } fseek(mfile, 0, SEEK_END); @@ -2926,9 +2905,9 @@ static void da2_loadfont(char* fname, void* p) { fseek(mfile, 0, SEEK_SET); if (fsize > DA2_FONTROM_SIZE) { fsize = DA2_FONTROM_SIZE; /* truncate read data */ - //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); - //fclose(mfile); - //return 1; + // da2_log("MSG: The binary ROM font is truncated: %s\n", fname); + // fclose(mfile); + // return 1; } uint32_t j = 0; while (ftell(mfile) < fsize) { @@ -2941,50 +2920,58 @@ static void da2_loadfont(char* fname, void* p) { } /* 12-bit DAC color palette for IBMJ Display Adapter with color monitor */ -static uint8_t ps55_palette_color[64][3] = -{ -{0x00,0x00,0x00},{0x00,0x00,0x2A},{0x00,0x2A,0x00},{0x00,0x2A,0x2A},{0x2A,0x00,0x00},{0x2A,0x00,0x2A},{0x2A,0x2A,0x00},{0x2A,0x2A,0x2A}, -{0x00,0x00,0x15},{0x00,0x00,0x3F},{0x00,0x2A,0x15},{0x00,0x2A,0x3F},{0x2A,0x00,0x15},{0x2A,0x00,0x3F},{0x2A,0x2A,0x15},{0x2A,0x2A,0x3F}, -{0x00,0x15,0x00},{0x00,0x15,0x2A},{0x00,0x3F,0x00},{0x00,0x3F,0x2A},{0x2A,0x15,0x00},{0x2A,0x15,0x2A},{0x2A,0x3F,0x00},{0x2A,0x3F,0x2A}, -{0x00,0x15,0x15},{0x00,0x15,0x3F},{0x00,0x3F,0x15},{0x00,0x3F,0x3F},{0x2A,0x15,0x15},{0x2A,0x15,0x3F},{0x2A,0x3F,0x15},{0x2A,0x3F,0x3F}, -{0x15,0x00,0x00},{0x15,0x00,0x2A},{0x15,0x2A,0x00},{0x15,0x2A,0x2A},{0x3F,0x00,0x00},{0x3F,0x00,0x2A},{0x3F,0x2A,0x00},{0x3F,0x2A,0x2A}, -{0x15,0x00,0x15},{0x15,0x00,0x3F},{0x15,0x2A,0x15},{0x15,0x2A,0x3F},{0x3F,0x00,0x15},{0x3F,0x00,0x3F},{0x3F,0x2A,0x15},{0x3F,0x2A,0x3F}, -{0x15,0x15,0x00},{0x15,0x15,0x2A},{0x15,0x3F,0x00},{0x15,0x3F,0x2A},{0x3F,0x15,0x00},{0x3F,0x15,0x2A},{0x3F,0x3F,0x00},{0x3F,0x3F,0x2A}, -{0x15,0x15,0x15},{0x15,0x15,0x3F},{0x15,0x3F,0x15},{0x15,0x3F,0x3F},{0x3F,0x15,0x15},{0x3F,0x15,0x3F},{0x3F,0x3F,0x15},{0x3F,0x3F,0x3F} +static uint8_t ps55_palette_color[64][3] = { + { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x2A }, { 0x00, 0x2A, 0x00 }, { 0x00, 0x2A, 0x2A }, + { 0x2A, 0x00, 0x00 }, { 0x2A, 0x00, 0x2A }, { 0x2A, 0x2A, 0x00 }, { 0x2A, 0x2A, 0x2A }, + { 0x00, 0x00, 0x15 }, { 0x00, 0x00, 0x3F }, { 0x00, 0x2A, 0x15 }, { 0x00, 0x2A, 0x3F }, + { 0x2A, 0x00, 0x15 }, { 0x2A, 0x00, 0x3F }, { 0x2A, 0x2A, 0x15 }, { 0x2A, 0x2A, 0x3F }, + { 0x00, 0x15, 0x00 }, { 0x00, 0x15, 0x2A }, { 0x00, 0x3F, 0x00 }, { 0x00, 0x3F, 0x2A }, + { 0x2A, 0x15, 0x00 }, { 0x2A, 0x15, 0x2A }, { 0x2A, 0x3F, 0x00 }, { 0x2A, 0x3F, 0x2A }, + { 0x00, 0x15, 0x15 }, { 0x00, 0x15, 0x3F }, { 0x00, 0x3F, 0x15 }, { 0x00, 0x3F, 0x3F }, + { 0x2A, 0x15, 0x15 }, { 0x2A, 0x15, 0x3F }, { 0x2A, 0x3F, 0x15 }, { 0x2A, 0x3F, 0x3F }, + { 0x15, 0x00, 0x00 }, { 0x15, 0x00, 0x2A }, { 0x15, 0x2A, 0x00 }, { 0x15, 0x2A, 0x2A }, + { 0x3F, 0x00, 0x00 }, { 0x3F, 0x00, 0x2A }, { 0x3F, 0x2A, 0x00 }, { 0x3F, 0x2A, 0x2A }, + { 0x15, 0x00, 0x15 }, { 0x15, 0x00, 0x3F }, { 0x15, 0x2A, 0x15 }, { 0x15, 0x2A, 0x3F }, + { 0x3F, 0x00, 0x15 }, { 0x3F, 0x00, 0x3F }, { 0x3F, 0x2A, 0x15 }, { 0x3F, 0x2A, 0x3F }, + { 0x15, 0x15, 0x00 }, { 0x15, 0x15, 0x2A }, { 0x15, 0x3F, 0x00 }, { 0x15, 0x3F, 0x2A }, + { 0x3F, 0x15, 0x00 }, { 0x3F, 0x15, 0x2A }, { 0x3F, 0x3F, 0x00 }, { 0x3F, 0x3F, 0x2A }, + { 0x15, 0x15, 0x15 }, { 0x15, 0x15, 0x3F }, { 0x15, 0x3F, 0x15 }, { 0x15, 0x3F, 0x3F }, + { 0x3F, 0x15, 0x15 }, { 0x3F, 0x15, 0x3F }, { 0x3F, 0x3F, 0x15 }, { 0x3F, 0x3F, 0x3F } }; -void da2_reset_ioctl(da2_t* da2) +void +da2_reset_ioctl(da2_t *da2) { - da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ + da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ } static void -da2_reset(void* priv) +da2_reset(void *priv) { - da2_t* da2 = (da2_t*)priv; + da2_t *da2 = (da2_t *) priv; /* Initialize drawing */ da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; + da2->render = da2_render_blank; da2_reset_ioctl(da2); - da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ - da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ - da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ - da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ - da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ - da2->fctl[0] = 0x2b; /* 3E3h:0 */ - da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ - da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ - da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ - da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->ma_latch = 0; - da2->interlace = 0; - da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ - da2->attr_palette_enable = 0; /* disable attribute generator */ + da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ + da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8) << 1); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ + da2->fctl[0] = 0x2b; /* 3E3h:0 */ + da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ + da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ + da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ + da2->ma_latch = 0; + da2->interlace = 0; + da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Windows 3.1 display driver won't reset palette) */ for (int i = 0; i < 256; i++) { @@ -2993,171 +2980,178 @@ da2_reset(void* priv) da2->vgapal[i].b = ps55_palette_color[i & 0x3F][2]; da2->pallook[i] = makecol32((da2->vgapal[i].r & 0x3f) * 4, (da2->vgapal[i].g & 0x3f) * 4, (da2->vgapal[i].b & 0x3f) * 4); } + da2_log("da2_reset done.\n"); } -static void *da2_init() +static void * +da2_init() { - if (svga_get_pri() == NULL) - return NULL; - svga_t *mb_vga = svga_get_pri(); - mb_vga->cable_connected = 0; + if (svga_get_pri() == NULL) + return NULL; + svga_t *mb_vga = svga_get_pri(); + mb_vga->cable_connected = 0; - da2_t* da2 = malloc(sizeof(da2_t)); - da2->mb_vga = mb_vga; + da2_t *da2 = malloc(sizeof(da2_t)); + da2->mb_vga = mb_vga; - da2->dispontime = 1000ull << 32; - da2->dispofftime = 1000ull << 32; - int memsize = 1024 * 1024; - da2->vram = malloc(memsize); - da2->vram_mask = memsize - 1; - da2->cram = malloc(0x1000); - da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12); /* XX000h */ - da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ + da2->dispontime = 1000ull << 32; + da2->dispofftime = 1000ull << 32; + int memsize = 1024 * 1024; + da2->vram = malloc(memsize); + da2->vram_mask = memsize - 1; + da2->cram = malloc(0x1000); + da2->vram_display_mask = DA2_MASK_CRAM; + da2->changedvram = malloc(/*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ + da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - da2->mmio.charset = device_get_config_int("charset"); - da2->mmio.font= malloc(DA2_FONTROM_SIZE); - switch(da2->mmio.charset) - { - case DA2_DCONFIG_CHARSET_HANT: - da2_loadfont(DA2_FONTROM_PATH_HANT, da2); - break; - case DA2_DCONFIG_CHARSET_JPAN: - da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); - break; - } + da2->mmio.charset = device_get_config_int("charset"); + da2->mmio.font = malloc(DA2_FONTROM_SIZE); + switch (da2->mmio.charset) { + case DA2_DCONFIG_CHARSET_HANT: + da2_loadfont(DA2_FONTROM_PATH_HANT, da2); + break; + case DA2_DCONFIG_CHARSET_JPAN: + da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + break; + } - mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ + mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT - da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); - da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); - da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); - da2->bitblt.debug_reg_ip = 0; + da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); + da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); + da2->bitblt.debug_reg_ip = 0; #endif - da2->bitblt.payload_addr = 0; - da2_reset(da2); - - mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); + da2->bitblt.payload_addr = 0; + da2_reset(da2); - mem_mapping_disable(&da2->mmio.mapping); + mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + // da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); - mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + mem_mapping_disable(&da2->mmio.mapping); - mem_mapping_disable(&da2->cmapping); + mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ - timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + mem_mapping_disable(&da2->cmapping); - return da2; + timer_add(&da2->timer, da2_poll, da2, 0); + da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + + return da2; } -static int da2_available() +static int +da2_available() { - return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); + return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } -void da2_close(void *p) +void +da2_close(void *p) { - da2_t *da2 = (da2_t *)p; + da2_t *da2 = (da2_t *) p; - /* dump mem for debug */ + /* dump mem for debug */ #ifdef ENABLE_DA2_LOG - FILE* f; - f = fopen("da2_cram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->cram, 0x1000, 1, f); - fclose(f); - } - f = fopen("da2_vram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vram, 1024*1024, 1, f); - fclose(f); - } - f = fopen("da2_gram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->mmio.ram, 256*1024, 1, f); - fclose(f); - } - f = fopen("da2_attrpal.dmp", "wb"); - if (f != NULL) { - fwrite(da2->attrc, 32, 1, f); - fclose(f); - } - f = fopen("da2_dacrgb.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vgapal, 3*256, 1, f); - fclose(f); - } - f = fopen("da2_daregs.txt", "w"); - if (f != NULL) { - for (int i=0;i<0x10;i++) - fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); - for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); - fclose(f); - } + FILE *f; + f = fopen("da2_cram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->cram, 0x1000, 1, f); + fclose(f); + } + f = fopen("da2_vram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vram, 1024 * 1024, 1, f); + fclose(f); + } + f = fopen("da2_gram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->mmio.ram, 256 * 1024, 1, f); + fclose(f); + } + f = fopen("da2_attrpal.dmp", "wb"); + if (f != NULL) { + fwrite(da2->attrc, 32, 1, f); + fclose(f); + } + f = fopen("da2_dacrgb.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vgapal, 3 * 256, 1, f); + fclose(f); + } + f = fopen("da2_daregs.txt", "w"); + if (f != NULL) { + for (int i = 0; i < 0x10; i++) + fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (int i = 0; i < 0x40; i++) + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + fclose(f); + } #endif #ifdef ENABLE_DA2_DEBUGBLT - f = fopen("da2_bltdump.csv", "w"); - if (f != NULL && da2->bitblt.debug_reg_ip > 0) { - /* print header */ + f = fopen("da2_bltdump.csv", "w"); + if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + /* print header */ + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) + fprintf(f, "\"%02X\"\t", y); + } + fprintf(f, "\n"); + /* print data */ + for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) - fprintf(f, "\"%02X\"\t", y); + if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) + ; + else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) + fprintf(f, "\"\"\t"); + else + fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); } fprintf(f, "\n"); - /* print data */ - for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { - for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) - ; - else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) - fprintf(f, "\"\"\t"); - else - fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); - } - fprintf(f, "\n"); - } - fclose(f); } - if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); - if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); + fclose(f); + } + if (da2->mmdbg_fp != NULL) + fclose(da2->mmdbg_fp); + if (da2->mmrdbg_fp != NULL) + fclose(da2->mmrdbg_fp); + free(da2->bitblt.debug_reg); #endif - free(da2->cram); - free(da2->vram); - free(da2->changedvram); - free(da2->mmio.font); - free(da2); + free(da2->cram); + free(da2->vram); + free(da2->changedvram); + free(da2->mmio.font); + free(da2); } -void da2_speed_changed(void *p) +void +da2_speed_changed(void *p) { - da2_t* da2 = (da2_t*)p; - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + da2_t *da2 = (da2_t *) p; + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); da2_recalctimings(da2); } -void da2_force_redraw(void *p) +void +da2_force_redraw(void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; da2->fullchange = changeframecount; } static const device_config_t da2_configuration[] = { - // clang-format off + // clang-format off { .name = "charset", .description = "Charset", @@ -3197,7 +3191,7 @@ static const device_config_t da2_configuration[] = { } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t ps55da2_device = { From 32c040f8fa6e58feaf288cded6a003e42a383f57 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 16 Feb 2025 05:57:28 +0100 Subject: [PATCH 0287/1190] NEAT: Fix alternate A20 gate, fixes #5168. --- src/chipset/neat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 069fa87e4..c1c2e827a 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -845,7 +845,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) dev->ems_size); } - mem_a20_key = val & RB12_GA20; + mem_a20_alt = val & RB12_GA20; mem_a20_recalc(); break; From f4df7491b0ae16ed5c272b19ff36bce7a4ecc0f2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 16 Feb 2025 14:45:12 +0100 Subject: [PATCH 0288/1190] The Commodore 386SX-16 now correctly has a PS/2 keyboard controller. --- src/machine/m_at_286_386sx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index cb2a04d07..362f035e0 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -628,7 +628,7 @@ machine_at_cmdsl386sx16_init(const machine_t *model) machine_at_common_ide_init(model); - device_add(&keyboard_at_device); + device_add(&keyboard_ps2_device); if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); From 8d54e6adf08746bdf463067abac69b88dcec8479 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 16 Feb 2025 15:38:02 +0100 Subject: [PATCH 0289/1190] NEAT: Fixed chipset A20 gate toggle. --- src/chipset/neat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index c1c2e827a..2990b5216 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -845,7 +845,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) dev->ems_size); } - mem_a20_alt = val & RB12_GA20; + mem_a20_key = !(val & RB12_GA20); mem_a20_recalc(); break; From 58c5d9606e0c24e86e85e7e7adff2a0e25bb3382 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 16 Feb 2025 23:47:10 +0900 Subject: [PATCH 0290/1190] fixed some drawing issues in Win 3.1. * Changed bitblt execution. This fixes a mouse cursor color issue in Windows 3.1. * Fixed splash graphics broken in A-Train IV. --- src/video/vid_ps55da2.c | 145 +++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 61 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 9ed099f19..060e47ce6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -237,6 +237,7 @@ #ifdef ENABLE_DA2_LOG # define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGFULLSCREEN 1 int da2_do_log = ENABLE_DA2_LOG; static void @@ -609,7 +610,7 @@ da2_bitblt_load(da2_t *da2) { uint32_t value32; uint64_t value64; - da2_log("BITBLT loading params\n"); + da2_log("bltload: loading params\n"); // da2_log("BitBlt memory:\n"); // if (da2->bitblt.payload[0] != 0) // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) @@ -665,17 +666,20 @@ da2_bitblt_load(da2_t *da2) case 0x00: break; default: - da2_log("da2_ParseBLT: Unknown PreOP!\n"); + da2_log("bltload: Unknown PreOP!\n"); break; } i++; } da2->bitblt.exec = DA2_BLT_CIDLE; - /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; + // /* clear payload memory */ + // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + // da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; #ifdef ENABLE_DA2_DEBUGBLT for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { // if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); @@ -690,7 +694,7 @@ da2_bitblt_load(da2_t *da2) #endif da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ - da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); + da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); for (int i = 0; i <= 0xb; i++) da2_log("%02x ", da2->gdcreg[i]); da2_log("\n"); @@ -820,11 +824,12 @@ void da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + da2_log("bitblt_exec: %d\n", da2->bitblt.exec); // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: - timer_disable(&da2->bitblt.timer); + // timer_disable(&da2->bitblt.timer); break; case DA2_BLT_CLOAD: da2->bitblt.indata = 0; @@ -960,17 +965,30 @@ da2_bitblt_exec(void *p) } } void -da2_bitblt_dopayload(da2_t *da2) +da2_bitblt_dopayload(void *priv) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) { - da2->bitblt.exec = DA2_BLT_CLOAD; - // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ - da2_log("da2 Do bitblt\n"); - while (da2->bitblt.exec != DA2_BLT_CIDLE) { + da2_t *da2 = (da2_t *) priv; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // if (da2->bitblt.indata) /* for OS/2 J1.3 */ + // { + // if (da2->bitblt.exec == DA2_BLT_CIDLE) { + // da2->bitblt.exec = DA2_BLT_CLOAD; + // /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ + // da2_log("da2 Do bitblt\n"); + // while (da2->bitblt.exec != DA2_BLT_CIDLE) { + // da2_bitblt_exec(da2); + // } + // da2_log("da2 End bitblt %x\n", da2->bitblt.exec); + // } + // } + if (da2->bitblt.exec != DA2_BLT_CIDLE) + da2_bitblt_exec(da2); + else if (da2->bitblt.indata) /* for OS/2 J1.3 */ + { + if (da2->bitblt.exec == DA2_BLT_CIDLE) { + da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); } - da2_log("da2 End bitblt %x\n", da2->bitblt.exec); } } @@ -1091,7 +1109,9 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ - // val = 0x400; /* for debugging bitblt in Win 3.x */ +#ifdef ENABLE_DA2_DEBUGFULLSCREEN + val = 0x400; /* for debugging bitblt in Win 3.x */ +#endif break; case LC_VIEWPORT_SELECT: /* ViewPort Select? */ // return; @@ -1204,7 +1224,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); return; } - da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; + da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; break; // case 0x3ed: /* used by Windows 3.1 display driver */ // da2->gdcreg[5] = val & 0xff; @@ -1280,11 +1300,11 @@ da2_in(uint16_t addr, void *p) temp |= 0x80; } temp &= 0xf6; /* clear busy bit */ - if (da2->bitblt.indata) /* for OS/2 J1.3 */ - da2_bitblt_dopayload(da2); + // if (da2->bitblt.indata) /* for OS/2 J1.3 */ + // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { // da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x08; // wait(bit 3 + bit 0) + temp |= 0x01; // wait(bit 3 + bit 0) // if (!da2->bitblt.timer.enabled) //{ // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); @@ -1292,8 +1312,8 @@ da2_in(uint16_t addr, void *p) // } } if (da2->bitblt.indata) - temp |= 0x01; - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + temp |= 0x08; + da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); } // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); break; @@ -2143,8 +2163,10 @@ da2_mapping_update(da2_t *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); @@ -2193,28 +2215,28 @@ da2_mca_reset(void *p) } static void -da2_gdcropB(uint32_t addr, da2_t *da2) +da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) { for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { - // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, bitmask); switch (da2->gdcreg[LG_COMMAND] & 0x03) { case 0: /*Set*/ - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->gdcsrc[i] & ~bitmask); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); break; case 1: /*AND*/ - // da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); break; case 2: /*OR*/ - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); break; case 3: /*XOR*/ - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); break; } } @@ -2303,15 +2325,13 @@ da2_mmio_read(uint32_t addr, void *p) return DA2_INVALIDACCESS8; /* invalid memory access */ break; } - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 or 256 color mode */ cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ // da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; - for (int i = 0; i < 8; i++) { if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); @@ -2319,8 +2339,8 @@ da2_mmio_read(uint32_t addr, void *p) return ~ret; } else return da2->gdcla[da2->readplane]; - } else /* text mode 3 */ - { + } else { /* text mode 3 */ + cycles -= video_timing_read_b; return da2->vram[addr]; } @@ -2329,7 +2349,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; - da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ @@ -2419,9 +2439,12 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); break; } - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ uint8_t wm = da2->writemask; + uint8_t bitmask; + /* align bitmask to even address */ + if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; // da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) @@ -2460,20 +2483,20 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->gdcinput[i] = ~val; else da2->gdcinput[i] = val; - da2_gdcropB(addr, da2); + da2_gdcropB(addr, bitmask, da2); return; } switch (da2->writemode) { - case 2: + case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; break; - case 0: + case 0:/* equiv to vga write mode 0 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; @@ -2486,38 +2509,39 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) for (int i = 0; i < 8; i++) da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ - da2_gdcropB(addr, da2); + 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], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch + // 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: + 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->writemask & (1 << i)) - da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + 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, da2); + da2_gdcropB(addr, bitmask, da2); + fprintf(da2->mmdbg_fp, "m1-2"); } break; - case 3: + case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = da2->gdcreg[LG_BIT_MASK_LOW]; - da2->gdcreg[LG_BIT_MASK_LOW] &= val; + wm = bitmask; + bitmask &= val; for (int i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - da2_gdcropB(addr, da2); - da2->gdcreg[LG_BIT_MASK_LOW] = wm; + da2_gdcropB(addr, bitmask, da2); + bitmask = wm; 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 */ - { + } else { /* mode 3h text */ cycles -= video_timing_write_b; da2->vram[addr] = val; da2->fullchange = 2; @@ -2644,8 +2668,7 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ addr &= DA2_MASK_MMIO; // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); @@ -3039,7 +3062,7 @@ da2_init() timer_add(&da2->timer, da2_poll, da2, 0); da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ - timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; } From f6b6e39349b5cbe83a8d5d8859dbd4c7be28e4b6 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 17 Feb 2025 00:06:47 +0900 Subject: [PATCH 0291/1190] cleanup format --- src/disk/hdc_esdi_mca.c | 74 +++++++++++------------------------------ 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index df2a26349..690f658a0 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1385,9 +1385,7 @@ esdi_init(UNUSED(const device_t *info)) if (info->local == ESDI_IS_ADAPTER) { dev->pos_regs[0] = 0xff; dev->pos_regs[1] = 0xdd; - } - else if (info->local == ESDI_IS_INTEGRATED) - { + } else if (info->local == ESDI_IS_INTEGRATED) { dev->pos_regs[0] = 0x9f; dev->pos_regs[1] = 0xdf; } @@ -1400,8 +1398,7 @@ esdi_init(UNUSED(const device_t *info)) mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev, slotno - 1); else mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev); - } - else + } else mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); /* Mark for a reset. */ @@ -1453,56 +1450,25 @@ const device_t esdi_ps2_device = { }; static device_config_t -esdi_integrated_config[] = -{ - { - .name = "in_esdi_slot", - .description = "Slot #", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Auto", - .value = 0 - }, - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "3", - .value = 3 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "5", - .value = 5 - }, - { - .description = "6", - .value = 6 - }, - { - .description = "7", - .value = 7 - }, - { - .description = "8", - .value = 8 - } - }, - .default_int = 0 + esdi_integrated_config[] = { + { + .name = "in_esdi_slot", + .description = "Slot #", + .type = CONFIG_SELECTION, + .selection = { + { .description = "Auto", .value = 0 }, + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "3", .value = 3 }, + { .description = "4", .value = 4 }, + { .description = "5", .value = 5 }, + { .description = "6", .value = 6 }, + { .description = "7", .value = 7 }, + { .description = "8", .value = 8 } + }, + .default_int = 0 }, - { - .type = -1 - } + { .type = -1 } }; const device_t From 5314f519adb59f4aa70f3ad68d3c47c627087451 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 17 Feb 2025 00:11:33 +0900 Subject: [PATCH 0292/1190] cleanup format --- src/floppy/fdc.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index a8d2e6520..8a1a33f2f 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -744,13 +744,11 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ if (fdc->flags & FDC_FLAG_PS2_MCA) { - if (val & 0x04) - { - fdc->tfifo = 8; + if (val & 0x04) { + fdc->tfifo = 8; fdc->fifointest = 1; - } - else { - fdc->tfifo = 1; + } else { + fdc->tfifo = 1; fdc->fifointest = 0; } } @@ -767,10 +765,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->dsr = val; return; case 5: /*Command register*/ - if (fdc->fifointest) - { + if (fdc->fifointest) { /* Write FIFO buffer in the test mode (PS/55) */ - fdc_log("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); + fdc_log("FIFO buffer position = %X\n", ((fifo_t *) fdc->fifo_p)->end); fifo_write(val, fdc->fifo_p); if (fifo_get_full(fdc->fifo_p)) fdc->stat &= ~0x80; @@ -1368,8 +1365,7 @@ fdc_read(uint16_t addr, void *priv) ret = fdc->stat; break; case 5: /*Data*/ - if (fdc->fifointest) - { + if (fdc->fifointest) { /* Read FIFO buffer in the test mode (PS/55) */ ret = fifo_read(fdc->fifo_p); break; From 4b92bb62cbc97bc342b24060e7a6e63223f92aa6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 00:41:34 +0100 Subject: [PATCH 0293/1190] Commodore SL386SX-16: Remove internal IDE controller, sicne the real board has none. --- src/machine/m_at_286_386sx.c | 2 +- src/machine/machine_table.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 362f035e0..24cb88f09 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -626,7 +626,7 @@ machine_at_cmdsl386sx16_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&keyboard_ps2_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5010f984c..cb6bc964e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4688,7 +4688,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 8192, From 3d8bc797725fe49adaeb9ba26e3d16fa55e354d6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 01:17:21 +0100 Subject: [PATCH 0294/1190] NEAT: Fix EMS memory space allocation to correctly take RAM from the bottom rather than from the top. --- src/chipset/neat.c | 71 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 2990b5216..696f48d20 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -27,6 +27,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> @@ -263,6 +264,64 @@ neat_log(const char *fmt, ...) # define neat_log(fmt, ...) #endif +static uint8_t +neat_read_ram(uint32_t addr, void *priv) +{ + neat_t *dev = (neat_t *) priv; + + if (dev->regs[REG_RB7] & RB7_EMSEN) + addr += (dev->ems_size << 10); + + if (cpu_use_exec) + addreadlookup(mem_logical_addr, addr); + + return ram[addr]; +} + +static uint16_t +neat_read_ramw(uint32_t addr, void *priv) +{ + neat_t *dev = (neat_t *) priv; + + if (dev->regs[REG_RB7] & RB7_EMSEN) + addr += (dev->ems_size << 10); + + if (cpu_use_exec) + addreadlookup(mem_logical_addr, addr); + + return *(uint16_t *) &ram[addr]; +} + +static void +neat_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + neat_t *dev = (neat_t *) priv; + + if (dev->regs[REG_RB7] & RB7_EMSEN) + addr += (dev->ems_size << 10); + + if (cpu_use_exec) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[addr >> 12]); + } else + ram[addr] = val; +} + +static void +neat_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ + neat_t *dev = (neat_t *) priv; + + if (dev->regs[REG_RB7] & RB7_EMSEN) + addr += (dev->ems_size << 10); + + if (cpu_use_exec) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[addr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + /* Read one byte from paged RAM. */ static uint8_t ems_readb(uint32_t addr, void *priv) @@ -603,9 +662,11 @@ remap_update(neat_t *dev, uint8_t val) else mem_mapping_set_addr(&ram_low_mapping, 0x00000000, dev->remap_base << 10); - if (dev->remap_base > 1024) + if (dev->remap_base > 1024) { mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (dev->remap_base << 10) - 0x00100000); - else + mem_mapping_set_exec(&ram_high_mapping, &(ram[(val & RB7_EMSEN) ? 0x00100000 : + (0x00100000 + (dev->ems_size << 10))])); + } else mem_mapping_disable(&ram_high_mapping); if (val & RB7_UMAREL) { @@ -908,6 +969,12 @@ neat_init(UNUSED(const device_t *info)) /* Create an instance. */ dev = (neat_t *) calloc(1, sizeof(neat_t)); + 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); + mem_mapping_set_p(&ram_high_mapping, dev); + } + /* Get configured I/O address. */ j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; dev->ems_base = 0x0208 + (0x10 * j); From 63b223973c63828862ee25184d064b573087b0bd Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 01:27:40 +0100 Subject: [PATCH 0295/1190] NEAT: Mirror EMS port 2x8h on port 2x9h for reads as well, fixes EMS detection by Chips Expanded Manager version 2.2.0. --- src/chipset/neat.c | 59 ++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 696f48d20..d4eb3ec7f 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -34,8 +34,6 @@ #include <86box/plat_unused.h> #include <86box/chipset.h> -#define NEAT_DEBUG 0 - #define EMS_MAXPAGE 4 #define EMS_PGSIZE 16384 #define EMS_PGMASK 16383 @@ -328,7 +326,7 @@ ems_readb(uint32_t addr, void *priv) { ram_page_t *dev = (ram_page_t *) priv; uint8_t ret = 0xff; -#ifdef ENABLE_NEAT_LOG +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) uint32_t old = addr; #endif @@ -338,7 +336,9 @@ ems_readb(uint32_t addr, void *priv) if (addr < (mem_size << 10)) ret = *(uint8_t *) &(ram[addr]); +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) neat_log("[R08] %08X -> %08X (%08X): ret = %02X\n", old, addr, (mem_size << 10), ret); +#endif return ret; } @@ -348,7 +348,7 @@ ems_readw(uint32_t addr, void *priv) { ram_page_t *dev = (ram_page_t *) priv; uint16_t ret = 0xffff; -#ifdef ENABLE_NEAT_LOG +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) uint32_t old = addr; #endif @@ -358,7 +358,9 @@ ems_readw(uint32_t addr, void *priv) if (addr < (mem_size << 10)) ret = *(uint16_t *) &(ram[addr]); +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) neat_log("[R16] %08X -> %08X (%08X): ret = %04X\n", old, addr, (mem_size << 10), ret); +#endif return ret; } @@ -367,13 +369,15 @@ static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { ram_page_t *dev = (ram_page_t *) priv; -#ifdef ENABLE_NEAT_LOG +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) uint32_t old = addr; #endif /* Write the data. */ addr = addr - dev->virt_base + dev->phys_base; +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) neat_log("[W08] %08X -> %08X (%08X): val = %02X\n", old, addr, (mem_size << 10), val); +#endif if (addr < (mem_size << 10)) *(uint8_t *) &(ram[addr]) = val; @@ -384,13 +388,15 @@ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { ram_page_t *dev = (ram_page_t *) priv; -#ifdef ENABLE_NEAT_LOG +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) uint32_t old = addr; #endif /* Write the data. */ addr = addr - dev->virt_base + dev->phys_base; +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 3) neat_log("[W16] %08X -> %08X (%08X): val = %04X\n", old, addr, (mem_size << 10), val); +#endif if (addr < (mem_size << 10)) *(uint16_t *) &(ram[addr]) = val; @@ -505,7 +511,7 @@ ems_recalc(neat_t *dev, ram_page_t *ems) neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, MEM_FLAG_EMS, MEM_FMASK_EMS); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", ems->page, ems->addr - ram, ems->enabled ? "en" : "dis"); #endif @@ -528,7 +534,7 @@ ems_write(uint16_t port, uint8_t val, void *priv) int8_t new_enabled; uint32_t new_phys_base; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: ems_write(%04x, %02x)\n", port, val); #endif @@ -577,6 +583,7 @@ ems_read(uint16_t port, void *priv) switch (port & 0x000f) { case 0x0008: /* page number register */ + case 0x0009: ret = (dev->ems[vpage].phys_base / EMS_PGSIZE) & 0x7f; if (dev->ems[vpage].enabled) ret |= 0x80; @@ -587,7 +594,7 @@ ems_read(uint16_t port, void *priv) neat_log("Port: %04X, ret: %02X\n", port, ret); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: ems_read(%04x) = %02x\n", port, ret); #endif @@ -686,7 +693,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) uint8_t *reg; int i; -#if NEAT_DEBUG > 2 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: write(%04x, %02x)\n", port, val); #endif @@ -704,7 +711,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) *reg = (*reg & ~RA0_MASK) | val | (RA0_REV_ID << RA0_REV_SH); if ((xval & 0x20) && (val & 0x20)) outb(0x64, 0xfe); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RA0=%02x(%02x)\n", val, *reg); #endif break; @@ -712,7 +719,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RA1: val &= RA1_MASK; *reg = (*reg & ~RA1_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RA1=%02x(%02x)\n", val, *reg); #endif break; @@ -720,7 +727,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RA2: val &= RA2_MASK; *reg = (*reg & ~RA2_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RA2=%02x(%02x)\n", val, *reg); #endif break; @@ -728,7 +735,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB0: val &= RB0_MASK; *reg = (*reg & ~RB0_MASK) | val | (RB0_REV_ID << RB0_REV_SH); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB0=%02x(%02x)\n", val, *reg); #endif break; @@ -737,7 +744,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) val &= RB1_MASK; *reg = (*reg & ~RB1_MASK) | val; shadow_recalc(dev); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg); #endif break; @@ -749,7 +756,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) 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); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); #endif break; @@ -758,7 +765,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) val &= RB3_MASK; *reg = (*reg & ~RB3_MASK) | val; shadow_recalc(dev); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg); #endif break; @@ -767,7 +774,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) val &= RB4_MASK; *reg = (*reg & ~RB4_MASK) | val; shadow_recalc(dev); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg); #endif break; @@ -776,7 +783,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) val &= RB5_MASK; *reg = (*reg & ~RB5_MASK) | val; shadow_recalc(dev); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg); #endif break; @@ -784,7 +791,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB6: val &= RB6_MASK; *reg = (*reg & ~RB6_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB6=%02x(%02x)\n", val, *reg); #endif break; @@ -803,7 +810,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) if ((xval & RB7_EMSEN) && (val & RB7_EMSEN)) ems_set_handlers(dev); -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); #endif break; @@ -811,7 +818,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB8: val &= RB8_MASK; *reg = (*reg & ~RB8_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB8=%02x(%02x)\n", val, *reg); #endif break; @@ -819,7 +826,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB9: val &= RB9_MASK; *reg = (*reg & ~RB9_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); #endif @@ -842,7 +849,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB10: val &= RB10_MASK; *reg = (*reg & ~RB10_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); #endif @@ -877,7 +884,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB12: val &= RB12_MASK; *reg = (*reg & ~RB12_MASK) | val; -#if NEAT_DEBUG > 1 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg); #endif i = (val & RB12_EMSLEN) >> RB12_EMSLEN_SH; @@ -944,7 +951,7 @@ neat_read(uint16_t port, void *priv) break; } -#if NEAT_DEBUG > 2 +#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: read(%04x) = %02x\n", port, ret); #endif From 5c4fcfaf8525768dccaad201ad7e7911f475c1b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 04:49:43 +0100 Subject: [PATCH 0296/1190] ESC/P Printer: No longer assume roms/ is where the binary is, fixes #5221. --- src/include/86box/plat.h | 4 +- src/include/86box/rom.h | 1 + src/io.c | 104 ++++++++++++++++++++++++++++++++++--- src/mem/rom.c | 42 +++++++++++++++ src/printer/prt_escp.c | 10 ++-- src/qt/languages/86box.pot | 6 +++ src/qt/languages/ca-ES.po | 6 +++ src/qt/languages/cs-CZ.po | 6 +++ src/qt/languages/de-DE.po | 6 +++ src/qt/languages/es-ES.po | 6 +++ src/qt/languages/fi-FI.po | 6 +++ src/qt/languages/fr-FR.po | 6 +++ src/qt/languages/hr-HR.po | 10 +++- src/qt/languages/hu-HU.po | 6 +++ src/qt/languages/it-IT.po | 8 ++- src/qt/languages/ja-JP.po | 6 +++ src/qt/languages/ko-KR.po | 6 +++ src/qt/languages/nl-NL.po | 6 +++ src/qt/languages/pl-PL.po | 6 +++ src/qt/languages/pt-BR.po | 6 +++ src/qt/languages/pt-PT.po | 6 +++ src/qt/languages/ru-RU.po | 6 +++ src/qt/languages/sk-SK.po | 6 +++ src/qt/languages/sl-SI.po | 10 +++- src/qt/languages/tr-TR.po | 6 +++ src/qt/languages/uk-UA.po | 6 +++ src/qt/languages/vi-VN.po | 6 +++ src/qt/languages/zh-CN.po | 6 +++ src/qt/languages/zh-TW.po | 8 ++- src/qt/qt_platform.cpp | 2 + 30 files changed, 300 insertions(+), 19 deletions(-) diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index f39f6ba51..81874685e 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -50,7 +50,9 @@ enum { STRING_HW_NOT_AVAILABLE_DEVICE, /* "Device \"%hs\" is not available..." */ STRING_MONITOR_SLEEP, /* "Monitor in sleep mode" */ STRING_GHOSTPCL_ERROR_TITLE, /* "Unable to initialize GhostPCL" */ - STRING_GHOSTPCL_ERROR_DESC /* "gpcl6dll32.dll/gpcl6dll64.dll/libgpcl6 is required..." */ + STRING_GHOSTPCL_ERROR_DESC, /* "gpcl6dll32.dll/gpcl6dll64.dll/libgpcl6 is required..." */ + STRING_ESCP_ERROR_TITLE, /* "Unable to find Dot-Matrix fonts" */ + STRING_ESCP_ERROR_DESC /* "TrueType fonts in the \"roms/printer/fonts\" directory..." */ }; /* The Win32 API uses _wcsicmp. */ diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index 1f6e611b1..83fd7cf90 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -52,6 +52,7 @@ extern uint8_t rom_read(uint32_t addr, void *priv); extern uint16_t rom_readw(uint32_t addr, void *priv); extern uint32_t rom_readl(uint32_t addr, void *priv); +extern void rom_get_full_path(char *dest, const char *fn); extern FILE *rom_fopen(const char *fn, char *mode); extern int rom_getfile(char *fn, char *s, int size); extern int rom_present(const char *fn); diff --git a/src/io.c b/src/io.c index 27f8503b0..2565ac537 100644 --- a/src/io.c +++ b/src/io.c @@ -30,6 +30,7 @@ #include "cpu.h" #include <86box/m_amstrad.h> #include <86box/pci.h> +#include <86box/mem.h> #define NPORTS 65536 /* PC/AT supports 64K ports */ @@ -59,6 +60,7 @@ int initialized = 0; io_t *io[NPORTS]; io_t *io_last[NPORTS]; +// #define ENABLE_IO_LOG 1 #ifdef ENABLE_IO_LOG int io_do_log = ENABLE_IO_LOG; @@ -69,7 +71,8 @@ io_log(const char *fmt, ...) if (io_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + if (CS == 0xf000) + pclog_ex(fmt, ap); va_end(ap); } } @@ -77,6 +80,18 @@ io_log(const char *fmt, ...) # define io_log(fmt, ...) #endif +uint16_t last_port_read = 0xffff; + +static void +print_lpr(void) +{ + FILE *f = fopen("d:\\86boxnew\\ndiags.dmp", "wb"); + fwrite(&(ram[0x24c30]), 1, 65536, f); + fclose(f); + + pclog("last_port_read = %04X\n", last_port_read); +} + void io_init(void) { @@ -106,6 +121,8 @@ io_init(void) /* io[c] should be NULL. */ io[c] = io_last[c] = NULL; } + + atexit(print_lpr); } void @@ -333,6 +350,11 @@ io_debug_check_addr(uint16_t addr) } #endif +#include <86box/random.h> + +uint8_t post_code = 0xc6; +uint8_t action = 0x00; + uint8_t inb(uint16_t port) { @@ -393,7 +415,33 @@ inb(uint16_t port) ret = 0xfe; #endif - io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); +#if 0 + if (port == 0x5f7) + ret = 0xaf; +#endif + + if (port == 0x379) + ret &= 0xf8; + + // io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + + // if (CS == 0xc000) + // pclog("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); + + // if (port == 0x62) + // ret = 0xf2; + + // if (port == 0x62) + // ret |= random_generate() & 0x80; + + // if ((port >= 0x60) && (port <= 0x66)) + // pclog("[%04X:%04X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); + + if ((port != 0x0061) && (port != 0x0177) && (port != 0x01f7) && (port != 0x0376) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9) && (port != 0x03f6) && (port != 0x03da)) { + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + } + + last_port_read = port; return ret; } @@ -447,7 +495,20 @@ outb(uint16_t port, uint8_t val) #endif } - io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + // io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + + if (port == 0x0068) + action = val; + + if (port == 0x0080) + post_code = val; + + // if (port == 0x3db) + // pclog("[%04X:%04X] [W] %04X = %02X\n", CS, cpu_state.pc, port, val); + + if ((port != 0x0061) && (port != 0x00ed) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9)) { + io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + } return; } @@ -525,7 +586,9 @@ inw(uint16_t port) if (!found) cycles -= io_delay; - io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + } return ret; } @@ -594,7 +657,21 @@ outw(uint16_t port, uint16_t val) #endif } - io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + if (port == 0x0080) + post_code = val; + +#if 0 + if (port == 0x0c02) { + if (val) + mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else + mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } +#endif + + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + } return; } @@ -704,7 +781,9 @@ inl(uint16_t port) if (!found) cycles -= io_delay; - io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + } return ret; } @@ -791,7 +870,9 @@ outl(uint16_t port, uint32_t val) #endif } - io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + } return; } @@ -801,6 +882,7 @@ io_trap_readb(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 0, 0, trap->priv); + pclog("[%04X:%08X] io_trap_readb(%04X)\n", CS, cpu_state.pc, addr); return 0xff; } @@ -809,6 +891,7 @@ io_trap_readw(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 0, 0, trap->priv); + pclog("[%04X:%08X] io_trap_readw(%04X)\n", CS, cpu_state.pc, addr); return 0xffff; } @@ -817,6 +900,7 @@ io_trap_readl(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 0, 0, trap->priv); + pclog("[%04X:%08X] io_trap_readl(%04X)\n", CS, cpu_state.pc, addr); return 0xffffffff; } @@ -825,6 +909,7 @@ io_trap_writeb(uint16_t addr, uint8_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 1, val, trap->priv); + pclog("[%04X:%08X] io_trap_writeb(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -832,6 +917,7 @@ io_trap_writew(uint16_t addr, uint16_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 1, val, trap->priv); + pclog("[%04X:%08X] io_trap_writew(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -839,6 +925,7 @@ io_trap_writel(uint16_t addr, uint32_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 1, val, trap->priv); + pclog("[%04X:%08X] io_trap_writel(%04X)\n", CS, cpu_state.pc, addr); } void * @@ -885,6 +972,9 @@ io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size) io_trap_writeb, io_trap_writew, io_trap_writel, trap); } + + if ((addr == 0x0170) || (addr == 0x0376) || (addr == 0x01f0) || (addr == 0x03f6)) + pclog("io_trap_remape(%04X) = %i\n", addr, trap->enable); } void diff --git a/src/mem/rom.c b/src/mem/rom.c index f9718b7ce..8b2308402 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -86,6 +86,48 @@ rom_add_path(const char *path) path_slash(rom_path->path); } +static int +rom_check(const char *fn) +{ + FILE *fp = NULL; + int ret = 0; + + if ((fn[strlen(fn) - 1] == '/') || (fn[strlen(fn) - 1] == '\\')) + ret = plat_dir_check((char *) fn); + else { + fp = fopen(fn, "rb"); + ret = (fp != NULL); + fclose(fp); + } + + return ret; +} + +void +rom_get_full_path(char *dest, const char *fn) +{ + char temp[1024] = { 0 }; + + dest[0] = 0x00; + + if (strstr(fn, "roms/") == fn) { + /* Relative path */ + for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) { + path_append_filename(temp, rom_path->path, fn + 5); + + if (rom_check(temp)) { + strcpy(dest, temp); + return; + } + } + + return; + } else { + /* Absolute path */ + strcpy(dest, fn); + } +} + FILE * rom_fopen(const char *fn, char *mode) { diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 0198444a0..d0836e5f2 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1968,16 +1968,16 @@ escp_init(void *lpt) dev->ctrl = 0x04; dev->lpt = lpt; + rom_get_full_path(dev->fontpath, "roms/printer/fonts/"); + /* Create a full pathname for the font files. */ - if (strlen(exe_path) >= sizeof(dev->fontpath)) { + if (strlen(dev->fontpath) == 0) { + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_ESCP_ERROR_TITLE), + plat_get_string(STRING_ESCP_ERROR_DESC)); free(dev); return (NULL); } - strcpy(dev->fontpath, exe_path); - path_slash(dev->fontpath); - strcat(dev->fontpath, "roms/printer/fonts/"); - /* Create the full path for the page images. */ path_append_filename(dev->pagepath, usr_path, "printer"); if (!plat_dir_check(dev->pagepath)) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index ac2db7d07..65cc32f85 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2135,3 +2135,9 @@ msgstr "" msgid "Generic PC/AT Memory Expansion" msgstr "" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index e49ab3223..cf3d5c7f7 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -2129,3 +2129,9 @@ msgstr "Expansió de memòria genèrica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansió de memòria genèrica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "No es pot trobar tipus de lletra de matriu de punts" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Els tipus de lletra TrueType al directori \"roms/printer/fonts\" són necessaris per a l'emulació de la impressora de matriu de punts ESC/P genèrica." diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index cafadd63b..e3d85dd09 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -2129,3 +2129,9 @@ msgstr "Obecné rozšíření paměti PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Obecné rozšíření paměti PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nastala chyba při nachození jehličkových písem" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Pro emulaci obecné jehličkové tiskárny ESC/P jsou vyžadována písma TrueType ve složce \"roms/printer/fonts\"." diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index aa666cc48..c904cad0d 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -2132,3 +2132,9 @@ msgstr "Generische PC/XT-Speichererweiterung" msgid "Generic PC/AT Memory Expansion" msgstr "Generische PC/AT-Speichererweiterung" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nadel-Schriften konnten nicht gefunden werden" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType-Schriften in das \"roms/printer/fonts\"-Verzeichnis sind für die Allgemeines ESC/P Nadel-Druckers erforderlich." diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 5cac8968f..ca7a3ad53 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -2128,3 +2128,9 @@ msgstr "Expansión de Memoria Generica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansión de Memoria Generica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "No fué posible encontrar las fuentes matriciales" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Las fuentes TrueType en el directorio \"roms/printer/fonts\" son necesarias para la emulación de la impresora matricial ESC/P genérica." diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 21dcfd1bc..f044365f0 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -2129,3 +2129,9 @@ msgstr "Yleinen PC/XT-muistilaajennus" msgid "Generic PC/AT Memory Expansion" msgstr "Yleinen PC/AT-muistilaajennus" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Pistematriisifontteja ei löydy" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType-fontteja kansiossa \"roms/printer/fonts\"-hakemistoon yleinen ESC/P pistematriisitulostin emulointiin." diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index ff8a5168f..3b283b3dd 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -2129,3 +2129,9 @@ msgstr "Expansion de la mémoire générique PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansion de la mémoire générique PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Impossible de trouver les polices à matrice à points" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Les polices TrueType dans le répertoire \"roms/printer/fonts\" sont nécessaires à l'émulation de l'imprimante générique ESC/P à matrice à points." diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 9d242f8e0..ed4fdf621 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -655,7 +655,7 @@ msgid "ZIP images" msgstr "ZIP slike" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box nije mogao pronaći upotrebljive ROM datoteke.\n\nMolimte posjetite sknite paket s ROM datotekama i ekstrahirajte paket u \"roms\" mapu." +msgstr "86Box nije mogao pronaći upotrebljive ROM datoteke.\n\nMolimte posjetite sknite paket s ROM datotekama i ekstrahirajte paket u mapu \"roms\"." msgid "(empty)" msgstr "(prazno)" @@ -2062,7 +2062,7 @@ msgid "Generic Text Printer" msgstr "Generični tekstovni pisač" msgid "Generic ESC/P Dot-Matrix Printer" -msgstr "Generični pisač matrični ESC/P" +msgstr "Generični matrični pisač ESC/P" msgid "Generic PostScript Printer" msgstr "Generični pisač PostScript" @@ -2129,3 +2129,9 @@ msgstr "Generičko proširenje memorije PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Generičko proširenje memorije PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nije moguće pronaći matrične fontove" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType fontovi u mapi \"roms/printer/fonts\" potrebni su za emulaciju generičnog matričnog pisača ESC/P." diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 2b5adacf4..b4afd8010 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -2129,3 +2129,9 @@ msgstr "Általános PC/XT memóriabővítők" msgid "Generic PC/AT Memory Expansion" msgstr "Általános PC/AT memóriabővítők" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nem találja a Dot-Matrix betűtípusokat" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Az általános ESC/P pontmátrixnyomtató emulációjához a \"roms/printer/fonts\" könyvtárban található TrueType betűtípusok szükségesek." diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index c9af80127..73ec57ec0 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -655,7 +655,7 @@ msgid "ZIP images" msgstr "Immagini ZIP" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box non può trovare immagini ROM utilizzabili.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgstr "86Box non può trovare immagini ROM utilizzabili.\n\nSi prega di scaricare un set di ROM ed estrarlo nella directory \"roms\"." msgid "(empty)" msgstr "(empty)" @@ -2129,3 +2129,9 @@ msgstr "Espansione di memoria generica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Espansione di memoria generica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Impossibile trovare i font a matrice di punti" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "I font TrueType presenti nella directory \"roms/printer/fonts\" sono necessari per l'emulazione della stampante a matrice di punti ESC/P generica." diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 9a3289b51..9c6fa66e7 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -2129,3 +2129,9 @@ msgstr "汎用PC/XTメモリ拡張カード" msgid "Generic PC/AT Memory Expansion" msgstr "汎用PC/ATメモリ拡張カード" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "ドットマトリクスフォントが見つかりません" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "汎用ESC/Pドットマトリクスプリンタのエミュレーションには、roms/printer/fontsディレクトリ内のTrueTypeフォントが必要です。" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index c6928ad43..ec4b20d0d 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -2129,3 +2129,9 @@ msgstr "일반 PC/XT 메모리 확장 카드" msgid "Generic PC/AT Memory Expansion" msgstr "일반 PC/AT 메모리 확장 카드" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "도트 매트릭스 글꼴을 찾을 수 없습니다" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "일반 ESC/P 도트 매트릭스 프린터의 에뮬레이션을 사용하려면 \"roms/printer/fonts\" 디렉터리에 있는 트루타입 글꼴이 필요합니다." diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 27870db90..c601197ac 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -2129,3 +2129,9 @@ msgstr "Generieke PC/XT geheugenuitbreiding" msgid "Generic PC/AT Memory Expansion" msgstr "Generieke PC/AT geheugenuitbreiding" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Dot-matrix-lettertypen niet gevonden" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType lettertypen in de map \"roms/printer/fonts\" zijn nodig voor de emulatie van de generieke ESC/P dot-matrix-printer." diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index e42904458..78ded239f 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -2129,3 +2129,9 @@ msgstr "Generyczne rozszerzenie pamięci PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Generyczne rozszerzenie pamięci PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nie można znaleźć czcionek igłowych" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Czcionki TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generyczniej drukarki igłowej ESC/P." diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index de1bcd544..1594e30ab 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2129,3 +2129,9 @@ msgstr "Expansão de memória genérica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansão de memória genérica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Não foi possível localizar os fontes matriciais de pontos" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica." diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index d4c8bf170..b31f020d4 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -2129,3 +2129,9 @@ msgstr "Expansão de memória genérica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansão de memória genérica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Não foi possível encontrar os fontes matriciais de pontos" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a2e352faa..a8a4b7794 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2135,3 +2135,9 @@ msgstr "Стандартное расширение памяти PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Стандартное расширение памяти PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Невозможно найти матричные шрифты" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 6b2074d47..e789d9ef9 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -2129,3 +2129,9 @@ msgstr "Všeobecné rozšírenie pamäte PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Všeobecné rozšírenie pamäte PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nastala chyba pri hľadaní ihličkových písem" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Písma TrueType v adresári \"roms/printer/fonts\" sú potrebné na emuláciu generickej ihličkovej tlačiarne ESC/P." diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 9d8ccaaf9..1394a3635 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -823,10 +823,10 @@ msgid "Are you sure you want to exit 86Box?" msgstr "Ste prepričani, da želite zapreti 86Box?" msgid "Unable to initialize Ghostscript" -msgstr "Ne morem inicializirati Ghostscript" +msgstr "Ghostscript-a ni bilo mogoče inicializirati" msgid "Unable to initialize GhostPCL" -msgstr "Ne morem inicializirati GhostPCL" +msgstr "GhostPCL-ja ni bilo mogoče inicializirati" msgid "MO %i (%ls): %ls" msgstr "MO %i (%ls): %ls" @@ -2129,3 +2129,9 @@ msgstr "Generična razširitev pomnilnika PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Generična razširitev pomnilnika PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Matričnih pisav ni bilo mogoče najti" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Matrične pisave v imeniku \"roms/printer/fonts\" so potrebne za emulacijo generičnega matričnega tiskalnika ESC/P." diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 288412154..81866b3ce 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -2129,3 +2129,9 @@ msgstr "Sıradan PC/XT bellek artırma" msgid "Generic PC/AT Memory Expansion" msgstr "Sıradan PC/AT bellek artırma" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Dot Matrix yazı tipleri bulunamıyor" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Sıradan ESC/P Dot Matrix Yazıcının emülasyonu için \"roms/printer/fonts\" dizinindeki TrueType yazı tipleri gereklidir." diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 5ce59be01..9b57ac03e 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -2135,3 +2135,9 @@ msgstr "Загальне розширення пам'яті PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Загальне розширення пам'яті PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Неможливо знайти матричні шрифти" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Шрифти TrueType у каталозі \"roms/printer/fonts\" потрібні для емуляції загального матричного принтера Generic ESC/P." diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 707c7ae7f..fafbbc160 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -2129,3 +2129,9 @@ msgstr "Chung mở rộng bộ nhớ qua PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Chung mở rộng bộ nhớ qua PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Không tìm thấy phông chữ ma trận chấm" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Cần có phông chữ TrueType trong thư mục \"roms/printer/fonts\" để mô phỏng máy in generic ESC/P ma trận chấm." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 81451b2b3..ec5d2c252 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -2129,3 +2129,9 @@ msgstr "通用 PC/XT 内存扩展" msgid "Generic PC/AT Memory Expansion" msgstr "通用 PC/AT 内存扩展" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "无法找到点阵字体" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 9bf8edfc6..b0d8163cb 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2062,7 +2062,7 @@ msgid "Generic Text Printer" msgstr "通用文字印表機" msgid "Generic ESC/P Dot-Matrix Printer" -msgstr "通用 ESC/P 點矩陣" +msgstr "通用 ESC/P 點矩陣印表機" msgid "Generic PostScript Printer" msgstr "通用 PostScript 印表機" @@ -2129,3 +2129,9 @@ msgstr "通用 PC/XT 記憶體擴充" msgid "Generic PC/AT Memory Expansion" msgstr "通用 PC/AT 記憶體擴充" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "無法找到點矩陣字型" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "通用 ESC/P 點矩陣印表機的模擬需要 \"roms/printer/fonts\" 目錄中的 TrueType 字體。" diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index dd6c34efc..561c94d8a 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -639,6 +639,8 @@ ProgSettings::reloadStrings() translatedstrings[STRING_MONITOR_SLEEP] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString(); translatedstrings[STRING_NET_ERROR] = QCoreApplication::translate("", "Failed to initialize network driver").toStdWString(); translatedstrings[STRING_NET_ERROR_DESC] = QCoreApplication::translate("", "The network configuration will be switched to the null driver").toStdWString(); + translatedstrings[STRING_ESCP_ERROR_TITLE] = QCoreApplication::translate("", "Unable to find Dot-Matrix fonts").toStdWString(); + translatedstrings[STRING_ESCP_ERROR_DESC] = QCoreApplication::translate("", "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulatio of the Generic ESC/P Dot-Matrix Printer.").toStdWString(); } wchar_t * From a6a377757f3098eeb38ec3a71c725d31a897de53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 04:57:49 +0100 Subject: [PATCH 0297/1190] Paradise VGA: Override the horizontal skew handling, fixes #5228. --- src/video/vid_paradise.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index d0acaf276..da8bb9aa6 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -571,6 +571,8 @@ paradise_init(const device_t *info, uint32_t memory) paradise->type = info->local; + svga->hoverride = 1; + return paradise; } From f68810b2777ccfa749efe89bc815648fa8651a73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 15:20:16 +0100 Subject: [PATCH 0298/1190] Reverted the io.c changes that should not have been committed. --- src/io.c | 104 ++++--------------------------------------------------- 1 file changed, 7 insertions(+), 97 deletions(-) diff --git a/src/io.c b/src/io.c index 2565ac537..27f8503b0 100644 --- a/src/io.c +++ b/src/io.c @@ -30,7 +30,6 @@ #include "cpu.h" #include <86box/m_amstrad.h> #include <86box/pci.h> -#include <86box/mem.h> #define NPORTS 65536 /* PC/AT supports 64K ports */ @@ -60,7 +59,6 @@ int initialized = 0; io_t *io[NPORTS]; io_t *io_last[NPORTS]; -// #define ENABLE_IO_LOG 1 #ifdef ENABLE_IO_LOG int io_do_log = ENABLE_IO_LOG; @@ -71,8 +69,7 @@ io_log(const char *fmt, ...) if (io_do_log) { va_start(ap, fmt); - if (CS == 0xf000) - pclog_ex(fmt, ap); + pclog_ex(fmt, ap); va_end(ap); } } @@ -80,18 +77,6 @@ io_log(const char *fmt, ...) # define io_log(fmt, ...) #endif -uint16_t last_port_read = 0xffff; - -static void -print_lpr(void) -{ - FILE *f = fopen("d:\\86boxnew\\ndiags.dmp", "wb"); - fwrite(&(ram[0x24c30]), 1, 65536, f); - fclose(f); - - pclog("last_port_read = %04X\n", last_port_read); -} - void io_init(void) { @@ -121,8 +106,6 @@ io_init(void) /* io[c] should be NULL. */ io[c] = io_last[c] = NULL; } - - atexit(print_lpr); } void @@ -350,11 +333,6 @@ io_debug_check_addr(uint16_t addr) } #endif -#include <86box/random.h> - -uint8_t post_code = 0xc6; -uint8_t action = 0x00; - uint8_t inb(uint16_t port) { @@ -415,33 +393,7 @@ inb(uint16_t port) ret = 0xfe; #endif -#if 0 - if (port == 0x5f7) - ret = 0xaf; -#endif - - if (port == 0x379) - ret &= 0xf8; - - // io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - - // if (CS == 0xc000) - // pclog("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); - - // if (port == 0x62) - // ret = 0xf2; - - // if (port == 0x62) - // ret |= random_generate() & 0x80; - - // if ((port >= 0x60) && (port <= 0x66)) - // pclog("[%04X:%04X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); - - if ((port != 0x0061) && (port != 0x0177) && (port != 0x01f7) && (port != 0x0376) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9) && (port != 0x03f6) && (port != 0x03da)) { - io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - } - - last_port_read = port; + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } @@ -495,20 +447,7 @@ outb(uint16_t port, uint8_t val) #endif } - // io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - - if (port == 0x0068) - action = val; - - if (port == 0x0080) - post_code = val; - - // if (port == 0x3db) - // pclog("[%04X:%04X] [W] %04X = %02X\n", CS, cpu_state.pc, port, val); - - if ((port != 0x0061) && (port != 0x00ed) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9)) { - io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - } + io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); return; } @@ -586,9 +525,7 @@ inw(uint16_t port) if (!found) cycles -= io_delay; - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - } + io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } @@ -657,21 +594,7 @@ outw(uint16_t port, uint16_t val) #endif } - if (port == 0x0080) - post_code = val; - -#if 0 - if (port == 0x0c02) { - if (val) - mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - else - mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } -#endif - - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - } + io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); return; } @@ -781,9 +704,7 @@ inl(uint16_t port) if (!found) cycles -= io_delay; - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - } + io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } @@ -870,9 +791,7 @@ outl(uint16_t port, uint32_t val) #endif } - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - } + io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); return; } @@ -882,7 +801,6 @@ io_trap_readb(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 0, 0, trap->priv); - pclog("[%04X:%08X] io_trap_readb(%04X)\n", CS, cpu_state.pc, addr); return 0xff; } @@ -891,7 +809,6 @@ io_trap_readw(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 0, 0, trap->priv); - pclog("[%04X:%08X] io_trap_readw(%04X)\n", CS, cpu_state.pc, addr); return 0xffff; } @@ -900,7 +817,6 @@ io_trap_readl(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 0, 0, trap->priv); - pclog("[%04X:%08X] io_trap_readl(%04X)\n", CS, cpu_state.pc, addr); return 0xffffffff; } @@ -909,7 +825,6 @@ io_trap_writeb(uint16_t addr, uint8_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 1, val, trap->priv); - pclog("[%04X:%08X] io_trap_writeb(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -917,7 +832,6 @@ io_trap_writew(uint16_t addr, uint16_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 1, val, trap->priv); - pclog("[%04X:%08X] io_trap_writew(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -925,7 +839,6 @@ io_trap_writel(uint16_t addr, uint32_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 1, val, trap->priv); - pclog("[%04X:%08X] io_trap_writel(%04X)\n", CS, cpu_state.pc, addr); } void * @@ -972,9 +885,6 @@ io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size) io_trap_writeb, io_trap_writew, io_trap_writel, trap); } - - if ((addr == 0x0170) || (addr == 0x0376) || (addr == 0x01f0) || (addr == 0x03f6)) - pclog("io_trap_remape(%04X) = %i\n", addr, trap->enable); } void From 464253a8cd4dcbfd3c857ace6dfabe3be2a315ef Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 19:48:31 +0100 Subject: [PATCH 0299/1190] IDE: Fix device bus flags. --- 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 b69ddf128..fb95bef28 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3338,7 +3338,7 @@ const device_t ide_vlb_device = { const device_t ide_vlb_sec_device = { .name = "VLB IDE Controller (Secondary)", .internal_name = "ide_vlb_sec", - .flags = DEVICE_VLB | DEVICE_ISA16, + .flags = DEVICE_VLB, .local = 2, .init = ide_sec_init, .close = ide_sec_close, @@ -3352,7 +3352,7 @@ const device_t ide_vlb_sec_device = { const device_t ide_vlb_2ch_device = { .name = "VLB IDE Controller (Dual-Channel)", .internal_name = "ide_vlb_2ch", - .flags = DEVICE_VLB | DEVICE_ISA16, + .flags = DEVICE_VLB, .local = 3, .init = ide_init, .close = ide_close, @@ -3366,7 +3366,7 @@ const device_t ide_vlb_2ch_device = { const device_t ide_pci_device = { .name = "PCI IDE Controller", .internal_name = "ide_pci", - .flags = DEVICE_PCI | DEVICE_ISA16, + .flags = DEVICE_PCI, .local = 4, .init = ide_init, .close = ide_close, @@ -3380,7 +3380,7 @@ const device_t ide_pci_device = { const device_t ide_pci_sec_device = { .name = "PCI IDE Controller (Secondary)", .internal_name = "ide_pci_sec", - .flags = DEVICE_PCI | DEVICE_ISA16, + .flags = DEVICE_PCI, .local = 4, .init = ide_sec_init, .close = ide_sec_close, @@ -3394,7 +3394,7 @@ const device_t ide_pci_sec_device = { const device_t ide_pci_2ch_device = { .name = "PCI IDE Controller (Dual-Channel)", .internal_name = "ide_pci_2ch", - .flags = DEVICE_PCI | DEVICE_ISA16, + .flags = DEVICE_PCI, .local = 5, .init = ide_init, .close = ide_close, From 45dc381251e5769fccc0fe4f0575ae77a8bf3a40 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 19:50:53 +0100 Subject: [PATCH 0300/1190] Forgot the single-channel VLB controller. --- src/disk/hdc_ide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index fb95bef28..125cd806d 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3324,7 +3324,7 @@ const device_t ide_isa_2ch_device = { const device_t ide_vlb_device = { .name = "VLB IDE Controller", .internal_name = "ide_vlb", - .flags = DEVICE_VLB | DEVICE_ISA16, + .flags = DEVICE_VLB, .local = 2, .init = ide_init, .close = ide_close, From a6e866c0e547f4bffca287e425bdf598e7966a62 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 18 Feb 2025 22:34:27 +0900 Subject: [PATCH 0301/1190] added comments --- src/disk/hdc_esdi_mca.c | 16 ++++++++++++++-- src/floppy/fdc.c | 2 +- src/machine/m_ps2_mca.c | 6 +++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 690f658a0..8f1def137 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1471,16 +1471,28 @@ static device_config_t { .type = -1 } }; +/* +Device for an IBM DBA (Direct Bus Attachment) hard disk. +The Disk BIOS is included in the System ROM. +Some models have an exclusive channel slot for the DBA hard disk. +Following IBM machines are supported: + * PS/2 model 55SX + * PS/2 model 65SX + * PS/2 model 70 type 3 (Slot #4) + * PS/2 model 70 type 4 (Slot #4) + * PS/55 model 5550-T (Slot #5) + * PS/55 model 5550-V (Slot #5) +*/ const device_t esdi_integrated_device = { - .name = "IBM Integrated Fixed Disk Controller (MCA)", + .name = "IBM Integrated Fixed Disk and Controller (MCA)", .internal_name = "esdi_integrated_mca", .flags = DEVICE_MCA, .local = ESDI_IS_INTEGRATED, .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - .available = NULL, /* The Disk BIOS is included in the System ROM */ + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 8a1a33f2f..5de1a8ef4 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -740,7 +740,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } - /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + /* Bit 2: FIFO test mode (PS/55 5550-S,T only. Undocumented) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ if (fdc->flags & FDC_FLAG_PS2_MCA) { diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 1edff2991..ac22af2fe 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1890,7 +1890,11 @@ machine_ps55_model_50t_init(const machine_t* model) * Planar ID * FFFAh - PS/55 model 5551-S0x, T0x (stage 1?) * FFEEh - PS/55 model 5551-S1x, T1x (stage 2?) - * POST (P/N 38F6933) determination: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * Verification in BIOS P/N 38F6933: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * + * The only difference between S and T models is the CPU speed (16 MHz vs 20 MHz). + * The POST measures the speed, and sets a flag in the BIOS Data Area to indicate the sub model. + * The VM in 86Box runs faster than the real, so the POST always determines it as the T model. */ ps2.planar_id = 0xffee; ps55_mca_board_model_50t_init(); From 2c78e7bb2f5710bfbe57877422b8b6e96c8e3999 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 18 Feb 2025 22:46:18 +0900 Subject: [PATCH 0302/1190] added comments --- src/disk/hdc_esdi_mca.c | 16 ++++++++++++++-- src/floppy/fdc.c | 2 +- src/machine/m_ps2_mca.c | 6 +++++- src/video/vid_svga.c | 6 +++--- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 690f658a0..8f1def137 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1471,16 +1471,28 @@ static device_config_t { .type = -1 } }; +/* +Device for an IBM DBA (Direct Bus Attachment) hard disk. +The Disk BIOS is included in the System ROM. +Some models have an exclusive channel slot for the DBA hard disk. +Following IBM machines are supported: + * PS/2 model 55SX + * PS/2 model 65SX + * PS/2 model 70 type 3 (Slot #4) + * PS/2 model 70 type 4 (Slot #4) + * PS/55 model 5550-T (Slot #5) + * PS/55 model 5550-V (Slot #5) +*/ const device_t esdi_integrated_device = { - .name = "IBM Integrated Fixed Disk Controller (MCA)", + .name = "IBM Integrated Fixed Disk and Controller (MCA)", .internal_name = "esdi_integrated_mca", .flags = DEVICE_MCA, .local = ESDI_IS_INTEGRATED, .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - .available = NULL, /* The Disk BIOS is included in the System ROM */ + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 8a1a33f2f..5de1a8ef4 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -740,7 +740,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } - /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + /* Bit 2: FIFO test mode (PS/55 5550-S,T only. Undocumented) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ if (fdc->flags & FDC_FLAG_PS2_MCA) { diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 1edff2991..ac22af2fe 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1890,7 +1890,11 @@ machine_ps55_model_50t_init(const machine_t* model) * Planar ID * FFFAh - PS/55 model 5551-S0x, T0x (stage 1?) * FFEEh - PS/55 model 5551-S1x, T1x (stage 2?) - * POST (P/N 38F6933) determination: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * Verification in BIOS P/N 38F6933: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * + * The only difference between S and T models is the CPU speed (16 MHz vs 20 MHz). + * The POST measures the speed, and sets a flag in the BIOS Data Area to indicate the sub model. + * The VM in 86Box runs faster than the real, so the POST always determines it as the T model. */ ps2.planar_id = 0xffee; ps55_mca_board_model_50t_init(); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index db378b754..caa20e196 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -512,9 +512,9 @@ svga_in(uint16_t addr, void *priv) /* The IBM PS/55 Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). When the monitor cable is connected to the Display Adapter, the port 3C2h returns the value as 'no cable connection'. - The POST of PS/55 has an extra code that tries detecting the monitor on the planar VGA. - If it fails, then the POST reads the NVRAM set by the reference diskette, and writes the BIOS Data Area (Mem 487h, 489h). - MONCHK.EXE in the reference diskette uses both I/O ports to determine the monitor type, and writes the BDA. + The POST of PS/55 has an extra code. If the monitor is not detected on the planar VGA, + it reads the POS data in NVRAM set by the reference diskette, and writes the BIOS Data Area (Mem 487h, 489h). + MONCHK.EXE in the reference diskette uses both I/O ports to determine the monitor type, updates the NVRAM and BDA. */ if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) ret = 0; From 244f7665580767eec6b7f6b24a8e01eb1987795d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 18 Feb 2025 23:45:16 +0900 Subject: [PATCH 0303/1190] fix unexpected write to null fp in rel build --- src/video/vid_ps55da2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 060e47ce6..ba6835e8c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -369,8 +369,10 @@ typedef struct da2_t { int raster_op; uint8_t payload[DA2_BLT_MEMSIZE]; int32_t reg[DA2_BLT_REGSIZE]; // must be signed int +#ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug int debug_reg_ip; // for debug +#endif int payload_addr; pc_timer_t timer; int64_t timerspeed; @@ -387,10 +389,12 @@ typedef struct da2_t { int x, y; } bitblt; +#ifdef ENABLE_DA2_DEBUGBLT FILE *mmdbg_fp; FILE *mmrdbg_fp; uint32_t mmdbg_vidaddr; uint32_t mmrdbg_vidaddr; +#endif uint8_t pos_regs[8]; svga_t *mb_vga; @@ -2520,12 +2524,12 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - fprintf(da2->mmdbg_fp, "m1-1"); + //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"); + //fprintf(da2->mmdbg_fp, "m1-2"); } break; case 3:/* equiv to vga write mode 3 */ From 61acd4473609faddb2ee5ef84f2082412a4da8ea Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 00:16:18 +0900 Subject: [PATCH 0304/1190] added comment --- src/video/vid_ps55da2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ba6835e8c..ca4ba85b4 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -96,9 +96,9 @@ [Japanese DOS and Display Adapter compatibility] | POS ID | Adapter Name | K3.31 | J4.04 | J4.08 | OS2 J1.3 | Win3 | |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| - | EFFFh | Display Adapter | X | | | ? | | - | FFEDh | ? [Atlas EVT] | X | | | ? | | - | FFFDh | ? [LDT EVT] | X | | | ? | | + | EFFFh | Display Adapter | X | | | | | + | FFEDh | ? [Atlas EVT] | X | | | | | + | FFFDh | ? [LDT EVT] | X | | | | | | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | | E013h | ? [LDT] | X | X | X | X | | | ECCEh | Display Adapter IV | | X | X | X | | @@ -1308,7 +1308,7 @@ da2_in(uint16_t addr, void *p) // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { // da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x01; // wait(bit 3 + bit 0) + 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); From 3c00fece65aff62b03f18b8f953c5006db7dfedb Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 00:37:40 +0900 Subject: [PATCH 0305/1190] change machine name, update comments --- src/machine/m_ps2_mca.c | 2 +- src/machine/machine_table.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index ac22af2fe..400971138 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1919,7 +1919,7 @@ machine_ps55_model_50v_init(const machine_t* model) /* * Planar ID * F1FFh - PS/55 model 5551-V0x, V1x - * POST (P/N 38F6933) determination: FBxx -> 5 slots (ok), F1xx -> 5 slots (ok), others -> 8 (error) + * Verification in BIOS P/N 56F7416,56F7417: FBxx -> 5 slots (ok), F1xx -> 5 slots (ok), others -> 8 (error) */ ps2.planar_id = 0xf1ff; ps55_mca_board_model_50v_init(); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bf540922b..7ec31892a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5680,7 +5680,7 @@ const machine_t machines[] = { }, /* Has IBM PS/55 5551-V0x, V1x firmware. */ { - .name = "[MCA] IBM PS/55 model 5550-V0", + .name = "[MCA] IBM PS/55 model 5550-V", .internal_name = "ibmps55_m50v", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_PROPRIETARY, From 2d115e9b8481069e2f56a258dedce32f2f6192a0 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:02:28 +0900 Subject: [PATCH 0306/1190] added patch for font rom, cleanup * Added magic code for OS/2 J1.3 to disable BitBlt's text drawing function that is not implemented yet. * Added comments * Cleanup --- src/video/vid_ps55da2.c | 46 ++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ca4ba85b4..ad27c978c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -7,6 +7,17 @@ * This file is part of the 86Box distribution. * * IBM PS/55 Display Adapter II (and its successors) emulation. + * + * Notes: There are some known issues that should be corrected. + * - Incorrect foreground text color appears on an active window in OS/2 J1.3. + * - BitBlt's text drawing function does not work correctly. + * - 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. + * - Run SAMPLE program with the BASIC interpreter in DOS K3.3. + * - Run DOS J4.0 install program to test video mode 03. + * - Run Win 3.1 (IBM-J OEM) and OS/2 J1.3 with 16 and 256 color driver to test BilBlt operations. * * Authors: Akamaki. * @@ -662,9 +673,9 @@ da2_bitblt_load(da2_t *da2) value64 |= da2->bitblt.payload[i + 3]; value64 <<= 8; value64 |= da2->bitblt.payload[i + 2]; - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; i += 7; break; case 0x00: @@ -699,9 +710,12 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - for (int i = 0; i <= 0xb; i++) - da2_log("%02x ", da2->gdcreg[i]); - da2_log("\n"); + // for (int i = 0; i <= 0xb; i++) + // { + // da2_log("%02x ", da2->gdcreg[i]); + // da2->gdcreg[i] = da2->bitblt.reg[i] & 0xff; + // } + // da2_log("\n"); da2->bitblt.destaddr = da2->bitblt.reg[0x29]; da2->bitblt.size_x = da2->bitblt.reg[0x33]; @@ -919,7 +933,7 @@ da2_bitblt_exec(void *p) da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; break; - case DA2_BLT_CPUTCHAR: + case DA2_BLT_CPUTCHAR: /* used in OS/2 J1.3 wo ROM patch. TODO: still not work */ // da2->bitblt.y += 2; da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; // pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); @@ -1346,7 +1360,7 @@ da2_in(uint16_t addr, void *p) if (da2->cgastat & 0x01) da2->cgastat &= ~0x30; else - da2->cgastat ^= 0x30; + da2->cgastat ^= 0x30; /* toggle */ temp = da2->cgastat; } else temp = da2->attrc[da2->attraddr]; @@ -1444,9 +1458,10 @@ da2_outw(uint16_t addr, uint16_t val, void *p) da2_out(addr, val, da2); da2->outflipflop = 0; break; - case 0x3EE: + 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->reg3ee[val & 0xff] = val >> 8; + da2->reg3ee[val & 0x0f] = val >> 8; break; } } @@ -2444,17 +2459,16 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) break; } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ - uint8_t wm = da2->writemask; uint8_t bitmask; /* align bitmask to even address */ if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; - // da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT + da2_log("da2_wB %x %02x\n", addr, 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, "\nB %x ", addr); + fprintf(da2->mmdbg_fp, "\nB %x %02x ", addr, val); for (int i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } @@ -2535,13 +2549,11 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = bitmask; bitmask &= val; for (int i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, bitmask, da2); - bitmask = wm; break; } // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2560,7 +2572,6 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; - uint8_t wm = da2->writemask; uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; @@ -2651,13 +2662,11 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work - wm = bitmask; bitmask &= val; for (int i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; da2_gdcropW(addr, bitmask, da2); - bitmask = wm; break; } // da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] @@ -3039,6 +3048,9 @@ da2_init() break; case DA2_DCONFIG_CHARSET_JPAN: da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + /* Add magic code for OS/2 J1.3. This disables BitBlt's text drawing function. */ + da2->mmio.font[0x1AFFE] = 0x80; + da2->mmio.font[0x1AFFF] = 0x01; break; } @@ -3065,7 +3077,7 @@ da2_init() mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + da2->bitblt.timerspeed = 1 * TIMER_USEC; timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From ed555c86d72eb6f3f9bdf7060de5567b779fb63f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:38:00 +0900 Subject: [PATCH 0307/1190] correct function declaration in m_ps2_mca.c --- src/machine/m_ps2_mca.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 400971138..1a2f4d6c6 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1770,8 +1770,8 @@ machine_ps2_model_70_type4_init(const machine_t *model) return ret; } -void -ps55_mca_board_model_50t_init() +static void +ps55_mca_board_model_50t_init(void) { ps2_mca_board_common_init(); @@ -1814,8 +1814,8 @@ ps55_mca_board_model_50t_init() ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); } -void -ps55_mca_board_model_50v_init() +static void +ps55_mca_board_model_50v_init(void) { ps2_mca_board_common_init(); From 6328d5110825d6a9ff437400bcc2c3adfd59fe0c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 10:54:22 +0100 Subject: [PATCH 0308/1190] Gave the PCjr the missing MACHINE_CARTRIDGE flag. --- 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 b9cc8461b..cc3d6aa9f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -324,7 +324,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PCJR, - .flags = MACHINE_VIDEO_FIXED, + .flags = MACHINE_VIDEO_FIXED | MACHINE_CARTRIDGE, .ram = { .min = 64, .max = 640, From 655a0075795cfe0154c5fac5e8cef04e9e234c18 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 11:12:49 +0100 Subject: [PATCH 0309/1190] SLiRP: Introduce a new queue for packets received immediately transmssion - those are now collected into said queue and processed immediately after, improves SLiRP operation. --- src/include/86box/network.h | 12 +++++--- src/network/net_slirp.c | 60 +++++++++++++++++++++++++++---------- src/network/network.c | 37 +++++++++++++++++++++++ 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/include/86box/network.h b/src/include/86box/network.h index 2140d62dd..ef9f291ad 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -57,7 +57,7 @@ /* Queue size must be a power of 2 */ #define NET_QUEUE_LEN 16 #define NET_QUEUE_LEN_MASK (NET_QUEUE_LEN - 1) -#define NET_QUEUE_COUNT 3 +#define NET_QUEUE_COUNT 4 #define NET_CARD_MAX 4 #define NET_HOST_INTF_MAX 64 @@ -84,9 +84,10 @@ enum { }; enum { - NET_QUEUE_RX = 0, - NET_QUEUE_TX_VM = 1, - NET_QUEUE_TX_HOST = 2 + NET_QUEUE_RX = 0, + NET_QUEUE_TX_VM = 1, + NET_QUEUE_TX_HOST = 2, + NET_QUEUE_RX_ON_TX = 3 }; typedef struct netcard_conf_t { @@ -199,7 +200,10 @@ extern const device_t *network_card_getdevice(int); extern int network_tx_pop(netcard_t *card, netpkt_t *out_pkt); extern int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size); extern int network_rx_put(netcard_t *card, uint8_t *bufp, int len); +extern int network_rx_on_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size); +extern int network_rx_on_tx_put(netcard_t *card, uint8_t *bufp, int len); extern int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt); +extern int network_rx_on_tx_put_pkt(netcard_t *card, netpkt_t *pkt); #ifdef EMU_DEVICE_H /* 3Com Etherlink */ diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 11f1a74b2..203428b83 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -60,16 +60,19 @@ enum { }; typedef struct net_slirp_t { - Slirp *slirp; - uint8_t mac_addr[6]; - netcard_t *card; /* netcard attached to us */ - thread_t *poll_tid; - net_evt_t tx_event; - net_evt_t stop_event; - netpkt_t pkt; - netpkt_t pkt_tx_v[SLIRP_PKT_BATCH]; + Slirp * slirp; + uint8_t mac_addr[6]; + netcard_t * card; /* netcard attached to us */ + thread_t * poll_tid; + net_evt_t rx_event; + net_evt_t tx_event; + net_evt_t stop_event; + netpkt_t pkt; + netpkt_t pkt_tx_v[SLIRP_PKT_BATCH]; + int during_tx; + int recv_on_tx; #ifdef _WIN32 - HANDLE sock_event; + HANDLE sock_event; #else uint32_t pfd_len; uint32_t pfd_size; @@ -184,7 +187,11 @@ net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque) memcpy(slirp->pkt.data, (uint8_t *) qp, pkt_len); slirp->pkt.len = pkt_len; - network_rx_put_pkt(slirp->card, &slirp->pkt); + if (slirp->during_tx) { + network_rx_on_tx_put_pkt(slirp->card, &slirp->pkt); + slirp->recv_on_tx = 1; + } else + network_rx_put_pkt(slirp->card, &slirp->pkt); return pkt_len; } @@ -324,6 +331,21 @@ net_slirp_in_available(void *priv) net_event_set(&slirp->tx_event); } +static void +net_slirp_rx_deferred_packets(net_slirp_t *slirp) +{ + int packets = 0; + + if (slirp->recv_on_tx) { + do { + packets = network_rx_on_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); + for (int i = 0; i < packets; i++) + network_rx_put_pkt(slirp->card, &(slirp->pkt_tx_v[i])); + } while (packets > 0); + slirp->recv_on_tx = 0; + } +} + #ifdef _WIN32 static void net_slirp_thread(void *priv) @@ -352,10 +374,13 @@ net_slirp_thread(void *priv) case NET_EVENT_TX: { + slirp->during_tx = 1; int packets = network_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); - for (int i = 0; i < packets; i++) { + for (int i = 0; i < packets; i++) net_slirp_in(slirp, slirp->pkt_tx_v[i].data, slirp->pkt_tx_v[i].len); - } + slirp->during_tx = 0; + + net_slirp_rx_deferred_packets(slirp); } break; @@ -398,10 +423,13 @@ net_slirp_thread(void *priv) if (slirp->pfd[NET_EVENT_TX].revents & POLLIN) { net_event_clear(&slirp->tx_event); + slirp->during_tx = 1; int packets = network_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); - for (int i = 0; i < packets; i++) { + for (int i = 0; i < packets; i++) net_slirp_in(slirp, slirp->pkt_tx_v[i].data, slirp->pkt_tx_v[i].len); - } + slirp->during_tx = 0; + + net_slirp_rx_deferred_packets(slirp); } } @@ -477,6 +505,7 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv slirp->pkt_tx_v[i].data = calloc(1, NET_MAX_FRAME); } slirp->pkt.data = calloc(1, NET_MAX_FRAME); + net_event_init(&slirp->rx_event); net_event_init(&slirp->tx_event); net_event_init(&slirp->stop_event); #ifdef _WIN32 @@ -531,8 +560,9 @@ net_slirp_close(void *priv) slirp_log("SLiRP: waiting for thread to end...\n"); thread_wait(slirp->poll_tid); - net_event_close(&slirp->tx_event); net_event_close(&slirp->stop_event); + net_event_close(&slirp->tx_event); + net_event_close(&slirp->rx_event); slirp_cleanup(slirp->slirp); for (int i = 0; i < SLIRP_PKT_BATCH; i++) { free(slirp->pkt_tx_v[i].data); diff --git a/src/network/network.c b/src/network/network.c index 66990e51d..047642085 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -643,6 +643,43 @@ network_rx_put(netcard_t *card, uint8_t *bufp, int len) return ret; } +int +network_rx_on_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size) +{ + int pkt_count = 0; + + netqueue_t *queue = &card->queues[NET_QUEUE_RX_ON_TX]; + for (int i = 0; i < vec_size; i++) { + if (!network_queue_get_swap(queue, pkt_vec)) + break; + network_dump_packet(pkt_vec); + pkt_count++; + pkt_vec++; + } + + return pkt_count; +} + +int +network_rx_on_tx_put(netcard_t *card, uint8_t *bufp, int len) +{ + int ret = 0; + + ret = network_queue_put(&card->queues[NET_QUEUE_RX_ON_TX], bufp, len); + + return ret; +} + +int +network_rx_on_tx_put_pkt(netcard_t *card, netpkt_t *pkt) +{ + int ret = 0; + + ret = network_queue_put_swap(&card->queues[NET_QUEUE_RX_ON_TX], pkt); + + return ret; +} + int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt) { From c7d9b4c5e78eae31390b4c05045675f2462bdd6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 11:21:50 +0100 Subject: [PATCH 0310/1190] PS/55: Fix some warnings and compile-breaking errors. --- src/device/keyboard.c | 3 +++ src/include/86box/machine.h | 2 +- src/video/vid_ps55da2.c | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index de97592bf..2b851f36c 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -85,6 +85,8 @@ typedef struct { const uint8_t brk[4]; } scconvtbl; +/* Is this a left-over of something planned earlier? */ +#ifdef USE_SCCONV55_82 static scconvtbl scconv55_82[18 + 1] = { // clang-format off @@ -109,6 +111,7 @@ static scconvtbl scconv55_82[18 + 1] = {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ // clang-format on }; +#endif static scconvtbl scconv55_8a[18 + 1] = { diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 690d867db..78f4902eb 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -903,7 +903,7 @@ extern int machine_ps2_model_70_type3_init(const machine_t *); extern int machine_ps2_model_80_init(const machine_t *); extern int machine_ps2_model_80_axx_init(const machine_t *); extern int machine_ps2_model_70_type4_init(const machine_t *); -extern int machine_ps55_model_50t_init(const machine_t*);; +extern int machine_ps55_model_50t_init(const machine_t*); extern int machine_ps55_model_50v_init(const machine_t*); /* m_tandy.c */ diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ad27c978c..aaf5d4803 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1256,8 +1256,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) uint16_t da2_in(uint16_t addr, void *p) { - da2_t *da2 = (da2_t *) p; - uint16_t temp; + da2_t *da2 = (da2_t *) p; + uint16_t temp = 0xff; switch (addr) { case 0x3c3: @@ -3020,7 +3020,7 @@ da2_reset(void *priv) } static void * -da2_init() +da2_init(UNUSED(const device_t *info)) { if (svga_get_pri() == NULL) return NULL; @@ -3083,7 +3083,7 @@ da2_init() return da2; } static int -da2_available() +da2_available(void) { return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } From 83d840381a08339a4f275b38a918841633558325 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 11:58:13 +0100 Subject: [PATCH 0311/1190] Fixed more warnings and compile-breaking mistakes. --- src/machine/m_ps2_mca.c | 8 ++++---- src/sound/resid-fp/SID.cpp | 2 ++ src/sound/resid-fp/WaveformGenerator.cpp | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 1a2f4d6c6..d3f881b24 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -375,7 +375,7 @@ ps55_model_50t_read(uint16_t port) return ps2.planar_id >> 8; case 0x102: return ps2.option[0]; - case 0x103: + case 0x103: { uint8_t val = 0xff; /* I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) @@ -413,7 +413,7 @@ ps55_model_50t_read(uint16_t port) } ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); return val; - case 0x104: + } case 0x104: return ps2.option[2]; case 0x105: return ps2.option[3]; @@ -435,7 +435,7 @@ ps55_model_50v_read(uint16_t port) return ps2.planar_id >> 8; case 0x102: return ps2.option[0]; - case 0x103: + case 0x103: { uint8_t val = 0xff; /* I/O 103h - Bit 7-4: Reserved @@ -460,7 +460,7 @@ ps55_model_50v_read(uint16_t port) break; } return val; - case 0x104: + } case 0x104: /* Reading cache ID (bit 3-2) always returns zero */ return ps2.option[2] & 0xf3; case 0x105: diff --git a/src/sound/resid-fp/SID.cpp b/src/sound/resid-fp/SID.cpp index 5b5506bc3..4db69af0c 100644 --- a/src/sound/resid-fp/SID.cpp +++ b/src/sound/resid-fp/SID.cpp @@ -107,8 +107,10 @@ constexpr unsigned int OSC_DAC_BITS = 12; * On my 6581R4AR has 0x3A as the only value giving the same output level as 1.prg */ //@{ +#ifdef USE_RESID_UNUSED constexpr unsigned int OFFSET_6581 = 0x380; constexpr unsigned int OFFSET_8580 = 0x9c0; +#endif //@} /** diff --git a/src/sound/resid-fp/WaveformGenerator.cpp b/src/sound/resid-fp/WaveformGenerator.cpp index be0738bba..847560f2a 100644 --- a/src/sound/resid-fp/WaveformGenerator.cpp +++ b/src/sound/resid-fp/WaveformGenerator.cpp @@ -43,7 +43,9 @@ namespace reSIDfp constexpr unsigned int FLOATING_OUTPUT_TTL_6581R3 = 54000; constexpr unsigned int FLOATING_OUTPUT_FADE_6581R3 = 1400; // ~1s +#ifdef USE_RESID_UNUSED constexpr unsigned int FLOATING_OUTPUT_TTL_6581R4 = 1000000; +#endif // ~1s constexpr unsigned int FLOATING_OUTPUT_TTL_8580R5 = 800000; constexpr unsigned int FLOATING_OUTPUT_FADE_8580R5 = 50000; @@ -61,7 +63,9 @@ constexpr unsigned int FLOATING_OUTPUT_FADE_8580R5 = 50000; constexpr unsigned int SHIFT_REGISTER_RESET_6581R3 = 50000; constexpr unsigned int SHIFT_REGISTER_FADE_6581R3 = 15000; // ~2.15s +#ifdef USE_RESID_UNUSED constexpr unsigned int SHIFT_REGISTER_RESET_6581R4 = 2150000; +#endif // ~2.8s constexpr unsigned int SHIFT_REGISTER_RESET_8580R5 = 986000; constexpr unsigned int SHIFT_REGISTER_FADE_8580R5 = 314300; From c262760155c617cf9130ed616303af760f838d37 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 12:56:22 +0100 Subject: [PATCH 0312/1190] PS/1: Move NVR initialization to the end of ps1_setup(), fixes segmentation fault due to the BIOS language being obtained from the wrong device. --- src/machine/m_ps1.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 130481394..41821a4a8 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -320,30 +320,28 @@ ps1_setup(int model) mem_remap_top(384); - device_add(&ps_nvr_device); - device_add(&fdc_ps2_device); if (model == 2011) { - if (!strcmp("english_us", device_get_config_bios("bios_language"))) { - /* US English */ - rom_init(&ps->high_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), - 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + const device_t *d = device_context_get_device(); + const char * bios = device_get_config_bios("bios_language"); + const char * first = device_get_bios_file(d, bios, 0); + const char * second = device_get_bios_file(d, bios, 1); - } else if ((device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1)) == NULL) { + if (!strcmp(bios, "english_us")) { + /* US English */ + rom_init(&ps->high_rom, first, + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + } else if (second == NULL) { /* Combined ROM. */ - rom_init(&ps->high_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + rom_init(&ps->high_rom, first, 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); } else { /* Split ROM. */ - rom_init(&ps->mid_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + rom_init(&ps->mid_rom, first, 0xf80000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); - rom_init(&ps->high_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1), + rom_init(&ps->high_rom, second, 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); } @@ -381,6 +379,8 @@ ps1_setup(int model) device_add(&ps1snd_device); } + + device_add(&ps_nvr_device); } static void From baae4c15d65404d7c70ff45ffdf19b8b0fdda2a4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 12:58:40 +0100 Subject: [PATCH 0313/1190] Fixed a compile-breaking error in vid_p55da2.c as well. --- src/video/vid_ps55da2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index aaf5d4803..288aca027 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -872,7 +872,7 @@ da2_bitblt_exec(void *p) } da2->bitblt.destaddr += 2; break; - case DA2_BLT_CFILLTILE: + case DA2_BLT_CFILLTILE: { int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; if (da2->bitblt.x >= da2->bitblt.size_x - 1) { DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); @@ -891,7 +891,7 @@ da2_bitblt_exec(void *p) } da2->bitblt.destaddr += 2; break; - case DA2_BLT_CCOPYF: + } case DA2_BLT_CCOPYF: if (da2->bitblt.x >= da2->bitblt.size_x - 1) { DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); if (da2->bitblt.y >= da2->bitblt.size_y - 1) { From 71c9e694569fa09120f90ae069e5b3d538e94ffc Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 20 Feb 2025 15:35:56 +0100 Subject: [PATCH 0314/1190] Mach32 changes of the day (February 20th, 2025) 1. Actually fix the LFB access by subtracting the linear base address from the current address when LFB/MMIO is on. This fixes blankness of certain Mach32 drivers on Win3.1x. 2. Apply a minor but important fix to the fonts used by said Win3.1x driver when the dpconfig activates bit 2 without bit 12 set (e.g.: 0x2255), ergo, issuing host data as monochrome without swapping it. --- src/video/vid_ati_mach8.c | 70 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 06a60449f..71dd973da 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -336,7 +336,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) - mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", + mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monopattern = %x.\n", 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); @@ -1039,7 +1039,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 2: - if (mach->accel.dp_config & 0x1000) { + if ((mach->accel.dp_config & 0x1000) || (mach->accel.dp_config & 0x04)) { mix = mix_dat >> 0x1f; mix_dat <<= 1; } else { @@ -2185,7 +2185,7 @@ mach_accel_out_pixtrans(svga_t *svga, mach_t *mach, ibm8514_t *dev, uint16_t val case 0x200: /*16-bit size*/ if (mono_src == 2) { if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if ((mach->accel.dp_config & 0x1000) && !swap) { + if (((mach->accel.dp_config & 0x1000) && !swap) || swap) { mach_log("16-bit bus size swap.\n"); val = (val >> 8) | (val << 8); } @@ -5184,11 +5184,11 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { mach_log("Port WORDB Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outb(0x02ee + (addr & 1) + (port_dword << 8), val, mach); } else { @@ -5199,9 +5199,9 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) 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); + mach32_write_common(addr - mach->linear_base, val, 1, mach, svga); else - svga_write_linear(addr, val, svga); + svga_write_linear(addr - mach->linear_base, val, svga); } } @@ -5211,11 +5211,11 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outw(0x02ee + (port_dword << 8), val, mach); } else { @@ -5224,11 +5224,11 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) } } else { mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x.\n", - addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_writew_linear(addr, val, mach); + mach32_writew_linear(addr - mach->linear_base, val, mach); else - svga_writew_linear(addr, val, svga); + svga_writew_linear(addr - mach->linear_base, val, svga); } } @@ -5238,11 +5238,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 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); @@ -5253,11 +5253,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) } } else { mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x.\n", - addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_writel_linear(addr, val, mach); + mach32_writel_linear(addr - mach->linear_base, val, mach); else - svga_writel_linear(addr, val, svga); + svga_writel_linear(addr - mach->linear_base, val, svga); } } @@ -5268,19 +5268,19 @@ mach32_ap_readb(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); else temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_read_common(addr, 1, mach, svga); + temp = mach32_read_common(addr - mach->linear_base, 1, mach, svga); else - temp = svga_read_linear(addr, svga); + temp = svga_read_linear(addr - mach->linear_base, svga); mach_log("Linear WORDB Read=%08x, ret=%02x, fast=%d.\n", addr, temp, svga->fast); } @@ -5295,19 +5295,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 & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); else temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_readw_linear(addr, mach); + temp = mach32_readw_linear(addr - mach->linear_base, mach); else - temp = svga_readw_linear(addr, svga); + temp = svga_readw_linear(addr - mach->linear_base, svga); mach_log("Linear WORDW Read=%08x, ret=%04x.\n", addr, temp); } @@ -5322,11 +5322,11 @@ mach32_ap_readl(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); } else { @@ -5335,9 +5335,9 @@ mach32_ap_readl(uint32_t addr, void *priv) } } else { if (dev->on) - temp = mach32_readl_linear(addr, mach); + temp = mach32_readl_linear(addr - mach->linear_base, mach); else - temp = svga_readl_linear(addr, svga); + temp = svga_readl_linear(addr - mach->linear_base, svga); mach_log("Linear WORDL Read=%08x, ret=%08x, ON%d.\n", addr, temp, dev->on); } From 6c933dd15719b3ba96f6f03f9a657a39ca6d8059 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Thu, 20 Feb 2025 18:24:38 -0300 Subject: [PATCH 0315/1190] Voodoo: Implement missing AGP CMDFIFO features Note that the reproduction cases for command 6 currently appear to be a result of CMDFIFO corruption instead of actual usage. --- src/include/86box/vid_voodoo_banshee.h | 1 + src/include/86box/vid_voodoo_common.h | 2 + src/video/vid_voodoo_banshee.c | 77 +++++++++++++++++++++++++- src/video/vid_voodoo_fifo.c | 77 ++++++++++++++++++++++++-- 4 files changed, 148 insertions(+), 9 deletions(-) diff --git a/src/include/86box/vid_voodoo_banshee.h b/src/include/86box/vid_voodoo_banshee.h index 89298e94e..257a549dd 100644 --- a/src/include/86box/vid_voodoo_banshee.h +++ b/src/include/86box/vid_voodoo_banshee.h @@ -18,6 +18,7 @@ #ifndef VIDEO_VOODOO_BANSHEE_H #define VIDEO_VOODOO_BANSHEE_H +void banshee_cmd_write(void *priv, uint32_t addr, uint32_t val); void banshee_set_overlay_addr(void *priv, uint32_t addr); #endif /*VIDEO_VOODOO_BANSHEE_H*/ diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 5ab63ec3a..4201562c2 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -420,6 +420,7 @@ typedef struct voodoo_t { int cmdfifo_rp; int cmdfifo_ret_addr; int cmdfifo_in_sub; + int cmdfifo_in_agp; atomic_int cmdfifo_depth_rd; atomic_int cmdfifo_depth_wr; atomic_int cmdfifo_enabled; @@ -433,6 +434,7 @@ typedef struct voodoo_t { int cmdfifo_rp_2; int cmdfifo_ret_addr_2; int cmdfifo_in_sub_2; + int cmdfifo_in_agp_2; atomic_int cmdfifo_depth_rd_2; atomic_int cmdfifo_depth_wr_2; atomic_int cmdfifo_enabled_2; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index fadd782a5..3727ccf8e 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -30,6 +30,7 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include <86box/dma.h> #include <86box/pci.h> #include <86box/rom.h> #include <86box/timer.h> @@ -43,9 +44,11 @@ #include <86box/vid_svga_render.h> #include <86box/vid_voodoo_common.h> #include <86box/vid_voodoo_display.h> +#include <86box/vid_voodoo_fb.h> #include <86box/vid_voodoo_fifo.h> #include <86box/vid_voodoo_regs.h> #include <86box/vid_voodoo_render.h> +#include <86box/vid_voodoo_texture.h> #define ROM_BANSHEE "roms/video/voodoo/Pci_sg.rom" #define ROM_CREATIVE_BANSHEE "roms/video/voodoo/BlasterPCI.rom" @@ -220,6 +223,7 @@ enum { Agp_agpHostAddressHigh = 0x08, Agp_agpGraphicsAddress = 0x0C, Agp_agpGraphicsStride = 0x10, + Agp_agpMoveCMD = 0x14, }; #define VGAINIT0_RAMDAC_8BIT (1 << 2) @@ -1365,6 +1369,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) case cmdBaseSize0: ret = voodoo->cmdfifo_size; + if (voodoo->cmdfifo_enabled) + ret |= 0x100; + if (voodoo->cmdfifo_in_agp) + ret |= 0x200; break; case cmdBaseAddr1: @@ -1394,6 +1402,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) case cmdBaseSize1: ret = voodoo->cmdfifo_size_2; + if (voodoo->cmdfifo_enabled_2) + ret |= 0x100; + if (voodoo->cmdfifo_in_agp_2) + ret |= 0x200; break; case 0x108: @@ -1613,10 +1625,11 @@ banshee_reg_writew(uint32_t addr, uint16_t val, void *priv) } } -static void -banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) +void +banshee_cmd_write(void *priv, uint32_t addr, uint32_t val) { - voodoo_t *voodoo = banshee->voodoo; + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; #if 0 banshee_log("banshee_cmd_write: addr=%03x val=%08x\n", addr & 0x1fc, val); #endif @@ -1641,6 +1654,62 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) banshee->agpReqSize = val; break; + case Agp_agpMoveCMD: { + uint32_t src_addr = banshee->agpHostAddressLow; + uint32_t src_width = banshee->agpHostAddressHigh & 0x3fff; + uint32_t src_stride = (banshee->agpHostAddressHigh >> 14) & 0x3fff; + uint32_t src_end = src_addr + (banshee->agpReqSize & 0xfffff); /* don't know whether or not stride is accounted for! */ + uint32_t dest_addr = banshee->agpGraphicsAddress & 0x3ffffff; + uint32_t dest_stride = banshee->agpGraphicsStride & 0x7fff; +#if 0 + banshee_log("AGP: %d bytes W%d from %08x S%d to %d:%08x S%d\n", src_end - src_addr, src_width, src_addr, src_stride, (val >> 3) & 3, dest_addr, dest_stride); +#endif + switch ((val >> 3) & 3) { + case 0: /*Linear framebuffer (Banshee)*/ + case 1: /*Planar YUV*/ + if (voodoo->texture_present[0][(dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + banshee_log("texture_present at %08x %i\n", dest_addr, (dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, dest_addr & voodoo->texture_mask, 0); + } + if (voodoo->texture_present[1][(dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + banshee_log("texture_present at %08x %i\n", dest_addr, (dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, dest_addr & voodoo->texture_mask, 1); + } + while ((src_addr < src_end) && (dest_addr <= voodoo->fb_mask)) { + dma_bm_read(src_addr, &voodoo->fb_mem[dest_addr], MIN(src_width, voodoo->fb_mask - dest_addr), 4); + src_addr += src_stride; + dest_addr += dest_stride; + } + break; + case 2: /*Framebuffer*/ + src_width &= ~3; + while (src_addr < src_end) { + for (uint32_t i = 0; i < src_width; i += 4) + voodoo_fb_writel(dest_addr + i, mem_readl_phys(src_addr + i), voodoo); + src_addr += src_stride; + dest_addr += dest_stride; + } + break; + case 3: /*Texture*/ + src_width &= ~3; + while (src_addr < src_end) { + for (uint32_t i = 0; i < src_width; i += 4) + voodoo_tex_writel(dest_addr + i, mem_readl_phys(src_addr + i), voodoo); + src_addr += src_stride; + dest_addr += dest_stride; + } + break; + + default: + break; + } + break; + } + case cmdBaseAddr0: voodoo->cmdfifo_base = (val & 0xfff) << 12; voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); @@ -1655,6 +1724,7 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) voodoo->cmdfifo_enabled = val & 0x100; if (!voodoo->cmdfifo_enabled) voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/ + voodoo->cmdfifo_in_agp = val & 0x200; #if 0 banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); #endif @@ -1694,6 +1764,7 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) voodoo->cmdfifo_enabled_2 = val & 0x100; if (!voodoo->cmdfifo_enabled_2) voodoo->cmdfifo_in_sub_2 = 0; /*Not sure exactly when this should be reset*/ + voodoo->cmdfifo_in_agp_2 = val & 0x200; #if 0 banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); #endif diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index 54a0140f6..83be0f7bb 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -35,6 +35,7 @@ #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> +#include <86box/vid_voodoo_banshee.h> #include <86box/vid_voodoo_banshee_blitter.h> #include <86box/vid_voodoo_fb.h> #include <86box/vid_voodoo_fifo.h> @@ -166,7 +167,10 @@ cmdfifo_get(voodoo_t *voodoo) } } - val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; + if (voodoo->cmdfifo_in_agp) + val = mem_readl_phys(voodoo->cmdfifo_rp); + else + val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; if (!voodoo->cmdfifo_in_sub) voodoo->cmdfifo_depth_rd++; @@ -200,7 +204,10 @@ cmdfifo_get_2(voodoo_t *voodoo) } } - val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask]; + if (voodoo->cmdfifo_in_agp_2) + val = mem_readl_phys(voodoo->cmdfifo_rp_2); + else + val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask]; if (!voodoo->cmdfifo_in_sub_2) voodoo->cmdfifo_depth_rd_2++; @@ -362,9 +369,21 @@ voodoo_fifo_thread(void *param) break; case 3: /*JMP local frame buffer*/ - voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_agp = 0; #if 0 - voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); + voodoo_fifo_log("JMP LFB to %08x %04x\n", voodoo->cmdfifo_rp, header); +#endif + break; + + case 4: /*JMP AGP*/ + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) + fatal("CMDFIFO0: Not Banshee %08x\n", header); + + voodoo->cmdfifo_rp = ((header >> 4) & 0x1fffffc) | (cmdfifo_get(voodoo) << 25); + voodoo->cmdfifo_in_agp = 1; +#if 0 + voodoo_fifo_log("JMP AGP to %08x %04x\n", voodoo->cmdfifo_rp, header); #endif break; @@ -573,6 +592,23 @@ voodoo_fifo_thread(void *param) } break; + case 6: + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) { + fatal("CMDFIFO6: Not Banshee %08x %08x\n", header, voodoo->cmdfifo_rp); + } else { + uint32_t val = cmdfifo_get(voodoo); + banshee_cmd_write(voodoo->priv, 0x00, val >> 5); /* agpReqSize */ + banshee_cmd_write(voodoo->priv, 0x04, cmdfifo_get(voodoo)); /* agpHostAddressLow */ + banshee_cmd_write(voodoo->priv, 0x08, cmdfifo_get(voodoo)); /* agpHostAddressHigh */ + banshee_cmd_write(voodoo->priv, 0x0c, cmdfifo_get(voodoo)); /* agpGraphicsAddress */ + banshee_cmd_write(voodoo->priv, 0x10, cmdfifo_get(voodoo)); /* agpGraphicsStride */ + banshee_cmd_write(voodoo->priv, 0x14, (val & 0x18) | 0x00); /* agpMoveCMD - start transfer */ +#if 0 + voodoo_fifo_log("CMDFIFO6 addr=%08x num=%i\n", addr, banshee->agpReqSize); +#endif + } + break; + default: fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); } @@ -624,9 +660,21 @@ voodoo_fifo_thread(void *param) break; case 3: /*JMP local frame buffer*/ - voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_agp_2 = 0; #if 0 - voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); + voodoo_fifo_log("JMP LFB to %08x %04x\n", voodoo->cmdfifo_rp_2, header); +#endif + break; + + case 4: /*JMP AGP*/ + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) + fatal("CMDFIFO0: Not Banshee %08x\n", header); + + voodoo->cmdfifo_rp_2 = ((header >> 4) & 0x1fffffc) | (cmdfifo_get_2(voodoo) << 25); + voodoo->cmdfifo_in_agp_2 = 1; +#if 0 + voodoo_fifo_log("JMP AGP to %08x %04x\n", voodoo->cmdfifo_rp_2, header); #endif break; @@ -835,6 +883,23 @@ voodoo_fifo_thread(void *param) } break; + case 6: + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) { + fatal("CMDFIFO6: Not Banshee %08x %08x\n", header, voodoo->cmdfifo_rp); + } else { + uint32_t val = cmdfifo_get_2(voodoo); + banshee_cmd_write(voodoo->priv, 0x00, val >> 5); /* agpReqSize */ + banshee_cmd_write(voodoo->priv, 0x04, cmdfifo_get_2(voodoo)); /* agpHostAddressLow */ + banshee_cmd_write(voodoo->priv, 0x08, cmdfifo_get_2(voodoo)); /* agpHostAddressHigh */ + banshee_cmd_write(voodoo->priv, 0x0c, cmdfifo_get_2(voodoo)); /* agpGraphicsAddress */ + banshee_cmd_write(voodoo->priv, 0x10, cmdfifo_get_2(voodoo)); /* agpGraphicsStride */ + banshee_cmd_write(voodoo->priv, 0x14, (val & 0x18) | 0x20); /* agpMoveCMD - start transfer */ +#if 0 + voodoo_fifo_log("CMDFIFO6 addr=%08x num=%i\n", addr, banshee->agpReqSize); +#endif + } + break; + default: fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); } From 67c02a53619d2bf1cfd4fa014925264fce675655 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 21 Feb 2025 00:32:15 +0100 Subject: [PATCH 0316/1190] Spock/Tribble (IBM PS/2 SCSI) changes of the late night (February 21st, 2025) 1. Made logs more consistent. 2. Actually add Write and Verify command, used by IBM OS/2 1.2 Extended, and fixes a hang by said OS after inserting disk 6. --- src/scsi/scsi_spock.c | 46 ++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index d6a26b7d0..567879a12 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -196,6 +196,7 @@ typedef struct { #define CMD_UNKNOWN_1C11 0x1c11 #define CMD_WRITE_DATA 0x1c02 #define CMD_VERIFY 0x1c03 +#define CMD_WRITE_VERIFY 0x1c04 #define IRQ_TYPE_NONE 0x0 #define IRQ_TYPE_SCB_COMPLETE 0x1 @@ -291,7 +292,7 @@ spock_write(uint16_t port, uint8_t val, void *priv) { spock_t *scsi = (spock_t *) priv; - spock_log("spock_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); + spock_log("spock_writeb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); switch (port & 7) { case 0: @@ -332,6 +333,8 @@ spock_writew(uint16_t port, uint16_t val, void *priv) { spock_t *scsi = (spock_t *) priv; + spock_log("spock_writew: port=%04x, val=%04x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); + switch (port & 7) { case 0: /*Command Interface Register*/ scsi->cir_pending[0] = val & 0xff; @@ -347,8 +350,6 @@ spock_writew(uint16_t port, uint16_t val, void *priv) default: break; } - - spock_log("spock_writew: port=%04x val=%04x\n", port, val); } static uint8_t @@ -390,7 +391,7 @@ spock_read(uint16_t port, void *priv) break; } - spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x.\n", port, temp, CS, cs, cpu_state.pc); + spock_log("spock_readb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, temp, CS, cpu_state.pc); return temp; } @@ -412,7 +413,7 @@ spock_readw(uint16_t port, void *priv) break; } - spock_log("spock_readw: port=%04x val=%04x\n", port, temp); + spock_log("spock_readw: port=%04x, val=%04x, %04x:%04x.\n", port & 7, temp, CS, cpu_state.pc); return temp; } @@ -534,7 +535,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) int old_scb_state; if (scsi->in_reset) { - spock_log("Reset type = %d\n", scsi->in_reset); + spock_log("Reset type=%d\n", scsi->in_reset); scsi->status &= ~STATUS_BUSY; scsi->irq_status = 0; @@ -542,9 +543,8 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) for (c = 0; c < SCSI_ID_MAX; c++) spock_clear_irq(scsi, c); - if (scsi->in_reset == 1) { + if (scsi->in_reset == 1) scsi->basic_ctrl |= CTRL_IRQ_ENA; - } spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); @@ -585,6 +585,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) switch (scsi->scb_state) { case 0: /* Idle */ + spock_log("Start Idle.\n"); break; case 1: /* Select */ @@ -820,6 +821,28 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) scsi->scb_state = 2; return; + case CMD_WRITE_VERIFY: + if (scsi->present[scsi->scb_id] != 0xff) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + + spock_log("Device Write with Verify\n"); + scsi->cdb[0] = GPCMD_WRITE_AND_VERIFY_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + case CMD_REQUEST_SENSE: if (scsi->present[scsi->scb_id] != 0xff) scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; @@ -943,7 +966,7 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) sd->buffer_length = spock_get_len(scsi, scb); scsi_device_command_phase0(sd, scsi->temp_cdb); - spock_log("SCSI ID %i: Current CDB[0] = %02x, LUN = %i, data len = %i, max len = %i, phase val = %02x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase); + spock_log("SCSI ID %i: Current CDB[0]=%02x, LUN=%i, buffer len=%i, max len=%i, phase val=%02x, data len=%d, enable bit 10=%03x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase, scsi->data_len, scb->enable & 0x400); if ((sd->phase != SCSI_PHASE_STATUS) && (sd->buffer_length > 0)) { p = scsi_device_get_callback(sd); @@ -1018,12 +1041,11 @@ spock_callback(void *priv) if (scsi->cmd_timer) { scsi->cmd_timer--; - if (!scsi->cmd_timer) { + if (!scsi->cmd_timer) spock_execute_cmd(scsi, scb); - } } - if (scsi->attention_wait && (scsi->scb_state == 0 || (scsi->attention_pending & 0xf0) == 0xe0)) { + if (scsi->attention_wait && ((scsi->scb_state == 0) || (scsi->attention_pending & 0xf0) == 0xe0)) { scsi->attention_wait--; if (!scsi->attention_wait) { scsi->attention = scsi->attention_pending; From 136183b998d127e4219d52e6e1f5bf81a5240adf Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Feb 2025 01:43:22 +0100 Subject: [PATCH 0317/1190] MO and ZIP: Set phase data out on WRITE SAME command. --- src/disk/mo.c | 1 + src/disk/zip.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/disk/mo.c b/src/disk/mo.c index 5494fc9a8..7808e524e 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1461,6 +1461,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) break; case GPCMD_WRITE_SAME_10: + mo_set_phase(dev, SCSI_PHASE_DATA_OUT); alloc_length = 512; if ((cdb[1] & 6) == 6) diff --git a/src/disk/zip.c b/src/disk/zip.c index 72781281a..f579f23ec 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1506,6 +1506,7 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb) break; case GPCMD_WRITE_SAME_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); alloc_length = 512; if ((cdb[1] & 6) == 6) From 9801e8b1493754d9b22f5fa1c40c14151799bdc9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Feb 2025 19:37:53 +0100 Subject: [PATCH 0318/1190] IBM PS/55 Display Adapter II: Use calloc instead of malloc, fixes incorrect operation when heap protection is enabled. --- src/video/vid_ps55da2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 288aca027..f81a62ffe 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -3027,17 +3027,17 @@ da2_init(UNUSED(const device_t *info)) svga_t *mb_vga = svga_get_pri(); mb_vga->cable_connected = 0; - da2_t *da2 = malloc(sizeof(da2_t)); + da2_t *da2 = calloc(1, sizeof(da2_t)); da2->mb_vga = mb_vga; da2->dispontime = 1000ull << 32; da2->dispofftime = 1000ull << 32; int memsize = 1024 * 1024; - da2->vram = malloc(memsize); + da2->vram = calloc(1, memsize); da2->vram_mask = memsize - 1; - da2->cram = malloc(0x1000); + da2->cram = calloc(1, 0x1000); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ + da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ da2->mmio.charset = device_get_config_int("charset"); From ce906664a51a1311f445536d8d0aa7270af410c1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Feb 2025 22:25:00 +0100 Subject: [PATCH 0319/1190] Device: increased the length of the temporary pbus string, should fix heap corruptions. --- src/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device.c b/src/device.c index 8b2ddf35e..434bd3776 100644 --- a/src/device.c +++ b/src/device.c @@ -490,7 +490,7 @@ device_get_name(const device_t *dev, int bus, char *name) const char *sbus = NULL; const char *fbus; char *tname; - char pbus[12] = { 0 }; + char pbus[16] = { 0 }; if (dev == NULL) return; From 9047bd48784191920d8fccdb53ac1040ea0461b4 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 12 Feb 2025 05:44:59 -0500 Subject: [PATCH 0320/1190] Corrections to PCjr --- src/include/86box/machine.h | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 78f4902eb..52af90581 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -48,7 +48,7 @@ #define MACHINE_BUS_AGP 0x00080000 /* sys has AGP bus */ #define MACHINE_BUS_AC97 0x00100000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ /* Aliases. */ -#define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ +#define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ /* Combined flags. */ #define MACHINE_PC (MACHINE_BUS_ISA) /* sys is PC/XT-compatible (ISA) */ #define MACHINE_AT (MACHINE_BUS_ISA | MACHINE_BUS_ISA16) /* sys is AT-compatible (ISA + ISA16) */ @@ -67,18 +67,19 @@ #define MACHINE_AGP (MACHINE_BUS_AGP | MACHINE_PCI) /* sys is AT-compatible with AGP */ #define MACHINE_AGP98 (MACHINE_BUS_AGP | MACHINE_PCI98) /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ -#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ -#define MACHINE_PCJR (MACHINE_PC | MACHINE_CASSETTE | MACHINE_BUS_SIDECAR) /* sys is PCjr */ -#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ -#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ -#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ -#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ -#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ -#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ -#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ -#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ -#define MACHINE_PS2_PCIONLY (MACHINE_PS2_NOISA & ~MACHINE_BUS_AGP) /* sys is PCI PS/2 without ISA */ -#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ +#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ +#define MACHINE_PCJR (MACHINE_CASSETTE | MACHINE_BUS_SIDECAR) /* sys is PCjr */ +#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ +#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ +#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ +#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ +#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ +#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ +#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ +#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ +#define MACHINE_PS2_PCIONLY (MACHINE_PS2_NOISA & ~MACHINE_BUS_AGP) /* sys is PCI PS/2 without ISA */ +#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ + /* Feature flags for miscellaneous internal devices. */ #define MACHINE_FLAGS_NONE 0x00000000 /* sys has no int devices */ #define MACHINE_SOFTFLOAT_ONLY 0x00000001 /* sys requires SoftFloat FPU */ From 62444f3da0189caeb065e9b77013011c63eec0d8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 12 Feb 2025 06:01:18 -0500 Subject: [PATCH 0321/1190] Devices supported on PCjr PC Enterprises GameMaster, Resound jr (adlib) MS Booster/PC Enterprises jrBus-Mouse, PC Enterprises GameMaster (bus mouse) Various (generic) RTC Corel LS2000 SCSI --- src/device/isartc.c | 2 +- src/device/mouse_bus.c | 4 ++-- src/scsi/scsi_ncr53c400.c | 2 +- src/sound/snd_adlib.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/device/isartc.c b/src/device/isartc.c index 63ce0b065..5d6b4aea4 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -862,7 +862,7 @@ static const device_config_t mm58167_config[] = { static const device_t mm58167_device = { .name = "Generic MM58167 RTC", .internal_name = "rtc_mm58167", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_SIDECAR, .local = ISARTC_MM58167, .init = isartc_init, .close = isartc_close, diff --git a/src/device/mouse_bus.c b/src/device/mouse_bus.c index 7074a71ac..c81bc6aba 100644 --- a/src/device/mouse_bus.c +++ b/src/device/mouse_bus.c @@ -815,7 +815,7 @@ static const device_config_t ms_config[] = { const device_t mouse_logibus_device = { .name = "Logitech/Microsoft Bus Mouse", .internal_name = "logibus", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_SIDECAR, .local = MOUSE_TYPE_LOGIBUS, .init = bm_init, .close = bm_close, @@ -843,7 +843,7 @@ const device_t mouse_logibus_onboard_device = { const device_t mouse_msinport_device = { .name = "Microsoft Bus Mouse (InPort)", .internal_name = "msbus", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_SIDECAR, .local = MOUSE_TYPE_INPORT, .init = bm_init, .close = bm_close, diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 10934880f..c83e75442 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -1024,7 +1024,7 @@ const device_t scsi_t130b_device = { const device_t scsi_ls2000_device = { .name = "Corel LS2000", .internal_name = "ls2000", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_SIDECAR, .local = ROM_LS2000, .init = ncr53c400_init, .close = ncr53c400_close, diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index 1f307596c..17990e842 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -145,7 +145,7 @@ adlib_close(void *priv) const device_t adlib_device = { .name = "AdLib", .internal_name = "adlib", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_SIDECAR, .local = 0, .init = adlib_init, .close = adlib_close, From e821aa1b0a8eed7ebe24959b3fb7d472f350e673 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 21 Feb 2025 22:52:27 +0100 Subject: [PATCH 0322/1190] Add Packard Bell PB286 (part 1) --- src/include/86box/machine.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 78f4902eb..6d48dbff6 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -438,6 +438,8 @@ extern int machine_at_ibmatquadtel_init(const machine_t *); // IBM AT with Quadt extern int machine_at_ibmxt286_init(const machine_t *); +extern int machine_at_pb286_init(const machine_t *); + extern int machine_at_siemens_init(const machine_t *); // Siemens PCD-2L. N82330 discrete machine. It segfaults in some places extern int machine_at_wellamerastar_init(const machine_t *); // Wells American A*Star with custom award BIOS From e4600291ed0135735021de2984fa73c205d6ff8f Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 21 Feb 2025 22:56:09 +0100 Subject: [PATCH 0323/1190] Add Packard Bell PB286 (part 2) --- src/machine/m_at.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 3f5e88011..15b828676 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -332,6 +332,22 @@ machine_at_ibmxt286_init(const machine_t *model) return ret; } +machine_at_pb286_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/pb286/LB_V332P.BIN", + "roms/machines/pb286/HB_V332P.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ibm_common_init(model); + + return ret; +} + int machine_at_siemens_init(const machine_t *model) { From e0fda208dfa4d1d788a6b0a82e5211b1916d9661 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 21 Feb 2025 23:03:16 +0100 Subject: [PATCH 0324/1190] Add Packard Bell PB286 (part 3) --- src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3706126a3..eb0584802 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3259,6 +3259,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has IBM AT KBC firmware. */ + /* To configure the BIOS, use PB_2330a_diag.IMA from MS-DOS 3.30 Packard Bell OEM, GSETUP might work too*/ + { + .name = "[ISA] Packard Bell PB286", + .internal_name = "pb286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_pb286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 1024, + .step = 256 + }, + .nvrmask = 63, + .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 + }, /* This has a Siemens proprietary KBC which is completely undocumented. */ { .name = "[ISA] Siemens PCD-2L", From e012777244f903fc3ffe9d2dc44229eb12bb6f46 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 21 Feb 2025 23:19:57 +0100 Subject: [PATCH 0325/1190] Fix compile-breaking mistake (forgot "int") --- src/machine/m_at.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 15b828676..162006803 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -332,6 +332,7 @@ machine_at_ibmxt286_init(const machine_t *model) return ret; } +int machine_at_pb286_init(const machine_t *model) { int ret; From 48da4f3811898058762be3fb5ab374c8e46918db Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sat, 22 Feb 2025 00:27:23 +0100 Subject: [PATCH 0326/1190] adjust the RAM step, Packard Bell 286s are known to support 640 KB RAM configurations --- 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 eb0584802..abfdf9d16 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3286,7 +3286,7 @@ const machine_t machines[] = { .ram = { .min = 256, .max = 1024, - .step = 256 + .step = 128 }, .nvrmask = 63, .kbc_device = NULL, From 457601330d169c911d80fb2b18becbba4949a3d7 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 21 Feb 2025 20:15:26 -0500 Subject: [PATCH 0327/1190] Tag cassette_device correctly --- src/device/cassette.c | 2 +- src/include/86box/device.h | 1 + src/include/86box/machine.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/device/cassette.c b/src/device/cassette.c index ac79edff2..5cde2fbd0 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -715,7 +715,7 @@ cassette_init(UNUSED(const device_t *info)) const device_t cassette_device = { .name = "IBM PC/PCjr Cassette Device", .internal_name = "cassette", - .flags = 0, + .flags = DEVICE_CASETTE, .local = 0, .init = cassette_init, .close = cassette_close, diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 1c3ef1ef3..4cc283a25 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -79,6 +79,7 @@ // #define CONFIG_STANDALONE 257 /* not available on the on-board variant */ enum { + DEVICE_CASETTE = 1, /* requires a Casette Port */ DEVICE_SIDECAR = 2, /* requires an IBM PCjr */ DEVICE_ISA = 4, /* requires the ISA bus */ DEVICE_XT_KBC = 8, /* requires an XT-compatible keyboard controller */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 52af90581..b2e4c01f2 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -67,7 +67,7 @@ #define MACHINE_AGP (MACHINE_BUS_AGP | MACHINE_PCI) /* sys is AT-compatible with AGP */ #define MACHINE_AGP98 (MACHINE_BUS_AGP | MACHINE_PCI98) /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ -#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ +#define MACHINE_PC5150 (MACHINE_CASSETTE | MACHINE_PC) /* sys is IBM PC 5150 */ #define MACHINE_PCJR (MACHINE_CASSETTE | MACHINE_BUS_SIDECAR) /* sys is PCjr */ #define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ #define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ From c1f8944c402e199c91d2298dda3fa66b3c3d785f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 22 Feb 2025 20:31:05 +0900 Subject: [PATCH 0328/1190] remove unused 5576 key conv table --- src/device/keyboard.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 2b851f36c..582dcf0b1 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -85,34 +85,6 @@ typedef struct { const uint8_t brk[4]; } scconvtbl; -/* Is this a left-over of something planned earlier? */ -#ifdef USE_SCCONV55_82 -static scconvtbl scconv55_82[18 + 1] = -{ - // clang-format off - {.sc = 0x02 , .mk = { 0x5f, 0 }, .brk = { 0xf0, 0x5f, 0 } }, /* '1' -> 'Clear/ /SysRq' */ - {.sc = 0x03 , .mk = { 0x48, 0 }, .brk = { 0xf0, 0x48, 0 } }, /* '2' -> '終了 (Exit)' */ - {.sc = 0x04 , .mk = { 0x38, 0 }, .brk = { 0xf0, 0x38, 0 } }, /* '3' -> 'メッセージ (Message)/ /応答 (Respond)' */ - {.sc = 0x05 , .mk = { 0x30, 0 }, .brk = { 0xf0, 0x30, 0 } }, /* '4' -> 'サイズ変換 (Change Size)/ /横倍角 (2x Width)' */ - {.sc = 0x06 , .mk = { 0x20, 0 }, .brk = { 0xf0, 0x20, 0 } }, /* '5' -> '単語登録 (Register Word)/ /再交換 (Re-change)' */ - {.sc = 0x07 , .mk = { 0x28, 0 }, .brk = { 0xf0, 0x28, 0 } }, /* '6' -> '漢字 (Kanji)/ /番号 (Number)' */ - {.sc = 0x08 , .mk = { 0x60, 0 }, .brk = { 0xf0, 0x60, 0 } }, /* '7' -> '取消 (Cancel)' */ - {.sc = 0x09 , .mk = { 0x40, 0 }, .brk = { 0xf0, 0x40, 0 } }, /* '8' -> 'コピー (Copy)/ /移動 (Move)' */ - {.sc = 0x3d , .mk = { 0x1f, 0 }, .brk = { 0xf0, 0x1f, 0 } }, /* 'F3' -> 'Cr Bnk/領域呼出 (Call Range)/All Cr/登録 (Register)' */ - {.sc = 0x3e , .mk = { 0x27, 0 }, .brk = { 0xf0, 0x27, 0 } }, /* 'F4' -> '割込み (Interrupt)' */ - {.sc = 0x3f , .mk = { 0x2f, 0 }, .brk = { 0xf0, 0x2f, 0 } }, /* 'F5' -> 'UF1' */ - {.sc = 0x40 , .mk = { 0x5e, 0 }, .brk = { 0xf0, 0x5e, 0 } }, /* 'F6' -> 'UF2' */ - {.sc = 0x41 , .mk = { 0x08, 0 }, .brk = { 0xf0, 0x08, 0 } }, /* 'F7' -> 'UF3' */ - {.sc = 0x42 , .mk = { 0x10, 0 }, .brk = { 0xf0, 0x10, 0 } }, /* 'F8' -> 'UF4' */ - {.sc = 0x43 , .mk = { 0x50, 0 }, .brk = { 0xf0, 0x50, 0 } }, /* 'F9' -> 'EOF/Erase/ErInp' */ - {.sc = 0x44 , .mk = { 0x18, 0 }, .brk = { 0xf0, 0x18, 0 } }, /* 'F10' -> 'Attn/ /CrSel' */ - {.sc = 0x57 , .mk = { 0x17, 0 }, .brk = { 0xf0, 0x17, 0 } }, /* 'F11' -> 'PA1/ /DvCncl' */ - {.sc = 0x58 , .mk = { 0x37, 0 }, .brk = { 0xf0, 0x37, 0 } }, /* 'F12' -> 'PA2/ /PA3' */ - {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ - // clang-format on -}; -#endif - static scconvtbl scconv55_8a[18 + 1] = { // clang-format off From ffedf62a4a0707acb947a271c7751de3e00157e2 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:02:44 +0900 Subject: [PATCH 0329/1190] add scancode set 81h and 82h (incompleted) need to modify the keyboard initialization --- src/86box.c | 4 +- src/device/keyboard_at.c | 1090 +++++++++++++++++++++++++++++++++++++- 2 files changed, 1071 insertions(+), 23 deletions(-) diff --git a/src/86box.c b/src/86box.c index 1cd0ffec8..6b64cd2ec 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1094,8 +1094,8 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { - if (keyboard_mode == 0x8A) { - /* Use R-Alt because PS/55 DOS assigns L-Alt Kanji */ + if (keyboard_mode >= 0x81) { + /* Use R-Alt because PS/55 DOS and OS/2 assign L-Alt Kanji */ keyboard_input(1, 0x1D); /* Ctrl key pressed */ keyboard_input(1, 0x138); /* R-Alt key pressed */ keyboard_input(1, sc); diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 5c66029ad..d44833dd3 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1651,10 +1651,1045 @@ static const scancode scancode_set3[512] = { [Japanese DOS and keyboard scancode set comparison] | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | DOS 5(US)| |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| - | IBM 101-key | n/a | n/a | n/a | n/a | 2 | n/a | 2 | - | IBM-J 5576-00x (obsolete) | 8Ah | 8Ah | 8Ah | 82h | 82h | 82h | 2 | - | OADG (modern Japanese) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ + | IBM 101 US English | n/a | n/a | n/a | 2 | 2 | 2 | 2 | + | IBM-J 5576-00x (obsolete) | 8Ah | 8Ah | 8Ah | 82h | 82h | 81h | 2 | + | OADG (modern Japanese) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | +*/ +/* Scancode set 81h : Set 01 with language specific keys support used by OS/2 */ +static const scancode scancode_set81[512] = { + // clang-format off + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 012 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028* */ + { .mk = { 0x77, 0 }, .brk = { 0xf7, 0 } }, /* 029 0x45 Hankaku, Zenkaku */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 02b 0x17 Mu */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 * (asterisk) */ + { .mk = { 0x70, 0 }, .brk = { 0xf0, 0 } }, /* 038 0x3A LALT = Kanji */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 NUMLOCKCLEAR -> Shift + SCRLOCK :TODO */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 0x75 SCROLLLOCK */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0x54, 0 }, .brk = { 0xd4, 0 } }, /* 054 */ + { .mk = { 0x55, 0 }, .brk = { 0xd5, 0 } }, /* 055 */ + { .mk = { 0x56, 0 }, .brk = { 0xd6, 0 } }, /* 056 */ + { .mk = { 0x57, 0 }, .brk = { 0xd7, 0 } }, /* 057 F11 */ + { .mk = { 0x58, 0 }, .brk = { 0xd8, 0 } }, /* 058 F12 */ + { .mk = { 0x59, 0 }, .brk = { 0xd9, 0 } }, /* 059 */ + { .mk = { 0x5a, 0 }, .brk = { 0xda, 0 } }, /* 05a */ + { .mk = { 0x5b, 0 }, .brk = { 0xdb, 0 } }, /* 05b */ + { .mk = { 0x5c, 0 }, .brk = { 0xdc, 0 } }, /* 05c */ + { .mk = { 0x5d, 0 }, .brk = { 0xdd, 0 } }, /* 05d */ + { .mk = { 0x5e, 0 }, .brk = { 0xde, 0 } }, /* 05e */ + { .mk = { 0x5f, 0 }, .brk = { 0xdf, 0 } }, /* 05f */ + { .mk = { 0x60, 0 }, .brk = { 0xe0, 0 } }, /* 060 */ + { .mk = { 0x61, 0 }, .brk = { 0xe1, 0 } }, /* 061 */ + { .mk = { 0x62, 0 }, .brk = { 0xe2, 0 } }, /* 062 */ + { .mk = { 0x63, 0 }, .brk = { 0xe3, 0 } }, /* 063 */ + { .mk = { 0x64, 0 }, .brk = { 0xe4, 0 } }, /* 064 */ + { .mk = { 0x65, 0 }, .brk = { 0xe5, 0 } }, /* 065 */ + { .mk = { 0x66, 0 }, .brk = { 0xe6, 0 } }, /* 066 */ + { .mk = { 0x67, 0 }, .brk = { 0xe7, 0 } }, /* 067 */ + { .mk = { 0x68, 0 }, .brk = { 0xe8, 0 } }, /* 068 */ + { .mk = { 0x69, 0 }, .brk = { 0xe9, 0 } }, /* 069 */ + { .mk = { 0x6a, 0 }, .brk = { 0xea, 0 } }, /* 06a */ + { .mk = { 0x6b, 0 }, .brk = { 0xeb, 0 } }, /* 06b */ + { .mk = { 0x6c, 0 }, .brk = { 0xec, 0 } }, /* 06c */ + { .mk = { 0x6d, 0 }, .brk = { 0xed, 0 } }, /* 06d */ + { .mk = { 0x6e, 0 }, .brk = { 0xee, 0 } }, /* 06e */ + { .mk = { 0x6f, 0 }, .brk = { 0xef, 0 } }, /* 06f */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xb8, 0 } }, /* 070 0x36 Kana */ + { .mk = { 0x71, 0 }, .brk = { 0xf1, 0 } }, /* 071 */ + { .mk = { 0x72, 0 }, .brk = { 0xf2, 0 } }, /* 072 */ + { .mk = { 0x73, 0 }, .brk = { 0xf3, 0 } }, /* 073 0x0b Ro, Underline */ + { .mk = { 0x74, 0 }, .brk = { 0xf4, 0 } }, /* 074 */ + { .mk = { 0x75, 0 }, .brk = { 0xf5, 0 } }, /* 075 */ + { .mk = { 0x76, 0 }, .brk = { 0xf6, 0 } }, /* 076 */ + { .mk = { 0x77, 0 }, .brk = { 0xf7, 0 } }, /* 077 */ + { .mk = { 0x78, 0 }, .brk = { 0xf8, 0 } }, /* 078 */ + { .mk = { 0x79, 0 }, .brk = { 0xf9, 0 } }, /* 079 0x35 Henkan */ + { .mk = { 0x7a, 0 }, .brk = { 0xfa, 0 } }, /* 07a */ + { .mk = { 0x7b, 0 }, .brk = { 0xfb, 0 } }, /* 07b 0x33 Muhenkan */ + { .mk = { 0x7c, 0 }, .brk = { 0xfc, 0 } }, /* 07c */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 07d 0x30 Yen, Vertical line */ + { .mk = { 0x7e, 0 }, .brk = { 0xfe, 0 } }, /* 07e */ + { .mk = { 0x7f, 0 }, .brk = { 0xff, 0 } }, /* 07f */ + { .mk = { 0x80, 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0x81, 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0x82, 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0x85, 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0x86, 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0x87, 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0x88, 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0x89, 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0x8a, 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0x8b, 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0x8c, 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0x8d, 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0x8e, 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0x8f, 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0x90, 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0x91, 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0x92, 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0x93, 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0x94, 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0x95, 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0x96, 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0x97, 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0x98, 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0x99, 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0x9a, 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0x9b, 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0x9c, 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0x9d, 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0x9e, 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0x9f, 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0xa0, 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0xa1, 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0xa2, 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0xa3, 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0xa4, 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0xa5, 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0xa6, 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0xa7, 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0xa8, 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0xa9, 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0xaa, 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0xab, 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0xac, 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0xad, 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0xae, 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0xaf, 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0xb0, 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0xb1, 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0xb2, 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0xb3, 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0xb4, 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0xb5, 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0xb6, 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0xb7, 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0xb8, 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0xb9, 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0xba, 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0xbb, 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0xbc, 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0xbd, 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0xbe, 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0xbf, 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0xc0, 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0xc1, 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0xc2, 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0xc3, 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0xc4, 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0xc5, 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0xc6, 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0xc7, 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0xc8, 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0xc9, 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0xca, 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0xcb, 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0xcc, 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0xcd, 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0xce, 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0xcf, 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0xd0, 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0xd1, 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0xd2, 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0xd3, 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0xd4, 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0xd5, 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0xd6, 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0xd7, 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0xd8, 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0xd9, 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0xda, 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0xdb, 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0xdc, 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0xdd, 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0xde, 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0xdf, 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0xe0, 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0xe1, 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0xe2, 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0xe3, 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0xe4, 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0xe5, 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0xe6, 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0xe7, 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0xe8, 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0xe9, 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0xea, 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0xeb, 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0xec, 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0xed, 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0xee, 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0xef, 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0xf1, 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0xf2, 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0xf3, 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0xf4, 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0xf5, 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0xf6, 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0xf7, 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0xf8, 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0xf9, 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0xfa, 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0xfb, 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0xfc, 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0xfd, 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0xfe, 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0xff, 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = {0xe1, 0x1d, 0 }, .brk = { 0xe1, 0x9d, 0 } }, /* 100 */ + { .mk = {0xe0, 0x01, 0 }, .brk = { 0xe0, 0x81, 0 } }, /* 101 */ + { .mk = {0xe0, 0x02, 0 }, .brk = { 0xe0, 0x82, 0 } }, /* 102 */ + { .mk = {0xe0, 0x03, 0 }, .brk = { 0xe0, 0x83, 0 } }, /* 103 */ + { .mk = {0xe0, 0x04, 0 }, .brk = { 0xe0, 0x84, 0 } }, /* 104 */ + { .mk = {0xe0, 0x05, 0 }, .brk = { 0xe0, 0x85, 0 } }, /* 105 */ + { .mk = {0xe0, 0x06, 0 }, .brk = { 0xe0, 0x86, 0 } }, /* 106 */ + { .mk = {0xe0, 0x07, 0 }, .brk = { 0xe0, 0x87, 0 } }, /* 107 */ + { .mk = {0xe0, 0x08, 0 }, .brk = { 0xe0, 0x88, 0 } }, /* 108 */ + { .mk = {0xe0, 0x09, 0 }, .brk = { 0xe0, 0x89, 0 } }, /* 109 */ + { .mk = {0xe0, 0x0a, 0 }, .brk = { 0xe0, 0x8a, 0 } }, /* 10a */ + { .mk = {0xe0, 0x0b, 0 }, .brk = { 0xe0, 0x8b, 0 } }, /* 10b */ + { .mk = {0xe0, 0x0c, 0 }, .brk = { 0xe0, 0x8c, 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = {0xe0, 0x0e, 0 }, .brk = { 0xe0, 0x8e, 0 } }, /* 10e */ + { .mk = {0xe0, 0x0f, 0 }, .brk = { 0xe0, 0x8f, 0 } }, /* 10f */ + { .mk = {0xe0, 0x10, 0 }, .brk = { 0xe0, 0x90, 0 } }, /* 110 */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0x91, 0 } }, /* 112 */ + { .mk = {0xe0, 0x12, 0 }, .brk = { 0xe0, 0x92, 0 } }, /* 113 */ + { .mk = {0xe0, 0x13, 0 }, .brk = { 0xe0, 0x93, 0 } }, /* 113 */ + { .mk = {0xe0, 0x14, 0 }, .brk = { 0xe0, 0x94, 0 } }, /* 114 */ + { .mk = {0xe0, 0x15, 0 }, .brk = { 0xe0, 0x95, 0 } }, /* 115 */ + { .mk = {0xe0, 0x16, 0 }, .brk = { 0xe0, 0x96, 0 } }, /* 116 */ + { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0x97, 0 } }, /* 117 */ + { .mk = {0xe0, 0x18, 0 }, .brk = { 0xe0, 0x98, 0 } }, /* 118 */ + { .mk = {0xe0, 0x19, 0 }, .brk = { 0xe0, 0x99, 0 } }, /* 119 */ + { .mk = {0xe0, 0x1a, 0 }, .brk = { 0xe0, 0x9a, 0 } }, /* 11a */ + { .mk = {0xe0, 0x1b, 0 }, .brk = { 0xe0, 0x9b, 0 } }, /* 11b */ + { .mk = {0xe0, 0x1c, 0 }, .brk = { 0xe0, 0x9c, 0 } }, /* 11c */ + { .mk = {0xe0, 0x1d, 0 }, .brk = { 0xe0, 0x9d, 0 } }, /* 11d */ + { .mk = {0xe0, 0x1e, 0 }, .brk = { 0xe0, 0x9e, 0 } }, /* 11e */ + { .mk = {0xe0, 0x1f, 0 }, .brk = { 0xe0, 0x9f, 0 } }, /* 11f */ + { .mk = {0xe0, 0x20, 0 }, .brk = { 0xe0, 0xa0, 0 } }, /* 120 */ + { .mk = {0xe0, 0x21, 0 }, .brk = { 0xe0, 0xa1, 0 } }, /* 121 */ + { .mk = {0xe0, 0x22, 0 }, .brk = { 0xe0, 0xa2, 0 } }, /* 122 */ + { .mk = {0xe0, 0x23, 0 }, .brk = { 0xe0, 0xa3, 0 } }, /* 123 */ + { .mk = {0xe0, 0x24, 0 }, .brk = { 0xe0, 0xa4, 0 } }, /* 124 */ + { .mk = {0xe0, 0x25, 0 }, .brk = { 0xe0, 0xa5, 0 } }, /* 125 */ + { .mk = {0xe0, 0x26, 0 }, .brk = { 0xe0, 0xa6, 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = {0xe0, 0x2c, 0 }, .brk = { 0xe0, 0xac, 0 } }, /* 12c */ + { .mk = {0xe0, 0x2d, 0 }, .brk = { 0xe0, 0xad, 0 } }, /* 12d */ + { .mk = {0xe0, 0x2e, 0 }, .brk = { 0xe0, 0xae, 0 } }, /* 12e */ + { .mk = {0xe0, 0x2f, 0 }, .brk = { 0xe0, 0xaf, 0 } }, /* 12f */ + { .mk = {0xe0, 0x30, 0 }, .brk = { 0xe0, 0xb0, 0 } }, /* 130 */ + { .mk = {0xe0, 0x31, 0 }, .brk = { 0xe0, 0xb1, 0 } }, /* 131 */ + { .mk = {0xe0, 0x32, 0 }, .brk = { 0xe0, 0xb2, 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = {0xe0, 0x34, 0 }, .brk = { 0xe0, 0xb4, 0 } }, /* 134 */ + { .mk = {0xe0, 0x35, 0 }, .brk = { 0xe0, 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = {0xe0, 0x37, 0 }, .brk = { 0xe0, 0xb7, 0 } }, /* 137 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 138* 0x31 R-Alt */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = {0xe0, 0x3a, 0 }, .brk = { 0xe0, 0xba, 0 } }, /* 13a */ + { .mk = {0xe0, 0x3b, 0 }, .brk = { 0xe0, 0xbb, 0 } }, /* 13b */ + { .mk = {0xe0, 0x3c, 0 }, .brk = { 0xe0, 0xbc, 0 } }, /* 13c */ + { .mk = {0xe0, 0x3d, 0 }, .brk = { 0xe0, 0xbd, 0 } }, /* 13d */ + { .mk = {0xe0, 0x3e, 0 }, .brk = { 0xe0, 0xbe, 0 } }, /* 13e */ + { .mk = {0xe0, 0x3f, 0 }, .brk = { 0xe0, 0xbf, 0 } }, /* 13f */ + { .mk = {0xe0, 0x40, 0 }, .brk = { 0xe0, 0xc0, 0 } }, /* 140 */ + { .mk = {0xe0, 0x41, 0 }, .brk = { 0xe0, 0xc1, 0 } }, /* 141 */ + { .mk = {0xe0, 0x42, 0 }, .brk = { 0xe0, 0xc2, 0 } }, /* 142 */ + { .mk = {0xe0, 0x43, 0 }, .brk = { 0xe0, 0xc3, 0 } }, /* 143 */ + { .mk = {0xe0, 0x44, 0 }, .brk = { 0xe0, 0xc4, 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = {0xe0, 0x46, 0 }, .brk = { 0xe0, 0xc6, 0 } }, /* 146 */ + { .mk = {0xe0, 0x47, 0 }, .brk = { 0xe0, 0xc7, 0 } }, /* 147 */ + { .mk = {0xe0, 0x48, 0 }, .brk = { 0xe0, 0xc8, 0 } }, /* 148 */ + { .mk = {0xe0, 0x49, 0 }, .brk = { 0xe0, 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = {0xe0, 0x4b, 0 }, .brk = { 0xe0, 0xcb, 0 } }, /* 14b */ + { .mk = {0xe0, 0x4c, 0 }, .brk = { 0xe0, 0xcc, 0 } }, /* 14c */ + { .mk = {0xe0, 0x4d, 0 }, .brk = { 0xe0, 0xcd, 0 } }, /* 14d */ + { .mk = {0xe0, 0x4e, 0 }, .brk = { 0xe0, 0xce, 0 } }, /* 14e */ + { .mk = {0xe0, 0x4f, 0 }, .brk = { 0xe0, 0xcf, 0 } }, /* 14f */ + { .mk = {0xe0, 0x50, 0 }, .brk = { 0xe0, 0xd0, 0 } }, /* 150 */ + { .mk = {0xe0, 0x51, 0 }, .brk = { 0xe0, 0xd1, 0 } }, /* 151 */ + { .mk = {0xe0, 0x52, 0 }, .brk = { 0xe0, 0xd2, 0 } }, /* 152 */ + { .mk = {0xe0, 0x53, 0 }, .brk = { 0xe0, 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = {0xe0, 0x55, 0 }, .brk = { 0xe0, 0xd5, 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */ + { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */ + { .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */ + { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */ + { .mk = { 0x7b, 0 }, .brk = { 0xfb, 0 } }, /* 15b 0x33 LGUI->Muhenkan (in emulator only) */ + { .mk = { 0x79, 0 }, .brk = { 0xf9, 0 } }, /* 15c 0x35 RGUI->Henkan (in emulator only) */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xb8, 0 } }, /* 15d 0x36 APPLICATION->Kana (in emulator only) */ + { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */ + { .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */ + { .mk = {0xe0, 0x62, 0 }, .brk = { 0xe0, 0xe2, 0 } }, /* 162 */ + { .mk = {0xe0, 0x63, 0 }, .brk = { 0xe0, 0xe3, 0 } }, /* 163 */ + { .mk = {0xe0, 0x64, 0 }, .brk = { 0xe0, 0xe4, 0 } }, /* 164 */ + { .mk = {0xe0, 0x65, 0 }, .brk = { 0xe0, 0xe5, 0 } }, /* 165 */ + { .mk = {0xe0, 0x66, 0 }, .brk = { 0xe0, 0xe6, 0 } }, /* 166 */ + { .mk = {0xe0, 0x67, 0 }, .brk = { 0xe0, 0xe7, 0 } }, /* 167 */ + { .mk = {0xe0, 0x68, 0 }, .brk = { 0xe0, 0xe8, 0 } }, /* 168 */ + { .mk = {0xe0, 0x69, 0 }, .brk = { 0xe0, 0xe9, 0 } }, /* 169 */ + { .mk = {0xe0, 0x6a, 0 }, .brk = { 0xe0, 0xea, 0 } }, /* 16a */ + { .mk = {0xe0, 0x6b, 0 }, .brk = { 0xe0, 0xeb, 0 } }, /* 16b */ + { .mk = {0xe0, 0x6c, 0 }, .brk = { 0xe0, 0xec, 0 } }, /* 16c */ + { .mk = {0xe0, 0x6d, 0 }, .brk = { 0xe0, 0xed, 0 } }, /* 16d */ + { .mk = {0xe0, 0x6e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = {0xe0, 0x70, 0 }, .brk = { 0xe0, 0xf0, 0 } }, /* 170 */ + { .mk = {0xe0, 0x71, 0 }, .brk = { 0xe0, 0xf1, 0 } }, /* 171 */ + { .mk = {0xe0, 0x72, 0 }, .brk = { 0xe0, 0xf2, 0 } }, /* 172 */ + { .mk = {0xe0, 0x73, 0 }, .brk = { 0xe0, 0xf3, 0 } }, /* 173 */ + { .mk = {0xe0, 0x74, 0 }, .brk = { 0xe0, 0xf4, 0 } }, /* 174 */ + { .mk = {0xe0, 0x75, 0 }, .brk = { 0xe0, 0xf5, 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = {0xe0, 0x77, 0 }, .brk = { 0xe0, 0xf7, 0 } }, /* 177 */ + { .mk = {0xe0, 0x78, 0 }, .brk = { 0xe0, 0xf8, 0 } }, /* 178 */ + { .mk = {0xe0, 0x79, 0 }, .brk = { 0xe0, 0xf9, 0 } }, /* 179 */ + { .mk = {0xe0, 0x7a, 0 }, .brk = { 0xe0, 0xfa, 0 } }, /* 17a */ + { .mk = {0xe0, 0x7b, 0 }, .brk = { 0xe0, 0xfb, 0 } }, /* 17b */ + { .mk = {0xe0, 0x7c, 0 }, .brk = { 0xe0, 0xfc, 0 } }, /* 17c */ + { .mk = {0xe0, 0x7d, 0 }, .brk = { 0xe0, 0xfd, 0 } }, /* 17d */ + { .mk = {0xe0, 0x7e, 0 }, .brk = { 0xe0, 0xfe, 0 } }, /* 17e */ + { .mk = {0xe0, 0x7f, 0 }, .brk = { 0xe0, 0xff, 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cv */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = {0xe0, 0xe1, 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = {0xe0, 0xee, 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = {0xe0, 0xf1, 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = {0xe0, 0xfe, 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = {0xe0, 0xff, 0 }, .brk = { 0 } } /* 1ff */ + // clang-format on + }; +/* Scancode set 82h : Set 02 with language specific keys support used by DOS/V */ +static const scancode scancode_set82[512] = { + // clang-format off + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x76, 0 }, .brk = { 0xF0, 0x76, 0 } }, /* 001 */ + { .mk = { 0x16, 0 }, .brk = { 0xF0, 0x16, 0 } }, /* 002 */ + { .mk = { 0x1E, 0 }, .brk = { 0xF0, 0x1E, 0 } }, /* 003 */ + { .mk = { 0x26, 0 }, .brk = { 0xF0, 0x26, 0 } }, /* 004 */ + { .mk = { 0x25, 0 }, .brk = { 0xF0, 0x25, 0 } }, /* 005 */ + { .mk = { 0x2E, 0 }, .brk = { 0xF0, 0x2E, 0 } }, /* 006 */ + { .mk = { 0x36, 0 }, .brk = { 0xF0, 0x36, 0 } }, /* 007 */ + { .mk = { 0x3D, 0 }, .brk = { 0xF0, 0x3D, 0 } }, /* 008 */ + { .mk = { 0x3E, 0 }, .brk = { 0xF0, 0x3E, 0 } }, /* 009 */ + { .mk = { 0x46, 0 }, .brk = { 0xF0, 0x46, 0 } }, /* 00a */ + { .mk = { 0x45, 0 }, .brk = { 0xF0, 0x45, 0 } }, /* 00b */ + { .mk = { 0x4E, 0 }, .brk = { 0xF0, 0x4E, 0 } }, /* 00c */ + { .mk = { 0x55, 0 }, .brk = { 0xF0, 0x55, 0 } }, /* 00d */ + { .mk = { 0x66, 0 }, .brk = { 0xF0, 0x66, 0 } }, /* 00e */ + { .mk = { 0x0D, 0 }, .brk = { 0xF0, 0x0D, 0 } }, /* 00f */ + { .mk = { 0x15, 0 }, .brk = { 0xF0, 0x15, 0 } }, /* 010 */ + { .mk = { 0x1D, 0 }, .brk = { 0xF0, 0x1D, 0 } }, /* 011 */ + { .mk = { 0x24, 0 }, .brk = { 0xF0, 0x24, 0 } }, /* 012 */ + { .mk = { 0x2D, 0 }, .brk = { 0xF0, 0x2D, 0 } }, /* 013 */ + { .mk = { 0x2C, 0 }, .brk = { 0xF0, 0x2C, 0 } }, /* 014 */ + { .mk = { 0x35, 0 }, .brk = { 0xF0, 0x35, 0 } }, /* 015 */ + { .mk = { 0x3C, 0 }, .brk = { 0xF0, 0x3C, 0 } }, /* 016 */ + { .mk = { 0x43, 0 }, .brk = { 0xF0, 0x43, 0 } }, /* 017 */ + { .mk = { 0x44, 0 }, .brk = { 0xF0, 0x44, 0 } }, /* 018 */ + { .mk = { 0x4D, 0 }, .brk = { 0xF0, 0x4D, 0 } }, /* 019 */ + { .mk = { 0x54, 0 }, .brk = { 0xF0, 0x54, 0 } }, /* 01a */ + { .mk = { 0x5B, 0 }, .brk = { 0xF0, 0x5B, 0 } }, /* 01b */ + { .mk = { 0x5A, 0 }, .brk = { 0xF0, 0x5A, 0 } }, /* 01c */ + { .mk = { 0x14, 0 }, .brk = { 0xF0, 0x14, 0 } }, /* 01d */ + { .mk = { 0x1C, 0 }, .brk = { 0xF0, 0x1C, 0 } }, /* 01e */ + { .mk = { 0x1B, 0 }, .brk = { 0xF0, 0x1B, 0 } }, /* 01f */ + { .mk = { 0x23, 0 }, .brk = { 0xF0, 0x23, 0 } }, /* 020 */ + { .mk = { 0x2B, 0 }, .brk = { 0xF0, 0x2B, 0 } }, /* 021 */ + { .mk = { 0x34, 0 }, .brk = { 0xF0, 0x34, 0 } }, /* 022 */ + { .mk = { 0x33, 0 }, .brk = { 0xF0, 0x33, 0 } }, /* 023 */ + { .mk = { 0x3B, 0 }, .brk = { 0xF0, 0x3B, 0 } }, /* 024 */ + { .mk = { 0x42, 0 }, .brk = { 0xF0, 0x42, 0 } }, /* 025 */ + { .mk = { 0x4B, 0 }, .brk = { 0xF0, 0x4B, 0 } }, /* 026 */ + { .mk = { 0x4C, 0 }, .brk = { 0xF0, 0x4C, 0 } }, /* 027 */ + { .mk = { 0x52, 0 }, .brk = { 0xF0, 0x52, 0 } }, /* 028* */ + { .mk = { 0x62, 0 }, .brk = { 0xf0, 0x62, 0 } }, /* 029 0x45 Hankaku, Zenkaku */ + { .mk = { 0x12, 0 }, .brk = { 0xF0, 0x12, 0 } }, /* 02a */ + { .mk = { 0x5b, 0 }, .brk = { 0xf0, 0x5b, 0 } }, /* 02b 0x17 Mu */ + { .mk = { 0x1A, 0 }, .brk = { 0xF0, 0x1A, 0 } }, /* 02c */ + { .mk = { 0x22, 0 }, .brk = { 0xF0, 0x22, 0 } }, /* 02d */ + { .mk = { 0x21, 0 }, .brk = { 0xF0, 0x21, 0 } }, /* 02e */ + { .mk = { 0x2A, 0 }, .brk = { 0xF0, 0x2A, 0 } }, /* 02f */ + { .mk = { 0x32, 0 }, .brk = { 0xF0, 0x32, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xF0, 0x31, 0 } }, /* 031 */ + { .mk = { 0x3A, 0 }, .brk = { 0xF0, 0x3A, 0 } }, /* 032 */ + { .mk = { 0x41, 0 }, .brk = { 0xF0, 0x41, 0 } }, /* 033 */ + { .mk = { 0x49, 0 }, .brk = { 0xF0, 0x49, 0 } }, /* 034 */ + { .mk = { 0x4A, 0 }, .brk = { 0xF0, 0x4A, 0 } }, /* 035 */ + { .mk = { 0x59, 0 }, .brk = { 0xF0, 0x59, 0 } }, /* 036 */ + { .mk = { 0x7C, 0 }, .brk = { 0xF0, 0x7C, 0 } }, /* 037 */ + { .mk = { 0x13, 0 }, .brk = { 0xF0, 0x13, 0 } }, /* 038 0x3A LALT = Kanji */ + { .mk = { 0x29, 0 }, .brk = { 0xF0, 0x29, 0 } }, /* 039 */ + { .mk = { 0x58, 0 }, .brk = { 0xF0, 0x58, 0 } }, /* 03a */ + { .mk = { 0x05, 0 }, .brk = { 0xF0, 0x05, 0 } }, /* 03b */ + { .mk = { 0x06, 0 }, .brk = { 0xF0, 0x06, 0 } }, /* 03c */ + { .mk = { 0x04, 0 }, .brk = { 0xF0, 0x04, 0 } }, /* 03d */ + { .mk = { 0x0C, 0 }, .brk = { 0xF0, 0x0C, 0 } }, /* 03e */ + { .mk = { 0x03, 0 }, .brk = { 0xF0, 0x03, 0 } }, /* 03f */ + { .mk = { 0x0B, 0 }, .brk = { 0xF0, 0x0B, 0 } }, /* 040 */ + { .mk = { 0x83, 0 }, .brk = { 0xF0, 0x83, 0 } }, /* 041 */ + { .mk = { 0x0A, 0 }, .brk = { 0xF0, 0x0A, 0 } }, /* 042 */ + { .mk = { 0x01, 0 }, .brk = { 0xF0, 0x01, 0 } }, /* 043 */ + { .mk = { 0x09, 0 }, .brk = { 0xF0, 0x09, 0 } }, /* 044 */ + { .mk = { 0x77, 0 }, .brk = { 0xF0, 0x77, 0 } }, /* 045 NUMLOCKCLEAR -> Shift + SCRLOCK :TODO */ + { .mk = { 0x7E, 0 }, .brk = { 0xF0, 0x7E, 0 } }, /* 046 0x75 SCROLLLOCK */ + { .mk = { 0x6C, 0 }, .brk = { 0xF0, 0x6C, 0 } }, /* 047 */ + { .mk = { 0x75, 0 }, .brk = { 0xF0, 0x75, 0 } }, /* 048 */ + { .mk = { 0x7D, 0 }, .brk = { 0xF0, 0x7D, 0 } }, /* 049 */ + { .mk = { 0x7B, 0 }, .brk = { 0xF0, 0x7B, 0 } }, /* 04a */ + { .mk = { 0x6B, 0 }, .brk = { 0xF0, 0x6B, 0 } }, /* 04b */ + { .mk = { 0x73, 0 }, .brk = { 0xF0, 0x73, 0 } }, /* 04c */ + { .mk = { 0x74, 0 }, .brk = { 0xF0, 0x74, 0 } }, /* 04d */ + { .mk = { 0x79, 0 }, .brk = { 0xF0, 0x79, 0 } }, /* 04e */ + { .mk = { 0x69, 0 }, .brk = { 0xF0, 0x69, 0 } }, /* 04f */ + { .mk = { 0x72, 0 }, .brk = { 0xF0, 0x72, 0 } }, /* 050 */ + { .mk = { 0x7A, 0 }, .brk = { 0xF0, 0x7A, 0 } }, /* 051 */ + { .mk = { 0x70, 0 }, .brk = { 0xF0, 0x70, 0 } }, /* 052 */ + { .mk = { 0x71, 0 }, .brk = { 0xF0, 0x71, 0 } }, /* 053 */ + { .mk = { 0x84, 0 }, .brk = { 0xF0, 0x84, 0 } }, /* 054 */ + { .mk = { 0x60, 0 }, .brk = { 0xF0, 0x60, 0 } }, /* 055 */ + { .mk = { 0x61, 0 }, .brk = { 0xF0, 0x61, 0 } }, /* 056 */ + { .mk = { 0x78, 0 }, .brk = { 0xF0, 0x78, 0 } }, /* 057 */ + { .mk = { 0x07, 0 }, .brk = { 0xF0, 0x07, 0 } }, /* 058 */ + { .mk = { 0x0F, 0 }, .brk = { 0xF0, 0x0F, 0 } }, /* 059 */ + { .mk = { 0x17, 0 }, .brk = { 0xF0, 0x17, 0 } }, /* 05a */ + { .mk = { 0x1F, 0 }, .brk = { 0xF0, 0x1F, 0 } }, /* 05b */ + { .mk = { 0x27, 0 }, .brk = { 0xF0, 0x27, 0 } }, /* 05c */ + { .mk = { 0x2F, 0 }, .brk = { 0xF0, 0x2F, 0 } }, /* 05d */ + { .mk = { 0x37, 0 }, .brk = { 0xF0, 0x37, 0 } }, /* 05e */ + { .mk = { 0x3F, 0 }, .brk = { 0xF0, 0x3F, 0 } }, /* 05f */ + { .mk = { 0x47, 0 }, .brk = { 0xF0, 0x47, 0 } }, /* 060 */ + { .mk = { 0x4F, 0 }, .brk = { 0xF0, 0x4F, 0 } }, /* 061 */ + { .mk = { 0x56, 0 }, .brk = { 0xF0, 0x56, 0 } }, /* 062 */ + { .mk = { 0x5E, 0 }, .brk = { 0xF0, 0x5E, 0 } }, /* 063 */ + { .mk = { 0x08, 0 }, .brk = { 0xF0, 0x08, 0 } }, /* 064 */ + { .mk = { 0x10, 0 }, .brk = { 0xF0, 0x10, 0 } }, /* 065 */ + { .mk = { 0x18, 0 }, .brk = { 0xF0, 0x18, 0 } }, /* 066 */ + { .mk = { 0x20, 0 }, .brk = { 0xF0, 0x20, 0 } }, /* 067 */ + { .mk = { 0x28, 0 }, .brk = { 0xF0, 0x28, 0 } }, /* 068 */ + { .mk = { 0x30, 0 }, .brk = { 0xF0, 0x30, 0 } }, /* 069 */ + { .mk = { 0x38, 0 }, .brk = { 0xF0, 0x38, 0 } }, /* 06a */ + { .mk = { 0x40, 0 }, .brk = { 0xF0, 0x40, 0 } }, /* 06b */ + { .mk = { 0x48, 0 }, .brk = { 0xF0, 0x48, 0 } }, /* 06c */ + { .mk = { 0x50, 0 }, .brk = { 0xF0, 0x50, 0 } }, /* 06d */ + { .mk = { 0x57, 0 }, .brk = { 0xF0, 0x57, 0 } }, /* 06e */ + { .mk = { 0x6F, 0 }, .brk = { 0xF0, 0x6F, 0 } }, /* 06f */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0xf0, 0x11, 0 } }, /* 070 0x36 Kana */ + { .mk = { 0x19, 0 }, .brk = { 0xF0, 0x19, 0 } }, /* 071 */ + { .mk = { 0x39, 0 }, .brk = { 0xF0, 0x39, 0 } }, /* 072 */ + { .mk = { 0x51, 0 }, .brk = { 0xF0, 0x51, 0 } }, /* 073 0x0b Ro, Underline */ + { .mk = { 0x53, 0 }, .brk = { 0xF0, 0x53, 0 } }, /* 074 */ + { .mk = { 0x5C, 0 }, .brk = { 0xF0, 0x5C, 0 } }, /* 075 */ + { .mk = { 0x5F, 0 }, .brk = { 0xF0, 0x5F, 0 } }, /* 076 */ + { .mk = { 0x62, 0 }, .brk = { 0xF0, 0x62, 0 } }, /* 077 */ + { .mk = { 0x63, 0 }, .brk = { 0xF0, 0x63, 0 } }, /* 078 */ + { .mk = { 0x64, 0 }, .brk = { 0xF0, 0x64, 0 } }, /* 079 0x35 Henkan */ + { .mk = { 0x65, 0 }, .brk = { 0xF0, 0x65, 0 } }, /* 07a */ + { .mk = { 0x67, 0 }, .brk = { 0xF0, 0x67, 0 } }, /* 07b 0x33 Muhenkan */ + { .mk = { 0x68, 0 }, .brk = { 0xF0, 0x68, 0 } }, /* 07c */ + { .mk = { 0x5d, 0 }, .brk = { 0xf0, 0x5d, 0 } }, /* 07d 0x30 Yen, Vertical line */ + { .mk = { 0x6D, 0 }, .brk = { 0xF0, 0x6D, 0 } }, /* 07e */ + { .mk = { 0x6E, 0 }, .brk = { 0xF0, 0x6E, 0 } }, /* 07f */ + { .mk = { 0x80, 0 }, .brk = { 0xf0, 0x80, 0 } }, /* 080 */ + { .mk = { 0x81, 0 }, .brk = { 0xf0, 0x81, 0 } }, /* 081 */ + { .mk = { 0x82, 0 }, .brk = { 0xf0, 0x82, 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0x85, 0 }, .brk = { 0xf0, 0x54, 0 } }, /* 085 */ + { .mk = { 0x86, 0 }, .brk = { 0xf0, 0x86, 0 } }, /* 086 */ + { .mk = { 0x87, 0 }, .brk = { 0xf0, 0x87, 0 } }, /* 087 */ + { .mk = { 0x88, 0 }, .brk = { 0xf0, 0x88, 0 } }, /* 088 */ + { .mk = { 0x89, 0 }, .brk = { 0xf0, 0x89, 0 } }, /* 089 */ + { .mk = { 0x8a, 0 }, .brk = { 0xf0, 0x8a, 0 } }, /* 08a */ + { .mk = { 0x8b, 0 }, .brk = { 0xf0, 0x8b, 0 } }, /* 08b */ + { .mk = { 0x8c, 0 }, .brk = { 0xf0, 0x8c, 0 } }, /* 08c */ + { .mk = { 0x8d, 0 }, .brk = { 0xf0, 0x8d, 0 } }, /* 08d */ + { .mk = { 0x8e, 0 }, .brk = { 0xf0, 0x8e, 0 } }, /* 08e */ + { .mk = { 0x8f, 0 }, .brk = { 0xf0, 0x8f, 0 } }, /* 08f */ + { .mk = { 0x90, 0 }, .brk = { 0xf0, 0x90, 0 } }, /* 090 */ + { .mk = { 0x91, 0 }, .brk = { 0xf0, 0x91, 0 } }, /* 091 */ + { .mk = { 0x92, 0 }, .brk = { 0xf0, 0x92, 0 } }, /* 092 */ + { .mk = { 0x93, 0 }, .brk = { 0xf0, 0x93, 0 } }, /* 093 */ + { .mk = { 0x94, 0 }, .brk = { 0xf0, 0x94, 0 } }, /* 094 */ + { .mk = { 0x95, 0 }, .brk = { 0xf0, 0x95, 0 } }, /* 095 */ + { .mk = { 0x96, 0 }, .brk = { 0xf0, 0x96, 0 } }, /* 096 */ + { .mk = { 0x97, 0 }, .brk = { 0xf0, 0x97, 0 } }, /* 097 */ + { .mk = { 0x98, 0 }, .brk = { 0xf0, 0x98, 0 } }, /* 098 */ + { .mk = { 0x99, 0 }, .brk = { 0xf0, 0x99, 0 } }, /* 099 */ + { .mk = { 0x9a, 0 }, .brk = { 0xf0, 0x9a, 0 } }, /* 09a */ + { .mk = { 0x9b, 0 }, .brk = { 0xf0, 0x9b, 0 } }, /* 09b */ + { .mk = { 0x9c, 0 }, .brk = { 0xf0, 0x9c, 0 } }, /* 09c */ + { .mk = { 0x9d, 0 }, .brk = { 0xf0, 0x9d, 0 } }, /* 09d */ + { .mk = { 0x9e, 0 }, .brk = { 0xf0, 0x9e, 0 } }, /* 09e */ + { .mk = { 0x9f, 0 }, .brk = { 0xf0, 0x9f, 0 } }, /* 09f */ + { .mk = { 0xa0, 0 }, .brk = { 0xf0, 0xa0, 0 } }, /* 0a0 */ + { .mk = { 0xa1, 0 }, .brk = { 0xf0, 0xa1, 0 } }, /* 0a1 */ + { .mk = { 0xa2, 0 }, .brk = { 0xf0, 0xa2, 0 } }, /* 0a2 */ + { .mk = { 0xa3, 0 }, .brk = { 0xf0, 0xa3, 0 } }, /* 0a3 */ + { .mk = { 0xa4, 0 }, .brk = { 0xf0, 0xa4, 0 } }, /* 0a4 */ + { .mk = { 0xa5, 0 }, .brk = { 0xf0, 0xa5, 0 } }, /* 0a5 */ + { .mk = { 0xa6, 0 }, .brk = { 0xf0, 0xa6, 0 } }, /* 0a6 */ + { .mk = { 0xa7, 0 }, .brk = { 0xf0, 0xa7, 0 } }, /* 0a7 */ + { .mk = { 0xa8, 0 }, .brk = { 0xf0, 0xa8, 0 } }, /* 0a8 */ + { .mk = { 0xa9, 0 }, .brk = { 0xf0, 0xa9, 0 } }, /* 0a9 */ + { .mk = { 0xaa, 0 }, .brk = { 0xf0, 0xaa, 0 } }, /* 0aa */ + { .mk = { 0xab, 0 }, .brk = { 0xf0, 0xab, 0 } }, /* 0ab */ + { .mk = { 0xac, 0 }, .brk = { 0xf0, 0xac, 0 } }, /* 0ac */ + { .mk = { 0xad, 0 }, .brk = { 0xf0, 0xad, 0 } }, /* 0ad */ + { .mk = { 0xae, 0 }, .brk = { 0xf0, 0xae, 0 } }, /* 0ae */ + { .mk = { 0xaf, 0 }, .brk = { 0xf0, 0xaf, 0 } }, /* 0af */ + { .mk = { 0xb0, 0 }, .brk = { 0xf0, 0xb0, 0 } }, /* 0b0 */ + { .mk = { 0xb1, 0 }, .brk = { 0xf0, 0xb1, 0 } }, /* 0b1 */ + { .mk = { 0xb2, 0 }, .brk = { 0xf0, 0xb2, 0 } }, /* 0b2 */ + { .mk = { 0xb3, 0 }, .brk = { 0xf0, 0xb3, 0 } }, /* 0b3 */ + { .mk = { 0xb4, 0 }, .brk = { 0xf0, 0xb4, 0 } }, /* 0b4 */ + { .mk = { 0xb5, 0 }, .brk = { 0xf0, 0xb5, 0 } }, /* 0b5 */ + { .mk = { 0xb6, 0 }, .brk = { 0xf0, 0xb6, 0 } }, /* 0b6 */ + { .mk = { 0xb7, 0 }, .brk = { 0xf0, 0xb7, 0 } }, /* 0b7 */ + { .mk = { 0xb8, 0 }, .brk = { 0xf0, 0xb8, 0 } }, /* 0b8 */ + { .mk = { 0xb9, 0 }, .brk = { 0xf0, 0xb9, 0 } }, /* 0b9 */ + { .mk = { 0xba, 0 }, .brk = { 0xf0, 0xba, 0 } }, /* 0ba */ + { .mk = { 0xbb, 0 }, .brk = { 0xf0, 0xbb, 0 } }, /* 0bb */ + { .mk = { 0xbc, 0 }, .brk = { 0xf0, 0xbc, 0 } }, /* 0bc */ + { .mk = { 0xbd, 0 }, .brk = { 0xf0, 0xbd, 0 } }, /* 0bd */ + { .mk = { 0xbe, 0 }, .brk = { 0xf0, 0xbe, 0 } }, /* 0be */ + { .mk = { 0xbf, 0 }, .brk = { 0xf0, 0xbf, 0 } }, /* 0bf */ + { .mk = { 0xc0, 0 }, .brk = { 0xf0, 0xc0, 0 } }, /* 0c0 */ + { .mk = { 0xc1, 0 }, .brk = { 0xf0, 0xc1, 0 } }, /* 0c1 */ + { .mk = { 0xc2, 0 }, .brk = { 0xf0, 0xc2, 0 } }, /* 0c2 */ + { .mk = { 0xc3, 0 }, .brk = { 0xf0, 0xc3, 0 } }, /* 0c3 */ + { .mk = { 0xc4, 0 }, .brk = { 0xf0, 0xc4, 0 } }, /* 0c4 */ + { .mk = { 0xc5, 0 }, .brk = { 0xf0, 0xc5, 0 } }, /* 0c5 */ + { .mk = { 0xc6, 0 }, .brk = { 0xf0, 0xc6, 0 } }, /* 0c6 */ + { .mk = { 0xc7, 0 }, .brk = { 0xf0, 0xc7, 0 } }, /* 0c7 */ + { .mk = { 0xc8, 0 }, .brk = { 0xf0, 0xc8, 0 } }, /* 0c8 */ + { .mk = { 0xc9, 0 }, .brk = { 0xf0, 0xc9, 0 } }, /* 0c9 */ + { .mk = { 0xca, 0 }, .brk = { 0xf0, 0xca, 0 } }, /* 0ca */ + { .mk = { 0xcb, 0 }, .brk = { 0xf0, 0xcb, 0 } }, /* 0cb */ + { .mk = { 0xcc, 0 }, .brk = { 0xf0, 0xcc, 0 } }, /* 0cc */ + { .mk = { 0xcd, 0 }, .brk = { 0xf0, 0xcd, 0 } }, /* 0cd */ + { .mk = { 0xce, 0 }, .brk = { 0xf0, 0xce, 0 } }, /* 0ce */ + { .mk = { 0xcf, 0 }, .brk = { 0xf0, 0xcf, 0 } }, /* 0cf */ + { .mk = { 0xd0, 0 }, .brk = { 0xf0, 0xd0, 0 } }, /* 0d0 */ + { .mk = { 0xd1, 0 }, .brk = { 0xf0, 0xd0, 0 } }, /* 0d1 */ + { .mk = { 0xd2, 0 }, .brk = { 0xf0, 0xd2, 0 } }, /* 0d2 */ + { .mk = { 0xd3, 0 }, .brk = { 0xf0, 0xd3, 0 } }, /* 0d3 */ + { .mk = { 0xd4, 0 }, .brk = { 0xf0, 0xd4, 0 } }, /* 0d4 */ + { .mk = { 0xd5, 0 }, .brk = { 0xf0, 0xd5, 0 } }, /* 0d5 */ + { .mk = { 0xd6, 0 }, .brk = { 0xf0, 0xd6, 0 } }, /* 0d6 */ + { .mk = { 0xd7, 0 }, .brk = { 0xf0, 0xd7, 0 } }, /* 0d7 */ + { .mk = { 0xd8, 0 }, .brk = { 0xf0, 0xd8, 0 } }, /* 0d8 */ + { .mk = { 0xd9, 0 }, .brk = { 0xf0, 0xd9, 0 } }, /* 0d9 */ + { .mk = { 0xda, 0 }, .brk = { 0xf0, 0xda, 0 } }, /* 0da */ + { .mk = { 0xdb, 0 }, .brk = { 0xf0, 0xdb, 0 } }, /* 0db */ + { .mk = { 0xdc, 0 }, .brk = { 0xf0, 0xdc, 0 } }, /* 0dc */ + { .mk = { 0xdd, 0 }, .brk = { 0xf0, 0xdd, 0 } }, /* 0dd */ + { .mk = { 0xde, 0 }, .brk = { 0xf0, 0xde, 0 } }, /* 0de */ + { .mk = { 0xdf, 0 }, .brk = { 0xf0, 0xdf, 0 } }, /* 0df */ + { .mk = { 0xe0, 0 }, .brk = { 0xf0, 0xe0, 0 } }, /* 0e0 */ + { .mk = { 0xe1, 0 }, .brk = { 0xf0, 0xe1, 0 } }, /* 0e1 */ + { .mk = { 0xe2, 0 }, .brk = { 0xf0, 0xe2, 0 } }, /* 0e2 */ + { .mk = { 0xe3, 0 }, .brk = { 0xf0, 0xe3, 0 } }, /* 0e3 */ + { .mk = { 0xe4, 0 }, .brk = { 0xf0, 0xe4, 0 } }, /* 0e4 */ + { .mk = { 0xe5, 0 }, .brk = { 0xf0, 0xe5, 0 } }, /* 0e5 */ + { .mk = { 0xe6, 0 }, .brk = { 0xf0, 0xe6, 0 } }, /* 0e6 */ + { .mk = { 0xe7, 0 }, .brk = { 0xf0, 0xe7, 0 } }, /* 0e7 */ + { .mk = { 0xe8, 0 }, .brk = { 0xf0, 0xe8, 0 } }, /* 0e8 */ + { .mk = { 0xe9, 0 }, .brk = { 0xf0, 0xe9, 0 } }, /* 0e9 */ + { .mk = { 0xea, 0 }, .brk = { 0xf0, 0xea, 0 } }, /* 0ea */ + { .mk = { 0xeb, 0 }, .brk = { 0xf0, 0xeb, 0 } }, /* 0eb */ + { .mk = { 0xec, 0 }, .brk = { 0xf0, 0xec, 0 } }, /* 0ec */ + { .mk = { 0xed, 0 }, .brk = { 0xf0, 0xed, 0 } }, /* 0ed */ + { .mk = { 0xee, 0 }, .brk = { 0xf0, 0xee, 0 } }, /* 0ee */ + { .mk = { 0xef, 0 }, .brk = { 0xf0, 0xef, 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0xf1, 0 }, .brk = { 0xf0, 0xf1, 0 } }, /* 0f1 */ + { .mk = { 0xf2, 0 }, .brk = { 0xf0, 0xf2, 0 } }, /* 0f2 */ + { .mk = { 0xf3, 0 }, .brk = { 0xf0, 0xf3, 0 } }, /* 0f3 */ + { .mk = { 0xf4, 0 }, .brk = { 0xf0, 0xf4, 0 } }, /* 0f4 */ + { .mk = { 0xf5, 0 }, .brk = { 0xf0, 0xf5, 0 } }, /* 0f5 */ + { .mk = { 0xf6, 0 }, .brk = { 0xf0, 0xf6, 0 } }, /* 0f6 */ + { .mk = { 0xf7, 0 }, .brk = { 0xf0, 0xf7, 0 } }, /* 0f7 */ + { .mk = { 0xf8, 0 }, .brk = { 0xf0, 0xf8, 0 } }, /* 0f8 */ + { .mk = { 0xf9, 0 }, .brk = { 0xf0, 0xf9, 0 } }, /* 0f9 */ + { .mk = { 0xfa, 0 }, .brk = { 0xf0, 0xfa, 0 } }, /* 0fa */ + { .mk = { 0xfb, 0 }, .brk = { 0xf0, 0xfb, 0 } }, /* 0fb */ + { .mk = { 0xfc, 0 }, .brk = { 0xf0, 0xfc, 0 } }, /* 0fc */ + { .mk = { 0xfd, 0 }, .brk = { 0xf0, 0xfd, 0 } }, /* 0fd */ + { .mk = { 0xfe, 0 }, .brk = { 0xf0, 0xfe, 0 } }, /* 0fe */ + { .mk = { 0xff, 0 }, .brk = { 0xf0, 0xff, 0 } }, /* 0ff */ + { .mk = {0xe1, 0x14, 0 }, .brk = { 0xe1, 0xf0, 0x14, 0 } }, /* 100 */ + { .mk = {0xe0, 0x76, 0 }, .brk = { 0xe0, 0xF0, 0x76, 0 } }, /* 101 */ + { .mk = {0xe0, 0x16, 0 }, .brk = { 0xe0, 0xF0, 0x16, 0 } }, /* 102 */ + { .mk = {0xe0, 0x1E, 0 }, .brk = { 0xe0, 0xF0, 0x1E, 0 } }, /* 103 */ + { .mk = {0xe0, 0x26, 0 }, .brk = { 0xe0, 0xF0, 0x26, 0 } }, /* 104 */ + { .mk = {0xe0, 0x25, 0 }, .brk = { 0xe0, 0xF0, 0x25, 0 } }, /* 105 */ + { .mk = {0xe0, 0x2E, 0 }, .brk = { 0xe0, 0xF0, 0x2E, 0 } }, /* 106 */ + { .mk = {0xe0, 0x36, 0 }, .brk = { 0xe0, 0xF0, 0x36, 0 } }, /* 107 */ + { .mk = {0xe0, 0x3D, 0 }, .brk = { 0xe0, 0xF0, 0x3D, 0 } }, /* 108 */ + { .mk = {0xe0, 0x3E, 0 }, .brk = { 0xe0, 0xF0, 0x3E, 0 } }, /* 109 */ + { .mk = {0xe0, 0x46, 0 }, .brk = { 0xe0, 0xF0, 0x46, 0 } }, /* 10a */ + { .mk = {0xe0, 0x45, 0 }, .brk = { 0xe0, 0xF0, 0x45, 0 } }, /* 10b */ + { .mk = {0xe0, 0x4E, 0 }, .brk = { 0xe0, 0xF0, 0x4E, 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = {0xe0, 0x66, 0 }, .brk = { 0xe0, 0xF0, 0x66, 0 } }, /* 10e */ + { .mk = {0xe0, 0x0D, 0 }, .brk = { 0xe0, 0xF0, 0x0D, 0 } }, /* 10f */ + { .mk = {0xe0, 0x15, 0 }, .brk = { 0xe0, 0xF0, 0x15, 0 } }, /* 110 */ + { .mk = {0xe0, 0x1D, 0 }, .brk = { 0xe0, 0xF0, 0x1D, 0 } }, /* 112 */ + { .mk = {0xe0, 0x24, 0 }, .brk = { 0xe0, 0xF0, 0x24, 0 } }, /* 113 */ + { .mk = {0xe0, 0x2D, 0 }, .brk = { 0xe0, 0xF0, 0x2D, 0 } }, /* 113 */ + { .mk = {0xe0, 0x2C, 0 }, .brk = { 0xe0, 0xF0, 0x2C, 0 } }, /* 114 */ + { .mk = {0xe0, 0x35, 0 }, .brk = { 0xe0, 0xF0, 0x35, 0 } }, /* 115 */ + { .mk = {0xe0, 0x3C, 0 }, .brk = { 0xe0, 0xF0, 0x3C, 0 } }, /* 116 */ + { .mk = {0xe0, 0x43, 0 }, .brk = { 0xe0, 0xF0, 0x43, 0 } }, /* 117 */ + { .mk = {0xe0, 0x44, 0 }, .brk = { 0xe0, 0xF0, 0x44, 0 } }, /* 118 */ + { .mk = {0xe0, 0x4D, 0 }, .brk = { 0xe0, 0xF0, 0x4D, 0 } }, /* 119 */ + { .mk = {0xe0, 0x54, 0 }, .brk = { 0xe0, 0xF0, 0x54, 0 } }, /* 11a */ + { .mk = {0xe0, 0x5B, 0 }, .brk = { 0xe0, 0xF0, 0x5B, 0 } }, /* 11b */ + { .mk = {0xe0, 0x5A, 0 }, .brk = { 0xe0, 0xF0, 0x5A, 0 } }, /* 11c */ + { .mk = {0xe0, 0x14, 0 }, .brk = { 0xe0, 0xF0, 0x14, 0 } }, /* 11d */ + { .mk = {0xe0, 0x1C, 0 }, .brk = { 0xe0, 0xF0, 0x1C, 0 } }, /* 11e */ + { .mk = {0xe0, 0x1B, 0 }, .brk = { 0xe0, 0xF0, 0x1B, 0 } }, /* 11f */ + { .mk = {0xe0, 0x23, 0 }, .brk = { 0xe0, 0xF0, 0x23, 0 } }, /* 120 */ + { .mk = {0xe0, 0x2B, 0 }, .brk = { 0xe0, 0xF0, 0x2B, 0 } }, /* 121 */ + { .mk = {0xe0, 0x34, 0 }, .brk = { 0xe0, 0xF0, 0x34, 0 } }, /* 122 */ + { .mk = {0xe0, 0x33, 0 }, .brk = { 0xe0, 0xF0, 0x33, 0 } }, /* 123 */ + { .mk = {0xe0, 0x3B, 0 }, .brk = { 0xe0, 0xF0, 0x3B, 0 } }, /* 124 */ + { .mk = {0xe0, 0x42, 0 }, .brk = { 0xe0, 0xF0, 0x42, 0 } }, /* 125 */ + { .mk = {0xe0, 0x4B, 0 }, .brk = { 0xe0, 0xF0, 0x4B, 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = {0xe0, 0x1A, 0 }, .brk = { 0xe0, 0xF0, 0x1A, 0 } }, /* 12c */ + { .mk = {0xe0, 0x22, 0 }, .brk = { 0xe0, 0xF0, 0x22, 0 } }, /* 12d */ + { .mk = {0xe0, 0x21, 0 }, .brk = { 0xe0, 0xF0, 0x21, 0 } }, /* 12e */ + { .mk = {0xe0, 0x2A, 0 }, .brk = { 0xe0, 0xF0, 0x2A, 0 } }, /* 12f */ + { .mk = {0xe0, 0x32, 0 }, .brk = { 0xe0, 0xF0, 0x32, 0 } }, /* 130 */ + { .mk = {0xe0, 0x31, 0 }, .brk = { 0xe0, 0xF0, 0x31, 0 } }, /* 131 */ + { .mk = {0xe0, 0x3A, 0 }, .brk = { 0xe0, 0xF0, 0x3A, 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = {0xe0, 0x49, 0 }, .brk = { 0xe0, 0xF0, 0x49, 0 } }, /* 134 */ + { .mk = {0xe0, 0x4A, 0 }, .brk = { 0xe0, 0xF0, 0x4A, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = {0xe0, 0x7C, 0 }, .brk = { 0xe0, 0xF0, 0x7C, 0 } }, /* 137 */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0xF0, 0x11, 0 } }, /* 138* 0x31 R-Alt */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xF0, 0x58, 0 } }, /* 13a */ + { .mk = {0xe0, 0x05, 0 }, .brk = { 0xe0, 0xF0, 0x05, 0 } }, /* 13b */ + { .mk = {0xe0, 0x06, 0 }, .brk = { 0xe0, 0xF0, 0x06, 0 } }, /* 13c */ + { .mk = {0xe0, 0x04, 0 }, .brk = { 0xe0, 0xF0, 0x04, 0 } }, /* 13d */ + { .mk = {0xe0, 0x0C, 0 }, .brk = { 0xe0, 0xF0, 0x0C, 0 } }, /* 13e */ + { .mk = {0xe0, 0x03, 0 }, .brk = { 0xe0, 0xF0, 0x03, 0 } }, /* 13f */ + { .mk = {0xe0, 0x0B, 0 }, .brk = { 0xe0, 0xF0, 0x0B, 0 } }, /* 140 */ + { .mk = {0xe0, 0x02, 0 }, .brk = { 0xe0, 0xF0, 0x02, 0 } }, /* 141 */ + { .mk = {0xe0, 0x0A, 0 }, .brk = { 0xe0, 0xF0, 0x0A, 0 } }, /* 142 */ + { .mk = {0xe0, 0x01, 0 }, .brk = { 0xe0, 0xF0, 0x01, 0 } }, /* 143 */ + { .mk = {0xe0, 0x09, 0 }, .brk = { 0xe0, 0xF0, 0x09, 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = {0xe0, 0x7E, 0 }, .brk = { 0xe0, 0xF0, 0x7E, 0 } }, /* 146 */ + { .mk = {0xe0, 0x6C, 0 }, .brk = { 0xe0, 0xF0, 0x6C, 0 } }, /* 147 */ + { .mk = {0xe0, 0x75, 0 }, .brk = { 0xe0, 0xF0, 0x75, 0 } }, /* 148 */ + { .mk = {0xe0, 0x7D, 0 }, .brk = { 0xe0, 0xF0, 0x7D, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = {0xe0, 0x6B, 0 }, .brk = { 0xe0, 0xF0, 0x6B, 0 } }, /* 14b */ + { .mk = {0xe0, 0x73, 0 }, .brk = { 0xe0, 0xF0, 0x73, 0 } }, /* 14c */ + { .mk = {0xe0, 0x74, 0 }, .brk = { 0xe0, 0xF0, 0x74, 0 } }, /* 14d */ + { .mk = {0xe0, 0x79, 0 }, .brk = { 0xe0, 0xF0, 0x79, 0 } }, /* 14e */ + { .mk = {0xe0, 0x69, 0 }, .brk = { 0xe0, 0xF0, 0x69, 0 } }, /* 14f */ + { .mk = {0xe0, 0x72, 0 }, .brk = { 0xe0, 0xF0, 0x72, 0 } }, /* 150 */ + { .mk = {0xe0, 0x7A, 0 }, .brk = { 0xe0, 0xF0, 0x7A, 0 } }, /* 151 */ + { .mk = {0xe0, 0x70, 0 }, .brk = { 0xe0, 0xF0, 0x70, 0 } }, /* 152 */ + { .mk = {0xe0, 0x71, 0 }, .brk = { 0xe0, 0xF0, 0x71, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = {0xe0, 0x60, 0 }, .brk = { 0xe0, 0xF0, 0x60, 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = {0xe0, 0x78, 0 }, .brk = { 0xe0, 0xF0, 0x78, 0 } }, /* 157 */ + { .mk = {0xe0, 0x07, 0 }, .brk = { 0xe0, 0xF0, 0x07, 0 } }, /* 158 */ + { .mk = {0xe0, 0x0F, 0 }, .brk = { 0xe0, 0xF0, 0x0F, 0 } }, /* 159 */ + { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0xF0, 0x17, 0 } }, /* 15a */ + { .mk = { 0x67, 0 }, .brk = { 0xf0, 0x67, 0 } }, /* 15b 0x33 LGUI->Muhenkan (in emulator only) */ + { .mk = { 0x64, 0 }, .brk = { 0xf0, 0x64, 0 } }, /* 15c 0x35 RGUI->Henkan (in emulator only) */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0xf0, 0x11, 0 } }, /* 15d 0x36 APPLICATION->Kana (in emulator + { .mk = {0xe0, 0x37, 0 }, .brk = { 0xe0, 0xF0, 0x37, 0 } }, /* 15e */ + { .mk = {0xe0, 0x3F, 0 }, .brk = { 0xe0, 0xF0, 0x3F, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = {0xe0, 0x4F, 0 }, .brk = { 0xe0, 0xF0, 0x4F, 0 } }, /* 161 */ + { .mk = {0xe0, 0x56, 0 }, .brk = { 0xe0, 0xF0, 0x56, 0 } }, /* 162 */ + { .mk = {0xe0, 0x5E, 0 }, .brk = { 0xe0, 0xF0, 0x5E, 0 } }, /* 163 */ + { .mk = {0xe0, 0x08, 0 }, .brk = { 0xe0, 0xF0, 0x08, 0 } }, /* 164 */ + { .mk = {0xe0, 0x10, 0 }, .brk = { 0xe0, 0xF0, 0x10, 0 } }, /* 165 */ + { .mk = {0xe0, 0x18, 0 }, .brk = { 0xe0, 0xF0, 0x18, 0 } }, /* 166 */ + { .mk = {0xe0, 0x20, 0 }, .brk = { 0xe0, 0xF0, 0x20, 0 } }, /* 167 */ + { .mk = {0xe0, 0x28, 0 }, .brk = { 0xe0, 0xF0, 0x28, 0 } }, /* 168 */ + { .mk = {0xe0, 0x30, 0 }, .brk = { 0xe0, 0xF0, 0x30, 0 } }, /* 169 */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xF0, 0x38, 0 } }, /* 16a */ + { .mk = {0xe0, 0x40, 0 }, .brk = { 0xe0, 0xF0, 0x40, 0 } }, /* 16b */ + { .mk = {0xe0, 0x48, 0 }, .brk = { 0xe0, 0xF0, 0x48, 0 } }, /* 16c */ + { .mk = {0xe0, 0x50, 0 }, .brk = { 0xe0, 0xF0, 0x50, 0 } }, /* 16d */ + { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xF0, 0x57, 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = {0xe0, 0x13, 0 }, .brk = { 0xe0, 0xF0, 0x13, 0 } }, /* 170 */ + { .mk = {0xe0, 0x19, 0 }, .brk = { 0xe0, 0xF0, 0x19, 0 } }, /* 171 */ + { .mk = {0xe0, 0x39, 0 }, .brk = { 0xe0, 0xF0, 0x39, 0 } }, /* 172 */ + { .mk = {0xe0, 0x51, 0 }, .brk = { 0xe0, 0xF0, 0x51, 0 } }, /* 173 */ + { .mk = {0xe0, 0x53, 0 }, .brk = { 0xe0, 0xF0, 0x53, 0 } }, /* 174 */ + { .mk = {0xe0, 0x5C, 0 }, .brk = { 0xe0, 0xF0, 0x5C, 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = {0xe0, 0x62, 0 }, .brk = { 0xe0, 0xF0, 0x62, 0 } }, /* 177 */ + { .mk = {0xe0, 0x63, 0 }, .brk = { 0xe0, 0xF0, 0x63, 0 } }, /* 178 */ + { .mk = {0xe0, 0x64, 0 }, .brk = { 0xe0, 0xF0, 0x64, 0 } }, /* 179 */ + { .mk = {0xe0, 0x65, 0 }, .brk = { 0xe0, 0xF0, 0x65, 0 } }, /* 17a */ + { .mk = {0xe0, 0x67, 0 }, .brk = { 0xe0, 0xF0, 0x67, 0 } }, /* 17b */ + { .mk = {0xe0, 0x68, 0 }, .brk = { 0xe0, 0xF0, 0x68, 0 } }, /* 17c */ + { .mk = {0xe0, 0x6A, 0 }, .brk = { 0xe0, 0xF0, 0x6A, 0 } }, /* 17d */ + { .mk = {0xe0, 0x6D, 0 }, .brk = { 0xe0, 0xF0, 0x6D, 0 } }, /* 17e */ + { .mk = {0xe0, 0x6E, 0 }, .brk = { 0xe0, 0xF0, 0x6E, 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cv */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = {0xe0, 0xe1, 0 }, .brk = { 0xe0, 0xF0, 0xE1, 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = {0xe0, 0xee, 0 }, .brk = { 0xe0, 0xF0, 0xEE, 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = {0xe0, 0xf1, 0 }, .brk = { 0xe0, 0xF0, 0xF1, 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = {0xe0, 0xfe, 0 }, .brk = { 0xe0, 0xF0, 0xFE, 0 } }, /* 1fe */ + { .mk = {0xe0, 0xff, 0 }, .brk = { 0xe0, 0xF0, 0xFF, 0 } } /* 1ff */ + // clang-format on +}; /* Scancode set 8Ah : IBM 5556 keyboard compatible scancode set used by J-DOS */ static scancode scancode_set8a[512] = { @@ -1700,9 +2735,9 @@ static scancode scancode_set8a[512] = {.mk = { 0x14, 0 }, .brk = { 0 } }, /* 026 */ {.mk = { 0x15, 0 }, .brk = { 0 } }, /* 027 */ {.mk = { 0x16, 0 }, .brk = { 0 } }, /* 028* */ - {.mk = { 0x45, 0 }, .brk = { 0 } }, /* 029 Hankaku, Zenkaku */ + {.mk = { 0x45, 0 }, .brk = { 0 } }, /* 029 0x45 Hankaku, Zenkaku */ {.mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 02a LSHIFT */ - {.mk = { 0x17, 0 }, .brk = { 0 } }, /* 02b Mu */ + {.mk = { 0x17, 0 }, .brk = { 0 } }, /* 02b 0x17 Mu */ {.mk = { 0x01, 0 }, .brk = { 0 } }, /* 02c */ {.mk = { 0x02, 0 }, .brk = { 0 } }, /* 02d */ {.mk = { 0x03, 0 }, .brk = { 0 } }, /* 02e */ @@ -1715,7 +2750,7 @@ static scancode scancode_set8a[512] = {.mk = { 0x0a, 0 }, .brk = { 0 } }, /* 035 */ {.mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 036 RSHIFT */ {.mk = { 0x64, 0 }, .brk = { 0 } }, /* 037 * (asterisk) */ - {.mk = { 0x3A, 0 }, .brk = { 0xba, 0 } }, /* 038 LALT = Kanji */ + {.mk = { 0x3A, 0 }, .brk = { 0xba, 0 } }, /* 038 0x3A LALT = Kanji */ {.mk = { 0x34, 0 }, .brk = { 0 } }, /* 039 */ {.mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 03a CAPSLOCK */ {.mk = { 0x68, 0 }, .brk = { 0 } }, /* 03b F1 */ @@ -1728,8 +2763,8 @@ static scancode scancode_set8a[512] = {.mk = { 0x6f, 0 }, .brk = { 0 } }, /* 042 */ {.mk = { 0x70, 0 }, .brk = { 0 } }, /* 043 */ {.mk = { 0x71, 0 }, .brk = { 0 } }, /* 044 F10 */ - {.mk = { 0 }, .brk = { 0 } }, /* 045 NUMLOCKCLEAR -> Shift + SCRLOCK :TODO */ - {.mk = { 0x75, 0 }, .brk = { 0 } }, /* 046 SCROLLLOCK */ + {.mk = { 0x47, 0 }, .brk = { 0 } }, /* 045 NUMLOCKCLEAR -> Shift + SCRLOCK :TODO */ + {.mk = { 0x75, 0 }, .brk = { 0 } }, /* 046 0x75 SCROLLLOCK */ {.mk = { 0x5d, 0 }, .brk = { 0 } }, /* 047 KP7 */ {.mk = { 0x5e, 0 }, .brk = { 0 } }, /* 048 */ {.mk = { 0x5f, 0 }, .brk = { 0 } }, /* 049 */ @@ -1771,20 +2806,20 @@ static scancode scancode_set8a[512] = {.mk = { 0 }, .brk = { 0 } }, /* 06d */ {.mk = { 0 }, .brk = { 0 } }, /* 06e */ {.mk = { 0 }, .brk = { 0 } }, /* 06f */ - {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 070 Kana */ + {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 070 0x36 Kana */ {.mk = { 0 }, .brk = { 0 } }, /* 071 */ {.mk = { 0 }, .brk = { 0 } }, /* 072 */ - {.mk = { 0x0b, 0 }, .brk = { 0 } }, /* 073 Ro, Underline */ + {.mk = { 0x0b, 0 }, .brk = { 0 } }, /* 073 0x0b Ro, Underline */ {.mk = { 0 }, .brk = { 0 } }, /* 074 */ {.mk = { 0 }, .brk = { 0 } }, /* 075 */ {.mk = { 0 }, .brk = { 0 } }, /* 076 */ {.mk = { 0 }, .brk = { 0 } }, /* 077 */ {.mk = { 0 }, .brk = { 0 } }, /* 078 */ - {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 079 Henkan */ + {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 079 0x35 Henkan */ {.mk = { 0 }, .brk = { 0 } }, /* 07a */ - {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 07b Muhenkan */ + {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 07b 0x33 Muhenkan */ {.mk = { 0 }, .brk = { 0 } }, /* 07c */ - {.mk = { 0x30, 0 }, .brk = { 0 } }, /* 07d Yen, Vertical line */ + {.mk = { 0x30, 0 }, .brk = { 0 } }, /* 07d 0x30 Yen, Vertical line */ {.mk = { 0 }, .brk = { 0 } }, /* 07e */ {.mk = { 0 }, .brk = { 0 } }, /* 07f */ {.mk = { 0 }, .brk = { 0 } }, /* 080 */ @@ -1915,7 +2950,7 @@ static scancode scancode_set8a[512] = {.mk = { 0 }, .brk = { 0 } }, /* 0fd */ {.mk = { 0 }, .brk = { 0 } }, /* 0fe */ {.mk = { 0 }, .brk = { 0 } }, /* 0ff */ - {.mk = { 0x47, 0 }, .brk = { 0 } }, /* 100 Pause */ + {.mk = { 0 }, .brk = { 0 } }, /* 100 */ {.mk = { 0 }, .brk = { 0 } }, /* 101 */ {.mk = { 0 }, .brk = { 0 } }, /* 102 */ {.mk = { 0 }, .brk = { 0 } }, /* 103 */ @@ -1971,7 +3006,7 @@ static scancode scancode_set8a[512] = {.mk = { 0x65, 0 }, .brk = { 0 } }, /* 135 KP_DIVIDE */ {.mk = { 0 }, .brk = { 0 } }, /* 136 */ {.mk = { 0x74, 0 }, .brk = { 0 } }, /* 137 PRINTSCREEN */ - {.mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 138* R-Alt */ + {.mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 138* 0x31 R-Alt */ {.mk = { 0 }, .brk = { 0 } }, /* 139 */ {.mk = { 0 }, .brk = { 0 } }, /* 13a */ {.mk = { 0 }, .brk = { 0 } }, /* 13b */ @@ -2006,9 +3041,9 @@ static scancode scancode_set8a[512] = {.mk = { 0 }, .brk = { 0 } }, /* 158 */ {.mk = { 0 }, .brk = { 0 } }, /* 159 */ {.mk = { 0 }, .brk = { 0 } }, /* 15a */ - {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 15b LGUI->Muhenkan (in emulator only) */ - {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 15c RGUI->Henkan (in emulator only) */ - {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 15d APPLICATION->Kana (in emulator only) */ + {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 15b 0x33 LGUI->Muhenkan (in emulator only) */ + {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 15c 0x35 RGUI->Henkan (in emulator only) */ + {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 15d 0x36 APPLICATION->Kana (in emulator only) */ {.mk = { 0 }, .brk = { 0 } }, /* 15e */ {.mk = { 0 }, .brk = { 0 } }, /* 15f */ {.mk = { 0 }, .brk = { 0 } }, /* 160 */ @@ -2173,7 +3208,7 @@ static scancode scancode_set8a[512] = {.mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; - +#define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -2209,6 +3244,14 @@ keyboard_at_set_scancode_set(void) keyboard_set_table(scancode_set3); break; + case 0x81: + keyboard_set_table(scancode_set81); + break; + + case 0x82: + keyboard_set_table(scancode_set82); + break; + case 0x8a: keyboard_set_table(scancode_set8a); break; @@ -2477,6 +3520,8 @@ keyboard_at_write(void *priv) kbc_at_dev_queue_add(dev, keyboard_mode, 0); break; case 0x01 ... 0x03: + case 0x81: + case 0x82: case 0x8a: kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK */ keyboard_mode = val; @@ -2560,7 +3605,7 @@ keyboard_at_write(void *priv) break; case 0xf2: /* read ID */ - keyboard_at_log("%s: read keyboard id\n", dev->name); + keyboard_at_log("%s: read keyboard id: ", dev->name); /* TODO: After keyboard type selection is implemented, make this return the correct keyboard ID for the selected type. */ kbc_at_dev_queue_add(dev, 0xfa, 0); @@ -2569,7 +3614,9 @@ keyboard_at_write(void *priv) break; kbc_at_dev_queue_add(dev, id_bytes[dev->type][i], 0); + keyboard_at_log("%02X ", id_bytes[dev->type][i]); } + keyboard_at_log("\n"); break; case 0xf3: /* set command mode */ @@ -2694,7 +3741,8 @@ keyboard_at_init(const device_t *info) Key 63 = Japanese key between right Ctrl and right Alt, scan code: 86 (Henkan/Zenkouho 79); Key 65? = Japanese key between right Ctrl and right Alt, scan code: 87 (Hiragana/Katakana 70). */ - dev->type = FLAG_PS2 | KBD_102_KEY /* device_get_config_int("type") */; + // dev->type = FLAG_PS2 | KBD_102_KEY /* device_get_config_int("type") */; + dev->type = FLAG_PS2 | KBD_JIS; keyboard_at_log("%s: type=%d\n", dev->name, dev->type); From 4042fd15fb9dcf5b59d6d916ef3f05c3c3db50c1 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:03:39 +0900 Subject: [PATCH 0330/1190] DA2 skip recalctimings if output is disabled --- src/video/vid_ps55da2.c | 83 ++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f81a62ffe..31559cc52 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1075,14 +1075,10 @@ da2_out(uint16_t addr, uint16_t val, void *p) if (oldval != val) { if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ da2_reset_ioctl(da2); - else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ - { + else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) { /* Mode register */ da2->fullchange = changeframecount; da2_recalctimings(da2); da2_updatevidselector(da2); - } else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ - { - // da2->bitblt.indata = 1; } } break; @@ -1117,7 +1113,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) // return; break; case LC_MAXIMUM_SCAN_LINE: - if (!(da2->ioctl[LS_MODE] & 0x01)) + if (!(da2->ioctl[LS_MODE] & 0x01)) /* 16 or 256 color graphics mode */ val = 0; break; case LC_START_ADDRESS_HIGH: @@ -2035,14 +2031,15 @@ da2_render_color_8bpp(da2_t *da2) void da2_updatevidselector(da2_t *da2) { - da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); if (da2->ioctl[LS_MODE] & 0x02) { /* VGA passthrough mode */ da2->override = 1; svga_set_override(da2->mb_vga, 0); + da2_log("DA2 selector: VGA\n"); } else { svga_set_override(da2->mb_vga, 1); da2->override = 0; + da2_log("DA2 selector: DA2\n"); } } @@ -2051,6 +2048,10 @@ da2_recalctimings(da2_t *da2) { double crtcconst; double _dispontime, _dispofftime, disptime; + + /* if output disabled or VGA passthrough */ + if (!(da2->attrc[LV_COMPATIBILITY] & 0x08) || da2->ioctl[LS_MODE] & 0x02) + return; da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; @@ -2092,40 +2093,36 @@ da2_recalctimings(da2_t *da2) da2->render = da2_render_blank; /* determine display mode */ // if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - if (da2->attrc[LV_COMPATIBILITY] & 0x08) { - /* 16 color graphics mode */ - 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_GRAM; - } else { /* PS/55 8-color */ - da2_log("Set videomode to PS/55 4 bpp graphics.\n"); - da2->vram_display_mask = DA2_MASK_GRAM; - da2->render = da2_render_color_4bpp; - } - } else { - /* text mode */ - if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { - da2_log("Set videomode to PS/55 Mode 03 text.\n"); - da2->render = da2_render_textm3; - da2->vram_display_mask = DA2_MASK_CRAM; - } - /* PS/55 text(color/mono) */ - else { - da2_log("Set videomode to PS/55 Mode 8/E text.\n"); - da2->render = da2_render_text; - da2->vram_display_mask = DA2_MASK_CRAM; - } - da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; - da2->char_width = 13; + /* 16 color graphics mode */ + 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_GRAM; + } else { /* PS/55 8-color */ + da2_log("Set videomode to PS/55 4 bpp graphics.\n"); + da2->vram_display_mask = DA2_MASK_GRAM; + da2->render = da2_render_color_4bpp; } } else { - da2_log("Set videomode to blank.\n"); + /* text mode */ + if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { + da2_log("Set videomode to PS/55 Mode 03 text.\n"); + da2->render = da2_render_textm3; + da2->vram_display_mask = DA2_MASK_CRAM; + } + /* PS/55 text(color/mono) */ + else { + da2_log("Set videomode to PS/55 Mode 8/E text.\n"); + da2->render = da2_render_text; + 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) //{ @@ -2344,7 +2341,7 @@ da2_mmio_read(uint32_t addr, void *p) return DA2_INVALIDACCESS8; /* invalid memory access */ break; } - } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 or 256 color mode */ cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ @@ -2371,7 +2368,7 @@ da2_mmio_readw(uint32_t addr, void *p) //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 16 color or 256 color mode */ { cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; @@ -2458,7 +2455,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); break; } - } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; /* align bitmask to even address */ if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; @@ -2681,7 +2678,7 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); - } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ addr &= DA2_MASK_MMIO; // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); From 0b97701e7a43ba1162c15f80bf0a8f1c31ce9ace Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:53:44 +0900 Subject: [PATCH 0331/1190] add keyboard ID switcher for PS/55 --- src/device/keyboard_at.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index d44833dd3..d04ab07e9 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -25,6 +25,7 @@ #include <86box/device.h> #include <86box/keyboard.h> #include <86box/mouse.h> +#include <86box/machine.h> #define FLAG_PS2 0x08 /* dev is AT or PS/2 */ #define FLAG_AT 0x00 /* dev is AT or PS/2 */ @@ -1639,14 +1640,14 @@ static const scancode scancode_set3[512] = { 5576 keyboards kept 101-key compatible scancode sets because PS/55 had to support western (PS/2) versions of operating systems. The default scancode set is 2. In Japanese DOS, the keyboard driver confirms its keyboard ID, and sends a command to switch the scancode set to 8Ah. - Japanese OS/2 and Windows use the scancode set 82h. + Japanese OS/2 and Windows use the scancode set 81h or 82h. - The OADG standard (1991-) and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. + The OADG standard (1991-) and modern Japanese keyboards use the same keyboard ID and scancode set ID as PS/2 keyboards use. Three extra scancode sets are no longer available. Instead, language input keys are available in scancode set 1 and 2. However, their physical key layout is a bit-paired layout. Users have to choose the correct keyboard layout on setup, and the driver needs to remap keys. - Currently, scancode set 81h and 82h are not implemented yet. Also, the key layout is designed to match with the Japanese keyboard. + Currently, the key mapping is designed to match with the Japanese layout keyboard. [Japanese DOS and keyboard scancode set comparison] | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | DOS 5(US)| @@ -3208,7 +3209,7 @@ static scancode scancode_set8a[512] = {.mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; -#define ENABLE_KEYBOARD_AT_LOG 1 + #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -3741,8 +3742,14 @@ keyboard_at_init(const device_t *info) Key 63 = Japanese key between right Ctrl and right Alt, scan code: 86 (Henkan/Zenkouho 79); Key 65? = Japanese key between right Ctrl and right Alt, scan code: 87 (Hiragana/Katakana 70). */ - // dev->type = FLAG_PS2 | KBD_102_KEY /* device_get_config_int("type") */; - dev->type = FLAG_PS2 | KBD_JIS; + dev->type = FLAG_PS2 | KBD_102_KEY /* device_get_config_int("type") */; + /* + We assume that the IBM PS/55 machine uses the 5576-002 keyboard (JP/CN layout) here. + This is not smart but suitable for supporting a keyboard ID that is rarely used in standard PCs. + At least, the Taiwanese PS/55 uses the same keyboard ID and scancode set. The Korean one is unknown. + */ + if (!!strstr(machine_getname(), "PS/55")) + dev->type = FLAG_PS2 | KBD_JIS; keyboard_at_log("%s: type=%d\n", dev->name, dev->type); From d70f43828c86d72258a2d5737531e3a94b45ab73 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Feb 2025 05:12:54 +0900 Subject: [PATCH 0332/1190] replace magic numbers with predifined macros --- src/video/vid_ps55da2.c | 46 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 31559cc52..a517b7e6c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -54,9 +54,14 @@ #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_VM03_BASECHR 0x18000 +#define DA2_VM03_BASEEXATTR 0x10000 #define DA2_INVALIDACCESS8 0xff #define DA2_MASK_MMIO 0x1ffff -#define DA2_MASK_GRAM 0x1ffff +#define DA2_SIZE_VRAM 1024 * 1024 /* 0x100000 */ +#define DA2_SIZE_CRAM 4 * 1024 /* 0x1000 */ +#define DA2_SIZE_GAIJIRAM 256 * 1024 /* 0x40000 */ +#define DA2_MASK_A000 0x1ffff #define DA2_MASK_CRAM 0xfff #define DA2_MASK_GAIJIRAM 0x3ffff #define DA2_PIXELCLOCK 58000000.0 @@ -243,7 +248,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 @@ -370,7 +375,7 @@ typedef struct da2_t { { int enable; mem_mapping_t mapping; - uint8_t ram[256 * 1024]; + uint8_t ram[DA2_SIZE_GAIJIRAM]; uint8_t *font; int charset; } mmio; @@ -1855,10 +1860,10 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; - extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; - // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + chr = da2->vram[(DA2_VM03_BASECHR + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((DA2_VM03_BASECHR + (da2->ma)) + 1) & da2->vram_mask]; + extattr = da2->vram[((DA2_VM03_BASEEXATTR + (da2->ma)) + 1) & da2->vram_mask]; + // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; // fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; @@ -1875,7 +1880,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs = da2->vram[(DA2_VM03_BASECHR + (da2->ma) + 2) & da2->vram_mask]; chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -1887,11 +1892,9 @@ da2_render_textm3(da2_t *da2) } } else { /* the char code is SBCS (ANK) */ - uint32_t fontbase; - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ + uint16_t font = da2->mmio.ram[DA2_GAIJIRAM_SBCS + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + font |= da2->mmio.ram[DA2_GAIJIRAM_SBCS+ chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2101,10 +2104,10 @@ da2_recalctimings(da2_t *da2) 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_GRAM; + 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_GRAM; + da2->vram_display_mask = DA2_MASK_A000; da2->render = da2_render_color_4bpp; } } else { @@ -3029,12 +3032,11 @@ da2_init(UNUSED(const device_t *info)) da2->dispontime = 1000ull << 32; da2->dispofftime = 1000ull << 32; - int memsize = 1024 * 1024; - da2->vram = calloc(1, memsize); - da2->vram_mask = memsize - 1; - da2->cram = calloc(1, 0x1000); + da2->vram = calloc(1, DA2_SIZE_VRAM); + da2->vram_mask = DA2_SIZE_VRAM - 1; + da2->cram = calloc(1, DA2_SIZE_CRAM); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ + da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ DA2_SIZE_VRAM >> 12); /* XX000h */ da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ da2->mmio.charset = device_get_config_int("charset"); @@ -3095,17 +3097,17 @@ da2_close(void *p) FILE *f; f = fopen("da2_cram.dmp", "wb"); if (f != NULL) { - fwrite(da2->cram, 0x1000, 1, f); + fwrite(da2->cram, DA2_SIZE_CRAM, 1, f); fclose(f); } f = fopen("da2_vram.dmp", "wb"); if (f != NULL) { - fwrite(da2->vram, 1024 * 1024, 1, f); + fwrite(da2->vram, DA2_SIZE_VRAM, 1, f); fclose(f); } f = fopen("da2_gram.dmp", "wb"); if (f != NULL) { - fwrite(da2->mmio.ram, 256 * 1024, 1, f); + fwrite(da2->mmio.ram, DA2_SIZE_GAIJIRAM, 1, f); fclose(f); } f = fopen("da2_attrpal.dmp", "wb"); From 4bc47894de81c995c36592b2a1eeafb59e9846c1 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Feb 2025 05:53:34 +0900 Subject: [PATCH 0333/1190] safety read/write vram memory --- src/video/vid_ps55da2.c | 112 ++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a517b7e6c..7c7891926 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -437,12 +437,19 @@ typedef struct { /* safety read for internal functions */ uint32_t -DA2_readvram_s(uint32_t addr, da2_t *da2) +DA2_vram_r(uint32_t addr, da2_t *da2) { if (addr & ~da2->vram_mask) return -1; return da2->vram[addr]; } +/* safety write for internal functions */ +void +DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) +{ + da2->vram[addr & da2->vram_mask] = val; + return; +} void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) @@ -455,10 +462,10 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s destaddr <<= 3; /* read destination data with big endian order */ for (int i = 0; i < 8; i++) - writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) - | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + writepx[i] = DA2_vram_r((destaddr + 24) | i, da2) + | (DA2_vram_r((destaddr + 16) | i, da2) << 8) + | (DA2_vram_r((destaddr + 8) | i, da2) << 16) + | (DA2_vram_r((destaddr + 0) | i, da2) << 24); DA2_VidSeq32 mask32in; mask32in.d = (uint32_t) mask; @@ -487,8 +494,8 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s } } for (int i = 0; i < 8; i++) { - da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; - da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; + DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); + DA2_vram_w((destaddr + 8) | i, (writepx[i] >> 16) & 0xff, da2); } } @@ -531,10 +538,10 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, srcaddr &= 0xfffffffe; srcaddr <<= 3; for (int i = 0; i < 8; i++) - srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) - | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24); + srcpx.p8[i] = DA2_vram_r((srcaddr + 24) | i, da2) + | (DA2_vram_r((srcaddr + 16) | i, da2) << 8) + | (DA2_vram_r((srcaddr + 8) | i, da2) << 16) + | (DA2_vram_r((srcaddr + 0) | i, da2) << 24); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -560,7 +567,7 @@ pixel1tohex(uint32_t addr, int index, da2_t *da2) { uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { - if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) + if (DA2_vram_r(((addr << 3) | j) & (1 << (7 - index)), da2)) pixeldata++; } return pixeldata; @@ -1724,8 +1731,8 @@ da2_render_text(da2_t *da2) int chr_wide = 0; // 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->vram_display_mask]; - attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; + 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 */ { /* --Parse attribute byte in color mode-- */ @@ -1860,9 +1867,9 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = da2->vram[(DA2_VM03_BASECHR + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((DA2_VM03_BASECHR + (da2->ma)) + 1) & da2->vram_mask]; - extattr = da2->vram[((DA2_VM03_BASEEXATTR + (da2->ma)) + 1) & da2->vram_mask]; + chr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma), da2); + attr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 1, da2); + extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + (da2->ma) + 1, da2); // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; @@ -1880,7 +1887,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->vram[(DA2_VM03_BASECHR + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 2, da2); chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -2116,9 +2123,7 @@ da2_recalctimings(da2_t *da2) da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; - } - /* PS/55 text(color/mono) */ - else { + } else { /* PS/55 text(color/mono) */ da2_log("Set videomode to PS/55 Mode 8/E text.\n"); da2->render = da2_render_text; da2->vram_display_mask = DA2_MASK_CRAM; @@ -2243,19 +2248,19 @@ da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) case 0: /*Set*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->gdcsrc[i] & ~bitmask); // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 1: /*AND*/ // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 2: /*OR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 3: /*XOR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; } } @@ -2273,30 +2278,30 @@ da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) case 0: /*Set*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 1: /*AND*/ // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 2: /*OR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 3: /*XOR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; } } @@ -2359,7 +2364,6 @@ da2_mmio_read(uint32_t addr, void *p) } else return da2->gdcla[da2->readplane]; } else { /* text mode 3 */ - cycles -= video_timing_read_b; return da2->vram[addr]; } @@ -2371,8 +2375,7 @@ da2_mmio_readw(uint32_t addr, void *p) //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 16 color or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) {/* 16 color or 256 color mode */ cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) @@ -2417,8 +2420,8 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; // da2_log("da2_mmio_write %x %x\n", addr, val); - if ((addr & ~DA2_MASK_MMIO) != 0xA0000) - return; + // if ((addr & ~DA2_MASK_MMIO) != 0xA0000) + // return; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { @@ -2434,8 +2437,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } switch (da2->fctl[LF_MMIO_MODE]) { case 0xb0: /* Gaiji RAM 1011 0000 */ - addr &= DA2_MASK_GAIJIRAM; /* safety access */ - da2->mmio.ram[addr] = val; + da2->mmio.ram[addr & DA2_MASK_GAIJIRAM] = val; break; case 0x10: /* Font ROM 0001 0000 */ /* Read-Only */ @@ -2509,7 +2511,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = da2->gdcsrc[i]; + DA2_vram_w(addr | i, da2->gdcsrc[i], da2); break; case 0:/* equiv to vga write mode 0 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) @@ -2517,7 +2519,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = val; + DA2_vram_w(addr | i, val, da2); } else { for (int i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) @@ -2537,7 +2539,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + 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++) @@ -2559,7 +2561,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) // 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[addr] = val; + DA2_vram_w(addr, val, da2); da2->fullchange = 2; } } @@ -2622,8 +2624,8 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) case 2: for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { - da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; - da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + DA2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); + DA2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); } break; case 0: @@ -2632,8 +2634,8 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { - da2->vram[addr | i] = val & 0xff; - da2->vram[(addr + 8) | i] = val >> 8; + DA2_vram_w(addr | i, val & 0xff, da2); + DA2_vram_w((addr + 8) | i, val >> 8, da2); } } else { for (int i = 0; i < 8; i++) @@ -2649,9 +2651,9 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - da2->vram[addr | i] = wdata & 0xff; - da2->vram[(addr + 8) | i] = wdata >> 8; + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + DA2_vram_w(addr | i, wdata & 0xff, da2); + DA2_vram_w((addr + 8) | i, wdata >> 8, da2); } } else { for (int i = 0; i < 8; i++) From 50300a1d9a949ccfb59b2b00a8bd9b794c802527 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:08:12 +0900 Subject: [PATCH 0334/1190] Add line drawing function (incomplete) remains a bug that the second hand doesn't appear in the Clock app of Windows 3.1. --- src/video/vid_ps55da2.c | 163 ++++++++++++++++++++++++++++++++++------ 1 file changed, 138 insertions(+), 25 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 7c7891926..f157d8fca 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -87,8 +87,9 @@ #define DA2_BLT_CCOPYF 3 #define DA2_BLT_CCOPYR 4 #define DA2_BLT_CPUTCHAR 5 -#define DA2_BLT_CDONE 6 -#define DA2_BLT_CLOAD 7 +#define DA2_BLT_CLINE 6 +#define DA2_BLT_CDONE 7 +#define DA2_BLT_CLOAD 8 /* POS ID = 0xeffe : Display Adapter II, III, V */ #define DA2_POSID_H 0xef #define DA2_POSID_L 0xfe @@ -253,7 +254,9 @@ #ifdef ENABLE_DA2_LOG # define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 +// # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; static void @@ -388,6 +391,7 @@ typedef struct da2_t { #ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug int debug_reg_ip; // for debug + int debug_exesteps; #endif int payload_addr; pc_timer_t timer; @@ -398,14 +402,20 @@ typedef struct da2_t { int32_t srcaddr; int32_t size_x, tile_w; int32_t size_y; + int32_t dest_x; + int32_t dest_y; int16_t destpitch; int16_t srcpitch; int32_t fcolor; int32_t maskl, maskr; + int32_t count; + // int32_t countj; + int32_t d; + int octdir; int x, y; } bitblt; -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM FILE *mmdbg_fp; FILE *mmrdbg_fp; uint32_t mmdbg_vidaddr; @@ -520,7 +530,7 @@ Param Desc 0A Plane Mask? 0B ROP?(8h or 200h + 0-3h) 0D -20 Exec (1) +20 Exec (1) or Exec without reset regs (21h) 21 ? 22 ? 23 Tile W @@ -718,6 +728,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.debug_reg_ip++; if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; + da2->bitblt.debug_exesteps = 0; #endif da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ @@ -749,11 +760,14 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ - { - da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); - da2->bitblt.exec = DA2_BLT_CDONE; - } else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + // if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ + // { + // da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); + // da2->bitblt.exec = DA2_BLT_CDONE; + // } else + + /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ + if (da2->bitblt.reg[0x10] == 0xbc04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ // if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ @@ -776,7 +790,9 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif - } else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + } + /* Put SBCS char used by OS/2 */ + else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; @@ -792,7 +808,36 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif } - /* Fill a rectangle(or draw a line) */ + /* Draw a line */ + else if (da2->bitblt.reg[0x5] == 0x43) { + // da2_log("drawline x=%d, y=%d, 24=%d, 2A=%d, 2B=%d, 2D=%d\n", + // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + // n24, n2a, n2b, da2->bitblt.reg[0x2D]); + da2->bitblt.exec = DA2_BLT_CLINE; + da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff); + da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff); + da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff)); + da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff)); + // da2->bitblt.raster_op = 0; + da2->bitblt.count = 0; + da2->bitblt.octdir = da2->bitblt.reg[0x2D]; + da2->bitblt.bitshift_destr = 0; + if (da2->bitblt.octdir & 0x04) /* dX > dY */ + da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x; + else + da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y; + da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n", + da2->bitblt.dest_x, da2->bitblt.dest_y, + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); + // FILE *f = fopen("da2_drawline.csv", "a"); + // if (f != NULL) { + // fprintf(f,"drawline,%d,%d,%d,%d,%d,%d\n", + // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + // n24, n2a, n2b, da2->bitblt.reg[0x2D]); + // fclose(f); + // } + } + /* Fill a rectangle (or draw a horizontal / vertical line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), @@ -824,7 +869,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - /* Block transfer (range copy) */ + /* Block copy */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; @@ -855,7 +900,13 @@ da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); +#ifdef ENABLE_DA2_DEBUGBLT + if(!(da2->bitblt.debug_exesteps & 0xf)) + da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); + da2->bitblt.debug_exesteps++; +#else da2_log("bitblt_exec: %d\n", da2->bitblt.exec); +#endif // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: @@ -865,6 +916,60 @@ da2_bitblt_exec(void *p) da2->bitblt.indata = 0; da2_bitblt_load(da2); break; + case DA2_BLT_CLINE: + int pos_x = da2->bitblt.dest_x + da2->bitblt.x; + int pos_y = da2->bitblt.dest_y + da2->bitblt.y; + + /* Draw a dot */ + // outb(0x680, da2->bitblt.octdir); + // da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; + int pixelmask = pos_x % 16; + if (pixelmask >= 8) + pixelmask = (0x8000 >> (pixelmask - 8)); + else + pixelmask = (0x80 >> pixelmask); + DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); + // da2_log("draw: %x %x %x\n", destaddr, da2->bitblt.fcolor, pixelmask); + da2->bitblt.count++; + + /* Bresenham's line */ + if (da2->bitblt.octdir & 0x04) { /* dX > dY */ + if (da2->bitblt.octdir & 0x02) { + da2->bitblt.x++; + } else { + da2->bitblt.x--; + } + if (da2->bitblt.d >= 0) { + da2->bitblt.d -= (2 * da2->bitblt.size_x); + if (da2->bitblt.octdir & 0x01) { + da2->bitblt.y++; + } else { + da2->bitblt.y--; + } + } + da2->bitblt.d += (2 * da2->bitblt.size_y); + if (da2->bitblt.count >= da2->bitblt.size_x) + da2->bitblt.exec = DA2_BLT_CDONE; + } else { + if (da2->bitblt.octdir & 0x01) { + da2->bitblt.y++; + } else { + da2->bitblt.y--; + } + if (da2->bitblt.d >= 0) { + da2->bitblt.d -= (2 * da2->bitblt.size_y); + if (da2->bitblt.octdir & 0x02) { + da2->bitblt.x++; + } else { + da2->bitblt.x--; + } + } + da2->bitblt.d += (2 * da2->bitblt.size_x); + if (da2->bitblt.count >= da2->bitblt.size_y) + da2->bitblt.exec = DA2_BLT_CDONE; + } + break; case DA2_BLT_CFILLRECT: // da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); if (da2->bitblt.x >= da2->bitblt.size_x - 1) { @@ -982,11 +1087,14 @@ da2_bitblt_exec(void *p) // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; break; case DA2_BLT_CDONE: - /* initialize regs for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) - da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } + if (!(da2->bitblt.reg[0x20] & 0x20)) { + /* initialize regs and set magic value for debug dump */ + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) + da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + } else /* without init regs */ + da2->bitblt.reg[0x20] = 0; /* need to stop execution */ if (da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; else @@ -1013,7 +1121,7 @@ da2_bitblt_dopayload(void *priv) // } if (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); - else if (da2->bitblt.indata) /* for OS/2 J1.3 */ + else if (da2->bitblt.indata) { if (da2->bitblt.exec == DA2_BLT_CIDLE) { da2->bitblt.exec = DA2_BLT_CLOAD; @@ -1339,9 +1447,10 @@ da2_in(uint16_t addr, void *p) } if (da2->bitblt.indata) temp |= 0x08; - da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); +#ifdef ENABLE_DA2_DEBUGMONWAIT + da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); +#endif } - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); break; case LF_INDEX: temp = da2->fctladdr; @@ -2381,7 +2490,7 @@ da2_mmio_readw(uint32_t addr, void *p) for (int i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t) (da2->vram[(addr << 3) | i]) | ((uint16_t) (da2->vram[((addr << 3) + 8) | i]) << 8); /* read vram into latch */ -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM ////debug // if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ @@ -2465,7 +2574,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) /* align bitmask to even address */ if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_wB %x %02x\n", addr, val); // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ @@ -2577,7 +2686,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM // 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) { @@ -3061,9 +3170,11 @@ da2_init(UNUSED(const device_t *info)) memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->bitblt.debug_reg_ip = 0; +#endif +#ifdef ENABLE_DA2_DEBUGVRAM da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); - da2->bitblt.debug_reg_ip = 0; #endif da2->bitblt.payload_addr = 0; da2_reset(da2); @@ -3162,11 +3273,13 @@ da2_close(void *p) } fclose(f); } + free(da2->bitblt.debug_reg); +#endif +#ifdef ENABLE_DA2_DEBUGVRAM if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); #endif free(da2->cram); free(da2->vram); From e9b8bbd0be4c575e5d420fbb24956c660776bcdf Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 25 Feb 2025 11:59:46 +0900 Subject: [PATCH 0335/1190] add bit invert operation in bitblt --- src/video/vid_ps55da2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f157d8fca..4922c6d30 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -502,6 +502,8 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s writepx[i] ^= srcpx->p8[i] & mask32.d; break; } + if (da2->bitblt.raster_op & 0x20) /* NOT */ + writepx[i] ^= 0xFFFFFFFF & mask32.d; } for (int i = 0; i < 8; i++) { DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); @@ -524,11 +526,11 @@ Param Desc 01 Color 03 Bit Shift 04 Select plane? -05 Dir(10 or 11) + Command?(40 or 48) +05 Dir(1000h or 1100h) + Command?(40 or 48) 08 Mask Left 09 Mask Right 0A Plane Mask? -0B ROP?(8h or 200h + 0-3h) +0B ROP?(8h or 200h) + Bitop (0 None, 1 AND, 2 OR, 3 XOR) 0D 20 Exec (1) or Exec without reset regs (21h) 21 ? @@ -709,9 +711,9 @@ da2_bitblt_load(da2_t *da2) i++; } da2->bitblt.exec = DA2_BLT_CIDLE; - // /* clear payload memory */ - // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - // da2->bitblt.payload_addr = 0; + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { /* clear payload memory */ @@ -731,7 +733,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.debug_exesteps = 0; #endif da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x23; /* 01 AND, 03 XOR */ da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); // for (int i = 0; i <= 0xb; i++) // { @@ -780,7 +782,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; @@ -797,7 +798,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; From 813afb8562d8cab16c7fdc88ad066015504584d7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 26 Feb 2025 04:16:36 +0900 Subject: [PATCH 0336/1190] change bitblt exec speed slower probably the real machine is slower than this --- src/video/vid_ps55da2.c | 40 ++++++---------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 4922c6d30..fa43ebeb6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -532,7 +532,7 @@ Param Desc 0A Plane Mask? 0B ROP?(8h or 200h) + Bitop (0 None, 1 AND, 2 OR, 3 XOR) 0D -20 Exec (1) or Exec without reset regs (21h) +20 Exec (1) or Exec without reset regs? (21h) 21 ? 22 ? 23 Tile W @@ -762,12 +762,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - // if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ - // { - // da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); - // da2->bitblt.exec = DA2_BLT_CDONE; - // } else - /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ if (da2->bitblt.reg[0x10] == 0xbc04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; @@ -810,15 +804,11 @@ da2_bitblt_load(da2_t *da2) } /* Draw a line */ else if (da2->bitblt.reg[0x5] == 0x43) { - // da2_log("drawline x=%d, y=%d, 24=%d, 2A=%d, 2B=%d, 2D=%d\n", - // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - // n24, n2a, n2b, da2->bitblt.reg[0x2D]); da2->bitblt.exec = DA2_BLT_CLINE; da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff); da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff); da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff)); da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff)); - // da2->bitblt.raster_op = 0; da2->bitblt.count = 0; da2->bitblt.octdir = da2->bitblt.reg[0x2D]; da2->bitblt.bitshift_destr = 0; @@ -829,13 +819,6 @@ da2_bitblt_load(da2_t *da2) da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n", da2->bitblt.dest_x, da2->bitblt.dest_y, da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); - // FILE *f = fopen("da2_drawline.csv", "a"); - // if (f != NULL) { - // fprintf(f,"drawline,%d,%d,%d,%d,%d,%d\n", - // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - // n24, n2a, n2b, da2->bitblt.reg[0x2D]); - // fclose(f); - // } } /* Fill a rectangle (or draw a horizontal / vertical line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { @@ -922,7 +905,7 @@ da2_bitblt_exec(void *p) /* Draw a dot */ // outb(0x680, da2->bitblt.octdir); - // da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; int pixelmask = pos_x % 16; if (pixelmask >= 8) @@ -1107,26 +1090,15 @@ da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - // if (da2->bitblt.indata) /* for OS/2 J1.3 */ - // { - // if (da2->bitblt.exec == DA2_BLT_CIDLE) { - // da2->bitblt.exec = DA2_BLT_CLOAD; - // /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ - // da2_log("da2 Do bitblt\n"); - // while (da2->bitblt.exec != DA2_BLT_CIDLE) { - // da2_bitblt_exec(da2); - // } - // da2_log("da2 End bitblt %x\n", da2->bitblt.exec); - // } - // } if (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); - else if (da2->bitblt.indata) - { + else if (da2->bitblt.indata) { if (da2->bitblt.exec == DA2_BLT_CIDLE) { da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); } + } else { + // timer_disable(&da2->bitblt.timer); } } @@ -3189,7 +3161,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; + da2->bitblt.timerspeed = 10 * TIMER_USEC; timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From 168910b72ff1820a2524b642496483a910ecc81b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Feb 2025 11:39:04 +0600 Subject: [PATCH 0337/1190] All held-down keys are now released when Alt-Tab'ing out Only applies when Raw Input is in use on Windows --- src/device/keyboard.c | 14 ++++++++++++++ src/include/86box/keyboard.h | 1 + src/qt/qt_mainwindow.cpp | 2 ++ 3 files changed, 17 insertions(+) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 582dcf0b1..58d5a4724 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -332,6 +332,20 @@ keyboard_input(int down, uint16_t scan) } } +void +keyboard_all_up(void) +{ + for (unsigned short i = 0; i < 0x200; i++) { + if (recv_key_ui[i]) { + recv_key_ui[i] = 0; + } + if (recv_key[i]) { + recv_key[i] = 0; + key_process(i, 0); + } + } +} + static uint8_t keyboard_do_break(uint16_t scan) { diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index ec5c05775..110e4f760 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -269,6 +269,7 @@ extern void keyboard_poll_host(void); extern void keyboard_process(void); extern uint16_t keyboard_convert(int ch); extern void keyboard_input(int down, uint16_t scan); +extern void keyboard_all_up(void); extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl); extern uint8_t keyboard_get_shift(void); extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 3ee58f23b..62ac94f30 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -277,6 +277,8 @@ MainWindow::MainWindow(QWidget *parent) if (mouse_capture) emit setMouseCapture(false); + keyboard_all_up(); + if (do_auto_pause && !dopause) { auto_paused = 1; plat_pause(1); From 6d3816df64aac6cb0e604bab30239c3b4b888265 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Feb 2025 01:03:00 +0600 Subject: [PATCH 0338/1190] x87: Fix Final Reality discolored screen for interpreter --- src/cpu/x87_ops.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index f1362bf76..276c32876 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -113,12 +113,33 @@ typedef union { static __inline void x87_push(double i) { +#ifdef X87_INLINE_ASM + unsigned char buffer[10]; +#else + x87_conv_t test; +#endif #ifdef USE_NEW_DYNAREC cpu_state.TOP--; #else cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif cpu_state.ST[cpu_state.TOP & 7] = i; + +#ifdef X87_INLINE_ASM + __asm volatile("" + : + : + : "memory"); + + __asm volatile("fldl %1\n" + "fstpt %0\n" : "=m"(buffer) : "m"(i)); + + cpu_state.MM[cpu_state.TOP & 7].q = (*(uint64_t*)buffer); +#else + x87_to80(i, &test); + cpu_state.MM[cpu_state.TOP & 7].q = test.eind.ll; +#endif + #ifdef USE_NEW_DYNAREC cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID; #else @@ -129,6 +150,11 @@ x87_push(double i) static __inline void x87_push_u64(uint64_t i) { +#ifdef X87_INLINE_ASM + unsigned char buffer[10]; +#else + x87_conv_t test; +#endif union { double d; uint64_t ll; @@ -142,6 +168,21 @@ x87_push_u64(uint64_t i) cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif cpu_state.ST[cpu_state.TOP & 7] = td.d; + +#ifdef X87_INLINE_ASM + __asm volatile("" + : + : + : "memory"); + + __asm volatile("fldl %1\n" + "fstpt %0\n" : "=m"(buffer) : "m"(td.d)); + + cpu_state.MM[cpu_state.TOP & 7].q = (*(uint64_t*)buffer); +#else + x87_to80(td.d, &test); + cpu_state.MM[cpu_state.TOP & 7].q = test.eind.ll; +#endif #ifdef USE_NEW_DYNAREC cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID; #else From 3cde104ff683bb91c71768d32fbd8c8a26bf643b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 27 Feb 2025 08:29:06 +0900 Subject: [PATCH 0339/1190] add inversion ROPs (still in debug) --- src/video/vid_ps55da2.c | 75 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index fa43ebeb6..91752a7a8 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -387,13 +387,13 @@ typedef struct da2_t { int bitshift_destr; int raster_op; uint8_t payload[DA2_BLT_MEMSIZE]; + int payload_addr; int32_t reg[DA2_BLT_REGSIZE]; // must be signed int #ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug int debug_reg_ip; // for debug int debug_exesteps; #endif - int payload_addr; pc_timer_t timer; int64_t timerspeed; int exec; @@ -409,7 +409,6 @@ typedef struct da2_t { int32_t fcolor; int32_t maskl, maskr; int32_t count; - // int32_t countj; int32_t d; int octdir; int x, y; @@ -460,7 +459,7 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) da2->vram[addr & da2->vram_mask] = val; return; } - +/* write pixel data with rop (Note: bitmask must be in big endian) */ void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) { @@ -487,7 +486,11 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s for (int i = 0; i < 8; i++) { if (da2->bitblt.bitshift_destr > 0) srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; - switch (da2->bitblt.raster_op) { + if (da2->bitblt.raster_op & 0x2010) /* NOT Src or NOT Pattern */ + srcpx->p8[i] = ~srcpx->p8[i] & mask32.d; + if (da2->bitblt.raster_op & 0x20) /* Dest NOT */ + writepx[i] = (~writepx[i] & mask32.d) | (writepx[i] & ~mask32.d); + switch (da2->bitblt.raster_op & 0x03) { case 0x00: /* None */ writepx[i] &= ~mask32.d; writepx[i] |= srcpx->p8[i] & mask32.d; @@ -502,8 +505,6 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s writepx[i] ^= srcpx->p8[i] & mask32.d; break; } - if (da2->bitblt.raster_op & 0x20) /* NOT */ - writepx[i] ^= 0xFFFFFFFF & mask32.d; } for (int i = 0; i < 8; i++) { DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); @@ -530,7 +531,13 @@ Param Desc 08 Mask Left 09 Mask Right 0A Plane Mask? -0B ROP?(8h or 200h) + Bitop (0 None, 1 AND, 2 OR, 3 XOR) +0B ROP + 2000 NOT Source + 200 Source / Pattern + 20 NOT Dest + 10 NOT Pattern + 8 ? + 0-3 Bit op (0 None, 1 AND, 2 OR, 3 XOR) 0D 20 Exec (1) or Exec without reset regs? (21h) 21 ? @@ -602,7 +609,7 @@ print_bytetobin(uint8_t b) b <<= 1; } } -// Convert internal char code to Shift JIS code +/* Convert internal char code to Shift JIS code */ inline int isKanji1(uint8_t chr) { @@ -649,17 +656,19 @@ da2_bitblt_load(da2_t *da2) { uint32_t value32; uint64_t value64; +#ifdef ENABLE_DA2_DEBUGBLT da2_log("bltload: loading params\n"); - // da2_log("BitBlt memory:\n"); - // if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - // { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - // } + da2_log("BitBlt memory:\n"); + if (da2->bitblt.payload[0] != 0) + for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + { + int i = j * 8; + da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + } +#endif int i = 0; - while (i < DA2_BLT_MEMSIZE) { + while (i < da2->bitblt.payload_addr) { if (da2->bitblt.reg[0x20] & 0x1) break; switch (da2->bitblt.payload[i]) { @@ -712,36 +721,26 @@ da2_bitblt_load(da2_t *da2) } da2->bitblt.exec = DA2_BLT_CIDLE; /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; + // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + // da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { /* clear payload memory */ memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); da2->bitblt.payload_addr = 0; #ifdef ENABLE_DA2_DEBUGBLT - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - // if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); - } for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; } da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; da2->bitblt.debug_reg_ip++; - if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) + if ((DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip) >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; da2->bitblt.debug_exesteps = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x23; /* 01 AND, 03 XOR */ da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - // for (int i = 0; i <= 0xb; i++) - // { - // da2_log("%02x ", da2->gdcreg[i]); - // da2->gdcreg[i] = da2->bitblt.reg[i] & 0xff; - // } - // da2_log("\n"); - + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b]; da2->bitblt.destaddr = da2->bitblt.reg[0x29]; da2->bitblt.size_x = da2->bitblt.reg[0x33]; da2->bitblt.size_y = da2->bitblt.reg[0x35]; @@ -890,14 +889,13 @@ da2_bitblt_exec(void *p) #else da2_log("bitblt_exec: %d\n", da2->bitblt.exec); #endif - // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: // timer_disable(&da2->bitblt.timer); break; case DA2_BLT_CLOAD: - da2->bitblt.indata = 0; da2_bitblt_load(da2); + da2->bitblt.indata = 0; break; case DA2_BLT_CLINE: int pos_x = da2->bitblt.dest_x + da2->bitblt.x; @@ -1512,7 +1510,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 %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -2534,8 +2532,10 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->bitblt.indata = 1; if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; + else { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + } break; default: da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); @@ -3008,7 +3008,6 @@ da2_loadfont(char *fname, void *p) { da2_t *da2 = (da2_t *) p; uint8_t buf; - // uint32_t code = 0; uint64_t fsize; if (!fname) return; From e49be34d3070730b63053a0df9bdffa833c01e8e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 27 Feb 2025 11:15:57 +0900 Subject: [PATCH 0340/1190] fix an issue when loading bitblt data in async --- src/video/vid_ps55da2.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 91752a7a8..f8c72833e 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -273,6 +273,11 @@ da2_log(const char *fmt, ...) #else # define da2_log(fmt, ...) #endif +#ifdef ENABLE_DA2_DEBUGBLT +# define da2_bltlog da2_log +#else +# define da2_bltlog(fmt, ...) +#endif typedef struct da2_t { // mem_mapping_t vmapping; @@ -678,7 +683,7 @@ da2_bitblt_load(da2_t *da2) value32 = da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_bltlog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 3; break; @@ -690,7 +695,7 @@ da2_bitblt_load(da2_t *da2) value32 |= da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_bltlog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 5; break; @@ -706,7 +711,7 @@ da2_bitblt_load(da2_t *da2) value64 |= da2->bitblt.payload[i + 3]; value64 <<= 8; value64 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; i += 7; @@ -721,13 +726,10 @@ da2_bitblt_load(da2_t *da2) } da2->bitblt.exec = DA2_BLT_CIDLE; /* clear payload memory */ - // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - // da2->bitblt.payload_addr = 0; + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { - /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; #ifdef ENABLE_DA2_DEBUGBLT for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; @@ -759,7 +761,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.x = 0; da2->bitblt.y = 0; da2->bitblt.exec = DA2_BLT_CDONE; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ if (da2->bitblt.reg[0x10] == 0xbc04) { @@ -886,8 +887,6 @@ da2_bitblt_exec(void *p) if(!(da2->bitblt.debug_exesteps & 0xf)) da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); da2->bitblt.debug_exesteps++; -#else - da2_log("bitblt_exec: %d\n", da2->bitblt.exec); #endif switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: @@ -903,7 +902,7 @@ da2_bitblt_exec(void *p) /* Draw a dot */ // outb(0x680, da2->bitblt.octdir); - da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + da2_bltlog("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; int pixelmask = pos_x % 16; if (pixelmask >= 8) @@ -1090,11 +1089,9 @@ da2_bitblt_dopayload(void *priv) timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); if (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); - else if (da2->bitblt.indata) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) { + else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); - } } else { // timer_disable(&da2->bitblt.timer); } @@ -2656,6 +2653,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + addr &= DA2_MASK_MMIO; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGVRAM @@ -2676,7 +2674,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) //} #endif cycles -= video_timing_write_w; - // cycles_lost += video_timing_write_w; // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); // 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); @@ -2765,7 +2762,6 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ - addr &= DA2_MASK_MMIO; // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); @@ -2808,8 +2804,8 @@ static uint8_t da2_code_read(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) - return DA2_INVALIDACCESS8; + // if ((addr & ~DA2_MASK_CRAM) != 0xE0000) + // return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } From 03dd94f361259b102fad8cfce2592fa81b801ee8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Feb 2025 13:50:45 +0600 Subject: [PATCH 0341/1190] x87: Fix Final Reality discolored screen for all dynarecs --- src/codegen/codegen_ops_x86-64.h | 14 +++++++++ src/codegen/codegen_ops_x86.h | 7 +++++ src/codegen_new/codegen_ops_helpers.h | 3 ++ src/cpu/386_dynarec.c | 45 +++++++++++++++++++++++++++ src/cpu/cpu.h | 6 ++++ 5 files changed, 75 insertions(+) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index e46f55a05..01fb292cf 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -3571,6 +3571,8 @@ FP_FLD(int reg) addbyte(0x89); /*MOV [TOP], EBX*/ addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(TOP)); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -3688,6 +3690,8 @@ FP_LOAD_S(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_D(void) @@ -3717,6 +3721,8 @@ FP_LOAD_D(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -3754,6 +3760,8 @@ FP_LOAD_IW(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IL(void) @@ -3787,6 +3795,8 @@ FP_LOAD_IL(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IQ(void) @@ -3831,6 +3841,8 @@ FP_LOAD_IQ(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -3863,6 +3875,8 @@ FP_LOAD_IMM_Q(uint64_t v) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); addbyte(v ? 0 : 1); + + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index c48324c2a..3b47d81a9 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -1794,6 +1794,7 @@ FP_FLD(int reg) addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(TOP)); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -2037,6 +2038,7 @@ FP_LOAD_S(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_D(void) @@ -2096,6 +2098,7 @@ FP_LOAD_D(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IW(void) @@ -2154,6 +2157,7 @@ FP_LOAD_IW(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IL(void) @@ -2210,6 +2214,7 @@ FP_LOAD_IL(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IQ(void) @@ -2285,6 +2290,7 @@ FP_LOAD_IQ(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -2336,6 +2342,7 @@ FP_LOAD_IMM_Q(uint64_t v) addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(TOP)); } + CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline int diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 92b721099..2304aa542 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -64,6 +64,9 @@ fpu_POP2(codeblock_t *block, ir_data_t *ir) static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir) { + uop_LOAD_FUNC_ARG_IMM(ir, 0, ((uint16_t)cpu_state.TOP - 1)); + uop_CALL_FUNC(ir, x87_to_mmxreg); + if (block->flags & CODEBLOCK_STATIC_TOP) uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); else diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 5f41c416a..5cb385122 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -74,6 +74,51 @@ x386_dynarec_log(const char *fmt, ...) # define x386_dynarec_log(fmt, ...) #endif +/* Deliberately stashed here; this function is only relevant for dynamic recompilers. */ +#if defined(_MSC_VER) && !defined(__clang__) +# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 +# define X87_INLINE_ASM +# endif +#else +# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 || defined __amd64__ +# define X87_INLINE_ASM +# endif +#endif + +#ifdef USE_NEW_DYNAREC +void +x87_to_mmxreg(uint16_t reg) +#else +void +x87_to_mmxreg(void) +#endif +{ +#ifndef USE_NEW_DYNAREC + uint32_t reg = cpu_state.TOP & 7; +#endif + double val = cpu_state.ST[reg & 7]; +#ifdef X87_INLINE_ASM + unsigned char buffer[10]; +#else + x87_conv_t test; +#endif + +#ifdef X87_INLINE_ASM + __asm volatile("" + : + : + : "memory"); + + __asm volatile("fldl %1\n" + "fstpt %0\n" : "=m"(buffer) : "m"(val)); + + cpu_state.MM[reg & 7].q = (*(uint64_t*)buffer); +#else + x87_to80(val, &test); + cpu_state.MM[reg & 7].q = test.eind.ll; +#endif +} + static __inline void fetch_ea_32_long(uint32_t rmdat) { diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 1d003ddc9..98c6f4938 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -829,6 +829,12 @@ extern uint16_t prefetch_queue_get_ip(void); extern int prefetch_queue_get_prefetching(void); extern int prefetch_queue_get_size(void); +#ifdef USE_NEW_DYNAREC +extern void x87_to_mmxreg(uint16_t reg); +#else +extern void x87_to_mmxreg(void); +#endif + #define prefetch_queue_set_suspended(s) prefetch_queue_set_prefetching(!s) #define prefetch_queue_get_suspended !prefetch_queue_get_prefetching From c7153916eb21c67647e4df2512cda9b8776e5653 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Feb 2025 14:33:44 +0600 Subject: [PATCH 0342/1190] Fix compile on ARM64 --- src/cpu/386_dynarec.c | 70 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 5cb385122..04681c9dc 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -74,7 +74,6 @@ x386_dynarec_log(const char *fmt, ...) # define x386_dynarec_log(fmt, ...) #endif -/* Deliberately stashed here; this function is only relevant for dynamic recompilers. */ #if defined(_MSC_VER) && !defined(__clang__) # if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 # define X87_INLINE_ASM @@ -85,40 +84,6 @@ x386_dynarec_log(const char *fmt, ...) # endif #endif -#ifdef USE_NEW_DYNAREC -void -x87_to_mmxreg(uint16_t reg) -#else -void -x87_to_mmxreg(void) -#endif -{ -#ifndef USE_NEW_DYNAREC - uint32_t reg = cpu_state.TOP & 7; -#endif - double val = cpu_state.ST[reg & 7]; -#ifdef X87_INLINE_ASM - unsigned char buffer[10]; -#else - x87_conv_t test; -#endif - -#ifdef X87_INLINE_ASM - __asm volatile("" - : - : - : "memory"); - - __asm volatile("fldl %1\n" - "fstpt %0\n" : "=m"(buffer) : "m"(val)); - - cpu_state.MM[reg & 7].q = (*(uint64_t*)buffer); -#else - x87_to80(val, &test); - cpu_state.MM[reg & 7].q = test.eind.ll; -#endif -} - static __inline void fetch_ea_32_long(uint32_t rmdat) { @@ -278,6 +243,41 @@ fetch_ea_16_long(uint32_t rmdat) # define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) #endif +/* Deliberately stashed here; this function is only relevant for dynamic recompilers. */ +#ifdef USE_NEW_DYNAREC +void +x87_to_mmxreg(uint16_t reg) +#else +void +x87_to_mmxreg(void) +#endif +{ +#ifndef USE_NEW_DYNAREC + uint32_t reg = cpu_state.TOP & 7; +#endif + double val = cpu_state.ST[reg & 7]; +#ifdef X87_INLINE_ASM + unsigned char buffer[10]; +#else + x87_conv_t test; +#endif + +#ifdef X87_INLINE_ASM + __asm volatile("" + : + : + : "memory"); + + __asm volatile("fldl %1\n" + "fstpt %0\n" : "=m"(buffer) : "m"(val)); + + cpu_state.MM[reg & 7].q = (*(uint64_t*)buffer); +#else + x87_to80(val, &test); + cpu_state.MM[reg & 7].q = test.eind.ll; +#endif +} + #ifdef USE_DYNAREC int32_t cycles_main = 0; static int32_t cycles_old = 0; From fc656cbe0519b1a108aef25a333bf61cd5131cf8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Feb 2025 16:31:27 +0600 Subject: [PATCH 0343/1190] Mouse cursor now properly appears after uncapture --- src/qt/qt_mainwindow.cpp | 4 +++- src/qt/qt_rendererstack.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 62ac94f30..89d17a07c 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -262,8 +262,10 @@ MainWindow::MainWindow(QWidget *parent) ui->stackedWidget->mouse_capture_func(this->windowHandle()); } else { this->releaseKeyboard(); - if (ui->stackedWidget->mouse_uncapture_func) + if (ui->stackedWidget->mouse_uncapture_func) { ui->stackedWidget->mouse_uncapture_func(); + } + ui->stackedWidget->unsetCursor(); } }); diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index a8bd47a79..8c31da2b2 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -155,7 +155,7 @@ RendererStack::mouseReleaseEvent(QMouseEvent *event) } if (mouse_capture && (event->button() == Qt::MiddleButton) && (mouse_get_buttons() < 3)) { plat_mouse_capture(0); - this->setCursor(Qt::ArrowCursor); + this->unsetCursor(); isMouseDown &= ~1; return; } From 95f12bc206e955324731bfcac18025f034d6db09 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Feb 2025 00:50:01 +0900 Subject: [PATCH 0344/1190] fix glitch in Bitblt's line drawing function fix a line glitch issue occurs in MS Paint and QEMM Manifest apps. --- src/video/vid_ps55da2.c | 58 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f8c72833e..c476d12b9 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -405,10 +405,11 @@ typedef struct da2_t { int indata; int32_t destaddr; int32_t srcaddr; - int32_t size_x, tile_w; - int32_t size_y; - int32_t dest_x; - int32_t dest_y; + int16_t size_x; + int16_t tile_w; + int16_t size_y; + int16_t dest_x; + int16_t dest_y; int16_t destpitch; int16_t srcpitch; int32_t fcolor; @@ -416,7 +417,7 @@ typedef struct da2_t { int32_t count; int32_t d; int octdir; - int x, y; + int x, y, wx1, wx2, wy1, wy2; } bitblt; #ifdef ENABLE_DA2_DEBUGVRAM @@ -805,20 +806,32 @@ da2_bitblt_load(da2_t *da2) /* Draw a line */ else if (da2->bitblt.reg[0x5] == 0x43) { da2->bitblt.exec = DA2_BLT_CLINE; - da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff); - da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff); - da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff)); - da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff)); - da2->bitblt.count = 0; - da2->bitblt.octdir = da2->bitblt.reg[0x2D]; + da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0xffff); + da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0xffff); + da2->bitblt.wx1 = (da2->bitblt.reg[0x32]) >> 16; + da2->bitblt.wx2 = (da2->bitblt.reg[0x33]) >> 16; + da2->bitblt.wy1 = (da2->bitblt.reg[0x34]) >> 16; + da2->bitblt.wy2 = (da2->bitblt.reg[0x35]) >> 16; + da2->bitblt.size_x = abs((int16_t)(da2->bitblt.reg[0x33] & 0xffff) - da2->bitblt.dest_x); + da2->bitblt.size_y = abs((int16_t)(da2->bitblt.reg[0x35] & 0xffff) - da2->bitblt.dest_y); + da2->bitblt.count = 0; + da2->bitblt.octdir = da2->bitblt.reg[0x2D]; da2->bitblt.bitshift_destr = 0; if (da2->bitblt.octdir & 0x04) /* dX > dY */ da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x; else da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y; - da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n", + da2->bitblt.x = da2->bitblt.dest_x; + da2->bitblt.y = da2->bitblt.dest_y; + da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%dn", da2->bitblt.dest_x, da2->bitblt.dest_y, da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); + da2_log(" x1=%d, x2=%d, y1=%d, y2=%d\n", + da2->bitblt.reg[0x32] & 0x7ff, da2->bitblt.reg[0x33] & 0x7ff, + da2->bitblt.reg[0x34] & 0x7ff, da2->bitblt.reg[0x35] & 0x7ff); + da2_log(" ux1=%d,ux2=%d,uy1=%d,uy2=%d\n", + (da2->bitblt.reg[0x32] >> 16) & 0x7ff, (da2->bitblt.reg[0x33] >> 16) & 0x7ff, + (da2->bitblt.reg[0x34] >> 16) & 0x7ff, (da2->bitblt.reg[0x35] >> 16) & 0x7ff); } /* Fill a rectangle (or draw a horizontal / vertical line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { @@ -884,7 +897,7 @@ da2_bitblt_exec(void *p) da2_t *da2 = (da2_t *) p; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); #ifdef ENABLE_DA2_DEBUGBLT - if(!(da2->bitblt.debug_exesteps & 0xf)) + if(!(da2->bitblt.debug_exesteps & 0xff)) da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); da2->bitblt.debug_exesteps++; #endif @@ -897,23 +910,26 @@ da2_bitblt_exec(void *p) da2->bitblt.indata = 0; break; case DA2_BLT_CLINE: - int pos_x = da2->bitblt.dest_x + da2->bitblt.x; - int pos_y = da2->bitblt.dest_y + da2->bitblt.y; - /* Draw a dot */ // outb(0x680, da2->bitblt.octdir); - da2_bltlog("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); - int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; - int pixelmask = pos_x % 16; + da2_bltlog("point: %d %d %d %d %d\n", da2->bitblt.x, da2->bitblt.y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; + int pixelmask = da2->bitblt.x % 16; if (pixelmask >= 8) pixelmask = (0x8000 >> (pixelmask - 8)); else pixelmask = (0x80 >> pixelmask); - DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); + + /* check the current position is inside the window */ + if (da2->bitblt.x < da2->bitblt.wx1 || da2->bitblt.x > da2->bitblt.wx2 + || da2->bitblt.y < da2->bitblt.wy1 || da2->bitblt.y > da2->bitblt.wy2) + ; + else + DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); // da2_log("draw: %x %x %x\n", destaddr, da2->bitblt.fcolor, pixelmask); da2->bitblt.count++; - /* Bresenham's line */ + /* calculate the next position with Bresenham's line algorithm */ if (da2->bitblt.octdir & 0x04) { /* dX > dY */ if (da2->bitblt.octdir & 0x02) { da2->bitblt.x++; From 95f30192e5cb7b20755c1235625c107a3391fe93 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Feb 2025 22:09:55 +0600 Subject: [PATCH 0345/1190] USB multimedia keys now work on Windows --- src/qt/qt_main.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 72b0eef53..7723261b4 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -211,8 +211,121 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) (GetForegroundWindow() == ((HWND) secondaryRenderer->winId()))); } - if ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window) + bool skip = ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window); + + if (skip) return CallNextHookEx(NULL, nCode, wParam, lParam); + + /* USB keyboards send a scancode of 0x00 for multimedia keys. */ + if (lpKdhs->scanCode == 0x00) { + /* Handle USB keyboard multimedia keys where possible. + Only a handful of keys can be handled via Virtual Key + detection; rest can't be reliably detected. */ + DWORD vkCode = lpKdhs->vkCode; + bool up = !!(lpKdhs->flags & LLKHF_UP); + ret = CallNextHookEx(NULL, nCode, wParam, lParam);; + + switch (vkCode) + { + case VK_MEDIA_PLAY_PAUSE: + { + win_keyboard_handle(0x22, up, 1, 0); + break; + } + case VK_MEDIA_STOP: + { + win_keyboard_handle(0x24, up, 1, 0); + break; + } + case VK_VOLUME_UP: + { + win_keyboard_handle(0x30, up, 1, 0); + break; + } + case VK_VOLUME_DOWN: + { + win_keyboard_handle(0x2E, up, 1, 0); + break; + } + case VK_VOLUME_MUTE: + { + win_keyboard_handle(0x20, up, 1, 0); + break; + } + case VK_MEDIA_NEXT_TRACK: + { + win_keyboard_handle(0x19, up, 1, 0); + break; + } + case VK_MEDIA_PREV_TRACK: + { + win_keyboard_handle(0x10, up, 1, 0); + break; + } + case VK_LAUNCH_MEDIA_SELECT: + { + win_keyboard_handle(0x6D, up, 1, 0); + break; + } + case VK_LAUNCH_MAIL: + { + win_keyboard_handle(0x6C, up, 1, 0); + break; + } + case VK_LAUNCH_APP1: + { + win_keyboard_handle(0x6B, up, 1, 0); + break; + } + case VK_LAUNCH_APP2: + { + win_keyboard_handle(0x21, up, 1, 0); + break; + } + case VK_BROWSER_BACK: + { + win_keyboard_handle(0x6A, up, 1, 0); + break; + } + case VK_BROWSER_FORWARD: + { + win_keyboard_handle(0x69, up, 1, 0); + break; + } + case VK_BROWSER_STOP: + { + win_keyboard_handle(0x68, up, 1, 0); + break; + } + case VK_BROWSER_HOME: + { + win_keyboard_handle(0x32, up, 1, 0); + break; + } + case VK_BROWSER_SEARCH: + { + win_keyboard_handle(0x65, up, 1, 0); + break; + } + case VK_BROWSER_REFRESH: + { + win_keyboard_handle(0x67, up, 1, 0); + break; + } + case VK_BROWSER_FAVORITES: + { + win_keyboard_handle(0x66, up, 1, 0); + break; + } + case VK_HELP: + { + win_keyboard_handle(0x3b, up, 1, 0); + break; + } + } + + return ret; + } else if ((lpKdhs->scanCode == 0x01) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) ret = TRUE; From 86342bfffe057d4ff01b18b05cd89816228c636c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Feb 2025 23:26:42 +0600 Subject: [PATCH 0346/1190] OS/2 3.0 icon backgrounds are now drawn properly --- src/video/vid_mga.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 3937c2a7d..f11983a20 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -4677,6 +4677,7 @@ blit_trap(mystique_t *mystique) int err_l = (int32_t)mystique->dwgreg.ar[1]; int err_r = (int32_t)mystique->dwgreg.ar[4]; const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + bool transc = !!(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC); switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { case DWGCTRL_ATYPE_BLK: @@ -4699,6 +4700,7 @@ blit_trap(mystique_t *mystique) int pattern = mystique->dwgreg.pattern[yoff][xoff]; uint32_t dst; + if (!transc || (transc && pattern)) switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; @@ -4770,6 +4772,7 @@ blit_trap(mystique_t *mystique) uint32_t dst; uint32_t old_dst; + if (!transc || (transc && pattern)) switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; From 726ce6c574076807772b4cbcfaedcfb309b2555d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Feb 2025 10:29:17 +0900 Subject: [PATCH 0347/1190] modify video memory mask and screen updating --- src/video/vid_ps55da2.c | 109 ++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index c476d12b9..441df620b 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -50,25 +50,29 @@ #define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" #define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" -#define DA2_FONTROM_SIZE 1536 * 1024 +#define DA2_FONTROM_SIZE (1536 * 1024) #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 #define DA2_VM03_BASECHR 0x18000 #define DA2_VM03_BASEEXATTR 0x10000 -#define DA2_INVALIDACCESS8 0xff +#define DA2_INVALIDACCESS8 0xffu +#define DA2_INVALIDACCESS16 0xffffu +#define DA2_INVALIDACCESS32 0xffffffffu #define DA2_MASK_MMIO 0x1ffff -#define DA2_SIZE_VRAM 1024 * 1024 /* 0x100000 */ -#define DA2_SIZE_CRAM 4 * 1024 /* 0x1000 */ -#define DA2_SIZE_GAIJIRAM 256 * 1024 /* 0x40000 */ -#define DA2_MASK_A000 0x1ffff -#define DA2_MASK_CRAM 0xfff -#define DA2_MASK_GAIJIRAM 0x3ffff -#define DA2_PIXELCLOCK 58000000.0 +#define DA2_SIZE_VRAM (1024 * 1024) /* 0x100000 */ +#define DA2_SIZE_CRAM (4 * 1024) /* 0x1000 */ +#define DA2_SIZE_GAIJIRAM (256 * 1024) /* 0x40000 */ +#define DA2_MASK_A000 0x1ffff /* 0x1FFFF */ +#define DA2_MASK_CRAM 0xfff /* 0xFFF */ +#define DA2_MASK_GAIJIRAM 0x3ffff /* 0x3FFFF */ +#define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */ +#define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ +#define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */ #define DA2_BLT_MEMSIZE 0x100 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256 * 1024 +#define DA2_DEBUG_BLTLOG_MAX (256 * 1024) #define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe #define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ @@ -253,7 +257,7 @@ #endif #ifdef ENABLE_DA2_LOG -# define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGBLT 1 // # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 @@ -304,7 +308,6 @@ typedef struct da2_t { uint32_t decode_mask; uint32_t vram_max; - uint32_t vram_mask; uint32_t gdcla[8]; uint32_t gdcinput[8]; @@ -363,13 +366,11 @@ typedef struct da2_t { // uint32_t cram_display_mask; /* APA Buffer A0000-BFFFFh (128 KB) */ uint8_t *vram; - /* addr >> 12 = xx000h */ + /* xxh */ uint8_t *changedvram; /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; - // uint32_t write_bank, read_bank; - int fullchange; void (*render)(struct da2_t *da2); @@ -454,15 +455,17 @@ typedef struct { uint32_t DA2_vram_r(uint32_t addr, da2_t *da2) { - if (addr & ~da2->vram_mask) - return -1; + if (addr & ~DA2_MASK_VRAM) + return DA2_INVALIDACCESS32; return da2->vram[addr]; } /* safety write for internal functions */ void DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) { - da2->vram[addr & da2->vram_mask] = val; + if (addr & ~DA2_MASK_VRAM) + return; + da2->vram[addr] = val; return; } /* write pixel data with rop (Note: bitmask must be in big endian) */ @@ -472,8 +475,7 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s uint32_t writepx[8]; destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; - da2->changedvram[(da2->vram_display_mask & (destaddr + 1)) >> 12] = changeframecount; + da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; destaddr <<= 3; /* read destination data with big endian order */ for (int i = 0; i < 8; i++) @@ -485,7 +487,6 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s DA2_VidSeq32 mask32in; mask32in.d = (uint32_t) mask; DA2_VidSeq32 mask32; - mask32.d = 0; mask32.b[3] = mask32in.b[0]; mask32.b[2] = mask32in.b[1]; mask32.d &= 0xffff0000; @@ -1395,7 +1396,7 @@ da2_in(uint16_t addr, void *p) case LS_DATA: // da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ if (da2->ioctladdr > 0xf) - return DA2_INVALIDACCESS8; + return DA2_INVALIDACCESS16; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ @@ -1440,7 +1441,7 @@ da2_in(uint16_t addr, void *p) break; case LF_DATA: if (da2->fctladdr > 0x1f) - return DA2_INVALIDACCESS8; + return DA2_INVALIDACCESS16; temp = da2->fctl[da2->fctladdr]; break; case LC_INDEX: @@ -1448,7 +1449,7 @@ da2_in(uint16_t addr, void *p) break; case LC_DATA: if (da2->crtcaddr > 0x1f) - return DA2_INVALIDACCESS8; + return DA2_INVALIDACCESS16; temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: @@ -1741,14 +1742,13 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *p) if (code >= 0x8000 && code <= 0x8183) code -= 0x6000; /* shift for IBM extended characters (I don't know how the real card works.) */ if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ - font <<= 8; /* 1111 1111 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ - font >>= 1; /* 0111 1111 1222 2000 */ - font <<= 4; /* 0111 1111 1222 2000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ - font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ + font = da2->mmio.font[code * 72 + fline * 3]; /* 0000 0000 0000 0000 0000 0000 1111 1111 */ + font <<= 8; /* 0000 0000 0000 0000 1111 1111 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 0000 0000 0000 0000 1111 1111 2222 0000 */ + font <<= 3; /* 0000 0000 0000 0111 1111 1222 2000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0000 0000 0000 0111 1111 1222 2000 2222 */ + font <<= 8; /* 0000 0111 1111 1222 2000 2222 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0000 0111 1111 1222 2000 2222 3333 3333 */ font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ /* font >>= 1;//put blank at column 1 (and 26) */ } else if (code >= 0xb000 && code <= 0xb75f) { @@ -1824,7 +1824,7 @@ da2_render_text(da2_t *da2) // 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]; + 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 */ { /* --Parse attribute byte in color mode-- */ @@ -1864,7 +1864,7 @@ da2_render_text(da2_t *da2) /* Stay drawing If the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; + chr_dbcs = da2->cram[(da2->ma + 2) & DA2_MASK_CRAM]; chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -1935,7 +1935,7 @@ da2_render_text(da2_t *da2) da2->ma += 2; p += 13; } - da2->ma &= da2->vram_display_mask; + // da2->ma &= DA2_MASK_CRAM; // da2->writelines++; } } @@ -1959,9 +1959,9 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma), da2); - attr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 1, da2); - extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + (da2->ma) + 1, da2); + chr = DA2_vram_r(DA2_VM03_BASECHR + da2->ma, da2); + attr = DA2_vram_r(DA2_VM03_BASECHR + da2->ma + 1, da2); + extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + da2->ma + 1, da2); // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; @@ -1979,7 +1979,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 2, da2); + chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + da2->ma + 2, da2); chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -2027,7 +2027,7 @@ da2_render_textm3(da2_t *da2) da2->ma += 2; p += 13; } - da2->ma &= da2->vram_display_mask; + // da2->ma &= DA2_MASK_CRAM; // da2->writelines++; } } @@ -2035,7 +2035,7 @@ da2_render_textm3(da2_t *da2) void da2_render_color_4bpp(da2_t *da2) { - int changed_offset = da2->ma >> 12; + int changed_offset = da2->ma >> 9; // da2_log("ma %x cf %x\n", da2->ma, changed_offset); da2->plane_mask &= 0x0f; /*safety */ @@ -2084,7 +2084,7 @@ da2_render_color_4bpp(da2_t *da2) void da2_render_color_8bpp(da2_t *da2) { - int changed_offset = da2->ma >> 12; + int changed_offset = da2->ma >> 9; // da2_log("ma %x cf %x\n", da2->ma, changed_offset); if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { @@ -2255,8 +2255,8 @@ da2_recalctimings(da2_t *da2) if (da2->dispofftime < TIMER_USEC) 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 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->render %08X\n", da2->render); } @@ -2580,7 +2580,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) cycles -= video_timing_write_b; - da2->changedvram[addr >> 12] = changeframecount; + da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ addr <<= 3; for (int i = 0; i < 8; i++) @@ -2694,8 +2694,8 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); // 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 >> 12] = changeframecount; - da2->changedvram[(addr + 1) >> 12] = changeframecount; + da2->changedvram[addr >> 9] = changeframecount; + // da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; for (int i = 0; i < 8; i++) @@ -2948,7 +2948,7 @@ da2_poll(void *priv) } da2->blink++; - for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) { + for (x = 0; x <= (DA2_MASK_VRAMPLANE >> 9); x++) { if (da2->changedvram[x]) da2->changedvram[x]--; } @@ -3089,7 +3089,7 @@ da2_reset(void *priv) da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ - da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (set by reference diskette) */ da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8) << 1); /* Configuration 1 : Monitor ID 3 */ da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ @@ -3127,11 +3127,10 @@ da2_init(UNUSED(const device_t *info)) da2->dispontime = 1000ull << 32; da2->dispofftime = 1000ull << 32; da2->vram = calloc(1, DA2_SIZE_VRAM); - da2->vram_mask = DA2_SIZE_VRAM - 1; da2->cram = calloc(1, DA2_SIZE_CRAM); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ DA2_SIZE_VRAM >> 12); /* XX000h */ - da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ + da2->monitorid = device_get_config_int("montype"); + da2->changedvram = calloc(1, (DA2_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ da2->mmio.charset = device_get_config_int("charset"); da2->mmio.font = malloc(DA2_FONTROM_SIZE); @@ -3148,7 +3147,7 @@ da2_init(UNUSED(const device_t *info)) } mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); - da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT @@ -3172,7 +3171,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 10 * TIMER_USEC; + da2->bitblt.timerspeed = 10ull * TIMER_USEC; timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; @@ -3275,7 +3274,7 @@ void da2_speed_changed(void *p) { da2_t *da2 = (da2_t *) p; - da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); da2_recalctimings(da2); } From 0bb89be0ad0e718841ca99ef2405cb42f9666f6f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Feb 2025 16:51:13 +0600 Subject: [PATCH 0348/1190] Revert "Fix compile on ARM64" This reverts commit c7153916eb21c67647e4df2512cda9b8776e5653. --- src/cpu/386_dynarec.c | 70 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 04681c9dc..5cb385122 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -74,6 +74,7 @@ x386_dynarec_log(const char *fmt, ...) # define x386_dynarec_log(fmt, ...) #endif +/* Deliberately stashed here; this function is only relevant for dynamic recompilers. */ #if defined(_MSC_VER) && !defined(__clang__) # if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 # define X87_INLINE_ASM @@ -84,6 +85,40 @@ x386_dynarec_log(const char *fmt, ...) # endif #endif +#ifdef USE_NEW_DYNAREC +void +x87_to_mmxreg(uint16_t reg) +#else +void +x87_to_mmxreg(void) +#endif +{ +#ifndef USE_NEW_DYNAREC + uint32_t reg = cpu_state.TOP & 7; +#endif + double val = cpu_state.ST[reg & 7]; +#ifdef X87_INLINE_ASM + unsigned char buffer[10]; +#else + x87_conv_t test; +#endif + +#ifdef X87_INLINE_ASM + __asm volatile("" + : + : + : "memory"); + + __asm volatile("fldl %1\n" + "fstpt %0\n" : "=m"(buffer) : "m"(val)); + + cpu_state.MM[reg & 7].q = (*(uint64_t*)buffer); +#else + x87_to80(val, &test); + cpu_state.MM[reg & 7].q = test.eind.ll; +#endif +} + static __inline void fetch_ea_32_long(uint32_t rmdat) { @@ -243,41 +278,6 @@ fetch_ea_16_long(uint32_t rmdat) # define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) #endif -/* Deliberately stashed here; this function is only relevant for dynamic recompilers. */ -#ifdef USE_NEW_DYNAREC -void -x87_to_mmxreg(uint16_t reg) -#else -void -x87_to_mmxreg(void) -#endif -{ -#ifndef USE_NEW_DYNAREC - uint32_t reg = cpu_state.TOP & 7; -#endif - double val = cpu_state.ST[reg & 7]; -#ifdef X87_INLINE_ASM - unsigned char buffer[10]; -#else - x87_conv_t test; -#endif - -#ifdef X87_INLINE_ASM - __asm volatile("" - : - : - : "memory"); - - __asm volatile("fldl %1\n" - "fstpt %0\n" : "=m"(buffer) : "m"(val)); - - cpu_state.MM[reg & 7].q = (*(uint64_t*)buffer); -#else - x87_to80(val, &test); - cpu_state.MM[reg & 7].q = test.eind.ll; -#endif -} - #ifdef USE_DYNAREC int32_t cycles_main = 0; static int32_t cycles_old = 0; From 6bb2b447fda8011e992472fa0959d3ee4cd8deed Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Feb 2025 16:51:33 +0600 Subject: [PATCH 0349/1190] Revert "x87: Fix Final Reality discolored screen for all dynarecs" This reverts commit 03dd94f361259b102fad8cfce2592fa81b801ee8. --- src/codegen/codegen_ops_x86-64.h | 14 --------- src/codegen/codegen_ops_x86.h | 7 ----- src/codegen_new/codegen_ops_helpers.h | 3 -- src/cpu/386_dynarec.c | 45 --------------------------- src/cpu/cpu.h | 6 ---- 5 files changed, 75 deletions(-) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 01fb292cf..e46f55a05 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -3571,8 +3571,6 @@ FP_FLD(int reg) addbyte(0x89); /*MOV [TOP], EBX*/ addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(TOP)); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -3690,8 +3688,6 @@ FP_LOAD_S(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_D(void) @@ -3721,8 +3717,6 @@ FP_LOAD_D(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -3760,8 +3754,6 @@ FP_LOAD_IW(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IL(void) @@ -3795,8 +3787,6 @@ FP_LOAD_IL(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IQ(void) @@ -3841,8 +3831,6 @@ FP_LOAD_IQ(void) addbyte(0x44); addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -3875,8 +3863,6 @@ FP_LOAD_IMM_Q(uint64_t v) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag)); addbyte(v ? 0 : 1); - - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index 3b47d81a9..c48324c2a 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -1794,7 +1794,6 @@ FP_FLD(int reg) addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(TOP)); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -2038,7 +2037,6 @@ FP_LOAD_S(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_D(void) @@ -2098,7 +2096,6 @@ FP_LOAD_D(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IW(void) @@ -2157,7 +2154,6 @@ FP_LOAD_IW(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IL(void) @@ -2214,7 +2210,6 @@ FP_LOAD_IL(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void FP_LOAD_IQ(void) @@ -2290,7 +2285,6 @@ FP_LOAD_IQ(void) addbyte(0x1d); addbyte((uint8_t) cpu_state_offset(tag[0])); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline void @@ -2342,7 +2336,6 @@ FP_LOAD_IMM_Q(uint64_t v) addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(TOP)); } - CALL_FUNC((uintptr_t) x87_to_mmxreg); } static __inline int diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 2304aa542..92b721099 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -64,9 +64,6 @@ fpu_POP2(codeblock_t *block, ir_data_t *ir) static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir) { - uop_LOAD_FUNC_ARG_IMM(ir, 0, ((uint16_t)cpu_state.TOP - 1)); - uop_CALL_FUNC(ir, x87_to_mmxreg); - if (block->flags & CODEBLOCK_STATIC_TOP) uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); else diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 5cb385122..5f41c416a 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -74,51 +74,6 @@ x386_dynarec_log(const char *fmt, ...) # define x386_dynarec_log(fmt, ...) #endif -/* Deliberately stashed here; this function is only relevant for dynamic recompilers. */ -#if defined(_MSC_VER) && !defined(__clang__) -# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -# define X87_INLINE_ASM -# endif -#else -# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 || defined __amd64__ -# define X87_INLINE_ASM -# endif -#endif - -#ifdef USE_NEW_DYNAREC -void -x87_to_mmxreg(uint16_t reg) -#else -void -x87_to_mmxreg(void) -#endif -{ -#ifndef USE_NEW_DYNAREC - uint32_t reg = cpu_state.TOP & 7; -#endif - double val = cpu_state.ST[reg & 7]; -#ifdef X87_INLINE_ASM - unsigned char buffer[10]; -#else - x87_conv_t test; -#endif - -#ifdef X87_INLINE_ASM - __asm volatile("" - : - : - : "memory"); - - __asm volatile("fldl %1\n" - "fstpt %0\n" : "=m"(buffer) : "m"(val)); - - cpu_state.MM[reg & 7].q = (*(uint64_t*)buffer); -#else - x87_to80(val, &test); - cpu_state.MM[reg & 7].q = test.eind.ll; -#endif -} - static __inline void fetch_ea_32_long(uint32_t rmdat) { diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 98c6f4938..1d003ddc9 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -829,12 +829,6 @@ extern uint16_t prefetch_queue_get_ip(void); extern int prefetch_queue_get_prefetching(void); extern int prefetch_queue_get_size(void); -#ifdef USE_NEW_DYNAREC -extern void x87_to_mmxreg(uint16_t reg); -#else -extern void x87_to_mmxreg(void); -#endif - #define prefetch_queue_set_suspended(s) prefetch_queue_set_prefetching(!s) #define prefetch_queue_get_suspended !prefetch_queue_get_prefetching From 23b89d88c4e4fee4914d4c20b92a741e25e7c0ca Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Feb 2025 16:51:48 +0600 Subject: [PATCH 0350/1190] Revert "x87: Fix Final Reality discolored screen for interpreter" This reverts commit 6d3816df64aac6cb0e604bab30239c3b4b888265. --- src/cpu/x87_ops.h | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 276c32876..f1362bf76 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -113,33 +113,12 @@ typedef union { static __inline void x87_push(double i) { -#ifdef X87_INLINE_ASM - unsigned char buffer[10]; -#else - x87_conv_t test; -#endif #ifdef USE_NEW_DYNAREC cpu_state.TOP--; #else cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif cpu_state.ST[cpu_state.TOP & 7] = i; - -#ifdef X87_INLINE_ASM - __asm volatile("" - : - : - : "memory"); - - __asm volatile("fldl %1\n" - "fstpt %0\n" : "=m"(buffer) : "m"(i)); - - cpu_state.MM[cpu_state.TOP & 7].q = (*(uint64_t*)buffer); -#else - x87_to80(i, &test); - cpu_state.MM[cpu_state.TOP & 7].q = test.eind.ll; -#endif - #ifdef USE_NEW_DYNAREC cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID; #else @@ -150,11 +129,6 @@ x87_push(double i) static __inline void x87_push_u64(uint64_t i) { -#ifdef X87_INLINE_ASM - unsigned char buffer[10]; -#else - x87_conv_t test; -#endif union { double d; uint64_t ll; @@ -168,21 +142,6 @@ x87_push_u64(uint64_t i) cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif cpu_state.ST[cpu_state.TOP & 7] = td.d; - -#ifdef X87_INLINE_ASM - __asm volatile("" - : - : - : "memory"); - - __asm volatile("fldl %1\n" - "fstpt %0\n" : "=m"(buffer) : "m"(td.d)); - - cpu_state.MM[cpu_state.TOP & 7].q = (*(uint64_t*)buffer); -#else - x87_to80(td.d, &test); - cpu_state.MM[cpu_state.TOP & 7].q = test.eind.ll; -#endif #ifdef USE_NEW_DYNAREC cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID; #else From 843dee57076a28d4028b9105c87ead95e64d7933 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 1 Mar 2025 15:05:39 +0600 Subject: [PATCH 0351/1190] x64 NDR: Properly address the entire cpu_state struct All missing edge cases are now handled where possible --- src/codegen_new/codegen_backend_x86-64_ops.c | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index 236a86ce7..2f65b46e3 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -509,6 +509,11 @@ host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) codegen_alloc_bytes(block, 4); codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ codegen_addbyte(block, imm_data); + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte2(block, 0xc6, 0x85); /*MOVB offset[RBP], imm_data*/ + codegen_addlong(block, offset); + codegen_addbyte(block, imm_data); } else { if ((uintptr_t) p >> 32) fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); @@ -527,6 +532,11 @@ host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) codegen_alloc_bytes(block, 6); 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_addbyte3(block, 0x66, 0xc7, 0x85); /*MOV offset[RBP], imm_data*/ + codegen_addlong(block, offset); + codegen_addword(block, imm_data); } else { if ((uintptr_t) p >> 32) fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); @@ -545,6 +555,11 @@ host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addlong(block, imm_data); + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0xc7, 0x85); /*MOV offset[RBP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); } else { if ((uintptr_t) p >> 32) fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); @@ -566,6 +581,10 @@ host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x88, 0x85 | ((src_reg & 7) << 3)); /*MOVB offset[RBP], src_reg*/ + codegen_addlong(block, offset); } else { if ((uintptr_t) p >> 32) fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); @@ -630,6 +649,10 @@ host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x48, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); } else { if ((uintptr_t) p >> 32) fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); From d15def050aba3e2652355c718918fb78e9c79b53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 1 Mar 2025 10:11:45 +0100 Subject: [PATCH 0352/1190] Fix an unclosed comment in device/keyboard_at.c. --- src/device/keyboard_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index d04ab07e9..e61b8547a 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2526,7 +2526,7 @@ static const scancode scancode_set82[512] = { { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0xF0, 0x17, 0 } }, /* 15a */ { .mk = { 0x67, 0 }, .brk = { 0xf0, 0x67, 0 } }, /* 15b 0x33 LGUI->Muhenkan (in emulator only) */ { .mk = { 0x64, 0 }, .brk = { 0xf0, 0x64, 0 } }, /* 15c 0x35 RGUI->Henkan (in emulator only) */ - { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0xf0, 0x11, 0 } }, /* 15d 0x36 APPLICATION->Kana (in emulator + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0xf0, 0x11, 0 } }, /* 15d 0x36 APPLICATION->Kana (in emulator only) */ { .mk = {0xe0, 0x37, 0 }, .brk = { 0xe0, 0xF0, 0x37, 0 } }, /* 15e */ { .mk = {0xe0, 0x3F, 0 }, .brk = { 0xe0, 0xF0, 0x3F, 0 } }, /* 15f */ { .mk = { 0 }, .brk = { 0 } }, /* 160 */ From 31d05b3e45a60ab1bf0eb057bac8d012d788e031 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 1 Mar 2025 23:58:31 +0900 Subject: [PATCH 0353/1190] modify blank render --- src/video/vid_ps55da2.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 441df620b..46ef4caf6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -257,9 +257,9 @@ #endif #ifdef ENABLE_DA2_LOG -// # define ENABLE_DA2_DEBUGBLT 1 -// # define ENABLE_DA2_DEBUGVRAM 1 -// # define ENABLE_DA2_DEBUGFULLSCREEN 1 +# define ENABLE_DA2_DEBUGBLT 1 +# define ENABLE_DA2_DEBUGVRAM 1 +# define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; @@ -1208,8 +1208,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_DATA: 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); + 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); if (!(da2->crtc[da2->crtcaddr] ^ val)) return; switch (da2->crtcaddr) { @@ -1325,6 +1325,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_DATA: // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); // 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); switch (da2->gdcaddr & 0x1f) { case LG_READ_MAP_SELECT: @@ -1332,6 +1333,11 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_MODE: da2->writemode = val & 3; + /* reset bit mask and plane mask (? idk when) */ + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->writemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; break; case LG_MAP_MASKJ: da2->writemask = val & 0xff; @@ -1429,8 +1435,7 @@ da2_in(uint16_t addr, void *p) // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } - if (da2->bitblt.indata) - temp |= 0x08; + if (da2->bitblt.indata) temp |= 0x09; #ifdef ENABLE_DA2_DEBUGMONWAIT da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); #endif @@ -1524,7 +1529,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 %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -1794,14 +1799,17 @@ void da2_render_blank(da2_t *da2) { int x, xx; + int cwidth; + if (da2->ioctl[LS_MODE] & 0x01) cwidth = 13; /* in character mode */ + else cwidth = 16; if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; for (x = 0; x < da2->hdisp; x++) { - for (xx = 0; xx < 13; xx++) - ((uint32_t *) buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + for (xx = 0; xx < cwidth; xx++) + ((uint32_t *) buffer32->line[da2->displine])[(x * cwidth) + xx + 32] = 0; } } /* Display Adapter Mode 8, E Drawing */ @@ -2152,8 +2160,10 @@ da2_recalctimings(da2_t *da2) double _dispontime, _dispofftime, disptime; /* if output disabled or VGA passthrough */ - if (!(da2->attrc[LV_COMPATIBILITY] & 0x08) || da2->ioctl[LS_MODE] & 0x02) + if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { + da2->render = da2_render_blank; return; + } da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; @@ -3171,7 +3181,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 10ull * TIMER_USEC; + da2->bitblt.timerspeed = 8ull * TIMER_USEC; /* Bitblt execution speed */ timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From f290cc017309494ec6c7bc952b63b2de1e8b1935 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 1 Mar 2025 22:31:10 +0600 Subject: [PATCH 0354/1190] x64 NDR: Fix crashes/undefined behaviour with 2+ GB of allocated RAM --- src/codegen_new/codegen_backend_x86-64.c | 2 +- src/codegen_new/codegen_backend_x86-64_defs.h | 2 +- src/codegen_new/codegen_backend_x86-64_ops.c | 64 +++++++++---------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/codegen_new/codegen_backend_x86-64.c b/src/codegen_new/codegen_backend_x86-64.c index 3cbca28f8..f4a5d024a 100644 --- a/src/codegen_new/codegen_backend_x86-64.c +++ b/src/codegen_new/codegen_backend_x86-64.c @@ -360,7 +360,7 @@ codegen_backend_prologue(codeblock_t *block) host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX); } if (block->flags & CODEBLOCK_NO_IMMEDIATES) - host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t) ram); + host_x86_MOV64_REG_IMM(block, REG_R12, ((uintptr_t) ram) + 2147483648ULL); } void diff --git a/src/codegen_new/codegen_backend_x86-64_defs.h b/src/codegen_new/codegen_backend_x86-64_defs.h index 12f05f01c..7c58fec31 100644 --- a/src/codegen_new/codegen_backend_x86-64_defs.h +++ b/src/codegen_new/codegen_backend_x86-64_defs.h @@ -1,5 +1,5 @@ /*RBP = cpu_state + 128 - R12 = ram (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/ + R12 = ram + 2147483648 (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/ #define REG_AX 0 #define REG_CX 1 #define REG_DX 2 diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index 2f65b46e3..e53c58083 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -505,7 +505,7 @@ host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ codegen_addbyte(block, imm_data); @@ -528,7 +528,7 @@ host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addword(block, imm_data); @@ -551,7 +551,7 @@ host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addlong(block, imm_data); @@ -578,7 +578,7 @@ host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) if (src_reg & 8) fatal("host_x86_MOV8_ABS_REG - bad reg\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ } else if (offset < (1ULL << 32)) { @@ -602,7 +602,7 @@ host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) if (src_reg & 8) fatal("host_x86_MOV16_ABS_REG - bad reg\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ULL << 32)) { @@ -622,7 +622,7 @@ host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) if (src_reg & 8) fatal("host_x86_MOV32_ABS_REG - bad reg\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ULL << 32)) { @@ -646,7 +646,7 @@ host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) if (src_reg & 8) fatal("host_x86_MOV64_ABS_REG - bad reg\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ULL << 32)) { @@ -706,19 +706,19 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + int64_t ram_offset = (uintptr_t) p - (((uintptr_t) ram) + 2147483648ULL); if (dst_reg & 8) fatal("host_x86_MOV8_REG_ABS reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ULL << 32)) { codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); - } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + } else if ((ram_offset >= -2147483648LL) && (ram_offset <= 2147483647LL) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ codegen_addlong(block, ram_offset); @@ -730,19 +730,19 @@ void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + int64_t ram_offset = (uintptr_t) p - (((uintptr_t) ram) + 2147483648ULL); if (dst_reg & 8) fatal("host_x86_MOV16_REG_ABS reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ULL << 32)) { codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); - } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + } else if ((ram_offset >= -2147483648LL) && (ram_offset <= 2147483647LL) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3)); /*MOV dst_reg, ram_offset[R12]*/ codegen_addbyte(block, 0x24); @@ -760,19 +760,19 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + int64_t ram_offset = (uintptr_t) p - (((uintptr_t) ram) + 2147483648ULL); if (dst_reg & 8) fatal("host_x86_MOV32_REG_ABS reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ULL << 32)) { codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); - } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + } else if ((ram_offset >= -2147483648LL) && (ram_offset <= 2147483647LL) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ codegen_addlong(block, ram_offset); @@ -792,7 +792,7 @@ host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (dst_reg & 8) fatal("host_x86_MOV64_REG_ABS reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ULL << 32)) { @@ -845,7 +845,7 @@ host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in if ((dst_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); @@ -863,7 +863,7 @@ host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in if ((dst_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); @@ -880,7 +880,7 @@ host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in if ((dst_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x48); @@ -899,7 +899,7 @@ host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int if ((src_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); @@ -916,7 +916,7 @@ host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int if ((src_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x48); @@ -935,7 +935,7 @@ host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uin if (base_reg & 8) fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); @@ -1107,16 +1107,16 @@ void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + int64_t ram_offset = (uintptr_t) p - (((uintptr_t) ram) + 2147483648ULL); if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + } else if ((ram_offset >= -2147483648LL) && (ram_offset <= 2147483647LL) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0x66, 0x41); codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ @@ -1134,14 +1134,14 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + int64_t ram_offset = (uintptr_t) p - (((uintptr_t) ram) + 2147483648ULL); #if 0 if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); #endif - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { if (dst_reg & 8) { codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x44); @@ -1150,7 +1150,7 @@ host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ } - } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + } else if ((ram_offset >= -2147483648LL) && (ram_offset <= 2147483647LL) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); @@ -1173,15 +1173,15 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + int64_t ram_offset = (uintptr_t) p - (((uintptr_t) ram) + 2147483648ULL); if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); - if (offset >= -128 && offset < 127) { + if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + } else if ((ram_offset >= -2147483648LL) && (ram_offset <= 2147483647LL) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { codegen_alloc_bytes(block, 9); codegen_addbyte(block, 0x41); codegen_addbyte4(block, 0x0f, 0xb7, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ From 6b55b2383a3fd6096f0e39a4c749272ecddc5650 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 2 Mar 2025 23:14:10 +0600 Subject: [PATCH 0355/1190] Misc NDR changes Force NDR on ARMv7/ARM64 Make GCC/Clang not use anything in the red zone Compile with `-fno-omit-frame-pointer` --- CMakeLists.txt | 7 +++++- src/CMakeLists.txt | 3 +++ src/codegen_new/codegen_backend_x86-64.c | 18 +++++++++++++++ src/codegen_new/codegen_backend_x86-64_ops.c | 24 ++++++++++---------- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa687222a..5c33bb3e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,13 +132,18 @@ option(RTMIDI "RtMidi" option(FLUIDSYNTH "FluidSynth" ON) option(MUNT "MUNT" ON) option(VNC "VNC renderer" OFF) -option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF) option(GDBSTUB "Enable GDB stub server for debugging" OFF) option(DEV_BRANCH "Development branch" OFF) option(DISCORD "Discord Rich Presence support" ON) option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF) +if((ARCH STREQUAL "arm64") OR (ARCH STREQUAL "arm")) + set(NEW_DYNAREC ON) +else() + option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) +endif() + if(WIN32) set(QT ON) option(CPPTHREADS "C++11 threads" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7d6daff9c..ee17a7a21 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -223,6 +223,9 @@ elseif(APPLE AND NOT QT) COMPONENT Runtime) endif() +if(NEW_DYNAREC AND (ARCH STREQUAL "x86_64") AND (NOT WIN32)) + add_compile_options(-mno-red-zone -fno-omit-frame-pointer) +endif() # Install the PDB file on Windows builds if(MSVC) diff --git a/src/codegen_new/codegen_backend_x86-64.c b/src/codegen_new/codegen_backend_x86-64.c index f4a5d024a..6242ea40b 100644 --- a/src/codegen_new/codegen_backend_x86-64.c +++ b/src/codegen_new/codegen_backend_x86-64.c @@ -315,13 +315,19 @@ codegen_backend_init(void) # endif host_x86_CALL(block, (void *) x86gpf); codegen_exit_rout = &codeblock[block_current].data[block_pos]; +#ifdef _WIN64 host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); +#else + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x48); +#endif host_x86_POP(block, REG_R15); host_x86_POP(block, REG_R14); host_x86_POP(block, REG_R13); host_x86_POP(block, REG_R12); +#ifdef _WIN64 host_x86_POP(block, REG_RDI); host_x86_POP(block, REG_RSI); +#endif host_x86_POP(block, REG_RBP); host_x86_POP(block, REG_RDX); host_x86_RET(block); @@ -346,13 +352,19 @@ codegen_backend_prologue(codeblock_t *block) block_pos = BLOCK_START; /*Entry code*/ host_x86_PUSH(block, REG_RBX); host_x86_PUSH(block, REG_RBP); +#ifdef _WIN64 host_x86_PUSH(block, REG_RSI); host_x86_PUSH(block, REG_RDI); +#endif host_x86_PUSH(block, REG_R12); host_x86_PUSH(block, REG_R13); host_x86_PUSH(block, REG_R14); host_x86_PUSH(block, REG_R15); +#ifdef _WIN64 host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38); +#else + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x48); +#endif host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t) &cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); @@ -366,13 +378,19 @@ codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { +#ifdef _WIN64 host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); +#else + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x48); +#endif host_x86_POP(block, REG_R15); host_x86_POP(block, REG_R14); host_x86_POP(block, REG_R13); host_x86_POP(block, REG_R12); +#ifdef _WIN64 host_x86_POP(block, REG_RDI); host_x86_POP(block, REG_RSI); +#endif host_x86_POP(block, REG_RBP); host_x86_POP(block, REG_RDX); host_x86_RET(block); diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index e53c58083..39173505b 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -848,11 +848,11 @@ host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); + codegen_addbyte(block, 0x66); /* MOV dst_reg, [RSP + offset] */ codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); /* MOV dst_reg, [base_reg + offset] */ } } else fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); @@ -866,10 +866,10 @@ host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); /* MOV dst_reg, [RSP + offset] */ } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); /* MOV dst_reg, [base_reg + offset] */ } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -883,11 +883,11 @@ host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x48); + codegen_addbyte(block, 0x48); /* MOV dst_reg, [RSP + offset] */ codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); /* MOV dst_reg, [base_reg + offset] */ } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -901,11 +901,11 @@ host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { - codegen_alloc_bytes(block, 4); + codegen_alloc_bytes(block, 4); /* MOV [RSP + offset], src_reg*/ codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); /* MOV [base_reg + offset], src_reg*/ } } else fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); @@ -919,11 +919,11 @@ host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x48); + codegen_addbyte(block, 0x48); /* MOV [RSP + offset], src_reg*/ codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); /* MOV [base_reg + offset], src_reg*/ } } else fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); @@ -938,11 +938,11 @@ host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uin if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); + codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); /* MOV [RSP + offset], imm_data */ codegen_addlong(block, imm_data); } else { codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); + codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); /* MOV [base_reg + offset], src_reg*/ codegen_addlong(block, imm_data); } } else From 8d6087a016ba1eb034c9c6d6d99533d124cb418e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 3 Mar 2025 01:06:03 +0600 Subject: [PATCH 0356/1190] Revert some unnecessary changes for NDR --- src/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee17a7a21..fb3bf9f50 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -223,10 +223,6 @@ elseif(APPLE AND NOT QT) COMPONENT Runtime) endif() -if(NEW_DYNAREC AND (ARCH STREQUAL "x86_64") AND (NOT WIN32)) - add_compile_options(-mno-red-zone -fno-omit-frame-pointer) -endif() - # Install the PDB file on Windows builds if(MSVC) # CMake fully supports PDB files on MSVC-compatible compilers From 54650963f02a995264d2b4cb3fb103c9bc0dac52 Mon Sep 17 00:00:00 2001 From: The Dax Date: Sun, 2 Mar 2025 14:12:25 -0500 Subject: [PATCH 0357/1190] Fix Acer 100T machine not showing up on Linux due to case-sensitivity. --- src/machine/m_at_286_386sx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 24cb88f09..9086f7c8a 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -742,7 +742,7 @@ machine_at_acer100t_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/acer100t/acer386.bin", + ret = bios_load_linear("roms/machines/acer100t/acer386.BIN", 0x000f0000, 65536, 0); if (bios_only || !ret) From fae26729f103010ddc7e621a37083bc4ae6d5736 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 3 Mar 2025 22:03:52 +0600 Subject: [PATCH 0358/1190] S3 ViRGE: Make IRQs happen in main thread FIFO is also no longer immediately woken up upon writes --- src/video/vid_s3_virge.c | 57 +++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 91b186240..05cd42459 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -338,6 +338,7 @@ typedef struct virge_t { event_t * fifo_not_full_event; atomic_int virge_busy; + atomic_uint virge_irq_req; uint8_t subsys_stat; uint8_t subsys_cntl; @@ -373,6 +374,9 @@ typedef struct virge_t { uint32_t dma_mmio_addr; uint32_t dma_data_type; + pc_timer_t wake_timer; + pc_timer_t irq_timer; + int pci; int is_agp; } virge_t; @@ -383,6 +387,28 @@ wake_fifo_thread(virge_t *virge) { thread_set_event(virge->wake_fifo_thread); } +void +s3_virge_wake_fifo_timer(void* priv) +{ + virge_t *virge = (virge_t *) priv; + + thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +void +s3_virge_wake_fifo_thread(virge_t *virge) +{ + if (!timer_is_enabled(&virge->wake_timer)) { + /*Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work.*/ + timer_on_auto(&virge->wake_timer, 100.0); + } + if (!timer_is_enabled(&virge->irq_timer)) + timer_on_auto(&virge->irq_timer, 100.0); +} + static virge_t *reset_state = NULL; static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; @@ -471,6 +497,19 @@ s3_virge_update_irqs(virge_t *virge) pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } +void +s3_virge_update_irq_timer(void* priv) +{ + virge_t *virge = (virge_t *) priv; + + if (virge->virge_irq_req) { + virge->virge_irq_req--; + s3_virge_update_irqs(virge); + } + + timer_on_auto(&virge->irq_timer, 100.); +} + static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { @@ -1101,6 +1140,9 @@ static void s3_virge_vblank_start(svga_t *svga) { virge_t *virge = (virge_t *) svga->priv; + if (virge->virge_irq_req) + virge->virge_irq_req--; + virge->subsys_stat |= INT_VSY; s3_virge_update_irqs(virge); } @@ -1795,7 +1837,8 @@ fifo_thread(void *param) if (virge->cmd_dma) virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); - s3_virge_update_irqs(virge); + //s3_virge_update_irqs(virge); + virge->virge_irq_req++; } } @@ -1835,10 +1878,8 @@ s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) virge->fifo_write_idx++; - if (FIFO_ENTRIES > 0xe000) - wake_fifo_thread(virge); - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(virge); + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 16) + s3_virge_wake_fifo_thread(virge); } static void @@ -3642,7 +3683,8 @@ render_thread(void *param) } virge->s3d_busy = 0; virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); + //s3_virge_update_irqs(virge); + virge->virge_irq_req++; } } @@ -4571,6 +4613,9 @@ s3_virge_init(const device_t *info) virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); + timer_add(&virge->wake_timer, s3_virge_wake_fifo_timer, virge, 0); + timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 0); + virge->local = info->local; *reset_state = *virge; From e24c9d51633730b165aa7c332600df8aee140c79 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 3 Mar 2025 23:22:24 +0600 Subject: [PATCH 0359/1190] S3 ViRGE: Use a significantly faster version of the ROP code DirectDraw tests now run significantly faster, and Direct3D tests also now run smoothly. --- src/video/vid_s3_virge.c | 788 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 775 insertions(+), 13 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 05cd42459..62ffcff0c 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -2216,19 +2216,781 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) } \ } while (0) -#define MIX() \ - do { \ - int c; \ - for (c = 0; c < 24; c++) { \ - int d = (dest & (1 << c)) ? 1 : 0; \ - if (source & (1 << c)) \ - d |= 2; \ - if (pattern & (1 << c)) \ - d |= 4; \ - if (virge->s3d.rop & (1 << d)) \ - out |= (1 << c); \ - } \ - } while (0) +#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; \ + } \ + } + +#define MIX() do { ROPMIX(virge->s3d.rop & 0xFF, dest, pattern, source, out); out &= 0xFFFFFF; } while (0) #define WRITE(addr, val) \ do { \ From 21f5415328cd5c101d020f3d1c601ba16322c53f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 4 Mar 2025 01:31:19 +0600 Subject: [PATCH 0360/1190] Trident TGUI: Use a significantly faster version of the ROP code At least 30%-40% performance improvement seen --- src/video/vid_tgui9440.c | 790 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 778 insertions(+), 12 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index d1391f1d1..c6edabac5 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -1457,18 +1457,784 @@ enum { else \ dat = vram_l[(addr) & (tgui->vram_mask >> 2)]; -#define MIX() \ - do { \ - out = 0; \ - for (c = 0; c < 32; c++) { \ - d = (dst_dat & (1 << c)) ? 1 : 0; \ - if (src_dat & (1 << c)) \ - d |= 2; \ - if (pat_dat & (1 << c)) \ - d |= 4; \ - if (tgui->accel.rop & (1 << d)) \ - out |= (1 << c); \ - } \ +#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; \ + } \ + } + +#define MIX() \ + do { \ + out = 0; \ + ROPMIX(tgui->accel.rop, dst_dat, pat_dat, src_dat, out); \ } while (0) #define WRITE(addr, dat) \ From a9653e5a99393924f09ab6f6c72fb8afc47310bf Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 3 Mar 2025 21:21:02 +0100 Subject: [PATCH 0361/1190] TGUI9440: Fix two newly introduced warnings. --- src/video/vid_tgui9440.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index c6edabac5..af203f327 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -2256,8 +2256,6 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) const uint32_t *pattern_data; int x; int y; - int c; - int d; uint32_t out; uint32_t src_dat = 0; uint32_t dst_dat; From 6f53e69efe666ac6824b03f098edc11cf8db97ff Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Mar 2025 07:47:15 +0900 Subject: [PATCH 0362/1190] added bit mask reset and alignment for compatibility with OS/2 J2.1 (beta), Windows 3.1 and Multitool Chart K3.1 in J-DOS. --- src/video/vid_ps55da2.c | 125 ++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 46ef4caf6..1b9ec473e 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -327,7 +327,7 @@ typedef struct da2_t { int fast; uint8_t colourcompare, colournocare; int readmode, writemode, readplane; - uint8_t writemask; + uint8_t planemask; uint32_t charseta, charsetb; uint8_t egapal[16]; @@ -441,6 +441,7 @@ 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); typedef union { uint32_t d; @@ -687,6 +688,7 @@ da2_bitblt_load(da2_t *da2) value32 |= da2->bitblt.payload[i + 2]; da2_bltlog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + // da2->gdcreg[da2->bitblt.payload[i + 1]] = value32; i += 3; break; case 0x91: @@ -699,6 +701,7 @@ da2_bitblt_load(da2_t *da2) value32 |= da2->bitblt.payload[i + 2]; da2_bltlog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + // da2->gdcreg[da2->bitblt.payload[i + 1]] = value32; i += 5; break; case 0x99: @@ -716,6 +719,7 @@ da2_bitblt_load(da2_t *da2) da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + // da2->gdcreg[da2->bitblt.payload[i + 1]] = value64; i += 7; break; case 0x00: @@ -1321,26 +1325,27 @@ 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->gdcaddr = val; break; case LG_DATA: - // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + // 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_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; switch (da2->gdcaddr & 0x1f) { case LG_READ_MAP_SELECT: da2->readplane = val & 0x7; break; case LG_MODE: da2->writemode = val & 3; - /* reset bit mask and plane mask (? idk when) */ - da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; - da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; - da2->writemask = 0xff; - da2->gdcreg[LG_MAP_MASKJ] = 0xff; + /* Resettting masks here gliches the screen in IBM Multitool Chart K3.1 */ + // da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + // da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + // da2->planemask = 0xff; + // da2->gdcreg[LG_MAP_MASKJ] = 0xff; break; case LG_MAP_MASKJ: - da2->writemask = val & 0xff; + da2->planemask = val & 0xff; break; case LG_COMMAND: break; @@ -1348,7 +1353,6 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); return; } - da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; break; // case 0x3ed: /* used by Windows 3.1 display driver */ // da2->gdcreg[5] = val & 0xff; @@ -1424,7 +1428,7 @@ da2_in(uint16_t addr, void *p) temp |= 0x80; } temp &= 0xf6; /* clear busy bit */ - // if (da2->bitblt.indata) /* for OS/2 J1.3 */ + // 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); @@ -1435,7 +1439,7 @@ da2_in(uint16_t addr, void *p) // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } - if (da2->bitblt.indata) temp |= 0x09; + 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); #endif @@ -1529,7 +1533,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 %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_log("DA2 Outw addr %03X val %04X\n", addr, val); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -1550,7 +1554,15 @@ da2_outw(uint16_t addr, uint16_t val, void *p) break; case 0x3EC: // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_log(" "); + // val = rightRotate(val, 8); + // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); + /* reset masks */ + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->planemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; break; case 0x3ED: da2->gdcaddr = LG_MODE; @@ -2340,11 +2352,12 @@ da2_mca_reset(void *p) da2_mca_write(0x102, 0, da2); } +/* ROP gdcinput and gdcsrc, and write the result with bitmask at addr (byte) */ static void da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) { for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, bitmask); switch (da2->gdcreg[LG_COMMAND] & 0x03) { case 0: /*Set*/ @@ -2368,13 +2381,15 @@ da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) } } } +/* ROP gdcinput and gdcsrc, and write the result with bitmask at addr (word) */ static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) { + if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = rightRotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { // da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); switch (da2->gdcreg[LG_COMMAND] & 0x03) { case 0: /*Set*/ @@ -2415,7 +2430,6 @@ da2_mmio_read(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; addr &= DA2_MASK_MMIO; - if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) /* linear access */ @@ -2455,7 +2469,7 @@ da2_mmio_read(uint32_t addr, void *p) cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ - // da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; for (int i = 0; i < 8; i++) { @@ -2474,7 +2488,9 @@ static uint16_t da2_mmio_readw(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; - //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + // da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); + if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } else if (!(da2->ioctl[LS_MODE] & 1)) {/* 16 color or 256 color mode */ @@ -2566,11 +2582,14 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask to even address */ - if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + /* align bitmask with even address for OS/2 J2.0 (need to verify the condition with Win 3.x) */ + if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; + #ifdef ENABLE_DA2_DEBUGVRAM - da2_log("da2_wB %x %02x\n", addr, val); + // da2_log("da2_wB %x %02x\n", addr, val); + da2_log("da2_wB %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) { @@ -2581,7 +2600,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) for (int i = 0; i < 8; i++) { int pixeldata = 0; if (val & (1 << (7 - i))) - pixeldata = (da2->writemask & 0xf); + pixeldata = (da2->planemask & 0xf); fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; @@ -2614,7 +2633,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) switch (da2->writemode) { case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) + if (da2->planemask & (1 << i)) DA2_vram_w(addr | i, da2->gdcsrc[i], da2); break; case 0:/* equiv to vga write mode 0 */ @@ -2622,7 +2641,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) + if (da2->planemask & (1 << i)) DA2_vram_w(addr | i, val, da2); } else { for (int i = 0; i < 8; i++) @@ -2631,8 +2650,8 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) else da2->gdcinput[i] = val; - for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ + // 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 @@ -2640,17 +2659,17 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } 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->writemask & (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 { + // 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) @@ -2658,7 +2677,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) bitmask &= val; for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, bitmask, da2); break; } @@ -2678,22 +2697,25 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; - uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + uint16_t bitmask; addr &= DA2_MASK_MMIO; + bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; #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 ", addr); + fprintf(da2->mmdbg_fp, "\nW %x %x ", addr, val); for (int i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } for (int i = 0; i < 16; i++) { int pixeldata = 0; if (val & (1 << (15 - i))) - pixeldata = (da2->writemask & 0xf); + pixeldata = (da2->planemask & 0xf); fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; @@ -2727,7 +2749,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) switch (da2->writemode) { case 2: for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { DA2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); DA2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); } @@ -2737,7 +2759,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { DA2_vram_w(addr | i, val & 0xff, da2); DA2_vram_w((addr + 8) | i, val >> 8, da2); } @@ -2752,18 +2774,18 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) } break; case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - DA2_vram_w(addr | i, wdata & 0xff, da2); - DA2_vram_w((addr + 8) | i, wdata >> 8, da2); - } - } else { + // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + // for (int i = 0; i < 8; i++) + // if (da2->planemask & (1 << i)) { + // uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + // DA2_vram_w(addr | i, wdata & 0xff, da2); + // DA2_vram_w((addr + 8) | i, wdata >> 8, da2); + // } + // } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); da2_gdcropW(addr, bitmask, da2); - } + // } break; case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) @@ -2771,7 +2793,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) bitmask &= val; for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; da2_gdcropW(addr, bitmask, da2); break; } @@ -2782,13 +2804,14 @@ static void da2_mmio_writew(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; + // if (da2->bitblt.exec != DA2_BLT_CIDLE) /* Bitblt is in operation. */ + // return; // if ((addr & ~0x1ffff) != 0xA0000) return; if (da2->ioctl[LS_MMIO] & 0x10) { // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ - // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); } else { /* mode 3h text */ @@ -3181,7 +3204,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 8ull * TIMER_USEC; /* Bitblt execution speed */ + da2->bitblt.timerspeed = 5ull * TIMER_USEC; /* Bitblt execution speed */ timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From e798030022d9ac1d0adfdbeada832a26aa9d33ed Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Mar 2025 11:38:31 +0900 Subject: [PATCH 0363/1190] modify bit mask alignment, added delay for vidsel for Win 3.1. And added delay for switching video selector --- src/video/vid_ps55da2.c | 72 +++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1b9ec473e..0f5851c6f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -431,6 +431,7 @@ typedef struct da2_t { uint8_t pos_regs[8]; svga_t *mb_vga; uint8_t monitorid; + pc_timer_t timer_vidupd; int old_pos2; } da2_t; @@ -1108,11 +1109,13 @@ da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - da2_bitblt_exec(da2); - else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { - da2->bitblt.exec = DA2_BLT_CLOAD; + /* do async operation but it causes the scrolling text glitch in OS/2 J1.3 Command Prompt (TODO) */ + if (da2->bitblt.exec != DA2_BLT_CIDLE) { + while (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); + } else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { + da2->bitblt.exec = DA2_BLT_CLOAD; + da2_bitblt_exec(da2); } else { // timer_disable(&da2->bitblt.timer); } @@ -1202,8 +1205,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) { - da2->fullchange = changeframecount; - da2_recalctimings(da2); + da2_log("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: @@ -1338,7 +1340,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_MODE: da2->writemode = val & 3; - /* Resettting masks here gliches the screen in IBM Multitool Chart K3.1 */ + /* Resettting masks here gliches chart drawing in IBM Multitool Chart K3.1 */ // da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; // da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; // da2->planemask = 0xff; @@ -1558,11 +1560,13 @@ da2_outw(uint16_t addr, uint16_t val, void *p) // val = rightRotate(val, 8); // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); - /* reset masks */ - da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; - da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; - da2->planemask = 0xff; - da2->gdcreg[LG_MAP_MASKJ] = 0xff; + /* reset masks for compatibility with Win 3.1 solitaire */ + if (da2->gdcaddr == LG_MODE) { + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->planemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; + } break; case 0x3ED: da2->gdcaddr = LG_MODE; @@ -2151,8 +2155,9 @@ da2_render_color_8bpp(da2_t *da2) } void -da2_updatevidselector(da2_t *da2) +da2_updatevidselector_tick(void *priv) { + da2_t *da2 = (da2_t *) priv; if (da2->ioctl[LS_MODE] & 0x02) { /* VGA passthrough mode */ da2->override = 1; @@ -2165,6 +2170,12 @@ da2_updatevidselector(da2_t *da2) } } +void +da2_updatevidselector(da2_t *da2) +{ + timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); +} + void da2_recalctimings(da2_t *da2) { @@ -2386,6 +2397,7 @@ static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) { if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = rightRotate(bitmask, 8); + // if((addr & 8)) bitmask = rightRotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { @@ -2582,9 +2594,15 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask with even address for OS/2 J2.0 (need to verify the condition with Win 3.x) */ - if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; + /* align bitmask with even address (need to verify the condition with OS/2 J2.x, Win 3.x and A-Train IV Win) */ + /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ + // if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + /* Without byte align: Win 3.1 (Window Title) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ + /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok, DOS J4.0 MC - ok */ + if ((addr & 1)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + else + /* No align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - bad */ + bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGVRAM // da2_log("da2_wB %x %02x\n", addr, val); @@ -2756,7 +2774,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) break; case 0: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->planemask & (1 << i)) { @@ -2774,22 +2792,13 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) } break; case 1: - // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - // for (int i = 0; i < 8; i++) - // if (da2->planemask & (1 << i)) { - // uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - // DA2_vram_w(addr | i, wdata & 0xff, da2); - // DA2_vram_w((addr + 8) | i, wdata >> 8, da2); - // } - // } else { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - // } + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); break; case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); bitmask &= val; for (int i = 0; i < 8; i++) @@ -3117,7 +3126,6 @@ da2_reset(void *priv) /* Initialize drawing */ da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; da2_reset_ioctl(da2); da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ @@ -3192,6 +3200,8 @@ da2_init(UNUSED(const device_t *info)) da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); #endif da2->bitblt.payload_addr = 0; + + timer_add(&da2->timer_vidupd, da2_updatevidselector_tick, da2, 0);/* Init timer before executing reset */ da2_reset(da2); mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); From 5a77092a717164bd67c3a8f786753f30e8c67e04 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 00:38:39 +0900 Subject: [PATCH 0364/1190] add support for 2nd sbcs in videomode 03 --- src/video/vid_ps55da2.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 0f5851c6f..1338304f1 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1111,7 +1111,7 @@ da2_bitblt_dopayload(void *priv) timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); /* do async operation but it causes the scrolling text glitch in OS/2 J1.3 Command Prompt (TODO) */ if (da2->bitblt.exec != DA2_BLT_CIDLE) { - while (da2->bitblt.exec != DA2_BLT_CIDLE) + while (da2->bitblt.exec != DA2_BLT_CIDLE) /* this disables async operation */ da2_bitblt_exec(da2); } else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { da2->bitblt.exec = DA2_BLT_CLOAD; @@ -2015,9 +2015,14 @@ da2_render_textm3(da2_t *da2) } } else { /* the char code is SBCS (ANK) */ - uint16_t font = da2->mmio.ram[DA2_GAIJIRAM_SBCS + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ + uint32_t fontbase; + if (extattr & 0x80) /* second map of SBCS font */ + fontbase = DA2_GAIJIRAM_SBEX; + else + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase+ chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[DA2_GAIJIRAM_SBCS+ chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2176,6 +2181,17 @@ da2_updatevidselector(da2_t *da2) timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); } +/* + Video modes supported by DOS J4.0 for the DA-2 (The DA-2 doesn't have a video BIOS on its card.) + Mode (hex) Type Colors Format Base Address PELs + 3 A/N/K 16 80 x 25 B8000h 1040 x 725 + 8 A/N/K 1 80 x 25 E0000h 1040 x 725 + A APA 1 78 x 25 A0000h 1024 x 768 + D APA 16 78 x 25 A0000h 1024 x 768 + E A/N/K 16 80 x 25 E0000h 1040 x 725 + F APA 256 A0000h 1024 x 768 + 45 (undoc) APA 16 A0000h 1040 x 768 +*/ void da2_recalctimings(da2_t *da2) { From 73576bb61ed1fb90be962f87028c3a6244b7723d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 5 Mar 2025 01:23:37 +0600 Subject: [PATCH 0365/1190] Revert "S3 ViRGE: Make IRQs happen in main thread" This reverts commit fae26729f103010ddc7e621a37083bc4ae6d5736. --- src/video/vid_s3_virge.c | 57 +++++----------------------------------- 1 file changed, 6 insertions(+), 51 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 62ffcff0c..af33003cb 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -338,7 +338,6 @@ typedef struct virge_t { event_t * fifo_not_full_event; atomic_int virge_busy; - atomic_uint virge_irq_req; uint8_t subsys_stat; uint8_t subsys_cntl; @@ -374,9 +373,6 @@ typedef struct virge_t { uint32_t dma_mmio_addr; uint32_t dma_data_type; - pc_timer_t wake_timer; - pc_timer_t irq_timer; - int pci; int is_agp; } virge_t; @@ -387,28 +383,6 @@ wake_fifo_thread(virge_t *virge) { thread_set_event(virge->wake_fifo_thread); } -void -s3_virge_wake_fifo_timer(void* priv) -{ - virge_t *virge = (virge_t *) priv; - - thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -void -s3_virge_wake_fifo_thread(virge_t *virge) -{ - if (!timer_is_enabled(&virge->wake_timer)) { - /*Don't wake FIFO thread immediately - if we do that it will probably - process one word and go back to sleep, requiring it to be woken on - almost every write. Instead, wait a short while so that the CPU - emulation writes more data so we have more batched-up work.*/ - timer_on_auto(&virge->wake_timer, 100.0); - } - if (!timer_is_enabled(&virge->irq_timer)) - timer_on_auto(&virge->irq_timer, 100.0); -} - static virge_t *reset_state = NULL; static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; @@ -497,19 +471,6 @@ s3_virge_update_irqs(virge_t *virge) pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } -void -s3_virge_update_irq_timer(void* priv) -{ - virge_t *virge = (virge_t *) priv; - - if (virge->virge_irq_req) { - virge->virge_irq_req--; - s3_virge_update_irqs(virge); - } - - timer_on_auto(&virge->irq_timer, 100.); -} - static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { @@ -1140,9 +1101,6 @@ static void s3_virge_vblank_start(svga_t *svga) { virge_t *virge = (virge_t *) svga->priv; - if (virge->virge_irq_req) - virge->virge_irq_req--; - virge->subsys_stat |= INT_VSY; s3_virge_update_irqs(virge); } @@ -1837,8 +1795,7 @@ fifo_thread(void *param) if (virge->cmd_dma) virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); - //s3_virge_update_irqs(virge); - virge->virge_irq_req++; + s3_virge_update_irqs(virge); } } @@ -1878,8 +1835,10 @@ s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) virge->fifo_write_idx++; - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 16) - s3_virge_wake_fifo_thread(virge); + if (FIFO_ENTRIES > 0xe000) + wake_fifo_thread(virge); + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(virge); } static void @@ -4445,8 +4404,7 @@ render_thread(void *param) } virge->s3d_busy = 0; virge->subsys_stat |= INT_S3D_DONE; - //s3_virge_update_irqs(virge); - virge->virge_irq_req++; + s3_virge_update_irqs(virge); } } @@ -5375,9 +5333,6 @@ s3_virge_init(const device_t *info) virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); - timer_add(&virge->wake_timer, s3_virge_wake_fifo_timer, virge, 0); - timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 0); - virge->local = info->local; *reset_state = *virge; From 92d69475f4eea136226842784ffdcf2d862dbb77 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 5 Mar 2025 02:17:51 +0600 Subject: [PATCH 0366/1190] Only retain the newer IRQ updating code --- src/video/vid_s3_virge.c | 43 ++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index af33003cb..904d4a4cf 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -338,6 +338,7 @@ typedef struct virge_t { event_t * fifo_not_full_event; atomic_int virge_busy; + atomic_uint irq_pending; uint8_t subsys_stat; uint8_t subsys_cntl; @@ -375,6 +376,8 @@ typedef struct virge_t { int pci; int is_agp; + + pc_timer_t irq_timer; } virge_t; static __inline void @@ -471,6 +474,19 @@ s3_virge_update_irqs(virge_t *virge) pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } +static void +s3_virge_update_irq_timer(void* priv) +{ + virge_t *virge = (virge_t *) priv; + + if (virge->irq_pending) { + virge->irq_pending--; + s3_virge_update_irqs(virge); + } + + timer_on_auto(&virge->irq_timer, 100.); +} + static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { @@ -1101,6 +1117,8 @@ static void s3_virge_vblank_start(svga_t *svga) { virge_t *virge = (virge_t *) svga->priv; + if (virge->irq_pending) + virge->irq_pending--; virge->subsys_stat |= INT_VSY; s3_virge_update_irqs(virge); } @@ -1784,18 +1802,18 @@ fifo_thread(void *param) virge->fifo_read_idx++; fifo->addr_type = FIFO_INVALID; - if (FIFO_ENTRIES > 0xe000) - thread_set_event(virge->fifo_not_full_event); + if (FIFO_ENTRIES > 0xe000) + thread_set_event(virge->fifo_not_full_event); - end_time = plat_timer_read(); - virge_time += end_time - start_time; - } - virge->virge_busy = 0; - virge->subsys_stat |= (INT_FIFO_EMP | INT_3DF_EMP); - if (virge->cmd_dma) - virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); + end_time = plat_timer_read(); + virge_time += end_time - start_time; + } + virge->virge_busy = 0; + virge->subsys_stat |= (INT_FIFO_EMP | INT_3DF_EMP); + if (virge->cmd_dma) + virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); - s3_virge_update_irqs(virge); + virge->irq_pending++; } } @@ -4404,7 +4422,7 @@ render_thread(void *param) } virge->s3d_busy = 0; virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); + virge->irq_pending++; } } @@ -5062,6 +5080,7 @@ s3_virge_disable_handlers(virge_t *dev) reset_state->svga.timer = dev->svga.timer; reset_state->svga.timer8514 = dev->svga.timer8514; + reset_state->irq_timer = dev->irq_timer; } static void @@ -5333,6 +5352,8 @@ s3_virge_init(const device_t *info) virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); + timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 1); + virge->local = info->local; *reset_state = *virge; From 6c92eb61bf4e8c0d225b9f6354324ff766cc13ab Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 07:12:15 +0900 Subject: [PATCH 0367/1190] fix a screen glitch in OS/2 DOS MODE 1 fix a glitch in OS/2 DOS MODE 1 (monochrome graphics) --- src/video/vid_ps55da2.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1338304f1..6568d9b45 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -259,7 +259,7 @@ #ifdef ENABLE_DA2_LOG # define ENABLE_DA2_DEBUGBLT 1 # define ENABLE_DA2_DEBUGVRAM 1 -# define ENABLE_DA2_DEBUGFULLSCREEN 1 +// # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; @@ -1227,7 +1227,9 @@ da2_out(uint16_t addr, uint16_t val, void *p) val = 0; break; case LC_START_ADDRESS_HIGH: - // if (da2->crtc[0x1c] & 0x40) return; + case LC_START_ADDRESS_LOW: + /* OS/2 DOS in MODE 1 read this to set the base line, but it does not work correctly. */ + val = 0; break; case LC_VERTICAL_TOTALJ: /* Vertical Total */ case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ @@ -1248,8 +1250,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_H_DISPLAY_ENABLE_END: case LC_VERTICAL_TOTALJ: case LC_MAXIMUM_SCAN_LINE: - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: + // case LC_START_ADDRESS_HIGH: + // case LC_START_ADDRESS_LOW: case LC_VERTICAL_SYNC_START: case LC_V_DISPLAY_ENABLE_END: case LC_START_VERTICAL_BLANK: @@ -2235,7 +2237,7 @@ da2_recalctimings(da2_t *da2) // da2->interlace = 0; - // da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + // da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW];//w + b da2->ca_adj = 0; da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; @@ -2517,7 +2519,7 @@ da2_mmio_readw(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; // da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); - da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); + // da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); @@ -2553,7 +2555,7 @@ da2_mmio_readw(uint32_t addr, void *p) } return ~ret; } else { - // da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + da2_log("da2_Rw: %05x(%d) = %04x\n", addr, da2->readplane, da2->gdcla[da2->readplane]); return da2->gdcla[da2->readplane]; } } else { @@ -3050,11 +3052,11 @@ da2_poll(void *priv) = 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->ma <<= 1; + // da2->maback <<= 1; da2->ca <<= 1; - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + // da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF); } if (da2->vc == da2->vtotal) { // da2_log("VC vtotal\n"); From 5b7766bb7ab571aee906dac14f8548e53905586c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 12:35:56 +0900 Subject: [PATCH 0368/1190] disable debug logging, update comments --- src/video/vid_ps55da2.c | 45 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 6568d9b45..335cbf86d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -10,7 +10,7 @@ * * Notes: There are some known issues that should be corrected. * - Incorrect foreground text color appears on an active window in OS/2 J1.3. - * - BitBlt's text drawing function does not work correctly. + * - 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. @@ -253,11 +253,11 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 +// #define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG -# define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGBLT 1 # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 @@ -1228,7 +1228,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LC_START_ADDRESS_HIGH: case LC_START_ADDRESS_LOW: - /* OS/2 DOS in MODE 1 read this to set the base line, but it does not work correctly. */ + /* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00. + OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */ val = 0; break; case LC_VERTICAL_TOTALJ: /* Vertical Total */ @@ -1625,11 +1626,13 @@ da2_inb(uint16_t addr, void *p) uint16_t da2_inw(uint16_t addr, void *p) { - // uint16_t temp; + uint16_t temp; da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; da2->outflipflop = 0; - return da2_in(addr, da2); + temp = da2_in(addr, da2); + da2_log("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 @@ -2184,15 +2187,15 @@ da2_updatevidselector(da2_t *da2) } /* - Video modes supported by DOS J4.0 for the DA-2 (The DA-2 doesn't have a video BIOS on its card.) - Mode (hex) Type Colors Format Base Address PELs - 3 A/N/K 16 80 x 25 B8000h 1040 x 725 - 8 A/N/K 1 80 x 25 E0000h 1040 x 725 - A APA 1 78 x 25 A0000h 1024 x 768 - D APA 16 78 x 25 A0000h 1024 x 768 - E A/N/K 16 80 x 25 E0000h 1040 x 725 - F APA 256 A0000h 1024 x 768 - 45 (undoc) APA 16 A0000h 1040 x 768 + 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 + 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 */ void da2_recalctimings(da2_t *da2) @@ -2499,7 +2502,9 @@ da2_mmio_read(uint32_t addr, void *p) cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ +#ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); +#endif if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; for (int i = 0; i < 8; i++) { @@ -2555,7 +2560,9 @@ da2_mmio_readw(uint32_t addr, void *p) } return ~ret; } else { +#ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_Rw: %05x(%d) = %04x\n", addr, da2->readplane, da2->gdcla[da2->readplane]); +#endif return da2->gdcla[da2->readplane]; } } else { @@ -2612,11 +2619,11 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask with even address (need to verify the condition with OS/2 J2.x, Win 3.x and A-Train IV Win) */ - /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ + /* Align bitmask with even address */ + /* With byte align: Win 3.1 (Window) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ // if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - /* Without byte align: Win 3.1 (Window Title) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ - /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok, DOS J4.0 MC - ok */ + /* Without byte align: Win 3.1 (Window) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ + /* With byte align: Win 3.1 (Window) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ if ((addr & 1)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else /* No align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - bad */ From 1a60f5aac4b7874cd0e16f78fa513b7b72a78949 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 13:01:58 +0900 Subject: [PATCH 0369/1190] remove video timing modification --- src/video/vid_ps55da2.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 335cbf86d..823ef4d2f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2220,14 +2220,7 @@ da2_recalctimings(da2_t *da2) if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { da2->hdisp--; da2->dispend -= 29; - } else { - // da2->vtotal += 2; - da2->dispend--; - // da2->vsyncstart++; - // da2->split++; - // da2->vblankstart++; - // da2->hdisp--; - } + } da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; From 8c2db2892d98b8b599f002c944667c47b10dc39e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 5 Mar 2025 21:52:17 +0100 Subject: [PATCH 0370/1190] CPU: Fix Cyrix SMM instructions. --- src/cpu/386_ops.h | 104 +++++++++++++++++++++++++++++++++++++++++--- src/cpu/cpu.c | 10 +---- src/cpu/cpu.h | 50 +++++++++++---------- src/cpu/cpu_table.c | 87 ++++++++++++++++++++++++++++++++++++ src/cpu/x86_ops.h | 2 + 5 files changed, 215 insertions(+), 38 deletions(-) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index b8ef9edda..80a856482 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -859,12 +859,12 @@ const OpFn OP_TABLE(c486_0f)[1024] = { /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, @@ -1392,7 +1392,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1414,7 +1414,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1436,7 +1436,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1458,7 +1458,99 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on +}; + +const OpFn OP_TABLE(c6x86l_0f)[1024] = { + // clang-format off + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 0802fa3ac..2d22ed796 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1462,22 +1462,16 @@ cpu_set(void) if (cpu_s->cpu_type == CPU_Cx6x86MX) x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); else if (cpu_s->cpu_type == CPU_Cx6x86L) - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); + x86_setopcodes(ops_386, ops_c6x86l_0f, dynarec_ops_386, dynarec_ops_c6x86l_0f); else - x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); -# if 0 x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f); -# endif # else if (cpu_s->cpu_type == CPU_Cx6x86MX) x86_setopcodes(ops_386, ops_c6x86mx_0f); else if (cpu_s->cpu_type == CPU_Cx6x86L) - x86_setopcodes(ops_386, ops_pentium_0f); + x86_setopcodes(ops_386, ops_c6x86l_0f); else - x86_setopcodes(ops_386, ops_c6x86mx_0f); -# if 0 x86_setopcodes(ops_386, ops_c6x86_0f); -# endif # endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 1d003ddc9..3e72db005 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -87,30 +87,32 @@ enum { enum { CPU_PKG_8088 = (1 << 0), CPU_PKG_8088_EUROPC = (1 << 1), - CPU_PKG_8086 = (1 << 2), - CPU_PKG_8086_MAZOVIA = (1 << 3), - CPU_PKG_188 = (1 << 4), - CPU_PKG_186 = (1 << 5), - CPU_PKG_286 = (1 << 6), - CPU_PKG_386SX = (1 << 7), - CPU_PKG_386DX = (1 << 8), - CPU_PKG_386DX_DESKPRO386 = (1 << 9), - CPU_PKG_M6117 = (1 << 10), - CPU_PKG_386SLC_IBM = (1 << 11), - CPU_PKG_486SLC = (1 << 12), - CPU_PKG_486SLC_IBM = (1 << 13), - CPU_PKG_486BL = (1 << 14), - CPU_PKG_486DLC = (1 << 15), - CPU_PKG_SOCKET1 = (1 << 16), - CPU_PKG_SOCKET3 = (1 << 17), - CPU_PKG_SOCKET3_PC330 = (1 << 18), - CPU_PKG_STPC = (1 << 19), - CPU_PKG_SOCKET4 = (1 << 20), - CPU_PKG_SOCKET5_7 = (1 << 21), - CPU_PKG_SOCKET8 = (1 << 22), - CPU_PKG_SLOT1 = (1 << 23), - CPU_PKG_SLOT2 = (1 << 24), - CPU_PKG_SOCKET370 = (1 << 25) + CPU_PKG_8088_VTECH = (1 << 2), + CPU_PKG_8086 = (1 << 3), + CPU_PKG_8086_MAZOVIA = (1 << 4), + CPU_PKG_8086_VTECH = (1 << 5), + CPU_PKG_188 = (1 << 6), + CPU_PKG_186 = (1 << 7), + CPU_PKG_286 = (1 << 8), + CPU_PKG_386SX = (1 << 9), + CPU_PKG_386DX = (1 << 10), + CPU_PKG_386DX_DESKPRO386 = (1 << 11), + CPU_PKG_M6117 = (1 << 12), + CPU_PKG_386SLC_IBM = (1 << 13), + CPU_PKG_486SLC = (1 << 14), + CPU_PKG_486SLC_IBM = (1 << 15), + CPU_PKG_486BL = (1 << 16), + CPU_PKG_486DLC = (1 << 17), + CPU_PKG_SOCKET1 = (1 << 18), + CPU_PKG_SOCKET3 = (1 << 19), + CPU_PKG_SOCKET3_PC330 = (1 << 20), + CPU_PKG_STPC = (1 << 21), + CPU_PKG_SOCKET4 = (1 << 22), + CPU_PKG_SOCKET5_7 = (1 << 23), + CPU_PKG_SOCKET8 = (1 << 24), + CPU_PKG_SLOT1 = (1 << 25), + CPU_PKG_SLOT2 = (1 << 26), + CPU_PKG_SOCKET370 = (1 << 27) }; #define CPU_SUPPORTS_DYNAREC 1 diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index b2ef71075..104d56d05 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -262,6 +262,50 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, + { + .package = CPU_PKG_8088_VTECH, + .manufacturer = "Intel", + .name = "8088", + .internal_name = "8088_vtech", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + + { + .name = "10", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } + }, { .package = CPU_PKG_8086, .manufacturer = "Intel", @@ -399,6 +443,49 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, + { + .package = CPU_PKG_8086_VTECH, + .manufacturer = "Intel", + .name = "8086", + .internal_name = "8086_vtech", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } + }, { .package = CPU_PKG_188, .manufacturer = "Intel", diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 3dfb3f917..7aec16855 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -92,6 +92,7 @@ extern const OpFn dynarec_ops_pentiummmx_0f[1024]; # ifdef USE_CYRIX_6X86 extern const OpFn dynarec_ops_c6x86_0f[1024]; +extern const OpFn dynarec_ops_c6x86l_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; # endif /* USE_CYRIX_6X86 */ @@ -234,6 +235,7 @@ extern const OpFn ops_pentiummmx_0f[1024]; #ifdef USE_CYRIX_6X86 extern const OpFn ops_c6x86_0f[1024]; +extern const OpFn ops_c6x86l_0f[1024]; extern const OpFn ops_c6x86mx_0f[1024]; #endif /* USE_CYRIX_6X86 */ From 5f3641ecbd7faf5caa77016392207a42ff9a2377 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 00:54:28 +0600 Subject: [PATCH 0371/1190] Implement Cyrix EMMI extensions and 4 FPU instructions PADDSIW, PSUBSIW, PMULHRW (named PMULHRWC in the code as recognized by some assemblers), PMULHRIW, PDISTIB, PMACHRIW, PAVEB, PMAGW, PMVZB, PMVNZB, PMVLZB, PMVGEZB, FTSTP, FRINT2, FRINEAR, FRICHOP are implemented for Cyrix 6x86MX. Cyrix 6x86(L) only has the last 4 instructions. --- src/cpu/386_ops.h | 9 +- src/cpu/cpu.c | 47 +- src/cpu/cpu.h | 10 + src/cpu/x86.c | 4 + src/cpu/x86_ops.h | 18 + src/cpu/x86_ops_mmx_emmi.h | 807 +++++++++++++++++++++++++++++++++++ src/cpu/x87_ops.h | 664 ++++++++++++++++++++++++++++ src/cpu/x87_ops_misc.h | 77 ++++ src/cpu/x87_ops_sf_arith.h | 81 ++++ src/cpu/x87_ops_sf_compare.h | 26 ++ 10 files changed, 1723 insertions(+), 20 deletions(-) create mode 100644 src/cpu/x86_ops_mmx_emmi.h diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 80a856482..e8300f134 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -206,6 +206,7 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_mmx_mov.h" # include "x86_ops_mmx_pack.h" # include "x86_ops_mmx_shift.h" +# include "x86_ops_mmx_emmi.h" #endif #include "x86_ops_mov.h" #ifdef OPS_286_386 @@ -1857,7 +1858,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a16, opPADDSIW_a16, opPMAGW_a16, ILLEGAL, opPDISTIB_a16, opPSUBSIW_a16, ILLEGAL, ILLEGAL, opPMVZB_a16, opPMULHRWC_a16, opPMVNZB_a16, opPMVLZB_a16, opPMVGEZB_a16, opPMULHRIW_a16, opPMACHRIW_a16, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, @@ -1879,7 +1880,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a16, opPADDSIW_a16, opPMAGW_a16, ILLEGAL, opPDISTIB_a16, opPSUBSIW_a16, ILLEGAL, ILLEGAL, opPMVZB_a16, opPMULHRWC_a16, opPMVNZB_a16, opPMVLZB_a16, opPMVGEZB_a16, opPMULHRIW_a16, opPMACHRIW_a16, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, @@ -1901,7 +1902,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a32, opPADDSIW_a32, opPMAGW_a32, ILLEGAL, opPDISTIB_a32, opPSUBSIW_a32, ILLEGAL, ILLEGAL, opPMVZB_a32, opPMULHRWC_a32, opPMVNZB_a32, opPMVLZB_a32, opPMVGEZB_a32, opPMULHRIW_a32, opPMACHRIW_a32, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, @@ -1923,7 +1924,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a32, opPADDSIW_a32, opPMAGW_a32, ILLEGAL, opPDISTIB_a32, opPSUBSIW_a32, ILLEGAL, ILLEGAL, opPMVZB_a32, opPMULHRWC_a32, opPMVNZB_a32, opPMVLZB_a32, opPMVGEZB_a32, opPMULHRIW_a32, opPMACHRIW_a32, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 2d22ed796..13a109d38 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -279,13 +279,14 @@ uint8_t do_translate2 = 0; void (*cpu_exec)(int32_t cycs); -static uint8_t ccr0; -static uint8_t ccr1; -static uint8_t ccr2; -static uint8_t ccr3; -static uint8_t ccr4; -static uint8_t ccr5; -static uint8_t ccr6; +uint8_t ccr0; +uint8_t ccr1; +uint8_t ccr2; +uint8_t ccr3; +uint8_t ccr4; +uint8_t ccr5; +uint8_t ccr6; +uint8_t ccr7; static int cyrix_addr; @@ -557,7 +558,8 @@ cpu_set(void) cpu_busspeed = cpu_s->rspeed; cpu_multi = (int) ceil(cpu_s->multi); cpu_dmulti = cpu_s->multi; - ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; + ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; + ccr4 = 0x85; cpu_update_waitstates(); @@ -1442,19 +1444,27 @@ cpu_set(void) } # endif /* USE_DYNAREC */ if (fpu_softfloat) { + x86_opcodes_d9_a16 = ops_sf_fpu_cyrix_d9_a16; + x86_opcodes_d9_a32 = ops_sf_fpu_cyrix_d9_a32; x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; x86_opcodes_da_a32 = ops_sf_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_sf_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_sf_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_sf_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_sf_fpu_686_df_a32; + x86_opcodes_db_a16 = ops_sf_fpu_cyrix_686_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_cyrix_686_db_a32; + x86_opcodes_dd_a16 = ops_sf_fpu_cyrix_dd_a16; + x86_opcodes_dd_a32 = ops_sf_fpu_cyrix_dd_a32; + x86_opcodes_df_a16 = ops_sf_fpu_cyrix_686_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_cyrix_686_df_a32; } else { + x86_opcodes_d9_a16 = ops_fpu_cyrix_d9_a16; + x86_opcodes_d9_a32 = ops_fpu_cyrix_d9_a32; x86_opcodes_da_a16 = ops_fpu_686_da_a16; x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; + x86_opcodes_db_a16 = ops_fpu_cyrix_686_db_a16; + x86_opcodes_db_a32 = ops_fpu_cyrix_686_db_a32; + x86_opcodes_dd_a16 = ops_fpu_cyrix_dd_a16; + x86_opcodes_dd_a32 = ops_fpu_cyrix_dd_a32; + x86_opcodes_df_a16 = ops_fpu_cyrix_686_df_a16; + x86_opcodes_df_a32 = ops_fpu_cyrix_686_df_a32; } } @@ -4291,6 +4301,9 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) if ((ccr3 & 0xf0) == 0x10) ccr6 = val; break; + case 0xeb: /* CCR7 */ + ccr7 = val & 5; + break; } } @@ -4319,6 +4332,8 @@ cpu_read(uint16_t addr, UNUSED(void *priv)) 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: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 3e72db005..8324c543e 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -589,6 +589,16 @@ extern uint32_t _tr[8]; extern uint32_t cache_index; extern uint8_t _cache[2048]; +/* For the Cyrix 6x86(MX) */ +extern uint8_t ccr0; +extern uint8_t ccr1; +extern uint8_t ccr2; +extern uint8_t ccr3; +extern uint8_t ccr4; +extern uint8_t ccr5; +extern uint8_t ccr6; +extern uint8_t ccr7; + /*Segments - _cs,_ds,_es,_ss are the segment structures CS,DS,ES,SS is the 16-bit data diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 6f15560f3..f1f5004d9 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -272,6 +272,10 @@ reset_common(int hard) msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw = 0; new_ne = 0; + + ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; + ccr4 = 0x85; + if (hascache) cr0 = 1 << 30; else diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 7aec16855..6d93fb435 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -265,14 +265,20 @@ extern const OpFn ops_sf_fpu_d8_a16[32]; extern const OpFn ops_sf_fpu_d8_a32[32]; extern const OpFn ops_sf_fpu_d9_a16[256]; extern const OpFn ops_sf_fpu_d9_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_d9_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_d9_a32[256]; extern const OpFn ops_sf_fpu_da_a16[256]; extern const OpFn ops_sf_fpu_da_a32[256]; extern const OpFn ops_sf_fpu_db_a16[256]; extern const OpFn ops_sf_fpu_db_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a32[256]; extern const OpFn ops_sf_fpu_dc_a16[32]; extern const OpFn ops_sf_fpu_dc_a32[32]; extern const OpFn ops_sf_fpu_dd_a16[256]; extern const OpFn ops_sf_fpu_dd_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_dd_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_dd_a32[256]; extern const OpFn ops_sf_fpu_de_a16[256]; extern const OpFn ops_sf_fpu_de_a32[256]; extern const OpFn ops_sf_fpu_df_a16[256]; @@ -297,6 +303,8 @@ extern const OpFn ops_fpu_d8_a16[32]; extern const OpFn ops_fpu_d8_a32[32]; extern const OpFn ops_fpu_d9_a16[256]; extern const OpFn ops_fpu_d9_a32[256]; +extern const OpFn ops_fpu_cyrix_d9_a16[256]; +extern const OpFn ops_fpu_cyrix_d9_a32[256]; extern const OpFn ops_fpu_da_a16[256]; extern const OpFn ops_fpu_da_a32[256]; extern const OpFn ops_fpu_db_a16[256]; @@ -305,6 +313,8 @@ extern const OpFn ops_fpu_dc_a16[32]; extern const OpFn ops_fpu_dc_a32[32]; extern const OpFn ops_fpu_dd_a16[256]; extern const OpFn ops_fpu_dd_a32[256]; +extern const OpFn ops_fpu_cyrix_dd_a16[256]; +extern const OpFn ops_fpu_cyrix_dd_a32[256]; extern const OpFn ops_fpu_de_a16[256]; extern const OpFn ops_fpu_de_a32[256]; extern const OpFn ops_fpu_df_a16[256]; @@ -316,15 +326,23 @@ extern const OpFn ops_sf_fpu_686_da_a16[256]; extern const OpFn ops_sf_fpu_686_da_a32[256]; extern const OpFn ops_sf_fpu_686_db_a16[256]; extern const OpFn ops_sf_fpu_686_db_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a32[256]; extern const OpFn ops_sf_fpu_686_df_a16[256]; extern const OpFn ops_sf_fpu_686_df_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_686_df_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_686_df_a32[256]; extern const OpFn ops_fpu_686_da_a16[256]; extern const OpFn ops_fpu_686_da_a32[256]; extern const OpFn ops_fpu_686_db_a16[256]; extern const OpFn ops_fpu_686_db_a32[256]; +extern const OpFn ops_fpu_cyrix_686_db_a16[256]; +extern const OpFn ops_fpu_cyrix_686_db_a32[256]; extern const OpFn ops_fpu_686_df_a16[256]; extern const OpFn ops_fpu_686_df_a32[256]; +extern const OpFn ops_fpu_cyrix_686_df_a16[256]; +extern const OpFn ops_fpu_cyrix_686_df_a32[256]; extern const OpFn ops_REPE[1024]; extern const OpFn ops_REPNE[1024]; diff --git a/src/cpu/x86_ops_mmx_emmi.h b/src/cpu/x86_ops_mmx_emmi.h new file mode 100644 index 000000000..4c994be0f --- /dev/null +++ b/src/cpu/x86_ops_mmx_emmi.h @@ -0,0 +1,807 @@ +/* Notes: "src2" means "first operand" */ + +static int +opPMULHRWC_a16(UNUSED(uint32_t fetchdat)) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->w[0] = ((int32_t) (dst->sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = ((int32_t) (dst->sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = ((int32_t) (dst->sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = ((int32_t) (dst->sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMULHRWC_a32(UNUSED(uint32_t fetchdat)) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->w[0] = ((int32_t) (dst->sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = ((int32_t) (dst->sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = ((int32_t) (dst->sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = ((int32_t) (dst->sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMULHRIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] = (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPMULHRIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] = (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPDISTIB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->b[0] = USATB(dst->b[0] + abs(src2.b[0] - src.b[0])); + dst->b[1] = USATB(dst->b[1] + abs(src2.b[1] - src.b[1])); + dst->b[2] = USATB(dst->b[2] + abs(src2.b[2] - src.b[2])); + dst->b[3] = USATB(dst->b[3] + abs(src2.b[3] - src.b[3])); + dst->b[4] = USATB(dst->b[4] + abs(src2.b[4] - src.b[4])); + dst->b[5] = USATB(dst->b[5] + abs(src2.b[5] - src.b[5])); + dst->b[6] = USATB(dst->b[6] + abs(src2.b[6] - src.b[6])); + dst->b[7] = USATB(dst->b[7] + abs(src2.b[7] - src.b[7])); + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPDISTIB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->b[0] = USATB(dst->b[0] + abs(src2.b[0] - src.b[0])); + dst->b[1] = USATB(dst->b[1] + abs(src2.b[1] - src.b[1])); + dst->b[2] = USATB(dst->b[2] + abs(src2.b[2] - src.b[2])); + dst->b[3] = USATB(dst->b[3] + abs(src2.b[3] - src.b[3])); + dst->b[4] = USATB(dst->b[4] + abs(src2.b[4] - src.b[4])); + dst->b[5] = USATB(dst->b[5] + abs(src2.b[5] - src.b[5])); + dst->b[6] = USATB(dst->b[6] + abs(src2.b[6] - src.b[6])); + dst->b[7] = USATB(dst->b[7] + abs(src2.b[7] - src.b[7])); + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPMACHRIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] += (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] += (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] += (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] += (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPMACHRIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] += (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] += (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] += (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] += (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPADDSIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] + src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] + src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] + src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] + src.sw[3]); + + MMX_SETEXP(cpu_reg ^ 1); + + return 0; +} + +static int +opPADDSIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] + src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] + src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] + src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] + src.sw[3]); + + MMX_SETEXP(cpu_reg ^ 1); + + return 0; +} + +static int +opPSUBSIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] - src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] - src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] - src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] - src.sw[3]); + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPSUBSIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] - src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] - src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] - src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] - src.sw[3]); + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPAVEB_a16(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->b[0] = (dst->b[0] + src.b[0]) >> 1; + dst->b[1] = (dst->b[1] + src.b[1]) >> 1; + dst->b[2] = (dst->b[2] + src.b[2]) >> 1; + dst->b[3] = (dst->b[3] + src.b[3]) >> 1; + dst->b[4] = (dst->b[4] + src.b[4]) >> 1; + dst->b[5] = (dst->b[5] + src.b[5]) >> 1; + dst->b[6] = (dst->b[6] + src.b[6]) >> 1; + dst->b[7] = (dst->b[7] + src.b[7]) >> 1; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPAVEB_a32(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->b[0] = (dst->b[0] + src.b[0]) >> 1; + dst->b[1] = (dst->b[1] + src.b[1]) >> 1; + dst->b[2] = (dst->b[2] + src.b[2]) >> 1; + dst->b[3] = (dst->b[3] + src.b[3]) >> 1; + dst->b[4] = (dst->b[4] + src.b[4]) >> 1; + dst->b[5] = (dst->b[5] + src.b[5]) >> 1; + dst->b[6] = (dst->b[6] + src.b[6]) >> 1; + dst->b[7] = (dst->b[7] + src.b[7]) >> 1; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMAGW_a16(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + if (abs(src.sw[0]) > abs(dst->sw[0])) dst->sw[0] = src.sw[0]; + if (abs(src.sw[1]) > abs(dst->sw[1])) dst->sw[1] = src.sw[1]; + if (abs(src.sw[2]) > abs(dst->sw[2])) dst->sw[2] = src.sw[2]; + if (abs(src.sw[3]) > abs(dst->sw[3])) dst->sw[3] = src.sw[3]; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMAGW_a32(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + if (abs(src.sw[0]) > abs(dst->sw[0])) dst->sw[0] = src.sw[0]; + if (abs(src.sw[1]) > abs(dst->sw[1])) dst->sw[1] = src.sw[1]; + if (abs(src.sw[2]) > abs(dst->sw[2])) dst->sw[2] = src.sw[2]; + if (abs(src.sw[3]) > abs(dst->sw[3])) dst->sw[3] = src.sw[3]; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMVZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] == 0) dst->b[0] = src.b[0]; + if (src2.b[1] == 0) dst->b[1] = src.b[1]; + if (src2.b[2] == 0) dst->b[2] = src.b[2]; + if (src2.b[3] == 0) dst->b[3] = src.b[3]; + if (src2.b[4] == 0) dst->b[4] = src.b[4]; + if (src2.b[5] == 0) dst->b[5] = src.b[5]; + if (src2.b[6] == 0) dst->b[6] = src.b[6]; + if (src2.b[7] == 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] == 0) dst->b[0] = src.b[0]; + if (src2.b[1] == 0) dst->b[1] = src.b[1]; + if (src2.b[2] == 0) dst->b[2] = src.b[2]; + if (src2.b[3] == 0) dst->b[3] = src.b[3]; + if (src2.b[4] == 0) dst->b[4] = src.b[4]; + if (src2.b[5] == 0) dst->b[5] = src.b[5]; + if (src2.b[6] == 0) dst->b[6] = src.b[6]; + if (src2.b[7] == 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVNZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] != 0) dst->b[0] = src.b[0]; + if (src2.b[1] != 0) dst->b[1] = src.b[1]; + if (src2.b[2] != 0) dst->b[2] = src.b[2]; + if (src2.b[3] != 0) dst->b[3] = src.b[3]; + if (src2.b[4] != 0) dst->b[4] = src.b[4]; + if (src2.b[5] != 0) dst->b[5] = src.b[5]; + if (src2.b[6] != 0) dst->b[6] = src.b[6]; + if (src2.b[7] != 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVNZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] != 0) dst->b[0] = src.b[0]; + if (src2.b[1] != 0) dst->b[1] = src.b[1]; + if (src2.b[2] != 0) dst->b[2] = src.b[2]; + if (src2.b[3] != 0) dst->b[3] = src.b[3]; + if (src2.b[4] != 0) dst->b[4] = src.b[4]; + if (src2.b[5] != 0) dst->b[5] = src.b[5]; + if (src2.b[6] != 0) dst->b[6] = src.b[6]; + if (src2.b[7] != 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVLZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] < 0) dst->b[0] = src.b[0]; + if (src2.sb[1] < 0) dst->b[1] = src.b[1]; + if (src2.sb[2] < 0) dst->b[2] = src.b[2]; + if (src2.sb[3] < 0) dst->b[3] = src.b[3]; + if (src2.sb[4] < 0) dst->b[4] = src.b[4]; + if (src2.sb[5] < 0) dst->b[5] = src.b[5]; + if (src2.sb[6] < 0) dst->b[6] = src.b[6]; + if (src2.sb[7] < 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVLZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] < 0) dst->b[0] = src.b[0]; + if (src2.sb[1] < 0) dst->b[1] = src.b[1]; + if (src2.sb[2] < 0) dst->b[2] = src.b[2]; + if (src2.sb[3] < 0) dst->b[3] = src.b[3]; + if (src2.sb[4] < 0) dst->b[4] = src.b[4]; + if (src2.sb[5] < 0) dst->b[5] = src.b[5]; + if (src2.sb[6] < 0) dst->b[6] = src.b[6]; + if (src2.sb[7] < 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVGEZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] >= 0) dst->b[0] = src.b[0]; + if (src2.sb[1] >= 0) dst->b[1] = src.b[1]; + if (src2.sb[2] >= 0) dst->b[2] = src.b[2]; + if (src2.sb[3] >= 0) dst->b[3] = src.b[3]; + if (src2.sb[4] >= 0) dst->b[4] = src.b[4]; + if (src2.sb[5] >= 0) dst->b[5] = src.b[5]; + if (src2.sb[6] >= 0) dst->b[6] = src.b[6]; + if (src2.sb[7] >= 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVGEZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] >= 0) dst->b[0] = src.b[0]; + if (src2.sb[1] >= 0) dst->b[1] = src.b[1]; + if (src2.sb[2] >= 0) dst->b[2] = src.b[2]; + if (src2.sb[3] >= 0) dst->b[3] = src.b[3]; + if (src2.sb[4] >= 0) dst->b[4] = src.b[4]; + if (src2.sb[5] >= 0) dst->b[5] = src.b[5]; + if (src2.sb[6] >= 0) dst->b[6] = src.b[6]; + if (src2.sb[7] >= 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} \ No newline at end of file diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index f1362bf76..97f5415b9 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -241,6 +241,24 @@ x87_fround32_64(double b) return (int64_t) x87_fround32(b); } +static __inline int64_t +x87_fround_nearest(double b) +{ + double da, dc; + int64_t a, c; + + da = floor(b); + dc = floor(b + 1.0); + a = (int64_t) da; + c = (int64_t) dc; + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; +} + static __inline int64_t x87_fround(double b) { @@ -1267,6 +1285,86 @@ const OpFn OP_TABLE(sf_fpu_d9_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(sf_fpu_cyrix_d9_a16)[256] = { + // clang-format off + /*0x00*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x18*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x20*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x28*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x30*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x38*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0x40*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x58*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x60*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x68*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x70*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x78*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0x80*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x98*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0xa0*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0xa8*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0xb0*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0xb8*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0xc0*/ sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + /*0xe0*/ sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, sf_FTSTP, ILLEGAL_a16, + /*0xe8*/ sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + /*0xf0*/ sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + /*0xf8*/ sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_cyrix_d9_a32)[256] = { + // clang-format off + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a32, ILLEGAL_a32, sf_FTST, sf_FXAM, sf_FTSTP, ILLEGAL_a32, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a32, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + const OpFn OP_TABLE(sf_fpu_287_da_a16)[256] = { // clang-format off sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, @@ -1750,6 +1848,87 @@ const OpFn OP_TABLE(sf_fpu_686_db_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_cyrix_686_db_a16)[256] = { + // clang-format off + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, + sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, + sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, + sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, + sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, sf_FRINT2, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; +const OpFn OP_TABLE(sf_fpu_cyrix_686_db_a32)[256] = { + // clang-format off + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, + sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, + sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, + sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, + sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, + sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, sf_FRINT2, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(sf_fpu_287_dc_a16)[32] = { // clang-format off sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, @@ -1946,6 +2125,86 @@ const OpFn OP_TABLE(sf_fpu_dd_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(sf_fpu_cyrix_dd_a16)[256] = { + // clang-format off + /*0x00*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x18*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x20*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x28*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x30*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x38*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0x40*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x58*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x60*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x68*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x70*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x78*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0x80*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x98*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0xa0*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0xa8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xb0*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0xb8*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0xc0*/ sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xe0*/ sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + /*0xe8*/ sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, sf_FRICHOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_cyrix_dd_a32)[256] = { + // clang-format off + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, sf_FRICHOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + const OpFn OP_TABLE(sf_fpu_287_de_a16)[256] = { // clang-format off sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, @@ -2348,6 +2607,88 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_cyrix_686_df_a16)[256] = { + // clang-format off + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, + sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, sf_FRINEAR, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_cyrix_686_df_a32)[256] = { + // clang-format off + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, + sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, sf_FRINEAR, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(fpu_d8_a16)[32] = { // clang-format off opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, @@ -2526,6 +2867,86 @@ const OpFn OP_TABLE(fpu_d9_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(fpu_cyrix_d9_a16)[256] = { + // clang-format off + opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ + opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, opFTSTP, ILLEGAL_a16, + opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on +}; + +const OpFn OP_TABLE(fpu_cyrix_d9_a32)[256] = { + // clang-format off + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFNOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ + opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, opFTSTP, ILLEGAL_a32, + opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on +}; + const OpFn OP_TABLE(fpu_287_da_a16)[256] = { // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, @@ -3009,6 +3430,87 @@ const OpFn OP_TABLE(fpu_686_db_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_cyrix_686_db_a16)[256] = { + // clang-format off + opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, + opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, + opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, + opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, + opFNOP, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL_a16, ILLEGAL_a16, + opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, + opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFRINT2, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; +const OpFn OP_TABLE(fpu_cyrix_686_db_a32)[256] = { + // clang-format off + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, + opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, + opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, + opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, + opFNOP, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL_a32, ILLEGAL_a32, + opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, + opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFRINT2, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(fpu_287_dc_a16)[32] = { // clang-format off opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, @@ -3205,6 +3707,86 @@ const OpFn OP_TABLE(fpu_dd_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(fpu_cyrix_dd_a16)[256] = { + // clang-format off + opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFST, opFST, opFST, opFST, opFST, opFST, opFST, opFST, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, + opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFRICHOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(fpu_cyrix_dd_a32)[256] = { + // clang-format off + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFST, opFST, opFST, opFST, opFST, opFST, opFST, opFST, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, + opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFRICHOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + const OpFn OP_TABLE(fpu_287_de_a16)[256] = { // clang-format off opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, @@ -3607,6 +4189,88 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_cyrix_686_df_a16)[256] = { + // clang-format off + opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, + opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFRINEAR, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(fpu_cyrix_686_df_a32)[256] = { + // clang-format off + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, + opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFRINEAR, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(nofpu_a16)[256] = { // clang-format off op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index c1f09fda9..cbad12e56 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -554,6 +554,22 @@ opFTST(UNUSED(uint32_t fetchdat)) return 0; } +static int +opFTSTP(UNUSED(uint32_t fetchdat)) +{ + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); + if (ST(0) == 0.0) + cpu_state.npxs |= FPU_SW_C3; + else if (ST(0) < 0.0) + cpu_state.npxs |= FPU_SW_C0; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); + return 0; +} + static int opFXAM(UNUSED(uint32_t fetchdat)) { @@ -838,6 +854,67 @@ opFRNDINT(UNUSED(uint32_t fetchdat)) return 0; } +static int +opFRINT2(UNUSED(uint32_t fetchdat)) +{ + double dst0, st0, integral, frac; + int prevRound; + + FP_ENTER(); + cpu_state.pc++; + prevRound = fegetround(); + fesetround(FE_TONEAREST); + st0 = ST(0); + frac = modf(st0, &integral); + if (frac == 0.5 || frac == -0.5) { + dst0 = (st0 < 0) ? floor(st0) : ceil(st0); + } else { + dst0 = round(st0); + } + fesetround(prevRound); + ST(0) = (double) dst0; + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +opFRINEAR(UNUSED(uint32_t fetchdat)) +{ + double dst0, st0, integral, frac; + int prevRound; + + FP_ENTER(); + cpu_state.pc++; + prevRound = fegetround(); + fesetround(FE_TONEAREST); + ST(0) = (double) x87_fround_nearest(ST(0)); + fesetround(prevRound); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +opFRICHOP(UNUSED(uint32_t fetchdat)) +{ + double dst0, st0, integral, frac; + int prevRound; + + FP_ENTER(); + cpu_state.pc++; + prevRound = fegetround(); + fesetround(FE_TONEAREST); + ST(0) = (double) ((int64_t)(ST(0))); + fesetround(prevRound); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + static int opFSCALE(UNUSED(uint32_t fetchdat)) { diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index c9e25e97c..620c44691 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -800,3 +800,84 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } + +static int +sf_FRINT2(uint32_t fetchdat) +{ + floatx80 result; + struct softfloat_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = extF80_roundToInt(FPU_read_regi(0), softfloat_round_near_maxMag, true, &status); + + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +sf_FRINEAR(uint32_t fetchdat) +{ + floatx80 result; + struct softfloat_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = extF80_roundToInt(FPU_read_regi(0), softfloat_round_near_even, true, &status); + + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +sf_FRICHOP(uint32_t fetchdat) +{ + floatx80 result; + struct softfloat_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = extF80_roundToInt(FPU_read_regi(0), softfloat_round_to_zero, true, &status); + + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index 945ed99d3..d1d9bc1dd 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -459,6 +459,32 @@ sf_FTST(uint32_t fetchdat) return 0; } +static int +sf_FTSTP(uint32_t fetchdat) +{ + const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); + struct softfloat_status_t status; + int rc; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + rc = extF80_compare_normal(FPU_read_regi(0), Const_Z, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); + FPU_pop(); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); + return 0; +} + static int sf_FXAM(UNUSED(uint32_t fetchdat)) { From c40aa61be419c6c6ed2365a2c69607964878b95a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 02:09:23 +0600 Subject: [PATCH 0372/1190] Cyrix 6x86: Correctly initalize ARR3 on reset to avoid some SMM problems --- src/cpu/x86.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpu/x86.c b/src/cpu/x86.c index f1f5004d9..97ae19f3a 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -275,6 +275,8 @@ reset_common(int hard) ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; ccr4 = 0x85; + cyrix.arr[3].base = 0x30000; + cyrix.arr[3].size = 65536; if (hascache) cr0 = 1 << 30; From a62a6594e6d437b88bcc46bfc65c2688497dce64 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 5 Mar 2025 23:48:47 +0100 Subject: [PATCH 0373/1190] 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 4c3ea296c3dbe7ab10c9660e2225059eebb1b676 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 5 Mar 2025 17:58:01 -0500 Subject: [PATCH 0374/1190] Fix ES1370 detection --- src/sound/snd_audiopci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index f8a6e4153..e3e2b9f1a 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -489,7 +489,10 @@ es137x_reset(void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ - dev->si_cr = 0xff800000; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = 0x00000000; + else + dev->si_cr = 0xff800000; /* DAC1 Channel Sample Count Register, Address 24H Addressable as word, longword */ From 2300339588f42744c8f5485a60a91b884fe6f8b3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 00:05:16 +0100 Subject: [PATCH 0375/1190] Included stdlib.h. --- src/cpu/386_dynarec_ops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index c31b725b2..3d9a7e080 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -1,6 +1,7 @@ #include -#include #include +#include +#include #include #include #include From 9b47522f43116dfaa04a03d18ced128ecbf31299 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 00:12:45 +0100 Subject: [PATCH 0376/1190] FPU: Fix newly-introduced x87-related warnings. --- src/cpu/x87_ops_misc.h | 8 ++++++-- src/cpu/x87_ops_sf_arith.h | 4 ++++ src/cpu/x87_ops_sf_compare.h | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index cbad12e56..5821a5cd5 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -554,6 +554,7 @@ opFTST(UNUSED(uint32_t fetchdat)) return 0; } +#ifndef FPU_8087 static int opFTSTP(UNUSED(uint32_t fetchdat)) { @@ -569,6 +570,7 @@ opFTSTP(UNUSED(uint32_t fetchdat)) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); return 0; } +#endif static int opFXAM(UNUSED(uint32_t fetchdat)) @@ -854,6 +856,8 @@ opFRNDINT(UNUSED(uint32_t fetchdat)) return 0; } +#ifndef FPU_8087 +#ifndef OPS_286_386 static int opFRINT2(UNUSED(uint32_t fetchdat)) { @@ -882,7 +886,6 @@ opFRINT2(UNUSED(uint32_t fetchdat)) static int opFRINEAR(UNUSED(uint32_t fetchdat)) { - double dst0, st0, integral, frac; int prevRound; FP_ENTER(); @@ -896,11 +899,11 @@ opFRINEAR(UNUSED(uint32_t fetchdat)) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif static int opFRICHOP(UNUSED(uint32_t fetchdat)) { - double dst0, st0, integral, frac; int prevRound; FP_ENTER(); @@ -914,6 +917,7 @@ opFRICHOP(UNUSED(uint32_t fetchdat)) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif static int opFSCALE(UNUSED(uint32_t fetchdat)) diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index 620c44691..7abde322b 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -801,6 +801,8 @@ next_ins: return 0; } +#ifndef FPU_8087 +#ifndef OPS_286_386 static int sf_FRINT2(uint32_t fetchdat) { @@ -854,6 +856,7 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif static int sf_FRICHOP(uint32_t fetchdat) @@ -881,3 +884,4 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index d1d9bc1dd..d90526b82 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -459,6 +459,7 @@ sf_FTST(uint32_t fetchdat) return 0; } +#ifndef FPU_8087 static int sf_FTSTP(uint32_t fetchdat) { @@ -484,6 +485,7 @@ sf_FTSTP(uint32_t fetchdat) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); return 0; } +#endif static int sf_FXAM(UNUSED(uint32_t fetchdat)) From 78f50c5b042ebd69c4fec875d47e10cf434e5806 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 00:17:16 +0100 Subject: [PATCH 0377/1190] Move the Cyrix 6x86 out of the Dev branch. --- CMakeLists.txt | 1 - src/cpu/386_ops.h | 4 ---- src/cpu/CMakeLists.txt | 10 +--------- src/cpu/cpu.c | 10 ---------- src/cpu/cpu_table.c | 2 -- src/cpu/x86_ops.h | 4 ---- src/cpu/x86_ops_mmx_mov.h | 2 -- 7 files changed, 1 insertion(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c33bb3e9..fb71553e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,7 +163,6 @@ endif() cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF) cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF) -cmake_dependent_option(CYRIX_6X86 "Cyrix 6x86" ON "DEV_BRANCH" OFF) cmake_dependent_option(G100 "Matrox Productiva G100" ON "DEV_BRANCH" OFF) cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index e8300f134..5113ca817 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -1385,7 +1385,6 @@ const OpFn OP_TABLE(pentium_0f)[1024] = { // clang-format on }; -# ifdef USE_CYRIX_6X86 const OpFn OP_TABLE(c6x86_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ @@ -1569,7 +1568,6 @@ const OpFn OP_TABLE(c6x86l_0f)[1024] = { /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, // clang-format on }; -# endif /* USE_CYRIX_6X86 */ const OpFn OP_TABLE(pentiummmx_0f)[1024] = { // clang-format off @@ -1847,7 +1845,6 @@ const OpFn OP_TABLE(k62_0f)[1024] = { // clang-format on }; -# ifdef USE_CYRIX_6X86 const OpFn OP_TABLE(c6x86mx_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ @@ -1939,7 +1936,6 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, // clang-format on }; -# endif /* USE_CYRIX_6X86 */ const OpFn OP_TABLE(pentiumpro_0f)[1024] = { // clang-format off diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 890d02e3e..9c1385d4f 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -42,20 +42,12 @@ endif() endif() -if(CYRIX_6X86) - target_compile_definitions(cpu PRIVATE USE_CYRIX_6X86) - -if(DYNAREC) - add_library(ct686 OBJECT codegen_timing_686.c) - target_link_libraries(86Box ct686) -endif() -endif() - if(DYNAREC) target_sources(cpu PRIVATE 386_dynarec_ops.c) add_library(cgt OBJECT codegen_timing_486.c + codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 13a109d38..e6a22394a 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1420,7 +1420,6 @@ cpu_set(void) #endif /* USE_DYNAREC */ break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -1541,7 +1540,6 @@ cpu_set(void) else if (CPU_Cx6x86) CPUID = 0; /* Disabled on powerup by default */ break; -#endif /* USE_CYRIX_6X86 */ #ifdef USE_AMD_K5 case CPU_K5: @@ -2386,7 +2384,6 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: if (!EAX) { EAX = 0x00000001; @@ -2447,7 +2444,6 @@ cpu_CPUID(void) } else EAX = EBX = ECX = EDX = 0; break; -#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: if (!EAX) { @@ -3124,7 +3120,6 @@ pentium_invalid_rdmsr: cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -3164,7 +3159,6 @@ pentium_invalid_rdmsr: } cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; -#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: case CPU_PENTIUM2: @@ -3945,7 +3939,6 @@ pentium_invalid_wrmsr: } break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -3979,7 +3972,6 @@ pentium_invalid_wrmsr: break; } break; -#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: case CPU_PENTIUM2: @@ -4283,14 +4275,12 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) case 0xe8: /* CCR4 */ if ((ccr3 & 0xf0) == 0x10) { ccr4 = val; -#ifdef USE_CYRIX_6X86 if (cpu_s->cpu_type >= CPU_Cx6x86) { if (val & 0x80) CPUID = cpu_s->cpuid_model; else CPUID = 0; } -#endif /* USE_CYRIX_6X86 */ } break; case 0xe9: /* CCR5 */ diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 104d56d05..5a156853e 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -6095,7 +6095,6 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, -#ifdef USE_CYRIX_6X86 { .package = CPU_PKG_SOCKET5_7, .manufacturer = "Cyrix", @@ -6455,7 +6454,6 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, -#endif /* USE_CYRIX_6X86 */ { .package = CPU_PKG_SOCKET8, .manufacturer = "Intel", diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 6d93fb435..ed95d04d9 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -90,11 +90,9 @@ extern const OpFn dynarec_ops_winchip2_0f[1024]; extern const OpFn dynarec_ops_pentium_0f[1024]; extern const OpFn dynarec_ops_pentiummmx_0f[1024]; -# ifdef USE_CYRIX_6X86 extern const OpFn dynarec_ops_c6x86_0f[1024]; extern const OpFn dynarec_ops_c6x86l_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; -# endif /* USE_CYRIX_6X86 */ extern const OpFn dynarec_ops_k6_0f[1024]; extern const OpFn dynarec_ops_k62_0f[1024]; @@ -233,11 +231,9 @@ extern const OpFn ops_winchip2_0f[1024]; extern const OpFn ops_pentium_0f[1024]; extern const OpFn ops_pentiummmx_0f[1024]; -#ifdef USE_CYRIX_6X86 extern const OpFn ops_c6x86_0f[1024]; extern const OpFn ops_c6x86l_0f[1024]; extern const OpFn ops_c6x86mx_0f[1024]; -#endif /* USE_CYRIX_6X86 */ extern const OpFn ops_k6_0f[1024]; extern const OpFn ops_k62_0f[1024]; diff --git a/src/cpu/x86_ops_mmx_mov.h b/src/cpu/x86_ops_mmx_mov.h index 8855f8ccd..0bf928198 100644 --- a/src/cpu/x86_ops_mmx_mov.h +++ b/src/cpu/x86_ops_mmx_mov.h @@ -110,7 +110,6 @@ opMOVD_mm_l_a32(uint32_t fetchdat) return 0; } -#ifdef USE_CYRIX_6X86 /*Cyrix maps both MOVD and SMINT to the same opcode*/ static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) @@ -170,7 +169,6 @@ opMOVD_mm_l_a32_cx(uint32_t fetchdat) return 0; } -#endif /* USE_CYRIX_6X86 */ static int opMOVQ_q_mm_a16(uint32_t fetchdat) From 4be691afe76181f3a885a3626bc814219a805424 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 01:44:02 +0100 Subject: [PATCH 0378/1190] 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 74368bfe7ab523f92d3533f0bdaf49c7c0611b4b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:26:11 +0600 Subject: [PATCH 0379/1190] Don't include `cpu.h` in `timer.h` Change the name of the define used to indicate SVGA multi-monitor-capable cards --- src/chipset/ali1531.c | 1 + src/chipset/ali1541.c | 1 + src/chipset/ali1543.c | 1 + src/chipset/ali6117.c | 1 + src/chipset/gc100.c | 1 + src/chipset/sis_5511_h2p.c | 1 + src/chipset/sis_5513_p2i.c | 1 + src/chipset/sis_5571_h2p.c | 1 + src/chipset/sis_5581_h2p.c | 1 + src/chipset/sis_5591_h2p.c | 1 + src/chipset/sis_5600_h2p.c | 1 + src/chipset/sis_85c50x.c | 1 + src/device/cartridge.c | 1 + src/device/keyboard_xt.c | 1 + src/device/serial.c | 1 + src/include/86box/timer.h | 2 +- src/include/86box/video.h | 2 ++ src/machine/m_at_socket5.c | 1 + src/machine/m_xt_olivetti.c | 1 + src/machine/m_xt_philips.c | 1 + src/mem/sst_flash.c | 1 + src/qt/qt_main.cpp | 1 + src/qt/qt_settingsdisplay.cpp | 6 +++--- src/scsi/scsi_t128.c | 1 + src/sound/snd_audiopci.c | 1 + src/sound/snd_gus.c | 1 + src/sound/snd_opl_esfm.c | 1 + src/sound/snd_opl_nuked.c | 1 + src/sound/snd_sb.c | 1 + src/timer.c | 1 + src/video/vid_ati_mach64.c | 1 + src/video/vid_ati_mach8.c | 1 + src/video/vid_chips_69000.c | 1 + src/video/vid_mga.c | 1 + src/video/vid_nga.c | 1 + src/video/vid_ogc.c | 1 + src/video/vid_table.c | 6 +++--- 37 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index e765e6d45..53324f8e6 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c index eed6ddbc5..ebbcd7e63 100644 --- a/src/chipset/ali1541.c +++ b/src/chipset/ali1541.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 69a8990e9..2f9273736 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> #include <86box/io.h> diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index 707b528b2..88bb4b572 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -26,6 +26,7 @@ #include <86box/io.h> #include <86box/pci.h> #include <86box/pic.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pit.h> #include <86box/device.h> diff --git a/src/chipset/gc100.c b/src/chipset/gc100.c index 23455b952..e9eb05ecf 100644 --- a/src/chipset/gc100.c +++ b/src/chipset/gc100.c @@ -27,6 +27,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/nmi.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pit.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c index 543fcacc5..b94e69f26 100644 --- a/src/chipset/sis_5511_h2p.c +++ b/src/chipset/sis_5511_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index 95a890fcf..b2346bbc4 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> diff --git a/src/chipset/sis_5571_h2p.c b/src/chipset/sis_5571_h2p.c index d04964581..a28553487 100644 --- a/src/chipset/sis_5571_h2p.c +++ b/src/chipset/sis_5571_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5581_h2p.c b/src/chipset/sis_5581_h2p.c index d01e9dd28..83983376d 100644 --- a/src/chipset/sis_5581_h2p.c +++ b/src/chipset/sis_5581_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5591_h2p.c b/src/chipset/sis_5591_h2p.c index 048e7deea..74dd6dfbd 100644 --- a/src/chipset/sis_5591_h2p.c +++ b/src/chipset/sis_5591_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5600_h2p.c b/src/chipset/sis_5600_h2p.c index a15c6fff5..c23309de4 100644 --- a/src/chipset/sis_5600_h2p.c +++ b/src/chipset/sis_5600_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 192ae3767..e932ff6ca 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -24,6 +24,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/apm.h> #include <86box/machine.h> diff --git a/src/device/cartridge.c b/src/device/cartridge.c index d2e91ecb3..00464026a 100644 --- a/src/device/cartridge.c +++ b/src/device/cartridge.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/plat.h> #include <86box/ui.h> diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 644168004..ddbcae61b 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -29,6 +29,7 @@ #include #include <86box/86box.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/fdd.h> #include <86box/machine.h> diff --git a/src/device/serial.c b/src/device/serial.c index c25da0070..deb97225a 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -27,6 +27,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/machine.h> #include <86box/io.h> diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 25aff6b2f..37a03d9ca 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -1,7 +1,7 @@ #ifndef _TIMER_H_ #define _TIMER_H_ -#include "cpu.h" +extern uint64_t tsc; /* Maximum period, currently 1 second. */ #define MAX_USEC64 1000000ULL diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 7ad29838c..2985559e1 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -69,6 +69,8 @@ enum { #define VIDEO_FLAG_TYPE_NONE 5 #define VIDEO_FLAG_TYPE_MASK 7 +#define VIDEO_FLAG_TYPE_SECONDARY VIDEO_FLAG_TYPE_SPECIAL + typedef struct video_timings_t { int type; int write_b; diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index b6e82301b..02922b425 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -29,6 +29,7 @@ #include <86box/fdc_ext.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/fdd.h> #include <86box/fdc.h> diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index b6e4fb94a..34ca441ec 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -30,6 +30,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/io.h> #include <86box/pic.h> diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index 604ccebaf..eed54e07f 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -23,6 +23,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/nmi.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pit.h> #include <86box/mem.h> diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index b41e0f2e2..34bfae83a 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -25,6 +25,7 @@ #include <86box/device.h> #include <86box/mem.h> #include <86box/machine.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nvr.h> #include <86box/plat.h> diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 7723261b4..719208c18 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -86,6 +86,7 @@ extern MainWindow *main_window; extern "C" { #include <86box/keyboard.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nvr.h> extern int qt_nvr_save(void); diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 75f8d376b..b7a930711 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -220,9 +220,9 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) int secondaryFlags = video_card_get_flags(c); if (video_card_available(c) && device_is_valid(video_dev, machineId) - && !((secondaryFlags == primaryFlags) && (secondaryFlags != VIDEO_FLAG_TYPE_SPECIAL)) - && !(((primaryFlags == VIDEO_FLAG_TYPE_8514) || (primaryFlags == VIDEO_FLAG_TYPE_XGA)) && (secondaryFlags != VIDEO_FLAG_TYPE_MDA) && (secondaryFlags != VIDEO_FLAG_TYPE_SPECIAL)) - && !((primaryFlags != VIDEO_FLAG_TYPE_MDA) && (primaryFlags != VIDEO_FLAG_TYPE_SPECIAL) && ((secondaryFlags == VIDEO_FLAG_TYPE_8514) || (secondaryFlags == VIDEO_FLAG_TYPE_XGA)))) { + && !((secondaryFlags == primaryFlags) && (secondaryFlags != VIDEO_FLAG_TYPE_SECONDARY)) + && !(((primaryFlags == VIDEO_FLAG_TYPE_8514) || (primaryFlags == VIDEO_FLAG_TYPE_XGA)) && (secondaryFlags != VIDEO_FLAG_TYPE_MDA) && (secondaryFlags != VIDEO_FLAG_TYPE_SECONDARY)) + && !((primaryFlags != VIDEO_FLAG_TYPE_MDA) && (primaryFlags != VIDEO_FLAG_TYPE_SECONDARY) && ((secondaryFlags == VIDEO_FLAG_TYPE_8514) || (secondaryFlags == VIDEO_FLAG_TYPE_XGA)))) { ui->comboBoxVideoSecondary->addItem(name, c); if (c == curVideoCard_2) ui->comboBoxVideoSecondary->setCurrentIndex(ui->comboBoxVideoSecondary->count() - 1); diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index a40d803f1..5ac3b5d67 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -29,6 +29,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/pic.h> diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index e3e2b9f1a..8d1de442b 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -39,6 +39,7 @@ #include <86box/pci.h> #include <86box/snd_ac97.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/plat_unused.h> #include <86box/snd_akm4531.h> diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 43638473c..1885581a5 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -15,6 +15,7 @@ #include <86box/nmi.h> #include <86box/pic.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #ifdef USE_GUSMAX # include <86box/snd_ad1848.h> diff --git a/src/sound/snd_opl_esfm.c b/src/sound/snd_opl_esfm.c index bcd2a56e9..b80d264d5 100644 --- a/src/sound/snd_opl_esfm.c +++ b/src/sound/snd_opl_esfm.c @@ -32,6 +32,7 @@ #include <86box/86box.h> #include <86box/sound.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/snd_opl.h> #include <86box/plat_unused.h> diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 03851a589..60f5ed2a6 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -46,6 +46,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> #include <86box/snd_opl.h> diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 4f8b8a0bd..689d0b91e 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -39,6 +39,7 @@ #include <86box/pic.h> #include <86box/rom.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/snd_sb.h> #include <86box/plat_unused.h> diff --git a/src/timer.c b/src/timer.c index 9fed37511..03908890f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -3,6 +3,7 @@ #include #include #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nv/vid_nv_rivatimer.h> diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 2df7782ff..24935e3a2 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -28,6 +28,7 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pci.h> #include <86box/rom.h> diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 71dd973da..2038f1b1d 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -27,6 +27,7 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mca.h> #include <86box/pci.h> diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 012a16348..a387e99fa 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -27,6 +27,7 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index f11983a20..00570bd9f 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -23,6 +23,7 @@ #include #include <86box/86box.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mem.h> #include <86box/pci.h> diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 3640e5106..ef1c6cd40 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -30,6 +30,7 @@ #include <86box/io.h> #include <86box/video.h> #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mem.h> #include <86box/pit.h> diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index 7fe5fbbeb..a49cd8a22 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -31,6 +31,7 @@ #include <86box/io.h> #include <86box/video.h> #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mem.h> #include <86box/pit.h> diff --git a/src/video/vid_table.c b/src/video/vid_table.c index ff3073c73..d1df2ba20 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -141,10 +141,10 @@ video_cards[] = { { .device = &chips_69000_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5430_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5434_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5436_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5436_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY }, { .device = &gd5440_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5446_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, - { .device = &gd5446_stb_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5446_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY }, + { .device = &gd5446_stb_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY }, { .device = &gd5480_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000w32p_videomagic_revb_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000w32p_revc_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, From 0e42547cca39beb1d07fd007b4c2d8a1e0a92a8d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:34:24 +0600 Subject: [PATCH 0380/1190] Remove some `timer.h`-related include hacks --- src/qt/qt_machinestatus.cpp | 3 --- src/qt/qt_mainwindow.cpp | 9 ++++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index d1335873c..dee90f11c 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -19,9 +19,6 @@ #include "qt_machinestatus.hpp" extern "C" { -#define EMU_CPU_H // superhack - don't want timer.h to include cpu.h here, and some combo is preventing a compile -extern uint64_t tsc; - #include <86box/hdd.h> #include <86box/timer.h> #include <86box/86box.h> diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 89d17a07c..552fd0310 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -48,11 +48,10 @@ extern "C" { #include <86box/machine.h> #include <86box/vid_ega.h> #include <86box/version.h> -#if 0 -#include <86box/acpi.h> /* Requires timer.h include, which conflicts with Qt headers */ -#endif -extern atomic_int acpi_pwrbut_pressed; -extern int acpi_enabled; +#include <86box/timer.h> +#include <86box/apm.h> +#include <86box/nvr.h> +#include <86box/acpi.h> #ifdef USE_VNC # include <86box/vnc.h> From 9badd32c9cc14efde3fc7352d4edc9e8c1e1ec71 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:44:37 +0600 Subject: [PATCH 0381/1190] Remove more `nvr.h` hacks --- src/qt/qt_settingsmachine.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 771f1cbec..9b1f9849e 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -32,13 +32,9 @@ extern "C" { #include <86box/config.h> #include <86box/device.h> #include <86box/machine.h> +#include <86box/nvr.h> } -// from nvr.h, which we can't import into CPP code -#define TIME_SYNC_DISABLED 0 -#define TIME_SYNC_ENABLED 1 -#define TIME_SYNC_UTC 2 - #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" From 4090c5a62cf61bc4f4437bb7df0577aed37106ee Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:56:08 +0600 Subject: [PATCH 0382/1190] Fix SDL builds --- src/unix/unix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unix/unix.c b/src/unix/unix.c index 7f653b9b6..33b78ddb1 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -38,6 +38,7 @@ #include <86box/device.h> #include <86box/gameport.h> #include <86box/unix_sdl.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nvr.h> #include <86box/version.h> From 5c78fa52035892bbe695afc7eca72ec58d68de5a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 6 Mar 2025 16:03:11 +0100 Subject: [PATCH 0383/1190] 8514/A compatible changes of the day (March 6th, 2025) 1. Follow the Mach32 manual more closely regarding vblank support. 2. The subsystem status now takes account of the other bits more accurately. 3. The Mach32 PCI, when used with the ATI 68860 ramdac, has its own bpp's when in accelerator mode, separate from the VGA compatible side, so fix this accordingly. 4. Reset the vram when a mapping change occurs, should clear the messups in the ATI Mach8/32 accel video mode tests. --- src/include/86box/vid_8514a.h | 2 +- src/video/vid_8514a.c | 71 +++++++++++++++----------- src/video/vid_ati68860_ramdac.c | 18 +++---- src/video/vid_ati_mach8.c | 88 ++++++++++++++++++++++++--------- 4 files changed, 115 insertions(+), 64 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 57e98cc44..bfde22d5e 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -213,7 +213,7 @@ typedef struct ibm8514_t { int vdisp2; int disp_cntl; int interlace; - uint8_t subsys_cntl; + uint16_t subsys_cntl; uint8_t subsys_stat; atomic_int fifo_idx; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 379772820..765258237 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -715,27 +715,13 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) break; case 0x42e8: - if (val & 0x01) - dev->subsys_stat &= ~0x01; - if (val & 0x02) - dev->subsys_stat &= ~0x02; - if (val & 0x04) - dev->subsys_stat &= ~0x04; - if (val & 0x08) - dev->subsys_stat &= ~0x08; + 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 = val; - if (val & 0x01) - dev->subsys_stat |= 0x01; - if (val & 0x02) - dev->subsys_stat |= 0x02; - if (val & 0x04) - dev->subsys_stat |= 0x04; - if (val & 0x08) - dev->subsys_stat |= 0x08; - - if ((val & 0xc0) == 0xc0) { + 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; @@ -882,10 +868,10 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) switch (port) { case 0x2e8: - if (dev->vc == dev->v_syncstart) + if (dev->vc == dev->dispend) temp |= 0x02; - ibm8514_log("0x2E8 read: Display Status=%02x.\n", temp); + ibm8514_log("Read: Display Status1=%02x.\n", temp); break; case 0x6e8: @@ -910,21 +896,25 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) case 0x42e8: case 0x42e9: - if (dev->vc == dev->v_syncstart) - dev->subsys_stat |= 0x01; + if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) + temp |= 0x01; if (cmd == 6) { - if ((dev->accel.dx >= clip_l) && + 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)) - dev->subsys_stat |= 0x02; + temp |= 0x02; } else { - if ((dev->accel.cx >= clip_l) && + 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)) - dev->subsys_stat |= 0x02; + temp |= 0x02; } if (!dev->fifo_idx) { @@ -932,9 +922,10 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) temp |= 0x08; } - if (port & 1) + if (port & 1) { temp = dev->vram_512k_8514 ? 0x00 : 0x80; - else { + temp |= (dev->subsys_cntl >> 8); + } else { temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); temp |= 0x20; } @@ -1155,6 +1146,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; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1250,6 +1242,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; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1385,6 +1378,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; 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)) { @@ -1543,6 +1537,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; if (ibm8514_cpu_dest(svga)) { READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); } else @@ -1634,6 +1629,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; 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)) { @@ -1832,6 +1828,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; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1989,6 +1986,7 @@ skip_vector_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; 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)) { @@ -2150,6 +2148,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2232,6 +2231,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2313,6 +2313,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2424,6 +2425,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2546,6 +2548,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2650,9 +2653,10 @@ skip_nibble_rect_write: dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r); if ((dev->accel.cx >= clip_l) && - (dev->accel.cx < clip_r) && + (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2811,6 +2815,7 @@ skip_nibble_rect_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2978,6 +2983,7 @@ skip_nibble_bitblt_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3075,6 +3081,7 @@ skip_nibble_bitblt_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3174,6 +3181,7 @@ skip_nibble_bitblt_write: (dx <= (((uint64_t)clip_r) * 3)) && (dev->accel.dy >= (clip_t << 1)) && (dev->accel.dy <= (clip_b << 1))) { + dev->subsys_stat |= 0x02; READ(dev->accel.src + cx, src_dat); READ(dev->accel.dest + dx, dest_dat); @@ -3196,6 +3204,7 @@ skip_nibble_bitblt_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -3704,6 +3713,8 @@ ibm8514_poll(void *priv) dev->vc &= 0xfff; if (dev->vc == dev->dispend) { + dev->subsys_stat |= 0x01; + ibm8514_log("VBLANK irq.\n"); dev->dispon = 0; for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index bb5ccbf31..17b2a6d22 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -70,20 +70,19 @@ void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) { ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; - const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; switch (addr) { case 0: - svga_out((dev && dev->on) ? 0x2ec : 0x3c8, val, svga); + svga_out(0x3c8, val, svga); break; case 1: - svga_out((dev && dev->on) ? 0x2ed : 0x3c9, val, svga); + svga_out(0x3c9, val, svga); break; case 2: - svga_out((dev && dev->on) ? 0x2ea : 0x3c6, val, svga); + svga_out(0x3c6, val, svga); break; case 3: - svga_out((dev && dev->on) ? 0x2eb : 0x3c7, val, svga); + svga_out(0x3c7, val, svga); break; default: ramdac->regs[addr & 0xf] = val; @@ -176,21 +175,20 @@ uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga) { const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; - const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp = 0; switch (addr) { case 0: - temp = svga_in((dev && dev->on) ? 0x2ec : 0x3c8, svga); + temp = svga_in(0x3c8, svga); break; case 1: - temp = svga_in((dev && dev->on) ? 0x2ed : 0x3c9, svga); + temp = svga_in(0x3c9, svga); break; case 2: - temp = svga_in((dev && dev->on) ? 0x2ea : 0x3c6, svga); + temp = svga_in(0x3c6, svga); break; case 3: - temp = svga_in((dev && dev->on) ? 0x2eb : 0x3c7, svga); + temp = svga_in(0x3c7, svga); break; case 4: case 8: diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 2038f1b1d..6e2798295 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -438,6 +438,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; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -661,6 +662,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; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1067,6 +1069,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; if (mach->accel.dp_config & 0x02) { READ(dev->accel.src + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); @@ -1308,6 +1311,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; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -1441,6 +1445,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; mach->accel.clip_overrun = 0; if (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { @@ -1599,6 +1604,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; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -1733,6 +1739,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; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -2028,6 +2035,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; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -2333,6 +2341,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); + mach_log("8514/A RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); if ((dev->local & 0xff) >= 0x02) { if (mach->regs[0xb0] & 0x20) { /*ATI extended 8514/A mode.*/ mach_log("Extended 8514/A mode.\n"); @@ -2341,10 +2350,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); mach32_updatemapping(mach, svga); } - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); - else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + if (dev->on) + svga_out(addr, val, svga); + else { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } } else svga_out(addr, val, svga); return; @@ -2355,6 +2368,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x3C9: rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); + mach_log("VGA RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); if ((dev->local & 0xff) >= 0x02) { if (svga->attrregs[0x10] & 0x40) { mach_log("VGA mode.\n"); @@ -2363,10 +2377,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); mach32_updatemapping(mach, svga); } - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); - else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + if (dev->on) + svga_out(addr, val, svga); + else { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } } else svga_out(addr, val, svga); return; @@ -2481,10 +2499,14 @@ mach_in(uint16_t addr, void *priv) rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); if ((dev->local & 0xff) >= 0x02) { - if (mach->pci_bus && !mach->ramdac_type) - temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); - else - temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + if (dev->on) + temp = svga_in(addr, svga); + else { + if (mach->pci_bus && !mach->ramdac_type) + temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); + else + temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } } else temp = svga_in(addr, svga); break; @@ -3407,7 +3429,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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) + if (port == 0x42e8 || port == 0x42e9) mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { @@ -3422,7 +3444,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 break; case 0x42e9: ibm8514_accel_out(port, val, svga, 2); - if ((val & 0xc0) == 0xc0) { + if ((val & 0xc0) == 0x80) { dev->ext_fifo_idx = 0; mach->force_busy = 0; } @@ -3513,6 +3535,11 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 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; @@ -4201,6 +4228,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) switch (port) { case 0x2e8: + case 0x2e9: case 0x6e8: case 0x22e8: case 0x26e8: @@ -4212,18 +4240,22 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x42e8: case 0x42e9: - if (dev->vc == dev->v_syncstart) + if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) temp |= 0x01; if (mach->accel.cmd_type == -1) { if (cmd == 6) { - if ((dev->accel.dx >= clip_l) && + 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->accel.cx >= clip_l) && + 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)) @@ -4234,7 +4266,9 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 1: case 2: case 5: - if ((dev->accel.dx >= clip_l) && + 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)) @@ -4242,7 +4276,9 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) break; case 3: case 4: - if ((dev->accel.cx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) @@ -4257,16 +4293,17 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) if ((!dev->force_busy && !dev->force_busy2) || !mach->force_busy) temp |= 0x08; } - if (port & 1) + if (port & 1) { temp = dev->vram_512k_8514 ? 0x00 : 0x80; - else { + temp |= (dev->subsys_cntl >> 8); + } else { 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); else temp |= 0x20; } - mach_log("0x%04x read: Subsystem Status=%02x.\n", port, temp); + mach_log("0x%04x read: Subsystem Status=%02x, monitoralias=%02x.\n", port, temp, mach->accel.ext_ge_config & 0x07); break; /*ATI Mach8/32 specific registers*/ @@ -4403,7 +4440,8 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) default: break; } - mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + 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); return temp; } @@ -5419,6 +5457,10 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) 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); } 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); From d25aed2da98cfc4e2208bb46cd24776d5e6b6020 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 7 Mar 2025 00:36:09 +0600 Subject: [PATCH 0384/1190] Add global mute option --- src/86box.c | 1 + src/config.c | 5 ++++ src/include/86box/86box.h | 1 + src/qt/icons/sound_mute.ico | Bin 0 -> 9622 bytes src/qt/qt_machinestatus.cpp | 45 +++++++++++++++++++++++++++++++----- src/qt/qt_machinestatus.hpp | 6 +++++ src/qt/qt_mainwindow.cpp | 1 + src/qt_resources.qrc | 1 + src/sound/openal.c | 2 +- src/sound/xaudio2.c | 2 +- 10 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/qt/icons/sound_mute.ico diff --git a/src/86box.c b/src/86box.c index 6b64cd2ec..aa3afb085 100644 --- a/src/86box.c +++ b/src/86box.c @@ -213,6 +213,7 @@ int do_auto_pause = 0; /* (C) Auto-pa int hook_enabled = 1; /* (C) Keyboard hook is enabled */ int test_mode = 0; /* (C) Test mode */ char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */ +int sound_muted = 0; /* (C) Is sound muted? */ int other_ide_present = 0; /* IDE controllers from non-IDE cards are present */ diff --git a/src/config.c b/src/config.c index 6c34c4790..07e770822 100644 --- a/src/config.c +++ b/src/config.c @@ -168,6 +168,7 @@ load_general(void) kbd_req_capture = ini_section_get_int(cat, "kbd_req_capture", 0); hide_status_bar = ini_section_get_int(cat, "hide_status_bar", 0); hide_tool_bar = ini_section_get_int(cat, "hide_tool_bar", 0); + sound_muted = ini_section_get_int(cat, "sound_muted", 0); confirm_reset = ini_section_get_int(cat, "confirm_reset", 1); confirm_exit = ini_section_get_int(cat, "confirm_exit", 1); @@ -1846,6 +1847,10 @@ save_general(void) const char *va_name; + ini_section_set_int(cat, "sound_muted", sound_muted); + if (sound_muted == 0) + ini_section_delete_var(cat, "sound_muted"); + ini_section_set_int(cat, "vid_resize", vid_resize); if (vid_resize == 0) ini_section_delete_var(cat, "vid_resize"); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index e4e5ecae1..79bb84009 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -158,6 +158,7 @@ extern int other_scsi_present; /* SCSI controllers from non-SCSI ca extern int hard_reset_pending; extern int fixed_size_x; extern int fixed_size_y; +extern int sound_muted; /* (C) Is sound muted? */ extern int do_auto_pause; /* (C) Auto-pause the emulator on focus loss */ extern int auto_paused; extern double mouse_sensitivity; /* (C) Mouse sensitivity scale */ diff --git a/src/qt/icons/sound_mute.ico b/src/qt/icons/sound_mute.ico new file mode 100644 index 0000000000000000000000000000000000000000..89a8407354ce0ef805689d75763cd17fd58ce52b GIT binary patch literal 9622 zcmeI2F^?QY5QTg3frUWg0!ujC3km%XxJ{hmz$3y#LPCTj#2ygBWDxKJHUNPJ38zQ| zcNRau(TdPGxd2PZiFL4Mx2Wo#Z>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#-aHFa7 #include <86box/ui.h> #include <86box/machine_status.h> +#include <86box/config.h> }; #include @@ -89,7 +90,7 @@ struct Pixmaps { PixmapSetEmptyActive mo; PixmapSetActive hd; PixmapSetEmptyActive net; - QPixmap sound; + QPixmap sound, soundMuted; }; struct StateActive { @@ -215,6 +216,7 @@ struct MachineStatus::States { 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); cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; @@ -256,12 +258,19 @@ MachineStatus::MachineStatus(QObject *parent) , refreshTimer(new QTimer(this)) { d = std::make_unique(this); + muteUnmuteAction = nullptr; connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons); refreshTimer->start(75); } MachineStatus::~MachineStatus() = default; +void +MachineStatus::setSoundGainAction(QAction* action) +{ + soundGainAction = action; +} + bool MachineStatus::hasCassette() { @@ -494,6 +503,28 @@ MachineStatus::refresh(QStatusBar *sbar) } sbar->removeWidget(d->sound.get()); + if (!muteUnmuteAction) { + muteUnmuteAction = new QAction; + connect(muteUnmuteAction, &QAction::triggered, this, [this]() { + sound_muted ^= 1; + config_save(); + if (d->sound) + d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + + muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); + }); + } + + if (!soundMenu) { + soundMenu = new QMenu((QWidget*)parent()); + + soundMenu->addAction(muteUnmuteAction); + soundMenu->addSeparator(); + soundMenu->addAction(soundGainAction); + + muteUnmuteAction->setParent(soundMenu); + } + if (cassette_enable) { d->cassette.label = std::make_unique(); d->cassette.setEmpty(QString(cassette_fname).isEmpty()); @@ -662,12 +693,14 @@ MachineStatus::refresh(QStatusBar *sbar) } d->sound = std::make_unique(); - d->sound->setPixmap(d->pixmaps.sound); - - connect(d->sound.get(), &ClickableLabel::doubleClicked, d->sound.get(), [](QPoint pos) { - SoundGain gain(main_window); - gain.exec(); + 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())); }); + d->sound->setToolTip(tr("Sound")); sbar->addWidget(d->sound.get()); d->text = std::make_unique(); diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index fc0e33e91..90b420763 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -1,6 +1,8 @@ #ifndef QT_MACHINESTATUS_HPP #define QT_MACHINESTATUS_HPP +#include +#include #include #include #include @@ -71,6 +73,7 @@ public: QString getMessage(); void clearActivity(); + void setSoundGainAction(QAction* action); public slots: void refresh(QStatusBar *sbar); void message(const QString &msg); @@ -82,6 +85,9 @@ private: struct States; std::unique_ptr d; QTimer *refreshTimer; + QAction *soundGainAction; + QAction *muteUnmuteAction; + QMenu *soundMenu; }; #endif // QT_MACHINESTATUS_HPP diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 552fd0310..61f5f6fe1 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -178,6 +178,7 @@ MainWindow::MainWindow(QWidget *parent) extern MainWindow *main_window; main_window = this; ui->setupUi(this); + status->setSoundGainAction(ui->actionSound_gain); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 1f6341786..6ca323b89 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -43,6 +43,7 @@ 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 diff --git a/src/sound/openal.c b/src/sound/openal.c index a41199b23..90f626362 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -278,7 +278,7 @@ givealbuffer_common(const void *buf, const uint8_t src, const int size, const in alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed); if (processed >= 1) { - const double gain = pow(10.0, (double) sound_gain / 20.0); + const double gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); alListenerf(AL_GAIN, (float) gain); alSourceUnqueueBuffers(source[src], 1, &buffer); diff --git a/src/sound/xaudio2.c b/src/sound/xaudio2.c index 9b341f574..2aee97efc 100644 --- a/src/sound/xaudio2.c +++ b/src/sound/xaudio2.c @@ -245,7 +245,7 @@ givealbuffer_common(const void *buf, IXAudio2SourceVoice *sourcevoice, const siz if (!initialized) return; - (void) IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double) sound_gain / 20.0), + (void) IXAudio2MasteringVoice_SetVolume(mastervoice, sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0), XAUDIO2_COMMIT_NOW); XAUDIO2_BUFFER buffer = { 0 }; buffer.Flags = 0; From c1c4bcc889d59f5a4f714d6802e5592054f5cacf Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 15:54:50 +0500 Subject: [PATCH 0385/1190] Disable Win11 rounded window corners when the status bar is hidden --- src/qt/qt_mainwindow.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 61f5f6fe1..9802a2666 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -122,6 +122,19 @@ extern int qt_nvr_save(void); #include "x11_util.h" #endif +#ifdef Q_OS_WINDOWS +#include +#ifndef DWMWA_WINDOW_CORNER_PREFERENCE +#define DWMWA_WINDOW_CORNER_PREFERENCE 33 +#endif +#ifndef DWMWCP_DEFAULT +#define DWMWCP_DEFAULT 0 +#endif +#ifndef DWMWCP_DONOTROUND +#define DWMWCP_DONOTROUND 1 +#endif +#endif + #ifdef Q_OS_MACOS # include "cocoa_keyboard.hpp" // The namespace is required to avoid clashing typedefs; we only use this @@ -181,6 +194,10 @@ MainWindow::MainWindow(QWidget *parent) status->setSoundGainAction(ui->actionSound_gain); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); +#ifdef Q_OS_WINDOWS + auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); + DwmSetWindowAttribute((HWND) this->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +#endif statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); this->centralWidget()->setStyleSheet("background-color: black;"); ui->toolBar->setVisible(!hide_tool_bar); @@ -1833,6 +1850,10 @@ MainWindow::on_actionHide_status_bar_triggered() hide_status_bar ^= 1; ui->actionHide_status_bar->setChecked(hide_status_bar); statusBar()->setVisible(!hide_status_bar); +#ifdef Q_OS_WINDOWS + auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); + DwmSetWindowAttribute((HWND) main_window->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +#endif if (vid_resize >= 2) { setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); } else { From d6fa4d4f98f15f6b21ebffcff0bfa3a2f6b8a76a Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 6 Mar 2025 22:20:13 +0500 Subject: [PATCH 0386/1190] Disable Win11 rounded corners on the secondary monitor windows --- src/qt/qt_mainwindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 9802a2666..036f56375 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -816,6 +816,10 @@ MainWindow::initRendererMonitorSlot(int monitor_index) if (vid_resize == 2) secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); secondaryRenderer->setWindowIcon(this->windowIcon()); +#ifdef Q_OS_WINDOWS + auto cornerPreference = DWMWCP_DONOTROUND; + DwmSetWindowAttribute((HWND) secondaryRenderer->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +#endif if (show_second_monitors) { secondaryRenderer->show(); if (window_remember) { From e6f96352e083a9df48e87babed6e3afadf7a0e89 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 02:01:00 +0500 Subject: [PATCH 0387/1190] Fix serial passthrough configure buttons not re-enabling when the checkboxes are toggled --- src/qt/qt_settingsports.cpp | 43 ++++++++++++++++--------------------- src/qt/qt_settingsports.hpp | 14 ++++++------ 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 9679c9e21..3855a8b68 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -68,21 +68,14 @@ SettingsPorts::SettingsPorts(QWidget *parent) for (int i = 0; i < SERIAL_MAX; i++) { auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); + auto *buttonPass = findChild(QString("pushButtonSerialPassThru%1").arg(i + 1)); if (checkBox != NULL) checkBox->setChecked(com_ports[i].enabled > 0); - if (checkBoxPass != NULL) + if (checkBoxPass != NULL) { checkBoxPass->setChecked(serial_passthrough_enabled[i]); + buttonPass->setEnabled(serial_passthrough_enabled[i]); + } } - - ui->pushButtonSerialPassThru1->setEnabled(serial_passthrough_enabled[0]); - ui->pushButtonSerialPassThru2->setEnabled(serial_passthrough_enabled[1]); - ui->pushButtonSerialPassThru3->setEnabled(serial_passthrough_enabled[2]); - ui->pushButtonSerialPassThru4->setEnabled(serial_passthrough_enabled[3]); -#if 0 - ui->pushButtonSerialPassThru5->setEnabled(serial_passthrough_enabled[4]); - ui->pushButtonSerialPassThru6->setEnabled(serial_passthrough_enabled[5]); - ui->pushButtonSerialPassThru7->setEnabled(serial_passthrough_enabled[6]); -#endif } SettingsPorts::~SettingsPorts() @@ -181,45 +174,45 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked() #endif void -SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru1_stateChanged(int state) { - ui->pushButtonSerialPassThru1->setEnabled(checked); + ui->pushButtonSerialPassThru1->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru2_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru2_stateChanged(int state) { - ui->pushButtonSerialPassThru2->setEnabled(checked); + ui->pushButtonSerialPassThru2->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru3_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru3_stateChanged(int state) { - ui->pushButtonSerialPassThru3->setEnabled(checked); + ui->pushButtonSerialPassThru3->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru4_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru4_stateChanged(int state) { - ui->pushButtonSerialPassThru4->setEnabled(checked); + ui->pushButtonSerialPassThru4->setEnabled(state == Qt::Checked); } #if 0 void -SettingsPorts::on_checkBoxSerialPassThru5_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru5_stateChanged(int state) { - ui->pushButtonSerialPassThru5->setEnabled(checked); + ui->pushButtonSerialPassThru5->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru6_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru6_stateChanged(int state) { - ui->pushButtonSerialPassThru6->setEnabled(checked); + ui->pushButtonSerialPassThru6->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru7_stateChanged(int state) { - ui->pushButtonSerialPassThru7->setEnabled(checked); + ui->pushButtonSerialPassThru7->setEnabled(state == Qt::Checked); } #endif diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index fb9cdb343..cba5bceff 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -18,14 +18,14 @@ public: #if 0 private slots: - void on_checkBoxSerialPassThru7_clicked(bool checked); - void on_checkBoxSerialPassThru6_clicked(bool checked); - void on_checkBoxSerialPassThru5_clicked(bool checked); + void on_checkBoxSerialPassThru7_stateChanged(int state); + void on_checkBoxSerialPassThru6_stateChanged(int state); + void on_checkBoxSerialPassThru5_stateChanged(int state); #endif - void on_checkBoxSerialPassThru4_clicked(bool checked); - void on_checkBoxSerialPassThru3_clicked(bool checked); - void on_checkBoxSerialPassThru2_clicked(bool checked); - void on_checkBoxSerialPassThru1_clicked(bool checked); + void on_checkBoxSerialPassThru4_stateChanged(int state); + void on_checkBoxSerialPassThru3_stateChanged(int state); + void on_checkBoxSerialPassThru2_stateChanged(int state); + void on_checkBoxSerialPassThru1_stateChanged(int state); private slots: #if 0 From b018017c55a5f2c8c80cc6816369ac56ef76811f Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 02:05:30 +0500 Subject: [PATCH 0388/1190] Disable serial passthrough checkboxes when the corresponding port is disabled --- src/qt/qt_settingsports.cpp | 54 ++++++++++++++++++++++++++++++++++++- src/qt/qt_settingsports.hpp | 22 ++++++++++----- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 3855a8b68..e5a8039a4 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -72,8 +72,9 @@ SettingsPorts::SettingsPorts(QWidget *parent) if (checkBox != NULL) checkBox->setChecked(com_ports[i].enabled > 0); if (checkBoxPass != NULL) { + checkBoxPass->setEnabled(com_ports[i].enabled > 0); checkBoxPass->setChecked(serial_passthrough_enabled[i]); - buttonPass->setEnabled(serial_passthrough_enabled[i]); + buttonPass->setEnabled((com_ports[i].enabled > 0) && serial_passthrough_enabled[i]); } } } @@ -173,6 +174,57 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked() } #endif +void +SettingsPorts::on_checkBoxSerial1_stateChanged(int state) +{ + ui->checkBoxSerialPassThru1->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru1->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru1->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial2_stateChanged(int state) +{ + ui->checkBoxSerialPassThru2->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru2->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru2->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial3_stateChanged(int state) +{ + ui->checkBoxSerialPassThru3->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru3->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru3->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial4_stateChanged(int state) +{ + ui->checkBoxSerialPassThru4->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru4->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru4->isChecked()); +} + +#if 0 +void +SettingsPorts::on_checkBoxSerial5_stateChanged(int state) +{ + ui->checkBoxSerialPassThru5->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru5->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru5->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial6_stateChanged(int state) +{ + ui->checkBoxSerialPassThru6->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru6->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru6->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial7_stateChanged(int state) +{ + ui->checkBoxSerialPassThru7->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru7->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru7->isChecked()); +} +#endif + void SettingsPorts::on_checkBoxSerialPassThru1_stateChanged(int state) { diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index cba5bceff..7d332509c 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -16,8 +16,8 @@ public: void save(); -#if 0 private slots: +#if 0 void on_checkBoxSerialPassThru7_stateChanged(int state); void on_checkBoxSerialPassThru6_stateChanged(int state); void on_checkBoxSerialPassThru5_stateChanged(int state); @@ -27,7 +27,16 @@ private slots: void on_checkBoxSerialPassThru2_stateChanged(int state); void on_checkBoxSerialPassThru1_stateChanged(int state); -private slots: +#if 0 + void on_checkBoxSerial7_stateChanged(int state); + void on_checkBoxSerial6_stateChanged(int state); + void on_checkBoxSerial5_stateChanged(int state); +#endif + void on_checkBoxSerial4_stateChanged(int state); + void on_checkBoxSerial3_stateChanged(int state); + void on_checkBoxSerial2_stateChanged(int state); + void on_checkBoxSerial1_stateChanged(int state); + #if 0 void on_pushButtonSerialPassThru7_clicked(); void on_pushButtonSerialPassThru6_clicked(); @@ -38,11 +47,10 @@ private slots: void on_pushButtonSerialPassThru2_clicked(); void on_pushButtonSerialPassThru1_clicked(); -private slots: - void on_checkBoxParallel4_stateChanged(int arg1); - void on_checkBoxParallel3_stateChanged(int arg1); - void on_checkBoxParallel2_stateChanged(int arg1); - void on_checkBoxParallel1_stateChanged(int arg1); + void on_checkBoxParallel4_stateChanged(int state); + void on_checkBoxParallel3_stateChanged(int state); + void on_checkBoxParallel2_stateChanged(int state); + void on_checkBoxParallel1_stateChanged(int state); private: Ui::SettingsPorts *ui; From 3bbeae91d1c405ea979b948c3407f3cef3479327 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 15:22:36 +0500 Subject: [PATCH 0389/1190] Add plumbing for updates on machine change to the port settings page --- src/qt/qt_settings.cpp | 2 + src/qt/qt_settingsports.cpp | 149 +++++++++++++++++++----------------- src/qt/qt_settingsports.hpp | 69 +++++++++-------- 3 files changed, 116 insertions(+), 104 deletions(-) diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index 67064b73a..471558e22 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -153,6 +153,8 @@ Settings::Settings(QWidget *parent) &SettingsSound::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, network, &SettingsNetwork::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, ports, + &SettingsPorts::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, storageControllers, &SettingsStorageControllers::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, otherPeripherals, diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index e5a8039a4..630c843b9 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -38,6 +38,40 @@ SettingsPorts::SettingsPorts(QWidget *parent) , ui(new Ui::SettingsPorts) { ui->setupUi(this); + onCurrentMachineChanged(machine); +} + +SettingsPorts::~SettingsPorts() +{ + delete ui; +} + +void +SettingsPorts::save() +{ + for (int i = 0; i < PARALLEL_MAX; i++) { + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); + if (cbox != NULL) + lpt_ports[i].device = cbox->currentData().toInt(); + if (checkBox != NULL) + lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + } + + for (int i = 0; i < SERIAL_MAX; i++) { + auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); + auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); + if (checkBox != NULL) + com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + if (checkBoxPass != NULL) + serial_passthrough_enabled[i] = checkBoxPass->isChecked(); + } +} + +void +SettingsPorts::onCurrentMachineChanged(int machineId) +{ + this->machineId = machineId; for (int i = 0; i < PARALLEL_MAX; i++) { auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); @@ -79,33 +113,6 @@ SettingsPorts::SettingsPorts(QWidget *parent) } } -SettingsPorts::~SettingsPorts() -{ - delete ui; -} - -void -SettingsPorts::save() -{ - for (int i = 0; i < PARALLEL_MAX; i++) { - auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); - auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); - if (cbox != NULL) - lpt_ports[i].device = cbox->currentData().toInt(); - if (checkBox != NULL) - lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; - } - - for (int i = 0; i < SERIAL_MAX; i++) { - auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); - auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); - if (checkBox != NULL) - com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; - if (checkBoxPass != NULL) - serial_passthrough_enabled[i] = checkBoxPass->isChecked(); - } -} - void SettingsPorts::on_checkBoxParallel1_stateChanged(int state) { @@ -130,50 +137,6 @@ SettingsPorts::on_checkBoxParallel4_stateChanged(int state) ui->comboBoxLpt4->setEnabled(state == Qt::Checked); } -void -SettingsPorts::on_pushButtonSerialPassThru1_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru2_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru3_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru4_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); -} - -#if 0 -void -SettingsPorts::on_pushButtonSerialPassThru5_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru6_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru7_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); -} -#endif - void SettingsPorts::on_checkBoxSerial1_stateChanged(int state) { @@ -268,3 +231,47 @@ SettingsPorts::on_checkBoxSerialPassThru7_stateChanged(int state) ui->pushButtonSerialPassThru7->setEnabled(state == Qt::Checked); } #endif + +void +SettingsPorts::on_pushButtonSerialPassThru1_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru2_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru3_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru4_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); +} + +#if 0 +void +SettingsPorts::on_pushButtonSerialPassThru5_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru6_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru7_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); +} +#endif diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index 7d332509c..83560914f 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -16,44 +16,47 @@ public: void save(); +public slots: + void onCurrentMachineChanged(int machineId); + private slots: -#if 0 - void on_checkBoxSerialPassThru7_stateChanged(int state); - void on_checkBoxSerialPassThru6_stateChanged(int state); - void on_checkBoxSerialPassThru5_stateChanged(int state); -#endif - void on_checkBoxSerialPassThru4_stateChanged(int state); - void on_checkBoxSerialPassThru3_stateChanged(int state); - void on_checkBoxSerialPassThru2_stateChanged(int state); - void on_checkBoxSerialPassThru1_stateChanged(int state); - -#if 0 - void on_checkBoxSerial7_stateChanged(int state); - void on_checkBoxSerial6_stateChanged(int state); - void on_checkBoxSerial5_stateChanged(int state); -#endif - void on_checkBoxSerial4_stateChanged(int state); - void on_checkBoxSerial3_stateChanged(int state); - void on_checkBoxSerial2_stateChanged(int state); - void on_checkBoxSerial1_stateChanged(int state); - -#if 0 - void on_pushButtonSerialPassThru7_clicked(); - void on_pushButtonSerialPassThru6_clicked(); - void on_pushButtonSerialPassThru5_clicked(); -#endif - void on_pushButtonSerialPassThru4_clicked(); - void on_pushButtonSerialPassThru3_clicked(); - void on_pushButtonSerialPassThru2_clicked(); - void on_pushButtonSerialPassThru1_clicked(); - - void on_checkBoxParallel4_stateChanged(int state); - void on_checkBoxParallel3_stateChanged(int state); - void on_checkBoxParallel2_stateChanged(int state); void on_checkBoxParallel1_stateChanged(int state); + void on_checkBoxParallel2_stateChanged(int state); + void on_checkBoxParallel3_stateChanged(int state); + void on_checkBoxParallel4_stateChanged(int state); + + void on_checkBoxSerial1_stateChanged(int state); + void on_checkBoxSerial2_stateChanged(int state); + void on_checkBoxSerial3_stateChanged(int state); + void on_checkBoxSerial4_stateChanged(int state); +#if 0 + void on_checkBoxSerial5_stateChanged(int state); + void on_checkBoxSerial6_stateChanged(int state); + void on_checkBoxSerial7_stateChanged(int state); +#endif + void on_checkBoxSerialPassThru1_stateChanged(int state); + void on_checkBoxSerialPassThru2_stateChanged(int state); + void on_checkBoxSerialPassThru3_stateChanged(int state); + void on_checkBoxSerialPassThru4_stateChanged(int state); +#if 0 + void on_checkBoxSerialPassThru5_stateChanged(int state); + void on_checkBoxSerialPassThru6_stateChanged(int state); + void on_checkBoxSerialPassThru7_stateChanged(int state); +#endif + + void on_pushButtonSerialPassThru1_clicked(); + void on_pushButtonSerialPassThru2_clicked(); + void on_pushButtonSerialPassThru3_clicked(); + void on_pushButtonSerialPassThru4_clicked(); +#if 0 + void on_pushButtonSerialPassThru5_clicked(); + void on_pushButtonSerialPassThru6_clicked(); + void on_pushButtonSerialPassThru7_clicked(); +#endif private: Ui::SettingsPorts *ui; + int machineId = 0; }; #endif // QT_SETTINGSPORTS_HPP From 676087bcaecd2986f48fdc919b430481023c06b9 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 7 Mar 2025 00:11:45 +0500 Subject: [PATCH 0390/1190] Refactor into a function --- src/qt/qt_mainwindow.cpp | 22 +++------------------- src/qt/qt_util.cpp | 22 ++++++++++++++++++++++ src/qt/qt_util.hpp | 3 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 036f56375..1cc6c33c9 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -122,19 +122,6 @@ extern int qt_nvr_save(void); #include "x11_util.h" #endif -#ifdef Q_OS_WINDOWS -#include -#ifndef DWMWA_WINDOW_CORNER_PREFERENCE -#define DWMWA_WINDOW_CORNER_PREFERENCE 33 -#endif -#ifndef DWMWCP_DEFAULT -#define DWMWCP_DEFAULT 0 -#endif -#ifndef DWMWCP_DONOTROUND -#define DWMWCP_DONOTROUND 1 -#endif -#endif - #ifdef Q_OS_MACOS # include "cocoa_keyboard.hpp" // The namespace is required to avoid clashing typedefs; we only use this @@ -195,8 +182,7 @@ MainWindow::MainWindow(QWidget *parent) ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); #ifdef Q_OS_WINDOWS - auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); - DwmSetWindowAttribute((HWND) this->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); + util::setWin11RoundedCorners(this->winId(), (hide_status_bar ? false : true)); #endif statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); this->centralWidget()->setStyleSheet("background-color: black;"); @@ -817,8 +803,7 @@ MainWindow::initRendererMonitorSlot(int monitor_index) secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); secondaryRenderer->setWindowIcon(this->windowIcon()); #ifdef Q_OS_WINDOWS - auto cornerPreference = DWMWCP_DONOTROUND; - DwmSetWindowAttribute((HWND) secondaryRenderer->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); + util::setWin11RoundedCorners(secondaryRenderer->winId(), false); #endif if (show_second_monitors) { secondaryRenderer->show(); @@ -1855,8 +1840,7 @@ MainWindow::on_actionHide_status_bar_triggered() ui->actionHide_status_bar->setChecked(hide_status_bar); statusBar()->setVisible(!hide_status_bar); #ifdef Q_OS_WINDOWS - auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); - DwmSetWindowAttribute((HWND) main_window->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); + util::setWin11RoundedCorners(main_window->winId(), (hide_status_bar ? false : true)); #endif if (vid_resize >= 2) { setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index 5c9059272..0c78c2f5e 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -26,6 +26,19 @@ #include #include "qt_util.hpp" +#ifdef Q_OS_WINDOWS +# include +# ifndef DWMWA_WINDOW_CORNER_PREFERENCE +# define DWMWA_WINDOW_CORNER_PREFERENCE 33 +# endif +# ifndef DWMWCP_DEFAULT +# define DWMWCP_DEFAULT 0 +# endif +# ifndef DWMWCP_DONOTROUND +# define DWMWCP_DONOTROUND 1 +# endif +#endif + extern "C" { #include <86box/86box.h> #include <86box/config.h> @@ -48,6 +61,15 @@ screenOfWidget(QWidget *widget) #endif } +#ifdef Q_OS_WINDOWS +void +setWin11RoundedCorners(WId hwnd, bool enable) +{ + auto cornerPreference = (enable ? DWMWCP_DEFAULT : DWMWCP_DONOTROUND); + DwmSetWindowAttribute((HWND) hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +} +#endif + QString DlgFilter(std::initializer_list extensions, bool last) { diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 6a0bdc30b..9432610b6 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -13,6 +13,9 @@ static constexpr auto UUID_MIN_LENGTH = 36; QString DlgFilter(std::initializer_list extensions, bool last = false); /* Returns screen the widget is on */ QScreen *screenOfWidget(QWidget *widget); +#ifdef Q_OS_WINDOWS +void setWin11RoundedCorners(WId hwnd, bool enable); +#endif QString currentUuid(); void storeCurrentUuid(); bool compareUuid(); From 05a005b6f0a681b965ab60ae7638c2c2408fd8e7 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 7 Mar 2025 05:21:16 +0500 Subject: [PATCH 0391/1190] Initialize the sound icon menu pointer Fixes a crash when clicking the icon --- src/qt/qt_machinestatus.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index 3c3f4019f..a00cc032b 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -259,6 +259,7 @@ MachineStatus::MachineStatus(QObject *parent) { d = std::make_unique(this); muteUnmuteAction = nullptr; + soundMenu = nullptr; connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons); refreshTimer->start(75); } From 265152db754b7b60cc3eeafd2b6b596ef0c4da0b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 7 Mar 2025 19:58:36 +0100 Subject: [PATCH 0392/1190] NCR 53c400: slightly more accurate speed. See above. --- src/scsi/scsi_ncr53c400.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index c83e75442..fc62a1cab 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -425,8 +425,8 @@ ncr53c400_callback(void *priv) if (scsi_bus->tx_mode != PIO_TX_BUS) { if (ncr400->type == ROM_T130B) { - ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 200.0); - timer_on_auto(&ncr400->timer, scsi_bus->period / 200.0); + 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); } From 86343327be6d2cd41424d1deeaa659b493bc31f2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 8 Mar 2025 02:13:14 +0600 Subject: [PATCH 0393/1190] Initial PCem OpenGL 3.x renderer port --- src/86box.c | 2 + src/device/kbc_at_dev.c | 3 + src/include/86box/86box.h | 2 + src/include/86box/ini.h | 28 + src/include/86box/keyboard.h | 27 +- src/include/86box/qt-glsl.h | 158 +++ src/include/86box/qt-glslp-parser.h | 56 + src/ini.c | 22 + src/qt/CMakeLists.txt | 3 + src/qt/qt.c | 5 + src/qt/qt_glsl_parser.cpp | 308 +++++ src/qt/qt_main.cpp | 1 + src/qt/qt_mainwindow.cpp | 3 + src/qt/qt_openglrenderer_pcem.cpp | 1679 +++++++++++++++++++++++++++ src/qt/qt_openglrenderer_pcem.hpp | 127 ++ src/qt/qt_rendererstack.cpp | 33 +- src/qt/qt_rendererstack.hpp | 1 + 17 files changed, 2442 insertions(+), 16 deletions(-) create mode 100644 src/include/86box/qt-glsl.h create mode 100644 src/include/86box/qt-glslp-parser.h create mode 100644 src/qt/qt_glsl_parser.cpp create mode 100644 src/qt/qt_openglrenderer_pcem.cpp create mode 100644 src/qt/qt_openglrenderer_pcem.hpp diff --git a/src/86box.c b/src/86box.c index aa3afb085..13167b1bd 100644 --- a/src/86box.c +++ b/src/86box.c @@ -252,6 +252,8 @@ int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */ int efscrnsz_y = SCREEN_RES_Y; #endif +__thread int is_cpu_thread = 0; + static wchar_t mouse_msg[3][200]; static volatile atomic_int do_pause_ack = 0; diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index c1041e6e1..82ce31bfd 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -88,6 +88,9 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main) { if (main) { kbc_at_dev_log("%s: dev->queue[%02X] = %02X;\n", dev->name, dev->queue_end, val); + if (!is_cpu_thread && kbc_at_dev_queue_pos(dev, 1) == dev->fifo_mask) { + while (kbc_at_dev_queue_pos(dev, 1) == dev->fifo_mask) {} + } dev->queue[dev->queue_end] = val; dev->queue_end = (dev->queue_end + 1) & dev->fifo_mask; } else { diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 79bb84009..30905741c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -188,6 +188,8 @@ extern FILE *stdlog; /* file to log output to */ #endif extern int config_changed; /* config has changed */ +extern __thread int is_cpu_thread; /* Is this the CPU thread? */ + /* Function prototypes. */ #ifdef HAVE_STDARG_H extern void pclog_ex(const char *fmt, va_list ap); diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h index d52620f69..2a73a18b0 100644 --- a/src/include/86box/ini.h +++ b/src/include/86box/ini.h @@ -58,6 +58,7 @@ extern void ini_section_set_hex20(ini_section_t section, const char *name, i extern void ini_section_set_mac(ini_section_t section, const char *name, int val); extern void ini_section_set_string(ini_section_t section, const char *name, const char *val); extern void ini_section_set_wstring(ini_section_t section, const char *name, wchar_t *val); +extern int ini_has_entry(ini_section_t self, const char *name); #define ini_delete_var(ini, head, name) ini_section_delete_var(ini_find_section(ini, head), name) @@ -90,6 +91,33 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); extern void ini_rename_section(ini_section_t section, const char *name); extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); +static inline void *wx_config_load(const char *path) { return (void*) ini_read(path); }; +static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); + if (size == 0) + return res; + strncpy(dst, str, size); + return res; +} +static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = ini_get_int((ini_t)config, "", name, defVal); + return res; +} +static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = (float)ini_get_double((ini_t)config, "", name, defVal); + return res; +} +static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = !!ini_get_int((ini_t)config, "", name, defVal); + return res; +} +static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); } +static inline void wx_config_free(void *config) { ini_close(config); }; + #ifdef __cplusplus } #endif diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 110e4f760..b7f301a58 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -22,6 +22,13 @@ #ifndef EMU_KEYBOARD_H #define EMU_KEYBOARD_H +#ifdef __cplusplus +# include +using atomic_uint = std::atomic_uint; +#else +# include +#endif + enum { DEV_KBD = 0, DEV_AUX = 1 @@ -54,16 +61,16 @@ typedef struct kbc_at_port_t { typedef struct atkbc_dev_t { const char *name; /* name of this device */ - uint8_t type; - uint8_t command; - uint8_t last_scan_code; - uint8_t state; - uint8_t resolution; - uint8_t rate; - uint8_t cmd_queue_start; - uint8_t cmd_queue_end; - uint8_t queue_start; - uint8_t queue_end; + uint8_t type; + uint8_t command; + uint8_t last_scan_code; + uint8_t state; + uint8_t resolution; + uint8_t rate; + uint8_t cmd_queue_start; + uint8_t cmd_queue_end; + atomic_uint queue_start; + atomic_uint queue_end; uint16_t flags; diff --git a/src/include/86box/qt-glsl.h b/src/include/86box/qt-glsl.h new file mode 100644 index 000000000..0cd8e27cd --- /dev/null +++ b/src/include/86box/qt-glsl.h @@ -0,0 +1,158 @@ +#ifndef SRC_WX_GLSL_H_ +#define SRC_WX_GLSL_H_ + +#define MAX_PREV 7 + +#define MAX_SHADERS 20 +#define MAX_TEXTURES 20 +#define MAX_PARAMETERS 100 + +#define MAX_USER_SHADERS 20 +//#define SDL2_SHADER_DEBUG + +struct shader_scale { + int mode[2]; + float value[2]; +}; + +struct shader_state { + float input_size[2]; + float input_texture_size[2]; + float output_texture_size[2]; + float output_size[2]; + float tex_coords[8]; +}; + +struct shader_vbo { + int vertex_coord; + int tex_coord; + int color; +}; + +struct shader_texture { + int id; + int width; + int height; + int type; + int internal_format; + int format; + int min_filter; + int mag_filter; + int wrap_mode; + void *data; + int mipmap; +}; + +struct shader_lut_texture { + char name[50]; + struct shader_texture texture; +}; + +struct shader_fbo { + int id; + struct shader_texture texture; + int srgb; + int mipmap_input; +}; + +struct shader_prev { + struct shader_fbo fbo; + struct shader_vbo vbo; +}; + +struct shader_input { + int texture; + int input_size; + int texture_size; + int tex_coord; +}; + +struct shader_uniforms { + int mvp_matrix; + int vertex_coord; + int tex_coord; + int color; + + int texture; + int input_size; + int texture_size; + int output_size; + + int frame_count; + int frame_direction; + + struct shader_input orig; + struct shader_input pass[MAX_SHADERS]; + struct shader_input prev_pass[MAX_SHADERS]; + struct shader_input prev[MAX_PREV]; + + int parameters[MAX_PARAMETERS]; + int lut_textures[MAX_TEXTURES]; +}; + +struct shader_program { + int vertex_shader; + int fragment_shader; + int id; +}; + +struct shader_parameter { + char id[64]; + char description[64]; + float default_value; + float value; + float min; + float max; + float step; +}; + +struct shader_pass { + int active; + char alias[64]; + int vertex_array; + int frame_count_mod; + struct shader_program program; + struct shader_uniforms uniforms; + struct shader_fbo fbo; + struct shader_vbo vbo; + struct shader_state state; + struct shader_scale scale; +}; + +struct glsl_shader { + int active; + char name[64]; + + int num_passes; + struct shader_pass passes[MAX_SHADERS]; + + int num_lut_textures; + struct shader_lut_texture lut_textures[MAX_TEXTURES]; + + int num_parameters; + struct shader_parameter parameters[MAX_PARAMETERS]; + + struct shader_pass prev_scene; + struct shader_prev prev[MAX_PREV + 1]; + + int last_prev_update; + int has_prev; + + float shader_refresh_rate; + + int input_filter_linear; +}; + +typedef struct glsl_t { + int num_shaders; + struct glsl_shader shaders[MAX_USER_SHADERS]; + struct shader_pass scene; + struct shader_pass final_pass; + struct shader_pass fs_color; +#ifdef SDL2_SHADER_DEBUG + struct shader_pass debug; +#endif + int srgb; +} glsl_t; + +#endif \ No newline at end of file diff --git a/src/include/86box/qt-glslp-parser.h b/src/include/86box/qt-glslp-parser.h new file mode 100644 index 000000000..cf2ac464a --- /dev/null +++ b/src/include/86box/qt-glslp-parser.h @@ -0,0 +1,56 @@ +#ifndef SRC_WX_GLSLP_PARSER_H_ +#define SRC_WX_GLSLP_PARSER_H_ + +#include "qt-glsl.h" + +struct parameter { + char id[64]; + char description[64]; + float default_value; + float value; + float min; + float max; + float step; +}; + +struct texture { + char path[256]; + char name[50]; + int linear; + int mipmap; + char wrap_mode[50]; +}; + +struct shader { + char shader_fn[1024]; + char *shader_program; + char alias[64]; + int filter_linear; + int float_framebuffer; + int srgb_framebuffer; + int mipmap_input; + int frame_count_mod; + char wrap_mode[50]; + char scale_type_x[9], scale_type_y[9]; + float scale_x, scale_y; +}; + +typedef struct glslp_t { + char name[64]; + int num_shaders; + struct shader shaders[MAX_SHADERS]; + + int num_textures; + struct texture textures[MAX_TEXTURES]; + + int num_parameters; + struct parameter parameters[MAX_PARAMETERS]; + + int input_filter_linear; +} glslp_t; + +void get_glslp_name(const char *f, char *s, int size); +glslp_t *glslp_parse(const char *f); +void glslp_free(glslp_t *p); + +#endif /* SRC_WX_GLSLP_PARSER_H_ */ \ No newline at end of file diff --git a/src/ini.c b/src/ini.c index 78c873758..4ea6f6381 100644 --- a/src/ini.c +++ b/src/ini.c @@ -157,6 +157,23 @@ find_entry(section_t *section, const char *name) return (NULL); } +int +ini_has_entry(ini_section_t self, const char *name) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + int value = 0; + + if (section == NULL) + return 0; + + entry = find_entry(section, name); + if (entry == NULL) + return 0; + + return 1; +} + static int entries_num(section_t *section) { @@ -593,6 +610,11 @@ ini_section_get_int(ini_section_t self, const char *name, int def) if (entry == NULL) return def; + if (stricmp(entry->data, "true") == 0) + return 1; + if (stricmp(entry->data, "false") == 0) + return 0; + sscanf(entry->data, "%i", &value); return value; diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index c08a03016..fd82b9053 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -89,6 +89,9 @@ add_library(ui STATIC qt_hardwarerenderer.hpp qt_openglrenderer.cpp qt_openglrenderer.hpp + qt_openglrenderer_pcem.cpp + qt_openglrenderer_pcem.hpp + qt_glsl_parser.cpp qt_opengloptions.cpp qt_opengloptions.hpp qt_opengloptionsdialog.cpp diff --git a/src/qt/qt.c b/src/qt/qt.c index a9a6460eb..13ddbf498 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -54,6 +54,8 @@ 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; @@ -83,6 +85,9 @@ 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_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp new file mode 100644 index 000000000..7cf032a52 --- /dev/null +++ b/src/qt/qt_glsl_parser.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +extern "C" +{ +#include <86box/86box.h> +#include <86box/ini.h> +#include <86box/qt-glslp-parser.h> +#include <86box/path.h> +} + +#define safe_strncpy(a, b, n) \ + do { \ + strncpy((a), (b), (n)-1); \ + (a)[(n)-1] = 0; \ + } while (0) + +static int endswith(const char *str, const char *ext) { + int i; + const char *p; + int elen = strlen(ext); + int slen = strlen(str); + if (slen >= elen) { + p = &str[slen - elen]; + for (i = 0; i < elen; ++i) { + if (tolower(p[i]) != tolower(ext[i])) + return 0; + } + return 1; + } + return 0; +} + +static char *load_file(const char *fn) { + FILE *f = fopen(fn, "rb"); + if (!f) + return 0; + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + char *data = (char*)malloc(fsize + 1); + + fread(data, fsize, 1, f); + fclose(f); + + data[fsize] = 0; + + return data; +} + +static void strip_lines(const char *program, const char *starts_with) { + /* strip parameters */ + char *ptr = strstr(program, starts_with); + while (ptr) { + while (*ptr != '\n' && *ptr != '\0') + *ptr++ = ' '; + ptr = strstr(program, starts_with); + } +} + +static void strip_parameters(const char *program) { + /* strip parameters */ + strip_lines(program, "#pragma parameter"); +} + +static void strip_defines(const char *program) { + /* strip texture define */ + strip_lines(program, "#define texture"); +} + +static int has_parameter(glslp_t *glsl, char *id) { + int i; + for (i = 0; i < glsl->num_parameters; ++i) + if (!strcmp(glsl->parameters[i].id, id)) + return 1; + return 0; +} + +static int get_parameters(glslp_t *glsl) { + int i; + struct parameter p; + for (i = 0; i < glsl->num_shaders; ++i) { + struct shader *shader = &glsl->shaders[i]; + FILE *f = fopen(shader->shader_fn, "rb"); + if (!f) + return 0; + + char line[1024]; + 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); + if (num < 5) + continue; + p.id[63] = 0; + p.description[63] = 0; + + if (num == 5) + p.step = 0.1f * (p.max - p.min); + + p.value = p.default_value; + + if (!has_parameter(glsl, p.id)) { + memcpy(&glsl->parameters[glsl->num_parameters++], &p, sizeof(struct parameter)); + pclog("Read parameter: %s (%s) %f, %f -> %f (%f)\n", p.id, p.description, p.default_value, p.min, + p.max, p.step); + } + } + + fclose(f); + } + + return 1; +} + +static struct parameter *get_parameter(glslp_t *glslp, const char *id) { + int i; + for (i = 0; i < glslp->num_parameters; ++i) { + if (!strcmp(glslp->parameters[i].id, id)) { + return &glslp->parameters[i]; + } + } + return 0; +} + +static glslp_t *glsl_parse(const char *f) { + glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t)); + memset(glslp, 0, sizeof(glslp_t)); + glslp->num_shaders = 1; + struct shader *shader = &glslp->shaders[0]; + strcpy(shader->shader_fn, f); + shader->shader_program = load_file(f); + if (!shader->shader_program) { + //wx_simple_messagebox("GLSL error", "Could not load shader %s\n", shader->shader_fn); + glslp_free(glslp); + return 0; + } + strip_parameters(shader->shader_program); + strip_defines(shader->shader_program); + shader->scale_x = shader->scale_y = 1.0f; + strcpy(shader->scale_type_x, "source"); + strcpy(shader->scale_type_y, "source"); + get_parameters(glslp); + return glslp; +} + +extern "C" { + +void get_glslp_name(const char *f, char *s, int size) { safe_strncpy(s, path_get_filename((char *)f), size); } + +glslp_t *glslp_parse(const char *f) { + int i, j, len, sublen; + char s[513], t[513], z[540]; + + memset(s, 0, sizeof(s)); + if (endswith(f, ".glsl")) + return glsl_parse(f); + + void *cfg = wx_config_load(f); + + if (!cfg) { + fprintf(stderr, "GLSLP Error: Could not load GLSLP-file %s\n", f); + return 0; + } + + glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t)); + memset(glslp, 0, sizeof(glslp_t)); + + get_glslp_name(f, glslp->name, sizeof(glslp->name)); + + wx_config_get_int(cfg, "shaders", &glslp->num_shaders, 0); + + wx_config_get_bool(cfg, "filter_linear0", &glslp->input_filter_linear, -1); + + for (i = 0; i < glslp->num_shaders; ++i) { + struct shader *shader = &glslp->shaders[i]; + + snprintf(s, sizeof(s) - 1, "shader%d", i); + if (!wx_config_get_string(cfg, s, t, sizeof(t), 0)) { + /* shader doesn't exist, lets break here */ + glslp->num_shaders = i; + break; + } + strcpy(s, f); + *path_get_filename(s) = 0; + snprintf(shader->shader_fn, sizeof(shader->shader_fn) - 1, "%s%s", s, t); + shader->shader_program = load_file(shader->shader_fn); + if (!shader->shader_program) { + fprintf(stderr, "GLSLP Error: Could not load shader %s\n", shader->shader_fn); + glslp_free(glslp); + return 0; + } + strip_parameters(shader->shader_program); + strip_defines(shader->shader_program); + + snprintf(s, sizeof(s) - 1, "alias%d", i); + wx_config_get_string(cfg, s, shader->alias, sizeof(shader->alias), 0); + + snprintf(s, sizeof(s) - 1, "filter_linear%d", i + 1); + wx_config_get_bool(cfg, s, &shader->filter_linear, 0); + + snprintf(s, sizeof(s) - 1, "wrap_mode%d", i); + wx_config_get_string(cfg, s, shader->wrap_mode, sizeof(shader->wrap_mode), 0); + + snprintf(s, sizeof(s) - 1, "float_framebuffer%d", i); + wx_config_get_bool(cfg, s, &shader->float_framebuffer, 0); + snprintf(s, sizeof(s) - 1, "srgb_framebuffer%d", i); + wx_config_get_bool(cfg, s, &shader->srgb_framebuffer, 0); + + snprintf(s, sizeof(s) - 1, "mipmap_input%d", i); + wx_config_get_bool(cfg, s, &shader->mipmap_input, 0); + + strcpy(shader->scale_type_x, "source"); + snprintf(s, sizeof(s) - 1, "scale_type_x%d", i); + wx_config_get_string(cfg, s, shader->scale_type_x, sizeof(shader->scale_type_x), 0); + strcpy(shader->scale_type_y, "source"); + snprintf(s, sizeof(s) - 1, "scale_type_y%d", i); + wx_config_get_string(cfg, s, shader->scale_type_y, sizeof(shader->scale_type_y), 0); + snprintf(s, sizeof(s) - 1, "scale_type%d", i); + if (wx_config_has_entry(cfg, s)) { + wx_config_get_string(cfg, s, shader->scale_type_x, sizeof(shader->scale_type_x), 0); + wx_config_get_string(cfg, s, shader->scale_type_y, sizeof(shader->scale_type_y), 0); + } + + snprintf(s, sizeof(s) - 1, "scale_x%d", i); + wx_config_get_float(cfg, s, &shader->scale_x, 1.0f); + snprintf(s, sizeof(s) - 1, "scale_y%d", i); + wx_config_get_float(cfg, s, &shader->scale_y, 1.0f); + snprintf(s, sizeof(s) - 1, "scale%d", i); + if (wx_config_has_entry(cfg, s)) { + wx_config_get_float(cfg, s, &shader->scale_x, 1.0f); + wx_config_get_float(cfg, s, &shader->scale_y, 1.0f); + } + + snprintf(s, sizeof(s) - 1, "frame_count_mod%d", i); + wx_config_get_int(cfg, s, &shader->frame_count_mod, 0); + } + + /* textures */ + glslp->num_textures = 0; + wx_config_get_string(cfg, "textures", t, sizeof(t), 0); + + len = strlen(t); + j = 0; + sublen = 0; + for (i = 0; i < len; ++i) { + if (t[i] == ';' || i == len - 1) { + sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1; + safe_strncpy(s, t + j, sublen); + s[511 < sublen ? 511 : sublen] = 0; + + struct texture *tex = &glslp->textures[glslp->num_textures++]; + + strcpy(tex->name, s); + wx_config_get_string(cfg, s, tex->path, sizeof(tex->path), 0); + + snprintf(z, sizeof(z) - 1, "%s_linear", s); + wx_config_get_bool(cfg, z, &tex->linear, 0); + + snprintf(z, sizeof(z) - 1, "%s_mipmap", s); + wx_config_get_bool(cfg, z, &tex->mipmap, 0); + + snprintf(z, sizeof(z) - 1, "%s_wrap_mode", s); + wx_config_get_string(cfg, z, tex->wrap_mode, sizeof(tex->wrap_mode), 0); + + j = i + 1; + } + } + + /* parameters */ + get_parameters(glslp); + + wx_config_get_string(cfg, "parameters", t, sizeof(t), 0); + + len = strlen(t); + j = 0; + sublen = 0; + for (i = 0; i < len; ++i) { + if (t[i] == ';' || i == len - 1) { + sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1; + safe_strncpy(s, t + j, sublen); + s[511 < sublen ? 511 : sublen] = 0; + + struct parameter *p = get_parameter(glslp, s); + + if (p) + wx_config_get_float(cfg, s, &p->default_value, 0); + + j = i + 1; + } + } + + wx_config_free(cfg); + + return glslp; +} + +void glslp_free(glslp_t *p) { + int i; + for (i = 0; i < p->num_shaders; ++i) + if (p->shaders[i].shader_program) + free(p->shaders[i].shader_program); + free(p); +} + +} \ No newline at end of file diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 719208c18..9d965be31 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -389,6 +389,7 @@ main_thread_fn() // title_update = 1; uint64_t old_time = elapsed_timer.elapsed(); int drawits = frames = 0; + is_cpu_thread = 1; while (!is_quit && cpu_thread_run) { /* See if it is time to run a frame of code. */ const uint64_t new_time = elapsed_timer.elapsed(); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 1cc6c33c9..4c1738e63 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -452,6 +452,9 @@ MainWindow::MainWindow(QWidget *parent) endblit(); } #endif + case 6: + newVidApi = RendererStack::Renderer::OpenGL3PCem; + break; } ui->stackedWidget->switchRenderer(newVidApi); if (!show_second_monitors) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp new file mode 100644 index 000000000..4ab66105c --- /dev/null +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -0,0 +1,1679 @@ +#include "qt_renderercommon.hpp" +#include "qt_mainwindow.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include "qt_openglrenderer_pcem.hpp" + +extern "C" { +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/video.h> +#include <86box/path.h> +#include <86box/ini.h> +#include <86box/config.h> +#include <86box/qt-glslp-parser.h> +} + +#define SCALE_SOURCE 0 +#define SCALE_VIEWPORT 1 +#define SCALE_ABSOLUTE 2 + +float gl3_shader_refresh_rate = 0; +float gl3_input_scale = 1.0f; +int gl3_input_stretch = FULLSCR_SCALE_FULL; +char gl3_shader_file[MAX_USER_SHADERS][512]; + +static int max_texture_size = 65536; + +static struct shader_texture scene_texture; + +static glsl_t *active_shader; + +static QOpenGLExtraFunctions glw; + +static GLfloat matrix[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; + +extern int video_filter_method; +extern int video_vsync; +extern int video_focus_dim; +extern int video_refresh_rate; + +static int glsl_version[2]; + +const char *vertex_shader_default_tex_src = "#version 130\n" + "\n" + "in vec4 VertexCoord;\n" + "in vec2 TexCoord;\n" + "\n" + "out vec2 texCoord;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = VertexCoord;\n" + " texCoord = TexCoord;\n" + "}\n"; + +const char *fragment_shader_default_tex_src = "#version 130\n" + "\n" + "in vec2 texCoord;\n" + "uniform sampler2D Texture;\n" + "\n" + "out vec4 color;" + "\n" + "void main()\n" + "{\n" + " color = texture(Texture, texCoord);\n" + "}\n"; + +const char *vertex_shader_default_color_src = "#version 130\n" + "\n" + "in vec4 VertexCoord;\n" + "in vec4 Color;\n" + "\n" + "out vec4 color;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = VertexCoord;\n" + " color = Color;\n" + "}\n"; + +const char *fragment_shader_default_color_src = "#version 130\n" + "\n" + "in vec4 color;\n" + "\n" + "out vec4 outColor;" + "\n" + "void main()\n" + "{\n" + " outColor = color;\n" + "}\n"; + +static int +next_pow2(unsigned int n) +{ + n--; + n |= n >> 1; // Divide by 2^k for consecutive doublings of k up to 32, + n |= n >> 2; // and then or the results. + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + + return n; +} + +static int +create_program(struct shader_program *program) +{ + GLint status; + program->id = glw.glCreateProgram(); + glw.glAttachShader(program->id, program->vertex_shader); + glw.glAttachShader(program->id, program->fragment_shader); + + glw.glLinkProgram(program->id); + + glw.glDeleteShader(program->vertex_shader); + glw.glDeleteShader(program->fragment_shader); + + program->vertex_shader = program->fragment_shader = 0; + + glw.glGetProgramiv(program->id, GL_LINK_STATUS, &status); + + if (!status) { + int maxLength; + int length; + glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); + char *log = (char *) malloc(maxLength); + glw.glGetProgramInfoLog(program->id, maxLength, &length, log); + // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); + free(log); + return 0; + } + + return 1; +} + +static int +compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) +{ + const char *source[3]; + char version[50]; + int ver = 0; + char *version_loc = strstr(program, "#version"); + if (version_loc) + ver = (int) strtol(version_loc + 8, (char **) &program, 10); + else { + ver = glsl_version[0] * 100 + glsl_version[1] * 10; + if (ver == 300) + ver = 130; + else if (ver == 310) + ver = 140; + else if (ver == 320) + ver = 150; + } + sprintf(version, "#version %d\n", ver); + source[0] = version; + source[1] = prepend ? prepend : ""; + source[2] = program; + + pclog("GLSL version %d\n", ver); + + GLuint shader = glw.glCreateShader(shader_type); + glw.glShaderSource(shader, 3, source, NULL); + glw.glCompileShader(shader); + + GLint status = 0; + glw.glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (!status) { + GLint length; + glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); + char *log = (char *) malloc(length); + glw.glGetShaderInfoLog(shader, length, &length, log); + // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); + + pclog("Could not compile shader: %s\n", log); + // pclog("Shader: %s\n", program); + + free(log); + return 0; + } + + *dst = shader; + + return 1; +} + +static GLuint +get_uniform(GLuint program, const char *name) +{ + return glw.glGetUniformLocation(program, name); +} + +static GLuint +get_attrib(GLuint program, const char *name) +{ + return glw.glGetAttribLocation(program, name); +} + +static void +find_uniforms(struct glsl_shader *glsl, int num_pass) +{ + int i; + char s[50]; + struct shader_pass *pass = &glsl->passes[num_pass]; + int p = pass->program.id; + glw.glUseProgram(p); + + struct shader_uniforms *u = &pass->uniforms; + + u->mvp_matrix = get_uniform(p, "MVPMatrix"); + u->vertex_coord = get_attrib(p, "VertexCoord"); + u->tex_coord = get_attrib(p, "TexCoord"); + u->color = get_attrib(p, "Color"); + + u->frame_count = get_uniform(p, "FrameCount"); + u->frame_direction = get_uniform(p, "FrameDirection"); + + u->texture = get_uniform(p, "Texture"); + u->input_size = get_uniform(p, "InputSize"); + u->texture_size = get_uniform(p, "TextureSize"); + u->output_size = get_uniform(p, "OutputSize"); + + u->orig.texture = get_uniform(p, "OrigTexture"); + u->orig.input_size = get_uniform(p, "OrigInputSize"); + u->orig.texture_size = get_uniform(p, "OrigTextureSize"); + + for (i = 0; i < glsl->num_passes; ++i) { + sprintf(s, "Pass%dTexture", (i + 1)); + u->pass[i].texture = get_uniform(p, s); + sprintf(s, "Pass%dInputSize", (i + 1)); + u->pass[i].input_size = get_uniform(p, s); + sprintf(s, "Pass%dTextureSize", (i + 1)); + u->pass[i].texture_size = get_uniform(p, s); + + sprintf(s, "PassPrev%dTexture", num_pass - i); + u->prev_pass[i].texture = get_uniform(p, s); + sprintf(s, "PassPrev%dInputSize", num_pass - i); + u->prev_pass[i].input_size = get_uniform(p, s); + sprintf(s, "PassPrev%dTextureSize", num_pass - i); + u->prev_pass[i].texture_size = get_uniform(p, s); + } + + u->prev[0].texture = get_uniform(p, "PrevTexture"); + u->prev[0].tex_coord = get_attrib(p, "PrevTexCoord"); + for (i = 1; i < MAX_PREV; ++i) { + sprintf(s, "Prev%dTexture", i); + u->prev[i].texture = get_uniform(p, s); + sprintf(s, "Prev%dTexCoord", i); + u->prev[i].tex_coord = get_attrib(p, s); + } + for (i = 0; i < MAX_PREV; ++i) + if (u->prev[i].texture >= 0) + glsl->has_prev = 1; + + for (i = 0; i < glsl->num_lut_textures; ++i) + u->lut_textures[i] = get_uniform(p, glsl->lut_textures[i].name); + + for (i = 0; i < glsl->num_parameters; ++i) + u->parameters[i] = get_uniform(p, glsl->parameters[i].id); + + glw.glUseProgram(0); +} + +static void +set_scale_mode(char *scale, int *dst) +{ + if (!strcmp(scale, "viewport")) + *dst = SCALE_VIEWPORT; + else if (!strcmp(scale, "absolute")) + *dst = SCALE_ABSOLUTE; + else + *dst = SCALE_SOURCE; +} + +static void +setup_scale(struct shader *shader, struct shader_pass *pass) +{ + set_scale_mode(shader->scale_type_x, &pass->scale.mode[0]); + set_scale_mode(shader->scale_type_y, &pass->scale.mode[1]); + pass->scale.value[0] = shader->scale_x; + pass->scale.value[1] = shader->scale_y; +} + +static void +create_texture(struct shader_texture *tex) +{ + if (tex->width > max_texture_size) + tex->width = max_texture_size; + if (tex->height > max_texture_size) + tex->height = max_texture_size; + pclog("Create texture with size %dx%d\n", tex->width, tex->height); + glw.glGenTextures(1, (GLuint *) &tex->id); + glw.glBindTexture(GL_TEXTURE_2D, tex->id); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex->wrap_mode); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex->wrap_mode); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex->min_filter); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex->mag_filter); + glw.glTexImage2D(GL_TEXTURE_2D, 0, tex->internal_format, tex->width, tex->height, 0, tex->format, tex->type, tex->data); + if (tex->mipmap) + glw.glGenerateMipmap(GL_TEXTURE_2D); + glw.glBindTexture(GL_TEXTURE_2D, 0); +} + +static void +delete_texture(struct shader_texture *tex) +{ + if (tex->id > 0) + glw.glDeleteTextures(1, (GLuint *) &tex->id); + tex->id = 0; +} + +static void +delete_fbo(struct shader_fbo *fbo) +{ + if (fbo->id >= 0) { + glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); + delete_texture(&fbo->texture); + } +} + +static void +delete_program(struct shader_program *program) +{ + if (program->vertex_shader) + glw.glDeleteShader(program->vertex_shader); + if (program->fragment_shader) + glw.glDeleteShader(program->fragment_shader); + glw.glDeleteProgram(program->id); +} + +static void +delete_vbo(struct shader_vbo *vbo) +{ + if (vbo->color >= 0) + glw.glDeleteBuffers(1, (GLuint *) &vbo->color); + glw.glDeleteBuffers(1, (GLuint *) &vbo->vertex_coord); + glw.glDeleteBuffers(1, (GLuint *) &vbo->tex_coord); +} + +static void +delete_pass(struct shader_pass *pass) +{ + delete_fbo(&pass->fbo); + delete_vbo(&pass->vbo); + delete_program(&pass->program); + glw.glDeleteVertexArrays(1, (GLuint *) &pass->vertex_array); +} + +static void +delete_prev(struct shader_prev *prev) +{ + delete_fbo(&prev->fbo); + delete_vbo(&prev->vbo); +} + +static void +delete_shader(struct glsl_shader *glsl) +{ + int i; + for (i = 0; i < glsl->num_passes; ++i) + delete_pass(&glsl->passes[i]); + if (glsl->has_prev) { + delete_pass(&glsl->prev_scene); + for (i = 0; i < MAX_PREV; ++i) + delete_prev(&glsl->prev[i]); + } + for (i = 0; i < glsl->num_lut_textures; ++i) + delete_texture(&glsl->lut_textures[i].texture); +} + +static void +delete_glsl(glsl_t *glsl) +{ + int i; + for (i = 0; i < glsl->num_shaders; ++i) + delete_shader(&glsl->shaders[i]); + delete_pass(&glsl->scene); + delete_pass(&glsl->fs_color); + delete_pass(&glsl->final_pass); +#ifdef SDL2_SHADER_DEBUG + delete_pass(&glsl->debug); +#endif +} + +static void +create_fbo(struct shader_fbo *fbo) +{ + create_texture(&fbo->texture); + + glw.glGenFramebuffers(1, (GLuint *) &fbo->id); + glw.glBindFramebuffer(GL_FRAMEBUFFER, fbo->id); + glw.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->texture.id, 0); + + if (glw.glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + pclog("Could not create framebuffer!\n"); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +static void +setup_fbo(struct shader *shader, struct shader_fbo *fbo) +{ + fbo->texture.internal_format = GL_RGBA8; + fbo->texture.format = GL_RGBA; + fbo->texture.min_filter = fbo->texture.mag_filter = shader->filter_linear ? GL_LINEAR : GL_NEAREST; + fbo->texture.width = 1024; + fbo->texture.height = 1024; + fbo->texture.type = GL_UNSIGNED_BYTE; + if (!strcmp(shader->wrap_mode, "repeat")) + fbo->texture.wrap_mode = GL_REPEAT; + else if (!strcmp(shader->wrap_mode, "mirrored_repeat")) + fbo->texture.wrap_mode = GL_MIRRORED_REPEAT; + else if (!strcmp(shader->wrap_mode, "clamp_to_edge")) + fbo->texture.wrap_mode = GL_CLAMP_TO_EDGE; + else + fbo->texture.wrap_mode = GL_CLAMP_TO_BORDER; + fbo->srgb = 0; + if (shader->srgb_framebuffer) { + fbo->texture.internal_format = GL_SRGB8_ALPHA8; + fbo->srgb = 1; + } else if (shader->float_framebuffer) { + fbo->texture.internal_format = GL_RGBA32F; + fbo->texture.type = GL_FLOAT; + } + + if (fbo->texture.mipmap) + fbo->texture.min_filter = shader->filter_linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST; + + create_fbo(fbo); +} + +static void +recreate_fbo(struct shader_fbo *fbo, int width, int height) +{ + if (width != fbo->texture.width || height != fbo->texture.height) { + glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); + glw.glDeleteTextures(1, (GLuint *) &fbo->texture.id); + fbo->texture.width = width; + fbo->texture.height = height; + create_fbo(fbo); + } +} + +static int +create_default_shader_tex(struct shader_pass *pass) +{ + if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_tex_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_tex_src, &pass->program.fragment_shader) || !create_program(&pass->program)) + return 0; + glw.glGenVertexArrays(1, (GLuint *) &pass->vertex_array); + + struct shader_uniforms *u = &pass->uniforms; + int p = pass->program.id; + memset(u, -1, sizeof(struct shader_uniforms)); + u->vertex_coord = get_attrib(p, "VertexCoord"); + u->tex_coord = get_attrib(p, "TexCoord"); + u->texture = get_uniform(p, "Texture"); + pass->scale.mode[0] = pass->scale.mode[1] = SCALE_SOURCE; + pass->scale.value[0] = pass->scale.value[1] = 1.0f; + pass->fbo.id = -1; + pass->active = 1; + return 1; +} + +static int +create_default_shader_color(struct shader_pass *pass) +{ + if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_color_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_color_src, &pass->program.fragment_shader) || !create_program(&pass->program)) + return 0; + glw.glGenVertexArrays(1, (GLuint *) &pass->vertex_array); + + struct shader_uniforms *u = &pass->uniforms; + int p = pass->program.id; + memset(u, -1, sizeof(struct shader_uniforms)); + u->vertex_coord = get_attrib(p, "VertexCoord"); + u->color = get_attrib(p, "Color"); + pass->scale.mode[0] = pass->scale.mode[1] = SCALE_SOURCE; + pass->scale.value[0] = pass->scale.value[1] = 1.0f; + pass->fbo.id = -1; + pass->active = 1; + return 1; +} + +/* create the default scene shader */ +static void +create_scene_shader() +{ + struct shader scene_shader_conf; + memset(&scene_shader_conf, 0, sizeof(struct shader)); + create_default_shader_tex(&active_shader->scene); + scene_shader_conf.filter_linear = video_filter_method; + if (active_shader->num_shaders > 0 && active_shader->shaders[0].input_filter_linear >= 0) + scene_shader_conf.filter_linear = active_shader->shaders[0].input_filter_linear; + setup_fbo(&scene_shader_conf, &active_shader->scene.fbo); + + memset(&scene_shader_conf, 0, sizeof(struct shader)); + create_default_shader_color(&active_shader->fs_color); + setup_fbo(&scene_shader_conf, &active_shader->fs_color.fbo); +} + +static int +load_texture(const char *f, struct shader_texture *tex) +{ + QImage img; + if (!img.load(f)) + return 0; + int width, height; + width = img.size().width(); + height = img.size().height(); + + if (width != next_pow2(width) || height != next_pow2(height)) + img = img.scaled(next_pow2(width), next_pow2(height)); + + width = img.size().width(); + height = img.size().height(); + + img.convertTo(QImage::Format_RGBA8888); + + const GLubyte *rgb = img.constBits(); + + int bpp = 4; + + GLubyte *data = (GLubyte *) malloc(width * height * bpp); + + int x, y, Y; + for (y = 0; y < height; ++y) { + Y = height - y - 1; + for (x = 0; x < width; x++) { + data[(y * width + x) * bpp + 0] = rgb[(Y * width + x) * 3 + 0]; + data[(y * width + x) * bpp + 1] = rgb[(Y * width + x) * 3 + 1]; + data[(y * width + x) * bpp + 2] = rgb[(Y * width + x) * 3 + 2]; + data[(y * width + x) * bpp + 3] = rgb[(Y * width + x) * 3 + 3]; + } + } + + tex->width = width; + tex->height = height; + tex->internal_format = GL_RGBA8; + tex->format = GL_RGBA; + tex->type = GL_UNSIGNED_BYTE; + tex->data = data; + return 1; +} + +static glsl_t * +load_glslp(glsl_t *glsl, int num_shader, const char *f) +{ + int i, j; + glslp_t *p = glslp_parse(f); + + if (p) { + char path[512]; + char file[1024]; + int failed = 0; + strcpy(path, f); + char *filename = path_get_filename(path); + + struct glsl_shader *gshader = &glsl->shaders[num_shader]; + + strcpy(gshader->name, p->name); + *filename = 0; + + gshader->num_lut_textures = p->num_textures; + + for (i = 0; i < p->num_textures; ++i) { + struct texture *texture = &p->textures[i]; + + sprintf(file, "%s%s", path, texture->path); + + struct shader_lut_texture *tex = &gshader->lut_textures[i]; + strcpy(tex->name, texture->name); + + pclog("Load texture %s...\n", file); + + if (!load_texture(file, &tex->texture)) { + // wx_simple_messagebox("GLSL Error", "Could not load texture: %s", file); + pclog("Could not load texture %s!\n", file); + failed = 1; + break; + } + + if (!strcmp(texture->wrap_mode, "repeat")) + tex->texture.wrap_mode = GL_REPEAT; + else if (!strcmp(texture->wrap_mode, "mirrored_repeat")) + tex->texture.wrap_mode = GL_MIRRORED_REPEAT; + else if (!strcmp(texture->wrap_mode, "clamp_to_edge")) + tex->texture.wrap_mode = GL_CLAMP_TO_EDGE; + else + tex->texture.wrap_mode = GL_CLAMP_TO_BORDER; + + tex->texture.mipmap = texture->mipmap; + + tex->texture.min_filter = tex->texture.mag_filter = texture->linear ? GL_LINEAR : GL_NEAREST; + if (tex->texture.mipmap) + tex->texture.min_filter = texture->linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST; + + create_texture(&tex->texture); + free(tex->texture.data); + tex->texture.data = 0; + } + + if (!failed) { + gshader->input_filter_linear = p->input_filter_linear; + + gshader->num_parameters = p->num_parameters; + for (j = 0; j < gshader->num_parameters; ++j) + memcpy(&gshader->parameters[j], &p->parameters[j], sizeof(struct shader_parameter)); + + gshader->num_passes = p->num_shaders; + + for (i = 0; i < p->num_shaders; ++i) { + struct shader *shader = &p->shaders[i]; + struct shader_pass *pass = &gshader->passes[i]; + + strcpy(pass->alias, shader->alias); + if (!strlen(pass->alias)) + sprintf(pass->alias, "Pass %u", (i + 1)); + + pclog("Creating pass %u (%s)\n", (i + 1), pass->alias); + pclog("Loading shader %s...\n", shader->shader_fn); + if (!shader->shader_program) { + // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); + pclog("Could not load shader %s\n", shader->shader_fn); + failed = 1; + break; + } else + pclog("Shader %s loaded\n", shader->shader_fn); + failed = !compile_shader(GL_VERTEX_SHADER, "#define VERTEX\n#define PARAMETER_UNIFORM\n", + shader->shader_program, &pass->program.vertex_shader) + || !compile_shader(GL_FRAGMENT_SHADER, "#define FRAGMENT\n#define PARAMETER_UNIFORM\n", + shader->shader_program, &pass->program.fragment_shader); + if (failed) + break; + + if (!create_program(&pass->program)) { + failed = 1; + break; + } + pass->frame_count_mod = shader->frame_count_mod; + pass->fbo.mipmap_input = shader->mipmap_input; + + glw.glGenVertexArrays(1, (GLuint *) &pass->vertex_array); + find_uniforms(gshader, i); + setup_scale(shader, pass); + if (i == p->num_shaders - 1) /* last pass may or may not be an fbo depending on scale */ + { + if (num_shader == glsl->num_shaders - 1) { + pass->fbo.id = -1; + + for (j = 0; j < 2; ++j) { + if (pass->scale.mode[j] != SCALE_SOURCE || pass->scale.value[j] != 1) { + setup_fbo(shader, &pass->fbo); + break; + } + } + } else { + /* check if next shaders' first pass wants the input mipmapped (will this ever + * happen?) */ + pass->fbo.texture.mipmap = glsl->shaders[num_shader + 1].num_passes > 0 && glsl->shaders[num_shader + 1].passes[0].fbo.mipmap_input; + /* check if next shader wants the output of this pass to be filtered */ + if (glsl->shaders[num_shader + 1].num_passes > 0 && glsl->shaders[num_shader + 1].input_filter_linear >= 0) + shader->filter_linear = glsl->shaders[num_shader + 1].input_filter_linear; + setup_fbo(shader, &pass->fbo); + } + } else { + /* check if next pass wants the input mipmapped, if so we need to generate mipmaps of this + * pass */ + pass->fbo.texture.mipmap = (i + 1) < p->num_shaders && p->shaders[i + 1].mipmap_input; + setup_fbo(shader, &pass->fbo); + } + if (pass->fbo.srgb) + glsl->srgb = 1; + pass->active = 1; + } + if (!failed) { + if (gshader->has_prev) { + struct shader scene_shader_conf; + memset(&scene_shader_conf, 0, sizeof(struct shader)); + for (i = 0; i < MAX_PREV; ++i) { + setup_fbo(&scene_shader_conf, &gshader->prev[i].fbo); + } + } + } + } + + glslp_free(p); + + return glsl; + } + return 0; +} + +static glsl_t * +load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) +{ + int i; + glsl_t *glsl; + + glsl = (glsl_t *) malloc(sizeof(glsl_t)); + memset(glsl, 0, sizeof(glsl_t)); + + glsl->num_shaders = num; + int failed = 0; + for (i = num - 1; i >= 0; --i) { + const char *f = shaders[i]; + if (f && strlen(f)) { + if (!load_glslp(glsl, i, f)) { + failed = 1; + break; + } + } + } + if (failed) { + delete_glsl(glsl); + memset(glsl, 0, sizeof(glsl_t)); + } + return glsl; +} + +static void +read_shader_config() +{ + char s[512]; + int i, j; + for (i = 0; i < active_shader->num_shaders; ++i) { + struct glsl_shader *shader = &active_shader->shaders[i]; + char *name = shader->name; + sprintf(s, "GL3 Shaders - %s", name); + // shader->shader_refresh_rate = config_get_float(CFG_MACHINE, s, "shader_refresh_rate", -1); + for (j = 0; j < shader->num_parameters; ++j) { + struct shader_parameter *param = &shader->parameters[j]; + param->value = config_get_double(s, param->id, param->default_value); + } + } +} + +OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) + : QWindow(parent->windowHandle()) + , renderTimer(new QTimer(this)) + , options(nullptr) +{ + connect(renderTimer, &QTimer::timeout, this, [this]() { this->render(); } ); + imagebufs[0] = std::unique_ptr(new uint8_t[2048 * 2048 * 4]); + imagebufs[1] = std::unique_ptr(new uint8_t[2048 * 2048 * 4]); + + buf_usage = std::vector(2); + buf_usage[0].clear(); + buf_usage[1].clear(); + + QSurfaceFormat format; + + setSurfaceType(QWindow::OpenGLSurface); + +#ifdef Q_OS_MACOS + format.setVersion(4, 1); +#else + format.setVersion(3, 2); +#endif + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + format.setOption(QSurfaceFormat::DebugContext); + + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) + format.setRenderableType(QSurfaceFormat::OpenGLES); + + setFormat(format); + + parentWidget = parent; + + source.setRect(0, 0, 2048, 2048); + isInitialized = false; + isFinalized = false; +} + +OpenGLRendererPCem::~OpenGLRendererPCem() { finalize(); } + +void +OpenGLRendererPCem::initialize() +{ + try { + context = new QOpenGLContext(this); + + context->setFormat(format()); + + if (!context->create()) + throw opengl_init_error_pcem(tr("Couldn't create OpenGL context.")); + + if (!context->makeCurrent(this)) + throw opengl_init_error_pcem(tr("Couldn't switch to OpenGL context.")); + + auto version = context->format().version(); + + if (version.first < 3) + throw opengl_init_error_pcem(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); + + glw.initializeOpenGLFunctions(); + + QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this); + + logger->initialize(); // initializes in the current context, i.e. ctx + connect(logger, QOpenGLDebugLogger::messageLogged, [this] (const QOpenGLDebugMessage &message) { + qDebug() << message; + //fprintf(stderr, "OpenGL DBG: %s\n", message.message().toUtf8()); + }); + logger->enableMessages(); + logger->startLogging(); + + glw.glEnable(GL_TEXTURE_2D); + + renderTimer->start(75); + + scene_texture.data = NULL; + scene_texture.width = 2048; + scene_texture.height = 2048; + scene_texture.internal_format = GL_RGBA8; + scene_texture.format = GL_BGRA; + scene_texture.type = GL_UNSIGNED_INT_8_8_8_8_REV; + scene_texture.wrap_mode = GL_CLAMP_TO_BORDER; + scene_texture.min_filter = scene_texture.mag_filter = video_filter_method ? GL_LINEAR : GL_NEAREST; + scene_texture.mipmap = 0; + + create_texture(&scene_texture); + + /* load shader */ + // const char* shaders[1]; + // shaders[0] = gl3_shader_file; + // + // active_shader = load_shaders(1, shaders); + + // const char* shaders[3]; + // shaders[0] = "/home/phantasy/git/glsl-shaders/ntsc/ntsc-320px.glslp"; + // shaders[1] = "/home/phantasy/git/glsl-shaders/motionblur/motionblur-simple.glslp"; + // shaders[2] = "/home/phantasy/git/glsl-shaders/crt/crt-lottes-multipass.glslp"; + // + // active_shader = load_shaders(3, shaders); + int num_shaders = 0; + for (int i = 0; i < MAX_USER_SHADERS; ++i) { + if (strlen(gl3_shader_file[i])) + ++num_shaders; + else + break; + } + active_shader = load_shaders(num_shaders, gl3_shader_file); + + create_scene_shader(); + + /* read config */ + read_shader_config(); + + /* buffers */ + + GLfloat vertex[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; + + GLfloat inv_vertex[] = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f }; + + GLfloat tex_coords[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; + + GLfloat colors[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; + + /* set the scene shader buffers */ + { + glw.glBindVertexArray(active_shader->scene.vertex_array); + + struct shader_vbo *vbo = &active_shader->scene.vbo; + + glw.glGenBuffers(1, (GLuint *) &vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(inv_vertex), inv_vertex, GL_STATIC_DRAW); + glw.glVertexAttribPointer(active_shader->scene.uniforms.vertex_coord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + + glw.glGenBuffers(1, (GLuint *) &vbo->tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->tex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_DYNAMIC_DRAW); + glw.glVertexAttribPointer(active_shader->scene.uniforms.tex_coord, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + } + + /* set buffers for all passes */ + for (int j = 0; j < active_shader->num_shaders; ++j) { + struct glsl_shader *shader = &active_shader->shaders[j]; + for (int i = 0; i < shader->num_passes; ++i) { + struct shader_uniforms *u = &shader->passes[i].uniforms; + + glw.glBindVertexArray(shader->passes[i].vertex_array); + + struct shader_vbo *vbo = &shader->passes[i].vbo; + + glw.glGenBuffers(1, (GLuint *) &vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW); + + glw.glVertexAttribPointer(u->vertex_coord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid *) 0); + + glw.glGenBuffers(1, (GLuint *) &vbo->tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->tex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_DYNAMIC_DRAW); + glw.glVertexAttribPointer(u->tex_coord, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), (GLvoid *) 0); + + if (u->color) { + glw.glGenBuffers(1, (GLuint *) &vbo->color); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->color); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW); + glw.glVertexAttribPointer(u->color, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid *) 0); + } + } + } + + for (int i = 0; i < active_shader->num_shaders; ++i) { + struct glsl_shader *shader = &active_shader->shaders[i]; + if (shader->has_prev) { + struct shader_pass *prev_pass = &shader->prev_scene; + create_default_shader_tex(prev_pass); + + struct shader_vbo *vbo = &prev_pass->vbo; + + glw.glBindVertexArray(prev_pass->vertex_array); + + glw.glGenBuffers(1, (GLuint *) &vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW); + glw.glVertexAttribPointer(prev_pass->uniforms.vertex_coord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + + glw.glGenBuffers(1, (GLuint *) &vbo->tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->tex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_DYNAMIC_DRAW); + glw.glVertexAttribPointer(prev_pass->uniforms.tex_coord, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + + for (int j = 0; j < MAX_PREV; ++j) { + struct shader_prev *prev = &shader->prev[j]; + struct shader_vbo *prev_vbo = &prev->vbo; + + glw.glGenBuffers(1, (GLuint *) &prev_vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, prev_vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW); + + glw.glGenBuffers(1, (GLuint *) &prev_vbo->tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, prev_vbo->tex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_DYNAMIC_DRAW); + } + } + } + + /* create final pass */ + if (active_shader->num_shaders == 0 || active_shader->shaders[active_shader->num_shaders - 1].passes[active_shader->shaders[active_shader->num_shaders - 1].num_passes - 1].fbo.id >= 0) { + struct shader_pass *final_pass = &active_shader->final_pass; + create_default_shader_tex(final_pass); + + glw.glBindVertexArray(final_pass->vertex_array); + + struct shader_vbo *vbo = &final_pass->vbo; + + glw.glGenBuffers(1, (GLuint *) &vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW); + glw.glVertexAttribPointer(final_pass->uniforms.vertex_coord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + + glw.glGenBuffers(1, (GLuint *) &vbo->tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->tex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_DYNAMIC_DRAW); + glw.glVertexAttribPointer(final_pass->uniforms.tex_coord, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + } + + { + struct shader_pass *color_pass = &active_shader->fs_color; + create_default_shader_color(color_pass); + + glw.glBindVertexArray(color_pass->vertex_array); + + struct shader_vbo *vbo = &color_pass->vbo; + + glw.glGenBuffers(1, (GLuint *) &vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW); + glw.glVertexAttribPointer(color_pass->uniforms.vertex_coord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), + (GLvoid *) 0); + + glw.glGenBuffers(1, (GLuint *) &vbo->color); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->color); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW); + glw.glVertexAttribPointer(color_pass->uniforms.color, 4, GL_FLOAT, GL_TRUE, 4 * sizeof(GLfloat), (GLvoid *) 0); + } +#ifdef SDL2_SHADER_DEBUG + struct shader_pass *debug_pass = &active_shader->debug; + create_default_shader(debug_pass); + + glw.glBindVertexArray(debug_pass->vertex_array); + + struct shader_vbo *vbo = &debug_pass->vbo; + + glw.glGenBuffers(1, &vbo->vertex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->vertex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW); + glw.glVertexAttribPointer(debug_pass->uniforms.vertex_coord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid *) 0); + + glw.glGenBuffers(1, &vbo->tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, vbo->tex_coord); + glw.glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_DYNAMIC_DRAW); + glw.glVertexAttribPointer(debug_pass->uniforms.tex_coord, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), (GLvoid *) 0); +#endif + + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + glw.glBindVertexArray(0); + + isInitialized = true; + isFinalized = false; + + emit initialized(); + + glw.glClearColor(0, 0, 0, 1); + + glw.glClear(GL_COLOR_BUFFER_BIT); + + context->swapBuffers(this); + } catch (const opengl_init_error_pcem &e) { + /* Mark all buffers as in use */ + for (auto &flag : buf_usage) + flag.test_and_set(); + + QMessageBox::critical((QWidget *) qApp->findChild(), tr("Error initializing OpenGL"), e.what() + tr("\nFalling back to software rendering.")); + + context->doneCurrent(); + isFinalized = true; + isInitialized = true; + + emit errorInitializing(); + } +} + +void +OpenGLRendererPCem::finalize() +{ + if (isFinalized) + return; + + context->makeCurrent(this); + + delete_texture(&scene_texture); + + if (active_shader) { + delete_glsl(active_shader); + free(active_shader); + } + active_shader = NULL; + + context->doneCurrent(); + + context = nullptr; + + isFinalized = true; +} + +void +OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) +{ + if (notReady()) + return; + + context->makeCurrent(this); + +#ifdef Q_OS_MACOS + glViewport( + destination.x() * devicePixelRatio(), + destination.y() * devicePixelRatio(), + destination.width() * devicePixelRatio(), + destination.height() * devicePixelRatio()); +#endif + source.setRect(x, y, w, h); + + glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); + glw.glPixelStorei(GL_UNPACK_ROW_LENGTH, 2048); + glw.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4))); + glw.glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glw.glBindTexture(GL_TEXTURE_2D, 0); + + buf_usage[buf_idx].clear(); + source.setRect(x, y, w, h); + onResize(this->width(), this->height()); + + render(); +} + +std::vector> +OpenGLRendererPCem::getBuffers() +{ + std::vector> buffers; + + buffers.push_back(std::make_tuple(imagebufs[0].get(), &buf_usage[0])); + buffers.push_back(std::make_tuple(imagebufs[1].get(), &buf_usage[1])); + + return buffers; +} + +void +OpenGLRendererPCem::exposeEvent(QExposeEvent *event) +{ + Q_UNUSED(event); + + if (!isInitialized) + initialize(); + + onResize(size().width(), size().height()); +} + +void +OpenGLRendererPCem::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + onResize(event->size().width(), event->size().height()); + + if (notReady()) + return; + + context->makeCurrent(this); + + glw.glViewport( + destination.x() * devicePixelRatio(), + destination.y() * devicePixelRatio(), + destination.width() * devicePixelRatio(), + destination.height() * devicePixelRatio()); +} + +struct render_data { + int pass; + struct glsl_shader *shader; + struct shader_pass *shader_pass; + GLfloat *output_size; + struct shader_pass *orig_pass; + GLint texture; + int frame_count; +}; + +static void +render_pass(struct render_data *data) +{ + int i; + GLuint texture_unit = 0; + + // pclog("pass %d: %gx%g, %gx%g -> %gx%g, %gx%g, %gx%g\n", num_pass, pass->state.input_size[0], + // pass->state.input_size[1], pass->state.input_texture_size[0], pass->state.input_texture_size[1], + // pass->state.output_size[0], pass->state.output_size[1], pass->state.output_texture_size[0], + // pass->state.output_texture_size[1], output_size[0], output_size[1]); + + glw.glBindVertexArray(data->shader_pass->vertex_array); + + GLint p = data->shader_pass->program.id; + struct shader_uniforms *u = &data->shader_pass->uniforms; + + glw.glUseProgram(p); + + if (data->texture) { + glw.glActiveTexture(GL_TEXTURE0 + texture_unit); + glw.glBindTexture(GL_TEXTURE_2D, data->texture); + glw.glUniform1i(u->texture, texture_unit); + texture_unit++; + } + + if (u->color >= 0) + glw.glEnableVertexAttribArray(u->color); + + if (u->mvp_matrix >= 0) + glw.glUniformMatrix4fv(u->mvp_matrix, 1, 0, matrix); + if (u->frame_direction >= 0) + glw.glUniform1i(u->frame_direction, 1); + + int framecnt = data->frame_count; + if (data->shader_pass->frame_count_mod > 0) + framecnt = framecnt % data->shader_pass->frame_count_mod; + if (u->frame_count >= 0) + glw.glUniform1i(u->frame_count, framecnt); + + if (u->input_size >= 0) + glw.glUniform2fv(u->input_size, 1, data->shader_pass->state.input_size); + if (u->texture_size >= 0) + glw.glUniform2fv(u->texture_size, 1, data->shader_pass->state.input_texture_size); + if (u->output_size >= 0) + glw.glUniform2fv(u->output_size, 1, data->output_size); + + if (data->shader) { + /* parameters */ + for (i = 0; i < data->shader->num_parameters; ++i) + if (u->parameters[i] >= 0) + glw.glUniform1f(u->parameters[i], data->shader->parameters[i].value); + + if (data->pass > 0) { + struct shader_pass *passes = data->shader->passes; + struct shader_pass *orig = data->orig_pass; + if (u->orig.texture >= 0) { + glw.glActiveTexture(GL_TEXTURE0 + texture_unit); + glw.glBindTexture(GL_TEXTURE_2D, orig->fbo.texture.id); + glw.glUniform1i(u->orig.texture, texture_unit); + texture_unit++; + } + if (u->orig.input_size >= 0) + glw.glUniform2fv(u->orig.input_size, 1, orig->state.input_size); + if (u->orig.texture_size >= 0) + glw.glUniform2fv(u->orig.texture_size, 1, orig->state.input_texture_size); + + for (i = 0; i < data->pass; ++i) { + if (u->pass[i].texture >= 0) { + glw.glActiveTexture(GL_TEXTURE0 + texture_unit); + glw.glBindTexture(GL_TEXTURE_2D, passes[i].fbo.texture.id); + glw.glUniform1i(u->pass[i].texture, texture_unit); + texture_unit++; + } + if (u->pass[i].texture_size >= 0) + glw.glUniform2fv(u->pass[i].texture_size, 1, passes[i].state.input_texture_size); + if (u->pass[i].input_size >= 0) + glw.glUniform2fv(u->pass[i].input_size, 1, passes[i].state.input_size); + + if (u->prev_pass[i].texture >= 0) { + glw.glActiveTexture(GL_TEXTURE0 + texture_unit); + glw.glBindTexture(GL_TEXTURE_2D, passes[i].fbo.texture.id); + glw.glUniform1i(u->prev_pass[i].texture, texture_unit); + texture_unit++; + } + if (u->prev_pass[i].texture_size >= 0) + glw.glUniform2fv(u->prev_pass[i].texture_size, 1, passes[i].state.input_texture_size); + if (u->prev_pass[i].input_size >= 0) + glw.glUniform2fv(u->prev_pass[i].input_size, 1, passes[i].state.input_size); + } + } + + if (data->shader->has_prev) { + /* loop through each previous frame */ + for (i = 0; i < MAX_PREV; ++i) { + if (u->prev[i].texture >= 0) { + glw.glActiveTexture(GL_TEXTURE0 + texture_unit); + glw.glBindTexture(GL_TEXTURE_2D, data->shader->prev[i].fbo.texture.id); + glw.glUniform1i(u->prev[i].texture, texture_unit); + texture_unit++; + } + if (u->prev[i].tex_coord >= 0) { + glw.glBindBuffer(GL_ARRAY_BUFFER, data->shader->prev[i].vbo.tex_coord); + glw.glVertexAttribPointer(u->prev[i].tex_coord, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), (GLvoid *) 0); + glw.glEnableVertexAttribArray(u->prev[i].tex_coord); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + } + } + } + + for (i = 0; i < data->shader->num_lut_textures; ++i) { + if (u->lut_textures[i] >= 0) { + glw.glActiveTexture(GL_TEXTURE0 + texture_unit); + glw.glBindTexture(GL_TEXTURE_2D, data->shader->lut_textures[i].texture.id); + glw.glUniform1i(u->lut_textures[i], texture_unit); + texture_unit++; + } + } + } + + glw.glEnableVertexAttribArray(u->vertex_coord); + glw.glEnableVertexAttribArray(u->tex_coord); + + glw.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glw.glActiveTexture(GL_TEXTURE0); + glw.glBindTexture(GL_TEXTURE_2D, 0); + + glw.glDisableVertexAttribArray(data->shader_pass->uniforms.vertex_coord); + glw.glDisableVertexAttribArray(data->shader_pass->uniforms.tex_coord); + if (data->shader_pass->uniforms.color >= 0) + glw.glDisableVertexAttribArray(data->shader_pass->uniforms.color); + + if (data->shader && data->shader->has_prev) { + for (i = 0; i < MAX_PREV; ++i) { + if (u->prev[i].tex_coord >= 0) + glw.glDisableVertexAttribArray(u->prev[i].tex_coord); + } + } + + glw.glBindVertexArray(0); + + glw.glUseProgram(0); +} + +bool +OpenGLRendererPCem::event(QEvent *event) +{ + Q_UNUSED(event); + + bool res = false; + if (!eventDelegate(event, res)) + return QWindow::event(event); + return res; +} + +void +OpenGLRendererPCem::render() +{ + if (!context) + return; + + int s, i, j; + + struct { + uint32_t x, y, w, h; + } window_rect; + + window_rect.w = this->size().width() * devicePixelRatio(); + window_rect.h = this->size().height() * devicePixelRatio(); + + GLfloat orig_output_size[] = { (GLfloat)window_rect.w, (GLfloat)window_rect.h }; + + if (active_shader->srgb) + glw.glEnable(GL_FRAMEBUFFER_SRGB); + + struct render_data data; + + /* render scene to texture */ + { + struct shader_pass *pass = &active_shader->scene; + + struct { + uint32_t x, y, w, h; + } rect, video_rect; + rect.x = destination.x(); + rect.y = destination.y(); + rect.w = destination.width(); + rect.h = destination.height(); + + video_rect.x = source.x(); + video_rect.y = source.y(); + video_rect.w = source.width(); + video_rect.h = source.height(); + + pass->state.input_size[0] = pass->state.output_size[0] = rect.w; + pass->state.input_size[1] = pass->state.output_size[1] = rect.h; + + pass->state.input_texture_size[0] = pass->state.output_texture_size[0] = next_pow2(pass->state.output_size[0]); + pass->state.input_texture_size[1] = pass->state.output_texture_size[1] = next_pow2(pass->state.output_size[1]); + + recreate_fbo(&active_shader->scene.fbo, pass->state.output_texture_size[0], pass->state.output_texture_size[1]); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, active_shader->scene.fbo.id); + glw.glClearColor(0, 0, 0, 1); + glw.glClear(GL_COLOR_BUFFER_BIT); + + glw.glViewport(0, 0, pass->state.output_size[0], pass->state.output_size[1]); + + GLfloat minx = 0; + GLfloat miny = 0; + GLfloat maxx = pass->state.output_size[0] / (GLfloat) pass->state.output_texture_size[0]; + GLfloat maxy = pass->state.output_size[1] / (GLfloat) pass->state.output_texture_size[1]; + + pass->state.tex_coords[0] = minx; + pass->state.tex_coords[1] = miny; + pass->state.tex_coords[2] = minx; + pass->state.tex_coords[3] = maxy; + pass->state.tex_coords[4] = maxx; + pass->state.tex_coords[5] = miny; + pass->state.tex_coords[6] = maxx; + pass->state.tex_coords[7] = maxy; + + // create input tex coords + minx = video_rect.x / 2048.f; + miny = video_rect.y / 2048.f; + maxx = (video_rect.x + video_rect.w) / (float) 2048.f; + maxy = (video_rect.y + video_rect.h) / (float) 2048.f; + + GLfloat tex_coords[] = { minx, miny, minx, maxy, maxx, miny, maxx, maxy }; + + glw.glBindVertexArray(pass->vertex_array); + + glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.tex_coord); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(GLfloat), tex_coords); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + memset(&data, 0, sizeof(struct render_data)); + data.pass = -1; + data.shader_pass = &active_shader->scene; + data.texture = scene_texture.id; + data.output_size = orig_output_size; + render_pass(&data); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + struct shader_pass *orig = &active_shader->scene; + struct shader_pass *input = &active_shader->scene; + + for (s = 0; s < active_shader->num_shaders; ++s) { + struct glsl_shader *shader = &active_shader->shaders[s]; + + // float refresh_rate = shader->shader_refresh_rate; + // if (refresh_rate < 0) + // refresh_rate = gl3_shader_refresh_rate; + float refresh_rate = gl3_shader_refresh_rate; + if (refresh_rate == 0) + refresh_rate = video_refresh_rate; + int frame_count = frameCounter; + + /* loop through each pass */ + for (i = 0; i < shader->num_passes; ++i) { + struct shader_pass *pass = &shader->passes[i]; + + memcpy(pass->state.input_size, input->state.output_size, 2 * sizeof(GLfloat)); + memcpy(pass->state.input_texture_size, input->state.output_texture_size, 2 * sizeof(GLfloat)); + + for (j = 0; j < 2; ++j) { + if (pass->scale.mode[j] == SCALE_VIEWPORT) + pass->state.output_size[j] = orig_output_size[j] * pass->scale.value[j]; + else if (pass->scale.mode[j] == SCALE_ABSOLUTE) + pass->state.output_size[j] = pass->scale.value[j]; + else + pass->state.output_size[j] = pass->state.input_size[j] * pass->scale.value[j]; + + pass->state.output_texture_size[j] = next_pow2(pass->state.output_size[j]); + } + + if (pass->fbo.id >= 0) { + recreate_fbo(&pass->fbo, pass->state.output_texture_size[0], pass->state.output_texture_size[1]); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, pass->fbo.id); + glw.glViewport(0, 0, pass->state.output_size[0], pass->state.output_size[1]); + } else + glw.glViewport(window_rect.x, window_rect.y, window_rect.w, window_rect.h); + + glw.glClearColor(0, 0, 0, 1); + glw.glClear(GL_COLOR_BUFFER_BIT); + + GLfloat minx = 0; + GLfloat miny = 0; + GLfloat maxx = pass->state.output_size[0] / (GLfloat) pass->state.output_texture_size[0]; + GLfloat maxy = pass->state.output_size[1] / (GLfloat) pass->state.output_texture_size[1]; + + pass->state.tex_coords[0] = minx; + pass->state.tex_coords[1] = miny; + pass->state.tex_coords[2] = minx; + pass->state.tex_coords[3] = maxy; + pass->state.tex_coords[4] = maxx; + pass->state.tex_coords[5] = miny; + pass->state.tex_coords[6] = maxx; + pass->state.tex_coords[7] = maxy; + + glw.glBindVertexArray(pass->vertex_array); + + glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.tex_coord); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(GLfloat), input->state.tex_coords); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + memset(&data, 0, sizeof(struct render_data)); + data.shader = shader; + data.pass = i; + data.shader_pass = pass; + data.texture = input->fbo.texture.id; + data.output_size = orig_output_size; + data.orig_pass = orig; + data.frame_count = frame_count; + + render_pass(&data); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (pass->fbo.texture.mipmap) { + glw.glActiveTexture(GL_TEXTURE0); + glw.glBindTexture(GL_TEXTURE_2D, pass->fbo.texture.id); + glw.glGenerateMipmap(GL_TEXTURE_2D); + glw.glBindTexture(GL_TEXTURE_2D, 0); + } + + input = pass; + } + + if (shader->has_prev) { + /* shift array */ + memmove(&shader->prev[1], &shader->prev[0], MAX_PREV * sizeof(struct shader_prev)); + memcpy(&shader->prev[0], &shader->prev[MAX_PREV], sizeof(struct shader_prev)); + + struct shader_pass *pass = orig; + struct shader_pass *prev_pass = &shader->prev_scene; + struct shader_prev *prev = &shader->prev[0]; + + memcpy(&prev_pass->state, &pass->state, sizeof(struct shader_state)); + + recreate_fbo(&prev->fbo, prev_pass->state.output_texture_size[0], + prev_pass->state.output_texture_size[1]); + + memcpy(&prev_pass->fbo, &prev->fbo, sizeof(struct shader_fbo)); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, prev->fbo.id); + glw.glClearColor(0, 0, 0, 1); + glw.glClear(GL_COLOR_BUFFER_BIT); + + glw.glViewport(0, 0, pass->state.output_size[0], pass->state.output_size[1]); + + glw.glBindVertexArray(prev_pass->vertex_array); + + glw.glBindBuffer(GL_ARRAY_BUFFER, prev->vbo.tex_coord); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(GLfloat), pass->state.tex_coords); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + glw.glBindBuffer(GL_ARRAY_BUFFER, prev_pass->vbo.tex_coord); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(GLfloat), pass->state.tex_coords); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + memset(&data, 0, sizeof(struct render_data)); + data.shader = shader; + data.pass = -10; + data.shader_pass = prev_pass; + data.texture = pass->fbo.texture.id; + data.output_size = orig_output_size; + + render_pass(&data); + + glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + orig = input; + } + + if (active_shader->final_pass.active) { + struct shader_pass *pass = &active_shader->final_pass; + + memcpy(pass->state.input_size, input->state.output_size, 2 * sizeof(GLfloat)); + memcpy(pass->state.input_texture_size, input->state.output_texture_size, 2 * sizeof(GLfloat)); + + for (j = 0; j < 2; ++j) { + if (pass->scale.mode[j] == SCALE_VIEWPORT) + pass->state.output_size[j] = orig_output_size[j] * pass->scale.value[j]; + else if (pass->scale.mode[j] == SCALE_ABSOLUTE) + pass->state.output_size[j] = pass->scale.value[j]; + else + pass->state.output_size[j] = pass->state.input_size[j] * pass->scale.value[j]; + + pass->state.output_texture_size[j] = next_pow2(pass->state.output_size[j]); + } + + glw.glViewport(window_rect.x, window_rect.y, window_rect.w, window_rect.h); + + glw.glClearColor(0, 0, 0, 1); + glw.glClear(GL_COLOR_BUFFER_BIT); + + GLfloat minx = 0; + GLfloat miny = 0; + GLfloat maxx = pass->state.output_size[0] / (GLfloat) pass->state.output_texture_size[0]; + GLfloat maxy = pass->state.output_size[1] / (GLfloat) pass->state.output_texture_size[1]; + + pass->state.tex_coords[0] = minx; + pass->state.tex_coords[1] = miny; + pass->state.tex_coords[2] = minx; + pass->state.tex_coords[3] = maxy; + pass->state.tex_coords[4] = maxx; + pass->state.tex_coords[5] = miny; + pass->state.tex_coords[6] = maxx; + pass->state.tex_coords[7] = maxy; + + glw.glBindVertexArray(pass->vertex_array); + + glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.tex_coord); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(GLfloat), input->state.tex_coords); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + memset(&data, 0, sizeof(struct render_data)); + data.pass = -2; + data.shader_pass = pass; + data.texture = input->fbo.texture.id; + data.output_size = orig_output_size; + data.orig_pass = orig; + + render_pass(&data); + } + + if (1) { + // if (video_focus_dim && !(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)) { +#if 0 + if (0) { + struct shader_pass *pass = &active_shader->fs_color; + GLfloat r = 0; + GLfloat g = 0; + GLfloat b = 0; + GLfloat a = 0x80 / (float) 0xff; + + GLfloat colors[] = { r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a }; + + glw.glBindVertexArray(pass->vertex_array); + + glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.color); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(GLfloat), colors); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + memset(&data, 0, sizeof(struct render_data)); + data.pass = -3; + data.shader_pass = pass; + data.texture = 0; + data.output_size = orig_output_size; + data.orig_pass = orig; + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + render_pass(&data); + glDisable(GL_BLEND); + } + + if (flash.enabled) { + struct shader_pass *pass = &active_shader->fs_color; + GLfloat r = (flash.color[0] & 0xff) / (float)0xff; + GLfloat g = (flash.color[1] & 0xff) / (float)0xff; + GLfloat b = (flash.color[2] & 0xff) / (float)0xff; + GLfloat a = (flash.color[3] & 0xff) / (float)0xff; + + GLfloat colors[] = {r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a}; + + glw.glBindVertexArray(pass->vertex_array); + + glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.color); + glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(GLfloat), colors); + glw.glBindBuffer(GL_ARRAY_BUFFER, 0); + + memset(&data, 0, sizeof(struct render_data)); + data.pass = -3; + data.shader_pass = pass; + data.texture = 0; + data.output_size = orig_output_size; + data.orig_pass = orig; + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + render_pass(&data); + glDisable(GL_BLEND); + } +#endif + } else { +#if 0 + take_screenshot = 0; + + int width = window_rect.w; + int height = window_rect.h; + + SDL_GetWindowSize(window, &width, &height); + + unsigned char *rgba = (unsigned char *)malloc(width * height * 4); + + glFinish(); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba); + + int x, y; + unsigned char *rgb = (unsigned char *)malloc(width * height * 3); + + for (x = 0; x < width; ++x) { + for (y = 0; y < height; ++y) { + rgb[(y * width + x) * 3 + 0] = rgba[((height - y - 1) * width + x) * 4 + 0]; + rgb[(y * width + x) * 3 + 1] = rgba[((height - y - 1) * width + x) * 4 + 1]; + rgb[(y * width + x) * 3 + 2] = rgba[((height - y - 1) * width + x) * 4 + 2]; + } + } + + screenshot_taken(rgb, width, height); + + free(rgb); + free(rgba); +#endif + } + + glw.glDisable(GL_FRAMEBUFFER_SRGB); + + context->swapBuffers(this); +} \ No newline at end of file diff --git a/src/qt/qt_openglrenderer_pcem.hpp b/src/qt/qt_openglrenderer_pcem.hpp new file mode 100644 index 000000000..0e3069536 --- /dev/null +++ b/src/qt/qt_openglrenderer_pcem.hpp @@ -0,0 +1,127 @@ +/* + * 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. + * + * Header file for OpenGL renderer + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#ifndef QT_OpenGLRendererPCem_HPP +#define QT_OpenGLRendererPCem_HPP + +#if defined Q_OS_MACOS || __arm__ +# define NO_BUFFER_STORAGE +#endif + +#include +#include +#include +#include +#include +#include +#if !defined NO_BUFFER_STORAGE && !(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +# include +#endif + +#include +#include +#include +#include + +#include "qt_opengloptions.hpp" +#include "qt_renderercommon.hpp" + +typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); + +class OpenGLRendererPCem : public QWindow, public RendererCommon { + Q_OBJECT + +public: + QOpenGLContext *context; + + OpenGLRendererPCem(QWidget *parent = nullptr); + ~OpenGLRendererPCem(); + + std::vector> getBuffers() override; + + void finalize() override final; + //bool hasOptions() const override { return true; } + //QDialog *getOptions(QWidget *parent) override; + //void reloadOptions() override; + +signals: + void initialized(); + void errorInitializing(); + +public slots: + void onBlit(int buf_idx, int x, int y, int w, int h); + +protected: + void exposeEvent(QExposeEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + bool event(QEvent *event) override; + +private: + static constexpr int INIT_WIDTH = 640; + static constexpr int INIT_HEIGHT = 400; + static constexpr int ROW_LENGTH = 2048; + static constexpr int BUFFERPIXELS = 4194304; + static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ + static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ + + std::array, 2> imagebufs; + + QTimer *renderTimer; + OpenGLOptions *options; + + QString glslVersion; + + bool isInitialized = false; + bool isFinalized = false; + + GLuint unpackBufferID = 0; + GLuint vertexArrayID = 0; + GLuint vertexBufferID = 0; + GLuint textureID = 0; + int frameCounter = 0; + + OpenGLOptions::FilterType currentFilter; + + void *unpackBuffer = nullptr; + + void initialize(); + void initializeExtensions(); + void initializeBuffers(); + void applyOptions(); + void applyShader(const OpenGLShaderPass &shader); + bool notReady() const { return !isInitialized || isFinalized; } + + /* GL_ARB_buffer_storage */ + bool hasBufferStorage = false; +#ifndef NO_BUFFER_STORAGE + PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr; +#endif + +private slots: + void render(); + //void updateOptions(OpenGLOptions *newOptions); +}; + +class opengl_init_error_pcem : public std::runtime_error { +public: + opengl_init_error_pcem(const QString &what) + : std::runtime_error(what.toStdString()) + { + } +}; + +#endif diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 8c31da2b2..63d35e719 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -23,6 +23,7 @@ #include "qt_hardwarerenderer.hpp" #include "qt_openglrenderer.hpp" +#include "qt_openglrenderer_pcem.hpp" #include "qt_softwarerenderer.hpp" #include "qt_vulkanwindowrenderer.hpp" @@ -337,19 +338,39 @@ RendererStack::createRenderer(Renderer renderer) current.reset(this->createWindowContainer(hw, this)); break; } - case Renderer::OpenGL3: + case Renderer::OpenGL3PCem: { this->createWinId(); - auto hw = new OpenGLRenderer(this); + auto hw = new OpenGLRendererPCem(this); rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection); - connect(hw, &OpenGLRenderer::initialized, [=]() { + connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection); + connect(hw, &OpenGLRendererPCem::initialized, [=]() { /* Buffers are available only after initialization. */ imagebufs = rendererWindow->getBuffers(); endblit(); emit rendererChanged(); }); - connect(hw, &OpenGLRenderer::errorInitializing, [=]() { + connect(hw, &OpenGLRendererPCem::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(); + auto hw = new OpenGLRendererPCem(this); + rendererWindow = hw; + connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection); + connect(hw, &OpenGLRendererPCem::initialized, [=]() { + /* Buffers are available only after initialization. */ + imagebufs = rendererWindow->getBuffers(); + endblit(); + emit rendererChanged(); + }); + connect(hw, &OpenGLRendererPCem::errorInitializing, [=]() { /* Renderer not could initialize, fallback to software. */ imagebufs = {}; QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); @@ -406,7 +427,7 @@ RendererStack::createRenderer(Renderer renderer) currentBuf = 0; - if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) { + if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::OpenGL3PCem) { imagebufs = rendererWindow->getBuffers(); endblit(); emit rendererChanged(); diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 5a08b351c..8059d59c5 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -59,6 +59,7 @@ public: OpenGLES, OpenGL3, Vulkan, + OpenGL3PCem = 6, None = -1 }; void switchRenderer(Renderer renderer); From 05f6940844f9fed4bc6d68cd6819ae7fb76cad8e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 8 Mar 2025 05:47:44 +0100 Subject: [PATCH 0394/1190] Fixed ROM BASIC loading on XT 1982, fixes #5243. --- src/machine/m_xt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 9f232ac95..78d2daa13 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -366,7 +366,11 @@ machine_xt_init(const machine_t *model) fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); - (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); + /* On the real machine, the BASIC is repeated. */ + (void) bios_load_aux_linear(fn, 0x000f0000, 8192, 0); + (void) bios_load_aux_linear(fn, 0x000f2000, 8192, 0); + (void) bios_load_aux_linear(fn, 0x000f4000, 8192, 0); + (void) bios_load_aux_linear(fn, 0x000f6000, 8192, 0); } device_context_restore(); From 16d7bc26dcddf666f67ba0f5d12d6c8ec237a3ab Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 8 Mar 2025 10:14:58 +0500 Subject: [PATCH 0395/1190] Fix the LPT device list duplicating on every machine change --- src/qt/qt_settingsports.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 630c843b9..cb1ab794a 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -74,22 +74,26 @@ SettingsPorts::onCurrentMachineChanged(int machineId) this->machineId = machineId; for (int i = 0; i < PARALLEL_MAX; i++) { - auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); - auto *model = cbox->model(); - int c = 0; - int selectedRow = 0; + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *model = cbox->model(); + const auto removeRows = model->rowCount(); + int c = 0; + int selectedRow = 0; while (true) { const char *lptName = lpt_device_get_name(c); if (lptName == nullptr) { break; } - Models::AddEntry(model, tr(lptName), c); + int row = Models::AddEntry(model, tr(lptName), c); if (c == lpt_ports[i].device) { - selectedRow = c; + selectedRow = row - removeRows; } c++; } + model->removeRows(0, removeRows); + cbox->setEnabled(model->rowCount() > 0); + cbox->setCurrentIndex(-1); cbox->setCurrentIndex(selectedRow); auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); From 63c5b6003f7c9fed9d12212cde9a58808bdcc1f0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:29:13 +0100 Subject: [PATCH 0396/1190] Spock/Tribble changes of the day (March 8th, 2025) 1. Make IRQ's more correct and per manual. 2. Only an adapter reset command should reset the SCSI devices connected to it. 3. Differentiate the two controllers by the connector bit (pos3 bit 12) in the CMD GET POS INFO SCB command. 4. Actually emulate bit 7 of pos4 in the pos writes so that selection between 16KB and 32KB rom loading is done properly. 5. Some cleanups. --- src/scsi/scsi_spock.c | 144 +++++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 65 deletions(-) diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 567879a12..c500abfbc 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -206,7 +206,6 @@ typedef struct { #define IRQ_TYPE_COMMAND_FAIL 0xc #define IRQ_TYPE_COMMAND_ERROR 0xe #define IRQ_TYPE_SW_SEQ_ERROR 0xf -#define IRQ_TYPE_RESET_COMPLETE 0x10 #ifdef ENABLE_SPOCK_LOG int spock_do_log = ENABLE_SPOCK_LOG; @@ -226,7 +225,9 @@ spock_log(const char *fmt, ...) # define spock_log(fmt, ...) #endif -static void +static void spock_reset(void *priv); + +static __inline void spock_rethink_irqs(spock_t *scsi) { int irq_pending = 0; @@ -236,7 +237,7 @@ spock_rethink_irqs(spock_t *scsi) if (scsi->irq_requests[c] != IRQ_TYPE_NONE) { /* Found IRQ */ scsi->irq_status = c | (scsi->irq_requests[c] << 4); - spock_log("Found IRQ: status = %02x\n", scsi->irq_status); + spock_log("Found IRQ: status=%02x.\n", scsi->irq_status); scsi->status |= STATUS_IRQ; irq_pending = 1; break; @@ -245,38 +246,37 @@ spock_rethink_irqs(spock_t *scsi) } else irq_pending = 1; + spock_log("spock_rethink_irqs: irqstat=%02x, ctrl=%02x, irqpend=%d.\n", scsi->irq_status, scsi->basic_ctrl, irq_pending); if (scsi->basic_ctrl & CTRL_IRQ_ENA) { if (irq_pending) { spock_log("IRQ issued\n"); - scsi->irq_inactive = 0; + scsi->status |= STATUS_IRQ; picint(1 << scsi->irq); } else { /* No IRQs pending, clear IRQ state */ spock_log("IRQ cleared\n"); - scsi->irq_status = 0; - scsi->irq_inactive = 1; - scsi->status &= ~STATUS_IRQ; picintc(1 << scsi->irq); } } else { - spock_log("IRQ disabled\n"); - picintc(1 << scsi->irq); + spock_log("IRQ disabled, pending=%d.\n", irq_pending); + if (irq_pending) + scsi->status |= STATUS_IRQ; } } -static __inline void +static void spock_set_irq(spock_t *scsi, int id, int type) { - spock_log("spock_set_irq id=%i type=%x %02x\n", id, type, scsi->irq_status); + spock_log("spock_set_irq: id=%i, type=%x, irqstat=%02x\n", id, type, scsi->irq_status); scsi->irq_requests[id] = type; if (!scsi->irq_status) /* Don't change IRQ status if one is currently being processed */ spock_rethink_irqs(scsi); } -static __inline void +static void spock_clear_irq(spock_t *scsi, int id) { - spock_log("spock_clear_irq id=%i\n", id); + spock_log("spock_clear_irq: id=%i.\n", id); scsi->irq_requests[id] = IRQ_TYPE_NONE; spock_rethink_irqs(scsi); } @@ -292,7 +292,7 @@ spock_write(uint16_t port, uint8_t val, void *priv) { spock_t *scsi = (spock_t *) priv; - spock_log("spock_writeb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); + spock_log("%04X:%08X: spock_writeb: port=%04x, val=%02x.\n", CS, cpu_state.pc, port & 7, val); switch (port & 7) { case 0: @@ -308,16 +308,14 @@ spock_write(uint16_t port, uint8_t val, void *priv) case 4: /*Attention Register*/ scsi->attention_pending = val; - scsi->attention_wait = 2; + scsi->attention_wait = 2; scsi->status |= STATUS_BUSY; break; case 5: /*Basic Control Register*/ - if ((scsi->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { + if (!(scsi->basic_ctrl & CTRL_RESET) && (val & CTRL_RESET)) { spock_log("Spock: SCSI reset and busy\n"); - scsi->in_reset = 1; - scsi->cmd_timer = SPOCK_TIME * 2; - scsi->status |= STATUS_BUSY; + spock_reset(scsi); } scsi->basic_ctrl = val; spock_rethink_irqs(scsi); @@ -333,7 +331,7 @@ spock_writew(uint16_t port, uint16_t val, void *priv) { spock_t *scsi = (spock_t *) priv; - spock_log("spock_writew: port=%04x, val=%04x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); + spock_log("%04X:%08X: spock_writew: port=%04x, val=%04x.\n", CS, cpu_state.pc, port & 7, val); switch (port & 7) { case 0: /*Command Interface Register*/ @@ -391,7 +389,7 @@ spock_read(uint16_t port, void *priv) break; } - spock_log("spock_readb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, temp, CS, cpu_state.pc); + spock_log("%04X:%08X: spock_readb: port=%04x, temp=%02x.\n", CS, cpu_state.pc, port & 7, temp); return temp; } @@ -442,9 +440,8 @@ spock_get_len(spock_t *scsi, scb_t *scb) DataToTransfer += scb->sge.sys_buf_byte_count; } return DataToTransfer; - } else { - return (scsi->data_len); } + return (scsi->data_len); } static void @@ -494,15 +491,14 @@ spock_process_imm_cmd(spock_t *scsi) spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; case CMD_INVALID_412: - spock_log("Invalid 412\n"); + spock_log("Invalid 412.\n"); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; case CMD_RESET: - spock_log("Reset Command, attention = %d.\n", scsi->attention & 0x0f); + spock_log("Reset command, attention=%02x.\n", scsi->attention & 0x0f); if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) scsi_device_reset(&scsi_devices[scsi->bus][i]); - } for (i = 6; i > -1; i--) { if (scsi_device_present(&scsi_devices[scsi->bus][i])) { @@ -514,10 +510,21 @@ spock_process_imm_cmd(spock_t *scsi) spock_log("Adapter Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); } } + } else if ((scsi->attention & 0x0f) < 7) { /*Device reset*/ + scsi_device_reset(&scsi_devices[scsi->bus][scsi->attention & 0x0f]); - scsi->scb_state = 0; + for (i = 6; i > -1; i--) { + if (scsi_device_present(&scsi_devices[scsi->bus][i])) { + spock_log("Device Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); + scsi->present[j] = i; + j++; + } else { + scsi->present[j] = 0xff; + spock_log("Device Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); + } + } } - + scsi->scb_state = 0; spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; @@ -535,18 +542,10 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) int old_scb_state; if (scsi->in_reset) { - spock_log("Reset type=%d\n", scsi->in_reset); - scsi->status &= ~STATUS_BUSY; - scsi->irq_status = 0; - for (c = 0; c < SCSI_ID_MAX; c++) - spock_clear_irq(scsi, c); - - if (scsi->in_reset == 1) - scsi->basic_ctrl |= CTRL_IRQ_ENA; - - spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); + scsi->irq_status = 0x0f; + spock_rethink_irqs(scsi); /*Reset device mappings*/ for (c = 0; c < 7; c++) { @@ -558,7 +557,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) scsi->in_reset = 0; - for (c = 6; c > -1; c--) { + for (c = 6; c >= 0; c--) { if (scsi_device_present(&scsi_devices[scsi->bus][c])) { spock_log("Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type); scsi->present[j] = c; @@ -678,7 +677,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) get_pos_info->pos = scsi->spock_16bit ? 0x8efe : 0x8eff; get_pos_info->pos1 = scsi->pos_regs[3] | (scsi->pos_regs[2] << 8); get_pos_info->pos2 = scsi->irq | (scsi->pos_regs[4] << 8); - get_pos_info->pos3 = 1 << 12; + get_pos_info->pos3 = scsi->spock_16bit ? (1 << 12) : (0 << 12); get_pos_info->pos4 = (7 << 8) | 8; get_pos_info->pos5 = (16 << 8) | scsi->pacing; get_pos_info->pos6 = (30 << 8) | 1; @@ -965,6 +964,8 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) else sd->buffer_length = spock_get_len(scsi, scb); + scsi_device_identify(sd, scsi->temp_cdb[1] >> 5); + scsi_device_command_phase0(sd, scsi->temp_cdb); spock_log("SCSI ID %i: Current CDB[0]=%02x, LUN=%i, buffer len=%i, max len=%i, phase val=%02x, data len=%d, enable bit 10=%03x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase, scsi->data_len, scb->enable & 0x400); @@ -1018,8 +1019,12 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) break; case SCSI_STATE_END_PHASE: + sd = &scsi_devices[scsi->bus][scsi->cdb_id]; scsi->scsi_state = SCSI_STATE_IDLE; + if (sd->type != SCSI_NONE) + scsi_device_identify(sd, SCSI_LUN_USE_CDB); + spock_log("State to idle, cmd timer %d\n", scsi->cmd_timer); if (!scsi->cmd_timer) scsi->cmd_timer = 1; @@ -1045,7 +1050,7 @@ spock_callback(void *priv) spock_execute_cmd(scsi, scb); } - if (scsi->attention_wait && ((scsi->scb_state == 0) || (scsi->attention_pending & 0xf0) == 0xe0)) { + if (scsi->attention_wait) { scsi->attention_wait--; if (!scsi->attention_wait) { scsi->attention = scsi->attention_pending; @@ -1094,6 +1099,7 @@ spock_callback(void *priv) case 0x0e: /*EOI*/ scsi->irq_status = 0; + scsi->status &= ~STATUS_IRQ; spock_clear_irq(scsi, scsi->attention & 0x0f); break; @@ -1118,23 +1124,30 @@ spock_mca_write(int port, uint8_t val, void *priv) if (port < 0x102) return; - io_removehandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + io_removehandler((((scsi->pos_regs[2] >> 1) & 7) << 3) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); mem_mapping_disable(&scsi->bios_rom.mapping); scsi->pos_regs[port & 7] = val; scsi->adapter_id = (scsi->pos_regs[3] & 0xe0) >> 5; - if (scsi->pos_regs[2] & 1) { - io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); - if (scsi->pos_regs[4] & 2) { - if (((scsi->pos_regs[2] >> 4) & 0x0f) != 0x0f) { - mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); - mem_mapping_enable(&scsi->bios_rom.mapping); + if (scsi->pos_regs[2] & 0x01) { + io_sethandler((((scsi->pos_regs[2] >> 1) & 7) << 3) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + if (scsi->pos_regs[4] & 0x02) { + if (scsi->pos_regs[4] & 0x80) { + if (((scsi->pos_regs[2] >> 4) & 0x0f) != 0x0f) { + mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); + mem_mapping_enable(&scsi->bios_rom.mapping); + } + } else { + if (((scsi->pos_regs[2] >> 4) & 0x0f) != 0x0f) { + mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x4000); + mem_mapping_enable(&scsi->bios_rom.mapping); + } } } } - spock_log("[%04X:%08X]: POS Write Port = %x, val = %02x, rom addr = %05x\n", CS, cpu_state.pc, port & 7, val, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000); + spock_log("%04X:%08X: POS Write Port=%x, val=%02x.\n", CS, cpu_state.pc, port & 7, val); } static uint8_t @@ -1142,7 +1155,7 @@ spock_mca_read(int port, void *priv) { const spock_t *scsi = (spock_t *) priv; - spock_log("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, + spock_log("%04X:%08X: POS Read Port=%x, temp=%02x.\n", CS, cpu_state.pc, port & 7, scsi->pos_regs[port & 7]); return scsi->pos_regs[port & 7]; } @@ -1155,12 +1168,13 @@ spock_mca_feedb(void *priv) return (scsi->pos_regs[2] & 0x01); } + static void -spock_mca_reset(void *priv) +spock_reset(void *priv) { spock_t *scsi = (spock_t *) priv; - scsi->in_reset = 2; + scsi->in_reset = 1; scsi->cmd_timer = SPOCK_TIME * 50; scsi->status = STATUS_BUSY; scsi->scsi_state = SCSI_STATE_IDLE; @@ -1169,13 +1183,15 @@ spock_mca_reset(void *priv) scsi->attention_wait = 0; scsi->basic_ctrl = 0; - /* Reset all devices on controller reset. */ - for (uint8_t i = 0; i < 8; i++) { - scsi_device_reset(&scsi_devices[scsi->bus][i]); - scsi->present[i] = 0xff; - } + spock_log("Actual Reset.\n"); +} - spock_log("Reset.\n"); +static void +spock_mca_reset(void *priv) +{ + spock_t *scsi = (spock_t *) priv; + + spock_reset(scsi); mem_mapping_disable(&scsi->bios_rom.mapping); scsi->pos_regs[4] = 0x02; spock_mca_write(0x102, 0, scsi); @@ -1213,10 +1229,6 @@ spock_init(const device_t *info) scsi->pos_regs[4] = 0x02; mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi); - scsi->in_reset = 2; - scsi->cmd_timer = SPOCK_TIME * 50; - scsi->status = STATUS_BUSY; - for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) scsi->dev_id[c].phys_id = -1; @@ -1230,6 +1242,8 @@ spock_init(const device_t *info) scsi_bus_set_speed(scsi->bus, 5000000.0); + spock_reset(scsi); + return scsi; } @@ -1278,7 +1292,7 @@ const device_t spock_device = { .local = 0, .init = spock_init, .close = spock_close, - .reset = NULL, + .reset = spock_reset, .available = spock_available, .speed_changed = NULL, .force_redraw = NULL, @@ -1292,7 +1306,7 @@ const device_t tribble_device = { .local = 1, .init = spock_init, .close = spock_close, - .reset = NULL, + .reset = spock_reset, .available = spock_available, .speed_changed = NULL, .force_redraw = NULL, From a2534c1f4f655c6675f1b324344aa7233900ec0b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:41:59 +0100 Subject: [PATCH 0397/1190] Trantor T128/MediaVision SCSI changes of the day (March 8th, 2025) 1. Made as best as possible implementation of the status bits 1-2 of the Trantor 128 so to make a more accurate speed for SCSI devices (CD-ROM and HDD) without stalls. 2. Slightly reorganized the timer of the T128. --- src/scsi/scsi_t128.c | 292 +++++++++++++++++++++---------------------- 1 file changed, 142 insertions(+), 150 deletions(-) diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 5ac3b5d67..6b73ae131 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -77,11 +77,8 @@ t128_write(uint32_t addr, uint8_t val, void *priv) if ((addr >= 0x1800) && (addr < 0x1880)) t128->ext_ram[addr & 0x7f] = val; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { - if ((val & 0x02) && !(t128->ctrl & 0x02)) - t128->status |= 0x02; - + t128_log("T128 ctrl write=%02x, mode=%02x.\n", val, ncr->mode & MODE_DMA); t128->ctrl = val; - t128_log("T128 ctrl write=%02x\n", val); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ncr5380_write((addr - 0x1d00) >> 5, val, ncr); else if ((addr >= 0x1e00) && (addr < 0x2000)) { @@ -90,13 +87,15 @@ t128_write(uint32_t addr, uint8_t val, void *priv) t128->buffer[t128->host_pos] = val; t128->host_pos++; - t128_log("T128 Write transfer, addr = %i, pos = %i, val = %02x\n", - addr & 0x1ff, t128->host_pos, val); + t128_log("T128 Write transfer: pos=%i, addr=%x.\n", + t128->host_pos, addr & 0x1ff); if (t128->host_pos == MIN(512, dev->buffer_length)) { + t128_log("T128 Transfer busy write, status=%02x, period=%lf, enabled=%d, loaded=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), t128->block_loaded); + t128->status &= ~0x04; - t128_log("Transfer busy write, status = %02x\n", t128->status); - timer_on_auto(&t128->timer, 0.02); + timer_on_auto(&t128->timer, 1.0); } } } @@ -119,31 +118,45 @@ t128_read(uint32_t addr, void *priv) ret = t128->ext_ram[addr & 0x7f]; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { ret = t128->ctrl; - t128_log("T128 ctrl read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + t128_log("T128 ctrl read=%02x, dma=%02x, load=%d, cnt=%d.\n", ret, ncr->mode & MODE_DMA, t128->block_loaded, t128->block_count); } else if ((addr >= 0x1c20) && (addr < 0x1c40)) { ret = t128->status; - t128_log("T128 status read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + t128_log("T128 status read=%02x, dma=%02x, blockload=%d, timer=%d.\n", ret, ncr->mode & MODE_DMA, t128->block_loaded, timer_is_enabled(&t128->timer)); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ret = ncr5380_read((addr - 0x1d00) >> 5, ncr); else if (addr >= 0x1e00 && addr < 0x2000) { - if ((t128->host_pos >= MIN(512, dev->buffer_length)) || - (scsi_bus->tx_mode != DMA_IN_TX_BUS)) - ret = 0xff; - else { + if ((scsi_bus->tx_mode == DMA_IN_TX_BUS) && + (t128->host_pos < MIN(512, dev->buffer_length))) { ret = t128->buffer[t128->host_pos++]; - t128_log("T128 Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, - t128->host_pos); + t128_log("T128 Read transfer: pos=%i, addr=%x.\n", + t128->host_pos, addr & 0x1ff); if (t128->host_pos == MIN(512, dev->buffer_length)) { - t128->status &= ~0x04; - t128_log("T128 Transfer busy read, status = %02x, period = %lf\n", - t128->status, scsi_bus->period); - if ((scsi_bus->period == 0.2) || (scsi_bus->period == 0.02)) - timer_on_auto(&t128->timer, 40.2); - } else if ((t128->host_pos < MIN(512, dev->buffer_length)) && - (scsi_device_get_callback(dev) > 100.0)) - cycles += 100; /*Needed to avoid timer de-syncing with transfers.*/ + t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer)); + + 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, 1.0); + else + t128->status &= ~0x04; + } + } else { + /*According to the WinNT DDK sources, just get the status timeout bit from here.*/ + if (!(t128->status & 0x02)) + t128->status |= 0x02; + + t128_log("Read not allowed.\n"); } } @@ -151,24 +164,20 @@ t128_read(uint32_t addr, void *priv) } static void -t128_dma_mode_ext(void *priv, void *ext_priv, UNUSED(uint8_t val)) +t128_dma_mode_ext(void *priv, void *ext_priv, uint8_t val) { t128_t *t128 = (t128_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; scsi_bus_t *scsi_bus = &ncr->scsibus; - /*Don't stop the timer until it finishes the transfer*/ - if (t128->block_loaded && (ncr->mode & MODE_DMA)) { - t128_log("Continuing DMA mode\n"); - timer_on_auto(&t128->timer, scsi_bus->period + 1.0); - } - /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!t128->block_loaded && !(ncr->mode & MODE_DMA)) { - t128_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - scsi_bus->tx_mode = PIO_TX_BUS; + if (!t128->block_loaded) { + if (!(val & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + scsi_bus->tx_mode = PIO_TX_BUS; + t128_log("End of DMA.\n"); + } } } @@ -180,9 +189,9 @@ t128_dma_send_ext(void *priv, void *ext_priv) scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; - if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + t128_log("T128 DMA OUT, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); - t128->status |= 0x04; t128->host_pos = 0; t128->block_count = dev->buffer_length >> 9; @@ -190,6 +199,7 @@ t128_dma_send_ext(void *priv, void *ext_priv) t128->block_count = 1; t128->block_loaded = 1; + t128->status |= 0x04; } return 1; } @@ -202,9 +212,9 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; - if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + t128_log("T128 DMA IN, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); - t128->status |= 0x04; t128->host_pos = MIN(512, dev->buffer_length); t128->block_count = dev->buffer_length >> 9; @@ -212,7 +222,8 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) t128->block_count = 1; t128->block_loaded = 1; - timer_on_auto(&t128->timer, 0.02); + t128->status &= ~0x04; + timer_on_auto(&t128->timer, 1.0); } return 1; } @@ -222,16 +233,16 @@ t128_timer_on_auto(void *ext_priv, double period) { t128_t *t128 = (t128_t *) ext_priv; - if (period == 0.0) + if (period <= 0.0) timer_stop(&t128->timer); - else + else if ((period > 0.0) && !timer_is_enabled(&t128->timer)) timer_on_auto(&t128->timer, period); } void t128_callback(void *priv) { - t128_t *t128 = (void *) priv; + t128_t *t128 = (t128_t *) priv; ncr_t *ncr = &t128->ncr; scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; @@ -240,128 +251,110 @@ t128_callback(void *priv) uint8_t temp; uint8_t status; - if ((scsi_bus->tx_mode != PIO_TX_BUS) && (ncr->mode & MODE_DMA) && t128->block_loaded) { - if ((t128->host_pos == MIN(512, dev->buffer_length)) && t128->block_count) - t128->status |= 0x04; - - timer_on_auto(&t128->timer, scsi_bus->period / 55.0); - } + if (scsi_bus->tx_mode != PIO_TX_BUS) + timer_on_auto(&t128->timer, scsi_bus->period / 65.0); if (scsi_bus->data_wait & 1) { scsi_bus->clear_req = 3; scsi_bus->data_wait &= ~1; - if (scsi_bus->tx_mode == PIO_TX_BUS) - return; + } + + if (scsi_bus->tx_mode == PIO_TX_BUS) { + t128_log("Timer CMD=%02x.\n", scsi_bus->command[0]); + return; } switch (scsi_bus->tx_mode) { case DMA_OUT_TX_BUS: - if (!(t128->status & 0x04)) { - t128_log("Write status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); - break; - } - - if (!t128->block_loaded) { - t128_log("Write block not loaded\n"); - break; - } - if (t128->host_pos < MIN(512, dev->buffer_length)) break; -write_again: - for (c = 0; c < 10; c++) { - status = scsi_bus_read(scsi_bus); - if (status & BUS_REQ) - break; - } - - /* Data ready. */ - temp = t128->buffer[t128->pos]; - - bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; - bus |= BUS_SETDATA(temp); - - scsi_bus_update(scsi_bus, bus | BUS_ACK); - scsi_bus_update(scsi_bus, bus & ~BUS_ACK); - - t128->pos++; - t128_log("T128 Buffer pos for writing = %d\n", t128->pos); - - if (t128->pos == MIN(512, dev->buffer_length)) { - t128->pos = 0; - t128->host_pos = 0; - t128->status &= ~0x02; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); - if (!t128->block_count) { - t128->block_loaded = 0; - t128_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&t128->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - t128_log("T128 write irq\n"); - ncr5380_irq(ncr, 1); - } - } + if (!t128->block_loaded) break; - } else - goto write_again; + + while (1) { + for (c = 0; c < 10; c++) { + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) + break; + } + + /* Data ready. */ + temp = t128->buffer[t128->pos]; + + bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); + + t128->pos++; + t128_log("T128 Buffer pos for writing = %d\n", t128->pos); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->status |= 0x04; + t128->status &= ~0x02; + t128->pos = 0; + t128->host_pos = 0; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("T128 write irq\n"); + ncr5380_irq(ncr, 1); + } + scsi_bus->tx_mode = PIO_TX_BUS; + timer_stop(&t128->timer); + t128_log("IO End of write transfer\n"); + } + break; + } + } break; case DMA_IN_TX_BUS: - if (!(t128->status & 0x04)) { - t128_log("Read status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); - break; - } - - if (!t128->block_loaded) { - t128_log("Read block not loaded\n"); - break; - } - if (t128->host_pos < MIN(512, dev->buffer_length)) break; -read_again: - for (c = 0; c < 10; c++) { - status = scsi_bus_read(scsi_bus); - if (status & BUS_REQ) - break; - } - - /* Data ready. */ - bus = scsi_bus_read(scsi_bus); - temp = BUS_GETDATA(bus); - - bus = ncr5380_get_bus_host(ncr); - - scsi_bus_update(scsi_bus, bus | BUS_ACK); - scsi_bus_update(scsi_bus, bus & ~BUS_ACK); - - t128->buffer[t128->pos++] = temp; - t128_log("T128 Buffer pos for reading=%d, temp=%02x, len=%d.\n", t128->pos, temp, dev->buffer_length); - - if (t128->pos == MIN(512, dev->buffer_length)) { - t128->pos = 0; - t128->host_pos = 0; - t128->status &= ~0x02; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); - if (!t128->block_count) { - t128->block_loaded = 0; - t128_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&t128->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - t128_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); - } - } + if (!t128->block_loaded) break; - } else - goto read_again; + + while (1) { + for (c = 0; c < 10; c++) { + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) + break; + } + /* Data ready. */ + bus = scsi_bus_read(scsi_bus); + temp = BUS_GETDATA(bus); + + bus = ncr5380_get_bus_host(ncr); + + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); + + t128->buffer[t128->pos++] = temp; + t128_log("T128 Buffer pos for reading = %d\n", t128->pos); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->status |= 0x04; + t128->status &= ~0x02; + t128->pos = 0; + t128->host_pos = 0; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be read=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + scsi_bus->bus_out |= BUS_REQ; + t128_log("IO End of read transfer\n"); + } + break; + } + } break; default: @@ -374,7 +367,7 @@ read_again: t128_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; scsi_bus->tx_mode = PIO_TX_BUS; - timer_on_auto(&t128->timer, 10.0); + t128->block_loaded = 0; } } @@ -513,7 +506,7 @@ t128_init(const device_t *info) scsi_bus->bus_device = ncr->bus; scsi_bus->timer = ncr->timer; scsi_bus->priv = ncr->priv; - t128->status = 0x00 /*0x04*/; + t128->status = 0x00; t128->host_pos = 512; if (!t128->bios_enabled && !(info->flags & DEVICE_MCA)) t128->status |= 0x80; @@ -528,7 +521,6 @@ t128_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 1.0; scsi_bus->multi = 1.0; - return t128; } From 5f833a0963a1e868b107157d75a09e7ccec77bd7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:45:41 +0100 Subject: [PATCH 0398/1190] Mach32 LFB changes of the day (March 8th, 2025) Do not subtract from the linear base when it's not in the range, should fix NT 3.x graphics bugs using the LFB. --- src/video/vid_ati_mach8.c | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 6e2798295..0c8fb6691 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -5223,11 +5223,11 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) { + 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); } else { @@ -5238,9 +5238,9 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) 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 - mach->linear_base, val, 1, mach, svga); + mach32_write_common(addr, val, 1, mach, svga); else - svga_write_linear(addr - mach->linear_base, val, svga); + svga_write_linear(addr, val, svga); } } @@ -5250,11 +5250,11 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; 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 - mach->linear_base) & 0x100) { + if (addr & 0x100) { mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outw(0x02ee + (port_dword << 8), val, mach); } else { @@ -5265,9 +5265,9 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) 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); if (dev->on) - mach32_writew_linear(addr - mach->linear_base, val, mach); + mach32_writew_linear(addr, val, mach); else - svga_writew_linear(addr - mach->linear_base, val, svga); + svga_writew_linear(addr, val, svga); } } @@ -5277,11 +5277,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; 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 - mach->linear_base) & 0x100) { + 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); @@ -5294,9 +5294,9 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) 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); if (dev->on) - mach32_writel_linear(addr - mach->linear_base, val, mach); + mach32_writel_linear(addr, val, mach); else - svga_writel_linear(addr - mach->linear_base, val, svga); + svga_writel_linear(addr, val, svga); } } @@ -5307,19 +5307,19 @@ mach32_ap_readb(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; 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 - mach->linear_base) & 0x100) + if (addr & 0x100) temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); else temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_read_common(addr - mach->linear_base, 1, mach, svga); + temp = mach32_read_common(addr, 1, mach, svga); else - temp = svga_read_linear(addr - mach->linear_base, svga); + temp = svga_read_linear(addr, svga); mach_log("Linear WORDB Read=%08x, ret=%02x, fast=%d.\n", addr, temp, svga->fast); } @@ -5338,15 +5338,15 @@ mach32_ap_readw(uint32_t addr, 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 - mach->linear_base) & 0x100) + if (addr & 0x100) temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); else temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_readw_linear(addr - mach->linear_base, mach); + temp = mach32_readw_linear(addr, mach); else - temp = svga_readw_linear(addr - mach->linear_base, svga); + temp = svga_readw_linear(addr, svga); mach_log("Linear WORDW Read=%08x, ret=%04x.\n", addr, temp); } @@ -5361,11 +5361,11 @@ mach32_ap_readl(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; 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 - mach->linear_base) & 0x100) { + if (addr & 0x100) { temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); } else { @@ -5374,9 +5374,9 @@ mach32_ap_readl(uint32_t addr, void *priv) } } else { if (dev->on) - temp = mach32_readl_linear(addr - mach->linear_base, mach); + temp = mach32_readl_linear(addr, mach); else - temp = svga_readl_linear(addr - mach->linear_base, svga); + temp = svga_readl_linear(addr, svga); mach_log("Linear WORDL Read=%08x, ret=%08x, ON%d.\n", addr, temp, dev->on); } From a4a521b3453ed28a3c19c38a2c57f53b5a836bbd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 8 Mar 2025 20:18:27 +0600 Subject: [PATCH 0399/1190] Instantiate the renderer properly --- src/qt/qt_openglrenderer_pcem.cpp | 169 ++++++++++++++---------------- src/qt/qt_openglrenderer_pcem.hpp | 71 +++++++++---- 2 files changed, 127 insertions(+), 113 deletions(-) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 4ab66105c..8b2a25663 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -29,25 +29,14 @@ extern "C" { #include <86box/ini.h> #include <86box/config.h> #include <86box/qt-glslp-parser.h> + +char gl3_shader_file[MAX_USER_SHADERS][512]; } #define SCALE_SOURCE 0 #define SCALE_VIEWPORT 1 #define SCALE_ABSOLUTE 2 -float gl3_shader_refresh_rate = 0; -float gl3_input_scale = 1.0f; -int gl3_input_stretch = FULLSCR_SCALE_FULL; -char gl3_shader_file[MAX_USER_SHADERS][512]; - -static int max_texture_size = 65536; - -static struct shader_texture scene_texture; - -static glsl_t *active_shader; - -static QOpenGLExtraFunctions glw; - static GLfloat matrix[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; extern int video_filter_method; @@ -55,8 +44,6 @@ extern int video_vsync; extern int video_focus_dim; extern int video_refresh_rate; -static int glsl_version[2]; - const char *vertex_shader_default_tex_src = "#version 130\n" "\n" "in vec4 VertexCoord;\n" @@ -106,7 +93,7 @@ const char *fragment_shader_default_color_src = "#version 130\n" " outColor = color;\n" "}\n"; -static int +static inline int next_pow2(unsigned int n) { n--; @@ -120,8 +107,8 @@ next_pow2(unsigned int n) return n; } -static int -create_program(struct shader_program *program) +int +OpenGLRendererPCem::create_program(struct shader_program *program) { GLint status; program->id = glw.glCreateProgram(); @@ -151,8 +138,8 @@ create_program(struct shader_program *program) return 1; } -static int -compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) +int +OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) { const char *source[3]; char version[50]; @@ -201,20 +188,20 @@ compile_shader(GLenum shader_type, const char *prepend, const char *program, int return 1; } -static GLuint -get_uniform(GLuint program, const char *name) +GLuint +OpenGLRendererPCem::get_uniform(GLuint program, const char *name) { return glw.glGetUniformLocation(program, name); } -static GLuint -get_attrib(GLuint program, const char *name) +GLuint +OpenGLRendererPCem::get_attrib(GLuint program, const char *name) { return glw.glGetAttribLocation(program, name); } -static void -find_uniforms(struct glsl_shader *glsl, int num_pass) +void +OpenGLRendererPCem::find_uniforms(struct glsl_shader *glsl, int num_pass) { int i; char s[50]; @@ -298,8 +285,8 @@ setup_scale(struct shader *shader, struct shader_pass *pass) pass->scale.value[1] = shader->scale_y; } -static void -create_texture(struct shader_texture *tex) +void +OpenGLRendererPCem::create_texture(struct shader_texture *tex) { if (tex->width > max_texture_size) tex->width = max_texture_size; @@ -318,16 +305,16 @@ create_texture(struct shader_texture *tex) glw.glBindTexture(GL_TEXTURE_2D, 0); } -static void -delete_texture(struct shader_texture *tex) +void +OpenGLRendererPCem::delete_texture(struct shader_texture *tex) { if (tex->id > 0) glw.glDeleteTextures(1, (GLuint *) &tex->id); tex->id = 0; } -static void -delete_fbo(struct shader_fbo *fbo) +void +OpenGLRendererPCem::delete_fbo(struct shader_fbo *fbo) { if (fbo->id >= 0) { glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); @@ -335,8 +322,8 @@ delete_fbo(struct shader_fbo *fbo) } } -static void -delete_program(struct shader_program *program) +void +OpenGLRendererPCem::delete_program(struct shader_program *program) { if (program->vertex_shader) glw.glDeleteShader(program->vertex_shader); @@ -345,8 +332,8 @@ delete_program(struct shader_program *program) glw.glDeleteProgram(program->id); } -static void -delete_vbo(struct shader_vbo *vbo) +void +OpenGLRendererPCem::delete_vbo(struct shader_vbo *vbo) { if (vbo->color >= 0) glw.glDeleteBuffers(1, (GLuint *) &vbo->color); @@ -354,8 +341,8 @@ delete_vbo(struct shader_vbo *vbo) glw.glDeleteBuffers(1, (GLuint *) &vbo->tex_coord); } -static void -delete_pass(struct shader_pass *pass) +void +OpenGLRendererPCem::delete_pass(struct shader_pass *pass) { delete_fbo(&pass->fbo); delete_vbo(&pass->vbo); @@ -363,15 +350,15 @@ delete_pass(struct shader_pass *pass) glw.glDeleteVertexArrays(1, (GLuint *) &pass->vertex_array); } -static void -delete_prev(struct shader_prev *prev) +void +OpenGLRendererPCem::delete_prev(struct shader_prev *prev) { delete_fbo(&prev->fbo); delete_vbo(&prev->vbo); } -static void -delete_shader(struct glsl_shader *glsl) +void +OpenGLRendererPCem::delete_shader(struct glsl_shader *glsl) { int i; for (i = 0; i < glsl->num_passes; ++i) @@ -385,8 +372,8 @@ delete_shader(struct glsl_shader *glsl) delete_texture(&glsl->lut_textures[i].texture); } -static void -delete_glsl(glsl_t *glsl) +void +OpenGLRendererPCem::delete_glsl(glsl_t *glsl) { int i; for (i = 0; i < glsl->num_shaders; ++i) @@ -399,8 +386,8 @@ delete_glsl(glsl_t *glsl) #endif } -static void -create_fbo(struct shader_fbo *fbo) +void +OpenGLRendererPCem::create_fbo(struct shader_fbo *fbo) { create_texture(&fbo->texture); @@ -414,14 +401,14 @@ create_fbo(struct shader_fbo *fbo) glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); } -static void -setup_fbo(struct shader *shader, struct shader_fbo *fbo) +void +OpenGLRendererPCem::setup_fbo(struct shader *shader, struct shader_fbo *fbo) { fbo->texture.internal_format = GL_RGBA8; fbo->texture.format = GL_RGBA; fbo->texture.min_filter = fbo->texture.mag_filter = shader->filter_linear ? GL_LINEAR : GL_NEAREST; - fbo->texture.width = 1024; - fbo->texture.height = 1024; + fbo->texture.width = 2048; + fbo->texture.height = 2048; fbo->texture.type = GL_UNSIGNED_BYTE; if (!strcmp(shader->wrap_mode, "repeat")) fbo->texture.wrap_mode = GL_REPEAT; @@ -446,8 +433,8 @@ setup_fbo(struct shader *shader, struct shader_fbo *fbo) create_fbo(fbo); } -static void -recreate_fbo(struct shader_fbo *fbo, int width, int height) +void +OpenGLRendererPCem::recreate_fbo(struct shader_fbo *fbo, int width, int height) { if (width != fbo->texture.width || height != fbo->texture.height) { glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); @@ -458,8 +445,8 @@ recreate_fbo(struct shader_fbo *fbo, int width, int height) } } -static int -create_default_shader_tex(struct shader_pass *pass) +int +OpenGLRendererPCem::create_default_shader_tex(struct shader_pass *pass) { if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_tex_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_tex_src, &pass->program.fragment_shader) || !create_program(&pass->program)) return 0; @@ -478,8 +465,8 @@ create_default_shader_tex(struct shader_pass *pass) return 1; } -static int -create_default_shader_color(struct shader_pass *pass) +int +OpenGLRendererPCem::create_default_shader_color(struct shader_pass *pass) { if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_color_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_color_src, &pass->program.fragment_shader) || !create_program(&pass->program)) return 0; @@ -498,8 +485,8 @@ create_default_shader_color(struct shader_pass *pass) } /* create the default scene shader */ -static void -create_scene_shader() +void +OpenGLRendererPCem::create_scene_shader() { struct shader scene_shader_conf; memset(&scene_shader_conf, 0, sizeof(struct shader)); @@ -558,8 +545,8 @@ load_texture(const char *f, struct shader_texture *tex) return 1; } -static glsl_t * -load_glslp(glsl_t *glsl, int num_shader, const char *f) +glsl_t * +OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) { int i, j; glslp_t *p = glslp_parse(f); @@ -706,8 +693,8 @@ load_glslp(glsl_t *glsl, int num_shader, const char *f) return 0; } -static glsl_t * -load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) +glsl_t * +OpenGLRendererPCem::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) { int i; glsl_t *glsl; @@ -733,8 +720,8 @@ load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) return glsl; } -static void -read_shader_config() +void +OpenGLRendererPCem::read_shader_config() { char s[512]; int i, j; @@ -810,19 +797,22 @@ OpenGLRendererPCem::initialize() glw.initializeOpenGLFunctions(); - QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this); + pclog("OpenGL information: [%s] %s (%s)\n", glw.glGetString(GL_VENDOR), glw.glGetString(GL_RENDERER), glw.glGetString(GL_VERSION)); + glsl_version[0] = glsl_version[1] = -1; + glw.glGetIntegerv(GL_MAJOR_VERSION, &glsl_version[0]); + glw.glGetIntegerv(GL_MINOR_VERSION, &glsl_version[1]); + if (glsl_version[0] < 3) { + throw opengl_init_error_pcem(tr("OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2").arg(glsl_version[0]).arg(glsl_version[1])); + } + pclog("Using OpenGL %s\n", glw.glGetString(GL_VERSION)); + pclog("Using Shading Language %s\n", glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); - logger->initialize(); // initializes in the current context, i.e. ctx - connect(logger, QOpenGLDebugLogger::messageLogged, [this] (const QOpenGLDebugMessage &message) { - qDebug() << message; - //fprintf(stderr, "OpenGL DBG: %s\n", message.message().toUtf8()); - }); - logger->enableMessages(); - logger->startLogging(); + glw.glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + pclog("Max texture size: %dx%d\n", max_texture_size, max_texture_size); glw.glEnable(GL_TEXTURE_2D); - renderTimer->start(75); + //renderTimer->start(75); scene_texture.data = NULL; scene_texture.width = 2048; @@ -1140,18 +1130,8 @@ OpenGLRendererPCem::resizeEvent(QResizeEvent *event) destination.height() * devicePixelRatio()); } -struct render_data { - int pass; - struct glsl_shader *shader; - struct shader_pass *shader_pass; - GLfloat *output_size; - struct shader_pass *orig_pass; - GLint texture; - int frame_count; -}; - -static void -render_pass(struct render_data *data) +void +OpenGLRendererPCem::render_pass(struct render_data *data) { int i; GLuint texture_unit = 0; @@ -1318,8 +1298,16 @@ OpenGLRendererPCem::render() uint32_t x, y, w, h; } window_rect; - window_rect.w = this->size().width() * devicePixelRatio(); - window_rect.h = this->size().height() * devicePixelRatio(); + window_rect.x = destination.x() * devicePixelRatio(); + window_rect.y = destination.y() * devicePixelRatio(); + window_rect.w = destination.width() * devicePixelRatio(); + window_rect.h = destination.height() * devicePixelRatio(); + + glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); + scene_texture.min_filter = scene_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, 0); GLfloat orig_output_size[] = { (GLfloat)window_rect.w, (GLfloat)window_rect.h }; @@ -1403,12 +1391,6 @@ OpenGLRendererPCem::render() for (s = 0; s < active_shader->num_shaders; ++s) { struct glsl_shader *shader = &active_shader->shaders[s]; - // float refresh_rate = shader->shader_refresh_rate; - // if (refresh_rate < 0) - // refresh_rate = gl3_shader_refresh_rate; - float refresh_rate = gl3_shader_refresh_rate; - if (refresh_rate == 0) - refresh_rate = video_refresh_rate; int frame_count = frameCounter; /* loop through each pass */ @@ -1675,5 +1657,6 @@ OpenGLRendererPCem::render() glw.glDisable(GL_FRAMEBUFFER_SRGB); + frameCounter++; context->swapBuffers(this); } \ No newline at end of file diff --git a/src/qt/qt_openglrenderer_pcem.hpp b/src/qt/qt_openglrenderer_pcem.hpp index 0e3069536..88844bb02 100644 --- a/src/qt/qt_openglrenderer_pcem.hpp +++ b/src/qt/qt_openglrenderer_pcem.hpp @@ -40,7 +40,20 @@ #include "qt_opengloptions.hpp" #include "qt_renderercommon.hpp" -typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +extern "C" +{ +#include <86box/qt-glslp-parser.h> +} + +struct render_data { + int pass; + struct glsl_shader *shader; + struct shader_pass *shader_pass; + GLfloat *output_size; + struct shader_pass *orig_pass; + GLint texture; + int frame_count; +}; class OpenGLRendererPCem : public QWindow, public RendererCommon { Q_OBJECT @@ -71,45 +84,63 @@ protected: bool event(QEvent *event) override; private: - static constexpr int INIT_WIDTH = 640; - static constexpr int INIT_HEIGHT = 400; - static constexpr int ROW_LENGTH = 2048; - static constexpr int BUFFERPIXELS = 4194304; - static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ - static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ std::array, 2> imagebufs; QTimer *renderTimer; OpenGLOptions *options; - QString glslVersion; + QString glslVersion = ""; bool isInitialized = false; bool isFinalized = false; - GLuint unpackBufferID = 0; - GLuint vertexArrayID = 0; - GLuint vertexBufferID = 0; - GLuint textureID = 0; - int frameCounter = 0; + int max_texture_size = 65536; + int frameCounter = 0; OpenGLOptions::FilterType currentFilter; + QOpenGLExtraFunctions glw; + struct shader_texture scene_texture; + glsl_t *active_shader; void *unpackBuffer = nullptr; + int glsl_version[2] = { 0, 0 }; + void initialize(); void initializeExtensions(); void initializeBuffers(); void applyOptions(); - void applyShader(const OpenGLShaderPass &shader); - bool notReady() const { return !isInitialized || isFinalized; } + + void create_scene_shader(); + void create_texture(struct shader_texture *tex); + void create_fbo(struct shader_fbo *fbo); + void recreate_fbo(struct shader_fbo *fbo, int width, int height); + void setup_fbo(struct shader *shader, struct shader_fbo *fbo); - /* GL_ARB_buffer_storage */ - bool hasBufferStorage = false; -#ifndef NO_BUFFER_STORAGE - PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr; -#endif + bool notReady() const { return !isInitialized || isFinalized; } + glsl_t* load_glslp(glsl_t *glsl, int num_shader, const char *f); + glsl_t* load_shaders(int num, char shaders[MAX_USER_SHADERS][512]); + int compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst); + int create_default_shader_tex(struct shader_pass *pass); + int create_default_shader_color(struct shader_pass *pass); + int create_program(struct shader_program *program); + + GLuint get_uniform(GLuint program, const char *name); + GLuint get_attrib(GLuint program, const char *name); + + void find_uniforms(struct glsl_shader *glsl, int num_pass); + void delete_texture(struct shader_texture *tex); + void delete_fbo(struct shader_fbo *fbo); + void delete_program(struct shader_program *program); + void delete_vbo(struct shader_vbo *vbo); + void delete_pass(struct shader_pass *pass); + void delete_prev(struct shader_prev *prev); + void delete_shader(struct glsl_shader *glsl); + void delete_glsl(glsl_t *glsl); + void read_shader_config(); + + void render_pass(struct render_data *data); private slots: void render(); From 2e46cc479c446b43ddf76ddf2d6f801c5b5ca964 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 8 Mar 2025 23:19:37 +0600 Subject: [PATCH 0400/1190] Fix Preferences dialog crash --- src/qt/qt_mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 1cc6c33c9..9864584d3 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1267,6 +1267,7 @@ void MainWindow::refreshMediaMenu() { mm->refresh(ui->menuMedia); + status->setSoundGainAction(ui->actionSound_gain); status->refresh(ui->statusbar); ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled); From 5db4de199bfc97a55b6f7c7fc9a9a05b0968f8cc Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 19:26:33 +0100 Subject: [PATCH 0401/1190] PAS16 SCSI change of the day (March 8th, 2025) Signal DRQ once the transfers are complete for real. --- src/sound/snd_pas16.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 353f9a3d5..675582367 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -789,6 +789,10 @@ pas16_in(uint16_t port, void *priv) scsi_bus = &pas16->scsi->ncr.scsibus; /* Bits 0-6 must absolutely be set for SCSI hard disk drivers to work. */ ret = (((scsi_bus->tx_mode != PIO_TX_BUS) && (pas16->scsi->status & 0x04)) << 7) | 0x7f; + if ((scsi_bus->tx_mode == PIO_TX_BUS) && !(ret & 0x80)) + ret |= 0x80; + + pas16_log("5C01 read ret=%02x, status=%02x, txmode=%x.\n", ret, pas16->scsi->status & 0x06, scsi_bus->tx_mode); } break; case 0x5c03: @@ -1190,6 +1194,7 @@ pas16_scsi_callback(void *priv) t128_callback(pas16->scsi); + pas16_log("TimeOutStatus=%02x, t128stat=%02x.\n", pas16->timeout_status, dev->status); if ((scsi_bus->tx_mode != PIO_TX_BUS) && (dev->status & 0x04)) { timer_stop(&pas16->scsi_timer); pas16->timeout_status &= 0x7f; From a39bef1ab881bac586532a498b5ca7cb748202d5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 19:39:55 +0100 Subject: [PATCH 0402/1190] ESS/SB changes of the day (March 8th, 2025) 1. Correct ChipChat mixer port length as well as making mixer reg 0x3a read back its value. 2. Swap the sb port addresses back so that they match the Piper adf. This fixes SoundPiper 16/32 detection. 3. Log cleanups and additions for better debugging. --- src/sound/snd_sb.c | 100 ++++++++++++++++++++--------------------- src/sound/snd_sb_dsp.c | 15 +++++-- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 689d0b91e..5f660509a 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1335,7 +1335,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) break; case 0x82: - ; /* Empty statement to make compilers happy about the following variable declaration. */ + /* Empty statement to make compilers happy about the following variable declaration. */ /* The Interrupt status register, addressed as register 82h on the Mixer register map, is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, in which case it should chain to the previous routine. */ @@ -1727,6 +1727,7 @@ ess_mixer_read(uint16_t addr, void *priv) case 0x32: case 0x36: case 0x38: + case 0x3a: case 0x3e: ret = mixer->regs[mixer->index]; break; @@ -2593,10 +2594,10 @@ ess_soundpiper_mca_write(const int port, const uint8_t val, void *priv) ess->dsp.sb_addr = 0x0000; break; case 0x08: - ess->dsp.sb_addr = 0x0240; + ess->dsp.sb_addr = 0x0220; break; case 0x0c: - ess->dsp.sb_addr = 0x0220; + ess->dsp.sb_addr = 0x0240; break; } @@ -2750,64 +2751,59 @@ ess_chipchat_mca_write(int port, uint8_t val, void *priv) ess->pos_regs[port & 7] = val; - if (ess->pos_regs[2] & 1) { - ess->dsp.sb_addr = (ess->pos_regs[2] == 0x51) ? 0x0220 : 0x0000; + if (ess->pos_regs[2] & 0x01) { + ess->dsp.sb_addr = 0x0220; - if (ess->dsp.sb_addr != 0x0000) { - io_sethandler(ess->dsp.sb_addr, 0x0004, - ess->opl.read, NULL, NULL, - ess->opl.write, NULL, NULL, - ess->opl.priv); - io_sethandler(ess->dsp.sb_addr + 8, 0x0002, - ess->opl.read, NULL, NULL, - ess->opl.write, NULL, NULL, - ess->opl.priv); - io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + io_sethandler(ess->dsp.sb_addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + io_sethandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(0x0388, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + + io_sethandler(ess->dsp.sb_addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) { + mpu401_change_addr(ess->mpu, 0x0330); + + io_sethandler(0x0330, 0x0002, ess_fm_midi_read, NULL, NULL, ess_fm_midi_write, NULL, NULL, ess); - io_sethandler(0x0388, 0x0004, - ess->opl.read, NULL, NULL, - ess->opl.write, NULL, NULL, ess->opl.priv); - io_sethandler(0x0388, 0x0004, - ess_fm_midi_read, NULL, NULL, - ess_fm_midi_write, NULL, NULL, - ess); - io_sethandler(ess->dsp.sb_addr + 4, 0x0004, - ess_mixer_read, NULL, NULL, - ess_mixer_write, NULL, NULL, - ess); - - io_sethandler(ess->dsp.sb_addr + 2, 0x0004, - ess_base_read, NULL, NULL, - ess_base_write, NULL, NULL, - ess); - io_sethandler(ess->dsp.sb_addr + 6, 0x0001, - ess_base_read, NULL, NULL, - ess_base_write, NULL, NULL, - ess); - io_sethandler(ess->dsp.sb_addr + 0x0a, 0x0006, - ess_base_read, NULL, NULL, - ess_base_write, NULL, NULL, - ess); - - if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) { - mpu401_change_addr(ess->mpu, (ess->pos_regs[2] == 0x51) ? 0x0330 : 0); - - if (ess->pos_regs[2] == 0x51) - io_sethandler(0x0330, 0x0002, - ess_fm_midi_read, NULL, NULL, - ess_fm_midi_write, NULL, NULL, - ess); - } } /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&ess->dsp, ess->dsp.sb_addr); - gameport_remap(ess->gameport, (ess->pos_regs[2] == 0x51) ? 0x200 : 0); - } + gameport_remap(ess->gameport, 0x0200); - if (ess->pos_regs[2] == 0x51) { sb_dsp_setirq(&ess->dsp, 7); mpu401_setirq(ess->mpu, 7); diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 9ce0b9fb7..10e5601f4 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -388,6 +388,7 @@ sb_update_status(sb_dsp_t *dsp, int bit, int set) { int masked = 0; + sb_dsp_log("SBIRQ8=%d, irqnum=%d, bit=%x, set=%x.\n", dsp->sb_irq8, dsp->sb_irqnum, bit, set); if (dsp->sb_irq8 || dsp->sb_irq16) return; @@ -423,6 +424,7 @@ sb_update_status(sb_dsp_t *dsp, int bit, int set) } } + sb_dsp_log("Masked=%02x.\n", masked); if (set && !masked) dsp->irq_update(dsp->irq_priv, 1); else if (!set) @@ -1039,6 +1041,8 @@ sb_ess_write_reg(sb_dsp_t *dsp, const uint8_t reg, uint8_t data) { uint8_t chg; + sb_dsp_log("ESS Write reg=%02x, val=%02x.\n", reg, data); + switch (reg) { case 0xA1: /* Extended Mode Sample Rate Generator */ { @@ -1110,6 +1114,7 @@ sb_ess_write_reg(sb_dsp_t *dsp, const uint8_t reg, uint8_t data) dsp->sb_irqnum = 10; break; } + sb_dsp_log("Legacy Audio IRQ control=%d.\n", dsp->sb_irqnum); sb_ess_update_irq_drq_readback_regs(dsp, false); break; case 0xB2: /* DRQ Control */ @@ -1131,6 +1136,7 @@ sb_ess_write_reg(sb_dsp_t *dsp, const uint8_t reg, uint8_t data) dsp->sb_8_dmanum = 3; break; } + sb_dsp_log("Legacy Audio DRQ control=%d, chg=%02x.\n", dsp->sb_8_dmanum, chg); sb_ess_update_irq_drq_readback_regs(dsp, false); if (chg & 0x40) sb_ess_update_dma_status(dsp); @@ -1876,12 +1882,12 @@ sb_write(uint16_t addr, uint8_t val, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; - sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); - /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE))) addr &= 0xfffe; + sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + switch (addr & 0xF) { case 6: /* Reset */ sb_do_reset(dsp, val); @@ -1962,7 +1968,7 @@ sb_read(uint16_t addr, void *priv) uint8_t ret = 0x00; /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xF))) + if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE))) /* Exception: ESS AudioDrive does not alias port base+0xf */ addr &= 0xfffe; @@ -2085,7 +2091,7 @@ sb_read(uint16_t addr, void *priv) break; } - sb_dsp_log("[%04X:%08X] DSP: [R] %04X = %02X\n", CS, cpu_state.pc, a, ret); + sb_dsp_log("[%04X:%08X] DSP: [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -2319,6 +2325,7 @@ pollsb(void *priv) if (dsp->sb_8_enable && dsp->sb_pausetime < 0 && dsp->sb_8_output) { sb_dsp_update(dsp); + sb_dsp_log("8-bit format=%02x, pause=%x, length=%d.\n", dsp->sb_8_format, dsp->sb_8_pause, dsp->sb_8_length); switch (dsp->sb_8_format) { case 0x00: /* Mono unsigned */ if (!dsp->sb_8_pause) { From e0603b28769a3c25f26f61e41e3f63d528b84159 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 8 Mar 2025 14:35:59 -0500 Subject: [PATCH 0403/1190] Fix compile error --- src/sound/snd_sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 5f660509a..e89946486 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1335,7 +1335,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) break; case 0x82: - /* Empty statement to make compilers happy about the following variable declaration. */ + ; /* Empty statement to make compilers happy about the following variable declaration. */ /* The Interrupt status register, addressed as register 82h on the Mixer register map, is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, in which case it should chain to the previous routine. */ From 757246998838dd1ccd84e1f3a30b53f060098b52 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 9 Mar 2025 01:39:07 +0600 Subject: [PATCH 0404/1190] Current OpenGL port status --- src/config.c | 58 +++++++++ src/include/86box/ini.h | 7 +- src/include/86box/qt-glslp-parser.h | 5 +- src/qt/CMakeLists.txt | 4 + src/qt/qt_glsl_parser.cpp | 31 ++++- src/qt/qt_mainwindow.cpp | 11 +- src/qt/qt_openglrenderer_pcem.cpp | 9 +- src/qt/qt_openglrenderer_pcem.hpp | 6 +- src/qt/qt_openglshadermanagerdialog.cpp | 159 ++++++++++++++++++++++++ src/qt/qt_openglshadermanagerdialog.hpp | 40 ++++++ src/qt/qt_openglshadermanagerdialog.ui | 148 ++++++++++++++++++++++ src/qt/qt_renderercommon.hpp | 2 + src/qt/qt_rendererstack.hpp | 2 + 13 files changed, 473 insertions(+), 9 deletions(-) create mode 100644 src/qt/qt_openglshadermanagerdialog.cpp create mode 100644 src/qt/qt_openglshadermanagerdialog.hpp create mode 100644 src/qt/qt_openglshadermanagerdialog.ui diff --git a/src/config.c b/src/config.c index 07e770822..3ff802952 100644 --- a/src/config.c +++ b/src/config.c @@ -77,6 +77,10 @@ #include <86box/snd_opl.h> #include <86box/version.h> +/* Deliberate to not make the 86box.h header kitchen-sink. */ +#include <86box/qt-glsl.h> +extern char gl3_shader_file[MAX_USER_SHADERS][512]; + static int cx; static int cy; static int cw; @@ -1714,6 +1718,30 @@ load_other_peripherals(void) ini_section_delete_var(cat, temp); } +/* Load OpenGL 3.0 renderer options. */ +static void +load_gl3_shaders(void) +{ + ini_section_t cat = ini_find_section(config, "GL3 Shaders"); + char *p; + char temp[512]; + int i = 0; + memset(temp, 0, sizeof(temp)); + memset(gl3_shader_file, 0, sizeof(gl3_shader_file)); + + for (int i = 0; i < MAX_USER_SHADERS; i++) { + temp[0] = 0; + snprintf(temp, 512, "shader%d", i); + p = ini_section_get_string(cat, temp, ""); + if (p[0]) { + strncpy(gl3_shader_file[i], p, 512); + } else { + gl3_shader_file[i][0] = 0; + break; + } + } +} + /* Load the specified or a default configuration file. */ void config_load(void) @@ -1810,6 +1838,7 @@ config_load(void) load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ load_other_removable_devices(); /* Other removable devices */ load_other_peripherals(); /* Other peripherals */ + load_gl3_shaders(); /* GL3 Shaders */ /* Migrate renamed device configurations. */ c = ini_find_section(config, "MDA"); @@ -2632,6 +2661,34 @@ save_other_peripherals(void) ini_delete_section_if_empty(config, cat); } +/* Save "GL3 Shaders" section. */ +static void +save_gl3_shaders(void) +{ + ini_section_t cat = ini_find_or_create_section(config, "GL3 Shaders"); + char temp[512]; + int shaders = 0, i = 0; + + for (i = 0; i < MAX_USER_SHADERS; i++) { + if (gl3_shader_file[i][0] == 0) + break; + shaders++; + } + + ini_section_set_int(cat, "shaders", shaders); + if (shaders == 0) { + ini_section_delete_var(cat, "shaders"); + } else { + for (i = 0; i < shaders; i++) { + temp[0] = 0; + snprintf(temp, 512, "shader%d"); + ini_section_set_string(cat, temp, gl3_shader_file[i]); + } + } + + ini_delete_section_if_empty(config, cat); +} + /* Save "Hard Disks" section. */ static void save_hard_disks(void) @@ -2987,6 +3044,7 @@ config_save(void) save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ save_other_removable_devices(); /* Other removable devices */ save_other_peripherals(); /* Other peripherals */ + save_gl3_shaders(); /* GL3 Shaders */ ini_write(config, cfg_path); } diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h index 2a73a18b0..2ce89f788 100644 --- a/src/include/86box/ini.h +++ b/src/include/86box/ini.h @@ -91,13 +91,16 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); extern void ini_rename_section(ini_section_t section, const char *name); extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); -static inline void *wx_config_load(const char *path) { return (void*) ini_read(path); }; +static inline void *wx_config_load(const char *path) { return (void*) ini_read(path); } static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); if (size == 0) return res; - strncpy(dst, str, size); + if (str != NULL) + strncpy(dst, str, size - 1); + else + dst[0] = 0; return res; } static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) { diff --git a/src/include/86box/qt-glslp-parser.h b/src/include/86box/qt-glslp-parser.h index cf2ac464a..853e50e66 100644 --- a/src/include/86box/qt-glslp-parser.h +++ b/src/include/86box/qt-glslp-parser.h @@ -53,4 +53,7 @@ void get_glslp_name(const char *f, char *s, int size); glslp_t *glslp_parse(const char *f); void glslp_free(glslp_t *p); -#endif /* SRC_WX_GLSLP_PARSER_H_ */ \ No newline at end of file +void glslp_read_shader_config(glslp_t *shader); +void glslp_write_shader_config(glslp_t *shader); + +#endif /* SRC_WX_GLSLP_PARSER_H_ */ diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index fd82b9053..8a06cbe5a 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -193,6 +193,10 @@ add_library(ui STATIC ../qt_resources.qrc ./qdarkstyle/dark/darkstyle.qrc + + qt_openglshadermanagerdialog.hpp + qt_openglshadermanagerdialog.cpp + qt_openglshadermanagerdialog.ui ) if(RTMIDI) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index 7cf032a52..b1a96a312 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -7,8 +7,12 @@ extern "C" { #include <86box/86box.h> #include <86box/ini.h> +#include <86box/config.h> #include <86box/qt-glslp-parser.h> #include <86box/path.h> + +extern void startblit(); +extern void endblit(); } #define safe_strncpy(a, b, n) \ @@ -305,4 +309,29 @@ void glslp_free(glslp_t *p) { free(p); } -} \ No newline at end of file +void glslp_read_shader_config(glslp_t *shader) { + char s[512]; + int i; + char *name = shader->name; + sprintf(s, "GL3 Shaders - %s", name); + for (i = 0; i < shader->num_parameters; ++i) { + struct parameter *param = &shader->parameters[i]; + param->value = config_get_double(s, param->id, param->default_value); + } +} + +void glslp_write_shader_config(glslp_t *shader) { + char s[512]; + int i; + char *name = shader->name; + + startblit(); + sprintf(s, "GL3 Shaders - %s", name); + for (i = 0; i < shader->num_parameters; ++i) { + struct parameter *param = &shader->parameters[i]; + config_set_double(s, param->id, param->value); + } + endblit(); +} + +} diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 4c1738e63..60e0494fc 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1987,7 +1987,16 @@ MainWindow::on_actionRenderer_options_triggered() { if (const auto dlg = ui->stackedWidget->getOptions(this)) { if (dlg->exec() == QDialog::Accepted) { - for (int i = 1; i < MONITORS_NUM; i++) { + if (ui->stackedWidget->reloadRendererOption()) { + 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)); + } + } + } + } else for (int i = 1; i < MONITORS_NUM; i++) { if (renderers[i] && renderers[i]->hasOptions()) renderers[i]->reloadOptions(); } diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 8b2a25663..17f4299d7 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -20,6 +20,7 @@ #include #include "qt_openglrenderer_pcem.hpp" +#include "qt_openglshadermanagerdialog.hpp" extern "C" { #include <86box/86box.h> @@ -1286,6 +1287,12 @@ OpenGLRendererPCem::event(QEvent *event) return res; } +QDialog* +OpenGLRendererPCem::getOptions(QWidget *parent) +{ + return new OpenGLShaderManagerDialog(parent); +} + void OpenGLRendererPCem::render() { @@ -1659,4 +1666,4 @@ OpenGLRendererPCem::render() frameCounter++; context->swapBuffers(this); -} \ No newline at end of file +} diff --git a/src/qt/qt_openglrenderer_pcem.hpp b/src/qt/qt_openglrenderer_pcem.hpp index 88844bb02..706a744fa 100644 --- a/src/qt/qt_openglrenderer_pcem.hpp +++ b/src/qt/qt_openglrenderer_pcem.hpp @@ -67,9 +67,9 @@ public: std::vector> getBuffers() override; void finalize() override final; - //bool hasOptions() const override { return true; } - //QDialog *getOptions(QWidget *parent) override; - //void reloadOptions() override; + bool hasOptions() const override { return true; } + QDialog *getOptions(QWidget *parent) override; + bool reloadRendererOption() { return true; } signals: void initialized(); diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp new file mode 100644 index 000000000..26f206a0e --- /dev/null +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -0,0 +1,159 @@ +#include "qt_openglshadermanagerdialog.hpp" +#include "ui_qt_openglshadermanagerdialog.h" + +#include +#include +#include + +extern "C" { +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/video.h> +#include <86box/path.h> +#include <86box/ini.h> +#include <86box/config.h> +#include <86box/qt-glslp-parser.h> + +extern char gl3_shader_file[MAX_USER_SHADERS][512]; +} + +OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent) + : QDialog(parent) + , ui(new Ui::OpenGLShaderManagerDialog) +{ + ui->setupUi(this); + + for (int i = 0; i < MAX_USER_SHADERS; i++) { + if (gl3_shader_file[i][0] != 0) { + char* filename = path_get_filename(gl3_shader_file[i]); + if (filename[0] != 0) { + glslp_t* shaderfile = glslp_parse(gl3_shader_file[i]); + if (shaderfile) { + QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget); + item->setText(filename); + item->setData(Qt::UserRole + 1, QString(gl3_shader_file[i])); + item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile); + } + } + } + } + if (ui->shaderListWidget->count()) { + ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1); + } else { + ui->buttonRemove->setDisabled(true); + ui->buttonMoveUp->setDisabled(true); + ui->buttonMoveDown->setDisabled(true); + } +} + +OpenGLShaderManagerDialog::~OpenGLShaderManagerDialog() +{ + for (int i = 0; i < ui->shaderListWidget->count(); i++) { + if (ui->shaderListWidget->item(i) && ui->shaderListWidget->item(i)->data(Qt::UserRole + 2).toULongLong()) { + glslp_free((glslp_t*)ui->shaderListWidget->item(i)->data(Qt::UserRole + 2).toULongLong()); + } + } + delete ui; +} + +void OpenGLShaderManagerDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { + accept(); + } else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) { + reject(); + } +} + + +void OpenGLShaderManagerDialog::on_buttonMoveUp_clicked() +{ + if (ui->shaderListWidget->currentRow() == 0) + return; + + int row = ui->shaderListWidget->currentRow(); + auto item = ui->shaderListWidget->takeItem(row); + ui->shaderListWidget->insertItem(row - 1, item); + ui->shaderListWidget->setCurrentItem(item); +} + + +void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) +{ + if (current == nullptr) { + ui->buttonRemove->setDisabled(true); + ui->buttonMoveUp->setDisabled(true); + ui->buttonMoveDown->setDisabled(true); + return; + } else { + ui->buttonRemove->setDisabled(false); + } + ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0); + ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)); +} + + +void OpenGLShaderManagerDialog::on_shaderListWidget_currentRowChanged(int currentRow) +{ + ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0); + ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)); +} + + +void OpenGLShaderManagerDialog::on_buttonMoveDown_clicked() +{ + if (ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)) + return; + + int row = ui->shaderListWidget->currentRow(); + auto item = ui->shaderListWidget->takeItem(row); + ui->shaderListWidget->insertItem(row + 1, item); + ui->shaderListWidget->setCurrentItem(item); +} + + +void OpenGLShaderManagerDialog::on_buttonAdd_clicked() +{ + auto res = QFileDialog::getOpenFileName(this, QString(), QString(), "GLSL Shaders (*.glslp *.glsl);;All files (*.*)"); + if (!res.isEmpty()) { + auto glslp_file = res.toUtf8(); + glslp_t* shaderfile = glslp_parse(glslp_file.data()); + if (shaderfile) { + auto filename = path_get_filename(glslp_file.data()); + QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget); + item->setText(filename); + item->setData(Qt::UserRole + 1, res); + item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile); + if (ui->shaderListWidget->count()) { + ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1); + } + } else { + QMessageBox::critical(this, tr("GLSL error"), tr("Could not load filename %1").arg(res)); + } + } +} + + +void OpenGLShaderManagerDialog::on_buttonRemove_clicked() +{ + if (ui->shaderListWidget->currentItem()) { + auto item = ui->shaderListWidget->takeItem(ui->shaderListWidget->currentRow()); + + if (item->data(Qt::UserRole + 2).toULongLong()) { + glslp_free((glslp_t*)item->data(Qt::UserRole + 2).toULongLong()); + } + delete item; + } +} + +void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted() +{ + memset(gl3_shader_file, 0, sizeof(gl3_shader_file)); + for (int i = 0; i < ui->shaderListWidget->count(); i++) { + strncpy(gl3_shader_file[i], ui->shaderListWidget->item(i)->data(Qt::UserRole + 1).toString().toUtf8(), 512); + } + startblit(); + config_save(); + endblit(); +} + diff --git a/src/qt/qt_openglshadermanagerdialog.hpp b/src/qt/qt_openglshadermanagerdialog.hpp new file mode 100644 index 000000000..bac0205cf --- /dev/null +++ b/src/qt/qt_openglshadermanagerdialog.hpp @@ -0,0 +1,40 @@ +#ifndef QT_OPENGLSHADERMANAGERDIALOG_H +#define QT_OPENGLSHADERMANAGERDIALOG_H + +#include +#include +#include + +namespace Ui { +class OpenGLShaderManagerDialog; +} + +class OpenGLShaderManagerDialog : public QDialog { + Q_OBJECT + +public: + explicit OpenGLShaderManagerDialog(QWidget *parent = nullptr); + ~OpenGLShaderManagerDialog(); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + + void on_buttonMoveUp_clicked(); + + void on_shaderListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); + + void on_shaderListWidget_currentRowChanged(int currentRow); + + void on_buttonMoveDown_clicked(); + + void on_buttonAdd_clicked(); + + void on_buttonRemove_clicked(); + + void on_OpenGLShaderManagerDialog_accepted(); + +private: + Ui::OpenGLShaderManagerDialog *ui; +}; + +#endif // QT_OPENGLSHADERMANAGERDIALOG_H diff --git a/src/qt/qt_openglshadermanagerdialog.ui b/src/qt/qt_openglshadermanagerdialog.ui new file mode 100644 index 000000000..2888e106f --- /dev/null +++ b/src/qt/qt_openglshadermanagerdialog.ui @@ -0,0 +1,148 @@ + + + OpenGLShaderManagerDialog + + + + 0 + 0 + 400 + 465 + + + + Dialog + + + + QLayout::SizeConstraint::SetFixedSize + + + + + QAbstractItemView::DragDropMode::InternalMove + + + QAbstractItemView::SelectionBehavior::SelectItems + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + false + + + Configure + + + + + + + Move up + + + + + + + Move down + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + Qt::Orientation::Vertical + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + false + + + + + + + + + + + buttonBox + accepted() + OpenGLShaderManagerDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + OpenGLShaderManagerDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index af72474c7..f3f5d2223 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -34,6 +34,8 @@ public: virtual QDialog *getOptions(QWidget *parent) { return nullptr; } /* Reloads options of renderer */ virtual void reloadOptions() { } + /* Make the renderer reload itself */ + virtual bool reloadRendererOption() { return false; } int r_monitor_index = 0; diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 8059d59c5..32ed5f7ca 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -70,6 +70,8 @@ public: void reloadOptions() const { return rendererWindow->reloadOptions(); } /* Returns options dialog for current renderer */ QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; } + /* Reload the renderer itself */ + bool reloadRendererOption() { return rendererWindow ? rendererWindow->reloadRendererOption() : false; } void setFocusRenderer(); void onResize(int width, int height); From f8517d05ef7f885a2d91629aec21fbf13a70d366 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 20:49:28 +0100 Subject: [PATCH 0405/1190] XGA/VGA changes of the evening (March 8th, 2025) Workaround xga/vga toggle bug in the inmos card so that it switches from xga to vga and viceversa on ami bioses. --- src/video/vid_svga.c | 5 +++-- src/video/vid_xga.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index caa20e196..1fd2460bd 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -782,7 +782,8 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) { if (xga->on) { - if ((svga->mapping.base == 0xb8000) && (xga->aperture_cntl == 1)) /*Some operating systems reset themselves with ctrl-alt-del by going into text mode.*/ + svga_log("XGA on=%d, base=%05x, ap=%x.\n", xga->on, svga->mapping.base, xga->aperture_cntl); + if ((svga->mapping.base == 0xb8000) && (xga->aperture_cntl >= 1)) /*Some operating systems reset themselves with ctrl-alt-del by going into text mode.*/ xga->on = 0; } } @@ -1541,7 +1542,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 32; svga->translate_address = NULL; - + svga->cable_connected = 1; svga->ksc5601_english_font_type = 0; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 2cc20044a..4c08b7b71 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -2738,7 +2738,7 @@ xga_write_test(uint32_t addr, uint8_t val, void *priv) xga_t *xga = (xga_t *) svga->xga; if (xga_active && xga) { - if (((xga->op_mode & 7) >= 1) && xga->aperture_cntl) { + if (((xga->op_mode & 7) >= 1) && xga->aperture_cntl && (svga->mapping.base == 0xb8000)) { xga_log("WriteAddr=%05x.\n", addr); if (val == 0xa5) { /*Memory size test of XGA*/ xga->test = val; @@ -2843,7 +2843,7 @@ xga_read_test(uint32_t addr, void *priv) uint8_t ret = 0x00; if (xga_active && xga) { - if (((xga->op_mode & 7) >= 1) && xga->aperture_cntl) { + if (((xga->op_mode & 7) >= 1) && xga->aperture_cntl && (svga->mapping.base == 0xb8000)) { if (xga->test == 0xa5) { /*Memory size test of XGA*/ if (addr == 0xa0001) { ret = xga->test; From 2f2a14e0e768dab93c78f8ee02ccac38642b6305 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 9 Mar 2025 01:58:47 +0600 Subject: [PATCH 0406/1190] Fix not saving shader section properly --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 3ff802952..46f935f7e 100644 --- a/src/config.c +++ b/src/config.c @@ -2681,7 +2681,7 @@ save_gl3_shaders(void) } else { for (i = 0; i < shaders; i++) { temp[0] = 0; - snprintf(temp, 512, "shader%d"); + snprintf(temp, 512, "shader%d", i); ini_section_set_string(cat, temp, gl3_shader_file[i]); } } From dad0a37ab3e7c66abecf54515f5679e39a708314 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 20:58:49 +0100 Subject: [PATCH 0407/1190] Mach32 LFB changes (March 8th, 2025) The Byte Write access of the LFB of the Mach32 was not correctly taking account of the subtraction of the address, this fixes possible graphics bugs using the LFB (Linear Aperture). --- src/video/vid_ati_mach8.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 0c8fb6691..d35257ea7 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -5226,7 +5226,7 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + (((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); @@ -5279,6 +5279,9 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + 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); + 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) { @@ -5291,8 +5294,6 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); } } else { - 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); if (dev->on) mach32_writel_linear(addr, val, mach); else From 9da53a611d8bfbd0100cd3caa6e88ca0d799f0fa Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 9 Mar 2025 01:58:48 +0100 Subject: [PATCH 0408/1190] VIA PIPC: Fix SCI IRQ readout. --- src/chipset/via_pipc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index dcfe41811..19355431e 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -413,7 +413,9 @@ pipc_reset_hard(void *priv) dev->power_regs[0x34] = 0x68; dev->power_regs[0x40] = 0x20; - dev->power_regs[0x42] = 0x50; + dev->power_regs[0x42] = 0x00; + acpi_set_irq_line(dev->acpi, 0x00); + dev->power_regs[0x48] = 0x01; if (dev->local == VIA_PIPC_686B) { @@ -1593,6 +1595,9 @@ pipc_reset(void *priv) pipc_write(pm_func, 0x48, 0x01, priv); pipc_write(pm_func, 0x49, 0x00, priv); + dev->power_regs[0x42] = 0x00; + acpi_set_irq_line(dev->acpi, 0x00); + pipc_write(1, 0x04, 0x80, priv); pipc_write(1, 0x09, 0x85, priv); pipc_write(1, 0x10, 0xf1, priv); From 0c7c85e66314fdbb7e8bad7a6392e43e1a3a0526 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 9 Mar 2025 02:18:18 +0100 Subject: [PATCH 0409/1190] ACPI: Do not raise or lower IRQ if IRQ line is set to IRQ 0. --- src/acpi.c | 10 ++++++++-- src/chipset/via_pipc.c | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index b33653663..ccd51ebca 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -211,7 +211,10 @@ acpi_update_irq(acpi_t *dev) if ((dev->regs.pmcntrl & 0x01) && sci_level) switch (dev->irq_mode) { default: - picintlevel(1 << dev->irq_line, &dev->irq_state); + if (dev->irq_line != 0) + picintlevel(1 << dev->irq_line, &dev->irq_state); + else + dev->irq_state = 1; break; case 1: pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); @@ -223,7 +226,10 @@ acpi_update_irq(acpi_t *dev) break; } else switch (dev->irq_mode) { default: - picintclevel(1 << dev->irq_line, &dev->irq_state); + if (dev->irq_line != 0) + picintclevel(1 << dev->irq_line, &dev->irq_state); + else + dev->irq_state = 0; break; case 1: pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 19355431e..11a192450 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -1699,6 +1699,8 @@ pipc_init(const device_t *info) acpi_set_nvr(dev->acpi, dev->nvr); acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); + + acpi_set_irq_mode(dev->acpi, 0); } return dev; From 7a4d5ee75e971fe4ddca1e72a2f8630cb2f8356e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 9 Mar 2025 13:06:58 +0600 Subject: [PATCH 0410/1190] Some optimizations --- src/qt/qt_openglrenderer_pcem.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 17f4299d7..e53b8b77b 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -770,7 +770,7 @@ OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) parentWidget = parent; - source.setRect(0, 0, 2048, 2048); + source.setRect(0, 0, 100, 100); isInitialized = false; isFinalized = false; } @@ -1075,11 +1075,18 @@ OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) destination.width() * devicePixelRatio(), destination.height() * devicePixelRatio()); #endif + + if (source.width() != w || source.height() != h) { + glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); + glw.glTexImage2D(GL_TEXTURE_2D, 0, (GLenum) QOpenGLTexture::RGBA8_UNorm, w, h, 0, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); + glw.glBindTexture(GL_TEXTURE_2D, 0); + } + source.setRect(x, y, w, h); glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); glw.glPixelStorei(GL_UNPACK_ROW_LENGTH, 2048); - glw.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4))); + glw.glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4))); glw.glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glw.glBindTexture(GL_TEXTURE_2D, 0); @@ -1369,10 +1376,10 @@ OpenGLRendererPCem::render() pass->state.tex_coords[7] = maxy; // create input tex coords - minx = video_rect.x / 2048.f; - miny = video_rect.y / 2048.f; - maxx = (video_rect.x + video_rect.w) / (float) 2048.f; - maxy = (video_rect.y + video_rect.h) / (float) 2048.f; + minx = 0; + miny = 0; + maxx = 1; + maxy = 1; GLfloat tex_coords[] = { minx, miny, minx, maxy, maxx, miny, maxx, maxy }; From 7e61d2d58692c10566b891c6f387920486fa54f5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 9 Mar 2025 23:58:54 +0600 Subject: [PATCH 0411/1190] OpenGL Shader configuration UI --- src/config.c | 14 +++- src/include/86box/ini.h | 3 +- src/ini.c | 52 +++++++++++--- src/qt/CMakeLists.txt | 1 + src/qt/qt_glsl_parser.cpp | 2 + src/qt/qt_mainwindow.cpp | 16 +++++ src/qt/qt_mainwindow.hpp | 4 ++ src/qt/qt_openglshaderconfig.cpp | 85 +++++++++++++++++++++++ src/qt/qt_openglshaderconfig.hpp | 40 +++++++++++ src/qt/qt_openglshaderconfig.ui | 92 +++++++++++++++++++++++++ src/qt/qt_openglshadermanagerdialog.cpp | 50 ++++++++++++++ src/qt/qt_openglshadermanagerdialog.hpp | 2 + src/qt/qt_openglshadermanagerdialog.ui | 4 +- 13 files changed, 349 insertions(+), 16 deletions(-) create mode 100644 src/qt/qt_openglshaderconfig.cpp create mode 100644 src/qt/qt_openglshaderconfig.hpp create mode 100644 src/qt/qt_openglshaderconfig.ui diff --git a/src/config.c b/src/config.c index 46f935f7e..20981885a 100644 --- a/src/config.c +++ b/src/config.c @@ -1725,11 +1725,15 @@ load_gl3_shaders(void) ini_section_t cat = ini_find_section(config, "GL3 Shaders"); char *p; char temp[512]; - int i = 0; + int i = 0, shaders = 0; memset(temp, 0, sizeof(temp)); memset(gl3_shader_file, 0, sizeof(gl3_shader_file)); - for (int i = 0; i < MAX_USER_SHADERS; i++) { + shaders = ini_section_get_int(cat, "shaders", 0); + if (shaders > MAX_USER_SHADERS) + shaders = MAX_USER_SHADERS; + + for (int i = 0; i < shaders; i++) { temp[0] = 0; snprintf(temp, 512, "shader%d", i); p = ini_section_get_string(cat, temp, ""); @@ -2670,8 +2674,12 @@ save_gl3_shaders(void) int shaders = 0, i = 0; for (i = 0; i < MAX_USER_SHADERS; i++) { - if (gl3_shader_file[i][0] == 0) + if (gl3_shader_file[i][0] == 0) { + temp[0] = 0; + snprintf(temp, 512, "shader%d", i); + ini_section_delete_var(cat, temp); break; + } shaders++; } diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h index 2ce89f788..3139f410e 100644 --- a/src/include/86box/ini.h +++ b/src/include/86box/ini.h @@ -31,6 +31,7 @@ typedef void *ini_section_t; extern ini_t ini_new(void); extern ini_t ini_read(const char *fn); +extern void ini_strip_quotes(ini_t ini); extern void ini_write(ini_t ini, const char *fn); extern void ini_dump(ini_t ini); extern void ini_close(ini_t ini); @@ -91,7 +92,7 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); extern void ini_rename_section(ini_section_t section, const char *name); extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); -static inline void *wx_config_load(const char *path) { return (void*) ini_read(path); } +static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; } static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); diff --git a/src/ini.c b/src/ini.c index 4ea6f6381..b4c905489 100644 --- a/src/ini.c +++ b/src/ini.c @@ -254,9 +254,8 @@ ini_delete_section_if_empty(ini_t ini, ini_section_t section) static section_t * create_section(list_t *head, const char *name) { - section_t *ns = malloc(sizeof(section_t)); + section_t *ns = calloc(1, sizeof(section_t)); - memset(ns, 0x00, sizeof(section_t)); memcpy(ns->name, name, strlen(name) + 1); list_add(&ns->list, head); @@ -279,9 +278,8 @@ ini_find_or_create_section(ini_t ini, const char *name) static entry_t * create_entry(section_t *section, const char *name) { - entry_t *ne = malloc(sizeof(entry_t)); + entry_t *ne = calloc(1, sizeof(entry_t)); - memset(ne, 0x00, sizeof(entry_t)); memcpy(ne->name, name, strlen(name) + 1); list_add(&ne->list, §ion->entry_head); @@ -390,11 +388,8 @@ ini_read(const char *fn) if (fp == NULL) return NULL; - head = malloc(sizeof(list_t)); - memset(head, 0x00, sizeof(list_t)); - - sec = malloc(sizeof(section_t)); - memset(sec, 0x00, sizeof(section_t)); + head = calloc(1, sizeof(list_t)); + sec = calloc(1, sizeof(section_t)); list_add(&sec->list, head); if (bom) @@ -475,7 +470,7 @@ ini_read(const char *fn) d = c; /* Allocate a new variable entry.. */ - ne = malloc(sizeof(entry_t)); + ne = calloc(1, sizeof(entry_t)); memset(ne, 0x00, sizeof(entry_t)); memcpy(ne->name, ename, 128); wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata) - 1); @@ -551,6 +546,43 @@ ini_write(ini_t ini, const char *fn) (void) fclose(fp); } +void +ini_strip_quotes(ini_t ini) +{ + list_t *list = (list_t *) ini; + section_t *sec; + + sec = (section_t *) list->next; + + while (sec != NULL) { + entry_t *ent; + + ent = (entry_t *) sec->entry_head.next; + while (ent != NULL) { + if (ent->name[0] != '\0') { + int i = 0; + if (ent->wdata[0] == L'\"') { + memmove(ent->wdata, &ent->wdata[1], sizeof(ent->wdata) - sizeof(wchar_t)); + } + if (ent->wdata[wcslen(ent->wdata) - 1] == L'\"') { + ent->wdata[wcslen(ent->wdata) - 1] = 0; + } + + if (ent->data[0] == '\"') { + memmove(ent->data, &ent->data[1], sizeof(ent->data) - sizeof(char)); + } + if (ent->data[strlen(ent->data) - 1] == '\"') { + ent->data[strlen(ent->data) - 1] = 0; + } + } + + ent = (entry_t *) ent->list.next; + } + + sec = (section_t *) sec->list.next; + } +} + ini_t ini_new(void) { diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 8a06cbe5a..574aae7b7 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -197,6 +197,7 @@ add_library(ui STATIC qt_openglshadermanagerdialog.hpp qt_openglshadermanagerdialog.cpp qt_openglshadermanagerdialog.ui + qt_openglshaderconfig.hpp qt_openglshaderconfig.cpp qt_openglshaderconfig.ui ) if(RTMIDI) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index b1a96a312..f43897506 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -255,6 +255,8 @@ glslp_t *glslp_parse(const char *f) { safe_strncpy(s, t + j, sublen); s[511 < sublen ? 511 : sublen] = 0; + if (s[strlen(s) - 1] == ';') s[strlen(s) - 1] = 0; + struct texture *tex = &glslp->textures[glslp->num_textures++]; strcpy(tex->name, s); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 60e0494fc..7e0cecdeb 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1982,6 +1982,12 @@ MainWindow::changeEvent(QEvent *event) } } +void +MainWindow::reloadAllRenderers() +{ + reload_renderers = true; +} + void MainWindow::on_actionRenderer_options_triggered() { @@ -2000,6 +2006,16 @@ MainWindow::on_actionRenderer_options_triggered() if (renderers[i] && renderers[i]->hasOptions()) renderers[i]->reloadOptions(); } + } else if (reload_renderers && ui->stackedWidget->reloadRendererOption()) { + reload_renderers = false; + 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)); + } + } + } } } } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 25e33d77c..dced698bb 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -32,6 +32,7 @@ public: QSize getRenderWidgetSize(); void setSendKeyboardInput(bool enabled); void checkFullscreenHotkey(); + void reloadAllRenderers(); std::array, 8> renderers; signals: @@ -173,6 +174,9 @@ private: bool fs_on_signal = false; bool fs_off_signal = false; + /* Reload the renderers after closing renderer options dialog. */ + bool reload_renderers = false; + friend class SpecifyDimensions; friend class ProgSettings; friend class RendererCommon; diff --git a/src/qt/qt_openglshaderconfig.cpp b/src/qt/qt_openglshaderconfig.cpp new file mode 100644 index 000000000..25f9d38a8 --- /dev/null +++ b/src/qt/qt_openglshaderconfig.cpp @@ -0,0 +1,85 @@ +#include "qt_openglshaderconfig.hpp" +#include "ui_qt_openglshaderconfig.h" + +#include "qt_mainwindow.hpp" + +extern MainWindow* main_window; + +extern "C" +{ +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/config.h> +} + +OpenGLShaderConfig::OpenGLShaderConfig(QWidget *parent, glslp_t* shader) + : QDialog(parent) + , ui(new Ui::OpenGLShaderConfig) +{ + ui->setupUi(this); + + currentShader = shader; + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + glslp_read_shader_config(currentShader); + + for (int i = 0; i < currentShader->num_parameters; i++) { + auto spinBox = new QDoubleSpinBox; + spinBox->setObjectName(currentShader->parameters[i].id); + spinBox->setRange(currentShader->parameters[i].min, currentShader->parameters[i].max); + spinBox->setValue(currentShader->parameters[i].value); + spinBox->setSingleStep(currentShader->parameters[i].step); + QFormLayout* layout = (QFormLayout*)ui->scrollAreaWidgetContents->layout(); + layout->addRow(currentShader->parameters[i].description, spinBox); + } +} + +OpenGLShaderConfig::~OpenGLShaderConfig() +{ + delete ui; +} + +void OpenGLShaderConfig::on_buttonBox_clicked(QAbstractButton *button) +{ + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) { + for (int i = 0; i < currentShader->num_parameters; i++) { + QDoubleSpinBox* box = this->findChild(QString(currentShader->parameters[i].id)); + if (box) { + box->setValue(currentShader->parameters[i].default_value); + } + } + } else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { + startblit(); + for (int i = 0; i < currentShader->num_parameters; i++) { + QDoubleSpinBox* box = this->findChild(QString(currentShader->parameters[i].id)); + if (box) { + float val = (float)box->value(); + currentShader->parameters[i].value = val; + } + } + glslp_write_shader_config(currentShader); + config_save(); + endblit(); + main_window->reloadAllRenderers(); + } +} + + +void OpenGLShaderConfig::on_OpenGLShaderConfig_accepted() +{ + startblit(); + for (int i = 0; i < currentShader->num_parameters; i++) { + QDoubleSpinBox* box = (QDoubleSpinBox*)this->findChild(QString(currentShader->parameters[i].id)); + if (box) { + float val = (float)box->value(); + currentShader->parameters[i].value = val; + } + } + glslp_write_shader_config(currentShader); + config_save(); + endblit(); + main_window->reloadAllRenderers(); +} + diff --git a/src/qt/qt_openglshaderconfig.hpp b/src/qt/qt_openglshaderconfig.hpp new file mode 100644 index 000000000..f71299d38 --- /dev/null +++ b/src/qt/qt_openglshaderconfig.hpp @@ -0,0 +1,40 @@ +#ifndef QT_OPENGLSHADERCONFIG_HPP +#define QT_OPENGLSHADERCONFIG_HPP + +#include +#include +#include +#include + +#include +#include + +extern "C" +{ +#include <86box/qt-glslp-parser.h> +} + +namespace Ui { +class OpenGLShaderConfig; +} + +class OpenGLShaderConfig : public QDialog { + Q_OBJECT + +public: + explicit OpenGLShaderConfig(QWidget *parent = nullptr, glslp_t* shader = nullptr); + ~OpenGLShaderConfig(); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + + void on_OpenGLShaderConfig_accepted(); + +private: + Ui::OpenGLShaderConfig *ui; + glslp_t* currentShader; + + std::map defaultValues; +}; + +#endif // QT_OPENGLSHADERCONFIG_HPP diff --git a/src/qt/qt_openglshaderconfig.ui b/src/qt/qt_openglshaderconfig.ui new file mode 100644 index 000000000..1aebdb6f6 --- /dev/null +++ b/src/qt/qt_openglshaderconfig.ui @@ -0,0 +1,92 @@ + + + OpenGLShaderConfig + + + + 0 + 0 + 400 + 300 + + + + Shader Configuration + + + + QLayout::SizeConstraint::SetMinAndMaxSize + + + + + true + + + + + 0 + 0 + 380 + 250 + + + + + QLayout::SizeConstraint::SetMaximumSize + + + QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow + + + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset + + + + + + + + + buttonBox + accepted() + OpenGLShaderConfig + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + OpenGLShaderConfig + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 26f206a0e..08cf94fd7 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -1,6 +1,8 @@ #include "qt_openglshadermanagerdialog.hpp" #include "ui_qt_openglshadermanagerdialog.h" +#include "qt_openglshaderconfig.hpp" + #include #include #include @@ -39,10 +41,21 @@ OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent) } if (ui->shaderListWidget->count()) { ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1); + auto current = ui->shaderListWidget->currentItem(); + if (current) { + glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong(); + if (shader->num_parameters > 0) + ui->buttonConfigure->setEnabled(true); + else + ui->buttonConfigure->setEnabled(false); + } else { + ui->buttonConfigure->setEnabled(false); + } } else { ui->buttonRemove->setDisabled(true); ui->buttonMoveUp->setDisabled(true); ui->buttonMoveDown->setDisabled(true); + ui->buttonConfigure->setDisabled(true); } } @@ -84,9 +97,16 @@ void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidg ui->buttonRemove->setDisabled(true); ui->buttonMoveUp->setDisabled(true); ui->buttonMoveDown->setDisabled(true); + ui->buttonConfigure->setDisabled(true); return; } else { ui->buttonRemove->setDisabled(false); + ui->buttonConfigure->setDisabled(true); + if (current) { + glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong(); + if (shader->num_parameters > 0) + ui->buttonConfigure->setEnabled(true); + } } ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0); ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)); @@ -95,6 +115,22 @@ void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidg void OpenGLShaderManagerDialog::on_shaderListWidget_currentRowChanged(int currentRow) { + auto current = ui->shaderListWidget->currentItem(); + if (current == nullptr) { + ui->buttonRemove->setDisabled(true); + ui->buttonMoveUp->setDisabled(true); + ui->buttonMoveDown->setDisabled(true); + ui->buttonConfigure->setDisabled(true); + return; + } else { + ui->buttonRemove->setDisabled(false); + ui->buttonConfigure->setDisabled(true); + if (current) { + glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong(); + if (shader->num_parameters > 0) + ui->buttonConfigure->setEnabled(true); + } + } ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0); ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)); } @@ -143,6 +179,8 @@ void OpenGLShaderManagerDialog::on_buttonRemove_clicked() glslp_free((glslp_t*)item->data(Qt::UserRole + 2).toULongLong()); } delete item; + + on_shaderListWidget_currentRowChanged(ui->shaderListWidget->currentRow()); } } @@ -157,3 +195,15 @@ void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted() endblit(); } + +void OpenGLShaderManagerDialog::on_buttonConfigure_clicked() +{ + auto item = ui->shaderListWidget->currentItem(); + if (item) { + glslp_t* shader = (glslp_t*)item->data(Qt::UserRole + 2).toULongLong(); + + auto configDialog = new OpenGLShaderConfig(this, shader); + configDialog->exec(); + } +} + diff --git a/src/qt/qt_openglshadermanagerdialog.hpp b/src/qt/qt_openglshadermanagerdialog.hpp index bac0205cf..b8885e3a3 100644 --- a/src/qt/qt_openglshadermanagerdialog.hpp +++ b/src/qt/qt_openglshadermanagerdialog.hpp @@ -33,6 +33,8 @@ private slots: void on_OpenGLShaderManagerDialog_accepted(); + void on_buttonConfigure_clicked(); + private: Ui::OpenGLShaderManagerDialog *ui; }; diff --git a/src/qt/qt_openglshadermanagerdialog.ui b/src/qt/qt_openglshadermanagerdialog.ui index 2888e106f..f68827436 100644 --- a/src/qt/qt_openglshadermanagerdialog.ui +++ b/src/qt/qt_openglshadermanagerdialog.ui @@ -11,7 +11,7 @@ - Dialog + Shader Manager @@ -59,7 +59,7 @@ - false + true Configure From f4479d34854a75777a7717287ac34cff42fd87c1 Mon Sep 17 00:00:00 2001 From: barnacl437 Date: Mon, 10 Mar 2025 01:05:37 +0700 Subject: [PATCH 0412/1190] some translation fixes for vi-VN lang --- src/qt/languages/vi-VN.po | 122 +++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 15802fc2d..abb17351b 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -682,13 +682,13 @@ msgid "Surface images" msgstr "Ảnh bề mặt" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/machines. Hãy chọn mẫu máy khác." +msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/machines. Hãy chọn mẫu máy khác." msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác." +msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác." msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác." +msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác." msgid "Machine" msgstr "Mẫu máy" @@ -1216,7 +1216,7 @@ msgid "Development of the WinBox manager stopped in 2022 due to a lack of mainta msgstr "Trình quản lý phiên WinBox đã bị dừng phát triển năm 2022 do thiếu nhân sự duy trì. Vì những quyết định để cho 86Box trở nên tốt hơn, chúng tôi đã không còn hỗ trợ trình quản lý WinBox.\n\n Sẽ không có bản cập nhật mới cho WinBox nữa, và nếu bạn tiếp tục sử dụng với các bản 86Box mới hơn có thể gặp lỗi. Bất kì các bản bug report liên quan đến lỗi của WinBox sẽ bị coi là không hợp lệ và bị đóng.\n\nTruy cập 86Box.net để tìm qua các trình quản lý phiên/manager khác cho phù hợp." msgid "Generate" -msgstr "Phát ra" +msgstr "Tạo" msgid "Joystick configuration" msgstr "Cấu hình cần điều khiển" @@ -1237,7 +1237,7 @@ msgid "List of MCA devices:" msgstr "Danh sách các thiết bị MCA:" msgid "Tablet tool" -msgstr "Công cụ máy tính bảng" +msgstr "Công cụ bảng nhập liệu" msgid "Qt (OpenGL &ES)" msgstr "QT (OpenGL &ES)" @@ -1261,19 +1261,19 @@ msgid "Cursor/Puck" msgstr "Con trỏ/puck" msgid "Pen" -msgstr "Cái bút" +msgstr "Bút" msgid "Host CD/DVD Drive (%1:)" msgstr "Máy chủ CD/DVD ổ đĩa (%1 :)" msgid "&Connected" -msgstr "& Kết nối" +msgstr "&Đã kết nối" msgid "Clear image history" msgstr "Xóa lịch sử ảnh đĩa" msgid "Create..." -msgstr "Tạo nên..." +msgstr "Tạo..." msgid "previous image" msgstr "đĩa trước đó" @@ -1306,7 +1306,7 @@ msgid "OpenGL 3.0 renderer options" msgstr "Tùy chọn kết xuất OpenGL 3.0" msgid "Render behavior" -msgstr "Hiện ra hành vi" +msgstr "Hành vi kết xuất" msgid "Use target framerate:" msgstr "Dùng số khung hình mục tiêu:" @@ -1318,16 +1318,16 @@ msgid "VSync" msgstr "Vsync" msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không sử dụng hình chữ nhật cho các hiệu ứng hoạt hình.</span></p></body></html>" +msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không tối ưu frametime cho các hiệu ứng động.</span></p></body></html>" msgid "Synchronize with video" -msgstr "Đồng bộ hóa với video" +msgstr "Đồng bộ với video" msgid "Shaders" msgstr "Shaders" msgid "Remove" -msgstr "Di dời" +msgstr "Loại bỏ" msgid "No shader selected" msgstr "Không có shader được chọn" @@ -1360,19 +1360,19 @@ msgid "Error initializing OpenGL" msgstr "Lỗi khởi tạo OpenGL" msgid "Falling back to software rendering.\n" -msgstr "Rơi trở lại kết xuất phần mềm.\n" +msgstr "Quay trở lại kết xuất phần mềm.\n" msgid "Allocating memory for unpack buffer failed.\n" msgstr "Phân bổ bộ nhớ cho bộ đệm giải nén không thành công.\n" msgid "<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>" -msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, FLOPPY, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>" +msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>" msgid "This machine might have been moved or copied." -msgstr "Máy này có thể đã được di chuyển hoặc sao chép." +msgstr "Cấu hình máy này có thể đã được di chuyển hoặc sao chép." msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure." -msgstr "Để đảm bảo chức năng kết nối mạng thích hợp, 86box cần biết liệu máy này có được di chuyển hay sao chép không.\n\nNếu bạn không chắc chắn, chọn \"Tôi đã sao chép nó\"." +msgstr "Để đảm bảo chức năng kết nối mạng thích hợp, 86Box cần biết liệu máy này có được di chuyển hay sao chép không.\n\nNếu bạn không chắc chắn, chọn \"Tôi đã sao chép nó\"." msgid "I Moved It" msgstr "Tôi đã di chuyển nó" @@ -1387,7 +1387,7 @@ msgid "No MCA devices." msgstr "Không có thiết bị MCA." msgid "MiB" -msgstr "Mib" +msgstr "MiB" msgid "Network Card #1" msgstr "Thẻ mạng 1" @@ -1402,7 +1402,7 @@ msgid "Network Card #4" msgstr "Thẻ mạng 4" msgid "Mode" -msgstr "Cách thức" +msgstr "Chế độ" msgid "Interface" msgstr "Giao diện" @@ -1414,7 +1414,7 @@ msgid "VDE Socket" msgstr "Ổ cắm VDE" msgid "86Box Unit Tester" -msgstr "Người kiểm tra đơn vị 86box" +msgstr "Trình kiểm tra đơn vị 86box" msgid "Novell NetWare 2.x Key Card" msgstr "Thẻ khóa Novell Netware 2.x" @@ -1432,7 +1432,7 @@ msgid "Serial port passthrough 4" msgstr "Thông qua cổng serial 4" msgid "Vision Systems LBA Enhancer" -msgstr "Hệ thống tầm nhìn LBA Enhancer" +msgstr "Vision Systems LBA Enhancer" msgid "Renderer options..." msgstr "Tùy chọn kết xuất ..." @@ -1474,7 +1474,7 @@ msgid "Roland CM-32LN Emulation" msgstr "Mô phỏng Roland CM-32LN" msgid "OPL4-ML Daughterboard" -msgstr "Con gái OPL4-ML" +msgstr "Bo mạch con OPL4-ML" msgid "System MIDI" msgstr "MIDI của hệ thống" @@ -1486,7 +1486,7 @@ msgid "BIOS Address" msgstr "Địa chỉ BIOS" msgid "Enable BIOS extension ROM Writes" -msgstr "Bật ROM mở rộng BIOS" +msgstr "Kích hoạt ghi ROM mở rộng BIOS" msgid "Address" msgstr "Địa chỉ" @@ -1513,22 +1513,22 @@ msgid "BIOS size" msgstr "Kích thước BIOS" msgid "Map C0000-C7FFF as UMB" -msgstr "Bản đồ C0000-C7FFF dưới dạng UMB" +msgstr "Map C0000-C7FFF dưới dạng UMB" msgid "Map C8000-CFFFF as UMB" -msgstr "Bản đồ C8000-CFFFF dưới dạng UMB" +msgstr "Map C8000-CFFFF dưới dạng UMB" msgid "Map D0000-D7FFF as UMB" -msgstr "Bản đồ D0000-D7FFF dưới dạng UMB" +msgstr "Map D0000-D7FFF dưới dạng UMB" msgid "Map D8000-DFFFF as UMB" -msgstr "Bản đồ D8000-Dffff dưới dạng UMB" +msgstr "Map D8000-Dffff dưới dạng UMB" msgid "Map E0000-E7FFF as UMB" -msgstr "Bản đồ E0000-E7FFF dưới dạng UMB" +msgstr "Map E0000-E7FFF dưới dạng UMB" msgid "Map E8000-EFFFF as UMB" -msgstr "Bản đồ e8000-effff dưới dạng umb" +msgstr "Map e8000-effff dưới dạng umb" msgid "JS9 Jumper (JIM)" msgstr "JS9 Jumper (Jim)" @@ -1543,13 +1543,13 @@ msgid "MIDI Thru" msgstr "Thông qua đầu vào MIDI" msgid "MIDI Clockout" -msgstr "MIDI đồng hồ" +msgstr "MIDI Clockout" msgid "SoundFont" -msgstr "Soundfont" +msgstr "Font âm thanh" msgid "Output Gain" -msgstr "Đầu ra tăng" +msgstr "Tăng đầu ra" msgid "Chorus" msgstr "Điệp khúc" @@ -1588,7 +1588,7 @@ msgid "Interpolation Method" msgstr "Phương pháp nội suy" msgid "Reverb Output Gain" -msgstr "Gợi ý đầu ra hồi âm" +msgstr "Tăng đầu ra hồi âm" msgid "Reversed stereo" msgstr "Đảo ngược âm thanh nổi" @@ -1609,10 +1609,10 @@ msgid "RTS toggle" msgstr "RT chuyển đổi" msgid "Revision" -msgstr "Ôn tập" +msgstr "Bản sửa đổi" msgid "Controller" -msgstr "Người điều khiển" +msgstr "Bộ điều khiển" msgid "Show Crosshair" msgstr "Hiển thị hình chữ thập" @@ -1624,7 +1624,7 @@ msgid "MAC Address" msgstr "Địa chỉ MAC" msgid "MAC Address OUI" -msgstr " OUI địa chỉ MAC" +msgstr "OUI địa chỉ MAC" msgid "Enable BIOS" msgstr "Bật BIOS" @@ -1696,7 +1696,7 @@ msgid "Enable OPL" msgstr "Bật OPL" msgid "Receive MIDI input (MPU-401)" -msgstr "Nhận nhập MIDI (MPU-401)" +msgstr "Nhận đầu vào MIDI (MPU-401)" msgid "SB low DMA" msgstr "SB DMA thấp" @@ -1708,7 +1708,7 @@ msgid "Enable CMS" msgstr "Bật CMS" msgid "Mixer" -msgstr "Máy trộn" +msgstr "Bộ trộn" msgid "High DMA" msgstr "DMA cao" @@ -1744,13 +1744,13 @@ msgid "RGB type" msgstr "Loại RGB" msgid "Line doubling type" -msgstr "Dòng nhân đôi" +msgstr "Loại dòng kép" msgid "Snow emulation" -msgstr "Đun tuyết" +msgstr "Giả lập hiệu ứng tuyết" msgid "Monitor type" -msgstr "Loại giám sát" +msgstr "Loại màn hình" msgid "Character set" msgstr "Bộ ký tự" @@ -1759,13 +1759,13 @@ msgid "XGA type" msgstr "Loại XGA" msgid "Instance" -msgstr "Ví dụ" +msgstr "Bản chạy" msgid "MMIO Address" msgstr "Địa chỉ MMIO" msgid "RAMDAC type" -msgstr "Loại Ramdac" +msgstr "Loại RAMDAC" msgid "Blend" msgstr "Trộn" @@ -1789,13 +1789,13 @@ msgid "Texture memory size" msgstr "Kích thước bộ nhớ kết cấu" msgid "Dither subtraction" -msgstr "Phân biệt trừ" +msgstr "Giảm ngân tán" msgid "Screen Filter" msgstr "Bộ lọc màn hình" msgid "Render threads" -msgstr "Kết xuất chủ đề" +msgstr "Luồng kết xuất" msgid "SLI" msgstr "SLI" @@ -1810,13 +1810,13 @@ msgid "I/O Width" msgstr "Chiều rộng I/O" msgid "Transfer Speed" -msgstr "Tốc độ chuyển" +msgstr "Tốc độ truyền tải" msgid "EMS mode" msgstr "Chế độ EMS" msgid "Address for > 2 MB" -msgstr "Địa chỉ cho> 2 MB" +msgstr "Địa chỉ cho > 2 MB" msgid "Frame Address" msgstr "Địa chỉ khung" @@ -1831,7 +1831,7 @@ msgid "Always at selected speed" msgstr "Luôn ở tốc độ đã chọn" msgid "BIOS setting + Hotkeys (off during POST)" -msgstr "Cài đặt BIOS + phím nóng (TẮT trong bài đăng)" +msgstr "Cài đặt BIOS + phím nóng (TẮT trong POST)" msgid "64 kB starting from F0000" msgstr "64 kb bắt đầu từ f0000" @@ -1858,7 +1858,7 @@ msgid "Non-timed (original)" msgstr "Không đúng lúc (bản gốc)" msgid "45 Hz (JMP2 not populated)" -msgstr "45 Hz (JMP2 không dân cư)" +msgstr "45 Hz (JMP2 không phổ cập)" msgid "Two" msgstr "Hai" @@ -1867,10 +1867,10 @@ msgid "Three" msgstr "Ba" msgid "Wheel" -msgstr "Bánh xe" +msgstr "Con lăn" msgid "Five + Wheel" -msgstr "Năm + bánh xe" +msgstr "Năm + con lăn" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serial / SMT3(R)V" @@ -2005,7 +2005,7 @@ msgid "Color" msgstr "Màu sắc" msgid "U.S. English" -msgstr "Tiếng Anh Hoa Kỳ" +msgstr "Tiếng Anh Mỹ" msgid "Scandinavian" msgstr "Scandinavia" @@ -2017,13 +2017,13 @@ msgid "Bochs latest" msgstr "Bochs mới nhất" msgid "Mono Non-Interlaced" -msgstr "Đơn sắc không được xen kẽ" +msgstr "Đơn sắc không xen kẽ" msgid "Color Interlaced" msgstr "Màu sắc xen kẽ" msgid "Color Non-Interlaced" -msgstr "Màu sắc không được xen kẽ" +msgstr "Màu sắc không xen kẽ" msgid "3Dfx Voodoo Graphics" msgstr "Đồ họa 3Dfx Voodoo" @@ -2071,7 +2071,7 @@ msgid "Parallel Line Internet Protocol" msgstr "Parallel Line Internet Protocol" msgid "Protection Dongle for Savage Quest" -msgstr "Bảo vệ dongle cho Savage Quest" +msgstr "Dongle bảo vệ cho Savage Quest" msgid "Serial Passthrough Device" msgstr "Thiết bị thông qua cổng serial" @@ -2083,7 +2083,7 @@ msgid "Host Serial Device" msgstr "Thiết bị serial máy chủ" msgid "Name of pipe" -msgstr "Tên của đường ống" +msgstr "Tên đường ống" msgid "Data bits" msgstr "Bit dữ liệu" @@ -2092,10 +2092,10 @@ msgid "Stop bits" msgstr "Dừng bit" msgid "Baud Rate of Passthrough" -msgstr "Tốc độ baud của qua đường" +msgstr "Tốc độ baud của đường thông" msgid "Named Pipe (Server)" -msgstr "Đường ống được đặt tên (máy chủ)" +msgstr "Đường ống có tên (máy chủ)" msgid "Host Serial Passthrough" msgstr "Thông qua cổng serial của máy chủ" @@ -2104,19 +2104,19 @@ msgid "Eject %s" msgstr "Đẩy đĩa ra %s" msgid "&Unmute" -msgstr "&Không quay được" +msgstr "&Mở tiếng" msgid "Softfloat FPU" msgstr "Softfloat FPU" msgid "High performance impact" -msgstr "Tác động cao đến hiệu suất" +msgstr "Ảnh hưởng lớn đến hiệu suất" msgid "RAM Disk (max. speed)" -msgstr "Đĩa RAM (Tối đa. Tốc độ)" +msgstr "Đĩa RAM (tốc độ tối đa)" msgid "IBM 8514/A clone (ISA)" -msgstr "IBM 8514/A dòng vô tính (ISA)" +msgstr "IBM 8514/A bản nhái (ISA)" msgid "Vendor" msgstr "Nhà sản xuất" From ff8b96aaede62c0c4b0dbf39ca3b0341ee3be9b3 Mon Sep 17 00:00:00 2001 From: Barnacl437 Date: Mon, 10 Mar 2025 01:20:25 +0700 Subject: [PATCH 0413/1190] fixing master branch conflict (vi-VN qt translation) --- src/qt/languages/vi-VN.po | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index abb17351b..6a2203de2 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -687,8 +687,11 @@ msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tươ msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Sẽ vô hiệu hóa card đồ họa thứ hai." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Thiết bị \"%hs\" không giả lập được do thiếu file ROM. Thiết bị sẽ bị bỏ qua." msgid "Machine" msgstr "Mẫu máy" From 34023692e15d8075127f16e14ae831f01b038fa0 Mon Sep 17 00:00:00 2001 From: Barnacl437 Date: Mon, 10 Mar 2025 01:24:41 +0700 Subject: [PATCH 0414/1190] conflict solving attempt #2 --- src/qt/languages/vi-VN.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 6a2203de2..93b800471 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -688,10 +688,10 @@ msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác." msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." -msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Sẽ vô hiệu hóa card đồ họa thứ hai." +msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Vô hiệu hóa card đồ họa thứ hai." msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." -msgstr "Thiết bị \"%hs\" không giả lập được do thiếu file ROM. Thiết bị sẽ bị bỏ qua." +msgstr "Thiết bị \"%hs\" không giả lập được do thiếu file ROM. Bỏ qua thiết bị." msgid "Machine" msgstr "Mẫu máy" From e854c5b4318b55898443c706d50b223fe29ef20d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 00:32:57 +0600 Subject: [PATCH 0415/1190] Some final fixes --- src/qt/qt_glsl_parser.cpp | 8 ++++++++ src/qt/qt_openglrenderer_pcem.cpp | 14 +++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index f43897506..a39e6d7bc 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -1,3 +1,10 @@ +#include "qt_mainwindow.hpp" +#include +#include +#include + +extern MainWindow* main_window; + #include #include #include @@ -137,6 +144,7 @@ static glslp_t *glsl_parse(const char *f) { strcpy(shader->shader_fn, f); shader->shader_program = load_file(f); if (!shader->shader_program) { + QMessageBox::critical((QWidget *) qApp->findChild(), QObject::tr("GLSL error"), QObject::tr("Could not load shader %s").arg(shader->shader_fn)); //wx_simple_messagebox("GLSL error", "Could not load shader %s\n", shader->shader_fn); glslp_free(glslp); return 0; diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index e53b8b77b..4644dc7be 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -1,6 +1,7 @@ #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" +#include #include #include #include @@ -131,6 +132,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); char *log = (char *) malloc(maxLength); glw.glGetProgramInfoLog(program->id, maxLength, &length, log); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Program not linked:\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); free(log); return 0; @@ -175,6 +177,7 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); char *log = (char *) malloc(length); glw.glGetShaderInfoLog(shader, length, &length, log); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not compile shader:\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); pclog("Could not compile shader: %s\n", log); @@ -577,7 +580,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Load texture %s...\n", file); if (!load_texture(file, &tex->texture)) { - // wx_simple_messagebox("GLSL Error", "Could not load texture: %s", file); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); pclog("Could not load texture %s!\n", file); failed = 1; break; @@ -623,6 +626,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Creating pass %u (%s)\n", (i + 1), pass->alias); pclog("Loading shader %s...\n", shader->shader_fn); if (!shader->shader_program) { + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); pclog("Could not load shader %s\n", shader->shader_fn); failed = 1; @@ -1337,10 +1341,10 @@ OpenGLRendererPCem::render() struct { uint32_t x, y, w, h; } rect, video_rect; - rect.x = destination.x(); - rect.y = destination.y(); - rect.w = destination.width(); - rect.h = destination.height(); + rect.x = 0; + rect.y = 0; + rect.w = source.width(); + rect.h = source.height(); video_rect.x = source.x(); video_rect.y = source.y(); From 1ca2aabf2f5f7e2d4c6e1a466e84b3b959585775 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 00:37:20 +0600 Subject: [PATCH 0416/1190] Remove some things that shouldn't be there --- src/device/kbc_at_dev.c | 3 --- src/include/86box/keyboard.h | 11 ++--------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index 82ce31bfd..c1041e6e1 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -88,9 +88,6 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main) { if (main) { kbc_at_dev_log("%s: dev->queue[%02X] = %02X;\n", dev->name, dev->queue_end, val); - if (!is_cpu_thread && kbc_at_dev_queue_pos(dev, 1) == dev->fifo_mask) { - while (kbc_at_dev_queue_pos(dev, 1) == dev->fifo_mask) {} - } dev->queue[dev->queue_end] = val; dev->queue_end = (dev->queue_end + 1) & dev->fifo_mask; } else { diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index b7f301a58..3a7260c72 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -22,13 +22,6 @@ #ifndef EMU_KEYBOARD_H #define EMU_KEYBOARD_H -#ifdef __cplusplus -# include -using atomic_uint = std::atomic_uint; -#else -# include -#endif - enum { DEV_KBD = 0, DEV_AUX = 1 @@ -69,8 +62,8 @@ typedef struct atkbc_dev_t { uint8_t rate; uint8_t cmd_queue_start; uint8_t cmd_queue_end; - atomic_uint queue_start; - atomic_uint queue_end; + uint8_t queue_start; + uint8_t queue_end; uint16_t flags; From 4d5907eac6d1955c1b7f7f6da09354f6a81fba3d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 9 Mar 2025 20:32:44 +0100 Subject: [PATCH 0417/1190] T128 changes of the evening (March 9th, 2025) 1. More accurate speed without stalls. 2. Added more IRQ's for AT compatibles. --- src/scsi/scsi_t128.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 6b73ae131..eada27246 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -95,7 +95,7 @@ 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, 1.0); + timer_on_auto(&t128->timer, 10.0); } } } @@ -147,7 +147,7 @@ t128_read(uint32_t addr, void *priv) scsi_bus->tx_mode = PIO_TX_BUS; timer_stop(&t128->timer); } else if (!timer_is_enabled(&t128->timer)) - timer_on_auto(&t128->timer, 1.0); + timer_on_auto(&t128->timer, 10.0); else t128->status &= ~0x04; } @@ -223,7 +223,7 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) t128->block_loaded = 1; t128->status &= ~0x04; - timer_on_auto(&t128->timer, 1.0); + timer_on_auto(&t128->timer, 10.0); } return 1; } @@ -252,7 +252,7 @@ t128_callback(void *priv) uint8_t status; if (scsi_bus->tx_mode != PIO_TX_BUS) - timer_on_auto(&t128->timer, scsi_bus->period / 65.0); + timer_on_auto(&t128->timer, scsi_bus->period / 60.0); if (scsi_bus->data_wait & 1) { scsi_bus->clear_req = 3; @@ -350,6 +350,7 @@ t128_callback(void *priv) if (!t128->block_count) { t128->block_loaded = 0; scsi_bus->bus_out |= BUS_REQ; + timer_on_auto(&t128->timer, 10.0); t128_log("IO End of read transfer\n"); } break; @@ -576,6 +577,10 @@ static const device_config_t t128_config[] = { { .description = "IRQ 3", .value = 3 }, { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, { .description = "" } }, .bios = { { 0 } } From 144558e60ec806aa9643645c6774876f19a30430 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 01:33:18 +0600 Subject: [PATCH 0418/1190] Fix another string mistake --- src/qt/qt_glsl_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index a39e6d7bc..2a4c4ddd1 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -144,7 +144,7 @@ static glslp_t *glsl_parse(const char *f) { strcpy(shader->shader_fn, f); shader->shader_program = load_file(f); if (!shader->shader_program) { - QMessageBox::critical((QWidget *) qApp->findChild(), QObject::tr("GLSL error"), QObject::tr("Could not load shader %s").arg(shader->shader_fn)); + QMessageBox::critical((QWidget *) qApp->findChild(), QObject::tr("GLSL error"), QObject::tr("Could not load shader %1").arg(shader->shader_fn)); //wx_simple_messagebox("GLSL error", "Could not load shader %s\n", shader->shader_fn); glslp_free(glslp); return 0; From 9756fa04062c7f4306939860fe49622c22998f98 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 02:00:24 +0600 Subject: [PATCH 0419/1190] Fix the parser for trailing hash comments --- src/ini.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ini.c b/src/ini.c index b4c905489..8dca54754 100644 --- a/src/ini.c +++ b/src/ini.c @@ -561,6 +561,10 @@ ini_strip_quotes(ini_t ini) while (ent != NULL) { if (ent->name[0] != '\0') { int i = 0; + int trailing_hash = strcspn(ent->data, "#"); + int trailing_quote; + ent->wdata[trailing_hash] = 0; + ent->data[trailing_hash] = 0; if (ent->wdata[0] == L'\"') { memmove(ent->wdata, &ent->wdata[1], sizeof(ent->wdata) - sizeof(wchar_t)); } @@ -574,6 +578,12 @@ ini_strip_quotes(ini_t ini) if (ent->data[strlen(ent->data) - 1] == '\"') { ent->data[strlen(ent->data) - 1] = 0; } + + trailing_quote = strcspn(ent->data, "\""); + ent->wdata[trailing_quote] = 0; + ent->data[trailing_quote] = 0; + + pclog("Section %s, entry %s, value %ls\n", sec->name, ent->name, ent->wdata); } ent = (entry_t *) ent->list.next; From cfe630e5239cd46207649028f2873223ae6224d2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 02:09:40 +0600 Subject: [PATCH 0420/1190] Temp changes --- src/qt/qt_openglrenderer_pcem.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 4644dc7be..8ee4dff39 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -132,7 +132,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); char *log = (char *) malloc(maxLength); glw.glGetProgramInfoLog(program->id, maxLength, &length, log); - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Program not linked:\n%1").arg(log)); + throw opengl_init_error_pcem(tr("Program not linked:\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); free(log); return 0; @@ -177,10 +177,9 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); char *log = (char *) malloc(length); glw.glGetShaderInfoLog(shader, length, &length, log); - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not compile shader:\n%1").arg(log)); - // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); - pclog("Could not compile shader: %s\n", log); + throw opengl_init_error_pcem(tr("Could not compile shader:\n%1").arg(log)); + // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); // pclog("Shader: %s\n", program); free(log); @@ -580,7 +579,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Load texture %s...\n", file); if (!load_texture(file, &tex->texture)) { - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); + throw opengl_init_error_pcem(tr("Could not load texture: %s").arg(file)); pclog("Could not load texture %s!\n", file); failed = 1; break; @@ -626,7 +625,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Creating pass %u (%s)\n", (i + 1), pass->alias); pclog("Loading shader %s...\n", shader->shader_fn); if (!shader->shader_program) { - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); + throw opengl_init_error_pcem(tr("Could not load shader: %1").arg(shader->shader_fn)); // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); pclog("Could not load shader %s\n", shader->shader_fn); failed = 1; From 29b6cd484cfdd5e2477b33cfc0fe40f3e710aef1 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 Jan 2025 21:48:38 -0500 Subject: [PATCH 0421/1190] Fix a few potential segfaults found in device.c --- src/device.c | 143 ++++++++++++++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 64 deletions(-) diff --git a/src/device.c b/src/device.c index 434bd3776..604f7e2f6 100644 --- a/src/device.c +++ b/src/device.c @@ -660,13 +660,15 @@ device_get_config_string(const char *str) int device_get_config_int(const char *str) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int)); + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int)); - cfg++; + cfg++; + } } return 0; @@ -675,13 +677,15 @@ device_get_config_int(const char *str) int device_get_config_int_ex(const char *str, int def) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_int((char *) device_current.name, (char *) str, def)); + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, def)); - cfg++; + cfg++; + } } return def; @@ -690,13 +694,15 @@ device_get_config_int_ex(const char *str, int def) int device_get_config_hex16(const char *str) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int)); + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) + return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int)); - cfg++; + cfg++; + } } return 0; @@ -705,13 +711,15 @@ device_get_config_hex16(const char *str) int device_get_config_hex20(const char *str) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int)); + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) + return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int)); - cfg++; + cfg++; + } } return 0; @@ -720,13 +728,15 @@ device_get_config_hex20(const char *str) int device_get_config_mac(const char *str, int def) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_mac((char *) device_current.name, (char *) str, def)); + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) + return (config_get_mac((char *) device_current.name, (char *) str, def)); - cfg++; + cfg++; + } } return def; @@ -735,60 +745,68 @@ device_get_config_mac(const char *str, int def) void device_set_config_int(const char *str, int val) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) { - config_set_int((char *) device_current.name, (char *) str, val); - break; + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) { + config_set_int((char *) device_current.name, (char *) str, val); + break; + } + + cfg++; } - - cfg++; } } void device_set_config_hex16(const char *str, int val) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) { - config_set_hex16((char *) device_current.name, (char *) str, val); - break; + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) { + config_set_hex16((char *) device_current.name, (char *) str, val); + break; + } + + cfg++; } - - cfg++; } } void device_set_config_hex20(const char *str, int val) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) { - config_set_hex20((char *) device_current.name, (char *) str, val); - break; - } + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) { + config_set_hex20((char *) device_current.name, (char *) str, val); + break; + } cfg++; + } } } void device_set_config_mac(const char *str, int val) { - const device_config_t *cfg = device_current.dev->config; + if (device_current.dev != NULL) { + const device_config_t *cfg = device_current.dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) { - config_set_mac((char *) device_current.name, (char *) str, val); - break; + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) { + config_set_mac((char *) device_current.name, (char *) str, val); + break; + } + + cfg++; } - - cfg++; } } @@ -806,20 +824,18 @@ device_is_valid(const device_t *device, int mch) int machine_get_config_int(char *str) { - const device_t *dev = machine_get_device(machine); - const device_config_t *cfg; + const device_t *dev = machine_get_device(machine); - if (dev == NULL) - return 0; + if (dev != NULL) { + const device_config_t *cfg = dev->config; - cfg = dev->config; - while (cfg && cfg->type != CONFIG_END) { - if (!strcmp(str, cfg->name)) - return (config_get_int((char *) dev->name, str, cfg->default_int)); + while ((cfg != NULL) && (cfg->type != CONFIG_END)) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) dev->name, str, cfg->default_int)); - cfg++; + cfg++; + } } - return 0; } @@ -830,9 +846,8 @@ machine_get_config_string(char *str) const char *ret = ""; if (dev != NULL) { - const device_config_t *cfg; + const device_config_t *cfg = dev->config; - cfg = dev->config; while ((cfg != NULL) && (cfg->type != CONFIG_END)) { if (!strcmp(str, cfg->name)) { const char *s = config_get_string((char *) dev->name, str, From a7d8f4a4e1e0808fae91ecc28149d443fc6b54d4 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 Jan 2025 23:30:51 -0500 Subject: [PATCH 0422/1190] Extra CONFIG_BIOS Helpers --- src/device.c | 107 +++++++++++++++++++++++++++++++++++++ src/include/86box/device.h | 9 +++- 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/src/device.c b/src/device.c index 604f7e2f6..814320c29 100644 --- a/src/device.c +++ b/src/device.c @@ -429,6 +429,113 @@ device_available(const device_t *dev) return 0; } +uint8_t +device_get_bios_type(const device_t *dev, const char *internal_name) +{ + const device_config_t *config = NULL; + const device_config_bios_t *bios = NULL; + + if (dev != NULL) { + config = dev->config; + if (config != NULL) { + while (config->type != CONFIG_END) { + if (config->type == CONFIG_BIOS) { + bios = config->bios; + while (bios->files_no != 0) { + if (!strcmp(internal_name, bios->internal_name)) + return bios->bios_type; + bios++; + } + } + config++; + } + } + } + + return 0; +} + +uint8_t +device_get_bios_num_files(const device_t *dev, const char *internal_name) +{ + const device_config_t *config = NULL; + const device_config_bios_t *bios = NULL; + + if (dev != NULL) { + config = dev->config; + if (config != NULL) { + while (config->type != CONFIG_END) { + if (config->type == CONFIG_BIOS) { + bios = config->bios; + while (bios->files_no != 0) { + if (!strcmp(internal_name, bios->internal_name)) + return bios->files_no; + bios++; + } + } + config++; + } + } + } + + return 0; +} + +uint32_t +device_get_bios_local(const device_t *dev, const char *internal_name) +{ + const device_config_t *config = NULL; + const device_config_bios_t *bios = NULL; + + if (dev != NULL) { + config = dev->config; + if (config != NULL) { + while (config->type != CONFIG_END) { + if (config->type == CONFIG_BIOS) { + bios = config->bios; + while (bios->files_no != 0) { + printf("Internal name was: %s", internal_name); + if (!strcmp(internal_name, bios->internal_name)) + return bios->local; + bios++; + } + } + config++; + } + } + } + + return 0; +} + +uint32_t +device_get_bios_file_size(const device_t *dev, const char *internal_name) +{ + const device_config_t *config = NULL; + const device_config_bios_t *bios = NULL; + + if (dev != NULL) { + config = dev->config; + if (config != NULL) { + while (config->type != CONFIG_END) { + if (config->type == CONFIG_BIOS) { + bios = config->bios; + + /* Go through the ROM's in the device configuration. */ + while (bios->files_no != 0) { + if (!strcmp(internal_name, bios->internal_name)) + return bios->size; + bios++; + } + } + config++; + } + } + } + + return 0; +} + const char * device_get_bios_file(const device_t *dev, const char *internal_name, int file_no) { diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 4cc283a25..c75cbfdcc 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -137,8 +137,8 @@ typedef struct device_config_spinner_t { typedef struct device_config_bios_t { const char *name; const char *internal_name; - int bios_type; - int files_no; + uint8_t bios_type; + uint8_t files_no; uint32_t local; uint32_t size; void *dev1; @@ -211,6 +211,11 @@ extern void device_speed_changed(void); extern void device_force_redraw(void); extern void device_get_name(const device_t *dev, int bus, char *name); extern int device_has_config(const device_t *dev); + +extern uint8_t device_get_bios_type(const device_t *dev, const char *internal_name); +extern uint8_t device_get_bios_num_files(const device_t *dev, const char *internal_name); +extern uint32_t device_get_bios_local(const device_t *dev, const char *internal_name); +extern uint32_t device_get_bios_file_size(const device_t *dev, const char *internal_name); extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no); extern int device_is_valid(const device_t *, int mch); From 6740b62d23e8443d7a44ebaf2e88bbdf9e3c2f1b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 9 Mar 2025 01:29:55 -0500 Subject: [PATCH 0423/1190] Improve empty bios file entry support --- src/device.c | 73 +++++++++++++++++++------------------- src/qt/qt_deviceconfig.cpp | 8 +++-- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/device.c b/src/device.c index 814320c29..e1af3c5f3 100644 --- a/src/device.c +++ b/src/device.c @@ -390,22 +390,21 @@ device_get_priv(const device_t *dev) int device_available(const device_t *dev) { - const device_config_t *config = NULL; - const device_config_bios_t *bios = NULL; - if (dev != NULL) { - config = dev->config; + const device_config_t *config = dev->config; if (config != NULL) { while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { int roms_present = 0; - - bios = (const device_config_bios_t *) config->bios; + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; /* Go through the ROM's in the device configuration. */ - while (bios->files_no != 0) { + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { int i = 0; - for (int bf = 0; bf < bios->files_no; bf++) + for (uint8_t bf = 0; bf < bios->files_no; bf++) i += !!rom_present(bios->files[bf]); if (i == bios->files_no) roms_present++; @@ -432,16 +431,16 @@ device_available(const device_t *dev) uint8_t device_get_bios_type(const device_t *dev, const char *internal_name) { - const device_config_t *config = NULL; - const device_config_bios_t *bios = NULL; - if (dev != NULL) { - config = dev->config; + const device_config_t *config = dev->config; if (config != NULL) { while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { - bios = config->bios; - while (bios->files_no != 0) { + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { if (!strcmp(internal_name, bios->internal_name)) return bios->bios_type; bios++; @@ -458,16 +457,16 @@ device_get_bios_type(const device_t *dev, const char *internal_name) uint8_t device_get_bios_num_files(const device_t *dev, const char *internal_name) { - const device_config_t *config = NULL; - const device_config_bios_t *bios = NULL; - if (dev != NULL) { - config = dev->config; + const device_config_t *config = dev->config; if (config != NULL) { while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { - bios = config->bios; - while (bios->files_no != 0) { + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { if (!strcmp(internal_name, bios->internal_name)) return bios->files_no; bios++; @@ -484,16 +483,16 @@ device_get_bios_num_files(const device_t *dev, const char *internal_name) uint32_t device_get_bios_local(const device_t *dev, const char *internal_name) { - const device_config_t *config = NULL; - const device_config_bios_t *bios = NULL; - if (dev != NULL) { - config = dev->config; + const device_config_t *config = dev->config; if (config != NULL) { while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { - bios = config->bios; - while (bios->files_no != 0) { + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { printf("Internal name was: %s", internal_name); if (!strcmp(internal_name, bios->internal_name)) return bios->local; @@ -511,18 +510,18 @@ device_get_bios_local(const device_t *dev, const char *internal_name) uint32_t device_get_bios_file_size(const device_t *dev, const char *internal_name) { - const device_config_t *config = NULL; - const device_config_bios_t *bios = NULL; - if (dev != NULL) { - config = dev->config; + const device_config_t *config = dev->config; if (config != NULL) { while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { - bios = config->bios; + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; /* Go through the ROM's in the device configuration. */ - while (bios->files_no != 0) { + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { if (!strcmp(internal_name, bios->internal_name)) return bios->size; bios++; @@ -539,18 +538,20 @@ device_get_bios_file_size(const device_t *dev, const char *internal_name) const char * device_get_bios_file(const device_t *dev, const char *internal_name, int file_no) { - const device_config_t *config = NULL; const device_config_bios_t *bios = NULL; if (dev != NULL) { - config = dev->config; + const device_config_t *config = dev->config; if (config != NULL) { while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { - bios = config->bios; + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; /* Go through the ROM's in the device configuration. */ - while (bios->files_no != 0) { + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { if (!strcmp(internal_name, bios->internal_name)) { if (file_no < bios->files_no) return bios->files[file_no]; diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index e2d6759ad..fff085194 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -242,8 +242,12 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep) int currentIndex = -1; q = 0; - for (auto *bios = config->bios; (bios != nullptr) && (bios->name != nullptr) && - (strlen(bios->name) > 0); ++bios) { + for (auto *bios = config->bios; (bios != nullptr) && + (bios->name != nullptr) && + (bios->internal_name != nullptr) && + (strlen(bios->name) > 0) && + (strlen(bios->internal_name) > 0) && + (bios->files_no > 0); ++bios) { p = 0; for (int d = 0; d < bios->files_no; d++) p += !!rom_present(const_cast(bios->files[d])); From 4504348fffc8fb3885347c124228fa25d19f6c86 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 9 Mar 2025 01:49:22 -0500 Subject: [PATCH 0424/1190] Make config_bios_t dev's into an array --- src/include/86box/device.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/include/86box/device.h b/src/include/86box/device.h index c75cbfdcc..fb86d2adc 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -141,8 +141,7 @@ typedef struct device_config_bios_t { uint8_t files_no; uint32_t local; uint32_t size; - void *dev1; - void *dev2; + void *dev[2]; const char *files[9]; } device_config_bios_t; From 097ea4abf2d6220b2951be2996e72e9c528d2d34 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 9 Mar 2025 04:54:42 -0400 Subject: [PATCH 0425/1190] Two missing CONFIG_END's in qt_deviceconfig.cpp --- src/qt/qt_deviceconfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index fff085194..cda52e722 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -123,7 +123,7 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep) if (config == NULL) return; - while (config->type != -1) { + while (config->type != CONFIG_END) { const int config_type = config->type & CONFIG_TYPE_MASK; /* Ignore options of the wrong class. */ @@ -376,7 +376,7 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se return; config = device->config; - while (config->type != -1) { + while (config->type != CONFIG_END) { switch (config->type) { default: break; From e84bbcac0f9e72613bd9d2d10dbf387e4d91de95 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 7 Mar 2025 21:24:55 +0500 Subject: [PATCH 0426/1190] Handle libslirp 4.9.0's deprecations --- src/network/net_slirp.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 203428b83..e86ea45fd 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -155,14 +155,22 @@ net_slirp_timer_mod(void *timer, int64_t expire_timer, UNUSED(void *opaque)) } static void +#if SLIRP_CHECK_VERSION(4, 9, 0) +net_slirp_register_poll_socket(slirp_os_socket fd, void *opaque) +#else net_slirp_register_poll_fd(int fd, void *opaque) +#endif { (void) fd; (void) opaque; } static void +#if SLIRP_CHECK_VERSION(4, 9, 0) +net_slirp_unregister_poll_socket(slirp_os_socket fd, void *opaque) +#else net_slirp_unregister_poll_fd(int fd, void *opaque) +#endif { (void) fd; (void) opaque; @@ -198,7 +206,11 @@ net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque) #ifdef _WIN32 static int +# if SLIRP_CHECK_VERSION(4, 9, 0) +net_slirp_add_poll(slirp_os_socket fd, int events, void *opaque) +# else net_slirp_add_poll(int fd, int events, void *opaque) +# endif { net_slirp_t *slirp = (net_slirp_t *) opaque; long bitmask = 0; @@ -216,7 +228,11 @@ net_slirp_add_poll(int fd, int events, void *opaque) } #else static int +# if SLIRP_CHECK_VERSION(4, 9, 0) +net_slirp_add_poll(slirp_os_socket fd, int events, void *opaque) +# else net_slirp_add_poll(int fd, int events, void *opaque) +# endif { net_slirp_t *slirp = (net_slirp_t *) opaque; @@ -307,8 +323,13 @@ static const SlirpCb slirp_cb = { .timer_new = net_slirp_timer_new, .timer_free = net_slirp_timer_free, .timer_mod = net_slirp_timer_mod, +#if SLIRP_CHECK_VERSION(4, 9, 0) + .register_poll_socket = net_slirp_register_poll_socket, + .unregister_poll_socket = net_slirp_unregister_poll_socket, +#else .register_poll_fd = net_slirp_register_poll_fd, .unregister_poll_fd = net_slirp_unregister_poll_fd, +#endif .notify = net_slirp_notify }; @@ -362,7 +383,11 @@ net_slirp_thread(void *priv) bool run = true; while (run) { uint32_t timeout = -1; +# if SLIRP_CHECK_VERSION(4, 9, 0) + slirp_pollfds_fill_socket(slirp->slirp, &timeout, net_slirp_add_poll, slirp); +# else slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp); +# endif if (timeout < 0) timeout = INFINITE; @@ -409,7 +434,11 @@ net_slirp_thread(void *priv) net_slirp_add_poll(net_event_get_fd(&slirp->stop_event), SLIRP_POLL_IN, slirp); net_slirp_add_poll(net_event_get_fd(&slirp->tx_event), SLIRP_POLL_IN, slirp); +# if SLIRP_CHECK_VERSION(4, 9, 0) + slirp_pollfds_fill_socket(slirp->slirp, &timeout, net_slirp_add_poll, slirp); +# else slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp); +# endif int ret = poll(slirp->pfd, slirp->pfd_len, timeout); From a29613a88015a5d3648e17ee6b31a92f9af11801 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 7 Mar 2025 22:20:46 +0500 Subject: [PATCH 0427/1190] Switch to slirp_new --- src/network/net_slirp.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index e86ea45fd..92c4c4ddf 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -489,10 +489,47 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv struct in_addr dhcp = { .s_addr = htonl(0x0a00000f | (slirp_card_num << 8)) }; /* 10.0.x.15 */ struct in_addr dns = { .s_addr = htonl(0x0a000003 | (slirp_card_num << 8)) }; /* 10.0.x.3 */ struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */ - struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */ + + const SlirpConfig slirp_config = { +#if SLIRP_CHECK_VERSION(4, 9, 0) + .version = 6, +#else + .version = 1, +#endif + .restricted = 0, + .in_enabled = 1, + .vnetwork = net, + .vnetmask = mask, + .vhost = host, + .in6_enabled = 0, + .vprefix_addr6 = { .s6_addr = { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, /* fec0:: - unused */ + .vprefix_len = 64, + .vhost6 = { .s6_addr = { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02 } }, /* fec0::2 - unused */ + .vhostname = "86Box", + .tftp_server_name = NULL, + .tftp_path = NULL, + .bootfile = NULL, + .vdhcp_start = dhcp, + .vnameserver = dns, + .vnameserver6 = { .s6_addr = { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03 } }, /* fec0::3 - unused */ + .vdnssearch = NULL, + .vdomainname = NULL, + .if_mtu = 0, + .if_mru = 0, + .disable_host_loopback = 0, + .enable_emu = 0, +#if SLIRP_CHECK_VERSION(4, 9, 0) + .outbound_addr = NULL, + .outbound_addr6 = NULL, + .disable_dns = 0, + .disable_dhcp = 0, + .mfr_id = 0, + .oob_eth_addr = { 0, 0, 0, 0, 0, 0 } +#endif + }; /* Initialize SLiRP. */ - slirp->slirp = slirp_init(0, 1, net, mask, host, 0, ipv6_dummy, 0, ipv6_dummy, NULL, NULL, NULL, NULL, dhcp, dns, ipv6_dummy, NULL, NULL, &slirp_cb, slirp); + slirp->slirp = slirp_new(&slirp_config, &slirp_cb, slirp); if (!slirp->slirp) { slirp_log("SLiRP: initialization failed\n"); snprintf(netdrv_errbuf, NET_DRV_ERRBUF_SIZE, "SLiRP initialization failed"); From 1005bdddd46125298461e1325dafa054fe7eeac1 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 10 Mar 2025 02:27:02 -0400 Subject: [PATCH 0428/1190] Fix warning in device.c --- src/device.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/device.c b/src/device.c index e1af3c5f3..25f0b55de 100644 --- a/src/device.c +++ b/src/device.c @@ -538,8 +538,6 @@ device_get_bios_file_size(const device_t *dev, const char *internal_name) const char * device_get_bios_file(const device_t *dev, const char *internal_name, int file_no) { - const device_config_bios_t *bios = NULL; - if (dev != NULL) { const device_config_t *config = dev->config; if (config != NULL) { From ba519fa6729fd1721308a77c1a0232c3f876bfb1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 12:37:50 +0600 Subject: [PATCH 0429/1190] Strip all whitespaces as well --- src/ini.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/ini.c b/src/ini.c index 8dca54754..7a54d5396 100644 --- a/src/ini.c +++ b/src/ini.c @@ -546,6 +546,55 @@ ini_write(ini_t ini, const char *fn) (void) fclose(fp); } +wchar_t * +trim_w(wchar_t *str) +{ + size_t len = 0; + wchar_t *frontp = str; + wchar_t *endp = NULL; + + if (str == NULL) { + return NULL; + } + if (str[0] == L'\0') { + return str; + } + + len = wcslen(str); + endp = str + len; + + /* Move the front and back pointers to address the first non-whitespace + * characters from each end. + */ + while (iswspace((wint_t) *frontp)) { + ++frontp; + } + if (endp != frontp) { + while (iswspace((wint_t) *(--endp)) && endp != frontp) { } + } + + if (frontp != str && endp == frontp) + *str = L'\0'; + else if ((str + len - 1) != endp) + *(endp + 1) = L'\0'; + + /* Shift the string so that it starts at str so that if it's dynamically + * allocated, we can still free it on the returned pointer. Note the reuse + * of endp to mean the front of the string buffer now. + */ + endp = str; + if (frontp != str) { + while (*frontp) { + *endp++ = *frontp++; + } + *endp = L'\0'; + } + + return str; +} + +extern char* trim(char* str); + void ini_strip_quotes(ini_t ini) { @@ -582,8 +631,9 @@ ini_strip_quotes(ini_t ini) trailing_quote = strcspn(ent->data, "\""); ent->wdata[trailing_quote] = 0; ent->data[trailing_quote] = 0; - - pclog("Section %s, entry %s, value %ls\n", sec->name, ent->name, ent->wdata); + + trim_w(ent->wdata); + trim(ent->data); } ent = (entry_t *) ent->list.next; From 1626ee8760ac985680be80feecaa8aada416f81f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 12:38:21 +0600 Subject: [PATCH 0430/1190] Revert "Temp changes" This reverts commit cfe630e5239cd46207649028f2873223ae6224d2. --- src/qt/qt_openglrenderer_pcem.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 8ee4dff39..4644dc7be 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -132,7 +132,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); char *log = (char *) malloc(maxLength); glw.glGetProgramInfoLog(program->id, maxLength, &length, log); - throw opengl_init_error_pcem(tr("Program not linked:\n%1").arg(log)); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Program not linked:\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); free(log); return 0; @@ -177,9 +177,10 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); char *log = (char *) malloc(length); glw.glGetShaderInfoLog(shader, length, &length, log); - pclog("Could not compile shader: %s\n", log); - throw opengl_init_error_pcem(tr("Could not compile shader:\n%1").arg(log)); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not compile shader:\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); + + pclog("Could not compile shader: %s\n", log); // pclog("Shader: %s\n", program); free(log); @@ -579,7 +580,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Load texture %s...\n", file); if (!load_texture(file, &tex->texture)) { - throw opengl_init_error_pcem(tr("Could not load texture: %s").arg(file)); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); pclog("Could not load texture %s!\n", file); failed = 1; break; @@ -625,7 +626,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Creating pass %u (%s)\n", (i + 1), pass->alias); pclog("Loading shader %s...\n", shader->shader_fn); if (!shader->shader_program) { - throw opengl_init_error_pcem(tr("Could not load shader: %1").arg(shader->shader_fn)); + QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); pclog("Could not load shader %s\n", shader->shader_fn); failed = 1; From dceb13f859d41185597a1e87be24d4b48bf5c283 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 13:27:29 +0600 Subject: [PATCH 0431/1190] OpenGL error messages are now reported properly --- src/qt/qt_main.cpp | 4 ++++ src/qt/qt_mainwindow.cpp | 12 ++++++++++-- src/qt/qt_mainwindow.hpp | 3 +++ src/qt/qt_openglrenderer_pcem.cpp | 18 +++++++++++------- src/qt/qt_platform.cpp | 5 +++++ 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 9d965be31..b48d272c5 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -90,6 +90,8 @@ extern "C" { #include <86box/timer.h> #include <86box/nvr.h> extern int qt_nvr_save(void); + +bool cpu_thread_running = false; } void qt_set_sequence_auto_mnemonic(bool b); @@ -444,6 +446,7 @@ main_thread_fn() } } + cpu_thread_running = false; is_quit = 1; for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if (gfxcard[i]) { @@ -736,6 +739,7 @@ main(int argc, char *argv[]) #endif plat_pause(0); + cpu_thread_running = true; main_thread = new std::thread(main_thread_fn); }); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 7e0cecdeb..85bc0de55 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -62,6 +62,8 @@ extern int qt_nvr_save(void); #ifdef MTR_ENABLED # include #endif + +extern bool cpu_thread_running; }; #include @@ -1256,7 +1258,7 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) static auto curdopause = dopause; if (event->type() == QEvent::WindowBlocked) { curdopause = dopause; - plat_pause(1); + plat_pause(isShowMessage ? 2 : 1); emit setMouseCapture(false); } else if (event->type() == QEvent::WindowUnblocked) { plat_pause(curdopause); @@ -1279,7 +1281,11 @@ void MainWindow::showMessage(int flags, const QString &header, const QString &message) { if (QThread::currentThread() == this->thread()) { - showMessage_(flags, header, message); + if (!cpu_thread_running) { + showMessageForNonQtThread(flags, header, message, nullptr); + } + else + showMessage_(flags, header, message); } else { std::atomic_bool done = false; emit showMessageForNonQtThread(flags, header, message, &done); @@ -1295,6 +1301,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag if (done) { *done = false; } + isShowMessage = true; QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this); if (flags & (MBX_FATAL)) { box.setIcon(QMessageBox::Critical); @@ -1306,6 +1313,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag if (done) { *done = true; } + isShowMessage = false; if (cpu_thread_run == 0) QApplication::exit(-1); } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index dced698bb..479ed38a4 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -182,6 +182,9 @@ private: friend class RendererCommon; friend class RendererStack; // For UI variable access by non-primary renderer windows. friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. + + + bool isShowMessage = false; }; #endif // QT_MAINWINDOW_HPP diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 4644dc7be..c8f3d3eb9 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -1,6 +1,8 @@ #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" +extern MainWindow* main_window; + #include #include #include @@ -26,6 +28,7 @@ extern "C" { #include <86box/86box.h> #include <86box/plat.h> +#include <86box/ui.h> #include <86box/video.h> #include <86box/path.h> #include <86box/ini.h> @@ -33,6 +36,7 @@ extern "C" { #include <86box/qt-glslp-parser.h> char gl3_shader_file[MAX_USER_SHADERS][512]; +extern bool cpu_thread_running; } #define SCALE_SOURCE 0 @@ -132,7 +136,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); char *log = (char *) malloc(maxLength); glw.glGetProgramInfoLog(program->id, maxLength, &length, log); - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Program not linked:\n%1").arg(log)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Program not linked:\n\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); free(log); return 0; @@ -177,7 +181,7 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); char *log = (char *) malloc(length); glw.glGetShaderInfoLog(shader, length, &length, log); - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not compile shader:\n%1").arg(log)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not compile shader:\n\n%1").arg(log)); // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); pclog("Could not compile shader: %s\n", log); @@ -580,7 +584,8 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Load texture %s...\n", file); if (!load_texture(file, &tex->texture)) { - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); + //QMessageBox::critical(main_window, tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); pclog("Could not load texture %s!\n", file); failed = 1; break; @@ -626,7 +631,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) pclog("Creating pass %u (%s)\n", (i + 1), pass->alias); pclog("Loading shader %s...\n", shader->shader_fn); if (!shader->shader_program) { - QMessageBox::critical((QWidget *) qApp->findChild(), tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); pclog("Could not load shader %s\n", shader->shader_fn); failed = 1; @@ -764,8 +769,7 @@ OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) #else format.setVersion(3, 2); #endif - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - format.setOption(QSurfaceFormat::DebugContext); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) format.setRenderableType(QSurfaceFormat::OpenGLES); @@ -1031,7 +1035,7 @@ OpenGLRendererPCem::initialize() for (auto &flag : buf_usage) flag.test_and_set(); - QMessageBox::critical((QWidget *) qApp->findChild(), tr("Error initializing OpenGL"), e.what() + tr("\nFalling back to software rendering.")); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("Error initializing OpenGL"), e.what() + tr("\nFalling back to software rendering.")); context->doneCurrent(); isFinalized = true; diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 561c94d8a..35dbc0081 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -385,6 +385,7 @@ plat_munmap(void *ptr, size_t size) #endif } +extern bool cpu_thread_running; void plat_pause(int p) { @@ -392,6 +393,10 @@ plat_pause(int p) wchar_t title[1024]; wchar_t paused_msg[512]; + if (!cpu_thread_running && p == 1) { + p = 2; + } + if ((!!p) == dopause) { #ifdef Q_OS_WINDOWS if (source_hwnd) From acf52f702793e610508b2e978c198a7db3f430e0 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 25 Aug 2024 17:55:41 -0400 Subject: [PATCH 0432/1190] XTIDE Changes --- src/disk/hdc_xtide.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index c18a24c4e..74abc1c4d 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -46,6 +46,7 @@ #include <86box/hdc_ide.h> #include <86box/plat_unused.h> +#define ROM_PATH_TINY "roms/hdd/xtide/ide_tiny.bin" #define ROM_PATH_XT "roms/hdd/xtide/ide_xt.bin" #define ROM_PATH_XTP "roms/hdd/xtide/ide_xtp.bin" #define ROM_PATH_AT "roms/hdd/xtide/ide_at.bin" From e257569e6763a6ba91763e089cd9c8fa64440042 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 9 Feb 2025 23:40:56 -0500 Subject: [PATCH 0433/1190] Single Channel XTIDE support --- src/disk/hdc.c | 2 ++ src/disk/hdc_xtide.c | 44 ++++++++++++++++++++++++++++++++++++----- src/include/86box/hdc.h | 10 ++++++---- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index f09a9a430..582c33428 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -72,7 +72,9 @@ static const struct { { &ide_isa_device }, { &ide_isa_2ch_device }, { &xtide_at_device }, + { &xtide_at_2ch_device }, { &xtide_at_ps2_device }, + { &xtide_at_ps2_2ch_device }, { &xta_wdxt150_device }, { &xtide_acculogic_device }, { &xtide_device }, diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 74abc1c4d..09e41b9ea 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -157,7 +157,10 @@ xtide_at_init(const device_t *info) device_get_bios_file(info, device_get_config_bios("bios"), 0), 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - device_add(&ide_isa_2ch_device); + if (info->local == 1) + device_add(&ide_isa_2ch_device); + else + device_add(&ide_isa_device); return xtide; } @@ -203,7 +206,10 @@ xtide_at_ps2_init(UNUSED(const device_t *info)) rom_init(&xtide->bios_rom, ROM_PATH_PS2AT, 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - device_add(&ide_isa_2ch_device); + if (info->local == 1) + device_add(&ide_isa_2ch_device); + else + device_add(&ide_isa_device); return xtide; } @@ -311,10 +317,24 @@ const device_t xtide_device = { }; const device_t xtide_at_device = { + .name = "PC/AT XTIDE (Primary Only)", + .internal_name = "xtide_at_1ch", + .flags = DEVICE_ISA16, + .local = 0, + .init = xtide_at_init, + .close = xtide_at_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = xtide_at_config +}; + +const device_t xtide_at_2ch_device = { .name = "PC/AT XTIDE", .internal_name = "xtide_at", .flags = DEVICE_ISA16, - .local = 0, + .local = 1, .init = xtide_at_init, .close = xtide_at_close, .reset = NULL, @@ -339,8 +359,8 @@ const device_t xtide_acculogic_device = { }; const device_t xtide_at_ps2_device = { - .name = "PS/2 AT XTIDE (1.1.5)", - .internal_name = "xtide_at_ps2", + .name = "PS/2 AT XTIDE (1.1.5) (Primary Only)", + .internal_name = "xtide_at_ps2_1ch", .flags = DEVICE_ISA16, .local = 0, .init = xtide_at_ps2_init, @@ -351,3 +371,17 @@ const device_t xtide_at_ps2_device = { .force_redraw = NULL, .config = NULL }; + +const device_t xtide_at_ps2_2ch_device = { + .name = "PS/2 AT XTIDE (1.1.5)", + .internal_name = "xtide_at_ps2", + .flags = DEVICE_ISA16, + .local = 1, + .init = xtide_at_ps2_init, + .close = xtide_at_close, + .reset = NULL, + .available = xtide_at_ps2_available, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 7f91fd61b..71f83e5e6 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -99,10 +99,12 @@ extern const device_t mcide_device; extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ extern const device_t xta_hd20_device; /* EuroPC internal */ -extern const device_t xtide_device; /* xtide_xt */ -extern const device_t xtide_at_device; /* xtide_at */ -extern const device_t xtide_acculogic_device; /* xtide_ps2 */ -extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ +extern const device_t xtide_device; /* xtide_xt */ +extern const device_t xtide_at_device; /* xtide_at */ +extern const device_t xtide_at_2ch_device; /* xtide_at_2ch */ +extern const device_t xtide_acculogic_device; /* xtide_ps2 */ +extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ +extern const device_t xtide_at_ps2_2ch_device; /* xtide_at_ps2_2ch */ /* Miscellaneous */ extern const device_t lba_enhancer_device; From b1d68b83e7af9a271440c45826790ed767848ff3 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 10 Feb 2025 01:51:36 -0500 Subject: [PATCH 0434/1190] Allow Configuration of XTIDE base and bios addr --- src/disk/hdc_xtide.c | 95 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 09e41b9ea..fc18d79db 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -137,11 +137,11 @@ xtide_init(const device_t *info) rom_init(&xtide->bios_rom, device_get_bios_file(info, device_get_config_bios("bios"), 0), - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + device_get_config_hex20("bios_addr"), 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); - io_sethandler(0x0300, 16, + io_sethandler(device_get_config_hex16("base"), 16, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide); @@ -228,8 +228,93 @@ xtide_at_close(void *priv) free(xtide); } +// clang-format off static const device_config_t xtide_config[] = { - // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x300, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "200H", .value = 0x200 }, + { .description = "210H", .value = 0x210 }, + { .description = "220H", .value = 0x220 }, + { .description = "230H", .value = 0x230 }, + { .description = "240H", .value = 0x240 }, + { .description = "250H", .value = 0x250 }, + { .description = "260H", .value = 0x260 }, + { .description = "270H", .value = 0x270 }, + { .description = "280H", .value = 0x280 }, + { .description = "290H", .value = 0x290 }, + { .description = "2A0H", .value = 0x2a0 }, + { .description = "2B0H", .value = 0x2b0 }, + { .description = "2C0H", .value = 0x2c0 }, + { .description = "2D0H", .value = 0x2d0 }, + { .description = "2E0H", .value = 0x2e0 }, + { .description = "2F0H", .value = 0x2f0 }, + { .description = "300H", .value = 0x300 }, + { .description = "310H", .value = 0x310 }, + { .description = "320H", .value = 0x320 }, + { .description = "330H", .value = 0x330 }, + { .description = "340H", .value = 0x340 }, + { .description = "350H", .value = 0x350 }, + { .description = "360H", .value = 0x360 }, + { .description = "370H", .value = 0x370 }, + { .description = "380H", .value = 0x380 }, + { .description = "390H", .value = 0x390 }, + { .description = "3A0H", .value = 0x3a0 }, + { .description = "3B0H", .value = 0x3b0 }, + { .description = "3C0H", .value = 0x3c0 }, + { .description = "3D0H", .value = 0x3d0 }, + { .description = "3E0H", .value = 0x3e0 }, + { .description = "3F0H", .value = 0x3f0 }, + { NULL } + }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0xd0000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, +#if 0 + // Supported on XT IDE Deluxe By Monotech + { .description = "C000H", .value = 0xc0000 }, + { .description = "C200H", .value = 0xc2000 }, + { .description = "C400H", .value = 0xc4000 }, + { .description = "C600H", .value = 0xc6000 }, +#endif + { .description = "C800H", .value = 0xc8000 }, + { .description = "CA00H", .value = 0xca000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "CE00H", .value = 0xce000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D200H", .value = 0xd2000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D600H", .value = 0xd6000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DA00H", .value = 0xda000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "DE00H", .value = 0xde000 }, +#if 0 + // Supported on VCFed rev 2 + { .description = "E000H", .value = 0xe0000 }, + { .description = "E400H", .value = 0xe4000 }, + { .description = "E800H", .value = 0xe8000 }, + { .description = "EC00H", .value = 0xec000 }, +#endif + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "bios", .description = "BIOS Revision", @@ -262,11 +347,9 @@ static const device_config_t xtide_config[] = { }, }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on }; static const device_config_t xtide_at_config[] = { - // clang-format off { .name = "bios", .description = "BIOS Revision", @@ -299,8 +382,8 @@ static const device_config_t xtide_at_config[] = { }, }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on }; +// clang-format on const device_t xtide_device = { .name = "PC/XT XTIDE", From 9e95e1e4752dcb3c01335f02d596c9592ffd6af5 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 10 Feb 2025 02:42:19 -0500 Subject: [PATCH 0435/1190] Move ROM write functions to rom.c --- src/floppy/fdc_monster.c | 51 ---------------------------------------- src/include/86box/rom.h | 5 ++++ src/mem/rom.c | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c index 1b0e2fbac..b91d4db66 100644 --- a/src/floppy/fdc_monster.c +++ b/src/floppy/fdc_monster.c @@ -47,57 +47,6 @@ typedef struct monster_fdc_t { char nvr_path[64]; } monster_fdc_t; -static void -rom_write(uint32_t addr, uint8_t val, void *priv) -{ - const rom_t *rom = (rom_t *) priv; - -#ifdef ROM_TRACE - if (rom->mapping.base == ROM_TRACE) - rom_log("ROM: read byte from BIOS at %06lX\n", addr); -#endif - - if (addr < rom->mapping.base) - return; - if (addr >= (rom->mapping.base + rom->sz)) - return; - rom->rom[(addr - rom->mapping.base) & rom->mask] = val; -} - -static void -rom_writew(uint32_t addr, uint16_t val, void *priv) -{ - rom_t *rom = (rom_t *) priv; - -#ifdef ROM_TRACE - if (rom->mapping.base == ROM_TRACE) - rom_log("ROM: read word from BIOS at %06lX\n", addr); -#endif - - if (addr < (rom->mapping.base - 1)) - return; - if (addr >= (rom->mapping.base + rom->sz)) - return; - *(uint16_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val; -} - -static void -rom_writel(uint32_t addr, uint32_t val, void *priv) -{ - rom_t *rom = (rom_t *) priv; - -#ifdef ROM_TRACE - if (rom->mapping.base == ROM_TRACE) - rom_log("ROM: read long from BIOS at %06lX\n", addr); -#endif - - if (addr < (rom->mapping.base - 3)) - return; - if (addr >= (rom->mapping.base + rom->sz)) - return; - *(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val; -} - static void monster_fdc_close(void *priv) { diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index 83fd7cf90..331d78526 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -52,7 +52,12 @@ extern uint8_t rom_read(uint32_t addr, void *priv); extern uint16_t rom_readw(uint32_t addr, void *priv); extern uint32_t rom_readl(uint32_t addr, void *priv); +extern void rom_write(uint32_t addr, uint8_t val, void *priv); +extern void rom_writew(uint32_t addr, uint16_t val, void *priv); +extern void rom_writel(uint32_t addr, uint32_t val, void *priv); + extern void rom_get_full_path(char *dest, const char *fn); + extern FILE *rom_fopen(const char *fn, char *mode); extern int rom_getfile(char *fn, char *s, int size); extern int rom_present(const char *fn); diff --git a/src/mem/rom.c b/src/mem/rom.c index 8b2308402..666652d53 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -244,6 +244,57 @@ rom_readl(uint32_t addr, void *priv) return (*(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask]); } +void +rom_write(uint32_t addr, uint8_t val, void *priv) +{ + const rom_t *rom = (rom_t *) priv; + +#ifdef ROM_TRACE + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: write byte from BIOS at %06lX\n", addr); +#endif + + if (addr < rom->mapping.base) + return; + if (addr >= (rom->mapping.base + rom->sz)) + return; + rom->rom[(addr - rom->mapping.base) & rom->mask] = val; +} + +void +rom_writew(uint32_t addr, uint16_t val, void *priv) +{ + rom_t *rom = (rom_t *) priv; + +#ifdef ROM_TRACE + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: write word from BIOS at %06lX\n", addr); +#endif + + if (addr < (rom->mapping.base - 1)) + return; + if (addr >= (rom->mapping.base + rom->sz)) + return; + *(uint16_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val; +} + +void +rom_writel(uint32_t addr, uint32_t val, void *priv) +{ + rom_t *rom = (rom_t *) priv; + +#ifdef ROM_TRACE + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: write long from BIOS at %06lX\n", addr); +#endif + + if (addr < (rom->mapping.base - 3)) + return; + if (addr >= (rom->mapping.base + rom->sz)) + return; + *(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val; +} + int rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { From f41f26a6e08d026429fd4c59f324a31557db2426 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 10 Feb 2025 02:43:32 -0500 Subject: [PATCH 0436/1190] The xtide (XT) ROM is now optionally writable --- src/disk/hdc_xtide.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index fc18d79db..154a28cec 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -41,6 +41,7 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/timer.h> +#include <86box/nvr.h> #include <86box/device.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -58,6 +59,7 @@ typedef struct xtide_t { void *ide_board; uint8_t data_high; rom_t bios_rom; + char nvr_path[64]; } xtide_t; static void @@ -145,6 +147,18 @@ xtide_init(const device_t *info) xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide); + uint8_t rom_writes_enabled = device_get_config_int("rom_writes_enabled"); + + if (rom_writes_enabled) { + mem_mapping_set_write_handler(&xtide->bios_rom.mapping, rom_write, rom_writew, rom_writel); + sprintf(xtide->nvr_path, "xtide_%i.nvr", device_get_instance()); + FILE *fp = nvr_fopen(xtide->nvr_path, "rb"); + if (fp != NULL) { + fread(xtide->bios_rom.rom, 1, 0x2000, fp); + fclose(fp); + } + } + return xtide; } @@ -193,6 +207,14 @@ xtide_close(void *priv) { xtide_t *xtide = (xtide_t *) priv; + if (xtide->nvr_path[0] != 0x00) { + FILE *fp = nvr_fopen(xtide->nvr_path, "wb"); + if (fp != NULL) { + fwrite(xtide->bios_rom.rom, 1, 0x2000, fp); + fclose(fp); + } + } + free(xtide); ide_xtide_close(); @@ -275,6 +297,17 @@ static const device_config_t xtide_config[] = { }, .bios = { { 0 } } }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "bios_addr", .description = "BIOS Address", From 837c0d369e4f6ea1613e3ad127b4e1271581cd32 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 21 Feb 2025 13:43:07 -0500 Subject: [PATCH 0437/1190] A few cleanups in qt_settingssound.cpp --- src/qt/qt_settingssound.cpp | 88 +++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/src/qt/qt_settingssound.cpp b/src/qt/qt_settingssound.cpp index e0572c3d8..cca903076 100644 --- a/src/qt/qt_settingssound.cpp +++ b/src/qt/qt_settingssound.cpp @@ -50,13 +50,15 @@ void SettingsSound::save() { for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { - auto *cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); - sound_card_current[i] = cbox->currentData().toInt(); + QComboBox *cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); + sound_card_current[i] = cbox->currentData().toInt(); } midi_output_device_current = ui->comboBoxMidiOut->currentData().toInt(); - midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt(); - mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0; + + midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt(); + + mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0; sound_is_float = ui->checkBoxFloat32->isChecked() ? 1 : 0; @@ -74,12 +76,13 @@ SettingsSound::onCurrentMachineChanged(const int machineId) int c; int selectedRow; + // Sound Card for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { - auto * cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); - auto * model = cbox->model(); - const auto removeRows = model->rowCount(); - c = 0; - selectedRow = 0; + QComboBox *cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); + c = 0; + auto model = cbox->model(); + auto removeRows = model->rowCount(); + selectedRow = 0; while (true) { /* Skip "internal" if machine doesn't have it or this is not the primary card. */ @@ -88,17 +91,21 @@ SettingsSound::onCurrentMachineChanged(const int machineId) continue; } - auto name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); + const QString name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); if (name.isEmpty()) { break; } - if (sound_card_available(c) && device_is_valid(sound_card_getdevice(c), machineId)) { - int row = Models::AddEntry(model, name, c); - if (c == sound_card_current[i]) { - selectedRow = row - removeRows; + if (sound_card_available(c)) { + const device_t *sound_dev = sound_card_getdevice(c); + if (device_is_valid(sound_dev, machineId)) { + int row = Models::AddEntry(model, name, c); + if (c == sound_card_current[i]) { + selectedRow = row - removeRows; + } } } + c++; } @@ -108,12 +115,14 @@ SettingsSound::onCurrentMachineChanged(const int machineId) cbox->setCurrentIndex(selectedRow); } - auto model = ui->comboBoxMidiOut->model(); - auto removeRows = model->rowCount(); - c = 0; - selectedRow = 0; + // Midi Out + c = 0; + auto model = ui->comboBoxMidiOut->model(); + auto removeRows = model->rowCount(); + selectedRow = 0; + while (true) { - QString name = DeviceConfig::DeviceName(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0); + const QString name = DeviceConfig::DeviceName(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0); if (name.isEmpty()) { break; } @@ -124,19 +133,23 @@ SettingsSound::onCurrentMachineChanged(const int machineId) selectedRow = row - removeRows; } } + c++; } + model->removeRows(0, removeRows); ui->comboBoxMidiOut->setEnabled(model->rowCount() > 0); ui->comboBoxMidiOut->setCurrentIndex(-1); ui->comboBoxMidiOut->setCurrentIndex(selectedRow); + // Midi In + c = 0; model = ui->comboBoxMidiIn->model(); removeRows = model->rowCount(); - c = 0; selectedRow = 0; + while (true) { - QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0); + const QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0); if (name.isEmpty()) { break; } @@ -150,14 +163,19 @@ SettingsSound::onCurrentMachineChanged(const int machineId) c++; } + model->removeRows(0, removeRows); ui->comboBoxMidiIn->setEnabled(model->rowCount() > 0); ui->comboBoxMidiIn->setCurrentIndex(-1); ui->comboBoxMidiIn->setCurrentIndex(selectedRow); + // Standalone MPU401 ui->checkBoxMPU401->setChecked(mpu401_standalone_enable > 0); + + // Float32 Sound ui->checkBoxFloat32->setChecked(sound_is_float > 0); + // FM Driver switch (fm_driver) { case FM_DRV_YMFM: ui->radioButtonYMFM->setChecked(true); @@ -193,6 +211,7 @@ SettingsSound::on_comboBoxSoundCard1_currentIndexChanged(int index) return; } int sndCard = ui->comboBoxSoundCard1->currentData().toInt(); + if (sndCard == SOUND_INTERNAL) ui->pushButtonConfigureSoundCard1->setEnabled(machine_has_flags(machineId, MACHINE_SOUND) && device_has_config(machine_get_snd_device(machineId))); @@ -203,8 +222,9 @@ SettingsSound::on_comboBoxSoundCard1_currentIndexChanged(int index) void SettingsSound::on_pushButtonConfigureSoundCard1_clicked() { - int sndCard = ui->comboBoxSoundCard1->currentData().toInt(); - auto *device = sound_card_getdevice(sndCard); + int sndCard = ui->comboBoxSoundCard1->currentData().toInt(); + auto *device = sound_card_getdevice(sndCard); + if (sndCard == SOUND_INTERNAL) device = machine_get_snd_device(machineId); DeviceConfig::ConfigureDevice(device, 1, qobject_cast(Settings::settings)); @@ -216,15 +236,17 @@ SettingsSound::on_comboBoxSoundCard2_currentIndexChanged(int index) if (index < 0) { return; } + int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); + ui->pushButtonConfigureSoundCard2->setEnabled(sound_card_has_config(sndCard)); } void SettingsSound::on_pushButtonConfigureSoundCard2_clicked() { - int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); - auto *device = sound_card_getdevice(sndCard); + int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); + const device_t *device = sound_card_getdevice(sndCard); DeviceConfig::ConfigureDevice(device, 2, qobject_cast(Settings::settings)); } @@ -234,15 +256,18 @@ SettingsSound::on_comboBoxSoundCard3_currentIndexChanged(int index) if (index < 0) { return; } + int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); + ui->pushButtonConfigureSoundCard3->setEnabled(sound_card_has_config(sndCard)); } void SettingsSound::on_pushButtonConfigureSoundCard3_clicked() { - int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); - auto *device = sound_card_getdevice(sndCard); + int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); + const device_t *device = sound_card_getdevice(sndCard); + DeviceConfig::ConfigureDevice(device, 3, qobject_cast(Settings::settings)); } @@ -252,15 +277,18 @@ SettingsSound::on_comboBoxSoundCard4_currentIndexChanged(int index) if (index < 0) { return; } + int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); + ui->pushButtonConfigureSoundCard4->setEnabled(sound_card_has_config(sndCard)); } void SettingsSound::on_pushButtonConfigureSoundCard4_clicked() { - int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); - auto *device = sound_card_getdevice(sndCard); + int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); + const device_t *device = sound_card_getdevice(sndCard); + DeviceConfig::ConfigureDevice(device, 4, qobject_cast(Settings::settings)); } @@ -270,6 +298,7 @@ SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) if (index < 0) { return; } + ui->pushButtonConfigureMidiOut->setEnabled(midi_out_device_has_config(ui->comboBoxMidiOut->currentData().toInt())); ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA))); ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked()); @@ -288,6 +317,7 @@ SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) if (index < 0) { return; } + ui->pushButtonConfigureMidiIn->setEnabled(midi_in_device_has_config(ui->comboBoxMidiIn->currentData().toInt())); ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA))); ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked()); From 727bfc0745d599ad32f04cb055070a929771cd27 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 21 Feb 2025 19:25:03 -0500 Subject: [PATCH 0438/1190] A few cleanups in qt_settingsstoragecontrollers.cpp --- src/qt/qt_settingsstoragecontrollers.cpp | 47 +++++++++++++----------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index a86362909..4adfe1546 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -52,8 +52,8 @@ void SettingsStorageControllers::save() { /* Storage devices category */ - for (int i = 0; i < SCSI_CARD_MAX; ++i) { - auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); + for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { + QComboBox *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); scsi_card_current[i] = cbox->currentData().toInt(); } hdc_current[0] = ui->comboBoxHD->currentData().toInt(); @@ -71,10 +71,11 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) this->machineId = machineId; /*HD controller config*/ + int c = 0; auto *model = ui->comboBoxHD->model(); auto removeRows = model->rowCount(); - int c = 0; int selectedRow = 0; + while (true) { /* Skip "internal" if machine doesn't have it. */ if ((c == 1) && (machine_has_flags(machineId, MACHINE_HDC) == 0)) { @@ -88,7 +89,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) } if (hdc_available(c)) { - auto *hdc_dev = hdc_get_device(c); + const device_t *hdc_dev = hdc_get_device(c); if (device_is_valid(hdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); @@ -124,7 +125,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) } if (fdc_card_available(c)) { - auto *fdc_dev = fdc_card_getdevice(c); + const device_t *fdc_dev = fdc_card_getdevice(c); if (device_is_valid(fdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); @@ -141,10 +142,11 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->comboBoxFD->setCurrentIndex(selectedRow); /*CD interface controller config*/ - model = ui->comboBoxCDInterface->model(); - removeRows = model->rowCount(); - c = 0; + c = 0; + model = ui->comboBoxCDInterface->model(); + removeRows = model->rowCount(); selectedRow = 0; + while (true) { /* Skip "internal" if machine doesn't have it. */ QString name = DeviceConfig::DeviceName(cdrom_interface_get_device(c), cdrom_interface_get_internal_name(c), 1); @@ -153,7 +155,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) } if (cdrom_interface_available(c)) { - auto *cdrom_interface_dev = cdrom_interface_get_device(c); + const device_t *cdrom_interface_dev = cdrom_interface_get_device(c); if (device_is_valid(cdrom_interface_dev, machineId)) { int row = Models::AddEntry(model, name, c); @@ -169,21 +171,21 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->comboBoxCDInterface->setCurrentIndex(-1); ui->comboBoxCDInterface->setCurrentIndex(selectedRow); - for (int i = 0; i < SCSI_CARD_MAX; ++i) { - auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); - model = cbox->model(); - removeRows = model->rowCount(); - c = 0; - selectedRow = 0; + for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { + QComboBox *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); + c = 0; + model = cbox->model(); + removeRows = model->rowCount(); + selectedRow = 0; while (true) { - auto name = DeviceConfig::DeviceName(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1); + QString name = DeviceConfig::DeviceName(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1); if (name.isEmpty()) { break; } if (scsi_card_available(c)) { - auto *scsi_dev = scsi_card_getdevice(c); + const device_t *scsi_dev = scsi_card_getdevice(c); if (device_is_valid(scsi_dev, machineId)) { int row = Models::AddEntry(model, name, c); if (c == scsi_card_current[i]) { @@ -236,7 +238,8 @@ SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0); } -void SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index) +void +SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index) { if (index < 0) { return; @@ -346,14 +349,14 @@ SettingsStorageControllers::on_pushButtonSCSI4_clicked() DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1) +void +SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1) { ui->pushButtonConfigureLbaEnhancer->setEnabled(arg1 != 0); } - -void SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked() +void +SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked() { DeviceConfig::ConfigureDevice(&lba_enhancer_device); } - From fc639750ac91c48873219d167934f923bcd90b83 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 21 Feb 2025 20:02:28 -0500 Subject: [PATCH 0439/1190] Fix three warnings --- src/cdrom/cdrom.c | 2 +- src/scsi/scsi_cdrom.c | 2 +- src/video/vid_ps55da2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 8ebcfea1f..aea1afb94 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1159,7 +1159,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); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 04c6532df..cc9cc40c1 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -373,7 +373,7 @@ scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) if (fp) { if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp) != 0x10) log_fatal(dev->log, "scsi_cdrom_mode_sense_load(): Error reading data\n"); - (void) fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, + (void) !fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, 0x10, fp); fclose(fp); } diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 823ef4d2f..db2035717 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -3101,7 +3101,7 @@ da2_loadfont(char *fname, void *p) } uint32_t j = 0; while (ftell(mfile) < fsize) { - fread(&buf, sizeof(uint8_t), 1, mfile); + (void) !fread(&buf, sizeof(uint8_t), 1, mfile); da2->mmio.font[j] = buf; j++; } From 6b6e7b404b4b6400c3e1fef523a2c8a21e45dfc2 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 5 Jul 2024 19:15:49 -0400 Subject: [PATCH 0440/1190] Less magic numbers in via_vt82c49x.c --- src/chipset/via_vt82c49x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chipset/via_vt82c49x.c b/src/chipset/via_vt82c49x.c index 3aaef55a6..f8a5bb593 100644 --- a/src/chipset/via_vt82c49x.c +++ b/src/chipset/via_vt82c49x.c @@ -275,8 +275,8 @@ vt82c49x_write(uint16_t addr, uint8_t val, void *priv) case 0x71: if (dev->has_ide) { ide_pri_disable(); - ide_set_base(0, (val & 0x40) ? 0x170 : 0x1f0); - ide_set_side(0, (val & 0x40) ? 0x376 : 0x3f6); + ide_set_base(0, (val & 0x40) ? HDC_SECONDARY_BASE : HDC_PRIMARY_BASE); + ide_set_side(0, (val & 0x40) ? HDC_SECONDARY_SIDE : HDC_PRIMARY_SIDE); if (val & 0x01) ide_pri_enable(); vt82c49x_log("VT82C496 IDE now %sabled as %sary\n", (val & 0x01) ? "en" : "dis", From bb155ea9ef9c575e90f4708c43c9ad0c09005029 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 29 Dec 2023 23:00:13 -0500 Subject: [PATCH 0441/1190] Cleanups in vid_s3_virge.c --- src/video/vid_s3_virge.c | 1595 +++++++++++++++++++------------------- 1 file changed, 813 insertions(+), 782 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 904d4a4cf..cc0985c02 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -53,10 +53,10 @@ static uint64_t virge_time = 0; static int dither[4][4] = { - {0, 4, 1, 5}, - {6, 2, 7, 3}, - {1, 5, 0, 4}, - {7, 3, 6, 2} + { 0, 4, 1, 5 }, + { 6, 2, 7, 3 }, + { 1, 5, 0, 4 }, + { 7, 3, 6, 2 } }; #define ROM_VIRGE_325 "roms/video/s3virge/86c325.bin" @@ -112,80 +112,80 @@ enum { }; enum { - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), FIFO_WRITE_DWORD = (0x03 << 24) }; typedef struct { - uint32_t addr_type; - uint32_t val; + uint32_t addr_type; + uint32_t val; } fifo_entry_t; typedef struct s3d_t { - uint32_t cmd_set; - int clip_l; - int clip_r; - int clip_t; - int clip_b; + uint32_t cmd_set; + int clip_l; + int clip_r; + int clip_t; + int clip_b; - uint32_t dest_base; - uint32_t dest_str; + uint32_t dest_base; + uint32_t dest_str; - uint32_t z_base; - uint32_t z_str; + uint32_t z_base; + uint32_t z_str; - uint32_t tex_base; - uint32_t tex_bdr_clr; - uint32_t tbv; - uint32_t tbu; - int32_t TdVdX; - int32_t TdUdX; - int32_t TdVdY; - int32_t TdUdY; - uint32_t tus; - uint32_t tvs; + uint32_t tex_base; + uint32_t tex_bdr_clr; + uint32_t tbv; + uint32_t tbu; + int32_t TdVdX; + int32_t TdUdX; + int32_t TdVdY; + int32_t TdUdY; + uint32_t tus; + uint32_t tvs; - int32_t TdZdX; - int32_t TdZdY; - uint32_t tzs; + int32_t TdZdX; + int32_t TdZdY; + uint32_t tzs; - int32_t TdWdX; - int32_t TdWdY; - uint32_t tws; + int32_t TdWdX; + int32_t TdWdY; + uint32_t tws; - int32_t TdDdX; - int32_t TdDdY; - uint32_t tds; + int32_t TdDdX; + int32_t TdDdY; + uint32_t tds; - int16_t TdGdX; - int16_t TdBdX; - int16_t TdRdX; - int16_t TdAdX; - int16_t TdGdY; - int16_t TdBdY; - int16_t TdRdY; - int16_t TdAdY; - uint32_t tgs; - uint32_t tbs; - uint32_t trs; - uint32_t tas; + int16_t TdGdX; + int16_t TdBdX; + int16_t TdRdX; + int16_t TdAdX; + int16_t TdGdY; + int16_t TdBdY; + int16_t TdRdY; + int16_t TdAdY; + uint32_t tgs; + uint32_t tbs; + uint32_t trs; + uint32_t tas; - uint32_t TdXdY12; - uint32_t txend12; - uint32_t TdXdY01; - uint32_t txend01; - uint32_t TdXdY02; - uint32_t txs; - uint32_t tys; - int ty01; - int ty12; - int tlr; + uint32_t TdXdY12; + uint32_t txend12; + uint32_t TdXdY01; + uint32_t txend01; + uint32_t TdXdY02; + uint32_t txs; + uint32_t tys; + int ty01; + int ty12; + int tlr; - uint8_t fog_r; - uint8_t fog_g; - uint8_t fog_b; + uint8_t fog_r; + uint8_t fog_g; + uint8_t fog_b; } s3d_t; typedef struct virge_t { @@ -193,41 +193,41 @@ typedef struct virge_t { mem_mapping_t mmio_mapping; mem_mapping_t new_mmio_mapping; - rom_t bios_rom; + rom_t bios_rom; - svga_t svga; + svga_t svga; - uint8_t bank; - uint8_t ma_ext; + uint8_t bank; + uint8_t ma_ext; - uint8_t virge_id; - uint8_t virge_id_high; - uint8_t virge_id_low; - uint8_t virge_rev; + uint8_t virge_id; + uint8_t virge_id_high; + uint8_t virge_id_low; + uint8_t virge_rev; - uint32_t linear_base; - uint32_t linear_size; + uint32_t linear_base; + uint32_t linear_size; - uint8_t pci_regs[256]; - uint8_t pci_slot; + uint8_t pci_regs[256]; + uint8_t pci_slot; - int chip; + int chip; - int bilinear_enabled; - int dithering_enabled; - int memory_size; + int bilinear_enabled; + int dithering_enabled; + int memory_size; - int pixel_count; - int tri_count; + int pixel_count; + int tri_count; - thread_t * render_thread; - event_t * wake_render_thread; - event_t * wake_main_thread; - event_t * not_full_event; + thread_t *render_thread; + event_t *wake_render_thread; + event_t *wake_main_thread; + event_t *not_full_event; - uint32_t hwc_fg_col; - uint32_t hwc_bg_col; - int hwc_col_stack_pos; + uint32_t hwc_fg_col; + uint32_t hwc_bg_col; + int hwc_col_stack_pos; struct { uint32_t src_base; @@ -260,13 +260,13 @@ typedef struct virge_t { int lycnt; int line_dir; - int src_x; - int src_y; - int dest_x; - int dest_y; - int w; - int h; - uint8_t rop; + int src_x; + int src_y; + int dest_x; + int dest_y; + int w; + int h; + uint8_t rop; int data_left_count; uint32_t data_left; @@ -282,15 +282,16 @@ typedef struct virge_t { uint32_t plxstart; uint32_t pystart; uint32_t pycnt; - uint32_t dest_l, dest_r; + uint32_t dest_l; + uint32_t dest_r; } s3d; - s3d_t s3d_tri; + s3d_t s3d_tri; - s3d_t s3d_buffer[RB_SIZE]; - atomic_int s3d_read_idx; - atomic_int s3d_write_idx; - atomic_int s3d_busy; + s3d_t s3d_buffer[RB_SIZE]; + atomic_int s3d_read_idx; + atomic_int s3d_write_idx; + atomic_int s3d_busy; struct { uint32_t pri_ctrl; @@ -317,88 +318,89 @@ typedef struct virge_t { uint32_t sec_start; uint32_t sec_size; - int sdif; + int sdif; - int pri_x; - int pri_y; - int pri_w; - int pri_h; - int sec_x; - int sec_y; - int sec_w; - int sec_h; + int pri_x; + int pri_y; + int pri_w; + int pri_h; + int sec_x; + int sec_y; + int sec_w; + int sec_h; } streams; fifo_entry_t fifo[FIFO_SIZE]; atomic_int fifo_read_idx, fifo_write_idx; atomic_int fifo_thread_run, render_thread_run; - thread_t * fifo_thread; - event_t *wake_fifo_thread; - event_t * fifo_not_full_event; + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; - atomic_int virge_busy; - atomic_uint irq_pending; + atomic_int virge_busy; + atomic_uint irq_pending; - uint8_t subsys_stat; - uint8_t subsys_cntl; + uint8_t subsys_stat; + uint8_t subsys_cntl; - int local; + int local; - uint8_t serialport; + uint8_t serialport; - uint8_t irq_state; - uint8_t advfunc_cntl; + uint8_t irq_state; + uint8_t advfunc_cntl; - void *i2c, *ddc; + void *i2c, *ddc; - int onboard; - int fifo_slots_num; + int onboard; + int fifo_slots_num; - uint32_t vram_mask; + uint32_t vram_mask; - uint8_t reg6b; - uint8_t lfb_bios; - uint8_t int_line; - uint8_t cmd_dma; + uint8_t reg6b; + uint8_t lfb_bios; + uint8_t int_line; + uint8_t cmd_dma; - uint32_t cmd_dma_base; - uint32_t cmd_dma_buf_size; - uint32_t cmd_dma_buf_size_mask; - uint32_t cmd_base_addr; - uint32_t cmd_dma_write_ptr_reg; - uint32_t cmd_dma_write_ptr_update; - uint32_t cmd_dma_read_ptr_reg; - uint32_t dma_val; - uint32_t dma_dbl_words; - uint32_t dma_mmio_addr; - uint32_t dma_data_type; + uint32_t cmd_dma_base; + uint32_t cmd_dma_buf_size; + uint32_t cmd_dma_buf_size_mask; + uint32_t cmd_base_addr; + uint32_t cmd_dma_write_ptr_reg; + uint32_t cmd_dma_write_ptr_update; + uint32_t cmd_dma_read_ptr_reg; + uint32_t dma_val; + uint32_t dma_dbl_words; + uint32_t dma_mmio_addr; + uint32_t dma_data_type; - int pci; - int is_agp; + int pci; + int is_agp; - pc_timer_t irq_timer; + pc_timer_t irq_timer; } virge_t; static __inline void -wake_fifo_thread(virge_t *virge) { +wake_fifo_thread(virge_t *virge) +{ /* Wake up FIFO thread if moving from idle */ thread_set_event(virge->wake_fifo_thread); } -static virge_t *reset_state = NULL; +static virge_t *reset_state = NULL; static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; static video_timings_t timing_diamond_stealth3d_3000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; static video_timings_t timing_virge_dx_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; static video_timings_t timing_virge_agp = { .type = VIDEO_AGP, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; -static void queue_triangle(virge_t *virge); +static void queue_triangle(virge_t *virge); -static void s3_virge_recalctimings(svga_t *svga); -static void s3_virge_updatemapping(virge_t *virge); +static void s3_virge_recalctimings(svga_t *svga); +static void s3_virge_updatemapping(virge_t *virge); -static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); +static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); static uint8_t s3_virge_mmio_read(uint32_t addr, void *priv); static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *priv); @@ -407,33 +409,33 @@ static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv); static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv); static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv); -static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type); +static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type); enum { - CMD_SET_AE = 1, - CMD_SET_HC = (1 << 1), + CMD_SET_AE = 1, + CMD_SET_HC = (1 << 1), - CMD_SET_FORMAT_MASK = (7 << 2), - CMD_SET_FORMAT_8 = (0 << 2), - CMD_SET_FORMAT_16 = (1 << 2), - CMD_SET_FORMAT_24 = (2 << 2), + CMD_SET_FORMAT_MASK = (7 << 2), + CMD_SET_FORMAT_8 = (0 << 2), + CMD_SET_FORMAT_16 = (1 << 2), + CMD_SET_FORMAT_24 = (2 << 2), - CMD_SET_MS = (1 << 6), - CMD_SET_IDS = (1 << 7), - CMD_SET_MP = (1 << 8), - CMD_SET_TP = (1 << 9), + CMD_SET_MS = (1 << 6), + CMD_SET_IDS = (1 << 7), + CMD_SET_MP = (1 << 8), + CMD_SET_TP = (1 << 9), - CMD_SET_ITA_MASK = (3 << 10), - CMD_SET_ITA_BYTE = (0 << 10), - CMD_SET_ITA_WORD = (1 << 10), - CMD_SET_ITA_DWORD = (2 << 10), + CMD_SET_ITA_MASK = (3 << 10), + CMD_SET_ITA_BYTE = (0 << 10), + CMD_SET_ITA_WORD = (1 << 10), + CMD_SET_ITA_DWORD = (2 << 10), - CMD_SET_ZUP = (1 << 23), + CMD_SET_ZUP = (1 << 23), - CMD_SET_ZB_MODE = (3 << 24), + CMD_SET_ZB_MODE = (3 << 24), - CMD_SET_XP = (1 << 25), - CMD_SET_YP = (1 << 26), + CMD_SET_XP = (1 << 25), + CMD_SET_YP = (1 << 26), CMD_SET_COMMAND_MASK = (15 << 27) }; @@ -444,11 +446,11 @@ enum { #define CMD_SET_TWE (1 << 26) enum { - CMD_SET_COMMAND_BITBLT = (0 << 27), - CMD_SET_COMMAND_RECTFILL = (2 << 27), - CMD_SET_COMMAND_LINE = (3 << 27), - CMD_SET_COMMAND_POLY = (5 << 27), - CMD_SET_COMMAND_NOP = (15 << 27) + CMD_SET_COMMAND_BITBLT = (0 << 27), + CMD_SET_COMMAND_RECTFILL = (2 << 27), + CMD_SET_COMMAND_LINE = (3 << 27), + CMD_SET_COMMAND_POLY = (5 << 27), + CMD_SET_COMMAND_NOP = (15 << 27) }; #define INT_VSY (1 << 0) @@ -475,7 +477,7 @@ s3_virge_update_irqs(virge_t *virge) } static void -s3_virge_update_irq_timer(void* priv) +s3_virge_update_irq_timer(void *priv) { virge_t *virge = (virge_t *) priv; @@ -491,7 +493,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { virge_t *virge = (virge_t *) priv; - svga_t * svga = &virge->svga; + svga_t *svga = &virge->svga; uint8_t old; uint32_t cursoraddr; @@ -538,7 +540,7 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - old = svga->crtc[svga->crtcreg]; + old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; switch (svga->crtcreg) { @@ -622,7 +624,7 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) switch (virge->hwc_col_stack_pos) { case 0: virge->hwc_bg_col = (virge->hwc_bg_col & 0xffff00) | val; - break; + break; case 1: virge->hwc_bg_col = (virge->hwc_bg_col & 0xff00ff) | (val << 8); break; @@ -705,9 +707,10 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) } static uint8_t -s3_virge_in(uint16_t addr, void *priv) { +s3_virge_in(uint16_t addr, void *priv) +{ virge_t *virge = (virge_t *) priv; - svga_t * svga = &virge->svga; + svga_t *svga = &virge->svga; uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) @@ -758,7 +761,7 @@ s3_virge_in(uint16_t addr, void *priv) { break; case 0x45: virge->hwc_col_stack_pos = 0; - ret = svga->crtc[0x45]; + ret = svga->crtc[0x45]; break; case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); @@ -812,8 +815,10 @@ s3_virge_in(uint16_t addr, void *priv) { static void s3_virge_recalctimings(svga_t *svga) { - int n, r, m; - double freq; + int n; + int r; + int m; + double freq; virge_t *virge = (virge_t *) svga->priv; svga->hdisp = svga->hdisp_old; @@ -857,7 +862,7 @@ s3_virge_recalctimings(svga_t *svga) else r = (svga->seqregs[0x12] >> 5) & 0x03; - m = svga->seqregs[0x13] & 0x7f; + m = svga->seqregs[0x13] & 0x7f; freq = (((double) m + 2) / (((double) n + 2) * (double) (1 << r))) * 14318184.0; svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; @@ -876,7 +881,7 @@ s3_virge_recalctimings(svga_t *svga) svga->vblankstart = svga->dispend; video_force_resize_set_monitor(1, svga->monitor_index); } else { - svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | (((svga->crtc[0x5d] & 0x08) >> 3) << 6); @@ -894,39 +899,39 @@ s3_virge_recalctimings(svga_t *svga) svga->rowoffset = 256; svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; - case 16: - svga->render = svga_render_16bpp_highres; - if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; - case 24: - svga->render = svga_render_24bpp_highres; - if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) - svga->rowoffset = (svga->rowoffset * 3) >> 2; /*Hack*/ - break; - case 32: - svga->render = svga_render_32bpp_highres; - break; + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } + break; + case 16: + svga->render = svga_render_16bpp_highres; + if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } + break; + case 24: + svga->render = svga_render_24bpp_highres; + if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) + svga->rowoffset = (svga->rowoffset * 3) >> 2; /*Hack*/ + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; - default: - break; - } + default: + break; + } - svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && - (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; + svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; } else { /*Streams mode*/ if (virge->chip < S3_VIRGEGX2) { if (virge->streams.buffer_ctrl & 1) @@ -960,7 +965,7 @@ s3_virge_recalctimings(svga_t *svga) else svga->overlay.addr = virge->streams.sec_fb0; - svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.ena = (svga->overlay.x >= 0); svga->overlay.h_acc = virge->streams.dda_horiz_accumulator; svga->overlay.v_acc = virge->streams.dda_vert_accumulator; @@ -968,8 +973,7 @@ s3_virge_recalctimings(svga_t *svga) svga->rowoffset = virge->streams.pri_stride >> 3; if (virge->chip <= S3_VIRGEDX && svga->overlay.ena) { - svga->overlay.ena = (((virge->streams.blend_ctrl >> 24) & 7) == 0b000) || - (((virge->streams.blend_ctrl >> 24) & 7) == 0b101); + svga->overlay.ena = (((virge->streams.blend_ctrl >> 24) & 7) == 0b000) || (((virge->streams.blend_ctrl >> 24) & 7) == 0b101); } else if (virge->chip >= S3_VIRGEGX2 && svga->overlay.ena) { /* 0x20 = Secondary Stream enabled */ /* 0x2000 = Primary Stream enabled */ @@ -1028,7 +1032,8 @@ s3_virge_recalctimings(svga_t *svga) } static void -s3_virge_updatemapping(virge_t *virge) { +s3_virge_updatemapping(virge_t *virge) +{ svga_t *svga = &virge->svga; if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { @@ -1040,7 +1045,7 @@ s3_virge_updatemapping(virge_t *virge) { } switch (svga->gdcreg[6] & 0xc) { /*Banked framebuffer*/ - case 0x0: /*128k at A0000*/ + case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; @@ -1114,7 +1119,8 @@ s3_virge_updatemapping(virge_t *virge) { } static void -s3_virge_vblank_start(svga_t *svga) { +s3_virge_vblank_start(svga_t *svga) +{ virge_t *virge = (virge_t *) svga->priv; if (virge->irq_pending) @@ -1124,7 +1130,8 @@ s3_virge_vblank_start(svga_t *svga) { } static void -s3_virge_wait_fifo_idle(virge_t *virge) { +s3_virge_wait_fifo_idle(virge_t *virge) +{ while (!FIFO_EMPTY) { wake_fifo_thread(virge); thread_wait_event(virge->fifo_not_full_event, 1); @@ -1135,7 +1142,7 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *priv) { virge_t *virge = (virge_t *) priv; - uint8_t ret; + uint8_t ret; switch (addr & 0xffff) { case 0x8504: @@ -1216,9 +1223,10 @@ s3_virge_mmio_read_w(uint32_t addr, void *priv) } static uint32_t -s3_virge_mmio_read_l(uint32_t addr, void *priv) { +s3_virge_mmio_read_l(uint32_t addr, void *priv) +{ virge_t *virge = (virge_t *) priv; - uint32_t ret = 0xffffffff; + uint32_t ret = 0xffffffff; switch (addr & 0xfffc) { case 0x8180: @@ -1447,7 +1455,7 @@ s3_virge_mmio_read_l(uint32_t addr, void *priv) { break; } - //pclog("MMIO ReadL=%04x, ret=%08x.\n", addr & 0xfffc, ret); + // pclog("MMIO ReadL=%04x, ret=%08x.\n", addr & 0xfffc, ret); return ret; } @@ -1461,15 +1469,15 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) int y = (addr >> 3) & 7; int color; int byte; - uint32_t newaddr = addr; - virge->s3d.pattern_8[y * 8 + x] = val & 0xff; + uint32_t newaddr = addr; + virge->s3d.pattern_8[y * 8 + x] = val & 0xff; virge->s3d.pattern_8[y * 8 + x + 1] = val >> 8; virge->s3d.pattern_8[y * 8 + x + 2] = val >> 16; virge->s3d.pattern_8[y * 8 + x + 3] = val >> 24; - x = (addr >> 1) & 6; - y = (addr >> 4) & 7; - virge->s3d.pattern_16[y * 8 + x] = val & 0xffff; + x = (addr >> 1) & 6; + y = (addr >> 4) & 7; + virge->s3d.pattern_16[y * 8 + x] = val & 0xffff; virge->s3d.pattern_16[y * 8 + x + 1] = val >> 16; newaddr &= 0x00ff; @@ -1482,22 +1490,21 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) virge->s3d.pattern_24[y * 8 + x] |= ((val >> byte) & 0xff) << color; } - x = (addr >> 2) & 7; - y = (addr >> 5) & 7; + x = (addr >> 2) & 7; + y = (addr >> 5) & 7; virge->s3d.pattern_32[y * 8 + x] = val & 0xffffff; - } break; + } + break; case 0xa4d4: case 0xa8d4: case 0xacd4: - virge->s3d.src_base = val & ((virge->memory_size == 8) ? - (val & 0x7ffff8) : (val & 0x3ffff8)); + virge->s3d.src_base = val & ((virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8)); break; case 0xa4d8: case 0xa8d8: case 0xacd8: - virge->s3d.dest_base = val & ((virge->memory_size == 8) ? - (val & 0x7ffff8) : (val & 0x3ffff8)); + virge->s3d.dest_base = val & ((virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8)); break; case 0xa4dc: case 0xa8dc: @@ -1515,7 +1522,7 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) case 0xa8e4: case 0xace4: virge->s3d.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; + virge->s3d.src_str = val & 0xff8; break; case 0xa4e8: case 0xace8: @@ -1548,7 +1555,7 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) s3_virge_bitblt(virge, -1, 0); break; case 0xa504: - virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_width = (val >> 16) & 0x7ff; virge->s3d.r_height = val & 0x7ff; break; case 0xa508: @@ -1566,7 +1573,7 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) virge->s3d.lxend1 = val & 0x7ff; break; case 0xa970: - virge->s3d.ldx = (int32_t)val; + virge->s3d.ldx = (int32_t) val; break; case 0xa974: virge->s3d.lxstart = val; @@ -1575,7 +1582,7 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) virge->s3d.lystart = val & 0x7ff; break; case 0xa97c: - virge->s3d.lycnt = val & 0x7ff; + virge->s3d.lycnt = val & 0x7ff; virge->s3d.line_dir = val >> 31; if (virge->s3d.cmd_set & CMD_SET_AE) s3_virge_bitblt(virge, -1, 0); @@ -1604,13 +1611,11 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) case 0xb0d4: case 0xb4d4: - virge->s3d_tri.z_base = val & ((virge->memory_size == 8) ? - (val & 0x7ffff8) : (val & 0x3ffff8)); + virge->s3d_tri.z_base = val & ((virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8)); break; case 0xb0d8: case 0xb4d8: - virge->s3d_tri.dest_base = val & ((virge->memory_size == 8) ? - (val & 0x7ffff8) : (val & 0x3ffff8)); + virge->s3d_tri.dest_base = val & ((virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8)); break; case 0xb0dc: case 0xb4dc: @@ -1625,15 +1630,14 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) case 0xb0e4: case 0xb4e4: virge->s3d_tri.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; + virge->s3d.src_str = val & 0xff8; break; case 0xb0e8: case 0xb4e8: virge->s3d_tri.z_str = val & 0xff8; break; case 0xb4ec: - virge->s3d_tri.tex_base = val & ((virge->memory_size == 8) ? - (val & 0x7ffff8) : (val & 0x3ffff8)); + virge->s3d_tri.tex_base = val & ((virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8)); break; case 0xb4f0: virge->s3d_tri.tex_bdr_clr = val & 0xffffff; @@ -1750,17 +1754,17 @@ s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) case 0xb57c: virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; virge->s3d_tri.ty12 = val & 0x7ff; - virge->s3d_tri.tlr = val >> 31; + virge->s3d_tri.tlr = val >> 31; if (virge->s3d_tri.cmd_set & CMD_SET_AE) queue_triangle(virge); - break; + break; } } static void fifo_thread(void *param) { - virge_t *virge = (virge_t *)param; + virge_t *virge = (virge_t *) param; while (virge->fifo_thread_run) { thread_set_event(virge->fifo_not_full_event); @@ -1768,10 +1772,10 @@ fifo_thread(void *param) thread_reset_event(virge->wake_fifo_thread); virge->virge_busy = 1; while (!FIFO_EMPTY) { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; + uint64_t start_time = plat_timer_read(); + uint64_t end_time; fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; - uint32_t val = fifo->val; + uint32_t val = fifo->val; switch (fifo->addr_type & FIFO_TYPE) { case FIFO_WRITE_BYTE: @@ -1811,7 +1815,7 @@ fifo_thread(void *param) virge->virge_busy = 0; virge->subsys_stat |= (INT_FIFO_EMP | INT_3DF_EMP); if (virge->cmd_dma) - virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); + virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); virge->irq_pending++; } @@ -1820,8 +1824,8 @@ fifo_thread(void *param) static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) { - fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; - int limit = 0; + fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; + int limit = 0; if (type == FIFO_WRITE_DWORD) { switch (addr & 0xfffc) { @@ -1848,7 +1852,7 @@ s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) } } - fifo->val = val; + fifo->val = val; fifo->addr_type = (addr & FIFO_ADDR) | type; virge->fifo_write_idx++; @@ -1924,7 +1928,7 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) virge->streams.chroma_ctrl = val; break; case 0x8190: - virge->streams.sec_ctrl = val; + virge->streams.sec_ctrl = val; virge->streams.dda_horiz_accumulator = val & 0xfff; if (val & 0x1000) virge->streams.dda_horiz_accumulator |= ~0xfff; @@ -1935,7 +1939,7 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) virge->streams.chroma_upper_bound = val; break; case 0x8198: - virge->streams.sec_filter = val; + virge->streams.sec_filter = val; virge->streams.k1_horiz_scale = val & 0x7ff; if (val & 0x800) virge->streams.k1_horiz_scale |= ~0x7ff; @@ -2015,29 +2019,29 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; case 0x81f0: virge->streams.pri_start = val; - virge->streams.pri_x = (val >> 16) & 0x7ff; - virge->streams.pri_y = val & 0x7ff; + virge->streams.pri_x = (val >> 16) & 0x7ff; + virge->streams.pri_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f4: virge->streams.pri_size = val; - virge->streams.pri_w = (val >> 16) & 0x7ff; - virge->streams.pri_h = val & 0x7ff; + virge->streams.pri_w = (val >> 16) & 0x7ff; + virge->streams.pri_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f8: virge->streams.sec_start = val; - virge->streams.sec_x = (val >> 16) & 0x7ff; - virge->streams.sec_y = val & 0x7ff; + virge->streams.sec_x = (val >> 16) & 0x7ff; + virge->streams.sec_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81fc: virge->streams.sec_size = val; - virge->streams.sec_w = (val >> 16) & 0x7ff; - virge->streams.sec_h = val & 0x7ff; + virge->streams.sec_w = (val >> 16) & 0x7ff; + virge->streams.sec_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; @@ -2054,23 +2058,23 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; case 0x8590: - virge->cmd_dma_base = val; - virge->cmd_dma_buf_size = (val & 2) ? 0x10000 : 0x1000; + virge->cmd_dma_base = val; + virge->cmd_dma_buf_size = (val & 2) ? 0x10000 : 0x1000; virge->cmd_dma_buf_size_mask = virge->cmd_dma_buf_size - 1; - virge->cmd_base_addr = (val & 2) ? (val & 0xffff0000) : (val & 0xfffff000); + virge->cmd_base_addr = (val & 2) ? (val & 0xffff0000) : (val & 0xfffff000); break; case 0x8594: virge->cmd_dma_write_ptr_update = val & (1 << 16); if (virge->cmd_dma_write_ptr_update) { virge->cmd_dma_write_ptr_reg = (virge->cmd_dma_buf_size == 0x10000) ? (val & 0xffff) : (val & 0xfff); - virge->dma_dbl_words = 0; - virge->dma_data_type = 0; - virge->dma_val = 0; + virge->dma_dbl_words = 0; + virge->dma_data_type = 0; + virge->dma_val = 0; if (virge->cmd_dma) { while (virge->cmd_dma_read_ptr_reg != virge->cmd_dma_write_ptr_reg) { virge->cmd_dma_write_ptr_update = 0; - dma_bm_read(virge->cmd_base_addr + virge->cmd_dma_read_ptr_reg, (uint8_t *)&virge->dma_val, 4, 4); + dma_bm_read(virge->cmd_base_addr + virge->cmd_dma_read_ptr_reg, (uint8_t *) &virge->dma_val, 4, 4); if (!virge->dma_dbl_words) { virge->dma_dbl_words = (virge->dma_val & 0xffff); virge->dma_data_type = !!(virge->dma_val & (1 << 31)); @@ -2094,9 +2098,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; case 0x859c: - virge->cmd_dma = val & 1; + virge->cmd_dma = val & 1; virge->cmd_dma_write_ptr_reg = 0; - virge->cmd_dma_read_ptr_reg = 0; + virge->cmd_dma_read_ptr_reg = 0; break; case 0xff20: @@ -2106,26 +2110,26 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) } } -#define READ(addr, val) \ - do { \ - switch (bpp) { \ - case 0: /*8 bpp*/ \ - val = vram[addr & virge->vram_mask]; \ - break; \ - case 1: /*16 bpp*/ \ - val = *(uint16_t *)&vram[addr & virge->vram_mask]; \ - break; \ - case 2: /*24 bpp*/ \ - val = (*(uint32_t *)&vram[addr & virge->vram_mask]) & 0xffffff; \ - break; \ - } \ +#define READ(addr, val) \ + do { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ + val = vram[addr & virge->vram_mask]; \ + break; \ + case 1: /*16 bpp*/ \ + val = *(uint16_t *) &vram[addr & virge->vram_mask]; \ + break; \ + case 2: /*24 bpp*/ \ + val = (*(uint32_t *) &vram[addr & virge->vram_mask]) & 0xffffff; \ + break; \ + } \ } while (0) -#define Z_READ(addr) *(uint16_t *)&vram[addr & virge->vram_mask] +#define Z_READ(addr) *(uint16_t *) &vram[addr & virge->vram_mask] -#define Z_WRITE(addr, val) \ - if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ - *(uint16_t *)&vram[addr & virge->vram_mask] = val +#define Z_WRITE(addr, val) \ + if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ + *(uint16_t *) &vram[addr & virge->vram_mask] = val #define CLIP(x, y) \ do { \ @@ -2174,12 +2178,12 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) else \ Zzb = Zs; \ break; \ - case 5: \ + case 5: \ if (Zs == Zzb) \ update = 0; \ else \ Zzb = Zs; \ - break; \ + break; \ case 6: \ if (Zs > Zzb) \ update = 0; \ @@ -2188,10 +2192,10 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; \ case 7: \ update = 1; \ - Zzb = Zs; \ + Zzb = Zs; \ break; \ } \ - } while (0) + } while (0) #define ROPMIX(R, D, P, S, out) \ { \ @@ -2967,7 +2971,11 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) } \ } -#define MIX() do { ROPMIX(virge->s3d.rop & 0xFF, dest, pattern, source, out); out &= 0xFFFFFF; } while (0) +#define MIX() \ + do { \ + ROPMIX(virge->s3d.rop & 0xFF, dest, pattern, source, out); \ + out &= 0xFFFFFF; \ + } while (0) #define WRITE(addr, val) \ do { \ @@ -2994,7 +3002,7 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) { - uint8_t *vram = virge->svga.vram; + uint8_t *vram = virge->svga.vram; uint32_t mono_pattern[64]; int count_mask; int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; @@ -3008,33 +3016,33 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) { case CMD_SET_FORMAT_8: - bpp = 0; - x_mul = 1; + bpp = 0; + x_mul = 1; cpu_dat_shift = 8; - pattern_data = virge->s3d.pattern_8; - src_fg_clr = virge->s3d.src_fg_clr & 0xff; - src_bg_clr = virge->s3d.src_bg_clr & 0xff; + pattern_data = virge->s3d.pattern_8; + src_fg_clr = virge->s3d.src_fg_clr & 0xff; + src_bg_clr = virge->s3d.src_bg_clr & 0xff; break; case CMD_SET_FORMAT_16: - bpp = 1; - x_mul = 2; + bpp = 1; + x_mul = 2; cpu_dat_shift = 16; - pattern_data = virge->s3d.pattern_16; - src_fg_clr = virge->s3d.src_fg_clr & 0xffff; - src_bg_clr = virge->s3d.src_bg_clr & 0xffff; + pattern_data = virge->s3d.pattern_16; + src_fg_clr = virge->s3d.src_fg_clr & 0xffff; + src_bg_clr = virge->s3d.src_bg_clr & 0xffff; break; case CMD_SET_FORMAT_24: default: - bpp = 2; - x_mul = 3; + bpp = 2; + x_mul = 3; cpu_dat_shift = 24; - pattern_data = virge->s3d.pattern_24; - src_fg_clr = virge->s3d.src_fg_clr; - src_bg_clr = virge->s3d.src_bg_clr; + pattern_data = virge->s3d.pattern_24; + src_fg_clr = virge->s3d.src_fg_clr; + src_bg_clr = virge->s3d.src_bg_clr; break; - } - if (virge->s3d.cmd_set & CMD_SET_MP) - pattern_data = mono_pattern; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + pattern_data = mono_pattern; switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) { case CMD_SET_ITA_BYTE: @@ -3052,16 +3060,16 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) int x; int y; for (y = 0; y < 4; y++) { - for (x = 0; x < 8; x++) { - if (virge->s3d.mono_pat_0 & (1 << (x + y * 8))) - mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr; - else - mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr; - if (virge->s3d.mono_pat_1 & (1 << (x + y * 8))) - mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr; - else - mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr; - } + for (x = 0; x < 8; x++) { + if (virge->s3d.mono_pat_0 & (1 << (x + y * 8))) + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr; + else + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr; + if (virge->s3d.mono_pat_1 & (1 << (x + y * 8))) + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr; + else + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr; + } } } switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) { @@ -3070,13 +3078,13 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) case CMD_SET_COMMAND_BITBLT: if (count == -1) { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; virge->s3d.data_left_count = 0; if (virge->s3d.cmd_set & CMD_SET_IDS) @@ -3092,8 +3100,8 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) uint32_t source = 0; uint32_t dest = 0; uint32_t pattern; - uint32_t out = 0; - int update = 1; + uint32_t out = 0; + int update = 1; switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) { case 0: @@ -3111,18 +3119,18 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) count -= (cpu_dat_shift - virge->s3d.data_left_count); virge->s3d.data_left_count = 0; if (count < cpu_dat_shift) { - virge->s3d.data_left = cpu_dat; + virge->s3d.data_left = cpu_dat; virge->s3d.data_left_count = count; - count = 0; + count = 0; } } else { source = cpu_dat; cpu_dat >>= cpu_dat_shift; count -= cpu_dat_shift; if (count < cpu_dat_shift) { - virge->s3d.data_left = cpu_dat; + virge->s3d.data_left = cpu_dat; virge->s3d.data_left_count = count; - count = 0; + count = 0; } } if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) @@ -3152,9 +3160,9 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.dest_x += x_inc; virge->s3d.dest_x &= 0x7ff; if (!virge->s3d.w) { - virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_x = virge->s3d.rsrc_x; virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; + virge->s3d.w = virge->s3d.r_width; virge->s3d.src_y += y_inc; virge->s3d.dest_y += y_inc; @@ -3182,23 +3190,22 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) case CMD_SET_COMMAND_RECTFILL: /*No source, pattern = pat_fg_clr*/ if (count == -1) { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; virge->s3d.dest_x = virge->s3d.rdest_x; virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; } while (count && virge->s3d.h) { - uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + - (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); uint32_t source = 0; uint32_t dest = 0; uint32_t pattern = virge->s3d.pat_fg_clr; uint32_t out = 0; - int update = 1; + int update = 1; CLIP(virge->s3d.dest_x, virge->s3d.dest_y); @@ -3215,9 +3222,9 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.dest_x += x_inc; virge->s3d.dest_x &= 0x7ff; if (!virge->s3d.w) { - virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_x = virge->s3d.rsrc_x; virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; + virge->s3d.w = virge->s3d.r_width; virge->s3d.src_y += y_inc; virge->s3d.dest_y += y_inc; @@ -3225,7 +3232,7 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) if (!virge->s3d.h) return; } else - virge->s3d.w--; + virge->s3d.w--; count--; } break; @@ -3234,8 +3241,8 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) if (count == -1) { virge->s3d.dest_x = virge->s3d.lxstart; virge->s3d.dest_y = virge->s3d.lystart; - virge->s3d.h = virge->s3d.lycnt; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.h = virge->s3d.lycnt; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; } while (virge->s3d.h) { int x; @@ -3262,8 +3269,8 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) uint32_t source = 0; uint32_t dest = 0; uint32_t pattern; - uint32_t out = 0; - int update = 1; + uint32_t out = 0; + int update = 1; if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && ((virge->s3d.line_dir && x < virge->s3d.lxend0) || @@ -3306,39 +3313,39 @@ skip_line: virge->s3d.dest_r = virge->s3d.prxstart; if (virge->s3d.pycnt & (1 << 29)) virge->s3d.dest_l = virge->s3d.plxstart; - virge->s3d.h = virge->s3d.pycnt & 0x7ff; + virge->s3d.h = virge->s3d.pycnt & 0x7ff; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; while (virge->s3d.h) { - int x = virge->s3d.dest_l >> 20; - int xend = virge->s3d.dest_r >> 20; - int y = virge->s3d.pystart & 0x7ff; - int xdir = (x < xend) ? 1 : -1; - do { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); - uint32_t source = 0; - uint32_t dest = 0; - uint32_t pattern; - uint32_t out = 0; - int update = 1; + int x = virge->s3d.dest_l >> 20; + int xend = virge->s3d.dest_r >> 20; + int y = virge->s3d.pystart & 0x7ff; + int xdir = (x < xend) ? 1 : -1; + do { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern; + uint32_t out = 0; + int update = 1; - CLIP(x, y); + CLIP(x, y); - if (update) { - READ(dest_addr, dest); - pattern = pattern_data[(y & 7) * 8 + (x & 7)]; + if (update) { + READ(dest_addr, dest); + pattern = pattern_data[(y & 7) * 8 + (x & 7)]; - MIX(); + MIX(); - WRITE(dest_addr, out); - } + WRITE(dest_addr, out); + } - x = (x + xdir) & 0x7ff; - } while (x != (xend + xdir)); + x = (x + xdir) & 0x7ff; + } while (x != (xend + xdir)); - virge->s3d.dest_l += virge->s3d.pldx; - virge->s3d.dest_r += virge->s3d.prdx; - virge->s3d.h--; - virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; + virge->s3d.dest_l += virge->s3d.pldx; + virge->s3d.dest_r += virge->s3d.prdx; + virge->s3d.h--; + virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; } break; @@ -3375,54 +3382,57 @@ skip_line: #define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) typedef struct rgba_t { - int r, g, b, a; + int r; + int g; + int b; + int a; } rgba_t; typedef struct s3d_state_t { - int32_t r; - int32_t g; - int32_t b; - int32_t a; - int32_t u; - int32_t v; - int32_t d; - int32_t w; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + int32_t u; + int32_t v; + int32_t d; + int32_t w; - int32_t base_r; - int32_t base_g; - int32_t base_b; - int32_t base_a; - int32_t base_u; - int32_t base_v; - int32_t base_d; - int32_t base_w; + int32_t base_r; + int32_t base_g; + int32_t base_b; + int32_t base_a; + int32_t base_u; + int32_t base_v; + int32_t base_d; + int32_t base_w; - uint32_t base_z; + uint32_t base_z; - uint32_t tbu; - uint32_t tbv; + uint32_t tbu; + uint32_t tbv; - uint32_t cmd_set; - int max_d; + uint32_t cmd_set; + int max_d; uint16_t *texture[10]; - uint32_t tex_bdr_clr; + uint32_t tex_bdr_clr; - int32_t x1; - int32_t x2; + int32_t x1; + int32_t x2; - int y; + int y; - rgba_t dest_rgba; + rgba_t dest_rgba; } s3d_state_t; typedef struct s3d_texture_state_t { - int level; - int texture_shift; + int level; + int texture_shift; - int32_t u; - int32_t v; + int32_t u; + int32_t v; } s3d_texture_state_t; static void (*tex_read)(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out); @@ -3436,7 +3446,8 @@ static int _x; static int _y; static void -tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { +tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); uint16_t val = state->texture[texture_state->level][offset]; @@ -3448,7 +3459,8 @@ tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out } static void -tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { +tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); uint16_t val = state->texture[texture_state->level][offset]; @@ -3463,7 +3475,8 @@ tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba } static void -tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { +tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); uint16_t val = state->texture[texture_state->level][offset]; @@ -3475,7 +3488,8 @@ tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out } static void -tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { +tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); uint16_t val = state->texture[texture_state->level][offset]; @@ -3490,7 +3504,8 @@ tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba } static void -tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { +tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; @@ -3502,7 +3517,8 @@ tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out } static void -tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { +tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; @@ -3517,19 +3533,21 @@ tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba } static void -tex_sample_normal(s3d_state_t *state) { +tex_sample_normal(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_normal_filter(s3d_state_t *state) { +tex_sample_normal_filter(s3d_state_t *state) +{ s3d_texture_state_t texture_state; int tex_offset; rgba_t tex_samples[4]; @@ -3537,9 +3555,9 @@ tex_sample_normal_filter(s3d_state_t *state) { int dv; int d[4]; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = state->u + state->tbu; texture_state.v = state->v + state->tbv; @@ -3575,21 +3593,23 @@ tex_sample_normal_filter(s3d_state_t *state) { } static void -tex_sample_mipmap(s3d_state_t *state) { +tex_sample_mipmap(s3d_state_t *state) +{ s3d_texture_state_t texture_state; texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_mipmap_filter(s3d_state_t *state) { +tex_sample_mipmap_filter(s3d_state_t *state) +{ s3d_texture_state_t texture_state; int tex_offset; rgba_t tex_samples[4]; @@ -3601,7 +3621,7 @@ tex_sample_mipmap_filter(s3d_state_t *state) { if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = state->u + state->tbu; texture_state.v = state->v + state->tbv; @@ -3637,25 +3657,27 @@ tex_sample_mipmap_filter(s3d_state_t *state) { } static void -tex_sample_persp_normal(s3d_state_t *state) { +tex_sample_persp_normal(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_normal_filter(s3d_state_t *state) { +tex_sample_persp_normal_filter(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -3665,14 +3687,14 @@ tex_sample_persp_normal_filter(s3d_state_t *state) { int d[4]; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -3708,25 +3730,27 @@ tex_sample_persp_normal_filter(s3d_state_t *state) { } static void -tex_sample_persp_normal_375(s3d_state_t *state) { +tex_sample_persp_normal_375(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_normal_filter_375(s3d_state_t *state) { +tex_sample_persp_normal_filter_375(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -3736,14 +3760,14 @@ tex_sample_persp_normal_filter_375(s3d_state_t *state) { int d[4]; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -3779,27 +3803,29 @@ tex_sample_persp_normal_filter_375(s3d_state_t *state) { } static void -tex_sample_persp_mipmap(s3d_state_t *state) { +tex_sample_persp_mipmap(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_mipmap_filter(s3d_state_t *state) { +tex_sample_persp_mipmap_filter(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -3809,16 +3835,16 @@ tex_sample_persp_mipmap_filter(s3d_state_t *state) { int d[4]; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -3854,27 +3880,29 @@ tex_sample_persp_mipmap_filter(s3d_state_t *state) { } static void -tex_sample_persp_mipmap_375(s3d_state_t *state) { +tex_sample_persp_mipmap_375(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_mipmap_filter_375(s3d_state_t *state) { +tex_sample_persp_mipmap_filter_375(s3d_state_t *state) +{ s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -3884,16 +3912,16 @@ tex_sample_persp_mipmap_filter_375(s3d_state_t *state) { int d[4]; if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -3928,40 +3956,41 @@ tex_sample_persp_mipmap_filter_375(s3d_state_t *state) { tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } -#define CLAMP(x) \ - do { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ } while (0) -#define CLAMP_RGBA(r, g, b, a) \ - if ((r) & ~0xff) \ - r = ((r) < 0) ? 0 : 0xff; \ - if ((g) & ~0xff) \ - g = ((g) < 0) ? 0 : 0xff; \ - if ((b) & ~0xff) \ - b = ((b) < 0) ? 0 : 0xff; \ - if ((a) & ~0xff) \ - a = ((a) < 0) ? 0 : 0xff; +#define CLAMP_RGBA(r, g, b, a) \ + if ((r) & ~0xff) \ + r = ((r) < 0) ? 0 : 0xff; \ + if ((g) & ~0xff) \ + g = ((g) < 0) ? 0 : 0xff; \ + if ((b) & ~0xff) \ + b = ((b) < 0) ? 0 : 0xff; \ + if ((a) & ~0xff) \ + a = ((a) < 0) ? 0 : 0xff; -#define CLAMP_RGB(r, g, b) \ - do { \ - if ((r) < 0) \ - r = 0; \ - if ((r) > 0xff) \ - r = 0xff; \ - if ((g) < 0) \ - g = 0; \ - if ((g) > 0xff) \ - g = 0xff; \ - if ((b) < 0) \ - b = 0; \ - if ((b) > 0xff) \ - b = 0xff; \ +#define CLAMP_RGB(r, g, b) \ + do { \ + if ((r) < 0) \ + r = 0; \ + if ((r) > 0xff) \ + r = 0xff; \ + if ((g) < 0) \ + g = 0; \ + if ((g) > 0xff) \ + g = 0xff; \ + if ((b) < 0) \ + b = 0; \ + if ((b) > 0xff) \ + b = 0xff; \ } while (0) static void -dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) { +dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) +{ state->dest_rgba.r = state->r >> 7; CLAMP(state->dest_rgba.r); @@ -3976,7 +4005,8 @@ dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) { } static void -dest_pixel_unlit_texture_triangle(s3d_state_t *state) { +dest_pixel_unlit_texture_triangle(s3d_state_t *state) +{ tex_sample(state); if (state->cmd_set & CMD_SET_ABC_SRC) @@ -3984,7 +4014,8 @@ dest_pixel_unlit_texture_triangle(s3d_state_t *state) { } static void -dest_pixel_lit_texture_decal(s3d_state_t *state) { +dest_pixel_lit_texture_decal(s3d_state_t *state) +{ tex_sample(state); if (state->cmd_set & CMD_SET_ABC_SRC) @@ -3992,7 +4023,8 @@ dest_pixel_lit_texture_decal(s3d_state_t *state) { } static void -dest_pixel_lit_texture_reflection(s3d_state_t *state) { +dest_pixel_lit_texture_reflection(s3d_state_t *state) +{ tex_sample(state); state->dest_rgba.r += (state->r >> 7); @@ -4005,7 +4037,8 @@ dest_pixel_lit_texture_reflection(s3d_state_t *state) { } static void -dest_pixel_lit_texture_modulate(s3d_state_t *state) { +dest_pixel_lit_texture_modulate(s3d_state_t *state) +{ int r = state->r >> 7; int g = state->g >> 7; int b = state->b >> 7; @@ -4024,17 +4057,18 @@ dest_pixel_lit_texture_modulate(s3d_state_t *state) { } static void -tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) { - uint8_t *vram = virge->svga.vram; - int x_dir = s3d_tri->tlr ? 1 : -1; - int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); - int y_count = yc; - int bpp = (s3d_tri->cmd_set >> 2) & 7; - uint32_t dest_offset; - uint32_t z_offset; +tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) +{ + uint8_t *vram = virge->svga.vram; + int x_dir = s3d_tri->tlr ? 1 : -1; + int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); + int y_count = yc; + int bpp = (s3d_tri->cmd_set >> 2) & 7; + uint32_t dest_offset; + uint32_t z_offset; dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); - z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); + z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); if (s3d_tri->cmd_set & CMD_SET_HC) { if (state->y < s3d_tri->clip_t) @@ -4054,195 +4088,190 @@ tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int state->base_a += (s3d_tri->TdAdY * diff_y); state->base_d += (s3d_tri->TdDdY * diff_y); state->base_w += (s3d_tri->TdWdY * diff_y); - state->x1 += (dx1 * diff_y); - state->x2 += (dx2 * diff_y); - state->y -= diff_y; - dest_offset -= s3d_tri->dest_str; - z_offset -= s3d_tri->z_str; - y_count -= diff_y; + state->x1 += (dx1 * diff_y); + state->x2 += (dx2 * diff_y); + state->y -= diff_y; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; + y_count -= diff_y; } if ((state->y - y_count) < s3d_tri->clip_t) y_count = (state->y - s3d_tri->clip_t) + 1; } for (; y_count > 0; y_count--) { - int x = (state->x1 + ((1 << 20) - 1)) >> 20; - int xe = (state->x2 + ((1 << 20) - 1)) >> 20; - uint32_t z = (state->base_z > 0) ? (state->base_z << 1) : 0; + int x = (state->x1 + ((1 << 20) - 1)) >> 20; + int xe = (state->x2 + ((1 << 20) - 1)) >> 20; + uint32_t z = (state->base_z > 0) ? (state->base_z << 1) : 0; - if (x_dir < 0) { - x--; - xe--; - } + if (x_dir < 0) { + x--; + xe--; + } - if (x != xe && ((x_dir > 0 && x < xe) || (x_dir < 0 && x > xe))) { - uint32_t dest_addr; - uint32_t z_addr; - int dx = (x_dir > 0) ? ((31 - ((state->x1 - 1) >> 15)) & 0x1f) : - (((state->x1 - 1) >> 15) & 0x1f); - int x_offset = x_dir * (bpp + 1); - int xz_offset = x_dir << 1; + if (x != xe && ((x_dir > 0 && x < xe) || (x_dir < 0 && x > xe))) { + uint32_t dest_addr; + uint32_t z_addr; + int dx = (x_dir > 0) ? ((31 - ((state->x1 - 1) >> 15)) & 0x1f) : (((state->x1 - 1) >> 15) & 0x1f); + int x_offset = x_dir * (bpp + 1); + int xz_offset = x_dir << 1; - if (x_dir > 0) - dx += 1; + if (x_dir > 0) + dx += 1; - state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); - state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); - state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); - state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); - state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); - state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); - state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); - state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); - z += ((s3d_tri->TdZdX * dx) >> 5); + state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); + state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); + state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); + state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); + state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); + state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); + state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); + state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); + z += ((s3d_tri->TdZdX * dx) >> 5); - if (s3d_tri->cmd_set & CMD_SET_HC) { - if (x_dir > 0) { - if (x > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - xe = s3d_tri->clip_r + 1; - if (x < s3d_tri->clip_l) { - int diff_x = s3d_tri->clip_l - x; + if (s3d_tri->cmd_set & CMD_SET_HC) { + if (x_dir > 0) { + if (x > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + xe = s3d_tri->clip_r + 1; + if (x < s3d_tri->clip_l) { + int diff_x = s3d_tri->clip_l - x; - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); - x = s3d_tri->clip_l; - } - } else { - if (x < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - xe = s3d_tri->clip_l - 1; - if (x > s3d_tri->clip_r) { - int diff_x = x - s3d_tri->clip_r; + x = s3d_tri->clip_l; + } + } else { + if (x < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + xe = s3d_tri->clip_l - 1; + if (x > s3d_tri->clip_r) { + int diff_x = x - s3d_tri->clip_r; - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); - x = s3d_tri->clip_r; - } - } - } + x = s3d_tri->clip_r; + } + } + } - virge->svga.changedvram[(dest_offset & virge->vram_mask) >> 12] = changeframecount; + virge->svga.changedvram[(dest_offset & virge->vram_mask) >> 12] = changeframecount; - dest_addr = dest_offset + (x * (bpp + 1)); - z_addr = z_offset + (x << 1); + dest_addr = dest_offset + (x * (bpp + 1)); + z_addr = z_offset + (x << 1); - x &= 0xfff; - xe &= 0xfff; + x &= 0xfff; + xe &= 0xfff; - for (; x != xe; x = (x + x_dir) & 0xfff) { - int update = 1; - uint16_t src_z = 0; + for (; x != xe; x = (x + x_dir) & 0xfff) { + int update = 1; + uint16_t src_z = 0; - _x = x; - _y = state->y; + _x = x; + _y = state->y; - if (use_z) { - src_z = Z_READ(z_addr); - Z_CLIP(src_z, z >> 16); - } + if (use_z) { + src_z = Z_READ(z_addr); + Z_CLIP(src_z, z >> 16); + } - if (update) { - uint32_t dest_col; + if (update) { + uint32_t dest_col; - dest_pixel(state); + dest_pixel(state); - if (s3d_tri->cmd_set & CMD_SET_FE) { - int a = state->a >> 7; - state->dest_rgba.r = ((state->dest_rgba.r * a) + (s3d_tri->fog_r * (255 - a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; - } + if (s3d_tri->cmd_set & CMD_SET_FE) { + int a = state->a >> 7; + state->dest_rgba.r = ((state->dest_rgba.r * a) + (s3d_tri->fog_r * (255 - a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; + } - if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) { - uint32_t src_col; - int src_r = 0; - uint32_t src_g = 0; - uint32_t src_b = 0; + if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) { + uint32_t src_col; + int src_r = 0; + uint32_t src_g = 0; + uint32_t src_b = 0; + switch (bpp) { + case 0: /*8 bpp*/ + /*Not implemented yet*/ + break; + case 1: /*16 bpp*/ + src_col = *(uint16_t *) &vram[dest_addr & virge->vram_mask]; + RGB15_TO_24(src_col, src_r, src_g, src_b); + break; + case 2: /*24 bpp*/ + src_col = (*(uint32_t *) &vram[dest_addr & virge->vram_mask]) & 0xffffff; + RGB24_TO_24(src_col, src_r, src_g, src_b); + break; + } - switch (bpp) { - case 0: /*8 bpp*/ - /*Not implemented yet*/ - break; - case 1: /*16 bpp*/ - src_col = *(uint16_t *)&vram[dest_addr & virge->vram_mask]; - RGB15_TO_24(src_col, src_r, src_g, src_b); - break; - case 2: /*24 bpp*/ - src_col = (*(uint32_t *)&vram[dest_addr & virge->vram_mask]) & 0xffffff; - RGB24_TO_24(src_col, src_r, src_g, src_b); - break; - } + state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255; + } - state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + - (src_r * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + - (src_g * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + - (src_b * (255 - state->dest_rgba.a))) / 255; - } + switch (bpp) { + case 0: /*8 bpp*/ + /*Not implemented yet*/ + break; + case 1: /*16 bpp*/ + RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); + *(uint16_t *) &vram[dest_addr] = dest_col; + break; + case 2: /*24 bpp*/ + dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); + *(uint8_t *) &vram[dest_addr] = dest_col & 0xff; + *(uint8_t *) &vram[dest_addr + 1] = (dest_col >> 8) & 0xff; + *(uint8_t *) &vram[dest_addr + 2] = (dest_col >> 16) & 0xff; + break; + } - switch (bpp) { - case 0: /*8 bpp*/ - /*Not implemented yet*/ - break; - case 1: /*16 bpp*/ - RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); - *(uint16_t *)&vram[dest_addr] = dest_col; - break; - case 2: /*24 bpp*/ - dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); - *(uint8_t *)&vram[dest_addr] = dest_col & 0xff; - *(uint8_t *)&vram[dest_addr + 1] = (dest_col >> 8) & 0xff; - *(uint8_t *)&vram[dest_addr + 2] = (dest_col >> 16) & 0xff; - break; - } + if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) + Z_WRITE(z_addr, src_z); + } - if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) - Z_WRITE(z_addr, src_z); - } - - z += s3d_tri->TdZdX; - state->u += s3d_tri->TdUdX; - state->v += s3d_tri->TdVdX; - state->r += s3d_tri->TdRdX; - state->g += s3d_tri->TdGdX; - state->b += s3d_tri->TdBdX; - state->a += s3d_tri->TdAdX; - state->d += s3d_tri->TdDdX; - state->w += s3d_tri->TdWdX; - dest_addr += x_offset; - z_addr += xz_offset; - virge->pixel_count++; - } + z += s3d_tri->TdZdX; + state->u += s3d_tri->TdUdX; + state->v += s3d_tri->TdVdX; + state->r += s3d_tri->TdRdX; + state->g += s3d_tri->TdGdX; + state->b += s3d_tri->TdBdX; + state->a += s3d_tri->TdAdX; + state->d += s3d_tri->TdDdX; + state->w += s3d_tri->TdWdX; + dest_addr += x_offset; + z_addr += xz_offset; + virge->pixel_count++; + } } tri_skip_line: - state->x1 += dx1; - state->x2 += dx2; + state->x1 += dx1; + state->x2 += dx2; state->base_u += s3d_tri->TdUdY; state->base_v += s3d_tri->TdVdY; state->base_z += s3d_tri->TdZdY; @@ -4253,22 +4282,23 @@ tri_skip_line: state->base_d += s3d_tri->TdDdY; state->base_w += s3d_tri->TdWdY; state->y--; - dest_offset -= s3d_tri->dest_str; - z_offset -= s3d_tri->z_str; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; } } -static int tex_size[8] = {4 * 2, 2 * 2, 2 * 2, 1 * 2, 2 / 1, 2 / 1, 1 * 2, 1 * 2}; +static int tex_size[8] = { 4 * 2, 2 * 2, 2 * 2, 1 * 2, 2 / 1, 2 / 1, 1 * 2, 1 * 2 }; static void -s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) { +s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) +{ s3d_state_t state; - uint32_t tex_base; - int c; + uint32_t tex_base; + int c; - uint64_t start_time = plat_timer_read(); - uint64_t end_time; + uint64_t start_time = plat_timer_read(); + uint64_t end_time; state.tbu = s3d_tri->tbu << 11; state.tbv = s3d_tri->tbv << 11; @@ -4282,18 +4312,18 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) { state.base_u = s3d_tri->tus; state.base_v = s3d_tri->tvs; state.base_z = s3d_tri->tzs; - state.base_r = (int32_t)s3d_tri->trs; - state.base_g = (int32_t)s3d_tri->tgs; - state.base_b = (int32_t)s3d_tri->tbs; - state.base_a = (int32_t)s3d_tri->tas; + state.base_r = (int32_t) s3d_tri->trs; + state.base_g = (int32_t) s3d_tri->tgs; + state.base_b = (int32_t) s3d_tri->tbs; + state.base_a = (int32_t) s3d_tri->tas; state.base_d = s3d_tri->tds; state.base_w = s3d_tri->tws; tex_base = s3d_tri->tex_base; for (c = 9; c >= 0; c--) { - state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base]; - if (c <= state.max_d) - tex_base += ((1 << (c * 2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; + state.texture[c] = (uint16_t *) &virge->svga.vram[tex_base]; + if (c <= state.max_d) + tex_base += ((1 << (c * 2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; } switch ((s3d_tri->cmd_set >> 27) & 0xf) { @@ -4407,7 +4437,7 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) { static void render_thread(void *param) { - virge_t *virge = (virge_t *)param; + virge_t *virge = (virge_t *) param; while (virge->render_thread_run) { thread_wait_event(virge->wake_render_thread, -1); @@ -4443,14 +4473,14 @@ queue_triangle(virge_t *virge) static void s3_virge_hwcursor_draw(svga_t *svga, int displine) { - virge_t *virge = (virge_t *) svga->priv; - int x; - uint16_t dat[2] = { 0, 0 }; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - uint32_t fg; - uint32_t bg; - uint32_t vram_mask = virge->vram_mask; + virge_t *virge = (virge_t *) svga->priv; + int x; + uint16_t dat[2] = { 0, 0 }; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + uint32_t fg; + uint32_t bg; + uint32_t vram_mask = virge->vram_mask; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -4568,22 +4598,22 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) CLAMP(b[x_write + 1]); \ \ x_write = (x_write + 2) & 7; \ - } \ + } \ } while (0) /*Both YUV formats are untested*/ #define DECODE_YUV211() \ do { \ uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR; \ - int dG; \ - int dB; \ + int8_t U, V; \ + int dR; \ + int dG; \ + int dB; \ \ - U = src[0] - 0x80; \ + U = src[0] - 0x80; \ y1 = (298 * (src[1] - 16)) >> 8; \ y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ + V = src[3] - 0x80; \ y3 = (298 * (src[4] - 16)) >> 8; \ y4 = (298 * (src[5] - 16)) >> 8; \ src += 6; \ @@ -4634,9 +4664,9 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) int dG; \ int dB; \ \ - U = src[0] - 0x80; \ + U = src[0] - 0x80; \ y1 = (298 * (src[1] - 16)) >> 8; \ - V = src[2] - 0x80; \ + V = src[2] - 0x80; \ y2 = (298 * (src[3] - 16)) >> 8; \ src += 4; \ \ @@ -4757,13 +4787,13 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) static void s3_virge_overlay_draw(svga_t *svga, int displine) { - virge_t *virge = (virge_t *) svga->priv; + virge_t *virge = (virge_t *) svga->priv; int offset; int r[8]; int g[8]; int b[8]; int x_size; - int x_read = 4; + int x_read = 4; int x_write = 4; int x; uint32_t *p; @@ -4774,7 +4804,7 @@ s3_virge_overlay_draw(svga_t *svga, int displine) else offset = virge->streams.sec_x + 1; - p = &((uint32_t *)buffer32->line[displine])[offset + svga->x_add]; + p = &((uint32_t *) buffer32->line[displine])[offset + svga->x_add]; if (virge->chip < S3_VIRGEGX2) { if ((offset + virge->streams.sec_w) > virge->streams.pri_w) @@ -5078,9 +5108,9 @@ s3_virge_disable_handlers(virge_t *dev) reset_state->svga.mapping = dev->svga.mapping; reset_state->bios_rom.mapping = dev->bios_rom.mapping; - reset_state->svga.timer = dev->svga.timer; - reset_state->svga.timer8514 = dev->svga.timer8514; - reset_state->irq_timer = dev->irq_timer; + reset_state->svga.timer = dev->svga.timer; + reset_state->svga.timer8514 = dev->svga.timer8514; + reset_state->irq_timer = dev->irq_timer; } static void @@ -5090,12 +5120,12 @@ s3_virge_reset(void *priv) if (reset_state != NULL) { s3_virge_disable_handlers(dev); - dev->virge_busy = 0; - dev->fifo_write_idx = 0; - dev->fifo_read_idx = 0; - dev->s3d_busy = 0; - dev->s3d_write_idx = 0; - dev->s3d_read_idx = 0; + dev->virge_busy = 0; + dev->fifo_write_idx = 0; + dev->fifo_read_idx = 0; + dev->s3d_busy = 0; + dev->s3d_write_idx = 0; + dev->s3d_read_idx = 0; reset_state->pci_slot = dev->pci_slot; *dev = *reset_state; @@ -5106,8 +5136,8 @@ static void * s3_virge_init(const device_t *info) { const char *bios_fn = NULL; - virge_t *virge = (virge_t *) calloc(1, sizeof(virge_t)); - reset_state = calloc(1, sizeof(virge_t)); + virge_t *virge = (virge_t *) calloc(1, sizeof(virge_t)); + reset_state = calloc(1, sizeof(virge_t)); virge->bilinear_enabled = device_get_config_int("bilinear"); virge->dithering_enabled = device_get_config_int("dithering"); @@ -5118,44 +5148,45 @@ s3_virge_init(const device_t *info) virge->onboard = !!(info->local & 0x100); - if (!virge->onboard) switch (info->local) { - case S3_VIRGE_325: - bios_fn = ROM_VIRGE_325; - break; - case S3_DIAMOND_STEALTH3D_2000: - bios_fn = ROM_DIAMOND_STEALTH3D_2000; - break; - case S3_MIROCRYSTAL_3D: - bios_fn = ROM_MIROCRYSTAL_3D; - break; - case S3_DIAMOND_STEALTH3D_3000: - bios_fn = ROM_DIAMOND_STEALTH3D_3000; - break; - case S3_STB_VELOCITY_3D: - bios_fn = ROM_STB_VELOCITY_3D; - break; - case S3_VIRGE_DX: - bios_fn = ROM_VIRGE_DX; - break; - case S3_DIAMOND_STEALTH3D_2000PRO: - bios_fn = ROM_DIAMOND_STEALTH3D_2000PRO; - break; - case S3_VIRGE_GX: - bios_fn = ROM_VIRGE_GX; - break; - case S3_VIRGE_GX2: - bios_fn = ROM_VIRGE_GX2; - break; - case S3_DIAMOND_STEALTH3D_4000: - bios_fn = ROM_DIAMOND_STEALTH3D_4000; - break; - case S3_TRIO_3D2X: - bios_fn = ROM_TRIO3D2X; - break; - default: - free(virge); - return NULL; - } + if (!virge->onboard) + switch (info->local) { + case S3_VIRGE_325: + bios_fn = ROM_VIRGE_325; + break; + case S3_DIAMOND_STEALTH3D_2000: + bios_fn = ROM_DIAMOND_STEALTH3D_2000; + break; + case S3_MIROCRYSTAL_3D: + bios_fn = ROM_MIROCRYSTAL_3D; + break; + case S3_DIAMOND_STEALTH3D_3000: + bios_fn = ROM_DIAMOND_STEALTH3D_3000; + break; + case S3_STB_VELOCITY_3D: + bios_fn = ROM_STB_VELOCITY_3D; + break; + case S3_VIRGE_DX: + bios_fn = ROM_VIRGE_DX; + break; + case S3_DIAMOND_STEALTH3D_2000PRO: + bios_fn = ROM_DIAMOND_STEALTH3D_2000PRO; + break; + case S3_VIRGE_GX: + bios_fn = ROM_VIRGE_GX; + break; + case S3_VIRGE_GX2: + bios_fn = ROM_VIRGE_GX2; + break; + case S3_DIAMOND_STEALTH3D_4000: + bios_fn = ROM_DIAMOND_STEALTH3D_4000; + break; + case S3_TRIO_3D2X: + bios_fn = ROM_TRIO3D2X; + break; + default: + free(virge); + return NULL; + } svga_init(info, &virge->svga, virge, virge->memory_size << 20, s3_virge_recalctimings, @@ -5223,7 +5254,7 @@ s3_virge_init(const device_t *info) case S3_VIRGE_325: case S3_DIAMOND_STEALTH3D_2000: case S3_MIROCRYSTAL_3D: - virge->fifo_slots_num = 8; + virge->fifo_slots_num = 8; virge->svga.decode_mask = (4 << 20) - 1; virge->virge_id_high = 0x56; virge->virge_id_low = 0x31; @@ -5233,7 +5264,7 @@ s3_virge_init(const device_t *info) break; case S3_DIAMOND_STEALTH3D_3000: case S3_STB_VELOCITY_3D: - virge->fifo_slots_num = 8; + virge->fifo_slots_num = 8; virge->svga.decode_mask = (8 << 20) - 1; virge->virge_id_high = 0x88; virge->virge_id_low = 0x3d; @@ -5243,7 +5274,7 @@ s3_virge_init(const device_t *info) break; case S3_VIRGE_GX2: case S3_DIAMOND_STEALTH3D_4000: - virge->fifo_slots_num = 16; + virge->fifo_slots_num = 16; virge->svga.decode_mask = (4 << 20) - 1; virge->virge_id_high = 0x8a; virge->virge_id_low = 0x10; @@ -5255,7 +5286,7 @@ s3_virge_init(const device_t *info) break; case S3_TRIO_3D2X: - virge->fifo_slots_num = 16; + virge->fifo_slots_num = 16; virge->svga.decode_mask = (8 << 20) - 1; virge->virge_id_high = 0x8a; virge->virge_id_low = 0x13; @@ -5272,7 +5303,7 @@ s3_virge_init(const device_t *info) fallthrough; default: - virge->fifo_slots_num = 8; + virge->fifo_slots_num = 8; virge->svga.decode_mask = (4 << 20) - 1; virge->virge_id_high = 0x8a; virge->virge_id_low = 0x01; @@ -5341,16 +5372,16 @@ s3_virge_init(const device_t *info) virge->svga.force_old_addr = 1; - virge->render_thread_run = 1; + virge->render_thread_run = 1; virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread = thread_create(render_thread, virge); - virge->fifo_thread_run = 1; - virge->wake_fifo_thread = thread_create_event(); + virge->fifo_thread_run = 1; + virge->wake_fifo_thread = thread_create_event(); virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); + virge->fifo_thread = thread_create(fifo_thread, virge); timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 1); @@ -5473,7 +5504,7 @@ s3_virge_force_redraw(void *priv) } static const device_config_t s3_virge_config[] = { - // clang-format off + // clang-format off { .name = "memory", .description = "Memory size", @@ -5509,11 +5540,11 @@ static const device_config_t s3_virge_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t s3_virge_stb_config[] = { - // clang-format off + // clang-format off { .name = "memory", .description = "Memory size", @@ -5550,11 +5581,11 @@ static const device_config_t s3_virge_stb_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t s3_virge_357_config[] = { - // clang-format off + // clang-format off { .name = "bilinear", .description = "Bilinear filtering", @@ -5576,11 +5607,11 @@ static const device_config_t s3_virge_357_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t s3_trio3d2x_config[] = { - // clang-format off + // clang-format off { .name = "memory", .description = "Memory size", @@ -5619,7 +5650,7 @@ static const device_config_t s3_trio3d2x_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t s3_virge_325_pci_device = { From 6c32f3ec0c1cd5997bd1c2ed717403750ea29bff Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 19:06:05 +0600 Subject: [PATCH 0442/1190] Properly process line endings --- src/qt/qt_openglrenderer_pcem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index c8f3d3eb9..50583bf51 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -136,7 +136,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); char *log = (char *) malloc(maxLength); glw.glGetProgramInfoLog(program->id, maxLength, &length, log); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Program not linked:\n\n%1").arg(log)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Program not linked:\n\n%1").arg(log).replace("\n", "
    ")); // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); free(log); return 0; @@ -181,7 +181,7 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); char *log = (char *) malloc(length); glw.glGetShaderInfoLog(shader, length, &length, log); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not compile shader:\n\n%1").arg(log)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not compile shader:\n\n%1").arg(log).replace("\n", "
    ")); // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); pclog("Could not compile shader: %s\n", log); From 1ed579a0fceaa86d5b4dc00cc76bd751040042cf Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 19:52:59 +0600 Subject: [PATCH 0443/1190] Reimplement other missing options from current OpenGL renderer --- src/qt/qt_openglrenderer_pcem.cpp | 11 +- src/qt/qt_openglshadermanagerdialog.cpp | 51 ++++ src/qt/qt_openglshadermanagerdialog.hpp | 8 + src/qt/qt_openglshadermanagerdialog.ui | 300 ++++++++++++++---------- 4 files changed, 247 insertions(+), 123 deletions(-) diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 50583bf51..79960323f 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -774,6 +774,8 @@ OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) format.setRenderableType(QSurfaceFormat::OpenGLES); + format.setSwapInterval(video_vsync ? 1 : 0); + setFormat(format); parentWidget = parent; @@ -822,6 +824,9 @@ OpenGLRendererPCem::initialize() glw.glEnable(GL_TEXTURE_2D); //renderTimer->start(75); + if (video_framerate != -1) { + renderTimer->start(ceilf(1000.f / (float)video_framerate)); + } scene_texture.data = NULL; scene_texture.width = 2048; @@ -1102,7 +1107,8 @@ OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) source.setRect(x, y, w, h); onResize(this->width(), this->height()); - render(); + if (video_framerate == -1) + render(); } std::vector> @@ -1314,6 +1320,9 @@ OpenGLRendererPCem::render() if (!context) return; + if (notReady()) + return; + int s, i, j; struct { diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 08cf94fd7..0bf083252 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -1,6 +1,9 @@ #include "qt_openglshadermanagerdialog.hpp" #include "ui_qt_openglshadermanagerdialog.h" +#include "qt_mainwindow.hpp" +extern MainWindow* main_window; + #include "qt_openglshaderconfig.hpp" #include @@ -25,6 +28,15 @@ OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent) { ui->setupUi(this); + ui->checkBoxVSync->setChecked(!!video_vsync); + ui->radioButtonVideoSync->setChecked(video_framerate == -1); + ui->radioButtonTargetFramerate->setChecked(video_framerate != -1); + if (video_framerate != -1) { + ui->targetFrameRate->setValue(video_framerate); + } else { + ui->targetFrameRate->setDisabled(true); + } + for (int i = 0; i < MAX_USER_SHADERS; i++) { if (gl3_shader_file[i][0] != 0) { char* filename = path_get_filename(gl3_shader_file[i]); @@ -75,6 +87,9 @@ void OpenGLShaderManagerDialog::on_buttonBox_clicked(QAbstractButton *button) accept(); } else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) { reject(); + } else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { + on_OpenGLShaderManagerDialog_accepted(); + main_window->reloadAllRenderers(); } } @@ -191,6 +206,12 @@ void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted() strncpy(gl3_shader_file[i], ui->shaderListWidget->item(i)->data(Qt::UserRole + 1).toString().toUtf8(), 512); } startblit(); + video_vsync = ui->checkBoxVSync->isChecked(); + if (ui->radioButtonTargetFramerate->isChecked()) { + video_framerate = ui->horizontalSliderFramerate->value(); + } else { + video_framerate = -1; + } config_save(); endblit(); } @@ -207,3 +228,33 @@ void OpenGLShaderManagerDialog::on_buttonConfigure_clicked() } } + +void OpenGLShaderManagerDialog::on_radioButtonVideoSync_clicked() +{ + ui->targetFrameRate->setDisabled(true); +} + + +void OpenGLShaderManagerDialog::on_radioButtonTargetFramerate_clicked() +{ + ui->targetFrameRate->setDisabled(false); +} + + +void OpenGLShaderManagerDialog::on_horizontalSliderFramerate_sliderMoved(int position) +{ + (void)position; + + if (ui->horizontalSliderFramerate->value() != ui->targetFrameRate->value()) + ui->targetFrameRate->setValue(ui->horizontalSliderFramerate->value()); +} + + +void OpenGLShaderManagerDialog::on_targetFrameRate_valueChanged(int arg1) +{ + (void)arg1; + + if (ui->horizontalSliderFramerate->value() != ui->targetFrameRate->value()) + ui->horizontalSliderFramerate->setValue(ui->targetFrameRate->value()); +} + diff --git a/src/qt/qt_openglshadermanagerdialog.hpp b/src/qt/qt_openglshadermanagerdialog.hpp index b8885e3a3..a9f7ad3a9 100644 --- a/src/qt/qt_openglshadermanagerdialog.hpp +++ b/src/qt/qt_openglshadermanagerdialog.hpp @@ -35,6 +35,14 @@ private slots: void on_buttonConfigure_clicked(); + void on_radioButtonVideoSync_clicked(); + + void on_radioButtonTargetFramerate_clicked(); + + void on_horizontalSliderFramerate_sliderMoved(int position); + + void on_targetFrameRate_valueChanged(int arg1); + private: Ui::OpenGLShaderManagerDialog *ui; }; diff --git a/src/qt/qt_openglshadermanagerdialog.ui b/src/qt/qt_openglshadermanagerdialog.ui index f68827436..2a72c69ed 100644 --- a/src/qt/qt_openglshadermanagerdialog.ui +++ b/src/qt/qt_openglshadermanagerdialog.ui @@ -13,136 +13,192 @@ Shader Manager - + QLayout::SizeConstraint::SetFixedSize - - - - QAbstractItemView::DragDropMode::InternalMove - - - QAbstractItemView::SelectionBehavior::SelectItems + + + + Shaders + + + QLayout::SizeConstraint::SetFixedSize + + + + + QAbstractItemView::DragDropMode::InternalMove + + + QAbstractItemView::SelectionBehavior::SelectItems + + + + + + + QLayout::SizeConstraint::SetFixedSize + + + + + Add + + + + + + + Remove + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + true + + + Configure + + + + + + + Move up + + + + + + + Move down + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + Qt::Orientation::Vertical + + + QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + false + + + + + + - - - - - - Add - - - - - - - Remove - - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - - - true - - - Configure - - - - - - - Move up - - - - - - - Move down - - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - - - Qt::Orientation::Vertical - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - false - - - - + + + + Render behavior + + + + QLayout::SizeConstraint::SetDefaultConstraint + + + + + Use target framerate: + + + + + + + 15 + + + 240 + + + 60 + + + Qt::Orientation::Horizontal + + + false + + + false + + + + + + + Synchronize with video + + + true + + + + + + + VSync + + + + + + + fps + + + 15 + + + 240 + + + 60 + + + + +
    - - - buttonBox - accepted() - OpenGLShaderManagerDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - OpenGLShaderManagerDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - + From 81461f677df712457f3c98214ca2390c4f135d14 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 20:54:25 +0600 Subject: [PATCH 0444/1190] Cleanups, copyright headers and name changing for PRing --- src/86box.c | 1 - src/config.c | 19 +- src/include/86box/86box.h | 1 - src/include/86box/ini.h | 30 -- src/ini.c | 3 +- src/qt/CMakeLists.txt | 12 +- src/qt/qt_glsl_parser.cpp | 37 +++ src/qt/qt_opengloptions.cpp | 196 ------------- src/qt/qt_opengloptions.hpp | 102 ------- src/qt/qt_opengloptionsdialog.cpp | 116 -------- src/qt/qt_opengloptionsdialog.hpp | 51 ---- src/qt/qt_opengloptionsdialog.ui | 280 ------------------ src/qt/qt_openglrenderer.cpp | 468 ------------------------------ src/qt/qt_openglrenderer.hpp | 125 -------- src/qt/qt_openglrenderer_pcem.cpp | 111 ++++--- src/qt/qt_openglrenderer_pcem.hpp | 20 +- src/qt/qt_rendererstack.cpp | 17 +- 17 files changed, 136 insertions(+), 1453 deletions(-) delete mode 100644 src/qt/qt_opengloptions.cpp delete mode 100644 src/qt/qt_opengloptions.hpp delete mode 100644 src/qt/qt_opengloptionsdialog.cpp delete mode 100644 src/qt/qt_opengloptionsdialog.hpp delete mode 100644 src/qt/qt_opengloptionsdialog.ui delete mode 100644 src/qt/qt_openglrenderer.cpp delete mode 100644 src/qt/qt_openglrenderer.hpp diff --git a/src/86box.c b/src/86box.c index 13167b1bd..24f6f0deb 100644 --- a/src/86box.c +++ b/src/86box.c @@ -172,7 +172,6 @@ int force_43 = 0; /* (C) video * int video_filter_method = 1; /* (C) video */ int video_vsync = 0; /* (C) video */ int video_framerate = -1; /* (C) video */ -char video_shader[512] = { '\0' }; /* (C) video */ bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of pass-through for serial ports */ int bugger_enabled = 0; /* (C) enable ISAbugger */ diff --git a/src/config.c b/src/config.c index 20981885a..5ad804df6 100644 --- a/src/config.c +++ b/src/config.c @@ -200,7 +200,6 @@ load_general(void) video_framerate = ini_section_get_int(cat, "video_gl_framerate", -1); video_vsync = ini_section_get_int(cat, "video_gl_vsync", 0); - strncpy(video_shader, ini_section_get_string(cat, "video_gl_shader", ""), sizeof(video_shader) - 1); window_remember = ini_section_get_int(cat, "window_remember", 0); if (window_remember) { @@ -1733,7 +1732,19 @@ load_gl3_shaders(void) if (shaders > MAX_USER_SHADERS) shaders = MAX_USER_SHADERS; - for (int i = 0; i < shaders; i++) { + if (shaders == 0) { + ini_section_t general = ini_find_section(config, "General"); + if (general) { + p = ini_section_get_string(general, "video_gl_shader", NULL); + if (p) { + strncpy(gl3_shader_file[0], p, 512); + ini_delete_var(config, general, "video_gl_shader"); + return; + } + } + } + + for (i = 0; i < shaders; i++) { temp[0] = 0; snprintf(temp, 512, "shader%d", i); p = ini_section_get_string(cat, temp, ""); @@ -2035,10 +2046,6 @@ save_general(void) ini_section_set_int(cat, "video_gl_vsync", video_vsync); else ini_section_delete_var(cat, "video_gl_vsync"); - if (strlen(video_shader) > 0) - ini_section_set_string(cat, "video_gl_shader", video_shader); - else - ini_section_delete_var(cat, "video_gl_shader"); if (do_auto_pause) ini_section_set_int(cat, "do_auto_pause", do_auto_pause); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 30905741c..768ca6267 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -126,7 +126,6 @@ extern int video_filter_method; /* (C) video */ extern int video_vsync; /* (C) video */ extern int video_framerate; /* (C) video */ extern int gfxcard[GFXCARD_MAX]; /* (C) graphics/video card */ -extern char video_shader[512]; /* (C) video */ extern int bugger_enabled; /* (C) enable ISAbugger */ extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */ extern int postcard_enabled; /* (C) enable POST card */ diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h index 3139f410e..bb250e697 100644 --- a/src/include/86box/ini.h +++ b/src/include/86box/ini.h @@ -92,36 +92,6 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); extern void ini_rename_section(ini_section_t section, const char *name); extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); -static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; } -static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); - if (size == 0) - return res; - if (str != NULL) - strncpy(dst, str, size - 1); - else - dst[0] = 0; - return res; -} -static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - *dst = ini_get_int((ini_t)config, "", name, defVal); - return res; -} -static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - *dst = (float)ini_get_double((ini_t)config, "", name, defVal); - return res; -} -static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - *dst = !!ini_get_int((ini_t)config, "", name, defVal); - return res; -} -static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); } -static inline void wx_config_free(void *config) { ini_close(config); }; - #ifdef __cplusplus } #endif diff --git a/src/ini.c b/src/ini.c index 7a54d5396..503b17ae3 100644 --- a/src/ini.c +++ b/src/ini.c @@ -162,7 +162,6 @@ ini_has_entry(ini_section_t self, const char *name) { section_t *section = (section_t *) self; const entry_t *entry; - int value = 0; if (section == NULL) return 0; @@ -546,6 +545,7 @@ ini_write(ini_t ini, const char *fn) (void) fclose(fp); } +/* Wide-character version of "trim" */ wchar_t * trim_w(wchar_t *str) { @@ -609,7 +609,6 @@ ini_strip_quotes(ini_t ini) ent = (entry_t *) sec->entry_head.next; while (ent != NULL) { if (ent->name[0] != '\0') { - int i = 0; int trailing_hash = strcspn(ent->data, "#"); int trailing_quote; ent->wdata[trailing_hash] = 0; diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 574aae7b7..8137be98e 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -87,16 +87,9 @@ add_library(ui STATIC qt_softwarerenderer.hpp qt_hardwarerenderer.cpp qt_hardwarerenderer.hpp - qt_openglrenderer.cpp - qt_openglrenderer.hpp qt_openglrenderer_pcem.cpp qt_openglrenderer_pcem.hpp qt_glsl_parser.cpp - qt_opengloptions.cpp - qt_opengloptions.hpp - qt_opengloptionsdialog.cpp - qt_opengloptionsdialog.hpp - qt_opengloptionsdialog.ui qt_settings.cpp qt_settings.hpp @@ -197,7 +190,10 @@ add_library(ui STATIC qt_openglshadermanagerdialog.hpp qt_openglshadermanagerdialog.cpp qt_openglshadermanagerdialog.ui - qt_openglshaderconfig.hpp qt_openglshaderconfig.cpp qt_openglshaderconfig.ui + + qt_openglshaderconfig.hpp + qt_openglshaderconfig.cpp + qt_openglshaderconfig.ui ) if(RTMIDI) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index 2a4c4ddd1..bf02014db 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -28,6 +28,43 @@ extern void endblit(); (a)[(n)-1] = 0; \ } while (0) + + +static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; } + +static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); + if (size == 0) + return res; + if (str != NULL) + strncpy(dst, str, size - 1); + else + dst[0] = 0; + return res; +} + +static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = ini_get_int((ini_t)config, "", name, defVal); + return res; +} + +static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = (float)ini_get_double((ini_t)config, "", name, defVal); + return res; +} + +static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = !!ini_get_int((ini_t)config, "", name, defVal); + return res; +} + +static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); } +static inline void wx_config_free(void *config) { ini_close(config); }; + static int endswith(const char *str, const char *ext) { int i; const char *p; diff --git a/src/qt/qt_opengloptions.cpp b/src/qt/qt_opengloptions.cpp deleted file mode 100644 index 58030b467..000000000 --- a/src/qt/qt_opengloptions.cpp +++ /dev/null @@ -1,196 +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. - * - * OpenGL renderer options for Qt - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#include -#include -#include -#include - -#include - -#include "qt_opengloptions.hpp" - -extern "C" { -#include <86box/86box.h> -} - -/* Default vertex shader. */ -static const GLchar *vertex_shader = "\ -in vec2 VertexCoord;\n\ -in vec2 TexCoord;\n\ -out vec2 tex;\n\ -void main(){\n\ - gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\ - tex = TexCoord;\n\ -}\n"; - -/* Default fragment shader. */ -static const GLchar *fragment_shader = "\ -in vec2 tex;\n\ -uniform sampler2D texsampler;\n\ -out vec4 color;\n\ -void main() {\n\ - color = texture(texsampler, tex);\n\ -}\n"; - -OpenGLOptions::OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion) - : QObject(parent) - , m_glslVersion(glslVersion) -{ - m_filter = video_filter_method == 0 - ? FilterType::Nearest - : FilterType::Linear; - - if (!loadConfig) - return; - - /* Initialize with config. */ - m_vsync = video_vsync != 0; - m_framerate = video_framerate; - - m_renderBehavior = video_framerate == -1 - ? RenderBehaviorType::SyncWithVideo - : RenderBehaviorType::TargetFramerate; - - QString shaderPath(video_shader); - - if (shaderPath.isEmpty()) { - addDefaultShader(); - } else { - try { - addShader(shaderPath); - } catch (const std::runtime_error &) { - /* Fallback to default shader */ - addDefaultShader(); - } - } -} - -void -OpenGLOptions::save() const -{ - video_vsync = m_vsync ? 1 : 0; - video_framerate = m_renderBehavior == RenderBehaviorType::SyncWithVideo ? -1 : m_framerate; - video_filter_method = m_filter == FilterType::Nearest ? 0 : 1; - - /* TODO: multiple shaders */ - auto path = m_shaders.first().path().toLocal8Bit(); - - if (!path.isEmpty()) - qstrncpy(video_shader, path.constData(), sizeof(video_shader)); - else - video_shader[0] = '\0'; -} - -OpenGLOptions::FilterType -OpenGLOptions::filter() const -{ - /* Filter method is controlled externally */ - return video_filter_method == 0 - ? FilterType::Nearest - : FilterType::Linear; -} - -void -OpenGLOptions::setRenderBehavior(RenderBehaviorType value) -{ - m_renderBehavior = value; -} - -void -OpenGLOptions::setFrameRate(int value) -{ - m_framerate = value; -} - -void -OpenGLOptions::setVSync(bool value) -{ - m_vsync = value; -} - -void -OpenGLOptions::setFilter(FilterType value) -{ - m_filter = value; -} - -void -OpenGLOptions::addShader(const QString &path) -{ - QFile shader_file(path); - - if (!shader_file.open(QIODevice::ReadOnly | QIODevice::Text)) { - throw std::runtime_error( - QString(tr("Error opening \"%1\": %2")) - .arg(path) - .arg(shader_file.errorString()) - .toStdString()); - } - - auto shader_text = QString(shader_file.readAll()); - - shader_file.close(); - - /* Remove parameter lines */ - shader_text.remove(QRegularExpression("^\\s*#pragma parameter.*?\\n", QRegularExpression::MultilineOption)); - - QRegularExpression version("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption); - - auto match = version.match(shader_text); - - QString version_line(m_glslVersion); - - if (match.hasMatch()) { - /* Extract existing version and remove it. */ - version_line = match.captured(1); - shader_text.remove(version); - } - - auto shader = new QOpenGLShaderProgram(this); - - auto throw_shader_error = [path, shader](const QString &what) { - throw std::runtime_error( - QString(what % ":\n\n %2") - .arg(path) - .arg(shader->log()) - .toStdString()); - }; - - static const char *extension = "\n#extension GL_ARB_shading_language_420pack : enable\n"; - - if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % extension % "\n#define VERTEX\n#line 1\n" % shader_text)) - throw_shader_error(tr("Error compiling vertex shader in file \"%1\"")); - - if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % extension % "\n#define FRAGMENT\n#line 1\n" % shader_text)) - throw_shader_error(tr("Error compiling fragment shader in file \"%1\"")); - - if (!shader->link()) - throw_shader_error(tr("Error linking shader program in file \"%1\"")); - - m_shaders << OpenGLShaderPass(shader, path); -} - -void -OpenGLOptions::addDefaultShader() -{ - auto shader = new QOpenGLShaderProgram(this); - shader->addShaderFromSourceCode(QOpenGLShader::Vertex, m_glslVersion % "\n" % vertex_shader); - shader->addShaderFromSourceCode(QOpenGLShader::Fragment, m_glslVersion % "\n" % fragment_shader); - shader->link(); - m_shaders << OpenGLShaderPass(shader, QString()); -} diff --git a/src/qt/qt_opengloptions.hpp b/src/qt/qt_opengloptions.hpp deleted file mode 100644 index 64f761670..000000000 --- a/src/qt/qt_opengloptions.hpp +++ /dev/null @@ -1,102 +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. - * - * Header for OpenGL renderer options - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#ifndef QT_OPENGLOPTIONS_HPP -#define QT_OPENGLOPTIONS_HPP - -#include -#include -#include -#include - -class OpenGLShaderPass { -public: - OpenGLShaderPass(QOpenGLShaderProgram *shader, const QString &path) - : m_shader(shader) - , m_path(path) - , m_vertex_coord(shader->attributeLocation("VertexCoord")) - , m_tex_coord(shader->attributeLocation("TexCoord")) - , m_color(shader->attributeLocation("Color")) - , m_mvp_matrix(shader->uniformLocation("MVPMatrix")) - , m_input_size(shader->uniformLocation("InputSize")) - , m_output_size(shader->uniformLocation("OutputSize")) - , m_texture_size(shader->uniformLocation("TextureSize")) - , m_frame_count(shader->uniformLocation("FrameCount")) - { - } - - bool bind() const { return m_shader->bind(); } - const QString &path() const { return m_path; } - const GLint &vertex_coord() const { return m_vertex_coord; } - const GLint &tex_coord() const { return m_tex_coord; } - const GLint &color() const { return m_color; } - const GLint &mvp_matrix() const { return m_mvp_matrix; } - const GLint &input_size() const { return m_input_size; } - const GLint &output_size() const { return m_output_size; } - const GLint &texture_size() const { return m_texture_size; } - const GLint &frame_count() const { return m_frame_count; } - -private: - QOpenGLShaderProgram *m_shader; - QString m_path; - GLint m_vertex_coord; - GLint m_tex_coord; - GLint m_color; - GLint m_mvp_matrix; - GLint m_input_size; - GLint m_output_size; - GLint m_texture_size; - GLint m_frame_count; -}; - -class OpenGLOptions : public QObject { - Q_OBJECT - -public: - enum RenderBehaviorType { SyncWithVideo, - TargetFramerate }; - - enum FilterType { Nearest, - Linear }; - - OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion); - - RenderBehaviorType renderBehavior() const { return m_renderBehavior; } - int framerate() const { return m_framerate; } - bool vSync() const { return m_vsync; } - FilterType filter() const; - - const QList &shaders() const { return m_shaders; } - - void setRenderBehavior(RenderBehaviorType value); - void setFrameRate(int value); - void setVSync(bool value); - void setFilter(FilterType value); - void addShader(const QString &path); - void addDefaultShader(); - void save() const; - -private: - RenderBehaviorType m_renderBehavior = SyncWithVideo; - int m_framerate = -1; - bool m_vsync = false; - FilterType m_filter = Nearest; - QList m_shaders; - QString m_glslVersion; -}; - -#endif diff --git a/src/qt/qt_opengloptionsdialog.cpp b/src/qt/qt_opengloptionsdialog.cpp deleted file mode 100644 index acb2ce9f2..000000000 --- a/src/qt/qt_opengloptionsdialog.cpp +++ /dev/null @@ -1,116 +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. - * - * OpenGL renderer options dialog for Qt - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#include -#include -#include - -#include - -#include "qt_opengloptionsdialog.hpp" -#include "qt_util.hpp" -#include "ui_qt_opengloptionsdialog.h" - -OpenGLOptionsDialog::OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function optionsFactory) - : QDialog(parent) - , ui(new Ui::OpenGLOptionsDialog) - , createOptions(optionsFactory) -{ - ui->setupUi(this); - - if (options.renderBehavior() == OpenGLOptions::SyncWithVideo) - ui->syncWithVideo->setChecked(true); - else { - ui->syncToFramerate->setChecked(true); - ui->targetFps->setValue(options.framerate()); - } - - ui->vsync->setChecked(options.vSync()); - - if (!options.shaders().isEmpty()) { - auto path = options.shaders().first().path(); - if (!path.isEmpty()) - ui->shader->setPlainText(path); - } -} - -OpenGLOptionsDialog::~OpenGLOptionsDialog() -{ - delete ui; -} - -void -OpenGLOptionsDialog::accept() -{ - auto options = createOptions(); - - options->setRenderBehavior( - ui->syncWithVideo->isChecked() - ? OpenGLOptions::SyncWithVideo - : OpenGLOptions::TargetFramerate); - - options->setFrameRate(ui->targetFps->value()); - - options->setVSync(ui->vsync->isChecked()); - - auto shader = ui->shader->toPlainText(); - - try { - - if (!shader.isEmpty()) - options->addShader(shader); - else - options->addDefaultShader(); - - } catch (const std::runtime_error &e) { - delete options; - - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Shader error")); - msgBox.setText(tr("Could not load shaders.")); - msgBox.setInformativeText(tr("More information in details.")); - msgBox.setDetailedText(e.what()); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Close); - msgBox.setDefaultButton(QMessageBox::Close); - msgBox.setStyleSheet("QTextEdit { min-width: 45em; }"); - msgBox.exec(); - - return; - } - - options->save(); - - emit optionsChanged(options); - - QDialog::accept(); -} - -void -OpenGLOptionsDialog::on_addShader_clicked() -{ - auto shader = QFileDialog::getOpenFileName( - this, - QString(), - QString(), - tr("OpenGL Shaders") % util::DlgFilter({ "glsl" }, true)); - - if (shader.isNull()) - return; - - ui->shader->setPlainText(shader); -} diff --git a/src/qt/qt_opengloptionsdialog.hpp b/src/qt/qt_opengloptionsdialog.hpp deleted file mode 100644 index f34d74d75..000000000 --- a/src/qt/qt_opengloptionsdialog.hpp +++ /dev/null @@ -1,51 +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. - * - * Header for OpenGL renderer options dialog - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#ifndef QT_OPENGLOPTIONSDIALOG_H -#define QT_OPENGLOPTIONSDIALOG_H - -#include - -#include - -#include "qt_opengloptions.hpp" - -namespace Ui { -class OpenGLOptionsDialog; -} - -class OpenGLOptionsDialog : public QDialog { - Q_OBJECT - -public: - explicit OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function optionsFactory); - ~OpenGLOptionsDialog(); - -signals: - void optionsChanged(OpenGLOptions *options); - -public slots: - void accept() override; - -private: - Ui::OpenGLOptionsDialog *ui; - - std::function createOptions; - -private slots: - void on_addShader_clicked(); -}; - -#endif // QT_OPENGLOPTIONSDIALOG_H diff --git a/src/qt/qt_opengloptionsdialog.ui b/src/qt/qt_opengloptionsdialog.ui deleted file mode 100644 index a6f86b6c2..000000000 --- a/src/qt/qt_opengloptionsdialog.ui +++ /dev/null @@ -1,280 +0,0 @@ - - - OpenGLOptionsDialog - - - - 0 - 0 - 400 - 320 - - - - OpenGL 3.0 renderer options - - - - - - Render behavior - - - - - - Use target framerate: - - - - - - - false - - - fps - - - 15 - - - 240 - - - 60 - - - - - - - VSync - - - - - - - <html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html> - - - Synchronize with video - - - true - - - - - - - false - - - 15 - - - 240 - - - 60 - - - Qt::Horizontal - - - false - - - QSlider::NoTicks - - - - - - - - - - Shaders - - - - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - true - - - No shader selected - - - - - - - Browse... - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - syncWithVideo - syncToFramerate - fpsSlider - targetFps - vsync - shader - addShader - removeShader - - - - - buttonBox - accepted() - OpenGLOptionsDialog - accept() - - - 257 - 310 - - - 157 - 274 - - - - - buttonBox - rejected() - OpenGLOptionsDialog - reject() - - - 325 - 310 - - - 286 - 274 - - - - - syncToFramerate - toggled(bool) - targetFps - setEnabled(bool) - - - 140 - 71 - - - 380 - 98 - - - - - syncToFramerate - toggled(bool) - fpsSlider - setEnabled(bool) - - - 158 - 66 - - - 168 - 87 - - - - - fpsSlider - valueChanged(int) - targetFps - setValue(int) - - - 252 - 90 - - - 308 - 89 - - - - - targetFps - valueChanged(int) - fpsSlider - setValue(int) - - - 364 - 93 - - - 134 - 93 - - - - - removeShader - clicked() - shader - clear() - - - 333 - 201 - - - 235 - 208 - - - - - diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp deleted file mode 100644 index 60aa998a9..000000000 --- a/src/qt/qt_openglrenderer.cpp +++ /dev/null @@ -1,468 +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. - * - * OpenGL renderer for Qt - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "qt_opengloptionsdialog.hpp" -#include "qt_openglrenderer.hpp" - -#ifndef GL_MAP_PERSISTENT_BIT -# define GL_MAP_PERSISTENT_BIT 0x0040 -#endif - -#ifndef GL_MAP_COHERENT_BIT -# define GL_MAP_COHERENT_BIT 0x0080 -#endif - -OpenGLRenderer::OpenGLRenderer(QWidget *parent) - : QWindow(parent->windowHandle()) - , renderTimer(new QTimer(this)) - , options(nullptr) -{ - renderTimer->setTimerType(Qt::PreciseTimer); - /* TODO: need's more accuracy, maybe target 1ms earlier and spin yield */ - connect(renderTimer, &QTimer::timeout, this, &OpenGLRenderer::render); - - buf_usage = std::vector(BUFFERCOUNT); - for (auto &flag : buf_usage) - flag.clear(); - - setSurfaceType(QWindow::OpenGLSurface); - - QSurfaceFormat format; - -#ifdef Q_OS_MACOS - format.setVersion(4, 1); -#else - format.setVersion(3, 2); -#endif - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) - format.setRenderableType(QSurfaceFormat::OpenGLES); - - setFormat(format); - - parentWidget = parent; - - source.setRect(0, 0, INIT_WIDTH, INIT_HEIGHT); -} - -OpenGLRenderer::~OpenGLRenderer() -{ - finalize(); -} - -void -OpenGLRenderer::exposeEvent(QExposeEvent *event) -{ - Q_UNUSED(event); - - if (!isInitialized) - initialize(); - - onResize(size().width(), size().height()); -} - -void -OpenGLRenderer::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - onResize(event->size().width(), event->size().height()); - - if (notReady()) - return; - - context->makeCurrent(this); - - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); -} - -bool -OpenGLRenderer::event(QEvent *event) -{ - Q_UNUSED(event); - - bool res = false; - if (!eventDelegate(event, res)) - return QWindow::event(event); - return res; -} - -void -OpenGLRenderer::initialize() -{ - try { - context = new QOpenGLContext(this); - - context->setFormat(format()); - - if (!context->create()) - throw opengl_init_error(tr("Couldn't create OpenGL context.")); - - if (!context->makeCurrent(this)) - throw opengl_init_error(tr("Couldn't switch to OpenGL context.")); - - auto version = context->format().version(); - - if (version.first < 3) - throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); - - initializeOpenGLFunctions(); - - /* Prepare the shader version string */ - glslVersion = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); - glslVersion.truncate(4); - glslVersion.remove('.'); - glslVersion.prepend("#version "); - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) - glslVersion.append(" es"); - else if (context->format().profile() == QSurfaceFormat::CoreProfile) - glslVersion.append(" core"); - - initializeExtensions(); - - initializeBuffers(); - - /* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */ - const GLfloat surface[] = { - -1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, - 1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, - -1.f, -1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, - 1.f, -1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f - }; - - glGenVertexArrays(1, &vertexArrayID); - - glBindVertexArray(vertexArrayID); - - glGenBuffers(1, &vertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(surface), surface, GL_STATIC_DRAW); - - glGenTextures(1, &textureID); - glBindTexture(GL_TEXTURE_2D, textureID); - - const GLfloat border_color[] = { 0.f, 0.f, 0.f, 1.f }; - - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - - glTexImage2D(GL_TEXTURE_2D, 0, QOpenGLTexture::RGBA8_UNorm, INIT_WIDTH, INIT_HEIGHT, 0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt32_RGBA8_Rev, NULL); - - reloadOptions(); - - glClearColor(0.f, 0.f, 0.f, 1.f); - - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); - - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - throw opengl_init_error(tr("OpenGL initialization failed. Error %1.").arg(error)); - - isInitialized = true; - - emit initialized(); - - glClear(GL_COLOR_BUFFER_BIT); - - context->swapBuffers(this); - } catch (const opengl_init_error &e) { - /* Mark all buffers as in use */ - for (auto &flag : buf_usage) - flag.test_and_set(); - - QMessageBox::critical((QWidget *) qApp->findChild(), tr("Error initializing OpenGL"), e.what() % tr("\nFalling back to software rendering.")); - - context->doneCurrent(); - isFinalized = true; - isInitialized = true; - - emit errorInitializing(); - } -} - -void -OpenGLRenderer::finalize() -{ - if (isFinalized) - return; - - renderTimer->stop(); - - context->makeCurrent(this); - - if (hasBufferStorage) - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - - glDeleteBuffers(1, &unpackBufferID); - glDeleteTextures(1, &textureID); - glDeleteBuffers(1, &vertexBufferID); - glDeleteVertexArrays(1, &vertexArrayID); - - if (!hasBufferStorage && unpackBuffer) - free(unpackBuffer); - - context->doneCurrent(); - - isFinalized = true; -} - -QDialog * -OpenGLRenderer::getOptions(QWidget *parent) -{ - auto dialog = new OpenGLOptionsDialog(parent, *options, [this]() { return new OpenGLOptions(this, false, glslVersion); }); - - connect(dialog, &OpenGLOptionsDialog::optionsChanged, this, &OpenGLRenderer::updateOptions); - - return dialog; -} - -void -OpenGLRenderer::initializeExtensions() -{ -#ifndef NO_BUFFER_STORAGE - if (context->hasExtension("GL_ARB_buffer_storage") || context->hasExtension("GL_EXT_buffer_storage")) { - hasBufferStorage = true; - - glBufferStorage = (PFNGLBUFFERSTORAGEEXTPROC_LOCAL) context->getProcAddress(context->hasExtension("GL_EXT_buffer_storage") ? "glBufferStorageEXT" : "glBufferStorage"); - if (!glBufferStorage) - glBufferStorage = (PFNGLBUFFERSTORAGEEXTPROC_LOCAL) context->getProcAddress("glBufferStorage"); - } -#endif -} - -void -OpenGLRenderer::initializeBuffers() -{ - glGenBuffers(1, &unpackBufferID); - - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID); - - if (hasBufferStorage) { -#ifndef NO_BUFFER_STORAGE - /* Create persistent buffer for pixel transfer. */ - glBufferStorage(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - - unpackBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, BUFFERBYTES * BUFFERCOUNT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); -#endif - } else { - /* Fallback; create our own buffer. */ - unpackBuffer = malloc(BUFFERBYTES * BUFFERCOUNT); - - if (unpackBuffer == nullptr) - throw opengl_init_error(tr("Allocating memory for unpack buffer failed.")); - - glBufferData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_STREAM_DRAW); - } -} - -void -OpenGLRenderer::applyOptions() -{ - /* TODO: change detection in options */ - - if (options->framerate() > 0) { - int interval = (int) ceilf(1000.f / (float) options->framerate()); - renderTimer->setInterval(std::chrono::milliseconds(interval)); - } - - if (options->renderBehavior() == OpenGLOptions::TargetFramerate) - renderTimer->start(); - else - renderTimer->stop(); - - auto format = this->format(); - int interval = options->vSync() ? 1 : 0; - - if (format.swapInterval() != interval) { - format.setSwapInterval(interval); - setFormat(format); - context->setFormat(format); - } - - GLint filter = options->filter() == OpenGLOptions::Linear ? GL_LINEAR : GL_NEAREST; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - - currentFilter = options->filter(); -} - -void -OpenGLRenderer::reloadOptions() -{ - if (options) { - delete options; - options = nullptr; - } - options = new OpenGLOptions(this, true, glslVersion); - - applyOptions(); -} - -void -OpenGLRenderer::applyShader(const OpenGLShaderPass &shader) -{ - if (!shader.bind()) - return; - - if (shader.vertex_coord() != -1) { - glEnableVertexAttribArray(shader.vertex_coord()); - glVertexAttribPointer(shader.vertex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0); - } - - if (shader.tex_coord() != -1) { - glEnableVertexAttribArray(shader.tex_coord()); - glVertexAttribPointer(shader.tex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat))); - } - - if (shader.color() != -1) { - glEnableVertexAttribArray(shader.color()); - glVertexAttribPointer(shader.color(), 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (4 * sizeof(GLfloat))); - } - - if (shader.mvp_matrix() != -1) { - static const GLfloat mvp[] = { - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }; - glUniformMatrix4fv(shader.mvp_matrix(), 1, GL_FALSE, mvp); - } - - if (shader.output_size() != -1) - glUniform2f(shader.output_size(), destination.width(), destination.height()); - - if (shader.input_size() != -1) - glUniform2f(shader.input_size(), source.width(), source.height()); - - if (shader.texture_size() != -1) - glUniform2f(shader.texture_size(), source.width(), source.height()); - - if (shader.frame_count() != -1) - glUniform1i(shader.frame_count(), frameCounter); -} - -void -OpenGLRenderer::render() -{ - context->makeCurrent(this); - - if (options->filter() != currentFilter) - applyOptions(); - - /* TODO: multiple shader passes */ - applyShader(options->shaders().first()); - - glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - context->swapBuffers(this); - - frameCounter = (frameCounter + 1) & 1023; -} - -void -OpenGLRenderer::updateOptions(OpenGLOptions *newOptions) -{ - context->makeCurrent(this); - - glUseProgram(0); - - delete options; - - options = newOptions; - - options->setParent(this); - - applyOptions(); -} - -std::vector> -OpenGLRenderer::getBuffers() -{ - std::vector> buffers; - - if (notReady() || !unpackBuffer) - return buffers; - - /* Split the buffer area */ - for (int i = 0; i < BUFFERCOUNT; i++) { - buffers.push_back(std::make_tuple((uint8_t *) unpackBuffer + BUFFERBYTES * i, &buf_usage[i])); - } - - return buffers; -} - -void -OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) -{ - if (notReady()) - return; - - context->makeCurrent(this); - -#ifdef Q_OS_MACOS - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); -#endif - - if (source.width() != w || source.height() != h) { - source.setRect(0, 0, w, h); - - /* Resize the texture */ - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage2D(GL_TEXTURE_2D, 0, (GLenum) QOpenGLTexture::RGBA8_UNorm, source.width(), source.height(), 0, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID); - } - - if (!hasBufferStorage) - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * buf_idx, h * ROW_LENGTH * sizeof(uint32_t) + (y * ROW_LENGTH * sizeof(uint32_t)), (uint8_t *) unpackBuffer + BUFFERBYTES * buf_idx); - - glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * buf_idx + y * ROW_LENGTH + x); - glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); - - /* TODO: check if fence sync is implementable here and still has any benefit. */ - glFinish(); - - buf_usage[buf_idx].clear(); - - if (options->renderBehavior() == OpenGLOptions::SyncWithVideo) - render(); -} diff --git a/src/qt/qt_openglrenderer.hpp b/src/qt/qt_openglrenderer.hpp deleted file mode 100644 index 27822600c..000000000 --- a/src/qt/qt_openglrenderer.hpp +++ /dev/null @@ -1,125 +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. - * - * Header file for OpenGL renderer - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#ifndef QT_OPENGLRENDERER_HPP -#define QT_OPENGLRENDERER_HPP - -#if defined Q_OS_MACOS || __arm__ -# define NO_BUFFER_STORAGE -#endif - -#include -#include -#include -#include -#include -#include -#if !defined NO_BUFFER_STORAGE && !(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) -# include -#endif - -#include -#include -#include -#include - -#include "qt_opengloptions.hpp" -#include "qt_renderercommon.hpp" - -typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); - -class OpenGLRenderer : public QWindow, protected QOpenGLExtraFunctions, public RendererCommon { - Q_OBJECT - -public: - QOpenGLContext *context; - - OpenGLRenderer(QWidget *parent = nullptr); - ~OpenGLRenderer(); - - std::vector> getBuffers() override; - - void finalize() override final; - bool hasOptions() const override { return true; } - QDialog *getOptions(QWidget *parent) override; - void reloadOptions() override; - -signals: - void initialized(); - void errorInitializing(); - -public slots: - void onBlit(int buf_idx, int x, int y, int w, int h); - -protected: - void exposeEvent(QExposeEvent *event) override; - void resizeEvent(QResizeEvent *event) override; - bool event(QEvent *event) override; - -private: - static constexpr int INIT_WIDTH = 640; - static constexpr int INIT_HEIGHT = 400; - static constexpr int ROW_LENGTH = 2048; - static constexpr int BUFFERPIXELS = 4194304; - static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ - static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ - - QTimer *renderTimer; - OpenGLOptions *options; - - QString glslVersion; - - bool isInitialized = false; - bool isFinalized = false; - - GLuint unpackBufferID = 0; - GLuint vertexArrayID = 0; - GLuint vertexBufferID = 0; - GLuint textureID = 0; - int frameCounter = 0; - - OpenGLOptions::FilterType currentFilter; - - void *unpackBuffer = nullptr; - - void initialize(); - void initializeExtensions(); - void initializeBuffers(); - void applyOptions(); - void applyShader(const OpenGLShaderPass &shader); - bool notReady() const { return !isInitialized || isFinalized; } - - /* GL_ARB_buffer_storage */ - bool hasBufferStorage = false; -#ifndef NO_BUFFER_STORAGE - PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr; -#endif - -private slots: - void render(); - void updateOptions(OpenGLOptions *newOptions); -}; - -class opengl_init_error : public std::runtime_error { -public: - opengl_init_error(const QString &what) - : std::runtime_error(what.toStdString()) - { - } -}; - -#endif diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 79960323f..5b1c8518d 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -1,3 +1,26 @@ +/* + * 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. + * + * OpenGL renderer for Qt, mostly ported over from PCem. + * + * + * + * Authors: Teemu Korhonen + * Cacodemon345 + * bit + * Sarah Walker + * + * Copyright 2022 Teemu Korhonen + * Copyright 2025 Cacodemon345 + * Copyright 2017 Bit + * Copyright 2017-2020 Sarah Walker + */ + #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" @@ -114,7 +137,7 @@ next_pow2(unsigned int n) } int -OpenGLRendererPCem::create_program(struct shader_program *program) +OpenGLRenderer::create_program(struct shader_program *program) { GLint status; program->id = glw.glCreateProgram(); @@ -146,7 +169,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) } int -OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) +OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) { const char *source[3]; char version[50]; @@ -197,19 +220,19 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons } GLuint -OpenGLRendererPCem::get_uniform(GLuint program, const char *name) +OpenGLRenderer::get_uniform(GLuint program, const char *name) { return glw.glGetUniformLocation(program, name); } GLuint -OpenGLRendererPCem::get_attrib(GLuint program, const char *name) +OpenGLRenderer::get_attrib(GLuint program, const char *name) { return glw.glGetAttribLocation(program, name); } void -OpenGLRendererPCem::find_uniforms(struct glsl_shader *glsl, int num_pass) +OpenGLRenderer::find_uniforms(struct glsl_shader *glsl, int num_pass) { int i; char s[50]; @@ -294,7 +317,7 @@ setup_scale(struct shader *shader, struct shader_pass *pass) } void -OpenGLRendererPCem::create_texture(struct shader_texture *tex) +OpenGLRenderer::create_texture(struct shader_texture *tex) { if (tex->width > max_texture_size) tex->width = max_texture_size; @@ -314,7 +337,7 @@ OpenGLRendererPCem::create_texture(struct shader_texture *tex) } void -OpenGLRendererPCem::delete_texture(struct shader_texture *tex) +OpenGLRenderer::delete_texture(struct shader_texture *tex) { if (tex->id > 0) glw.glDeleteTextures(1, (GLuint *) &tex->id); @@ -322,7 +345,7 @@ OpenGLRendererPCem::delete_texture(struct shader_texture *tex) } void -OpenGLRendererPCem::delete_fbo(struct shader_fbo *fbo) +OpenGLRenderer::delete_fbo(struct shader_fbo *fbo) { if (fbo->id >= 0) { glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); @@ -331,7 +354,7 @@ OpenGLRendererPCem::delete_fbo(struct shader_fbo *fbo) } void -OpenGLRendererPCem::delete_program(struct shader_program *program) +OpenGLRenderer::delete_program(struct shader_program *program) { if (program->vertex_shader) glw.glDeleteShader(program->vertex_shader); @@ -341,7 +364,7 @@ OpenGLRendererPCem::delete_program(struct shader_program *program) } void -OpenGLRendererPCem::delete_vbo(struct shader_vbo *vbo) +OpenGLRenderer::delete_vbo(struct shader_vbo *vbo) { if (vbo->color >= 0) glw.glDeleteBuffers(1, (GLuint *) &vbo->color); @@ -350,7 +373,7 @@ OpenGLRendererPCem::delete_vbo(struct shader_vbo *vbo) } void -OpenGLRendererPCem::delete_pass(struct shader_pass *pass) +OpenGLRenderer::delete_pass(struct shader_pass *pass) { delete_fbo(&pass->fbo); delete_vbo(&pass->vbo); @@ -359,14 +382,14 @@ OpenGLRendererPCem::delete_pass(struct shader_pass *pass) } void -OpenGLRendererPCem::delete_prev(struct shader_prev *prev) +OpenGLRenderer::delete_prev(struct shader_prev *prev) { delete_fbo(&prev->fbo); delete_vbo(&prev->vbo); } void -OpenGLRendererPCem::delete_shader(struct glsl_shader *glsl) +OpenGLRenderer::delete_shader(struct glsl_shader *glsl) { int i; for (i = 0; i < glsl->num_passes; ++i) @@ -381,7 +404,7 @@ OpenGLRendererPCem::delete_shader(struct glsl_shader *glsl) } void -OpenGLRendererPCem::delete_glsl(glsl_t *glsl) +OpenGLRenderer::delete_glsl(glsl_t *glsl) { int i; for (i = 0; i < glsl->num_shaders; ++i) @@ -395,7 +418,7 @@ OpenGLRendererPCem::delete_glsl(glsl_t *glsl) } void -OpenGLRendererPCem::create_fbo(struct shader_fbo *fbo) +OpenGLRenderer::create_fbo(struct shader_fbo *fbo) { create_texture(&fbo->texture); @@ -410,7 +433,7 @@ OpenGLRendererPCem::create_fbo(struct shader_fbo *fbo) } void -OpenGLRendererPCem::setup_fbo(struct shader *shader, struct shader_fbo *fbo) +OpenGLRenderer::setup_fbo(struct shader *shader, struct shader_fbo *fbo) { fbo->texture.internal_format = GL_RGBA8; fbo->texture.format = GL_RGBA; @@ -442,7 +465,7 @@ OpenGLRendererPCem::setup_fbo(struct shader *shader, struct shader_fbo *fbo) } void -OpenGLRendererPCem::recreate_fbo(struct shader_fbo *fbo, int width, int height) +OpenGLRenderer::recreate_fbo(struct shader_fbo *fbo, int width, int height) { if (width != fbo->texture.width || height != fbo->texture.height) { glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); @@ -454,7 +477,7 @@ OpenGLRendererPCem::recreate_fbo(struct shader_fbo *fbo, int width, int height) } int -OpenGLRendererPCem::create_default_shader_tex(struct shader_pass *pass) +OpenGLRenderer::create_default_shader_tex(struct shader_pass *pass) { if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_tex_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_tex_src, &pass->program.fragment_shader) || !create_program(&pass->program)) return 0; @@ -474,7 +497,7 @@ OpenGLRendererPCem::create_default_shader_tex(struct shader_pass *pass) } int -OpenGLRendererPCem::create_default_shader_color(struct shader_pass *pass) +OpenGLRenderer::create_default_shader_color(struct shader_pass *pass) { if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_color_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_color_src, &pass->program.fragment_shader) || !create_program(&pass->program)) return 0; @@ -494,7 +517,7 @@ OpenGLRendererPCem::create_default_shader_color(struct shader_pass *pass) /* create the default scene shader */ void -OpenGLRendererPCem::create_scene_shader() +OpenGLRenderer::create_scene_shader() { struct shader scene_shader_conf; memset(&scene_shader_conf, 0, sizeof(struct shader)); @@ -554,7 +577,7 @@ load_texture(const char *f, struct shader_texture *tex) } glsl_t * -OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) +OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) { int i, j; glslp_t *p = glslp_parse(f); @@ -704,7 +727,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) } glsl_t * -OpenGLRendererPCem::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) +OpenGLRenderer::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) { int i; glsl_t *glsl; @@ -731,7 +754,7 @@ OpenGLRendererPCem::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) } void -OpenGLRendererPCem::read_shader_config() +OpenGLRenderer::read_shader_config() { char s[512]; int i, j; @@ -747,10 +770,9 @@ OpenGLRendererPCem::read_shader_config() } } -OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) +OpenGLRenderer::OpenGLRenderer(QWidget *parent) : QWindow(parent->windowHandle()) , renderTimer(new QTimer(this)) - , options(nullptr) { connect(renderTimer, &QTimer::timeout, this, [this]() { this->render(); } ); imagebufs[0] = std::unique_ptr(new uint8_t[2048 * 2048 * 4]); @@ -785,10 +807,10 @@ OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) isFinalized = false; } -OpenGLRendererPCem::~OpenGLRendererPCem() { finalize(); } +OpenGLRenderer::~OpenGLRenderer() { finalize(); } void -OpenGLRendererPCem::initialize() +OpenGLRenderer::initialize() { try { context = new QOpenGLContext(this); @@ -796,15 +818,15 @@ OpenGLRendererPCem::initialize() context->setFormat(format()); if (!context->create()) - throw opengl_init_error_pcem(tr("Couldn't create OpenGL context.")); + throw opengl_init_error(tr("Couldn't create OpenGL context.")); if (!context->makeCurrent(this)) - throw opengl_init_error_pcem(tr("Couldn't switch to OpenGL context.")); + throw opengl_init_error(tr("Couldn't switch to OpenGL context.")); auto version = context->format().version(); if (version.first < 3) - throw opengl_init_error_pcem(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); + throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); glw.initializeOpenGLFunctions(); @@ -813,7 +835,7 @@ OpenGLRendererPCem::initialize() glw.glGetIntegerv(GL_MAJOR_VERSION, &glsl_version[0]); glw.glGetIntegerv(GL_MINOR_VERSION, &glsl_version[1]); if (glsl_version[0] < 3) { - throw opengl_init_error_pcem(tr("OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2").arg(glsl_version[0]).arg(glsl_version[1])); + throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2").arg(glsl_version[0]).arg(glsl_version[1])); } pclog("Using OpenGL %s\n", glw.glGetString(GL_VERSION)); pclog("Using Shading Language %s\n", glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); @@ -1035,7 +1057,7 @@ OpenGLRendererPCem::initialize() glw.glClear(GL_COLOR_BUFFER_BIT); context->swapBuffers(this); - } catch (const opengl_init_error_pcem &e) { + } catch (const opengl_init_error &e) { /* Mark all buffers as in use */ for (auto &flag : buf_usage) flag.test_and_set(); @@ -1051,7 +1073,7 @@ OpenGLRendererPCem::initialize() } void -OpenGLRendererPCem::finalize() +OpenGLRenderer::finalize() { if (isFinalized) return; @@ -1074,7 +1096,7 @@ OpenGLRendererPCem::finalize() } void -OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) +OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) { if (notReady()) return; @@ -1112,7 +1134,7 @@ OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) } std::vector> -OpenGLRendererPCem::getBuffers() +OpenGLRenderer::getBuffers() { std::vector> buffers; @@ -1123,7 +1145,7 @@ OpenGLRendererPCem::getBuffers() } void -OpenGLRendererPCem::exposeEvent(QExposeEvent *event) +OpenGLRenderer::exposeEvent(QExposeEvent *event) { Q_UNUSED(event); @@ -1134,7 +1156,7 @@ OpenGLRendererPCem::exposeEvent(QExposeEvent *event) } void -OpenGLRendererPCem::resizeEvent(QResizeEvent *event) +OpenGLRenderer::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); @@ -1153,7 +1175,7 @@ OpenGLRendererPCem::resizeEvent(QResizeEvent *event) } void -OpenGLRendererPCem::render_pass(struct render_data *data) +OpenGLRenderer::render_pass(struct render_data *data) { int i; GLuint texture_unit = 0; @@ -1298,7 +1320,7 @@ OpenGLRendererPCem::render_pass(struct render_data *data) } bool -OpenGLRendererPCem::event(QEvent *event) +OpenGLRenderer::event(QEvent *event) { Q_UNUSED(event); @@ -1309,13 +1331,13 @@ OpenGLRendererPCem::event(QEvent *event) } QDialog* -OpenGLRendererPCem::getOptions(QWidget *parent) +OpenGLRenderer::getOptions(QWidget *parent) { return new OpenGLShaderManagerDialog(parent); } void -OpenGLRendererPCem::render() +OpenGLRenderer::render() { if (!context) return; @@ -1353,17 +1375,12 @@ OpenGLRendererPCem::render() struct { uint32_t x, y, w, h; - } rect, video_rect; + } rect; rect.x = 0; rect.y = 0; rect.w = source.width(); rect.h = source.height(); - video_rect.x = source.x(); - video_rect.y = source.y(); - video_rect.w = source.width(); - video_rect.h = source.height(); - pass->state.input_size[0] = pass->state.output_size[0] = rect.w; pass->state.input_size[1] = pass->state.output_size[1] = rect.h; diff --git a/src/qt/qt_openglrenderer_pcem.hpp b/src/qt/qt_openglrenderer_pcem.hpp index 706a744fa..9db1e7307 100644 --- a/src/qt/qt_openglrenderer_pcem.hpp +++ b/src/qt/qt_openglrenderer_pcem.hpp @@ -11,12 +11,14 @@ * * * Authors: Teemu Korhonen + * Cacodemon345 * * Copyright 2022 Teemu Korhonen + * Copyright 2025 Cacodemon345 */ -#ifndef QT_OpenGLRendererPCem_HPP -#define QT_OpenGLRendererPCem_HPP +#ifndef QT_OpenGLRenderer_HPP +#define QT_OpenGLRenderer_HPP #if defined Q_OS_MACOS || __arm__ # define NO_BUFFER_STORAGE @@ -37,7 +39,6 @@ #include #include -#include "qt_opengloptions.hpp" #include "qt_renderercommon.hpp" extern "C" @@ -55,14 +56,14 @@ struct render_data { int frame_count; }; -class OpenGLRendererPCem : public QWindow, public RendererCommon { +class OpenGLRenderer : public QWindow, public RendererCommon { Q_OBJECT public: QOpenGLContext *context; - OpenGLRendererPCem(QWidget *parent = nullptr); - ~OpenGLRendererPCem(); + OpenGLRenderer(QWidget *parent = nullptr); + ~OpenGLRenderer(); std::vector> getBuffers() override; @@ -88,7 +89,6 @@ private: std::array, 2> imagebufs; QTimer *renderTimer; - OpenGLOptions *options; QString glslVersion = ""; @@ -98,7 +98,6 @@ private: int max_texture_size = 65536; int frameCounter = 0; - OpenGLOptions::FilterType currentFilter; QOpenGLExtraFunctions glw; struct shader_texture scene_texture; glsl_t *active_shader; @@ -144,12 +143,11 @@ private: private slots: void render(); - //void updateOptions(OpenGLOptions *newOptions); }; -class opengl_init_error_pcem : public std::runtime_error { +class opengl_init_error : public std::runtime_error { public: - opengl_init_error_pcem(const QString &what) + opengl_init_error(const QString &what) : std::runtime_error(what.toStdString()) { } diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 63d35e719..26ea2271f 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -22,7 +22,6 @@ #include "ui_qt_rendererstack.h" #include "qt_hardwarerenderer.hpp" -#include "qt_openglrenderer.hpp" #include "qt_openglrenderer_pcem.hpp" #include "qt_softwarerenderer.hpp" #include "qt_vulkanwindowrenderer.hpp" @@ -341,16 +340,16 @@ RendererStack::createRenderer(Renderer renderer) case Renderer::OpenGL3PCem: { this->createWinId(); - auto hw = new OpenGLRendererPCem(this); + auto hw = new OpenGLRenderer(this); rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection); - connect(hw, &OpenGLRendererPCem::initialized, [=]() { + 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, &OpenGLRendererPCem::errorInitializing, [=]() { + connect(hw, &OpenGLRenderer::errorInitializing, [=]() { /* Renderer not could initialize, fallback to software. */ imagebufs = {}; QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); @@ -361,16 +360,16 @@ RendererStack::createRenderer(Renderer renderer) case Renderer::OpenGL3: { this->createWinId(); - auto hw = new OpenGLRendererPCem(this); + auto hw = new OpenGLRenderer(this); rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection); - connect(hw, &OpenGLRendererPCem::initialized, [=]() { + 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, &OpenGLRendererPCem::errorInitializing, [=]() { + connect(hw, &OpenGLRenderer::errorInitializing, [=]() { /* Renderer not could initialize, fallback to software. */ imagebufs = {}; QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); From 3cad9024c843575792f3d062d73c350396183c1a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 21:14:10 +0600 Subject: [PATCH 0445/1190] Rename the files as well --- src/qt/CMakeLists.txt | 4 ++-- src/qt/{qt_openglrenderer_pcem.cpp => qt_openglrenderer.cpp} | 2 +- src/qt/{qt_openglrenderer_pcem.hpp => qt_openglrenderer.hpp} | 0 src/qt/qt_rendererstack.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/qt/{qt_openglrenderer_pcem.cpp => qt_openglrenderer.cpp} (99%) rename src/qt/{qt_openglrenderer_pcem.hpp => qt_openglrenderer.hpp} (100%) diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 8137be98e..90ea218af 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -87,8 +87,8 @@ add_library(ui STATIC qt_softwarerenderer.hpp qt_hardwarerenderer.cpp qt_hardwarerenderer.hpp - qt_openglrenderer_pcem.cpp - qt_openglrenderer_pcem.hpp + qt_openglrenderer.cpp + qt_openglrenderer.hpp qt_glsl_parser.cpp qt_settings.cpp diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer.cpp similarity index 99% rename from src/qt/qt_openglrenderer_pcem.cpp rename to src/qt/qt_openglrenderer.cpp index 5b1c8518d..97a782f57 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -45,7 +45,7 @@ extern MainWindow* main_window; #include -#include "qt_openglrenderer_pcem.hpp" +#include "qt_openglrenderer.hpp" #include "qt_openglshadermanagerdialog.hpp" extern "C" { diff --git a/src/qt/qt_openglrenderer_pcem.hpp b/src/qt/qt_openglrenderer.hpp similarity index 100% rename from src/qt/qt_openglrenderer_pcem.hpp rename to src/qt/qt_openglrenderer.hpp diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 26ea2271f..ca16b680e 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -22,7 +22,7 @@ #include "ui_qt_rendererstack.h" #include "qt_hardwarerenderer.hpp" -#include "qt_openglrenderer_pcem.hpp" +#include "qt_openglrenderer.hpp" #include "qt_softwarerenderer.hpp" #include "qt_vulkanwindowrenderer.hpp" From 1ac02618b0fa9d6acc8f3f9f1d053706884dc313 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 21:22:52 +0600 Subject: [PATCH 0446/1190] Clean up secondary monitors properly on close --- src/qt/qt_mainwindow.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 85bc0de55..3af9c6f70 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -784,6 +784,14 @@ MainWindow::closeEvent(QCloseEvent *event) ui->stackedWidget->mouse_exit_func(); ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software); + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i] && renderers[i]->isHidden()) { + renderers[i]->show(); + QApplication::processEvents(); + renderers[i]->switchRenderer(RendererStack::Renderer::Software); + QApplication::processEvents(); + } + } qt_nvr_save(); config_save(); From c832729ee565fdd54eadec896f2f9bb72b1cc99b Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 16:31:52 +0100 Subject: [PATCH 0447/1190] Config: Ignore the GL3 stuff on SDL builds. --- src/config.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/config.c b/src/config.c index 5ad804df6..e5fbe59b4 100644 --- a/src/config.c +++ b/src/config.c @@ -77,9 +77,11 @@ #include <86box/snd_opl.h> #include <86box/version.h> +#ifndef USE_SDL_UI /* Deliberate to not make the 86box.h header kitchen-sink. */ #include <86box/qt-glsl.h> extern char gl3_shader_file[MAX_USER_SHADERS][512]; +#endif static int cx; static int cy; @@ -1717,6 +1719,7 @@ load_other_peripherals(void) ini_section_delete_var(cat, temp); } +#ifndef USE_SDL_UI /* Load OpenGL 3.0 renderer options. */ static void load_gl3_shaders(void) @@ -1756,6 +1759,7 @@ load_gl3_shaders(void) } } } +#endif /* Load the specified or a default configuration file. */ void @@ -1853,7 +1857,9 @@ config_load(void) load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ load_other_removable_devices(); /* Other removable devices */ load_other_peripherals(); /* Other peripherals */ +#ifndef USE_SDL_UI load_gl3_shaders(); /* GL3 Shaders */ +#endif /* Migrate renamed device configurations. */ c = ini_find_section(config, "MDA"); @@ -2672,6 +2678,7 @@ save_other_peripherals(void) ini_delete_section_if_empty(config, cat); } +#ifndef USE_SDL_UI /* Save "GL3 Shaders" section. */ static void save_gl3_shaders(void) @@ -2703,6 +2710,7 @@ save_gl3_shaders(void) ini_delete_section_if_empty(config, cat); } +#endif /* Save "Hard Disks" section. */ static void @@ -3059,7 +3067,9 @@ config_save(void) save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ save_other_removable_devices(); /* Other removable devices */ save_other_peripherals(); /* Other peripherals */ +#ifndef USE_SDL_UI save_gl3_shaders(); /* GL3 Shaders */ +#endif ini_write(config, cfg_path); } From 48a5f3280fed8def764c6d8406a252155964eea1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 17:26:44 +0100 Subject: [PATCH 0448/1190] device_t: Increase the selection array to 64 elements. --- src/include/86box/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/device.h b/src/include/86box/device.h index fb86d2adc..91ff2daa6 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -153,7 +153,7 @@ typedef struct _device_config_ { int default_int; const char *file_filter; const device_config_spinner_t spinner; - const device_config_selection_t selection[32]; + const device_config_selection_t selection[64]; const device_config_bios_t bios[32]; } device_config_t; From 8a2d841322c2af189acad170a678cad70cd11c24 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 17:29:42 +0100 Subject: [PATCH 0449/1190] OpenGL Renderer: Mark reloadRendererOption() as override, fixes compile on Mac. --- src/qt/qt_openglrenderer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_openglrenderer.hpp b/src/qt/qt_openglrenderer.hpp index 9db1e7307..4d1f68acb 100644 --- a/src/qt/qt_openglrenderer.hpp +++ b/src/qt/qt_openglrenderer.hpp @@ -70,7 +70,7 @@ public: void finalize() override final; bool hasOptions() const override { return true; } QDialog *getOptions(QWidget *parent) override; - bool reloadRendererOption() { return true; } + bool reloadRendererOption() override { return true; } signals: void initialized(); From c763c6db169c2b4f2ed9d1f8177d36d67166edfa Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 17:31:18 +0100 Subject: [PATCH 0450/1190] INI: Include so iswspace() is also found in Linux. --- src/ini.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ini.c b/src/ini.c index 503b17ae3..f5dfdef46 100644 --- a/src/ini.c +++ b/src/ini.c @@ -33,6 +33,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/ini.h> From 6fa39b3a67a0818f3d6a2535e5074d5901558cc1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 17:32:46 +0100 Subject: [PATCH 0451/1190] OpenGL Renderer: Explicitly cast const char * to char *. --- src/qt/qt_openglrenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 97a782f57..860b5d303 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -174,7 +174,7 @@ OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const ch const char *source[3]; char version[50]; int ver = 0; - char *version_loc = strstr(program, "#version"); + char *version_loc = (char *) strstr(program, "#version"); if (version_loc) ver = (int) strtol(version_loc + 8, (char **) &program, 10); else { From df85868e00cd3d8e71300f8d89323d8fd0be5631 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 17:34:33 +0100 Subject: [PATCH 0452/1190] Config: Brought the strncpy() in load_gl3_shaders() in line with the other stncpy()'s. --- src/config.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index e5fbe59b4..f68b23c37 100644 --- a/src/config.c +++ b/src/config.c @@ -1740,7 +1740,10 @@ load_gl3_shaders(void) if (general) { p = ini_section_get_string(general, "video_gl_shader", NULL); if (p) { - strncpy(gl3_shader_file[0], p, 512); + if (strlen(p) > 511) + fatal("Configuration: Length of video_gl_shadr is more than 511\n"); + else + strncpy(gl3_shader_file[0], p, 511); ini_delete_var(config, general, "video_gl_shader"); return; } From daf6e242efa3f244d05aa3f5ba6cf4b50b3c66a5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 18:00:28 +0100 Subject: [PATCH 0453/1190] QT GLSL Parser: More explicit const char * to char * casts. --- src/qt/qt_glsl_parser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index bf02014db..9a0a0fc03 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -101,11 +101,11 @@ static char *load_file(const char *fn) { static void strip_lines(const char *program, const char *starts_with) { /* strip parameters */ - char *ptr = strstr(program, starts_with); - while (ptr) { + char *ptr = (char *) strstr(program, starts_with); + while (ptr != nullptr) { while (*ptr != '\n' && *ptr != '\0') *ptr++ = ' '; - ptr = strstr(program, starts_with); + ptr = (char *) strstr(program, starts_with); } } From df1f739b90f53c1532492f6fa50c7585f0e95718 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 23:02:18 +0600 Subject: [PATCH 0454/1190] OpenGL 3.x screenshots are now processed --- src/qt/qt_openglrenderer.cpp | 114 +++++++++-------------------------- src/qt/qt_renderercommon.hpp | 2 + src/qt/qt_rendererstack.cpp | 7 ++- src/qt/qt_rendererstack.hpp | 4 ++ 4 files changed, 39 insertions(+), 88 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 860b5d303..37afd4810 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1612,95 +1612,35 @@ OpenGLRenderer::render() render_pass(&data); } - if (1) { - // if (video_focus_dim && !(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)) { -#if 0 - if (0) { - struct shader_pass *pass = &active_shader->fs_color; - GLfloat r = 0; - GLfloat g = 0; - GLfloat b = 0; - GLfloat a = 0x80 / (float) 0xff; + if (monitors[r_monitor_index].mon_screenshots) { + int width = destination.width() * devicePixelRatio(), height = destination.height() * devicePixelRatio(); + char path[1024]; + char fn[256]; + + memset(fn, 0, sizeof(fn)); + memset(path, 0, sizeof(path)); + + path_append_filename(path, usr_path, SCREENSHOT_PATH); + + if (!plat_dir_check(path)) + plat_dir_create(path); + + path_slash(path); + strcat(path, "Monitor_"); + snprintf(&path[strlen(path)], 42, "%d_", r_monitor_index + 1); + + plat_tempfile(fn, NULL, (char*)".png"); + strcat(path, fn); - GLfloat colors[] = { r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a }; + unsigned char *rgba = (unsigned char *)calloc(1, width * height * 4); + + glw.glFinish(); + glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba); - glw.glBindVertexArray(pass->vertex_array); - - glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.color); - glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(GLfloat), colors); - glw.glBindBuffer(GL_ARRAY_BUFFER, 0); - - memset(&data, 0, sizeof(struct render_data)); - data.pass = -3; - data.shader_pass = pass; - data.texture = 0; - data.output_size = orig_output_size; - data.orig_pass = orig; - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - render_pass(&data); - glDisable(GL_BLEND); - } - - if (flash.enabled) { - struct shader_pass *pass = &active_shader->fs_color; - GLfloat r = (flash.color[0] & 0xff) / (float)0xff; - GLfloat g = (flash.color[1] & 0xff) / (float)0xff; - GLfloat b = (flash.color[2] & 0xff) / (float)0xff; - GLfloat a = (flash.color[3] & 0xff) / (float)0xff; - - GLfloat colors[] = {r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a}; - - glw.glBindVertexArray(pass->vertex_array); - - glw.glBindBuffer(GL_ARRAY_BUFFER, pass->vbo.color); - glw.glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(GLfloat), colors); - glw.glBindBuffer(GL_ARRAY_BUFFER, 0); - - memset(&data, 0, sizeof(struct render_data)); - data.pass = -3; - data.shader_pass = pass; - data.texture = 0; - data.output_size = orig_output_size; - data.orig_pass = orig; - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - render_pass(&data); - glDisable(GL_BLEND); - } -#endif - } else { -#if 0 - take_screenshot = 0; - - int width = window_rect.w; - int height = window_rect.h; - - SDL_GetWindowSize(window, &width, &height); - - unsigned char *rgba = (unsigned char *)malloc(width * height * 4); - - glFinish(); - glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba); - - int x, y; - unsigned char *rgb = (unsigned char *)malloc(width * height * 3); - - for (x = 0; x < width; ++x) { - for (y = 0; y < height; ++y) { - rgb[(y * width + x) * 3 + 0] = rgba[((height - y - 1) * width + x) * 4 + 0]; - rgb[(y * width + x) * 3 + 1] = rgba[((height - y - 1) * width + x) * 4 + 1]; - rgb[(y * width + x) * 3 + 2] = rgba[((height - y - 1) * width + x) * 4 + 2]; - } - } - - screenshot_taken(rgb, width, height); - - free(rgb); - free(rgba); -#endif + QImage image(rgba, width, height, QImage::Format_RGBA8888); + image.mirrored(false, true).save(path, "png"); + monitors[r_monitor_index].mon_screenshots--; + free(rgba); } glw.glDisable(GL_FRAMEBUFFER_SRGB); diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index f3f5d2223..bbda9516b 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -36,6 +36,8 @@ public: virtual void reloadOptions() { } /* Make the renderer reload itself */ virtual bool reloadRendererOption() { return false; } + /* Should the renderer take screenshots itself? */ + virtual bool rendererTakeScreenshot() { return false; } int r_monitor_index = 0; diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index ca16b680e..38f087622 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -63,6 +63,7 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index) : QStackedWidget(parent) , ui(new Ui::RendererStack) { + rendererTakesScreenshots = false; #ifdef Q_OS_WINDOWS int raw = 1; #else @@ -305,6 +306,7 @@ RendererStack::switchRenderer(Renderer renderer) void RendererStack::createRenderer(Renderer renderer) { + rendererTakesScreenshots = false; switch (renderer) { default: case Renderer::Software: @@ -360,6 +362,7 @@ RendererStack::createRenderer(Renderer renderer) case Renderer::OpenGL3: { this->createWinId(); + this->rendererTakesScreenshots = true; auto hw = new OpenGLRenderer(this); rendererWindow = hw; connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection); @@ -424,6 +427,8 @@ RendererStack::createRenderer(Renderer renderer) this->setStyleSheet("background-color: black"); + rendererWindow->r_monitor_index = m_monitor_index; + currentBuf = 0; if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::OpenGL3PCem) { @@ -454,7 +459,7 @@ RendererStack::blit(int x, int y, int w, int h) video_copy(scanline, &(monitors[m_monitor_index].target_buffer->line[y1][x]), w * 4); } - if (monitors[m_monitor_index].mon_screenshots) { + if (monitors[m_monitor_index].mon_screenshots && !rendererTakesScreenshots) { video_screenshot_monitor((uint32_t *) imagebits, x, y, 2048, m_monitor_index); } video_blit_complete_monitor(m_monitor_index); diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 32ed5f7ca..a84773c72 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -15,6 +15,8 @@ #include "qt_renderercommon.hpp" +#include + namespace Ui { class RendererStack; } @@ -110,6 +112,8 @@ private: RendererCommon *rendererWindow { nullptr }; std::unique_ptr current; + + std::atomic_bool rendererTakesScreenshots; }; #endif // QT_RENDERERCONTAINER_HPP From c2eb7730296d53c39bcf230b0d8334499324e782 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 10 Mar 2025 23:27:19 +0600 Subject: [PATCH 0455/1190] Qt: Fix more compile errors --- src/qt/qt_openglshadermanagerdialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 0bf083252..7f8a19414 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -46,7 +46,7 @@ OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent) QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget); item->setText(filename); item->setData(Qt::UserRole + 1, QString(gl3_shader_file[i])); - item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile); + item->setData(Qt::UserRole + 2, (qulonglong)(uintptr_t)shaderfile); } } } @@ -174,7 +174,7 @@ void OpenGLShaderManagerDialog::on_buttonAdd_clicked() QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget); item->setText(filename); item->setData(Qt::UserRole + 1, res); - item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile); + item->setData(Qt::UserRole + 2, (qulonglong)(uintptr_t)shaderfile); if (ui->shaderListWidget->count()) { ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1); } From 2e77b47f89ec960416bb362dc75551afedd77800 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 11 Mar 2025 00:13:51 +0600 Subject: [PATCH 0456/1190] Call `glViewport` with correct function pointer --- src/qt/qt_openglrenderer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 37afd4810..6f024f36f 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1103,14 +1103,6 @@ OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) context->makeCurrent(this); -#ifdef Q_OS_MACOS - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); -#endif - if (source.width() != w || source.height() != h) { glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); glw.glTexImage2D(GL_TEXTURE_2D, 0, (GLenum) QOpenGLTexture::RGBA8_UNorm, w, h, 0, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); @@ -1129,6 +1121,14 @@ OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) source.setRect(x, y, w, h); onResize(this->width(), this->height()); +#ifdef Q_OS_MACOS + glw.glViewport( + destination.x() * devicePixelRatio(), + destination.y() * devicePixelRatio(), + destination.width() * devicePixelRatio(), + destination.height() * devicePixelRatio()); +#endif + if (video_framerate == -1) render(); } From f1720fdee481a226e4cc4269296a49be03269553 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 11 Mar 2025 01:20:00 +0600 Subject: [PATCH 0457/1190] Attempt fixing crash on NetBSD --- src/qt/qt_platform.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 35dbc0081..a1deb4137 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -368,6 +368,8 @@ plat_mmap(size_t size, uint8_t executable) void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE | (executable ? MAP_JIT : 0), -1, 0); # elif defined(PROT_MPROTECT) void *ret = mmap(0, size, PROT_MPROTECT(PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0)), MAP_ANON | MAP_PRIVATE, -1, 0); + if (ret) + mprotect(ret, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0)); # else void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE, -1, 0); # endif From df5cc9b03876ac34f296a8ad900e116182fee47f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Mar 2025 21:31:29 +0100 Subject: [PATCH 0458/1190] VIA PIPC: Restore old readout on the VT82C596/B southbridges, where it was correct, fixes the P6BAT. --- src/chipset/via_pipc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 11a192450..f7f5bf208 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -61,6 +61,7 @@ #define VIA_PIPC_586B 0x05864700 #define VIA_PIPC_596A 0x05960900 #define VIA_PIPC_596B 0x05962300 +#define VIA_PIPC_596 0x0596 #define VIA_PIPC_686A 0x06861400 #define VIA_PIPC_686B 0x06864000 #define VIA_PIPC_8231 0x82311000 @@ -413,7 +414,7 @@ pipc_reset_hard(void *priv) dev->power_regs[0x34] = 0x68; dev->power_regs[0x40] = 0x20; - dev->power_regs[0x42] = 0x00; + dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_596) ? 0x50 : 0x00; acpi_set_irq_line(dev->acpi, 0x00); dev->power_regs[0x48] = 0x01; @@ -1595,7 +1596,7 @@ pipc_reset(void *priv) pipc_write(pm_func, 0x48, 0x01, priv); pipc_write(pm_func, 0x49, 0x00, priv); - dev->power_regs[0x42] = 0x00; + dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_596) ? 0x50 : 0x00; acpi_set_irq_line(dev->acpi, 0x00); pipc_write(1, 0x04, 0x80, priv); From 9e5697126b08ffb6329a40151da6f9caf1ea7b67 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 11 Mar 2025 10:40:40 +0100 Subject: [PATCH 0459/1190] QT: Fix two strings. --- src/qt/qt_main.cpp | 2 +- src/qt/qt_platform.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index b48d272c5..f6ddddd32 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -665,7 +665,7 @@ main(int argc, char *argv[]) /* Force raw input if a debugger is present. */ if (IsDebuggerPresent()) { - pclog("WARNING: Debugged detected, forcing raw input\n"); + pclog("WARNING: Debugger detected, forcing raw input\n"); hook_enabled = 0; } diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index a1deb4137..ee8d8842a 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -647,7 +647,7 @@ ProgSettings::reloadStrings() translatedstrings[STRING_NET_ERROR] = QCoreApplication::translate("", "Failed to initialize network driver").toStdWString(); translatedstrings[STRING_NET_ERROR_DESC] = QCoreApplication::translate("", "The network configuration will be switched to the null driver").toStdWString(); translatedstrings[STRING_ESCP_ERROR_TITLE] = QCoreApplication::translate("", "Unable to find Dot-Matrix fonts").toStdWString(); - translatedstrings[STRING_ESCP_ERROR_DESC] = QCoreApplication::translate("", "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulatio of the Generic ESC/P Dot-Matrix Printer.").toStdWString(); + translatedstrings[STRING_ESCP_ERROR_DESC] = QCoreApplication::translate("", "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer.").toStdWString(); } wchar_t * From 4d5adeae36d47085da9bcdd0014dbe1b2e12b391 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 11 Mar 2025 20:35:05 +0600 Subject: [PATCH 0460/1190] Restore older GLSL version code --- src/qt/qt_openglrenderer.cpp | 47 +++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 6f024f36f..b451c2245 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -34,6 +34,7 @@ extern MainWindow* main_window; #include #include #include +#include #include #include @@ -171,30 +172,33 @@ OpenGLRenderer::create_program(struct shader_program *program) int OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) { - const char *source[3]; + QRegularExpression versionRegex("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption); + QString progSource = QString(program); + QByteArray finalSource = nullptr; + const char *source[5]; char version[50]; int ver = 0; char *version_loc = (char *) strstr(program, "#version"); - if (version_loc) - ver = (int) strtol(version_loc + 8, (char **) &program, 10); - else { - ver = glsl_version[0] * 100 + glsl_version[1] * 10; - if (ver == 300) - ver = 130; - else if (ver == 310) - ver = 140; - else if (ver == 320) - ver = 150; + if (version_loc) { + snprintf(version, 49, "%s\n", versionRegex.match(progSource).captured(1).toLatin1().data()); + progSource.remove(versionRegex); + } else { + snprintf(version, 49, "%s\n", this->glslVersion.toLatin1().data()); } - sprintf(version, "#version %d\n", ver); - source[0] = version; - source[1] = prepend ? prepend : ""; - source[2] = program; + + /* Remove parameter lines. */ + progSource.remove(QRegularExpression("^\\s*#pragma parameter.*?\\n", QRegularExpression::MultilineOption)); - pclog("GLSL version %d\n", ver); + finalSource = progSource.toLatin1(); + + source[0] = version; + source[1] = "\n#extension GL_ARB_shading_language_420pack : enable\n"; + source[2] = prepend ? prepend : ""; + source[3] = "\n#line 1\n"; + source[4] = finalSource.data(); GLuint shader = glw.glCreateShader(shader_type); - glw.glShaderSource(shader, 3, source, NULL); + glw.glShaderSource(shader, 5, source, NULL); glw.glCompileShader(shader); GLint status = 0; @@ -840,6 +844,15 @@ OpenGLRenderer::initialize() pclog("Using OpenGL %s\n", glw.glGetString(GL_VERSION)); pclog("Using Shading Language %s\n", glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); + glslVersion = reinterpret_cast(glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); + glslVersion.truncate(4); + glslVersion.remove('.'); + glslVersion.prepend("#version "); + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) + glslVersion.append(" es"); + else if (context->format().profile() == QSurfaceFormat::CoreProfile) + glslVersion.append(" core"); + glw.glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); pclog("Max texture size: %dx%d\n", max_texture_size, max_texture_size); From e2aa66a523d6b465b277c86a23e6a0e8cc9f8eb6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 12 Mar 2025 19:55:09 +0600 Subject: [PATCH 0461/1190] Qt: Make tooltip displays consistent --- src/qt/qdarkstyle/dark/darkstyle.qss | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/qt/qdarkstyle/dark/darkstyle.qss b/src/qt/qdarkstyle/dark/darkstyle.qss index 6e1ec4b06..134d6708e 100644 --- a/src/qt/qdarkstyle/dark/darkstyle.qss +++ b/src/qt/qdarkstyle/dark/darkstyle.qss @@ -130,16 +130,6 @@ QStatusBar::item { border: none; } -QStatusBar QToolTip { - background-color: #666666; - border: 1px solid #272727; - color: #272727; - /* Remove padding, for fix combo box tooltip */ - padding: 0px; - /* Reducing transparency to read better */ - opacity: 230; -} - QStatusBar QLabel { /* Fixes Spyder #9120, #9121 */ background: transparent; From 1c54261a1b1a3e813d5cb2940e959b493b55f26f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 12 Mar 2025 21:16:53 +0600 Subject: [PATCH 0462/1190] Fix shader manager dialog crash when using multi-monitors --- src/qt/qt_openglrenderer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index b451c2245..ef0332500 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -809,6 +809,7 @@ OpenGLRenderer::OpenGLRenderer(QWidget *parent) source.setRect(0, 0, 100, 100); isInitialized = false; isFinalized = false; + context = nullptr; } OpenGLRenderer::~OpenGLRenderer() { finalize(); } @@ -1088,7 +1089,7 @@ OpenGLRenderer::initialize() void OpenGLRenderer::finalize() { - if (isFinalized) + if (isFinalized || !context) return; context->makeCurrent(this); From 7261a0d74b11842370b2a326a96589f602f8133a Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 12 Mar 2025 17:53:58 +0100 Subject: [PATCH 0463/1190] Hook input: Fix Pause scan code. --- src/qt/qt_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index f6ddddd32..10900da0d 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -359,7 +359,7 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) } else if (!(lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000013)) { /* Pause - send E1 1D. */ win_keyboard_handle(0xe1, 0, 0, 0); - win_keyboard_handle(0x1d, LLKHF_UP, 0, 0); + win_keyboard_handle(0x1d, lpKdhs->flags & LLKHF_UP, 0, 0); } } else if (!last && (lpKdhs->scanCode == 0x00000036)) /* Non-fake right shift. */ From c73c7212f8baab1b25503a4f962d90e8c7a2330c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 12 Mar 2025 18:02:01 +0100 Subject: [PATCH 0464/1190] QT OpenGL Renderer: Remove the unused variable "ver". --- src/qt/qt_openglrenderer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index ef0332500..f654747eb 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -177,7 +177,6 @@ OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const ch QByteArray finalSource = nullptr; const char *source[5]; char version[50]; - int ver = 0; char *version_loc = (char *) strstr(program, "#version"); if (version_loc) { snprintf(version, 49, "%s\n", versionRegex.match(progSource).captured(1).toLatin1().data()); From f9572be8a5651437efe328e04516bd1666207caf Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 12 Mar 2025 23:54:57 +0600 Subject: [PATCH 0465/1190] Alter `#version` statements for macOS --- src/qt/qt_openglrenderer.cpp | 110 +++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 45 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index f654747eb..70c70527a 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -74,54 +74,74 @@ extern int video_vsync; extern int video_focus_dim; extern int video_refresh_rate; -const char *vertex_shader_default_tex_src = "#version 130\n" - "\n" - "in vec4 VertexCoord;\n" - "in vec2 TexCoord;\n" - "\n" - "out vec2 texCoord;\n" - "\n" - "void main()\n" - "{\n" - " gl_Position = VertexCoord;\n" - " texCoord = TexCoord;\n" - "}\n"; +const char* vertex_shader_default_tex_src = +#ifdef __APPLE__ + "#version 150\n" +#else + "#version 130\n" +#endif + "\n" + "in vec4 VertexCoord;\n" + "in vec2 TexCoord;\n" + "\n" + "out vec2 texCoord;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = VertexCoord;\n" + " texCoord = TexCoord;\n" + "}\n"; -const char *fragment_shader_default_tex_src = "#version 130\n" - "\n" - "in vec2 texCoord;\n" - "uniform sampler2D Texture;\n" - "\n" - "out vec4 color;" - "\n" - "void main()\n" - "{\n" - " color = texture(Texture, texCoord);\n" - "}\n"; +const char* fragment_shader_default_tex_src = +#ifdef __APPLE__ + "#version 150\n" +#else + "#version 130\n" +#endif + "\n" + "in vec2 texCoord;\n" + "uniform sampler2D Texture;\n" + "\n" + "out vec4 color;" + "\n" + "void main()\n" + "{\n" + " color = texture(Texture, texCoord);\n" + "}\n"; -const char *vertex_shader_default_color_src = "#version 130\n" - "\n" - "in vec4 VertexCoord;\n" - "in vec4 Color;\n" - "\n" - "out vec4 color;\n" - "\n" - "void main()\n" - "{\n" - " gl_Position = VertexCoord;\n" - " color = Color;\n" - "}\n"; +const char* vertex_shader_default_color_src = +#ifdef __APPLE__ + "#version 150\n" +#else + "#version 130\n" +#endif + "\n" + "in vec4 VertexCoord;\n" + "in vec4 Color;\n" + "\n" + "out vec4 color;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = VertexCoord;\n" + " color = Color;\n" + "}\n"; -const char *fragment_shader_default_color_src = "#version 130\n" - "\n" - "in vec4 color;\n" - "\n" - "out vec4 outColor;" - "\n" - "void main()\n" - "{\n" - " outColor = color;\n" - "}\n"; +const char* fragment_shader_default_color_src = +#ifdef __APPLE__ + "#version 150\n" +#else + "#version 130\n" +#endif + "\n" + "in vec4 color;\n" + "\n" + "out vec4 outColor;" + "\n" + "void main()\n" + "{\n" + " outColor = color;\n" + "}\n"; static inline int next_pow2(unsigned int n) From 0d22e736767975d9f77da1295d404bc277a90bb1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 13 Mar 2025 00:50:16 +0600 Subject: [PATCH 0466/1190] Microtouch: Properly restore system cursor if "Show Crosshair" is enabled --- src/qt/qt_rendererstack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 38f087622..43e696085 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -270,7 +270,7 @@ RendererStack::leaveEvent(QEvent *event) { mousedata.mouse_tablet_in_proximity = 0; - if (mouse_input_mode == 1 && QApplication::overrideCursor()) { + if (mouse_input_mode >= 1 && QApplication::overrideCursor()) { while (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); } From 6779a3c1bdef77a49832a03663fab16b7e96d99f Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 12 Mar 2025 23:16:16 +0100 Subject: [PATCH 0467/1190] Hook Keyboard Input: Ignore the extended flag for scan codes F1 and F2, fixes the passing of the Hanja and Han/Eng keys to the guest. --- src/qt/qt_main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 10900da0d..627455948 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -370,7 +370,11 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) else if (last && (lpKdhs->scanCode == 0x00000036)) last = 0; - win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0); + if ((lpKdhs->scanCode == 0xf1) || (lpKdhs->scanCode == 0xf2)) + /* Hanja and Han/Eng keys, suppress the extended flag. */ + win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, 0, 0); + else + win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0); return ret; } From 7c4df701cb37bb67b5decf625bcac81d64b9f967 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 13 Mar 2025 19:55:46 +0600 Subject: [PATCH 0468/1190] Add option to inhibit multimedia keys from host on Windows --- src/86box.c | 1 + src/config.c | 6 + src/include/86box/86box.h | 1 + src/qt/languages/86box.pot | 3 + src/qt/qt_main.cpp | 46 +++++++- src/qt/qt_progsettings.cpp | 9 +- src/qt/qt_progsettings.ui | 229 +++++++++++++++++++------------------ 7 files changed, 181 insertions(+), 114 deletions(-) diff --git a/src/86box.c b/src/86box.c index 24f6f0deb..5bf8177e8 100644 --- a/src/86box.c +++ b/src/86box.c @@ -213,6 +213,7 @@ int hook_enabled = 1; /* (C) Keyboar int test_mode = 0; /* (C) Test mode */ char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */ int sound_muted = 0; /* (C) Is sound muted? */ +int inhibit_multimedia_keys; /* (C) Inhibit multimedia keys on Windows. */ int other_ide_present = 0; /* IDE controllers from non-IDE cards are present */ diff --git a/src/config.c b/src/config.c index f68b23c37..3bb9fb59a 100644 --- a/src/config.c +++ b/src/config.c @@ -131,6 +131,8 @@ load_general(void) video_filter_method = ini_section_get_int(cat, "video_filter_method", 1); + inhibit_multimedia_keys = ini_section_get_int(cat, "inhibit_multimedia_keys", 0); + force_43 = !!ini_section_get_int(cat, "force_43", 0); scale = ini_section_get_int(cat, "scale", 1); if (scale > 9) @@ -1900,6 +1902,10 @@ save_general(void) const char *va_name; + ini_section_set_int(cat, "inhibit_multimedia_keys", inhibit_multimedia_keys); + if (inhibit_multimedia_keys == 0) + ini_section_delete_var(cat, "inhibit_multimedia_keys"); + ini_section_set_int(cat, "sound_muted", sound_muted); if (sound_muted == 0) ini_section_delete_var(cat, "sound_muted"); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 768ca6267..40e1f7927 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -107,6 +107,7 @@ extern uint64_t instru_run_ms; #define window_y monitor_settings[0].mon_window_y #define window_w monitor_settings[0].mon_window_w #define window_h monitor_settings[0].mon_window_h +extern int inhibit_multimedia_keys; /* (C) Inhibit multimedia keys on Windows. */ extern int window_remember; extern int vid_resize; /* (C) allow resizing */ extern int invert_display; /* (C) invert the display */ diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 65cc32f85..93a47a1cb 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2141,3 +2141,6 @@ msgstr "" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "" + +msgid "Inhibit multimedia keys on Windows" +msgstr "" diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 627455948..2e0ce33e0 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -226,7 +226,30 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) detection; rest can't be reliably detected. */ DWORD vkCode = lpKdhs->vkCode; bool up = !!(lpKdhs->flags & LLKHF_UP); - ret = CallNextHookEx(NULL, nCode, wParam, lParam);; + + if (inhibit_multimedia_keys + && (lpKdhs->vkCode == VK_MEDIA_PLAY_PAUSE + || lpKdhs->vkCode == VK_MEDIA_NEXT_TRACK + || lpKdhs->vkCode == VK_MEDIA_PREV_TRACK + || lpKdhs->vkCode == VK_VOLUME_DOWN + || lpKdhs->vkCode == VK_VOLUME_UP + || lpKdhs->vkCode == VK_VOLUME_MUTE + || lpKdhs->vkCode == VK_MEDIA_STOP + || lpKdhs->vkCode == VK_LAUNCH_MEDIA_SELECT + || lpKdhs->vkCode == VK_LAUNCH_MAIL + || lpKdhs->vkCode == VK_LAUNCH_APP1 + || lpKdhs->vkCode == VK_LAUNCH_APP2 + || lpKdhs->vkCode == VK_HELP + || lpKdhs->vkCode == VK_BROWSER_BACK + || lpKdhs->vkCode == VK_BROWSER_FORWARD + || lpKdhs->vkCode == VK_BROWSER_FAVORITES + || lpKdhs->vkCode == VK_BROWSER_HOME + || lpKdhs->vkCode == VK_BROWSER_REFRESH + || lpKdhs->vkCode == VK_BROWSER_SEARCH + || lpKdhs->vkCode == VK_BROWSER_STOP)) + ret = TRUE; + else + ret = CallNextHookEx(NULL, nCode, wParam, lParam); switch (vkCode) { @@ -349,6 +372,27 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) ret = TRUE; else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) ret = TRUE; + else if (inhibit_multimedia_keys + && (lpKdhs->vkCode == VK_MEDIA_PLAY_PAUSE + || lpKdhs->vkCode == VK_MEDIA_NEXT_TRACK + || lpKdhs->vkCode == VK_MEDIA_PREV_TRACK + || lpKdhs->vkCode == VK_VOLUME_DOWN + || lpKdhs->vkCode == VK_VOLUME_UP + || lpKdhs->vkCode == VK_VOLUME_MUTE + || lpKdhs->vkCode == VK_MEDIA_STOP + || lpKdhs->vkCode == VK_LAUNCH_MEDIA_SELECT + || lpKdhs->vkCode == VK_LAUNCH_MAIL + || lpKdhs->vkCode == VK_LAUNCH_APP1 + || lpKdhs->vkCode == VK_LAUNCH_APP2 + || lpKdhs->vkCode == VK_HELP + || lpKdhs->vkCode == VK_BROWSER_BACK + || lpKdhs->vkCode == VK_BROWSER_FORWARD + || lpKdhs->vkCode == VK_BROWSER_FAVORITES + || lpKdhs->vkCode == VK_BROWSER_HOME + || lpKdhs->vkCode == VK_BROWSER_REFRESH + || lpKdhs->vkCode == VK_BROWSER_SEARCH + || lpKdhs->vkCode == VK_BROWSER_STOP)) + ret = TRUE; else ret = CallNextHookEx(NULL, nCode, wParam, lParam); diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 9e1f8c168..6ec76a290 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -115,14 +115,19 @@ ProgSettings::ProgSettings(QWidget *parent) mouseSensitivity = mouse_sensitivity; ui->horizontalSlider->setValue(mouseSensitivity * 100.); ui->openDirUsrPath->setChecked(open_dir_usr_path > 0); + ui->checkBoxMultimediaKeys->setChecked(inhibit_multimedia_keys); +#ifndef Q_OS_WINDOWS + ui->checkBoxMultimediaKeys->setHidden(true); +#endif } 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; + lang_id = ui->comboBoxLanguage->currentData().toUInt(); + open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; + inhibit_multimedia_keys = ui->checkBoxMultimediaKeys->isChecked(); loadTranslators(QCoreApplication::instance()); reloadStrings(); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index ac4327341..dc5674425 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -27,8 +27,122 @@
    - QLayout::SetFixedSize + 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> + + + Select media images from program working directory + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 30 + + + + (System Default) + + + + + + + + Default + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + Icon set: + + + + + + + Language: + + + + + + + 10 + + + 200 + + + 10 + + + 20 + + + 100 + + + Qt::Orientation::Horizontal + + + @@ -51,13 +165,6 @@ - - - - Icon set: - - - @@ -65,77 +172,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - 10 - - - 200 - - - 10 - - - 20 - - - 100 - - - Qt::Horizontal - - - - - - - 30 - - - - (System Default) - - - - - - - - Language: - - - - - - - Default - - - @@ -143,39 +179,10 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - <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 + Inhibit multimedia keys on Windows From b1a02a6d137be594542741bde9f6c6b4571cd43b Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Mar 2025 20:59:59 +0100 Subject: [PATCH 0469/1190] Windows CD-ROM disc change notification: verify the correct bit of the unit mask. --- src/qt/qt_winrawinputfilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 13e0ec9a7..cff9950b2 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -160,7 +160,7 @@ notify_drives(ULONG unitmask, int empty) char p[1024] = { 0 }; for (int i = 0; i < 26; ++i) { - if (unitmask & 0x1) { + if (unitmask & (1 << i)) { cdrom_t *dev = NULL; sprintf(p, "ioctl://\\\\.\\%c:", 'A' + i); From 8722fe0080d312c469e2750f60644fa67753facd Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Mar 2025 21:17:25 +0100 Subject: [PATCH 0470/1190] CD-ROM: Optimize Windows IOCTL disc change checking. --- src/cdrom/cdrom.c | 4 ++++ src/include/86box/cdrom.h | 4 ++++ src/qt/qt_winrawinputfilter.cpp | 27 ++++++++------------------- src/qt/win_cdrom_ioctl.c | 16 ++++++++++++---- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index aea1afb94..c20e18db8 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -46,6 +46,7 @@ cdrom_t cdrom[CDROM_NUM] = { 0 }; int cdrom_interface_current; +int cdrom_assigned_letters = 0; #ifdef ENABLE_CDROM_LOG int cdrom_do_log = ENABLE_CDROM_LOG; @@ -2795,6 +2796,8 @@ cdrom_global_init(void) void cdrom_hard_reset(void) { + cdrom_assigned_letters = 0; + for (uint8_t i = 0; i < CDROM_NUM; i++) { cdrom_t *dev = &cdrom[i]; @@ -2825,6 +2828,7 @@ cdrom_hard_reset(void) } dev->cd_status = CD_STATUS_EMPTY; + dev->host_letter = 0xff; if (strlen(dev->image_path) > 0) { #ifdef _WIN32 diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 7c028d7d6..805f08b10 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -335,6 +335,8 @@ typedef struct cdrom { uint8_t subch_buffer[96]; int cdrom_sector_size; + /* Only used on Windows hosts for disc change notifications. */ + uint8_t host_letter; /* Needs some extra breathing space in case of overflows. */ uint8_t raw_buffer[4096]; @@ -437,6 +439,8 @@ extern int cdrom_is_empty(const uint8_t id); extern void cdrom_eject(const uint8_t id); extern void cdrom_reload(const uint8_t id); +extern int cdrom_assigned_letters; + #ifdef __cplusplus } #endif diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index cff9950b2..8a2841f97 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -157,27 +157,16 @@ WindowsRawInputFilter::~WindowsRawInputFilter() static void notify_drives(ULONG unitmask, int empty) { - char p[1024] = { 0 }; + if (unitmask & cdrom_assigned_letters) for (int i = 0; i < CDROM_NUM; i++) { + cdrom_t *dev = &(cdrom[i]); - for (int i = 0; i < 26; ++i) { - if (unitmask & (1 << i)) { - cdrom_t *dev = NULL; - - sprintf(p, "ioctl://\\\\.\\%c:", 'A' + i); - - for (int i = 0; i < CDROM_NUM; i++) - if (!stricmp(cdrom[i].image_path, p)) { - dev = &(cdrom[i]); - if (empty) - cdrom_set_empty(dev); - else - cdrom_update_status(dev); - // pclog("CD-ROM %i : Drive notified of media %s\n", - // dev->id, empty ? "removal" : "change"); - } + if ((dev->host_letter != 0xff) && + (unitmask & (1 << dev->host_letter))) { + if (empty) + cdrom_set_empty(dev); + else + cdrom_update_status(dev); } - - unitmask = unitmask >> 1; } } diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 621cf0b76..309f861e0 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -748,6 +748,11 @@ ioctl_close(void *local) log_close(ioctl->log); ioctl->log = NULL; + + cdrom_assigned_letters &= ~(1 << ioctl->dev->host_letter); + ioctl->dev->host_letter = 0xff; + + free(ioctl); } static void @@ -788,19 +793,22 @@ ioctl_open(cdrom_t *dev, const char *drv) ioctl_t *ioctl = (ioctl_t *) calloc(1, sizeof(ioctl_t)); if (ioctl != NULL) { - char n[1024] = { 0 }; + char n[1024] = { 0 }; sprintf(n, "CD-ROM %i IOCtl", dev->id + 1); - ioctl->log = log_open(n); + ioctl->log = log_open(n); memset(ioctl->path, 0x00, sizeof(ioctl->path)); wsprintf(ioctl->path, L"%S", &(drv[8])); ioctl_log(ioctl->log, "Path is %S\n", ioctl->path); - ioctl->dev = dev; + ioctl->dev = dev; - dev->ops = &ioctl_ops; + dev->ops = &ioctl_ops; + + dev->host_letter = (drv[12] & 0xdf) - 0x41; + cdrom_assigned_letters |= (1 << dev->host_letter); ioctl_load(ioctl); } From c23114ab8d7dc062d2acf39f0d6123857f9eb300 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 14 Mar 2025 04:18:07 +0600 Subject: [PATCH 0471/1190] Attempt fixing OpenGL 3.x screenshot --- src/qt/qt_openglrenderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 70c70527a..88fefa0c3 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1667,6 +1667,9 @@ OpenGLRenderer::render() unsigned char *rgba = (unsigned char *)calloc(1, width * height * 4); + glw.glFinish(); + glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); + glw.glReadBuffer(GL_BACK); glw.glFinish(); glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba); From c166abbbc1242184dc0113b4e1a15ce93c7658f2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 14 Mar 2025 14:07:33 +0600 Subject: [PATCH 0472/1190] Always use an alpha value of 1.0 for drawing scene to texture Fixes invisible screenshots and blank screens on certain systems --- src/qt/qt_openglrenderer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 88fefa0c3..3b2ec58e0 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -107,6 +107,7 @@ const char* fragment_shader_default_tex_src = "void main()\n" "{\n" " color = texture(Texture, texCoord);\n" + " color.a = 1.0;\n" "}\n"; const char* vertex_shader_default_color_src = @@ -141,6 +142,7 @@ const char* fragment_shader_default_color_src = "void main()\n" "{\n" " outColor = color;\n" + " outColor.a = 1.0;\n" "}\n"; static inline int @@ -1667,9 +1669,6 @@ OpenGLRenderer::render() unsigned char *rgba = (unsigned char *)calloc(1, width * height * 4); - glw.glFinish(); - glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); - glw.glReadBuffer(GL_BACK); glw.glFinish(); glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba); From 84112960c3f31df8455ea3c4b3d000f840cb5542 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Mar 2025 15:06:06 +0100 Subject: [PATCH 0473/1190] VIA PIPC: Also return 0x50 on power management register 0x42 for every other non-VT82c586-family southbridge, fixes CUV4X-LS. --- src/chipset/via_pipc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index f7f5bf208..6b855f5aa 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -59,6 +59,7 @@ listings on forums, as VIA's datasheets are not very helpful regarding those. */ #define VIA_PIPC_586A 0x05862500 #define VIA_PIPC_586B 0x05864700 +#define VIA_PIPC_586 0x0586 #define VIA_PIPC_596A 0x05960900 #define VIA_PIPC_596B 0x05962300 #define VIA_PIPC_596 0x0596 @@ -414,7 +415,7 @@ pipc_reset_hard(void *priv) dev->power_regs[0x34] = 0x68; dev->power_regs[0x40] = 0x20; - dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_596) ? 0x50 : 0x00; + dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_586) ? 0x00 : 0x50; acpi_set_irq_line(dev->acpi, 0x00); dev->power_regs[0x48] = 0x01; @@ -1596,7 +1597,7 @@ pipc_reset(void *priv) pipc_write(pm_func, 0x48, 0x01, priv); pipc_write(pm_func, 0x49, 0x00, priv); - dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_596) ? 0x50 : 0x00; + dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_586) ? 0x00 : 0x50; acpi_set_irq_line(dev->acpi, 0x00); pipc_write(1, 0x04, 0x80, priv); From aef06552fb383320707d17a51fea174ddba94ff0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Mar 2025 15:34:37 +0100 Subject: [PATCH 0474/1190] Some missing breaks in the Cyrix register writes. --- src/cpu/cpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index e6a22394a..c4d084947 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -3948,12 +3948,15 @@ pentium_invalid_wrmsr: /* Test Data */ case 0x03: msr.tr3 = EAX; + break; /* Test Address */ case 0x04: msr.tr4 = EAX; + break; /* Test Command/Status */ case 0x05: msr.tr5 = EAX & 0x008f0f3b; + break; /* Time Stamp Counter */ case 0x10: timer_set_new_tsc(EAX | ((uint64_t) EDX << 32)); From 0686045d2a7f3a2f7fc3ed4402874ca1e3406460 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 14 Mar 2025 21:24:36 +0600 Subject: [PATCH 0475/1190] Fix building on Haiku OS --- src/CMakeLists.txt | 4 ++++ src/qt/qt_platform.cpp | 7 +++++++ src/unix/unix.c | 11 +++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb3bf9f50..94dc6a61a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,6 +108,10 @@ 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) +if(HAIKU) + target_link_libraries(86Box be) +endif() + if(WIN32 AND ARCH STREQUAL "i386") if(MINGW) target_link_options(86Box PRIVATE "LINKER:--large-address-aware") diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index ee8d8842a..ebd6dc30c 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -18,6 +18,11 @@ * Copyright 2021-2022 Cacodemon345 * Copyright 2021-2022 Teemu Korhonen */ + +#ifdef __HAIKU__ +#include +#endif + #include #include @@ -828,6 +833,8 @@ plat_set_thread_name(void *thread, const char *name) pthread_setname_np(truncated); # elif defined(Q_OS_NETBSD) pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated, "%s"); +# elif defined(__HAIKU__) + rename_thread(find_thread(NULL), truncated); # elif defined(Q_OS_OPENBSD) pthread_set_name_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # else diff --git a/src/unix/unix.c b/src/unix/unix.c index 33b78ddb1..81312d25d 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -2,6 +2,9 @@ # define _FILE_OFFSET_BITS 64 # define _LARGEFILE64_SOURCE 1 #endif +#ifdef __HAIKU__ +#include +#endif #include #include #include @@ -1398,16 +1401,20 @@ plat_set_thread_name(void *thread, const char *name) if (thread) /* Apple pthread can only set self's name */ return; char truncated[64]; -#elif defined(Q_OS_NETBSD) +#elif defined(__NetBSD__) char truncated[64]; +#elif defined(__HAIKU__) + char truncated[32]; #else char truncated[16]; #endif strncpy(truncated, name, sizeof(truncated) - 1); #ifdef __APPLE__ pthread_setname_np(truncated); -#elif defined(Q_OS_NETBSD) +#elif defined(__NetBSD__) pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated, "%s"); +#elif defined(__HAIKU__) + rename_thread(find_thread(NULL), truncated); #else pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); #endif From a1996e79553ee41df49c30551403f5fd19bbd534 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 15 Mar 2025 01:09:41 +0700 Subject: [PATCH 0476/1190] 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 0477/1190] 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 0478/1190] 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 0479/1190] 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 0480/1190] 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 0481/1190] 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 0482/1190] 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 0483/1190] 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 0484/1190] 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 0485/1190] 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 0486/1190] 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 0487/1190] 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 0488/1190] 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 0489/1190] 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 0490/1190] 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 0491/1190] 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 0492/1190] 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 0493/1190] 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 0494/1190] 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 0495/1190] 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 0496/1190] 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 0497/1190] 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 0498/1190] 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 0499/1190] 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 0500/1190] 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 0501/1190] 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 0502/1190] 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 0503/1190] 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 0504/1190] 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 0505/1190] 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 0506/1190] 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 0507/1190] 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 0508/1190] 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 0509/1190] 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 0510/1190] 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 0511/1190] 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 0512/1190] 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 0513/1190] 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 0514/1190] 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 0515/1190] 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 0516/1190] 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 0517/1190] 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 0518/1190] 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 0519/1190] 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 0520/1190] 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 0521/1190] 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 0522/1190] 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 0523/1190] 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 0524/1190] 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 0525/1190] 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 0526/1190] 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 0527/1190] 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 0528/1190] 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 0529/1190] 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 0530/1190] #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 0531/1190] 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 0532/1190] 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 0533/1190] 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 0534/1190] 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 0535/1190] 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 0536/1190] 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 0537/1190] 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 0538/1190] 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 0539/1190] 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 0540/1190] 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 0541/1190] 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 0542/1190] 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 0543/1190] 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 0544/1190] 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 0545/1190] 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 0546/1190] 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 0547/1190] 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 0548/1190] 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 0549/1190] 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 0550/1190] 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 0551/1190] 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 0552/1190] 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 0553/1190] 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 0554/1190] 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 0555/1190] 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 0556/1190] 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 0557/1190] 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 0558/1190] 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 0559/1190] 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 0560/1190] 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 0561/1190] 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 0562/1190] 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 0563/1190] 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 0564/1190] 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 0565/1190] 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 0566/1190] 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 0567/1190] 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 0568/1190] 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 0569/1190] 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 0570/1190] 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 0571/1190] 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 0572/1190] 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 0573/1190] 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 0574/1190] 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 0575/1190] 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 0576/1190] 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 0577/1190] 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 0578/1190] 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 0579/1190] 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 0580/1190] 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 0581/1190] 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 0582/1190] 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 0583/1190] 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 0584/1190] 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 0585/1190] 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 0586/1190] 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 0587/1190] 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 0588/1190] 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 0589/1190] 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 0590/1190] 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 0591/1190] 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 0592/1190] 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 0593/1190] 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 0594/1190] 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 0595/1190] 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 0596/1190] 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 0597/1190] 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 0598/1190] 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 0599/1190] 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 0600/1190] 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 0601/1190] 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 0602/1190] 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 0603/1190] 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 0604/1190] 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 0605/1190] 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 0606/1190] 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 0607/1190] 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 0608/1190] 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 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 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 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 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 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 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 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 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 0609/1190] 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 0610/1190] 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 0611/1190] 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 85a94516f75f7c898d6c2cfd456c2aee97668175 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Mar 2025 16:31:32 +0600 Subject: [PATCH 0612/1190] Caps/Num/Scroll LED states are now displayed --- src/device/keyboard.c | 15 +++++++++------ src/device/keyboard_at.c | 3 +++ src/qt/qt_mainwindow.cpp | 33 +++++++++++++++++++++++++++++++++ src/qt/qt_mainwindow.hpp | 3 +++ 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index a00968cf7..aa9aba3c6 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -72,9 +72,9 @@ static int keydelay[512]; #endif static scancode *scan_table; /* scancode table for keyboard */ -static uint8_t caps_lock = 0; -static uint8_t num_lock = 0; -static uint8_t scroll_lock = 0; +static volatile uint8_t caps_lock = 0; +static volatile uint8_t num_lock = 0; +static volatile uint8_t scroll_lock = 0; static uint8_t shift = 0; static int key5576mode = 0; @@ -318,13 +318,16 @@ keyboard_input(int down, uint16_t scan) shift &= ~0x80; break; case 0x03a: /* Caps Lock */ - caps_lock ^= 1; + if (!(machine_has_bus(machine, MACHINE_AT) > 0)) + caps_lock ^= 1; break; case 0x045: - num_lock ^= 1; + if (!(machine_has_bus(machine, MACHINE_AT) > 0)) + num_lock ^= 1; break; case 0x046: - scroll_lock ^= 1; + if (!(machine_has_bus(machine, MACHINE_AT) > 0)) + scroll_lock ^= 1; break; default: diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index e61b8547a..c5f73459b 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -3476,6 +3476,7 @@ keyboard_at_bat(void *priv) keyboard_scan = 1; + keyboard_update_states(0, 0, 0); kbc_at_dev_queue_add(dev, 0xaa, 0); } else { bat_counter--; @@ -3510,6 +3511,7 @@ keyboard_at_write(void *priv) switch (dev->command) { case 0xed: /* Set/reset LEDs */ kbc_at_dev_queue_add(dev, 0xfa, 0); + keyboard_update_states(!!(val & 0x4), !!(val & 0x2), val & 0x1); keyboard_at_log("%s: Set/reset LEDs [%02X]\n", dev->name, val); break; @@ -3762,6 +3764,7 @@ keyboard_at_init(const device_t *info) if (dev->port != NULL) { kbc_at_dev_reset(dev, 0); + keyboard_update_states(0, 0, 0); bat_counter = 0x0000; } diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index b3d0d9fa9..9f63bf297 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -184,6 +184,32 @@ MainWindow::MainWindow(QWidget *parent) ui->menuEGA_S_VGA_settings->menuAction()->setMenuRole(QAction::NoRole); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); + + num_label = new QLabel; + num_label->setText(" NUM "); + statusBar()->addPermanentWidget(num_label); + + scroll_label = new QLabel; + scroll_label->setText(" SCRL "); + statusBar()->addPermanentWidget(scroll_label); + + caps_label = new QLabel; + caps_label->setText(" CAPS "); + statusBar()->addPermanentWidget(caps_label); + + QTimer* ledKeyboardTimer = new QTimer(this); + ledKeyboardTimer->setTimerType(Qt::CoarseTimer); + ledKeyboardTimer->setInterval(1); + connect(ledKeyboardTimer, &QTimer::timeout, this, [this] () { + uint8_t caps, num, scroll; + keyboard_get_states(&caps, &num, &scroll); + + num_label->setStyleSheet(num ? "QLabel { background: green; }" : ""); + caps_label->setStyleSheet(caps ? "QLabel { background: green; }" : ""); + scroll_label->setStyleSheet(scroll ? "QLabel { background: green; }" : ""); + }); + ledKeyboardTimer->start(); + #ifdef Q_OS_WINDOWS util::setWin11RoundedCorners(this->winId(), (hide_status_bar ? false : true)); #endif @@ -211,6 +237,9 @@ MainWindow::MainWindow(QWidget *parent) connect(this, &MainWindow::hardResetCompleted, this, [this]() { ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); + num_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); + scroll_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); + caps_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); while (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); #ifdef USE_WACOM @@ -1306,6 +1335,10 @@ MainWindow::refreshMediaMenu() status->refresh(ui->statusbar); ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled); + + num_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); + scroll_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); + caps_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); } void diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index f1c6cadf6..06a739dd8 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -184,6 +185,8 @@ private: friend class RendererStack; // For UI variable access by non-primary renderer windows. friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. + QLabel *caps_label, *scroll_label, *num_label; + bool isShowMessage = false; }; From 81e6b2a40a292474a03a2e1df38f774f53277f5d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 27 Mar 2025 16:58:42 +0600 Subject: [PATCH 0613/1190] Correct the order --- src/qt/qt_mainwindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 9f63bf297..3ee8d61b4 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -189,14 +189,14 @@ MainWindow::MainWindow(QWidget *parent) num_label->setText(" NUM "); statusBar()->addPermanentWidget(num_label); - scroll_label = new QLabel; - scroll_label->setText(" SCRL "); - statusBar()->addPermanentWidget(scroll_label); - caps_label = new QLabel; caps_label->setText(" CAPS "); statusBar()->addPermanentWidget(caps_label); + scroll_label = new QLabel; + scroll_label->setText(" SCRL "); + statusBar()->addPermanentWidget(scroll_label); + QTimer* ledKeyboardTimer = new QTimer(this); ledKeyboardTimer->setTimerType(Qt::CoarseTimer); ledKeyboardTimer->setInterval(1); From 8861741945404350589613bbe2ab4157c0f30c8c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Mar 2025 00:10:16 +0600 Subject: [PATCH 0614/1190] Some needed changes for hard resets --- src/86box.c | 3 +++ src/device/keyboard.c | 2 +- src/device/keyboard_at.c | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/86box.c b/src/86box.c index 2b6e1ba9f..57faa89c1 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1301,6 +1301,9 @@ pc_reset_hard_init(void) /* Mark ACPI as unavailable */ acpi_enabled = 0; + /* Reset all keyboard indicators */ + keyboard_update_states(0, 0, 0); + /* Reset the general machine support modules. */ io_init(); diff --git a/src/device/keyboard.c b/src/device/keyboard.c index aa9aba3c6..7666b0e70 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -75,7 +75,7 @@ static scancode *scan_table; /* scancode table for keyboard */ static volatile uint8_t caps_lock = 0; static volatile uint8_t num_lock = 0; static volatile uint8_t scroll_lock = 0; -static uint8_t shift = 0; +static uint8_t shift = 0; static int key5576mode = 0; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index c5f73459b..605f51e90 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -3764,12 +3764,12 @@ keyboard_at_init(const device_t *info) if (dev->port != NULL) { kbc_at_dev_reset(dev, 0); - keyboard_update_states(0, 0, 0); bat_counter = 0x0000; } keyboard_send = add_data_kbd; SavedKbd = dev; + keyboard_update_states(0, 0, 0); inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa; @@ -3788,6 +3788,8 @@ keyboard_at_close(void *priv) /* Disable the scancode maps. */ keyboard_set_table(NULL); + keyboard_update_states(0, 0, 0); + SavedKbd = NULL; free(dev); From 7e3cf32dcacc9b6af1b709c78323cbb3e6fd9cf0 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Mar 2025 00:15:06 +0600 Subject: [PATCH 0615/1190] Remove some no-more-needed changes --- src/86box.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/86box.c b/src/86box.c index 57faa89c1..2b6e1ba9f 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1301,9 +1301,6 @@ pc_reset_hard_init(void) /* Mark ACPI as unavailable */ acpi_enabled = 0; - /* Reset all keyboard indicators */ - keyboard_update_states(0, 0, 0); - /* Reset the general machine support modules. */ io_init(); From 94a928978e20fcb2b0b9edd86b430ce818f4255d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 29 Mar 2025 20:46:30 +0900 Subject: [PATCH 0616/1190] PS55DA2: update compatibility table --- src/video/vid_ps55da2.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 98db5f9fa..1f00b7cc5 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -112,17 +112,18 @@ EFD8h * Display Adapter/J [Atlas-SP2] [Japanese DOS and Display Adapter compatibility] - | POS ID | Adapter Name | K3.31 | J4.04 | J4.08 | OS2 J1.3 | Win3 | - |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| - | EFFFh | Display Adapter | X | | | | | - | FFEDh | ? [Atlas EVT] | X | | | | | - | FFFDh | ? [LDT EVT] | X | | | | | - | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | - | E013h | ? [LDT] | X | X | X | X | | - | ECCEh | Display Adapter IV | | X | X | X | | - | ECECh | Display Adapter IV,B1 | | X | X | X | X | - | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | - | EFD8h | Display Adapter /J | | | X | X | X | + | | | K3.31 | J4.04 | J4.08 | OS2J1.3 | Win3.02 | DOSVExt | + | POS ID | Adapter Name | 5605JBK | 5605PAA | 5605PCA | 5605PDE | 5605PAW | 5605PXA | + |------------|-----------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| + | EFFFh | Display Adapter | X | | | | | | + | FFEDh | ? [Atlas EVT] | X | | | | | | + | FFFDh | ? [LDT EVT] | X | | | | | | + | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | X | + | E013h | ? [LDT] | X | X | X | X | | X | + | ECCEh | Display Adapter IV | | X | X | X | | X | + | ECECh | Display Adapter IV,B1 | | X | X | X | X | X | + | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | X | + | EFD8h | Display Adapter /J | | | X | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ #define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ From 6d43f7e2df212fd7d9bf662a0fcf6caa18c75541 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:24:20 +0100 Subject: [PATCH 0617/1190] 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 0618/1190] 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 0619/1190] 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); } } From 8cc6f215362436aa72be5b1002ab830058a0602f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 18:32:41 +0100 Subject: [PATCH 0620/1190] PB450: Fix the default BIOS selection, fixes segmentation fault. --- src/machine/m_at_386dx_486.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 19c4b535e..639233e10 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -691,12 +691,12 @@ static const device_config_t pb450_config[] = { .name = "bios", .description = "BIOS Version", .type = CONFIG_BIOS, - .default_string = "pci10a", + .default_string = "pb450a", .default_int = 0, .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "PCI 1.0A", .internal_name = "pb450" /*"pci10a"*/, .bios_type = BIOS_NORMAL, + { .name = "PCI 1.0A", .internal_name = "pb450a" /*"pci10a"*/, .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/OPTI802.bin", "" } }, { .name = "PNP 1.1A", .internal_name = "pnp11a", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/PNP11A.bin", "" } }, @@ -732,7 +732,7 @@ machine_at_pb450_init(const machine_t *model) return ret; device_context(model->device); - fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); From 99c81fe03d640f06d16682e67ad84110bcfa9406 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 18:36:33 +0100 Subject: [PATCH 0621/1190] IBM PC/XT/AT and PB450: Remove "Device" from machine device_t names. --- src/machine/m_at.c | 4 ++-- src/machine/m_at_386dx_486.c | 2 +- src/machine/m_xt.c | 12 ++++++------ src/machine/m_xt_laserxt.c | 11 +++++++---- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 3f5e88011..8a561630c 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -187,7 +187,7 @@ static const device_config_t ibmat_config[] = { }; const device_t ibmat_device = { - .name = " IBM AT Devices", + .name = "IBM AT", .internal_name = "ibmat_device", .flags = 0, .local = 0, @@ -294,7 +294,7 @@ static const device_config_t ibmxt286_config[] = { }; const device_t ibmxt286_device = { - .name = "IBM XT Model 286 Devices", + .name = "IBM XT Model 286", .internal_name = "ibmxt286_device", .flags = 0, .local = 0, diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 639233e10..0ee353f53 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -708,7 +708,7 @@ static const device_config_t pb450_config[] = { }; const device_t pb450_device = { - .name = "Packard Bell PB450 Devices", + .name = "Packard Bell PB450", .internal_name = "pb450_device", .flags = 0, .local = 0, diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 78d2daa13..13f9c52ca 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -108,7 +108,7 @@ static const device_config_t ibmpc_config[] = { }; const device_t ibmpc_device = { - .name = "IBM PC (1981) Device", + .name = "IBM PC (1981)", .internal_name = "ibmpc_device", .flags = 0, .local = 0, @@ -218,7 +218,7 @@ static const device_config_t ibmpc82_config[] = { }; const device_t ibmpc82_device = { - .name = "IBM PC (1982) Devices", + .name = "IBM PC (1982)", .internal_name = "ibmpc82_device", .flags = 0, .local = 0, @@ -331,7 +331,7 @@ static const device_config_t ibmxt_config[] = { }; const device_t ibmxt_device = { - .name = "IBM XT (1982) Device", + .name = "IBM XT (1982)", .internal_name = "ibmxt_device", .flags = 0, .local = 0, @@ -451,7 +451,7 @@ static const device_config_t ibmxt86_config[] = { }; const device_t ibmxt86_device = { - .name = "IBM XT (1986) Device", + .name = "IBM XT (1986)", .internal_name = "ibmxt86_device", .flags = 0, .local = 0, @@ -624,7 +624,7 @@ static const device_config_t jukopc_config[] = { }; const device_t jukopc_device = { - .name = "Juko ST Devices", + .name = "Juko ST", .internal_name = "jukopc_device", .flags = 0, .local = 0, @@ -949,7 +949,7 @@ static const device_config_t vendex_config[] = { }; const device_t vendex_device = { - .name = "Vendex 888T Devices", + .name = "Vendex 888T", .internal_name = "vendex_device", .flags = 0, .local = 0, diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 877d26ff5..595cce1ca 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -154,6 +154,8 @@ machine_xt_laserxt_common_init(const machine_t *model,int is_lxt3) standalone_gameport_type = &gameport_device; laserxt_init(is_lxt3); + + device_add(&keyboard_xt_lxt3_device); } int @@ -167,8 +169,6 @@ machine_xt_laserxt_init(const machine_t *model) if (bios_only || !ret) return ret; - device_add(&keyboard_xt_device); - machine_xt_laserxt_common_init(model, 0); return ret; @@ -179,14 +179,17 @@ machine_xt_lxt3_init(const machine_t *model) { int ret; +#if 0 ret = bios_load_linear("roms/machines/lxt3/27c64d.bin", 0x000fe000, 8192, 0); +#else + ret = bios_load_linear("roms/machines/lxt3/vtech-laser-xt3-bios-v1-26-27c64-637cfbe96dfa1809192278.bin", + 0x000fe000, 8192, 0); +#endif if (bios_only || !ret) return ret; - device_add(&keyboard_xt_lxt3_device); - machine_xt_laserxt_common_init(model, 1); return ret; From c1ecafaeb55e597e068ad61a8a563d5162e81019 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 18:38:20 +0100 Subject: [PATCH 0622/1190] IBM PS/1 Model 2011: No need to explicitly refer to the zeroth element of the config array. --- src/machine/m_ps1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 41821a4a8..07128f157 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -290,7 +290,7 @@ const device_t ps1_2011_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = &ps1_2011_config[0] + .config = &ps1_2011_config }; static void From e48c6c8e8bd631471b45052c69270249e5193baa Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 18:40:27 +0100 Subject: [PATCH 0623/1190] Laser XT3: No longer use the other BIOS that has not yet been committed. --- src/machine/m_xt_laserxt.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 595cce1ca..c0405f99a 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -179,13 +179,8 @@ machine_xt_lxt3_init(const machine_t *model) { int ret; -#if 0 ret = bios_load_linear("roms/machines/lxt3/27c64d.bin", 0x000fe000, 8192, 0); -#else - ret = bios_load_linear("roms/machines/lxt3/vtech-laser-xt3-bios-v1-26-27c64-637cfbe96dfa1809192278.bin", - 0x000fe000, 8192, 0); -#endif if (bios_only || !ret) return ret; From 8b646ccc49a5d6b4f0e7ce9ccf7042d7d89c14f2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 18:47:21 +0100 Subject: [PATCH 0624/1190] Fix a compile-breaking mistake in machine/m_ps1.c. --- src/machine/m_ps1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 07128f157..c22463de4 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -290,7 +290,7 @@ const device_t ps1_2011_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = &ps1_2011_config + .config = ps1_2011_config }; static void From b6b840b67ec8f680d69d0672e49b8a0e6fd851df Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 19:54:48 +0100 Subject: [PATCH 0625/1190] Recognize 8514/a-type cards as (S)VGA for the purposes of force 4:3 calculations, fixes blurry picture and wrong resolution. --- src/86box.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/86box.c b/src/86box.c index 2b6e1ba9f..ad1cfc519 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1624,6 +1624,8 @@ set_screen_size_monitor(int x, int y, int monitor_index) { int temp_overscan_x = monitors[monitor_index].mon_overscan_x; int temp_overscan_y = monitors[monitor_index].mon_overscan_y; + int is_svga = (video_get_type_monitor(monitor_index) == VIDEO_FLAG_TYPE_SPECIAL) || + (video_get_type_monitor(monitor_index) == VIDEO_FLAG_TYPE_8514); double dx; double dy; double dtx; @@ -1657,19 +1659,19 @@ set_screen_size_monitor(int x, int y, int monitor_index) dty = (double) temp_overscan_y; /* Account for possible overscan. */ - if (video_get_type_monitor(monitor_index) != VIDEO_FLAG_TYPE_SPECIAL && (temp_overscan_y == 16)) { + if (!is_svga && (temp_overscan_y == 16)) { /* CGA */ dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else if (video_get_type_monitor(monitor_index) != VIDEO_FLAG_TYPE_SPECIAL && (temp_overscan_y < 16)) { + } else if (!is_svga && (temp_overscan_y < 16)) { /* MDA/Hercules */ - dy = (x / 4.0) * 3.0; + dy = (dx / 4.0) * 3.0; } else { if (enable_overscan) { /* EGA/(S)VGA with overscan */ dy = (((dx - dtx) / 4.0) * 3.0) + dty; } else { /* EGA/(S)VGA without overscan */ - dy = (x / 4.0) * 3.0; + dy = (dx / 4.0) * 3.0; } } monitors[monitor_index].mon_unscaled_size_y = (int) dy; From 5a4a939e02cca97d9f35d3cf4581a89ed87bc3ac Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 20:27:20 +0100 Subject: [PATCH 0626/1190] More fixes to the 8514/A compatible side. 1. Use proper identification to what chips use what. 2. Apply some mode switch fixes to the ATI 8514/A Ultra and make 1024x768 87Hz interlaced the default mode if htotal is 0 and on ati8514_init. 3. Add the undocumented ports to the ATI 8514/A Ultra add-on as well. --- src/include/86box/vid_8514a.h | 5 ++ src/video/vid_8514a.c | 5 +- src/video/vid_ati_mach8.c | 160 ++++++++++++++++++++-------------- src/video/vid_svga.c | 6 +- 4 files changed, 103 insertions(+), 73 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 153bface4..a467311ca 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -250,4 +250,9 @@ typedef struct ibm8514_t { } ibm8514_t; +#define IBM_8514A (((dev->local & 0xff) == 0x00) && (dev->extensions == 0x00)) +#define ATI_8514A_ULTRA (((dev->local & 0xff) == 0x00) && (dev->extensions == 0x01)) +#define ATI_GRAPHICS_ULTRA ((dev->local & 0xff) == 0x01) +#define ATI_MACH32 ((dev->local & 0xff) == 0x02) + #endif /*VIDEO_8514A_H*/ diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index efb05a307..df4cd7d9a 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -3846,10 +3846,7 @@ ibm8514_recalctimings(svga_t *svga) else svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - if (dev->dispend == 766) - dev->dispend += 2; - - if (dev->dispend == 478) + if ((dev->dispend == 478) || (dev->dispend == 766)) dev->dispend += 2; if (dev->interlace) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 9f1bb99d6..ba32dc129 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2250,7 +2250,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; - if (((dev->disp_cntl & 0x60) == 0x20) && ((dev->local & 0xff) >= 0x02)) { + if (((dev->disp_cntl & 0x60) == 0x20) && ATI_MACH32) { if ((addr >= 0x3c6) && (addr <= 0x3c9)) { mach_log("VGA DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); @@ -2281,7 +2281,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) } break; case 0xad: - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if ((old ^ val) & 0x0c) { mach_log("ATI AD bits 2-3.\n"); svga_recalctimings(svga); @@ -2301,14 +2301,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) if (mach->regs[0xbe] & 0x08) { /* Read/write bank mode */ mach->bank_r = (((mach->regs[0xb2] & 1) << 3) | ((mach->regs[0xb2] & 0xe0) >> 5)); mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2); mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } 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) + if (ATI_MACH32) mach->bank_w |= ((mach->regs[0xae] & 3) << 4); mach->bank_r = mach->bank_w; @@ -2338,7 +2338,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) } break; case 0xb8: - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if ((old ^ val) & 0x40) { mach_log("ATI B8 bit 6.\n"); svga_recalctimings(svga); @@ -2367,7 +2367,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); mach_log("8514/A RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->regs[0xb0] & 0x20) { /*ATI extended 8514/A mode.*/ mach_log("Extended 8514/A mode.\n"); dev->vendor_mode = 1; @@ -2394,7 +2394,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); mach_log("VGA RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (svga->attrregs[0x10] & 0x40) { mach_log("VGA mode.\n"); dev->vendor_mode = 0; @@ -2495,7 +2495,7 @@ mach_in(uint16_t addr, void *priv) case 0xb0: temp = mach->regs[0xb0] | 0x80; temp &= ~0x18; - if ((dev->local & 0xff) >= 0x02) { /*Mach32 VGA 1MB memory*/ + if (ATI_MACH32) { /*Mach32 VGA 1MB memory*/ temp |= 0x08; } else { /*ATI 28800 VGA 512kB memory*/ temp |= 0x10; @@ -2524,7 +2524,7 @@ mach_in(uint16_t addr, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (dev->on) temp = svga_in(addr, svga); else { @@ -2669,6 +2669,9 @@ mach_set_resolution(mach_t *mach, svga_t *svga) ibm8514_t *dev = (ibm8514_t *) svga->dev8514; dev->hdisp = (dev->hdisped + 1) << 3; + if (!dev->htotal) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/ + dev->htotal = 0x9d; + dev->h_total = dev->htotal + 1; dev->vdisp = (dev->v_disp + 1) >> 1; @@ -2693,6 +2696,16 @@ mach_set_resolution(mach_t *mach, svga_t *svga) dev->vdisp = 480; svga_recalctimings(svga); } + } else { + if (ATI_8514A_ULTRA) { + if (dev->accel.advfunc_cntl & 0x04) { + if (dev->hdisp == 640) { + dev->hdisp = 1024; + dev->vdisp = 768; + svga_recalctimings(svga); + } + } + } } } } @@ -2712,7 +2725,7 @@ ati8514_recalctimings(svga_t *svga) dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; - mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", + pclog("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); dev->h_disp = dev->hdisp; @@ -2756,7 +2769,7 @@ mach_recalctimings(svga_t *svga) clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->regs[0xad] & 0x04) svga->ma_latch |= 0x40000; @@ -2785,7 +2798,7 @@ mach_recalctimings(svga_t *svga) } else svga->packed_4bpp = 0; - if ((dev->local & 0xff) < 0x02) { + if (!ATI_MACH32) { if ((mach->regs[0xb6] & 0x18) == 0x08) { svga->hdisp <<= 1; svga->htotal <<= 1; @@ -2823,7 +2836,7 @@ mach_recalctimings(svga_t *svga) if (dev->interlace) dev->dispend >>= 1; - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { 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); @@ -2913,7 +2926,7 @@ mach_recalctimings(svga_t *svga) if ((svga->gdcreg[5] & 0x40) || (svga->attrregs[0x10] & 0x40) || (mach->regs[0xb0] & 0x20)) { svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); mach_log("VGA clock=%02x.\n", mach->regs[0xa7] & 0x80); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->regs[0xb8] & 0x40) svga->clock *= 2; } else { @@ -2960,7 +2973,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ if (!(mach->shadow_cntl & 0x04)) dev->htotal = val; @@ -2969,7 +2982,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ if (!(mach->shadow_cntl & 0x04)) { WRITE8(port, dev->hsync_start, val); } @@ -2978,7 +2991,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ if (!(mach->shadow_cntl & 0x04)) { WRITE8(port, dev->hsync_width, val); } @@ -2995,14 +3008,17 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } } - if (!(mach->shadow_cntl & 0x04)) - dev->htotal = (val >> 8) & 0xff; - + if (ATI_8514A_ULTRA) { + if (!(mach->shadow_cntl & 0x04)) + dev->htotal = (val >> 8) & 0xff; + } mach_set_resolution(mach, svga); } } else { @@ -3029,7 +3045,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ if (!(mach->shadow_cntl & 0x04)) { dev->htotal = val; } @@ -3040,7 +3056,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*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; @@ -3048,7 +3064,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*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; @@ -3061,7 +3077,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x12e9: if (len == 1) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { 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; @@ -3109,7 +3125,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x1ae8: if (len == 2) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { 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; @@ -3119,7 +3135,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { 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; @@ -3130,7 +3146,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x1ae9: if (len == 1) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { 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; @@ -3181,12 +3197,12 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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 { + if (ATI_MACH32) { mach_set_resolution(mach, svga); mach32_updatemapping(mach, svga); + } else { + dev->ext_crt_pitch = 128; + mach_set_resolution(mach, svga); } mach_log("Vendor IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); break; @@ -3390,7 +3406,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { if ((dev->accel.multifunc_cntl >> 12) == 5) { - if ((dev->local & 0xff) < 0x02) + if (!ATI_MACH32) dev->ext_crt_pitch = 128; } } @@ -3514,12 +3530,12 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else dev->ext_crt_pitch <<= 1; } - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { dev->on |= 0x01; dev->vendor_mode = 1; } svga_recalctimings(svga); - if ((dev->local & 0xff) >= 0x01) + if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); 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); @@ -3548,17 +3564,17 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { WRITE8(port, mach->local_cntl, val); } - if ((dev->local & 0xff) >= 0x01) + if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); break; case 0x36ee: case 0x36ef: if (len == 2) { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) mach->misc = val; } else { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) WRITE8(port, mach->misc, val); } mach->misc &= 0xfff0; @@ -3621,7 +3637,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("Vendor ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); - if ((dev->local & 0xff) >= 0x01) + if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); break; @@ -3675,7 +3691,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; - if ((dev->local & 0xff) >= 0x01) + if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); break; @@ -3729,7 +3745,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { WRITE8(port, mach->accel.ext_ge_config, val); } - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->accel.crt_pitch & 0xff) dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; @@ -4407,46 +4423,46 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xdaee: if (len == 2) { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) temp = mach->accel.src_x; } else { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) temp = mach->accel.src_x & 0xff; } break; case 0xdaef: if (len == 1) { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) temp = mach->accel.src_x >> 8; } break; case 0xdeee: if (len == 2) { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) temp = mach->accel.src_y; } else { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) temp = mach->accel.src_y & 0xff; } break; case 0xdeef: if (len == 1) { - if ((dev->local & 0xff) >= 0x02) + if (ATI_MACH32) temp = mach->accel.src_y >> 8; } break; case 0xfaee: if (len == 2) { - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->pci_bus) temp = 0x0017; else temp = 0x22f7; } } else { - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->pci_bus) temp = 0x17; else @@ -4456,7 +4472,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xfaef: if (len == 1) { - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->pci_bus) temp = 0x00; else @@ -4604,7 +4620,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x36ee: case 0x36ef: - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { READ8(port, mach->misc); if (!(port & 1)) { temp &= ~0x0c; @@ -5148,7 +5164,7 @@ mach32_write(uint32_t addr, uint8_t val, void *priv) return; } - if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; switch (addr & 0x06) { case 0x00: @@ -5188,7 +5204,7 @@ mach32_writew(uint32_t addr, uint16_t val, void *priv) return; } - if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; if (addr & 0x04) { mach32_write_common(addr - 2, val & 0x0f, 0, mach, svga); @@ -5223,7 +5239,7 @@ mach32_writel(uint32_t addr, uint32_t val, void *priv) return; } - if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; mach32_write_common(addr, val & 0x0f, 0, mach, svga); mach32_write_common(addr + 1, (val >> 4) & 0x0f, 0, mach, svga); @@ -5639,7 +5655,7 @@ mach32_read(uint32_t addr, void *priv) (void) xga_read_test(addr, svga); addr = (addr & svga->banked_mask) + svga->read_bank; - if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; switch (addr & 0x06) { case 0x00: @@ -5676,7 +5692,7 @@ mach32_readw(uint32_t addr, void *priv) (void) xga_read_test(addr, svga); addr = (addr & svga->banked_mask) + svga->read_bank; - if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; if (addr & 0x04) { ret = mach32_read_common(addr - 2, 0, mach, svga) & 0x0f; @@ -5708,7 +5724,7 @@ mach32_readl(uint32_t addr, void *priv) (void) xga_read_test(addr, svga); addr = (addr & svga->banked_mask) + svga->read_bank; - if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; ret = mach32_read_common(addr, 0, mach, svga) & 0x0f; ret |= (mach32_read_common(addr + 1, 0, mach, svga) << 4); @@ -5998,7 +6014,7 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; - if (((dev->local & 0xff) >= 0x02) && !(dev->accel.advfunc_cntl & 0x01) && !(mach->accel.clock_sel & 0x01)) { + if (ATI_MACH32 && !(dev->accel.advfunc_cntl & 0x01) && !(mach->accel.clock_sel & 0x01)) { if ((svga->gdcreg[6] & 0x01) || (svga->attrregs[0x10] & 0x01)) { if (svga->attrregs[0x10] & 0x40) { dev->vendor_mode = 0; @@ -6035,7 +6051,7 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) mem_mapping_disable(&mach->mmio_linear_mapping); } - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (dev->on && dev->vendor_mode) { mach_log("Mach32 banked mapping.\n"); mem_mapping_disable(&svga->mapping); @@ -6216,6 +6232,7 @@ ati8514_io_set(svga_t *svga) io_sethandler(0x7eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x82ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x86ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x8eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x92ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x96ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); @@ -6238,6 +6255,7 @@ ati8514_io_set(svga_t *svga) io_sethandler(0xdeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xe2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xe6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xeeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xf2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xf6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); @@ -6331,6 +6349,7 @@ mach_io_remove(mach_t *mach) io_removehandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0x86ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x8aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -6353,6 +6372,7 @@ mach_io_remove(mach_t *mach) io_removehandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xeaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_removehandler(0xf6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -6817,7 +6837,7 @@ mach8_init(const device_t *info) dev->vram_512k_8514 = dev->vram_amount == 512; dev->accel.cmd_back = 1; - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { if (mach->pci_bus) { if (mach->has_bios) { rom_init(&mach->bios_rom, @@ -6852,7 +6872,7 @@ mach8_init(const device_t *info) 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { svga_init(info, svga, mach, dev->vram_amount << 10, /*default: 2MB for Mach32*/ mach_recalctimings, mach_in, mach_out, @@ -6940,7 +6960,7 @@ mach8_init(const device_t *info) mach_io_set(mach); mach->accel.cmd_type = -2; - if ((dev->local & 0xff) >= 0x02) { + if (ATI_MACH32) { svga->decode_mask = (4 << 20) - 1; mach->cursor_col_1 = 0xff; mach->ext_cur_col_1_r = 0xff; @@ -6985,13 +7005,21 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) mach_t *mach = (mach_t *) ext8514; ibm8514_t *dev = (ibm8514_t *) dev8514; + /*Init as 1024x768 87hz interlaced first, per 8514/A.*/ dev->on = 0; dev->ext_pitch = 1024; dev->ext_crt_pitch = 0x80; dev->accel_bpp = 8; dev->rowoffset = 0x80; - dev->hdisp = 1024; - dev->vdisp = 768; + dev->hdisped = 0x7f; + dev->v_disp = 0x05ff; + dev->htotal = 0x9d; + dev->v_total_reg = 0x0668; + dev->v_sync_start = 0x0600; + dev->disp_cntl = 0x33; + mach->accel.clock_sel = 0x1c; + mach->shadow_set = 0x02; + mach->resolution_crt = 0x02; io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); ati8514_io_set(svga); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index a44838d68..8d1535dda 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -904,7 +904,7 @@ svga_recalctimings(svga_t *svga) svga->recalctimings_ex(svga); if (ibm8514_active && (svga->dev8514 != NULL)) { - if ((dev->local & 0xff) == 0x00) + if (IBM_8514A || ATI_8514A_ULTRA) ibm8514_recalctimings(svga); } @@ -1031,8 +1031,8 @@ svga_recalctimings(svga_t *svga) if (ibm8514_active && (svga->dev8514 != NULL)) { if (dev->on) { disptime8514 = dev->h_total; - _dispontime8514 = (dev->hdisped + 1) * 8; - svga_log("HDISPED 8514=%d, htotal=%02x.\n", (dev->hdisped + 1) << 3, dev->h_total); + _dispontime8514 = dev->h_disp; + svga_log("HTOTAL=%d, HDISP=%d.\n", dev->h_total, dev->h_disp); } } From ef588c118a1123161a8ee3ba7790c58686627487 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 20:36:00 +0100 Subject: [PATCH 0627/1190] Fixed log excess. --- src/video/vid_8514a.c | 4 ++-- src/video/vid_ati_mach8.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index df4cd7d9a..393b90b57 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -357,13 +357,13 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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); + 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: 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); + 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; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index ba32dc129..c21730497 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2725,7 +2725,7 @@ ati8514_recalctimings(svga_t *svga) dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; - pclog("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", + 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); dev->h_disp = dev->hdisp; From eeab2fe4090a75999bfdedb6ded9f4c82371ffbc Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 20:56:06 +0100 Subject: [PATCH 0628/1190] NE2000 Compatibles: Store the UI correctly. --- src/network/net_ne2000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 71e5c2ca7..e45b55b22 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -1071,7 +1071,7 @@ nic_init(const device_t *info) mac_oui = (((int) dev->maclocal[0]) << 16); mac_oui |= (((int) dev->maclocal[1]) << 8); mac_oui |= ((int) dev->maclocal[2]); - device_set_config_mac("mac", mac); + device_set_config_mac("mac_oui", mac_oui); } else { dev->maclocal[0] = (mac_oui >> 16) & 0xff; dev->maclocal[1] = (mac_oui >> 8) & 0xff; From 90464f7914d9d2ea0e99541f2729f2787e9d6c51 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 03:12:55 +0200 Subject: [PATCH 0629/1190] OKI IF386AX: Default NVR to 0x00's instead of 0xFF's, in order to default it to CRT instead of LCD. --- src/device/serial.c | 3 +-- src/machine/m_at_286_386sx.c | 10 +++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/device/serial.c b/src/device/serial.c index 8483f7fe3..deb97225a 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -999,8 +999,7 @@ void serial_standalone_init(void) { while (next_inst < SERIAL_MAX) - device_add_inst(!strcmp(machine_get_internal_name(), "if386sx") ? &ns16450_device : - &ns8250_device, next_inst + 1); + device_add_inst(&ns8250_device, next_inst + 1); }; const device_t ns8250_device = { diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 033233955..b084bfbbd 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -653,7 +653,9 @@ machine_at_if386sx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); /* NVR that is initialized to all 0x00's. */ + device_add(&keyboard_at_phoenix_device); device_add(&neat_sx_device); @@ -663,6 +665,12 @@ machine_at_if386sx_init(const machine_t *model) if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); + /* + One serial port - on the real hardware IF386AX, it is on the VL 16C451, + alognside the bidirectional parallel port. + */ + device_add_inst(&ns16450_device, 1); + return ret; } From 19e01b8ddfb318f892c6f49859d63d19e9d74e2b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 03:40:08 +0200 Subject: [PATCH 0630/1190] UI: Optimize several Settings pages to reduce the amount of iterations and repeated calls to functions where multiple there are multiple instances of the same device type, should further speed up te opening of the Settings dialog. --- src/qt/qt_settingsnetwork.cpp | 78 +++++++++++++----------- src/qt/qt_settingsotherperipherals.cpp | 56 ++++++++++------- src/qt/qt_settingsports.cpp | 59 +++++++++++------- src/qt/qt_settingssound.cpp | 63 ++++++++++--------- src/qt/qt_settingsstoragecontrollers.cpp | 55 ++++++++++------- 5 files changed, 184 insertions(+), 127 deletions(-) diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index a0acd7a3f..9a53411d5 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -137,54 +137,63 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) { this->machineId = machineId; - int c = 0; - int selectedRow = 0; + int c = 0; + int selectedRow = 0; - for (int i = 0; i < NET_CARD_MAX; ++i) { - auto *cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); - auto *model = cbox->model(); - auto removeRows = model->rowCount(); - c = 0; - selectedRow = 0; + // Network Card + QComboBox * cbox_[NET_CARD_MAX] = { 0 }; + QAbstractItemModel *models[NET_CARD_MAX] = { 0 }; + int removeRows_[NET_CARD_MAX] = { 0 }; + int selectedRows[NET_CARD_MAX] = { 0 }; + int m_has_net = machine_has_flags(machineId, MACHINE_NIC); - while (true) { - /* Skip "internal" if machine doesn't have it or this is not the primary card. */ - if ((c == 1) && ((i > 0) || (machine_has_flags(machineId, MACHINE_NIC) == 0))) { - c++; - continue; - } + for (uint8_t i = 0; i < NET_CARD_MAX; ++i) { + cbox_[i] = findChild(QString("comboBoxNIC%1").arg(i + 1)); + models[i] = cbox_[i]->model(); + removeRows_[i] = models[i]->rowCount(); + } - auto name = DeviceConfig::DeviceName(network_card_getdevice(c), network_card_get_internal_name(c), 1); - if (name.isEmpty()) { - break; - } + c = 0; + while (true) { + const QString name = DeviceConfig::DeviceName(network_card_getdevice(c), + network_card_get_internal_name(c), 1); - if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machineId)) { - int row = Models::AddEntry(model, name, c); - if (c == net_cards_conf[i].device_num) { - selectedRow = row - removeRows; + if (name.isEmpty()) + break; + + if (network_card_available(c)) { + if (device_is_valid(network_card_getdevice(c), machineId)) { + for (uint8_t i = 0; i < NET_CARD_MAX; ++i) { + if ((c != 1) || ((i == 0) && m_has_net)) { + int row = Models::AddEntry(models[i], name, c); + + if (c == net_cards_conf[i].device_num) + selectedRows[i] = row - removeRows_[i]; + } } } - c++; } - model->removeRows(0, removeRows); - cbox->setEnabled(model->rowCount() > 0); - cbox->setCurrentIndex(-1); - cbox->setCurrentIndex(selectedRow); + c++; + } - cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); - model = cbox->model(); - removeRows = model->rowCount(); + for (uint8_t i = 0; i < NET_CARD_MAX; ++i) { + models[i]->removeRows(0, removeRows_[i]); + cbox_[i]->setEnabled(models[i]->rowCount() > 1); + cbox_[i]->setCurrentIndex(-1); + cbox_[i]->setCurrentIndex(selectedRows[i]); + + auto cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + auto model = cbox->model(); + auto removeRows = model->rowCount(); Models::AddEntry(model, tr("Null Driver"), NET_TYPE_NONE); Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP); - if (network_ndev > 1) { + if (network_ndev > 1) Models::AddEntry(model, "PCap", NET_TYPE_PCAP); - } - if (network_devmap.has_vde) { + + if (network_devmap.has_vde) Models::AddEntry(model, "VDE", NET_TYPE_VDE); - } model->removeRows(0, removeRows); cbox->setCurrentIndex(cbox->findData(net_cards_conf[i].net_type)); @@ -205,6 +214,7 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) model->removeRows(0, removeRows); cbox->setCurrentIndex(selectedRow); } + if (net_cards_conf[i].net_type == NET_TYPE_VDE) { QString currentVdeSocket = net_cards_conf[i].host_dev_name; auto editline = findChild(QString("socketVDENIC%1").arg(i+1)); diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index a7db551ad..b780dc1a6 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -83,31 +83,45 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) ui->comboBoxRTC->setCurrentIndex(selectedRow); ui->pushButtonConfigureRTC->setEnabled((isartc_type != 0) && isartc_has_config(isartc_type) && machineHasIsa); - for (int c = 0; c < ISAMEM_MAX; c++) { - auto *cbox = findChild(QString("comboBoxCard%1").arg(c + 1)); - model = cbox->model(); - d = 0; - selectedRow = 0; - while (true) { - QString name = DeviceConfig::DeviceName(isamem_get_device(d), isamem_get_internal_name(d), 0); - if (name.isEmpty()) { - break; - } + // ISA Memory Expansion Card + QComboBox * cbox[ISAMEM_MAX] = { 0 }; + QAbstractItemModel *models[ISAMEM_MAX] = { 0 }; + int removeRows_[ISAMEM_MAX] = { 0 }; + int selectedRows[ISAMEM_MAX] = { 0 }; - if (!device_is_valid(isamem_get_device(d), machineId)) { - break; - } + for (uint8_t c = 0; c < ISAMEM_MAX; ++c) { + cbox[c] = findChild(QString("comboBoxCard%1").arg(c + 1)); + models[c] = cbox[c]->model(); + removeRows_[c] = models[c]->rowCount(); + } - int row = Models::AddEntry(model, name, d); - if (d == isamem_type[c]) { - selectedRow = row; + d = 0; + while (true) { + const QString name = DeviceConfig::DeviceName(isamem_get_device(d), + isamem_get_internal_name(d), 0); + + if (name.isEmpty()) + break; + + if (device_is_valid(isamem_get_device(d), machineId)) { + for (uint8_t c = 0; c < ISAMEM_MAX; ++c) { + int row = Models::AddEntry(models[c], name, d); + + if (d == isamem_type[c]) + selectedRows[c] = row - removeRows_[c]; } - ++d; } - cbox->setCurrentIndex(-1); - cbox->setCurrentIndex(selectedRow); - cbox->setEnabled(machineHasIsa); - findChild(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled((isamem_type[c] != 0) && isamem_has_config(isamem_type[c]) && machineHasIsa); + + d++; + } + + for (uint8_t c = 0; c < ISAMEM_MAX; ++c) { + models[c]->removeRows(0, removeRows_[c]); + cbox[c]->setEnabled(models[c]->rowCount() > 1); + cbox[c]->setCurrentIndex(-1); + cbox[c]->setCurrentIndex(selectedRows[c]); + findChild(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled((isamem_type[c] != 0) && + isamem_has_config(isamem_type[c]) && machineHasIsa); } } diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index cb1ab794a..f68106dc9 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -73,34 +73,49 @@ SettingsPorts::onCurrentMachineChanged(int machineId) { this->machineId = machineId; - for (int i = 0; i < PARALLEL_MAX; i++) { - auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); - auto *model = cbox->model(); - const auto removeRows = model->rowCount(); - int c = 0; - int selectedRow = 0; - while (true) { - const char *lptName = lpt_device_get_name(c); - if (lptName == nullptr) { - break; - } + int c = 0; - int row = Models::AddEntry(model, tr(lptName), c); - if (c == lpt_ports[i].device) { - selectedRow = row - removeRows; - } - c++; + // LPT Device + QComboBox * cbox[PARALLEL_MAX] = { 0 }; + QAbstractItemModel *models[PARALLEL_MAX] = { 0 }; + int removeRows_[PARALLEL_MAX] = { 0 }; + int selectedRows[PARALLEL_MAX] = { 0 }; + + for (uint8_t i = 0; i < PARALLEL_MAX; ++i) { + cbox[i] = findChild(QString("comboBoxLpt%1").arg(i + 1)); + models[i] = cbox[i]->model(); + removeRows_[i] = models[i]->rowCount(); + } + + while (true) { + const char *lptName = lpt_device_get_name(c); + + if (lptName == nullptr) + break; + + const QString name = tr(lptName); + + for (uint8_t i = 0; i < PARALLEL_MAX; ++i) { + int row = Models::AddEntry(models[i], name, c); + + if (c == lpt_ports[i].device) + selectedRows[i] = row - removeRows_[i]; } - model->removeRows(0, removeRows); - cbox->setEnabled(model->rowCount() > 0); - cbox->setCurrentIndex(-1); - cbox->setCurrentIndex(selectedRow); + + c++; + } + + for (uint8_t i = 0; i < PARALLEL_MAX; ++i) { + models[i]->removeRows(0, removeRows_[i]); + cbox[i]->setEnabled(models[i]->rowCount() > 1); + cbox[i]->setCurrentIndex(-1); + cbox[i]->setCurrentIndex(selectedRows[i]); auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); if (checkBox != NULL) checkBox->setChecked(lpt_ports[i].enabled > 0); - if (cbox != NULL) - cbox->setEnabled(lpt_ports[i].enabled > 0); + if (cbox[i] != NULL) + cbox[i]->setEnabled(lpt_ports[i].enabled > 0); } for (int i = 0; i < SERIAL_MAX; i++) { diff --git a/src/qt/qt_settingssound.cpp b/src/qt/qt_settingssound.cpp index cca903076..3e1240888 100644 --- a/src/qt/qt_settingssound.cpp +++ b/src/qt/qt_settingssound.cpp @@ -73,46 +73,51 @@ SettingsSound::onCurrentMachineChanged(const int machineId) { this->machineId = machineId; - int c; - int selectedRow; + int c; + int selectedRow; // Sound Card + QComboBox * cbox[SOUND_CARD_MAX] = { 0 }; + QAbstractItemModel *models[SOUND_CARD_MAX] = { 0 }; + int removeRows_[SOUND_CARD_MAX] = { 0 }; + int selectedRows[SOUND_CARD_MAX] = { 0 }; + int m_has_snd = machine_has_flags(machineId, MACHINE_SOUND); + for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { - QComboBox *cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); - c = 0; - auto model = cbox->model(); - auto removeRows = model->rowCount(); - selectedRow = 0; + cbox[i] = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); + models[i] = cbox[i]->model(); + removeRows_[i] = models[i]->rowCount(); + } - while (true) { - /* Skip "internal" if machine doesn't have it or this is not the primary card. */ - if ((c == 1) && ((i > 0) || (machine_has_flags(machineId, MACHINE_SOUND) == 0))) { - c++; - continue; - } + c = 0; + while (true) { + const QString name = DeviceConfig::DeviceName(sound_card_getdevice(c), + sound_card_get_internal_name(c), 1); - const QString name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - if (name.isEmpty()) { - break; - } + if (name.isEmpty()) + break; - if (sound_card_available(c)) { - const device_t *sound_dev = sound_card_getdevice(c); - if (device_is_valid(sound_dev, machineId)) { - int row = Models::AddEntry(model, name, c); - if (c == sound_card_current[i]) { - selectedRow = row - removeRows; + if (sound_card_available(c)) { + if (device_is_valid(sound_card_getdevice(c), machineId)) { + for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { + if ((c != 1) || ((i == 0) && m_has_snd)) { + int row = Models::AddEntry(models[i], name, c); + + if (c == sound_card_current[i]) + selectedRows[i] = row - removeRows_[i]; } } } - - c++; } - model->removeRows(0, removeRows); - cbox->setEnabled(model->rowCount() > 0); - cbox->setCurrentIndex(-1); - cbox->setCurrentIndex(selectedRow); + c++; + } + + for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { + models[i]->removeRows(0, removeRows_[i]); + cbox[i]->setEnabled(models[i]->rowCount() > 1); + cbox[i]->setCurrentIndex(-1); + cbox[i]->setCurrentIndex(selectedRows[i]); } // Midi Out diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 4adfe1546..eebed79e2 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -171,35 +171,48 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->comboBoxCDInterface->setCurrentIndex(-1); ui->comboBoxCDInterface->setCurrentIndex(selectedRow); + // SCSI Card + QComboBox * cbox[SCSI_CARD_MAX] = { 0 }; + QAbstractItemModel *models[SCSI_CARD_MAX] = { 0 }; + int removeRows_[SCSI_CARD_MAX] = { 0 }; + int selectedRows[SCSI_CARD_MAX] = { 0 }; + int m_has_scsi = machine_has_flags(machineId, MACHINE_SCSI); + for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { - QComboBox *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); - c = 0; - model = cbox->model(); - removeRows = model->rowCount(); - selectedRow = 0; + cbox[i] = findChild(QString("comboBoxSCSI%1").arg(i + 1)); + models[i] = cbox[i]->model(); + removeRows_[i] = models[i]->rowCount(); + } - while (true) { - QString name = DeviceConfig::DeviceName(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1); - if (name.isEmpty()) { - break; - } + c = 0; + while (true) { + const QString name = DeviceConfig::DeviceName(scsi_card_getdevice(c), + scsi_card_get_internal_name(c), 1); - if (scsi_card_available(c)) { - const device_t *scsi_dev = scsi_card_getdevice(c); - if (device_is_valid(scsi_dev, machineId)) { - int row = Models::AddEntry(model, name, c); - if (c == scsi_card_current[i]) { - selectedRow = row - removeRows; + if (name.isEmpty()) + break; + + if (scsi_card_available(c)) { + if (device_is_valid(scsi_card_getdevice(c), machineId)) { + for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { + if ((c != 1) || ((i == 0) && m_has_scsi)) { + int row = Models::AddEntry(models[i], name, c); + + if (c == scsi_card_current[i]) + selectedRows[i] = row - removeRows_[i]; } } } - c++; } - model->removeRows(0, removeRows); - cbox->setEnabled(model->rowCount() > 0); - cbox->setCurrentIndex(-1); - cbox->setCurrentIndex(selectedRow); + c++; + } + + for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { + models[i]->removeRows(0, removeRows_[i]); + cbox[i]->setEnabled(models[i]->rowCount() > 1); + cbox[i]->setCurrentIndex(-1); + cbox[i]->setCurrentIndex(selectedRows[i]); } int is_at = IS_AT(machineId); From 3fc6d29462a2f3bf6e5c7ecf79ca423e9f5ebb33 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 04:53:48 +0200 Subject: [PATCH 0631/1190] JEGA/JVGA: Only update renderer override on master, do not update CRTC cursor location unless it's either master or slave, and only override the text mode renderer - fixes AX Windows 3.0 386 enhanced mode returning from DOS box to full screen. --- src/video/vid_ega.c | 5 +---- src/video/vid_ega_render.c | 5 +++++ src/video/vid_jega.c | 39 +++++++++++++++++++++++++++---------- src/video/vid_svga.c | 6 ++---- src/video/vid_svga_render.c | 10 ++++++++++ 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index f002ef999..5b5427b9e 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -783,10 +783,7 @@ ega_poll(void *priv) ega->y_add *= ega->vres + 1; for (y = 0; y <= ega->vres; y++) { /* Render scanline */ - if (ega->render_override) - ega->render_override(ega->priv_parent); - else - ega->render(ega); + ega->render(ega); /* Render overscan */ ega->x_add = (overscan_x >> 1); diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 10667084a..8a73ffbbb 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -107,6 +107,11 @@ ega_render_overscan_right(ega_t *ega) void ega_render_text(ega_t *ega) { + if (ega->render_override) { + ega->render_override(ega->priv_parent); + return; + } + if ((ega->displine + ega->y_add) < 0) return; diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 11c9cbf8d..a238fbff9 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -464,21 +464,40 @@ jega_out(uint16_t addr, uint8_t val, void *priv) case 0x3d5: /* Data */ if (jega->regs_index != RINVALID_INDEX) { + if ((jega->regs_index < 7) && (jega->regs[0x11] & 0x80)) + return; + if ((jega->regs_index == 7) && (jega->regs[0x11] & 0x80)) + val = (jega->regs[7] & ~0x10) | (val & 0x10); + /* + Do not allow cursor updates if neither master nor slave is + active - the AX Windows 3.0 386 Enhanced Mode DOS grabber + relies on this for the cursor position to behave correctly. + */ + if ((jega->regs_index >= 0x0e) && (jega->regs_index <= 0x0f) && !(jega->regs[RMOD1] & 0x0c)) + return; 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->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; + /* + Do not allow override toggling unless it's on master and + only override the text renderer - the AX Windows 3.0 386 + Enhanced Mode DOS grabber relies on this for the grabbing + to behave correctly. + */ + if (val & 0x08) { + 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: diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 8d1535dda..b4abc18e5 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1176,10 +1176,7 @@ svga_do_render(svga_t *svga) } if (!svga->override) { - if (svga->render_override) - svga->render_override(svga->priv_parent); - else - svga->render(svga); + svga->render(svga); svga->x_add = (svga->monitor->mon_overscan_x >> 1); svga_render_overscan_left(svga); @@ -2019,6 +2016,7 @@ svga_doblit(int wx, int wy, svga_t *svga) /* Block resolution changes while in DPMS mode to avoid getting a bogus screen width (320). We're already rendering a blank screen anyway. */ + pclog("%i + %i, %i + %i\n", svga->monitor->mon_xsize, x_add, svga->monitor->mon_ysize, y_add); if (!svga->dpms) set_screen_size_monitor(svga->monitor->mon_xsize + x_add, svga->monitor->mon_ysize + y_add, svga->monitor_index); diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index c05d308fa..fbd667a1b 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -147,6 +147,11 @@ svga_render_text_40(svga_t *svga) int bg; uint32_t addr = 0; + if (svga->render_override) { + svga->render_override(svga->priv_parent); + return; + } + if ((svga->displine + svga->y_add) < 0) return; @@ -225,6 +230,11 @@ svga_render_text_80(svga_t *svga) int bg; uint32_t addr = 0; + if (svga->render_override) { + svga->render_override(svga->priv_parent); + return; + } + if ((svga->displine + svga->y_add) < 0) return; From e4877a57c52e81cace94e7e025352a9d1a0dca03 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 07:28:20 +0200 Subject: [PATCH 0632/1190] EGA/JEGA: More fixes and implemented more C&T SuperEGA behavior. --- src/video/vid_ega.c | 97 ++++++++++++++++++++++++++++++++------------ src/video/vid_jega.c | 3 +- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 5b5427b9e..82c88d827 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -61,14 +61,38 @@ int update_overscan = 0; uint8_t ega_in(uint16_t addr, void *priv); +static int +ega_get_type(ega_t *ega) +{ + int ret = ega_type; + + if (ega->actual_type == EGA_SUPEREGA) + ret = (ega->crtc[0x17] & 0x10) ? EGA_TYPE_OTHER : EGA_TYPE_IBM; + + return ret; +} + +static int +ega_get_actual_type(ega_t *ega) +{ + int ret = ega->actual_type; + + if (ega->actual_type == EGA_SUPEREGA) + ret = (ega->crtc[0x17] & 0x10) ? EGA_SUPEREGA : EGA_IBM; + + return ret; +} + void 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; + int type = ega_get_type(ega); + int atype = ega_get_actual_type(ega); + uint8_t gdcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x0f; + uint8_t crtcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x1f; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) addr ^= 0x60; @@ -94,7 +118,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) case 0x3c0: case 0x3c1: - if (ega->actual_type == EGA_SUPEREGA) + if (atype == EGA_SUPEREGA) val &= 0x7f; /* Bit 7 indicates the flipflop status (read only) */ if (!ega->attrff) { ega->attraddr = val & 31; @@ -110,7 +134,8 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->attrregs[ega->attraddr & 31] = val; if (ega->attraddr < 16) ega->fullchange = changeframecount; - if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) { + int is_attr14 = ega->chipset && (ega->attraddr == 0x14); + if ((ega->attraddr == 0x10) || is_attr14 || (ega->attraddr < 0x10)) { for (uint8_t c = 0; c < 16; c++) { if (ega->chipset) { if (ega->attrregs[0x10] & 0x80) @@ -148,7 +173,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if (!(val & 1)) io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); ega_recalctimings(ega); - if ((ega_type == EGA_TYPE_COMPAQ) && !(val & 0x02)) + if ((type == EGA_TYPE_COMPAQ) && !(val & 0x02)) mem_mapping_disable(&ega->mapping); else switch (ega->gdcreg[6] & 0xc) { case 0x0: /*128k at A0000*/ @@ -198,7 +223,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } break; case 0x3c6: - if (ega_type == EGA_TYPE_COMPAQ) + if (type == EGA_TYPE_COMPAQ) ega->ctl_mode = val; break; case 0x3ce: @@ -219,7 +244,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->chain2_read = val & 0x10; break; case 6: - if ((ega_type == EGA_TYPE_COMPAQ) && !(ega->miscout & 0x02)) + if ((type == EGA_TYPE_COMPAQ) && !(ega->miscout & 0x02)) mem_mapping_disable(&ega->mapping); else switch (val & 0xc) { case 0x0: /*128k at A0000*/ @@ -306,6 +331,8 @@ ega_in(uint16_t addr, void *priv) ega_t *ega = (ega_t *) priv; uint8_t gdcmask = (ega->actual_type == EGA_SUPEREGA) ? 0xff : 0x0f; uint8_t ret = 0xff; + int type = ega_get_type(ega); + int atype = ega_get_actual_type(ega); if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) addr ^= 0x60; @@ -329,48 +356,58 @@ ega_in(uint16_t addr, void *priv) break; 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) - ret = ega->attrregs[ega->attraddr]; + if (type == EGA_TYPE_OTHER) { + int data = (atype == EGA_SUPEREGA) ? (ega->attrff & 1) : (addr & 1); + if (data) + ret = ega->attrregs[ega->attraddr]; + else + ret = ega->attraddr | ega->attr_palette_enable; + if (atype == EGA_SUPEREGA) + /* Bit 7 indicates the flipflop status (read only) */ + ret = (ret & 0x3f) | (ega->attrff ? 0x80 : 0x00); + } break; case 0x3c2: ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; break; case 0x3c4: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = ega->seqaddr; break; case 0x3c5: - if (ega_type == EGA_TYPE_OTHER) - ret = ega->seqregs[ega->seqaddr & 0xf]; + if (type == EGA_TYPE_OTHER) { + if ((ega->seqaddr & 0x0f) > 0x04) + ret = ega->chipset ? ega->seqregs[ega->seqaddr & 0xf] : 0xff; + else + ret = ega->seqregs[ega->seqaddr & 0xf]; + } break; case 0x3c6: - if (ega_type == EGA_TYPE_COMPAQ) + if (type == EGA_TYPE_COMPAQ) ret = ega->ctl_mode; break; case 0x3c8: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = 2; break; case 0x3cc: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = ega->miscout; break; case 0x3ce: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = ega->gdcaddr; break; case 0x3cf: - if (ega_type == EGA_TYPE_OTHER) { + if (type == EGA_TYPE_OTHER) { switch (ega->gdcaddr & gdcmask) { default: ret = ega->gdcreg[ega->gdcaddr & gdcmask]; break; + case 0x09 ... 0xf7: + ret = ega->chipset ? ega->gdcreg[ega->gdcaddr & gdcmask] : 0xff; + break; case 0xf8: ret = ega->la; break; @@ -388,8 +425,14 @@ ega_in(uint16_t addr, void *priv) break; case 0x3d0: case 0x3d4: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) { ret = ega->crtcreg; + if (atype == EGA_SUPEREGA) { + ret = (ret & 0x1f) | 0xc0; + if ((ega->crtcreg & 0xc0) == 0xc0) + ret |= 0x20; + } + } break; case 0x3d1: case 0x3d5: @@ -402,28 +445,28 @@ ega_in(uint16_t addr, void *priv) break; case 0x10: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; else ret = ega->light_pen >> 8; break; case 0x11: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; else ret = ega->light_pen & 0xff; break; default: - if (ega_type == EGA_TYPE_OTHER) + if (type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; break; } break; case 0x3da: ega->attrff = 0; - if (ega_type == EGA_TYPE_COMPAQ) { + if (type == EGA_TYPE_COMPAQ) { ret = ega->stat & 0xcf; switch ((ega->attrregs[0x12] >> 4) & 0x03) { case 0x00: diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index a238fbff9..4240f5e98 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -428,7 +428,8 @@ jega_out(uint16_t addr, uint8_t val, void *priv) } } else { jega->attrregs[jega->attraddr & 31] = val; - if (jega->attraddr < 0x10) { + int is_attr14 = jega->is_vga ? (jega->attraddr == 0x14) : 0; + if (is_attr14 || (jega->attraddr < 0x10)) { for (uint8_t c = 0; c < 16; c++) { if (jega->is_vga) { if (jega->attrregs[0x10] & 0x80) From d2afb44412e414b0357c3f318c0fb5f5fbf41237 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 07:32:46 +0200 Subject: [PATCH 0633/1190] SVGA: Remove some excess logging. --- src/video/vid_svga.c | 1 - src/video/vid_svga_render.c | 9 --------- 2 files changed, 10 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index b4abc18e5..d0189e0f7 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -2016,7 +2016,6 @@ svga_doblit(int wx, int wy, svga_t *svga) /* Block resolution changes while in DPMS mode to avoid getting a bogus screen width (320). We're already rendering a blank screen anyway. */ - pclog("%i + %i, %i + %i\n", svga->monitor->mon_xsize, x_add, svga->monitor->mon_ysize, y_add); if (!svga->dpms) set_screen_size_monitor(svga->monitor->mon_xsize + x_add, svga->monitor->mon_ysize + y_add, svga->monitor_index); diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index fbd667a1b..d47697a7e 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -85,18 +85,9 @@ svga_render_blank(svga_t *svga) break; } -#if 0 - pclog("svga->displine = %i, svga->y_add = %i, svga->x_add = %i\n", svga->displine, svga->y_add, svga->x_add); -#endif uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; -#if 0 - pclog("svga->hdisp = %i, svga->scrollcache = %i, char_width = %i, sizeof(uint32_t) = %i\n", svga->hdisp, svga->scrollcache, char_width, sizeof(uint32_t)); -#endif uint32_t line_width = (uint32_t) (svga->hdisp + svga->scrollcache) * char_width * sizeof(uint32_t); -#if 0 - pclog("line_width = %i\n", line_width); -#endif if ((svga->hdisp + svga->scrollcache) > 0) memset(line_ptr, 0, line_width); } From 5569fa6f5dfbe2bed794236515307fcedcf17b91 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 08:22:14 +0200 Subject: [PATCH 0634/1190] C&T SuperEGA: More fixes, the BIOS no longer freezes on attempting to boot from anything. --- src/video/vid_ega.c | 90 +++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 82c88d827..03121751d 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -61,37 +61,15 @@ int update_overscan = 0; uint8_t ega_in(uint16_t addr, void *priv); -static int -ega_get_type(ega_t *ega) -{ - int ret = ega_type; - - if (ega->actual_type == EGA_SUPEREGA) - ret = (ega->crtc[0x17] & 0x10) ? EGA_TYPE_OTHER : EGA_TYPE_IBM; - - return ret; -} - -static int -ega_get_actual_type(ega_t *ega) -{ - int ret = ega->actual_type; - - if (ega->actual_type == EGA_SUPEREGA) - ret = (ega->crtc[0x17] & 0x10) ? EGA_SUPEREGA : EGA_IBM; - - return ret; -} - void ega_out(uint16_t addr, uint8_t val, void *priv) { ega_t *ega = (ega_t *) priv; uint8_t o; uint8_t old; - int type = ega_get_type(ega); - int atype = ega_get_actual_type(ega); - uint8_t gdcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x0f; + int type = ega_type; + int atype = ega->actual_type; + uint8_t gdcmask = (ega_type == EGA_SUPEREGA) ? 0xff : 0x0f; uint8_t crtcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x1f; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) @@ -168,7 +146,8 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->pallook = ega->vres ? pallook16 : pallook64; ega->vidclock = val & 4; ega->miscout = val; - ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : pallook64[ega->attrregs[0x11] & 0x3f]; + ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : + pallook64[ega->attrregs[0x11] & 0x3f]; io_removehandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); if (!(val & 1)) io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); @@ -290,28 +269,34 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if (ega->chipset) ega->crtcreg = val & 0x3f; else - ega->crtcreg = val & crtcmask; + ega->crtcreg = val; return; case 0x3d1: case 0x3d5: + int idx = ega->crtcreg; + if (ega->chipset) { if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) return; if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) val = (ega->crtc[7] & ~0x10) | (val & 0x10); } else { - if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80)) + idx &= crtcmask; + if ((idx >= 0x19) & (idx <= 0xf6)) return; - if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80)) + if ((idx < 7) && (ega->crtc[0x11] & 0x80)) + return; + if ((idx == 7) && (ega->crtc[0x11] & 0x80)) val = (ega->crtc[7] & ~0x10) | (val & 0x10); } - old = ega->crtc[ega->crtcreg]; - ega->crtc[ega->crtcreg] = val; + old = ega->crtc[idx]; + ega->crtc[idx] = val; if (old != val) { - if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) { - if ((ega->crtcreg == 0xc) || (ega->crtcreg == 0xd)) { + if ((idx < 0xe) || (idx > 0x10)) { + if ((idx == 0xc) || (idx == 0xd)) { ega->fullchange = 3; - ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + ((ega->crtc[8] & 0x60) >> 5); + ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + + ((ega->crtc[8] & 0x60) >> 5); } else { ega->fullchange = changeframecount; ega_recalctimings(ega); @@ -329,10 +314,11 @@ uint8_t ega_in(uint16_t addr, void *priv) { ega_t *ega = (ega_t *) priv; - uint8_t gdcmask = (ega->actual_type == EGA_SUPEREGA) ? 0xff : 0x0f; - uint8_t ret = 0xff; - int type = ega_get_type(ega); - int atype = ega_get_actual_type(ega); + uint8_t ret = 0xff; + int type = ega_type; + int atype = ega->actual_type; + uint8_t gdcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x0f; + uint8_t crtcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x1f; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) addr ^= 0x60; @@ -372,8 +358,12 @@ ega_in(uint16_t addr, void *priv) ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; break; case 0x3c4: - if (type == EGA_TYPE_OTHER) - ret = ega->seqaddr; + if (type == EGA_TYPE_OTHER) { + if (atype == EGA_SUPEREGA) + ret = 0x1f | ((ega->miscout & 0x01) << 5); + else + ret = ega->seqaddr; + } break; case 0x3c5: if (type == EGA_TYPE_OTHER) { @@ -396,8 +386,14 @@ ega_in(uint16_t addr, void *priv) ret = ega->miscout; break; case 0x3ce: - if (type == EGA_TYPE_OTHER) + if (ega_type == EGA_TYPE_OTHER) { ret = ega->gdcaddr; + if (atype == EGA_SUPEREGA) { + ret = (ret & 0x0f) | 0xe0; + if ((ega->gdcaddr & 0xe0) == 0xe0) + ret |= 0x10; + } + } break; case 0x3cf: if (type == EGA_TYPE_OTHER) { @@ -425,7 +421,7 @@ ega_in(uint16_t addr, void *priv) break; case 0x3d0: case 0x3d4: - if (type == EGA_TYPE_OTHER) { + if (ega_type == EGA_TYPE_OTHER) { ret = ega->crtcreg; if (atype == EGA_SUPEREGA) { ret = (ret & 0x1f) | 0xc0; @@ -436,7 +432,7 @@ ega_in(uint16_t addr, void *priv) break; case 0x3d1: case 0x3d5: - switch (ega->crtcreg) { + switch (ega->crtcreg & crtcmask) { case 0xc: case 0xd: case 0xe: @@ -458,6 +454,11 @@ ega_in(uint16_t addr, void *priv) ret = ega->light_pen & 0xff; break; + case 0x19 ... 0xf6: + if (type == EGA_TYPE_OTHER) + ret = ega->chipset ? ega->crtc[ega->crtcreg] : 0xff; + break; + default: if (type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; @@ -672,7 +673,8 @@ ega_recalctimings(ega_t *ega) disptime = (double) (ega->crtc[0] + 2); _dispontime = (double) (ega->crtc[1] + 1); } - if ((ega->actual_type == EGA_SUPEREGA) && (ega->crtc[0xf9] & 0x01)) { + if ((ega->actual_type == EGA_SUPEREGA) && (ega->crtc[0x17] & 0x10) && + (ega->crtc[0xf9] & 0x01)) { disptime *= 2.0; _dispontime *= 2.0; } From 512154e4a837c76405f446c0691e321817c526c2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Mar 2025 09:00:39 +0200 Subject: [PATCH 0635/1190] EGA: Add braces around a case block to make clang happy. --- src/video/vid_ega.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 03121751d..8333e522e 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -272,7 +272,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->crtcreg = val; return; case 0x3d1: - case 0x3d5: + case 0x3d5: { int idx = ega->crtcreg; if (ega->chipset) { @@ -305,7 +305,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } break; - default: + } default: break; } } From 8f94ccec8045afda48b88990d07b9ae966b91da7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 30 Mar 2025 21:03:46 +0600 Subject: [PATCH 0636/1190] Qt: Fix HiDPI scaling on non-software renderers --- src/qt/qt_hardwarerenderer.cpp | 7 +++++-- src/qt/qt_openglrenderer.cpp | 29 ++++++++++++++++------------- src/qt/qt_renderercommon.cpp | 3 +++ src/qt/qt_renderercommon.hpp | 2 ++ src/qt/qt_vulkanrenderer.cpp | 16 +++++----------- src/qt/qt_vulkanwindowrenderer.cpp | 5 ++++- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index ee2ec07df..d5aa86b79 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -37,7 +37,7 @@ void HardwareRenderer::resizeGL(int w, int h) { m_context->makeCurrent(this); - glViewport(0, 0, qRound(w * devicePixelRatio()), qRound(h * devicePixelRatio())); + glViewport(0, 0, qRound(w * devicePixelRatioF()), qRound(h * devicePixelRatioF())); } #define PROGRAM_VERTEX_ATTRIBUTE 0 @@ -220,14 +220,17 @@ HardwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) #endif buf_usage[buf_idx].clear(); source.setRect(x, y, w, h); - if (origSource != source) + if (origSource != source) { + this->pixelRatio = devicePixelRatioF(); onResize(this->width(), this->height()); + } update(); } void HardwareRenderer::resizeEvent(QResizeEvent *event) { + this->pixelRatio = devicePixelRatioF(); onResize(width(), height()); QOpenGLWindow::resizeEvent(event); diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index b465bfddd..cc48ca06e 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1154,14 +1154,15 @@ OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) buf_usage[buf_idx].clear(); source.setRect(x, y, w, h); + this->pixelRatio = devicePixelRatio(); onResize(this->width(), this->height()); #ifdef Q_OS_MACOS glw.glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); + destination.x(), + destination.y(), + destination.width(), + destination.height()); #endif if (video_framerate == -1) @@ -1187,6 +1188,7 @@ OpenGLRenderer::exposeEvent(QExposeEvent *event) if (!isInitialized) initialize(); + this->pixelRatio = devicePixelRatio(); onResize(size().width(), size().height()); } @@ -1195,6 +1197,7 @@ OpenGLRenderer::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); + this->pixelRatio = devicePixelRatio(); onResize(event->size().width(), event->size().height()); if (notReady()) @@ -1203,10 +1206,10 @@ OpenGLRenderer::resizeEvent(QResizeEvent *event) context->makeCurrent(this); glw.glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); + destination.x(), + destination.y(), + destination.width(), + destination.height()); } void @@ -1386,10 +1389,10 @@ OpenGLRenderer::render() uint32_t x, y, w, h; } window_rect; - window_rect.x = destination.x() * devicePixelRatio(); - window_rect.y = destination.y() * devicePixelRatio(); - window_rect.w = destination.width() * devicePixelRatio(); - window_rect.h = destination.height() * devicePixelRatio(); + window_rect.x = destination.x(); + window_rect.y = destination.y(); + window_rect.w = destination.width(); + window_rect.h = destination.height(); glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); scene_texture.min_filter = scene_texture.mag_filter = video_filter_method ? GL_LINEAR : GL_NEAREST; @@ -1652,7 +1655,7 @@ OpenGLRenderer::render() } if (monitors[r_monitor_index].mon_screenshots) { - int width = destination.width() * devicePixelRatio(), height = destination.height() * devicePixelRatio(); + int width = destination.width(), height = destination.height(); char path[1024]; char fn[256]; diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 2a20ff63c..3a34452e6 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -59,6 +59,9 @@ RendererCommon::onResize(int width, int height) bool main_max = main_window->isMaximized(); bool main_is_max = (main_is_ancestor && main_max == false); + width = round(pixelRatio * width); + height = round(pixelRatio * height); + if (is_fs && (video_fullscreen_scale_maximized ? (parent_max && main_is_max) : 1)) destination.setRect(0, 0, width, height); else { diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index bbda9516b..333b9df0a 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -49,5 +49,7 @@ protected: QRect destination; QWidget *parentWidget { nullptr }; + double pixelRatio = 1.0; + std::vector buf_usage; }; diff --git a/src/qt/qt_vulkanrenderer.cpp b/src/qt/qt_vulkanrenderer.cpp index 39830569c..2306661ec 100644 --- a/src/qt/qt_vulkanrenderer.cpp +++ b/src/qt/qt_vulkanrenderer.cpp @@ -970,17 +970,11 @@ VulkanRenderer2::startNextFrame() m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset); VkViewport viewport; - 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.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); diff --git a/src/qt/qt_vulkanwindowrenderer.cpp b/src/qt/qt_vulkanwindowrenderer.cpp index ab46b5961..d0fbb39a3 100644 --- a/src/qt/qt_vulkanwindowrenderer.cpp +++ b/src/qt/qt_vulkanwindowrenderer.cpp @@ -846,6 +846,7 @@ VulkanWindowRenderer::createRenderer() void VulkanWindowRenderer::resizeEvent(QResizeEvent *event) { + this->pixelRatio = devicePixelRatio(); onResize(width(), height()); QVulkanWindow::resizeEvent(event); @@ -868,8 +869,10 @@ VulkanWindowRenderer::onBlit(int buf_idx, int x, int y, int w, int h) if (isExposed()) requestUpdate(); buf_usage[0].clear(); - if (origSource != source) + if (origSource != source) { + this->pixelRatio = devicePixelRatio(); onResize(this->width(), this->height()); + } } uint32_t From 5ae5e99e41010861ab185012f47504fed40304dc Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 30 Mar 2025 22:06:16 +0200 Subject: [PATCH 0637/1190] Major changes on the 8514/A side again (March 30th, 2025) 1. The DX/DY coordinates for BitBLT are now signed again, fixes 8514/A cursor issues. 2. Made the busy/data available processor statuses more like the ATI one for more stability and no stalls, fixes Windows 3.x and IBM OS/2 1.x (possibly later ones too) that use the built-in 8514/A driver. 3. Made the mode switching clearer (through a note) regarding the shadow sets, this should make every program happy, I hope. 4. In the Mach32 series only, a first load of the CRT sets also initializes the GE offsets if the corresponding bit is set, fixes Mach8/32 mode tests in their eeprom and demoai with hdiload from ATI/IBM. --- src/include/86box/vid_8514a.h | 4 +- src/include/86box/vid_ati_mach8.h | 3 +- src/video/vid_8514a.c | 199 +++++++++++++++------------ src/video/vid_ati_mach8.c | 215 +++++++++++++++++++----------- 4 files changed, 256 insertions(+), 165 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index a467311ca..7694a028a 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -92,8 +92,8 @@ typedef struct ibm8514_t { uint16_t advfunc_cntl; uint16_t cur_y; uint16_t cur_x; - uint16_t destx; - uint16_t desty; + int16_t destx; + int16_t desty; int16_t desty_axstp; int16_t destx_distp; int16_t err_term; diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index 4a5d3deb5..8ed1dbc74 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -77,7 +77,8 @@ typedef struct mach_t { uint8_t overscan_g_col_24; uint8_t overscan_r_col_24; uint16_t fifo_test_data[17]; - int resolution_crt; + int port_len; + int crt_resolution; struct { uint8_t line_idx; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 393b90b57..7c0bf9702 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -834,10 +834,25 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) if (dev->force_busy) temp |= 0x0200; /*Hardware busy*/ - dev->force_busy = 0; + + if (dev->accel.cmd_back) + dev->force_busy = 0; + if (dev->data_available) { temp |= 0x0100; /*Read Data available*/ - dev->data_available = 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; + } } } break; @@ -850,9 +865,22 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) temp |= 0x02; /*Hardware busy*/ dev->force_busy2 = 0; + if (dev->data_available2) { temp |= 0x01; /*Read Data available*/ - dev->data_available2 = 0; + switch (dev->accel.cmd >> 13) { + case 2: + case 3: + case 4: + case 6: + if (dev->accel.sy < 0) + dev->data_available2 = 0; + break; + default: + if (!dev->accel.sy) + dev->data_available2 = 0; + break; + } } } break; @@ -931,10 +959,10 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) 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)) + (dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r_ibm) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b_ibm)) temp |= INT_GE_BSY; } else { if ((dev->subsys_cntl & INT_GE_BSY) && @@ -2796,8 +2824,13 @@ skip_nibble_rect_write: { dev->accel.x_count = 0; - dev->accel.dx_ibm = dev->accel.destx; - dev->accel.dy_ibm = dev->accel.desty; + 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.cx = dev->accel.cur_x; if (dev->accel.cur_x >= 0x600) @@ -2812,13 +2845,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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); } dev->accel.fill_state = 0; @@ -2844,15 +2877,15 @@ skip_nibble_rect_write: 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 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, dev->accel.dy, dev->accel.cx, dev->accel.cy, dev->accel.sx, dev->accel.sy, clip_l, clip_r, clip_t, clip_b); } if (cpu_input) { while (count-- && (dev->accel.sy >= 0)) { - 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 ((dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= 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); @@ -2916,7 +2949,7 @@ skip_nibble_rect_write: } } - READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -2932,20 +2965,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_ibm, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx, 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_ibm, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } } if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm++; + dev->accel.dx++; dev->accel.cx++; } else { - dev->accel.dx_ibm--; + dev->accel.dx--; dev->accel.cx--; } @@ -2972,30 +3005,30 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm -= (dev->accel.sx + 1); + dev->accel.dx -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx_ibm += (dev->accel.sx + 1); + dev->accel.dx += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy_ibm++; + dev->accel.dy++; dev->accel.cy++; } else { - dev->accel.dy_ibm--; + dev->accel.dy--; 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); } dev->accel.sy--; @@ -3018,10 +3051,10 @@ skip_nibble_bitblt_write: mix_dat >>= 8; dev->accel.temp_cnt = 8; } - 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 ((dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3040,7 +3073,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3052,7 +3085,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_ibm, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } @@ -3063,10 +3096,10 @@ skip_nibble_bitblt_write: } if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm++; + dev->accel.dx++; dev->accel.cx++; } else { - dev->accel.dx_ibm--; + dev->accel.dx--; dev->accel.cx--; } @@ -3075,30 +3108,30 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm -= (dev->accel.sx + 1); + dev->accel.dx -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx_ibm += (dev->accel.sx + 1); + dev->accel.dx += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy_ibm++; + dev->accel.dy++; dev->accel.cy++; } else { - dev->accel.dy_ibm--; + dev->accel.dy--; 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); } dev->accel.sy--; @@ -3117,10 +3150,10 @@ skip_nibble_bitblt_write: dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } - 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 ((dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b)) { switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3139,7 +3172,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3151,7 +3184,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_ibm, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } @@ -3159,10 +3192,10 @@ skip_nibble_bitblt_write: mix_dat >>= 1; if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm++; + dev->accel.dx++; dev->accel.cx++; } else { - dev->accel.dx_ibm--; + dev->accel.dx--; dev->accel.cx--; } @@ -3171,36 +3204,36 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm -= (dev->accel.sx + 1); + dev->accel.dx -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx_ibm += (dev->accel.sx + 1); + dev->accel.dx += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy_ibm++; + dev->accel.dy++; dev->accel.cy++; } else { - dev->accel.dy_ibm--; + dev->accel.dy--; 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); } dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.destx = dev->accel.dx_ibm; - dev->accel.desty = dev->accel.dy_ibm; + dev->accel.destx = dev->accel.dx; + dev->accel.desty = dev->accel.dy; dev->accel.cmd_back = 1; dev->fifo_idx = 0; return; @@ -3214,13 +3247,13 @@ skip_nibble_bitblt_write: int64_t dx; cx = (int64_t) dev->accel.cx; - dx = (int64_t) dev->accel.dx_ibm; + dx = (int64_t) dev->accel.dx; while (1) { if ((dx >= (((int64_t)clip_l) * 3)) && (dx <= (((uint64_t)clip_r) * 3)) && - (dev->accel.dy_ibm >= (clip_t << 1)) && - (dev->accel.dy_ibm <= (clip_b << 1))) { + (dev->accel.dy >= (clip_t << 1)) && + (dev->accel.dy <= (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); @@ -3239,10 +3272,10 @@ skip_nibble_bitblt_write: } } else { while (count-- && dev->accel.sy >= 0) { - 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 ((dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= 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); @@ -3276,7 +3309,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3291,11 +3324,11 @@ skip_nibble_bitblt_write: if (dev->accel.cmd & 0x04) { if (dev->accel.sx) { - WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } else { - 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); + WRITE(dev->accel.dest + dev->accel.dx, 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, dev->accel.dy, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); } } } @@ -3304,10 +3337,10 @@ skip_nibble_bitblt_write: mix_dat |= 1; if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm++; + dev->accel.dx++; dev->accel.cx++; } else { - dev->accel.dx_ibm--; + dev->accel.dx--; dev->accel.cx--; } @@ -3317,36 +3350,36 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx_ibm -= (dev->accel.sx + 1); + dev->accel.dx -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx_ibm += (dev->accel.sx + 1); + dev->accel.dx += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy_ibm++; + dev->accel.dy++; dev->accel.cy++; } else { - dev->accel.dy_ibm--; + dev->accel.dy--; 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * 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_ibm * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); } dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.destx = dev->accel.dx_ibm; - dev->accel.desty = dev->accel.dy_ibm; + dev->accel.destx = dev->accel.dx; + dev->accel.desty = dev->accel.dy; dev->accel.cmd_back = 1; dev->fifo_idx = 0; return; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index c21730497..474ae5660 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -344,7 +344,7 @@ 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); + mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i, dpconfig = %04x.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config); switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ @@ -900,14 +900,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } dev->accel.sy = 0; - if (mach->accel.dp_config & 0x02) - dev->accel.dest = (dev->accel.dy * dev->pitch); - else { - if (dev->bpp) - dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); - else - dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); - } + if (dev->bpp) + dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + else + dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); mach->accel.src_stepx = 0; /*Source Width*/ @@ -2221,7 +2217,7 @@ mach_accel_out_pixtrans(svga_t *svga, mach_t *mach, ibm8514_t *dev, uint16_t val case 0x200: /*16-bit size*/ if (mono_src == 2) { if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if (((mach->accel.dp_config & 0x1000) && !swap) || swap) { + if (((mach->accel.dp_config & 0x1000) && !swap) || (!(mach->accel.dp_config & 0x1000) && swap)) { mach_log("16-bit bus size swap.\n"); val = (val >> 8) | (val << 8); } @@ -2663,17 +2659,22 @@ ati_render_32bpp(svga_t *svga) } } +/*The situation is the following: + When ATI mode is selected, allow complete auto-detection. + But when 8514/A mode is selected, allow detection based on the shadow register sets. +*/ + static void mach_set_resolution(mach_t *mach, svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; dev->hdisp = (dev->hdisped + 1) << 3; - if (!dev->htotal) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/ - dev->htotal = 0x9d; - dev->h_total = dev->htotal + 1; + if (dev->h_total == 1) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/ + dev->h_total = 0x9e; + dev->vdisp = (dev->v_disp + 1) >> 1; if ((dev->vdisp == 478) || (dev->vdisp == 598) || (dev->vdisp == 766) || (dev->vdisp == 1022)) dev->vdisp += 2; @@ -2686,26 +2687,72 @@ mach_set_resolution(mach_t *mach, svga_t *svga) 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); + mach_log("Shadow set ATI=%x, shadow set 8514/A=%x, resolution h=%d, v=%d, vtotal=%d, vsyncstart=%d.\n", mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp, dev->v_total, dev->v_syncstart); 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); - } - } else { - if (ATI_8514A_ULTRA) { - if (dev->accel.advfunc_cntl & 0x04) { - if (dev->hdisp == 640) { - dev->hdisp = 1024; - dev->vdisp = 768; + switch (mach->shadow_set & 0x03) { + case 0x00: /*Primary CRT Register set*/ + if (dev->on) { + if (mach->crt_resolution == 0x01) { + if (ATI_8514A_ULTRA) { + if (dev->accel.advfunc_cntl & 0x04) { + if (dev->hdisp == 640) { + dev->hdisp = 1024; + dev->vdisp = 768; + svga_recalctimings(svga); + } + } else { + if (dev->hdisp == 1024) { + dev->hdisp = 640; + dev->vdisp = 480; + svga_recalctimings(svga); + } + } + } else + svga_recalctimings(svga); + } else if (mach->crt_resolution == 0x02) { + if (dev->accel.advfunc_cntl & 0x04) { + if (dev->hdisp == 640) { + dev->hdisp = 1024; + dev->vdisp = 768; + svga_recalctimings(svga); + } + } else { + if (dev->hdisp == 1024) { + dev->hdisp = 640; + dev->vdisp = 480; + svga_recalctimings(svga); + } + } + } else svga_recalctimings(svga); - } } - } + break; + case 0x01: /*Shadow 640x480 CRT register set*/ + if (dev->on) { + if (!(dev->accel.advfunc_cntl & 0x04)) { + if (dev->hdisp == 1024) { + dev->hdisp = 640; + dev->vdisp = 480; + } + } + svga_recalctimings(svga); + } + break; + case 0x02: /*Shadow 1024x768 CRT register set*/ + if (dev->on) { + if (dev->accel.advfunc_cntl & 0x04) { + if (dev->hdisp == 640) { + dev->hdisp = 1024; + dev->vdisp = 768; + } + } + svga_recalctimings(svga); + } + break; + default: + break; } } } @@ -2739,6 +2786,7 @@ ati8514_recalctimings(svga_t *svga) if (dev->interlace) dev->dispend >>= 1; + mach->crt_resolution = 0x00; 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); @@ -2752,7 +2800,6 @@ ati8514_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; - mach->resolution_crt = 0; svga->render8514 = ibm8514_render_8bpp; } } @@ -2808,15 +2855,15 @@ mach_recalctimings(svga_t *svga) svga->ati_4color = 0; } - mach_log("ON?=%d, override=%d.\n", dev->on, svga->override); + mach_log("ON?=%d, override=%d, gelo=%04x, gehi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, svga->hdisp); 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->ma_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; 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; + mach_log("8514/A ON, extpitch=%d, geoffset=%x, 8514malatch=%x, vgamalatch=%x.\n", dev->ext_pitch, mach->accel.ge_offset, dev->ma_latch, svga->ma_latch); 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, @@ -2836,6 +2883,7 @@ mach_recalctimings(svga_t *svga) if (dev->interlace) dev->dispend >>= 1; + mach->crt_resolution = 0x00; if (ATI_MACH32) { 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, @@ -2877,7 +2925,6 @@ mach_recalctimings(svga_t *svga) 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; @@ -2915,7 +2962,6 @@ mach_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; - mach->resolution_crt = 0; svga->render8514 = ibm8514_render_8bpp; } } else { @@ -2973,7 +3019,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u switch (port) { case 0x2e8: - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ + 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; @@ -2982,44 +3028,44 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xae8: - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ + 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); + mach_set_resolution(mach, svga); } break; case 0xee8: - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ + 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); + mach_set_resolution(mach, 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); + mach_set_resolution(mach, 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)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { - if (!(mach->shadow_cntl & 0x08)) { + 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 >> 8) & 0xff; + + if (!(mach->shadow_cntl & 0x08)) { + if (dev->htotal || (mach->accel.clock_sel & 0x01)) { WRITE8(port, dev->hdisped, val); } } - if (ATI_8514A_ULTRA) { - if (!(mach->shadow_cntl & 0x04)) - dev->htotal = (val >> 8) & 0xff; - } - mach_set_resolution(mach, svga); + if (dev->htotal || (mach->accel.clock_sel & 0x01)) + 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); @@ -3032,9 +3078,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (!(mach->shadow_cntl & 0x08)) { WRITE8(port, dev->hdisped, val); } - if (mach->resolution_crt == 0x00) - mach->resolution_crt = 0x02; - mach_set_resolution(mach, svga); } } @@ -3045,10 +3088,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ - if (!(mach->shadow_cntl & 0x04)) { + 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); } } @@ -3056,7 +3099,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x12e8: if (len == 2) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ + 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; @@ -3064,7 +3107,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_set_resolution(mach, svga); } } else { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { /*For 8514/A mode, take the shadow sets into account.*/ + 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; @@ -3077,7 +3120,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x12e9: if (len == 1) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { + 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; @@ -3090,8 +3133,14 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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.*/ + 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 & 0x20)) { + dev->v_disp = val; + dev->v_disp &= 0x1fff; + } + 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 & 0x20)) { dev->v_disp = val; dev->v_disp &= 0x1fff; } @@ -3100,8 +3149,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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.*/ + 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 & 0x20)) { WRITE8(port, dev->v_disp, val); dev->v_disp &= 0x1fff; } @@ -3111,8 +3160,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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.*/ + 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 & 0x20)) { WRITE8(port, dev->v_disp, val); dev->v_disp &= 0x1fff; } @@ -3125,8 +3174,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x1ae8: if (len == 2) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { - if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + 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_sync_start = val; dev->v_sync_start &= 0x1fff; } @@ -3135,8 +3184,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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)) || ATI_8514A_ULTRA) { - if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + 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_sync_start, val); dev->v_sync_start &= 0x1fff; } @@ -3146,8 +3195,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x1ae9: if (len == 1) { - if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03)) || ATI_8514A_ULTRA) { - if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + 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_sync_start, val); dev->v_sync_start &= 0x1fff; } @@ -3168,7 +3217,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u svga_recalctimings(svga); break; - case 0x42e8: case 0x42e9: mach_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); @@ -3672,11 +3720,19 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if ((mach->shadow_set & 0x03) == 0x00) mach_log("Primary CRT register set.\n"); else if ((mach->shadow_set & 0x03) == 0x01) { + mach->crt_resolution = 0x01; mach_log("CRT Shadow Set 1: 640x480.\n"); - mach->resolution_crt = 0x01; } else if ((mach->shadow_set & 0x03) == 0x02) { + mach->crt_resolution = 0x02; mach_log("CRT Shadow Set 2: 1024x768.\n"); - mach->resolution_crt = 0x02; + } + + if (ATI_MACH32) { + if ((mach->shadow_set & 0x300) == 0x000) { + mach_log("Load both SRC/DST GE Offset/Pitch.\n"); + mach->accel.ge_offset_lo = 0; + mach->accel.ge_offset_hi = 0; + } } break; @@ -4182,11 +4238,11 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 4: case 6: if (dev->accel.sy < 0) - dev->data_available = 0; + dev->data_available2 = 0; break; default: if (!dev->accel.sy) - dev->data_available = 0; + dev->data_available2 = 0; break; } } @@ -4525,10 +4581,10 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) 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)) + (dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r_ibm) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b_ibm)) temp |= INT_GE_BSY; } else { if ((dev->subsys_cntl & INT_GE_BSY) && @@ -4678,6 +4734,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) temp = 0x0000; } } else { + mach_log("ScratchPad0=%x.\n", mach->accel.scratch0); if (mach->accel.scratch0 == 0x1234) temp = 0x0000; } @@ -7019,7 +7076,7 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) dev->disp_cntl = 0x33; mach->accel.clock_sel = 0x1c; mach->shadow_set = 0x02; - mach->resolution_crt = 0x02; + mach->crt_resolution = 0x02; io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); ati8514_io_set(svga); From 8ff30ab2e63c55a03190b70040bc37bdac703d8d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 30 Mar 2025 23:17:58 +0200 Subject: [PATCH 0638/1190] Mach64 ISA/VLB LFB update of the day (March 30th, 2025) The LFB can now be enabled properly on the ISA/VLB variants of the Mach64GX. --- src/video/vid_ati_mach64.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 24935e3a2..4ec9afff8 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -3768,6 +3768,9 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x6aee: case 0x6aef: WRITE8(port, mach64->config_cntl, val); + if (!mach64->pci) + mach64->linear_base = (mach64->config_cntl & 0x3ff0) << 18; + mach64_updatemapping(mach64); break; From 3f0138a58c117c96fec7e74326ca0a31fa48e537 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 31 Mar 2025 04:35:17 +0200 Subject: [PATCH 0639/1190] VIA On-board AC'97 Audio: Fix PCI registers, implement PCI Power Manager capability registers, properly separate the modem SGD from the audio SGD, and fix 5-bit volume attenuation, this also fixes audio playback in NT 4.0. --- src/chipset/via_pipc.c | 149 +++++++++++++++++------- src/sound/snd_ac97_codec.c | 5 +- src/sound/snd_ac97_via.c | 224 ++++++++++++++++++++----------------- 3 files changed, 233 insertions(+), 145 deletions(-) diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 6b855f5aa..248664983 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -493,14 +493,28 @@ pipc_reset_hard(void *priv) } dev->ac97_regs[i][0x1c] = 0x01; + if (i == 0) { + dev->ac97_regs[i][0x34] = 0xc0; + + dev->ac97_regs[i][0xc0] = 0x01; + dev->ac97_regs[i][0xc1] = 0x00; + dev->ac97_regs[i][0xc2] = 0x03; + dev->ac97_regs[i][0xc3] = 0x00; + + dev->ac97_regs[i][0xc4] = 0x00; + dev->ac97_regs[i][0xc5] = 0x00; + dev->ac97_regs[i][0xc6] = 0x00; + dev->ac97_regs[i][0xc7] = 0x00; + } + dev->ac97_regs[i][0x3d] = 0x03; - if (i == 0) + if (i == 0) { dev->ac97_regs[i][0x40] = 0x01; - - dev->ac97_regs[i][0x43] = 0x1c; - dev->ac97_regs[i][0x48] = 0x01; - dev->ac97_regs[i][0x4b] = 0x02; + dev->ac97_regs[i][0x43] = 0x1c; + dev->ac97_regs[i][0x48] = 0x01; + dev->ac97_regs[i][0x4b] = 0x00; + } pipc_sgd_handlers(dev, i); pipc_codec_handlers(dev, i); @@ -742,10 +756,12 @@ pipc_codec_handlers(pipc_t *dev, uint8_t modem) if (!dev->ac97) return; + uint32_t base = (dev->ac97_regs[modem][0x1d] << 8); + if (modem) - ac97_via_remap_modem_codec(dev->ac97, dev->ac97_regs[1][0x1d] << 8, dev->ac97_regs[1][0x04] & PCI_COMMAND_IO); + ac97_via_remap_modem_codec(dev->ac97, base, dev->ac97_regs[1][0x04] & PCI_COMMAND_IO); else - ac97_via_remap_audio_codec(dev->ac97, dev->ac97_regs[0][0x1d] << 8, dev->ac97_regs[0][0x04] & PCI_COMMAND_IO); + ac97_via_remap_audio_codec(dev->ac97, base, dev->ac97_regs[0][0x04] & PCI_COMMAND_IO); } static uint8_t @@ -1204,7 +1220,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv) case 0x77: if ((dev->local >= VIA_PIPC_686A) && (val & 0x10)) - pclog("PIPC: Warning: Internal I/O APIC enabled.\n"); + warning("PIPC: Warning: Internal I/O APIC enabled.\n"); nvr_via_wp_set(!!(val & 0x04), 0x32, dev->nvr); nvr_via_wp_set(!!(val & 0x02), 0x0d, dev->nvr); break; @@ -1488,36 +1504,39 @@ pipc_write(int func, int addr, uint8_t val, void *priv) break; } } else if (func <= pm_func + 2) { /* AC97 / MC97 */ - /* Read-only addresses. */ - if ((addr < 0x4) || ((addr >= 0x6) && (addr < 0x9)) || ((addr >= 0xc) && (addr < 0x11)) || (addr == 0x16) || (addr == 0x17) || (addr == 0x1a) || (addr == 0x1b) || ((addr >= 0x1e) && (addr < 0x2c)) || ((addr >= 0x30) && (addr < 0x34)) || ((addr >= 0x35) && (addr < 0x3c)) || ((addr >= 0x3d) && (addr < 0x41)) || ((addr >= 0x45) && (addr < 0x4a)) || (addr >= 0x4c)) - return; - /* Small shortcut. */ func = func - pm_func - 1; - /* Check disable bits and specific read-only addresses for both controllers. */ - if ((func == 0) && (((addr >= 0x09) && (addr < 0xc)) || (addr == 0x44) || (dev->pci_isa_regs[0x85] & 0x04))) + /* Check disable bits. */ + if ((func == 0) && (dev->pci_isa_regs[0x85] & 0x04)) return; - if ((func == 1) && ((addr == 0x14) || (addr == 0x15) || (addr == 0x18) || (addr == 0x19) || (addr == 0x42) || (addr == 0x43) || (addr == 0x48) || (addr == 0x4a) || (addr == 0x4b) || (dev->pci_isa_regs[0x85] & 0x08))) + if ((func == 1) && (dev->pci_isa_regs[0x85] & 0x08)) return; switch (addr) { case 0x04: - dev->ac97_regs[func][addr] = val; + dev->ac97_regs[func][addr] = val & 0x01; pipc_sgd_handlers(dev, func); + if (func == 0) { + pipc_fmnmi_handlers(dev, func); + pipc_sb_handlers(dev, func); + } pipc_codec_handlers(dev, func); - pipc_fmnmi_handlers(dev, func); break; case 0x09: case 0x0a: case 0x0b: - if (dev->ac97_regs[func][0x44] & 0x20) + /* Not writable on audio, only on modem. */ + if ((func == 1) && (dev->ac97_regs[func][0x44] & 0x20)) dev->ac97_regs[func][addr] = val; break; - case 0x10: + /* + The lowest 10 bytes are always 0x01, indicating + a 256-byte I/O space. + */ case 0x11: dev->ac97_regs[func][addr] = val; pipc_sgd_handlers(dev, func); @@ -1525,21 +1544,26 @@ pipc_write(int func, int addr, uint8_t val, void *priv) case 0x14: case 0x15: - if (addr == 0x14) - val = (val & 0xfc) | 1; - dev->ac97_regs[func][addr] = val; - pipc_fmnmi_handlers(dev, func); + /* Not present on modem. */ + if (func == 0) { + if (addr == 0x14) + val = (val & 0xfc) | 1; + dev->ac97_regs[func][addr] = val; + pipc_fmnmi_handlers(dev, func); + } break; case 0x18: case 0x19: - if (addr == 0x18) - val = (val & 0xfc) | 1; - dev->ac97_regs[func][addr] = val; - pipc_sb_handlers(dev, func); + /* Not present on modem. */ + if (func == 0) { + if (addr == 0x18) + val = (val & 0xfc) | 1; + dev->ac97_regs[func][addr] = val; + pipc_sb_handlers(dev, func); + } break; - case 0x1c: case 0x1d: dev->ac97_regs[func][addr] = val; pipc_codec_handlers(dev, func); @@ -1549,39 +1573,84 @@ pipc_write(int func, int addr, uint8_t val, void *priv) case 0x2d: case 0x2e: case 0x2f: - if ((func == 0) && (dev->ac97_regs[func][0x42] & 0x20)) + if (((func == 0) && (dev->ac97_regs[func][0x42] & 0x20)) || + ((func == 1) && (dev->ac97_regs[func][0x44] & 0x10))) dev->ac97_regs[func][addr] = val; break; + case 0x3c: + dev->ac97_regs[func][addr] = val & 0x0f; + break; + case 0x41: dev->ac97_regs[func][addr] = val; ac97_via_write_control(dev->ac97, func, val); break; case 0x42: - case 0x4a: - case 0x4b: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val; - gameport_remap(dev->gameport, (dev->ac97_regs[0][0x42] & 0x08) ? ((dev->ac97_regs[0][0x4b] << 8) | (dev->ac97_regs[0][0x4a] & 0xf8)) : 0); - if (addr == 0x42) - pipc_sb_handlers(dev, func); + case 0x4a ... 0x4b: + if (func == 0) { + dev->ac97_regs[func][addr] = val; + gameport_remap(dev->gameport, (dev->ac97_regs[func][0x42] & 0x08) ? + ((dev->ac97_regs[func][0x4b] << 8) | + (dev->ac97_regs[func][0x4a] & 0xf8)) : 0); + + if (addr == 0x42) + pipc_sb_handlers(dev, func); + } break; case 0x43: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val; + if (func == 0) + dev->ac97_regs[func][addr] = val; break; case 0x44: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0xf0; + if (func == 1) + dev->ac97_regs[func][addr] = val & 0xf0; break; - case 0x45: case 0x48: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0x0f; + if (func == 0) + dev->ac97_regs[func][addr] = val & 0x0f; + break; + + case 0x80: + case 0x81: + case 0x82: + dev->ac97_regs[func][addr] = val; + break; + case 0x83: + dev->ac97_regs[func][addr] = ((dev->ac97_regs[func][addr] & 0x01) | + (val & 0xc0)) & ~(val & 0x0a); + break; + + case 0x88: + case 0x89: + dev->ac97_regs[func][addr] = val; + break; + case 0x8a: + case 0x8b: + dev->ac97_regs[func][addr] &= ~val; + break; + + case 0x8e: + case 0x8f: + dev->ac97_regs[func][addr] = val; + break; + + case 0xc4: + if (func == 0) + dev->ac97_regs[func][addr] = (dev->ac97_regs[func][addr] & 0x0c) | + (val & 0x03); + break; + case 0xc5: + if (func == 0) + dev->ac97_regs[func][addr] = (dev->ac97_regs[func][addr] & 0x60) | + (val & 0x9f); break; default: - dev->ac97_regs[func][addr] = val; break; } } diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index e92830f67..7a9951289 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -539,8 +539,9 @@ ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r) *l = codec_attn[0x3f - (l_val & 0x3f)]; *r = codec_attn[0x3f - (r_val & 0x3f)]; } else { /* 5-bit gain */ - *l = codec_attn[0x47 - (l_val & 0x1f)]; - *r = codec_attn[0x47 - (r_val & 0x1f)]; + /* Yes, 0x3f is correct, the 0x47 was most likely a decimal-hex mix-up. */ + *l = codec_attn[0x3f - (l_val & 0x1f)]; + *r = codec_attn[0x3f - (r_val & 0x1f)]; } /* Apply per-channel mute and center/LFE powerdowns where applicable. */ diff --git a/src/sound/snd_ac97_via.c b/src/sound/snd_ac97_via.c index 8c1e45c40..68ef5fe5d 100644 --- a/src/sound/snd_ac97_via.c +++ b/src/sound/snd_ac97_via.c @@ -24,6 +24,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include <86box/dma.h> #include <86box/mem.h> #include <86box/pci.h> #include <86box/pic.h> @@ -31,10 +32,13 @@ #include <86box/sound.h> #include <86box/timer.h> #include <86box/plat_unused.h> +#include "cpu.h" typedef struct ac97_via_sgd_t { uint8_t id; uint8_t always_run; + uint8_t modem; + uint8_t pad; struct _ac97_via_ *dev; uint32_t entry_ptr; @@ -63,7 +67,7 @@ typedef struct _ac97_via_ { uint16_t audio_codec_base; uint16_t modem_sgd_base; uint16_t modem_codec_base; - uint8_t sgd_regs[256]; + uint8_t sgd_regs[2][256]; uint8_t pcm_enabled : 1; uint8_t fm_enabled : 1; uint8_t vsr_enabled : 1; @@ -78,7 +82,7 @@ typedef struct _ac97_via_ { int irq_pin; ac97_codec_t *codec[2][2]; - ac97_via_sgd_t sgd[6]; + ac97_via_sgd_t sgd[2][6]; int master_vol_l; int master_vol_r; @@ -105,7 +109,7 @@ ac97_via_log(const char *fmt, ...) #endif static void ac97_via_sgd_process(void *priv); -static void ac97_via_update_codec(ac97_via_t *dev); +static void ac97_via_update_codec(ac97_via_t *dev, int modem); static void ac97_via_speed_changed(void *priv); static void ac97_via_filter_cd_audio(int channel, double *buffer, void *priv); @@ -160,29 +164,29 @@ ac97_via_write_control(void *priv, uint8_t modem, uint8_t val) /* Start or stop PCM playback. */ i = (val & 0xf4) == 0xc4; if (i && !dev->pcm_enabled) - timer_advance_u64(&dev->sgd[0].poll_timer, dev->sgd[0].timer_latch); + timer_advance_u64(&dev->sgd[0][0].poll_timer, dev->sgd[0][0].timer_latch); dev->pcm_enabled = i; /* Start or stop FM playback. */ i = (val & 0xf2) == 0xc2; if (i && !dev->fm_enabled) - timer_advance_u64(&dev->sgd[2].poll_timer, dev->sgd[2].timer_latch); + timer_advance_u64(&dev->sgd[0][2].poll_timer, dev->sgd[0][2].timer_latch); dev->fm_enabled = i; /* Update primary audio codec state. */ if (dev->codec[0][0]) - ac97_via_update_codec(dev); + ac97_via_update_codec(dev, 0); } } static void -ac97_via_update_irqs(ac97_via_t *dev) +ac97_via_update_irqs(ac97_via_t *dev, int modem) { /* Check interrupt flags in all SGDs. */ for (uint8_t i = 0x00; i < ((sizeof(dev->sgd) / sizeof(dev->sgd[0])) << 4); i += 0x10) { /* Stop immediately if any flag is set. Doing it this way optimizes rising edges for the playback SGD (0 - first to be checked). */ - if (dev->sgd_regs[i] & (dev->sgd_regs[i | 0x2] & 0x03)) { + if (dev->sgd_regs[modem][i] & (dev->sgd_regs[modem][i | 0x2] & 0x03)) { pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); return; } @@ -192,15 +196,15 @@ ac97_via_update_irqs(ac97_via_t *dev) } static void -ac97_via_update_codec(ac97_via_t *dev) +ac97_via_update_codec(ac97_via_t *dev, int modem) { /* Get primary audio codec. */ - ac97_codec_t *codec = dev->codec[0][0]; + ac97_codec_t *codec = dev->codec[modem][0]; /* Update volumes according to codec registers. */ ac97_codec_getattn(codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); - ac97_codec_getattn(codec, 0x18, &dev->sgd[0].vol_l, &dev->sgd[0].vol_r); - ac97_codec_getattn(codec, 0x18, &dev->sgd[2].vol_l, &dev->sgd[2].vol_r); /* VIAFMTSR sets Master, CD and PCM volumes to 0 dB */ + ac97_codec_getattn(codec, 0x18, &dev->sgd[modem][0].vol_l, &dev->sgd[modem][0].vol_r); + ac97_codec_getattn(codec, 0x18, &dev->sgd[modem][2].vol_l, &dev->sgd[modem][2].vol_r); /* VIAFMTSR sets Master, CD and PCM volumes to 0 dB */ ac97_codec_getattn(codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); /* Update sample rate according to codec registers and the variable sample rate flag. */ @@ -211,9 +215,9 @@ uint8_t ac97_via_sgd_read(uint16_t addr, void *priv) { const ac97_via_t *dev = (ac97_via_t *) priv; -#ifdef ENABLE_AC97_VIA_LOG +// #ifdef ENABLE_AC97_VIA_LOG uint8_t modem = (addr & 0xff00) == dev->modem_sgd_base; -#endif +// #endif addr &= 0xff; uint8_t ret; @@ -221,83 +225,83 @@ ac97_via_sgd_read(uint16_t addr, void *priv) /* Process SGD channel registers. */ switch (addr & 0xf) { case 0x4: - ret = dev->sgd[addr >> 4].entry_ptr; + ret = dev->sgd[modem][addr >> 4].entry_ptr; break; case 0x5: - ret = dev->sgd[addr >> 4].entry_ptr >> 8; + ret = dev->sgd[modem][addr >> 4].entry_ptr >> 8; break; case 0x6: - ret = dev->sgd[addr >> 4].entry_ptr >> 16; + ret = dev->sgd[modem][addr >> 4].entry_ptr >> 16; break; case 0x7: - ret = dev->sgd[addr >> 4].entry_ptr >> 24; + ret = dev->sgd[modem][addr >> 4].entry_ptr >> 24; break; case 0xc: - ret = dev->sgd[addr >> 4].sample_count; + ret = dev->sgd[modem][addr >> 4].sample_count; break; case 0xd: - ret = dev->sgd[addr >> 4].sample_count >> 8; + ret = dev->sgd[modem][addr >> 4].sample_count >> 8; break; case 0xe: - ret = dev->sgd[addr >> 4].sample_count >> 16; + ret = dev->sgd[modem][addr >> 4].sample_count >> 16; break; default: - ret = dev->sgd_regs[addr]; + ret = dev->sgd_regs[modem][addr]; break; } } else { /* Process regular registers. */ switch (addr) { case 0x84: - ret = (dev->sgd_regs[0x00] & 0x01); - ret |= (dev->sgd_regs[0x10] & 0x01) << 1; - ret |= (dev->sgd_regs[0x20] & 0x01) << 2; + ret = (dev->sgd_regs[modem][0x00] & 0x01); + ret |= (dev->sgd_regs[modem][0x10] & 0x01) << 1; + ret |= (dev->sgd_regs[modem][0x20] & 0x01) << 2; - ret |= (dev->sgd_regs[0x00] & 0x02) << 3; - ret |= (dev->sgd_regs[0x10] & 0x02) << 4; - ret |= (dev->sgd_regs[0x20] & 0x02) << 5; + ret |= (dev->sgd_regs[modem][0x00] & 0x02) << 3; + ret |= (dev->sgd_regs[modem][0x10] & 0x02) << 4; + ret |= (dev->sgd_regs[modem][0x20] & 0x02) << 5; break; case 0x85: - ret = (dev->sgd_regs[0x00] & 0x04) >> 2; - ret |= (dev->sgd_regs[0x10] & 0x04) >> 1; - ret |= (dev->sgd_regs[0x20] & 0x04); + ret = (dev->sgd_regs[modem][0x00] & 0x04) >> 2; + ret |= (dev->sgd_regs[modem][0x10] & 0x04) >> 1; + ret |= (dev->sgd_regs[modem][0x20] & 0x04); - ret |= (dev->sgd_regs[0x00] & 0x80) >> 3; - ret |= (dev->sgd_regs[0x10] & 0x80) >> 2; - ret |= (dev->sgd_regs[0x20] & 0x80) >> 1; + ret |= (dev->sgd_regs[modem][0x00] & 0x80) >> 3; + ret |= (dev->sgd_regs[modem][0x10] & 0x80) >> 2; + ret |= (dev->sgd_regs[modem][0x20] & 0x80) >> 1; break; case 0x86: - ret = (dev->sgd_regs[0x40] & 0x01); - ret |= (dev->sgd_regs[0x50] & 0x01) << 1; + ret = (dev->sgd_regs[modem][0x40] & 0x01); + ret |= (dev->sgd_regs[modem][0x50] & 0x01) << 1; - ret |= (dev->sgd_regs[0x40] & 0x02) << 3; - ret |= (dev->sgd_regs[0x50] & 0x02) << 4; + ret |= (dev->sgd_regs[modem][0x40] & 0x02) << 3; + ret |= (dev->sgd_regs[modem][0x50] & 0x02) << 4; break; case 0x87: - ret = (dev->sgd_regs[0x40] & 0x04) >> 2; - ret |= (dev->sgd_regs[0x50] & 0x04) >> 1; + ret = (dev->sgd_regs[modem][0x40] & 0x04) >> 2; + ret |= (dev->sgd_regs[modem][0x50] & 0x04) >> 1; - ret |= (dev->sgd_regs[0x40] & 0x80) >> 3; - ret |= (dev->sgd_regs[0x50] & 0x80) >> 2; + ret |= (dev->sgd_regs[modem][0x40] & 0x80) >> 3; + ret |= (dev->sgd_regs[modem][0x50] & 0x80) >> 2; break; default: - ret = dev->sgd_regs[addr]; + ret = dev->sgd_regs[modem][addr]; break; } } - ac97_via_log("AC97 VIA %d: sgd_read(%02X) = %02X\n", modem, addr, ret); + ac97_via_log("[%04X:%08X] [%i] AC97 VIA %d: sgd_read(%02X) = %02X\n", CS, cpu_state.pc, msw & 1, modem, addr, ret); return ret; } @@ -311,7 +315,9 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) ac97_codec_t *codec; addr &= 0xff; - ac97_via_log("AC97 VIA %d: sgd_write(%02X, %02X)\n", modem, addr, val); + ac97_via_log("[%04X:%08X] [%i] AC97 VIA %d: sgd_write(%02X, %02X)\n", CS, cpu_state.pc, msw & 1, modem, addr, val); + + // if ((CS == 0x10000) && (cpu_state.pc == 0x000073d1)) /* Check function-specific read only registers. */ if ((addr >= (modem ? 0x00 : 0x40)) && (addr < (modem ? 0x40 : 0x60))) @@ -324,42 +330,42 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) switch (addr & 0xf) { case 0x0: /* Clear RWC status bits. */ - dev->sgd_regs[addr] &= ~(val & 0x07); + dev->sgd_regs[modem][addr] &= ~(val & 0x07); /* Update status interrupts. */ - ac97_via_update_irqs(dev); + ac97_via_update_irqs(dev, modem); return; case 0x1: /* Start SGD if requested. */ if (val & 0x80) { - if (dev->sgd_regs[addr & 0xf0] & 0x80) { + if (dev->sgd_regs[modem][addr & 0xf0] & 0x80) { /* Queue SGD trigger if already running. */ - dev->sgd_regs[addr & 0xf0] |= 0x08; + dev->sgd_regs[modem][addr & 0xf0] |= 0x08; } else { /* Start SGD immediately. */ - dev->sgd_regs[addr & 0xf0] = (dev->sgd_regs[addr & 0xf0] & ~0x47) | 0x80; + dev->sgd_regs[modem][addr & 0xf0] = (dev->sgd_regs[modem][addr & 0xf0] & ~0x47) | 0x80; /* Start at the specified entry pointer. */ - dev->sgd[addr >> 4].entry_ptr = *((uint32_t *) &dev->sgd_regs[(addr & 0xf0) | 0x4]) & 0xfffffffe; - dev->sgd[addr >> 4].restart = 2; + dev->sgd[modem][addr >> 4].entry_ptr = *((uint32_t *) &dev->sgd_regs[modem][(addr & 0xf0) | 0x4]) & 0xfffffffe; + dev->sgd[modem][addr >> 4].restart = 2; /* Start the actual SGD process. */ - ac97_via_sgd_process(&dev->sgd[addr >> 4]); + ac97_via_sgd_process(&dev->sgd[modem][addr >> 4]); } } /* Stop SGD if requested. */ if (val & 0x40) - dev->sgd_regs[addr & 0xf0] &= ~0x88; + dev->sgd_regs[modem][addr & 0xf0] &= ~0x88; val &= 0x08; /* (Un)pause SGD if requested. */ if (val & 0x08) - dev->sgd_regs[addr & 0xf0] |= 0x40; + dev->sgd_regs[modem][addr & 0xf0] |= 0x40; else - dev->sgd_regs[addr & 0xf0] &= ~0x40; + dev->sgd_regs[modem][addr & 0xf0] &= ~0x40; break; @@ -387,7 +393,7 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) case 0x82: /* Determine the selected codec. */ - i = !!(dev->sgd_regs[0x83] & 0x40); + i = !!(dev->sgd_regs[modem][0x83] & 0x40); codec = dev->codec[modem][i]; /* Keep value in register if this codec is not present. */ @@ -395,20 +401,20 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) /* Read from or write to codec. */ if (val & 0x80) { if (val & 1) { /* return 0x0000 on unaligned reads (real 686B behavior) */ - dev->sgd_regs[0x80] = dev->sgd_regs[0x81] = 0x00; + dev->sgd_regs[modem][0x80] = dev->sgd_regs[modem][0x81] = 0x00; } else { - *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[0x80]) = ac97_codec_readw(codec, val); + *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[modem][0x80]) = ac97_codec_readw(codec, val); } /* Flag data/status/index for this codec as valid. */ - dev->sgd_regs[0x83] |= 0x02 << (i << 1); + dev->sgd_regs[modem][0x83] |= 0x02 << (i << 1); } else if (!(val & 1)) { /* do nothing on unaligned writes */ ac97_codec_writew(codec, val, - *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[0x80])); + *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[modem][0x80])); /* Update primary audio codec state if that codec was written to. */ if (!modem && !i) { - ac97_via_update_codec(dev); + ac97_via_update_codec(dev, 0); /* Set up CD audio filter if CD volume was written to. Setting it up at init prevents CD audio from working on other cards, but @@ -424,9 +430,9 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) case 0x83: /* Clear RWC status bits. */ #if 0 /* race condition with Linux accessing a register and clearing status bits on the same dword write */ - val = (dev->sgd_regs[addr] & ~(val & 0x0a)) | (val & 0xc0); + val = ((dev->sgd_regs[modem][addr] & 0x3f) & ~(val & 0x0a)) | (val & 0xc0); #else - val = dev->sgd_regs[addr] | (val & 0xc0); + val = (dev->sgd_regs[modem][addr] & 0x3f) | (val & 0xc0); #endif break; @@ -435,7 +441,7 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) } } - dev->sgd_regs[addr] = val; + dev->sgd_regs[modem][addr] = val; } void @@ -479,6 +485,8 @@ ac97_via_codec_read(uint16_t addr, void *priv) ac97_via_log("AC97 VIA %d: codec_read(%02X) = %02X\n", modem, addr, ret); + ac97_via_log("[%04X:%08X] [%i] AC97 VIA %d: codec_read(%02X) = %02X\n", CS, cpu_state.pc, msw & 1, modem, addr, ret); + return ret; } @@ -489,6 +497,8 @@ ac97_via_codec_write(uint16_t addr, uint8_t val, void *priv) uint8_t modem = (addr & 0xff00) == dev->modem_codec_base; addr &= 0xff; + ac97_via_log("[%04X:%08X] [%i] AC97 VIA %d: codec_write(%02X, %02X)\n", CS, cpu_state.pc, msw & 1, modem, addr, val); + ac97_via_log("AC97 VIA %d: codec_write(%02X, %02X)\n", modem, addr, val); /* Unknown behavior, maybe it does write to the shadow registers? */ @@ -501,12 +511,12 @@ ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable) ac97_via_t *dev = (ac97_via_t *) priv; if (dev->audio_codec_base) - io_removehandler(dev->audio_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_removehandler(dev->audio_codec_base, 4, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); dev->audio_codec_base = new_io_base; if (dev->audio_codec_base && enable) - io_sethandler(dev->audio_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_sethandler(dev->audio_codec_base, 4, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); } void @@ -515,12 +525,12 @@ ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable) ac97_via_t *dev = (ac97_via_t *) priv; if (dev->modem_codec_base) - io_removehandler(dev->modem_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_removehandler(dev->modem_codec_base, 4, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); dev->modem_codec_base = new_io_base; if (dev->modem_codec_base && enable) - io_sethandler(dev->modem_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_sethandler(dev->modem_codec_base, 4, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); } static void @@ -551,12 +561,12 @@ ac97_via_sgd_process(void *priv) ac97_via_t *dev = sgd->dev; /* Stop if this SGD is not active. */ - uint8_t sgd_status = dev->sgd_regs[sgd->id] & 0xc4; + uint8_t sgd_status = dev->sgd_regs[sgd->modem][sgd->id] & 0xc4; if (!(sgd_status & 0x80)) return; /* Schedule next run. */ - timer_on_auto(&sgd->dma_timer, 10.0); + timer_on_auto(&sgd->dma_timer, 1.0); /* Process SGD if it's active, and the FIFO has room or is disabled. */ if (((sgd_status & 0xc7) == 0x80) && (sgd->always_run || ((sgd->fifo_end - sgd->fifo_pos) <= (sizeof(sgd->fifo) - 4)))) { @@ -564,13 +574,15 @@ ac97_via_sgd_process(void *priv) if (sgd->restart) { /* (Re)load entry pointer if required. */ if (sgd->restart & 2) - sgd->entry_ptr = *((uint32_t *) &dev->sgd_regs[sgd->id | 0x4]) & 0xfffffffe; /* TODO: probe real hardware - does "even addr" actually mean dword aligned? */ + sgd->entry_ptr = *((uint32_t *) &dev->sgd_regs[sgd->modem][sgd->id | 0x4]) & 0xfffffffe; /* TODO: probe real hardware - does "even addr" actually mean dword aligned? */ sgd->restart = 0; /* Read entry. */ - sgd->sample_ptr = mem_readl_phys(sgd->entry_ptr); + // sgd->sample_ptr = mem_readl_phys(sgd->entry_ptr); + dma_bm_read(sgd->entry_ptr, (uint8_t *) &sgd->sample_ptr, 4, 4); sgd->entry_ptr += 4; - sgd->sample_count = mem_readl_phys(sgd->entry_ptr); + // sgd->sample_count = mem_readl_phys(sgd->entry_ptr); + dma_bm_read(sgd->entry_ptr, (uint8_t *) &sgd->sample_count, 4, 4); sgd->entry_ptr += 4; #ifdef ENABLE_AC97_VIA_LOG if (((sgd->sample_ptr == 0xffffffff) && (sgd->sample_count == 0xffffffff)) || ((sgd->sample_ptr == 0x00000000) && (sgd->sample_count == 0x00000000))) @@ -588,10 +600,12 @@ ac97_via_sgd_process(void *priv) if (sgd->id & 0x10) { /* Write channel: read data from FIFO. */ - mem_writel_phys(sgd->sample_ptr, *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)])); + // mem_writel_phys(sgd->sample_ptr, *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)])); + dma_bm_write(sgd->sample_ptr, &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)], 4, 4); } else { /* Read channel: write data to FIFO. */ - *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)]) = mem_readl_phys(sgd->sample_ptr); + // *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)]) = mem_readl_phys(sgd->sample_ptr); + dma_bm_read(sgd->sample_ptr, &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)], 4, 4); } sgd->fifo_end += 4; sgd->sample_ptr += 4; @@ -608,17 +622,17 @@ ac97_via_sgd_process(void *priv) ac97_via_log(" with STOP"); /* Raise STOP to pause SGD. */ - dev->sgd_regs[sgd->id] |= 0x04; + dev->sgd_regs[sgd->modem][sgd->id] |= 0x04; } if (sgd->entry_flags & 0x40) { ac97_via_log(" with FLAG"); /* Raise FLAG to pause SGD. */ - dev->sgd_regs[sgd->id] |= 0x01; + dev->sgd_regs[sgd->modem][sgd->id] |= 0x01; #ifdef ENABLE_AC97_VIA_LOG - if (dev->sgd_regs[sgd->id | 0x2] & 0x01) + if (dev->sgd_regs[sgd->modem][sgd->id | 0x2] & 0x01) ac97_via_log(" interrupt"); #endif } @@ -627,19 +641,19 @@ ac97_via_sgd_process(void *priv) ac97_via_log(" with EOL"); /* Raise EOL. */ - dev->sgd_regs[sgd->id] |= 0x02; + dev->sgd_regs[sgd->modem][sgd->id] |= 0x02; #ifdef ENABLE_AC97_VIA_LOG - if (dev->sgd_regs[sgd->id | 0x2] & 0x02) + if (dev->sgd_regs[sgd->modem][sgd->id | 0x2] & 0x02) ac97_via_log(" interrupt"); #endif /* Restart SGD if a trigger is queued or auto-start is enabled. */ - if ((dev->sgd_regs[sgd->id] & 0x08) || (dev->sgd_regs[sgd->id | 0x2] & 0x80)) { + if ((dev->sgd_regs[sgd->modem][sgd->id] & 0x08) || (dev->sgd_regs[sgd->modem][sgd->id | 0x2] & 0x80)) { ac97_via_log(" restart"); /* Un-queue trigger. */ - dev->sgd_regs[sgd->id] &= ~0x08; + dev->sgd_regs[sgd->modem][sgd->id] &= ~0x08; /* Go back to the starting block on the next run. */ sgd->restart = 2; @@ -647,13 +661,13 @@ ac97_via_sgd_process(void *priv) ac97_via_log(" finish"); /* Terminate SGD. */ - dev->sgd_regs[sgd->id] &= ~0x80; + dev->sgd_regs[sgd->modem][sgd->id] &= ~0x80; } } ac97_via_log("\n"); /* Fire any requested status interrupts. */ - ac97_via_update_irqs(dev); + ac97_via_update_irqs(dev, sgd->modem); } } } @@ -662,7 +676,7 @@ static void ac97_via_poll_stereo(void *priv) { ac97_via_t *dev = (ac97_via_t *) priv; - ac97_via_sgd_t *sgd = &dev->sgd[0]; /* Audio Read */ + ac97_via_sgd_t *sgd = &dev->sgd[0][0]; /* Audio Read */ /* Schedule next run if PCM playback is enabled. */ if (dev->pcm_enabled) @@ -672,7 +686,7 @@ ac97_via_poll_stereo(void *priv) ac97_via_update_stereo(dev, sgd); /* Feed next sample from the FIFO. */ - switch (dev->sgd_regs[sgd->id | 0x2] & 0x30) { + switch (dev->sgd_regs[0][sgd->id | 0x2] & 0x30) { case 0x00: /* Mono, 8-bit PCM */ if ((sgd->fifo_end - sgd->fifo_pos) >= 1) { sgd->out_l = sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; @@ -718,7 +732,7 @@ static void ac97_via_poll_fm(void *priv) { ac97_via_t *dev = (ac97_via_t *) priv; - ac97_via_sgd_t *sgd = &dev->sgd[2]; /* FM Read */ + ac97_via_sgd_t *sgd = &dev->sgd[0][2]; /* FM Read */ /* Schedule next run if FM playback is enabled. */ if (dev->fm_enabled) @@ -746,15 +760,15 @@ ac97_via_get_buffer(int32_t *buffer, int len, void *priv) { ac97_via_t *dev = (ac97_via_t *) priv; - ac97_via_update_stereo(dev, &dev->sgd[0]); - ac97_via_update_stereo(dev, &dev->sgd[2]); + ac97_via_update_stereo(dev, &dev->sgd[0][0]); + ac97_via_update_stereo(dev, &dev->sgd[0][2]); for (int c = 0; c < len * 2; c++) { - buffer[c] += dev->sgd[0].buffer[c] / 2; - buffer[c] += dev->sgd[2].buffer[c] / 2; + buffer[c] += dev->sgd[0][0].buffer[c] / 2; + buffer[c] += dev->sgd[0][2].buffer[c] / 2; } - dev->sgd[0].pos = dev->sgd[2].pos = 0; + dev->sgd[0][0].pos = dev->sgd[0][2].pos = 0; } static void @@ -780,8 +794,8 @@ ac97_via_speed_changed(void *priv) else freq = (double) SOUND_FREQ; - dev->sgd[0].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / freq)); - dev->sgd[2].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 24000.0)); /* FM operates at a fixed 24 KHz */ + dev->sgd[0][0].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / freq)); + dev->sgd[0][2].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 24000.0)); /* FM operates at a fixed 24 KHz */ } static void * @@ -799,19 +813,23 @@ ac97_via_init(UNUSED(const device_t *info)) /* Set up SGD channels. */ for (uint8_t i = 0; i < (sizeof(dev->sgd) / sizeof(dev->sgd[0])); i++) { - dev->sgd[i].id = i << 4; - dev->sgd[i].dev = dev; + for (uint8_t j = 0; j < 2; j++) { + dev->sgd[j][i].id = i << 4; + dev->sgd[j][i].dev = dev; - /* Disable the FIFO on SGDs we don't care about. */ - if ((i != 0) && (i != 2)) - dev->sgd[i].always_run = 1; + dev->sgd[j][i].modem = j; - timer_add(&dev->sgd[i].dma_timer, ac97_via_sgd_process, &dev->sgd[i], 0); + /* Disable the FIFO on SGDs we don't care about. */ + if ((i != 0) && (i != 2)) + dev->sgd[j][i].always_run = 1; + + timer_add(&dev->sgd[j][i].dma_timer, ac97_via_sgd_process, &dev->sgd[j][i], 0); + } } /* Set up playback pollers. */ - timer_add(&dev->sgd[0].poll_timer, ac97_via_poll_stereo, dev, 0); - timer_add(&dev->sgd[2].poll_timer, ac97_via_poll_fm, dev, 0); + timer_add(&dev->sgd[0][0].poll_timer, ac97_via_poll_stereo, dev, 0); + timer_add(&dev->sgd[0][2].poll_timer, ac97_via_poll_fm, dev, 0); ac97_via_speed_changed(dev); /* Set up playback handler. */ From afd910931b75019590f2fd1c87148fd10aa60ea0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 31 Mar 2025 04:36:37 +0200 Subject: [PATCH 0640/1190] Fix an accidental CPU mess-up. --- 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 fa383139b..e421e5637 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1713,7 +1713,7 @@ const machine_t machines[] = { { .name = "[8088] VTech Laser Turbo XT", .internal_name = "ltxt", - .type = MACHINE_TYPE_8088, + .type = MACHINE_TYPE_8088_VTECH, .chipset = MACHINE_CHIPSET_DISCRETE, .init = machine_xt_laserxt_init, .p1_handler = NULL, @@ -1762,7 +1762,7 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_8088_VTECH, + .package = CPU_PKG_8088, .block = CPU_BLOCK_NONE, .min_bus = 0, .max_bus = 0, From a00f4e2e7f006f41aacd0d67b0e35403ddef05f8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 31 Mar 2025 06:12:56 +0200 Subject: [PATCH 0641/1190] The _VTECH suffix is supposed to be on the CPU package, not on the machine type. --- 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 e421e5637..142571d9d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1713,7 +1713,7 @@ const machine_t machines[] = { { .name = "[8088] VTech Laser Turbo XT", .internal_name = "ltxt", - .type = MACHINE_TYPE_8088_VTECH, + .type = MACHINE_TYPE_8088, .chipset = MACHINE_CHIPSET_DISCRETE, .init = machine_xt_laserxt_init, .p1_handler = NULL, @@ -1721,7 +1721,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, From 73dfb3fea9e825618055eb992ade9b6a703da4cb Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 31 Mar 2025 22:48:46 +0600 Subject: [PATCH 0642/1190] Hardware Renderer: Make sure to account for devicePixelRatio when setting up the matrix --- src/qt/qt_hardwarerenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index d5aa86b79..fb84606b0 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -145,7 +145,7 @@ HardwareRenderer::paintGL() QVector texcoords; QMatrix4x4 mat; mat.setToIdentity(); - mat.ortho(QRectF(0, 0, (qreal) width(), (qreal) height())); + mat.ortho(QRectF(0, 0, (qreal) width() * (qreal) devicePixelRatioF(), (qreal) height() * (qreal) devicePixelRatioF())); verts.push_back(QVector2D((float) destination.x(), (float) destination.y())); verts.push_back(QVector2D((float) destination.x(), (float) destination.y() + (float) destination.height())); verts.push_back(QVector2D((float) destination.x() + (float) destination.width(), (float) destination.y() + (float) destination.height())); From 04247b3c25401039ea1d4aa1df150691de921c5b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Apr 2025 06:36:16 +0200 Subject: [PATCH 0643/1190] Both recompilers: Temporarily disable recompilation of exactly four memory versions in 32-bit address move of opcode C6h (8-bit MOV immediate) because they currently break NT 3.x NTVDM, fixes #5038. --- src/codegen/codegen_ops_mov.h | 8 +++++++- src/codegen_new/codegen_ops_mov.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/codegen/codegen_ops_mov.h b/src/codegen/codegen_ops_mov.h index 039489035..6a5054b81 100644 --- a/src/codegen/codegen_ops_mov.h +++ b/src/codegen/codegen_ops_mov.h @@ -152,7 +152,13 @@ ropMOV_b_imm(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t { if ((fetchdat & 0xc0) == 0xc0) { STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); - } else { + } +/* TODO: Fix the recompilation of that specific case so it no longer breaks NT 3.x NTVDM. */ +#ifndef RECOMPILE_MOVB_IMM_MEM_ALWAYS + else if (((fetchdat & 0xfc) == 0x80) && (op_32 & 0x200)) + return 0; +#endif + else { x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); uint32_t imm = fastreadb(cs + op_pc + 1); int host_reg = LOAD_REG_IMM(imm); diff --git a/src/codegen_new/codegen_ops_mov.c b/src/codegen_new/codegen_ops_mov.c index 031d2ea05..f79a959a7 100644 --- a/src/codegen_new/codegen_ops_mov.c +++ b/src/codegen_new/codegen_ops_mov.c @@ -296,7 +296,13 @@ ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t imm = fastreadb(cs + op_pc + 1); uop_MOV_IMM(ir, IREG_8(dest_reg), imm); - } else { + } +/* TODO: Fix the recompilation of that specific case so it no longer breaks NT 3.x NTVDM. */ +#ifndef RECOMPILE_MOVB_IMM_MEM_ALWAYS + else if (((fetchdat & 0xfc) == 0x80) && (op_32 & 0x200)) + return 0; +#endif + else { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); From 4c0f0ddd24c0e0ef0df2d035d9fcc337f7164082 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Apr 2025 06:42:14 +0200 Subject: [PATCH 0644/1190] VIA AC'97: Restore the 0x47 back (turns out it was *NOT* a mix-up), but divide by 208925 instead of by 32767, in order to keep the maximum in the -32768 to 32767 range even at +12 dB gain. --- src/sound/snd_ac97_codec.c | 2 +- src/sound/snd_ac97_via.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index 7a9951289..ad535591f 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -537,7 +537,7 @@ ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r) uint8_t r_val = val; if (reg <= 0x06) { /* 6-bit level */ *l = codec_attn[0x3f - (l_val & 0x3f)]; - *r = codec_attn[0x3f - (r_val & 0x3f)]; + *r = codec_attn[0x47 - (r_val & 0x3f)]; } else { /* 5-bit gain */ /* Yes, 0x3f is correct, the 0x47 was most likely a decimal-hex mix-up. */ *l = codec_attn[0x3f - (l_val & 0x1f)]; diff --git a/src/sound/snd_ac97_via.c b/src/sound/snd_ac97_via.c index 68ef5fe5d..2d994b08f 100644 --- a/src/sound/snd_ac97_via.c +++ b/src/sound/snd_ac97_via.c @@ -536,8 +536,13 @@ ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable) static void ac97_via_update_stereo(ac97_via_t *dev, ac97_via_sgd_t *sgd) { +#ifdef OLD_CODE int32_t l = (((sgd->out_l * sgd->vol_l) >> 15) * dev->master_vol_l) >> 15; int32_t r = (((sgd->out_r * sgd->vol_r) >> 15) * dev->master_vol_r) >> 15; +#else + int32_t l = (((sgd->out_l * sgd->vol_l) / 208925) * dev->master_vol_l) >> 15; + int32_t r = (((sgd->out_r * sgd->vol_r) / 208925) * dev->master_vol_r) >> 15; +#endif if (l < -32768) l = -32768; From 5ea48b20277374e23a1cf3208cfdd2153f7fc25a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Apr 2025 06:42:51 +0200 Subject: [PATCH 0645/1190] Correct the fix. --- src/sound/snd_ac97_codec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index ad535591f..e92830f67 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -537,11 +537,10 @@ ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r) uint8_t r_val = val; if (reg <= 0x06) { /* 6-bit level */ *l = codec_attn[0x3f - (l_val & 0x3f)]; - *r = codec_attn[0x47 - (r_val & 0x3f)]; + *r = codec_attn[0x3f - (r_val & 0x3f)]; } else { /* 5-bit gain */ - /* Yes, 0x3f is correct, the 0x47 was most likely a decimal-hex mix-up. */ - *l = codec_attn[0x3f - (l_val & 0x1f)]; - *r = codec_attn[0x3f - (r_val & 0x1f)]; + *l = codec_attn[0x47 - (l_val & 0x1f)]; + *r = codec_attn[0x47 - (r_val & 0x1f)]; } /* Apply per-channel mute and center/LFE powerdowns where applicable. */ From 1783da99a4b2becec060134c0ffcec57cdcccd6f Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Apr 2025 08:48:01 +0200 Subject: [PATCH 0646/1190] 86F internal handler: make the common handlers function initialize the floppy density hole return function, fixes 3-mode (dual-RPM) 3.5" drives. --- src/floppy/fdd_86f.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index f5626e35b..0a7120b16 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -3452,6 +3452,7 @@ d86f_common_handlers(int drive) drives[drive].poll = d86f_poll; drives[drive].format = d86f_proxy_format; drives[drive].stop = d86f_stop; + drives[drive].hole = d86f_hole; } int From 3e7f8a18de884e4ffe7ed9962b34442a4960017a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Apr 2025 09:18:12 +0200 Subject: [PATCH 0647/1190] FDC: Initialize DRVRATE to 1 on the OKI IF386AX so that 1.25 MB floppies can be read on a 3.5" 3-mode drive. --- src/floppy/fdc.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 51c3aa24a..6ffa47f29 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2268,10 +2268,21 @@ fdc_reset(void *priv) fdc_update_rwc(fdc, 1, default_rwc); fdc_update_rwc(fdc, 2, default_rwc); fdc_update_rwc(fdc, 3, default_rwc); - fdc_update_drvrate(fdc, 0, 0); - fdc_update_drvrate(fdc, 1, 0); - fdc_update_drvrate(fdc, 2, 0); - fdc_update_drvrate(fdc, 3, 0); + /* + The OKI IF386SX natively supports the Japanese 1.25 MB floppy format, + since it can read such images just fine, it also attempts to use data + rate 01 on a 3.5" MB drive (which is the only kind it can physically + take, anyway), and rate 01 on a 3.5" MB drive is usually used by 3-mode + drives to switch to 360 RPM. Hence why I'm switching DRVDEN to 1, so + rate 01 becomes 500 kbps, so on a 3-mode 3.5" drive, 1.25 MB floppies + can be read. The side effect is that to read 5.25" 360k drives, you + need to use a dual-RPM 5.25" drive - but hey, that finally gets those + drives some usage as well. + */ + fdc_update_drvrate(fdc, 0, !strcmp(machine_get_internal_name(), "if386sx")); + fdc_update_drvrate(fdc, 1, !strcmp(machine_get_internal_name(), "if386sx")); + fdc_update_drvrate(fdc, 2, !strcmp(machine_get_internal_name(), "if386sx")); + fdc_update_drvrate(fdc, 3, !strcmp(machine_get_internal_name(), "if386sx")); fdc_update_drv2en(fdc, 1); fdc_update_rates(fdc); From fd618440618e3d6e426d60e59921fd8495531b09 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 1 Apr 2025 15:44:37 +0600 Subject: [PATCH 0648/1190] Switch to SAASound for CMS --- src/include/86box/snd_cms.h | 23 +- src/sound/CMakeLists.txt | 3 + src/sound/saasound/CMakeLists.txt | 16 + src/sound/saasound/SAAAmp.cpp | 203 +++++++++ src/sound/saasound/SAAAmp.h | 44 ++ src/sound/saasound/SAAConfig.h | 41 ++ src/sound/saasound/SAADevice.cpp | 392 +++++++++++++++++ src/sound/saasound/SAADevice.h | 69 +++ src/sound/saasound/SAAEnv.cpp | 380 ++++++++++++++++ src/sound/saasound/SAAEnv.h | 54 +++ src/sound/saasound/SAAFreq.cpp | 280 ++++++++++++ src/sound/saasound/SAAFreq.dat | 141 ++++++ src/sound/saasound/SAAFreq.h | 72 +++ src/sound/saasound/SAAImpl.cpp | 487 +++++++++++++++++++++ src/sound/saasound/SAAImpl.h | 75 ++++ src/sound/saasound/SAANoise.cpp | 180 ++++++++ src/sound/saasound/SAANoise.h | 54 +++ src/sound/saasound/SAASndC.cpp | 100 +++++ src/sound/saasound/SAASndC.h | 102 +++++ src/sound/saasound/SAASound.cpp | 13 + src/sound/saasound/SAASound.h | 130 ++++++ src/sound/saasound/defns.h | 59 +++ src/sound/saasound/resource.h | 15 + src/sound/saasound/saasound_cmake_config.h | 14 + src/sound/saasound/types.h | 34 ++ src/sound/snd_cms.c | 138 ++---- 26 files changed, 3006 insertions(+), 113 deletions(-) create mode 100644 src/sound/saasound/CMakeLists.txt create mode 100755 src/sound/saasound/SAAAmp.cpp create mode 100755 src/sound/saasound/SAAAmp.h create mode 100644 src/sound/saasound/SAAConfig.h create mode 100644 src/sound/saasound/SAADevice.cpp create mode 100644 src/sound/saasound/SAADevice.h create mode 100755 src/sound/saasound/SAAEnv.cpp create mode 100755 src/sound/saasound/SAAEnv.h create mode 100755 src/sound/saasound/SAAFreq.cpp create mode 100755 src/sound/saasound/SAAFreq.dat create mode 100755 src/sound/saasound/SAAFreq.h create mode 100644 src/sound/saasound/SAAImpl.cpp create mode 100755 src/sound/saasound/SAAImpl.h create mode 100755 src/sound/saasound/SAANoise.cpp create mode 100755 src/sound/saasound/SAANoise.h create mode 100755 src/sound/saasound/SAASndC.cpp create mode 100644 src/sound/saasound/SAASndC.h create mode 100755 src/sound/saasound/SAASound.cpp create mode 100644 src/sound/saasound/SAASound.h create mode 100644 src/sound/saasound/defns.h create mode 100755 src/sound/saasound/resource.h create mode 100644 src/sound/saasound/saasound_cmake_config.h create mode 100755 src/sound/saasound/types.h diff --git a/src/include/86box/snd_cms.h b/src/include/86box/snd_cms.h index 8eec22935..8201fe32c 100644 --- a/src/include/86box/snd_cms.h +++ b/src/include/86box/snd_cms.h @@ -7,23 +7,20 @@ #define MASTER_CLOCK 7159090 typedef struct cms_t { - int addrs[2]; - uint8_t regs[2][32]; - uint16_t latch[2][6]; - int freq[2][6]; - float count[2][6]; - int vol[2][6][2]; - int stat[2][6]; - uint16_t noise[2][2]; - uint16_t noisefreq[2][2]; - int noisecount[2][2]; - int noisetype[2][2]; +#ifdef SAASOUND_H_INCLUDED + SAASND saasound; + SAASND saasound2; +#else + void* saasound; + void* saasound2; +#endif uint8_t latched_data; - int16_t buffer[SOUNDBUFLEN * 2]; + int16_t buffer[WTBUFLEN * 2]; + int16_t buffer2[WTBUFLEN * 2]; - int pos; + int pos, pos2; } cms_t; extern void cms_update(cms_t *cms); diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 0a04b0ff1..d575717a0 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -180,6 +180,9 @@ endif() add_subdirectory(ymfm) target_link_libraries(86Box ymfm) +add_subdirectory(saasound) +target_link_libraries(86Box saasound) + if(GUSMAX) target_compile_definitions(snd PRIVATE USE_GUSMAX) endif() diff --git a/src/sound/saasound/CMakeLists.txt b/src/sound/saasound/CMakeLists.txt new file mode 100644 index 000000000..2db75493e --- /dev/null +++ b/src/sound/saasound/CMakeLists.txt @@ -0,0 +1,16 @@ +add_library(saasound OBJECT + SAAAmp.cpp + SAAAmp.h + SAADevice.cpp + SAADevice.h + SAAEnv.cpp + SAAEnv.h + SAAFreq.cpp + SAAFreq.h + SAAImpl.cpp + SAAImpl.h + SAANoise.cpp + SAANoise.h + SAASndC.cpp + SAASndC.h + SAASound.cpp) \ No newline at end of file diff --git a/src/sound/saasound/SAAAmp.cpp b/src/sound/saasound/SAAAmp.cpp new file mode 100755 index 000000000..8f2473fb1 --- /dev/null +++ b/src/sound/saasound/SAAAmp.cpp @@ -0,0 +1,203 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAAmp.cpp: implementation of the CSAAAmp class. +// This class handles Tone/Noise mixing, Envelope application and +// amplification. +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" +#include "types.h" +#include "SAANoise.h" +#include "SAAEnv.h" +#include "SAAFreq.h" +#include "SAAAmp.h" +#include "defns.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSAAAmp::CSAAAmp(CSAAFreq * const ToneGenerator, const CSAANoise * const NoiseGenerator, const CSAAEnv * const EnvGenerator) +: +m_pcConnectedToneGenerator(ToneGenerator), +m_pcConnectedNoiseGenerator(NoiseGenerator), +m_pcConnectedEnvGenerator(EnvGenerator), +m_bUseEnvelope(EnvGenerator != NULL) +{ + leftlevel = 0; + leftlevela0x0e = 0; + rightlevel = 0; + rightlevela0x0e = 0; + m_nMixMode = 0; + m_bMute=true; + m_bSync = false; + m_nOutputIntermediate=0; + last_level_byte=0; + SetAmpLevel(0x00); + +} + +CSAAAmp::~CSAAAmp() +{ + // Nothing to do +} + +void CSAAAmp::SetAmpLevel(BYTE level_byte) +{ + // if level unchanged since last call then do nothing + if (level_byte != last_level_byte) + { + last_level_byte = level_byte; + leftlevel = level_byte & 0x0f; + leftlevela0x0e = leftlevel & 0x0e; + + rightlevel = (level_byte >> 4) & 0x0f; + rightlevela0x0e = rightlevel & 0x0e; + } + +} + +void CSAAAmp::SetToneMixer(BYTE bEnabled) +{ + if (bEnabled == 0) + { + // clear mixer bit + m_nMixMode &= ~(0x01); + } + else + { + // set mixer bit + m_nMixMode |= 0x01; + } +} + +void CSAAAmp::SetNoiseMixer(BYTE bEnabled) +{ + if (bEnabled == 0) + { + m_nMixMode &= ~(0x02); + } + else + { + m_nMixMode |= 0x02; + } +} + +void CSAAAmp::Mute(bool bMute) +{ + // m_bMute refers to the GLOBAL mute setting (register 28 bit 0) + // NOT the per-channel mixer settings !! + m_bMute = bMute; +} + +void CSAAAmp::Sync(bool bSync) +{ + // m_bSync refers to the GLOBAL sync setting (register 28 bit 1) + m_bSync = bSync; +} + +void CSAAAmp::Tick(void) +{ + // updates m_nOutputIntermediate to 0, 1 or 2 + // + + // connected oscillator always ticks (this isn't really connected to the amp) + int level = m_pcConnectedToneGenerator->Tick(); + + switch (m_nMixMode) + { + case 0: + // no tone or noise for this channel + m_nOutputIntermediate = 0; + break; + case 1: + // tone only for this channel + m_nOutputIntermediate = level * 2; + // NOTE: ConnectedToneGenerator returns either 0 or 1 + break; + case 2: + // noise only for this channel + m_nOutputIntermediate = m_pcConnectedNoiseGenerator->Level() * 2; + // NOTE: ConnectedNoiseGenerator()->Level() returns either 0 or 1 + break; + case 3: + // tone+noise for this channel ... mixing algorithm : + // tone noise output + // 0 0 0 + // 1 0 2 + // 0 1 0 + // 1 1 1 + // = 2 * tone - 1 * (tone & noise) + // = tone * (2 - noise) + m_nOutputIntermediate = level * (2 - m_pcConnectedNoiseGenerator->Level()); + break; + } + // intermediate is between 0 and 2 +} + +inline int CSAAAmp::EffectiveAmplitude(int amp, int env) const +{ + // Return the effective amplitude of the low-pass-filtered result of the logical + // AND of the amplitude PDM and envelope PDM patterns. This is a more accurate + // evaluation of the SAA than simply returning amp * env , based on how the SAA + // implements pulse-density modulation. + static const int pdm[16][16] = { + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,2,2,2,2,2,2,2,2,4,4,4,4}, + {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8}, + {0,1,1,2,4,5,5,6,6,7,7,8,10,11,11,12}, + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, + {0,1,2,3,6,7,8,9,10,11,12,13,16,17,18,19}, + {0,2,3,5,6,8,9,11,12,14,15,17,18,20,21,23}, + {0,2,3,5,8,10,11,13,14,16,17,19,22,24,25,27}, + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30}, + {0,2,4,6,10,12,14,16,18,20,22,24,28,30,32,34}, + {0,3,5,8,10,13,15,18,20,23,25,28,30,33,35,38}, + {0,3,5,8,12,15,17,20,22,25,27,30,34,37,39,42}, + {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}, + {0,3,6,9,14,17,20,23,26,29,32,35,40,43,46,49}, + {0,4,7,11,14,18,21,25,28,32,35,39,42,46,49,53}, + {0,4,7,11,16,20,23,27,30,34,37,41,46,50,53,57} + }; + + return(pdm[amp][env] * 4); +} + +void CSAAAmp::TickAndOutputStereo(unsigned int & left, unsigned int & right) +{ + // This returns a value between 0 and 480 inclusive. + // This represents the full dynamic range of one output mixer (tone, or noise+tone, at full volume, + // without envelopes enabled). Note that, with envelopes enabled, the actual dynamic range + // is reduced on-chip to just over 88% of this (424), so the "loudest" output requires disabling envs. + // NB for 6 channels at full volume, with simple additive mixing, you would see a combined + // output of 2880, and a multiplier of 11 (=31680) fits comfortably within 16-bit signed output range. + + if (m_bSync) + { + // TODO check this + left = right = 0; + return; + } + + // first, do the Tick: + Tick(); + + // now calculate the returned amplitude for this sample: + //////////////////////////////////////////////////////// + + if (m_bMute) + { + left = right = 0; + } + else if (m_bUseEnvelope && m_pcConnectedEnvGenerator->IsActive()) + { + left = EffectiveAmplitude(m_pcConnectedEnvGenerator->LeftLevel(), leftlevela0x0e) * (2 - m_nOutputIntermediate); + right = EffectiveAmplitude(m_pcConnectedEnvGenerator->RightLevel(), rightlevela0x0e) * (2 - m_nOutputIntermediate); + } + else + { + left = leftlevel * m_nOutputIntermediate * 16; + right = rightlevel * m_nOutputIntermediate * 16; + } +} diff --git a/src/sound/saasound/SAAAmp.h b/src/sound/saasound/SAAAmp.h new file mode 100755 index 000000000..4a6761f21 --- /dev/null +++ b/src/sound/saasound/SAAAmp.h @@ -0,0 +1,44 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAAmp.h: interface for the CSAAAmp class. +// This class handles Tone/Noise mixing, Envelope application and +// amplification. +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAAAMP_H_INCLUDED +#define SAAAMP_H_INCLUDED + +class CSAAAmp +{ +private: + int leftlevel; + int leftlevela0x0e; + int rightlevel; + int rightlevela0x0e; + int m_nOutputIntermediate; + unsigned int m_nMixMode; + CSAAFreq * const m_pcConnectedToneGenerator; // not const because amp calls ->Tick() + const CSAANoise * const m_pcConnectedNoiseGenerator; + const CSAAEnv * const m_pcConnectedEnvGenerator; + const bool m_bUseEnvelope; + mutable bool m_bMute; + mutable bool m_bSync; + mutable BYTE last_level_byte; + int EffectiveAmplitude(int amp, int env) const; + +public: + CSAAAmp(CSAAFreq * const ToneGenerator, const CSAANoise * const NoiseGenerator, const CSAAEnv * const EnvGenerator); + ~CSAAAmp(); + + void SetAmpLevel(BYTE level_byte); // really just a BYTE + void SetToneMixer(BYTE bEnabled); + void SetNoiseMixer(BYTE bEnabled); + void Mute(bool bMute); + void Sync(bool bSync); + void Tick(void); + void TickAndOutputStereo(unsigned int & left, unsigned int & right); + +}; + +#endif // SAAAMP_H_INCLUDED diff --git a/src/sound/saasound/SAAConfig.h b/src/sound/saasound/SAAConfig.h new file mode 100644 index 000000000..a655ec59f --- /dev/null +++ b/src/sound/saasound/SAAConfig.h @@ -0,0 +1,41 @@ +// Part of SAASound copyright 2020 Dave Hooper +// +// SAAConfig.h: configuration file handler class +// +////////////////////////////////////////////////////////////////////// + +#include "defns.h" +#ifdef USE_CONFIG_FILE + +#ifndef SAA_CONFIG_H_INCLUDED +#define SAA_CONFIG_H_INCLUDED + +#define INI_READONLY +#define INI_ANSIONLY /*nb not really 'ANSI', this just forces all read/write to use 8-bit char*/ +#include "minIni/minIni.h" + +class SAAConfig +{ +private: + minIni m_minIni; + bool m_bHasReadConfig; + +public: + bool m_bGenerateRegisterLogs; + bool m_bGeneratePcmLogs; + bool m_bGeneratePcmSeparateChannels; + t_string m_strRegisterLogPath; + t_string m_strPcmOutputPath; + unsigned int m_nOversample; + bool m_bHighpass; + double m_nBoost; + + SAAConfig(); + void ReadConfig(); + + t_string getChannelPcmOutputPath(int); +}; + +#endif // SAA_CONFIG_H_INCLUDED + +#endif // USE_CONFIG_FILE \ No newline at end of file diff --git a/src/sound/saasound/SAADevice.cpp b/src/sound/saasound/SAADevice.cpp new file mode 100644 index 000000000..306aa477a --- /dev/null +++ b/src/sound/saasound/SAADevice.cpp @@ -0,0 +1,392 @@ +// Part of SAASound copyright 2020 Dave Hooper +// +// SAADevice.cpp: connecting the subcomponents of the SAA1099 together. +// This class handles device inputs and outputs (clocking, data and +// address bus, and simulated output) +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" +#include "types.h" +#include "SAAEnv.h" +#include "SAANoise.h" +#include "SAAFreq.h" +#include "SAAAmp.h" +#include "SAASound.h" +#include "SAAImpl.h" +#include "defns.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSAADevice::CSAADevice() + : + m_nCurrentSaaReg(0), + m_bOutputEnabled(false), + m_bSync(false), + m_bHighpass(true), + m_nOversample(0), + m_Noise0(0xffffffff), + m_Noise1(0xffffffff), + m_Env0(), + m_Env1(), + m_Osc0(&m_Noise0, NULL), + m_Osc1(NULL, &m_Env0), + m_Osc2(NULL, NULL), + m_Osc3(&m_Noise1, NULL), + m_Osc4(NULL, &m_Env1), + m_Osc5(NULL, NULL), + m_Amp0(&m_Osc0, &m_Noise0, NULL), + m_Amp1(&m_Osc1, &m_Noise0, NULL), + m_Amp2(&m_Osc2, &m_Noise0, &m_Env0), + m_Amp3(&m_Osc3, &m_Noise1, NULL), + m_Amp4(&m_Osc4, &m_Noise1, NULL), + m_Amp5(&m_Osc5, &m_Noise1, &m_Env1) +{ + // Create and link up the objects that make up the emulator + Noise[0] = &m_Noise0; + Noise[1] = &m_Noise1; + Env[0] = &m_Env0; + Env[1] = &m_Env1; + + // Create oscillators (tone generators) and link to noise generators and + // envelope controllers + Osc[0] = &m_Osc0; + Osc[1] = &m_Osc1; + Osc[2] = &m_Osc2; + Osc[3] = &m_Osc3; + Osc[4] = &m_Osc4; + Osc[5] = &m_Osc5; + + // Create amplification/mixing stages and link to appropriate oscillators, + // noise generators and envelope controllers + Amp[0] = &m_Amp0; + Amp[1] = &m_Amp1; + Amp[2] = &m_Amp2; + Amp[3] = &m_Amp3; + Amp[4] = &m_Amp4; + Amp[5] = &m_Amp5; + + _SetClockRate(EXTERNAL_CLK_HZ); + _SetOversample(DEFAULT_OVERSAMPLE); +} + +CSAADevice::~CSAADevice() +{ +} + +////////////////////////////////////////////////////////////////////// +// CSAASound members +////////////////////////////////////////////////////////////////////// + +void CSAADevice::_SetClockRate(unsigned int nClockRate) +{ + m_Osc0._SetClockRate(nClockRate); + m_Osc1._SetClockRate(nClockRate); + m_Osc2._SetClockRate(nClockRate); + m_Osc3._SetClockRate(nClockRate); + m_Osc4._SetClockRate(nClockRate); + m_Osc5._SetClockRate(nClockRate); + m_Noise0._SetClockRate(nClockRate); + m_Noise1._SetClockRate(nClockRate); +} + +void CSAADevice::_SetSampleRate(unsigned int nSampleRate) +{ + m_Osc0._SetSampleRate(nSampleRate); + m_Osc1._SetSampleRate(nSampleRate); + m_Osc2._SetSampleRate(nSampleRate); + m_Osc3._SetSampleRate(nSampleRate); + m_Osc4._SetSampleRate(nSampleRate); + m_Osc5._SetSampleRate(nSampleRate); + m_Noise0._SetSampleRate(nSampleRate); + m_Noise1._SetSampleRate(nSampleRate); +} + +void CSAADevice::_SetOversample(unsigned int nOversample) +{ + if (nOversample != m_nOversample) + { + m_nOversample = nOversample; + m_Osc0._SetOversample(nOversample); + m_Osc1._SetOversample(nOversample); + m_Osc2._SetOversample(nOversample); + m_Osc3._SetOversample(nOversample); + m_Osc4._SetOversample(nOversample); + m_Osc5._SetOversample(nOversample); + m_Noise0._SetOversample(nOversample); + m_Noise1._SetOversample(nOversample); + } +} + +void CSAADevice::_WriteData(BYTE nData) +{ +#if defined(DEBUG) || defined(DEBUGSAA) + m_Reg[m_nCurrentSaaReg] = nData; +#endif + + // route nData to the appropriate place + switch (m_nCurrentSaaReg) + { + // Amplitude data (==> Amp) + case 0: + m_Amp0.SetAmpLevel(nData); + break; + case 1: + m_Amp1.SetAmpLevel(nData); + break; + case 2: + m_Amp2.SetAmpLevel(nData); + break; + case 3: + m_Amp3.SetAmpLevel(nData); + break; + case 4: + m_Amp4.SetAmpLevel(nData); + break; + case 5: + m_Amp5.SetAmpLevel(nData); + break; + + // Freq data (==> Osc) + case 8: + m_Osc0.SetFreqOffset(nData); + break; + case 9: + m_Osc1.SetFreqOffset(nData); + break; + case 10: + m_Osc2.SetFreqOffset(nData); + break; + case 11: + m_Osc3.SetFreqOffset(nData); + break; + case 12: + m_Osc4.SetFreqOffset(nData); + break; + case 13: + m_Osc5.SetFreqOffset(nData); + break; + + // Freq octave data (==> Osc) for channels 0,1 + case 16: + m_Osc0.SetFreqOctave(nData & 0x07); + m_Osc1.SetFreqOctave((nData >> 4) & 0x07); + break; + + // Freq octave data (==> Osc) for channels 2,3 + case 17: + m_Osc2.SetFreqOctave(nData & 0x07); + m_Osc3.SetFreqOctave((nData >> 4) & 0x07); + break; + + // Freq octave data (==> Osc) for channels 4,5 + case 18: + m_Osc4.SetFreqOctave(nData & 0x07); + m_Osc5.SetFreqOctave((nData >> 4) & 0x07); + break; + + // Tone mixer control (==> Amp) + case 20: + m_Amp0.SetToneMixer(nData & 0x01); + m_Amp1.SetToneMixer(nData & 0x02); + m_Amp2.SetToneMixer(nData & 0x04); + m_Amp3.SetToneMixer(nData & 0x08); + m_Amp4.SetToneMixer(nData & 0x10); + m_Amp5.SetToneMixer(nData & 0x20); + break; + + // Noise mixer control (==> Amp) + case 21: + m_Amp0.SetNoiseMixer(nData & 0x01); + m_Amp1.SetNoiseMixer(nData & 0x02); + m_Amp2.SetNoiseMixer(nData & 0x04); + m_Amp3.SetNoiseMixer(nData & 0x08); + m_Amp4.SetNoiseMixer(nData & 0x10); + m_Amp5.SetNoiseMixer(nData & 0x20); + break; + + // Noise frequency/source control (==> Noise) + case 22: + m_Noise0.SetSource(nData & 0x03); + m_Noise1.SetSource((nData >> 4) & 0x03); + break; + + // Envelope control data (==> Env) for envelope controller #0 + case 24: + m_Env0.SetEnvControl(nData); + break; + + // Envelope control data (==> Env) for envelope controller #1 + case 25: + m_Env1.SetEnvControl(nData); + break; + + // Global enable and reset (sync) controls + case 28: + { + // Reset (sync) bit + bool bSync = bool(nData & 0x02); + if (bSync != m_bSync) + { + // Sync all devices + // This amounts to telling them all to reset to a + // known state, which is also a state that doesn't change + // (i.e. no audio output, although there are some exceptions) + // bSync=true => all devices are sync (aka reset); + // bSync=false => all devices are allowed to run and generate changing output + m_Osc0.Sync(bSync); + m_Osc1.Sync(bSync); + m_Osc2.Sync(bSync); + m_Osc3.Sync(bSync); + m_Osc4.Sync(bSync); + m_Osc5.Sync(bSync); + m_Noise0.Sync(bSync); + m_Noise1.Sync(bSync); + m_Amp0.Sync(bSync); + m_Amp1.Sync(bSync); + m_Amp2.Sync(bSync); + m_Amp3.Sync(bSync); + m_Amp4.Sync(bSync); + m_Amp5.Sync(bSync); + m_bSync = bSync; + } + + // Global mute bit + bool bOutputEnabled = bool(nData & 0x01); + if (bOutputEnabled != m_bOutputEnabled) + { + // unmute all amps - sound 'enabled' + m_Amp0.Mute(!bOutputEnabled); + m_Amp1.Mute(!bOutputEnabled); + m_Amp2.Mute(!bOutputEnabled); + m_Amp3.Mute(!bOutputEnabled); + m_Amp4.Mute(!bOutputEnabled); + m_Amp5.Mute(!bOutputEnabled); + m_bOutputEnabled = bOutputEnabled; + } + } + break; + + default: + // anything else means data is being written to a register + // that is not used within the SAA-1099 architecture + // hence, we ignore it. + {} + } +} + +void CSAADevice::_WriteAddress(BYTE nReg) +{ + m_nCurrentSaaReg = nReg & 31; + if (m_nCurrentSaaReg == 24) + { + m_Env0.ExternalClock(); + } + else if (m_nCurrentSaaReg == 25) + { + m_Env1.ExternalClock(); + } +} + +#if 1 +BYTE CSAADevice::_ReadAddress(void) +{ + // Not a real hardware function of the SAA-1099, which is write-only + // However, this is used by SAAImpl to generate debug logs (if enabled) + return(m_nCurrentSaaReg); +} +#endif +#if defined(DEBUG) +BYTE CSAADevice::_ReadData(void) +{ + // Not a real hardware function of the SAA-1099, which is write-only + // This is only compiled for Debug builds + return(m_Reg[m_nCurrentSaaReg]); +} +#endif + +void CSAADevice::_TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed) +{ + unsigned int temp_left, temp_right; + unsigned int accum_left = 0, accum_right = 0; + for (int i = 1 << m_nOversample; i > 0; i--) + { + m_Noise0.Tick(); + m_Noise1.Tick(); + m_Amp0.TickAndOutputStereo(temp_left, temp_right); + accum_left += temp_left; + accum_right += temp_right; + m_Amp1.TickAndOutputStereo(temp_left, temp_right); + accum_left += temp_left; + accum_right += temp_right; + m_Amp2.TickAndOutputStereo(temp_left, temp_right); + accum_left += temp_left; + accum_right += temp_right; + m_Amp3.TickAndOutputStereo(temp_left, temp_right); + accum_left += temp_left; + accum_right += temp_right; + m_Amp4.TickAndOutputStereo(temp_left, temp_right); + accum_left += temp_left; + accum_right += temp_right; + m_Amp5.TickAndOutputStereo(temp_left, temp_right); + accum_left += temp_left; + accum_right += temp_right; + } + left_mixed = accum_left; + right_mixed = accum_right; +} + +void CSAADevice::_TickAndOutputSeparate(unsigned int& left_mixed, unsigned int& right_mixed, + unsigned int& left0, unsigned int& right0, + unsigned int& left1, unsigned int& right1, + unsigned int& left2, unsigned int& right2, + unsigned int& left3, unsigned int& right3, + unsigned int& left4, unsigned int& right4, + unsigned int& left5, unsigned int& right5 +) +{ + unsigned int temp_left, temp_right; + unsigned int accum_left = 0, accum_right = 0; + left0 = left1 = left2 = left3 = left4 = left5 = 0; + right0 = right1 = right2 = right3 = right4 = right5 = 0; + for (int i = 1 << m_nOversample; i > 0; i--) + { + m_Noise0.Tick(); + m_Noise1.Tick(); + m_Amp0.TickAndOutputStereo(temp_left, temp_right); + left0 += temp_left; + right0 += temp_right; + accum_left += temp_left; + accum_right += temp_right; + m_Amp1.TickAndOutputStereo(temp_left, temp_right); + left1 += temp_left; + right1 += temp_right; + accum_left += temp_left; + accum_right += temp_right; + m_Amp2.TickAndOutputStereo(temp_left, temp_right); + left2 += temp_left; + right2 += temp_right; + accum_left += temp_left; + accum_right += temp_right; + m_Amp3.TickAndOutputStereo(temp_left, temp_right); + left3 += temp_left; + right3 += temp_right; + accum_left += temp_left; + accum_right += temp_right; + m_Amp4.TickAndOutputStereo(temp_left, temp_right); + left4 += temp_left; + right4 += temp_right; + accum_left += temp_left; + accum_right += temp_right; + m_Amp5.TickAndOutputStereo(temp_left, temp_right); + left5 += temp_left; + right5 += temp_right; + accum_left += temp_left; + accum_right += temp_right; + } + left_mixed = accum_left; + right_mixed = accum_right; +} \ No newline at end of file diff --git a/src/sound/saasound/SAADevice.h b/src/sound/saasound/SAADevice.h new file mode 100644 index 000000000..7b697821f --- /dev/null +++ b/src/sound/saasound/SAADevice.h @@ -0,0 +1,69 @@ +// Part of SAASound copyright 2020 Dave Hooper +// +// SAADevice.h: connecting the subcomponents of the SAA1099 together. +// This class handles device inputs and outputs (clocking, data and +// address bus, and simulated output) +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAADEVICE_H_INCLUDED +#define SAADEVICE_H_INCLUDED + +#include "SAASound.h" +#include "SAANoise.h" +#include "SAAEnv.h" +#include "SAAFreq.h" +#include "SAAAmp.h" + +class CSAADevice +{ +private: + int m_nCurrentSaaReg; + bool m_bOutputEnabled; + bool m_bSync; + bool m_bHighpass; + int m_nOversample; + + CSAANoise m_Noise0, m_Noise1; + CSAAEnv m_Env0, m_Env1; + CSAAFreq m_Osc0, m_Osc1, m_Osc2, m_Osc3, m_Osc4, m_Osc5; + CSAAAmp m_Amp0, m_Amp1, m_Amp2, m_Amp3, m_Amp4, m_Amp5; + + CSAANoise* Noise[2]; + CSAAEnv* Env[2]; + CSAAFreq* Osc[6]; + CSAAAmp* Amp[6]; + +#if defined(DEBUG) || defined(DEBUGSAA) + BYTE m_Reg[32]; +#endif + +public: + CSAADevice(); + ~CSAADevice(); + + void _WriteAddress(BYTE nReg); + void _WriteData(BYTE nData); +#if 1 + BYTE _ReadAddress(void); +#endif +#if defined(DEBUG) + BYTE _ReadData(void); +#endif + + void _SetClockRate(unsigned int nClockRate); + void _SetSampleRate(unsigned int nSampleRate); + void _SetOversample(unsigned int nOversample); + void _TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed); + void _TickAndOutputSeparate(unsigned int& left_mixed, unsigned int& right_mixed, + unsigned int& left0, unsigned int& right0, + unsigned int& left1, unsigned int& right1, + unsigned int& left2, unsigned int& right2, + unsigned int& left3, unsigned int& right3, + unsigned int& left4, unsigned int& right4, + unsigned int& left5, unsigned int& right5 + ); + +}; + +#endif // SAADEVICE_H_INCLUDED \ No newline at end of file diff --git a/src/sound/saasound/SAAEnv.cpp b/src/sound/saasound/SAAEnv.cpp new file mode 100755 index 000000000..ae8191112 --- /dev/null +++ b/src/sound/saasound/SAAEnv.cpp @@ -0,0 +1,380 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAEnv.cpp: implementation of the CSAAEnv class. +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" +#include "types.h" +#include "SAAEnv.h" + + +////////////////////////////////////////////////////////////////////// +// Static member initialisation +////////////////////////////////////////////////////////////////////// + +const ENVDATA CSAAEnv::cs_EnvData[8] = +{ + {1,false, { {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, + {1,true, { {{15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15},{15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15}}, + {{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14},{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}}}}, + {1,false, { {{15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + {{14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, + {1,true, { {{15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + {{14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, + {2,false, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}}, + {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}}}}, + {2,true, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}}, + {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}}}}, + {1,false, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, + {1,true, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}} +}; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSAAEnv::CSAAEnv() +: +m_bEnabled(false), +m_bNewData(false), +m_nNextData(0), +m_bEnvelopeEnded(true), +m_nPhase(0), +m_nPhasePosition(0), +m_nResolution(1) +{ + // initialise itself with the value 'zero' + SetEnvControl(0); +} + +CSAAEnv::~CSAAEnv() +{ + // Nothing to do +} + +void CSAAEnv::InternalClock(void) +{ + // will only do something if envelope clock mode is set to internal + // and the env control is enabled + if (m_bEnabled && (!m_bClockExternally)) Tick(); +} + +void CSAAEnv::ExternalClock(void) +{ + // will only do something if envelope clock mode is set to external + // and the env control is enabled + if (m_bClockExternally && m_bEnabled) Tick(); +} + +void CSAAEnv::SetEnvControl(int nData) +{ + // process immediate stuff first: + // start with the Enabled flag. if env is disabled, + // there's not much to do + bool bEnabled = ((nData & 0x80)==0x80); + if (!bEnabled && !m_bEnabled) + return; + m_bEnabled = bEnabled; + if (!m_bEnabled) + { + // env control was enabled, and now disabled + // Any subsequent env control changes are immediate. + m_bEnvelopeEnded = true; + return; + } + + // Resolution (3bit/4bit) is also immediately processed + int new_resolution = ((nData & 0x10) == 0x10) ? 2 : 1; + // NOTE: undocumented behaviour when changing resolution mid-waveform + // Empirically, the following matches observations: + // * When ticking the env generator with 4-bit resolution, the position += 1 + // * When ticking the env generator with 3-bit resolution, the position += 2 + // * When changing between 4-bit resolution and 3-bit resolution + // without ticking the env generator, the position is unchanged + // (although, effectively, the LSB is ignored. Purely as an implementation + // detail, I'm implementing this as clearing the LSB ie LSB=0; see next point) + // * When changing between 3-bit resolution and 4-bit resolution + // without ticking the env generator, the position LSB is set to 1 + // See test case: envext_34b + // + if (m_nResolution == 1 && new_resolution == 2) + { + // change from 4-bit to 3-bit + m_nPhasePosition &= 0xe; + } + else if (m_nResolution == 2 && new_resolution == 1) + { + // change from 3-bit to 4-bit + m_nPhasePosition |= 0x1; + } + m_nResolution = new_resolution; + + // now buffered stuff: but only if it's ok to, and only if the + // envgenerator is not disabled. otherwise it just stays buffered until + // the Tick() function sets m_bEnvelopeEnded to true and realises there is + // already some new data waiting + if (m_bEnvelopeEnded) + { + SetNewEnvData(nData); // also does the SetLevels() call for us. + m_bNewData=false; + } + else + { + // since the 'next resolution' changes arrive unbuffered, we + // may need to change the current level because of this: + SetLevels(); + + // store current new data, and set the newdata flag: + m_bNewData = true; + m_nNextData = nData; + } + +} + +int CSAAEnv::LeftLevel(void) const +{ + return m_nLeftLevel; +} + +int CSAAEnv::RightLevel(void) const +{ + return m_nRightLevel; +} + +inline void CSAAEnv::Tick(void) +{ + // if disabled, do nothing + if (!m_bEnabled) // m_bEnabled is set directly, not buffered, so this is ok + { + // for sanity, reset stuff: + m_bEnvelopeEnded = true; + m_nPhase = 0; + m_nPhasePosition = 0; + return; + } + + // else : m_bEnabled + + + if (m_bEnvelopeEnded) + { + // do nothing + // (specifically, don't change the values of m_bEnvelopeEnded, + // m_nPhase and m_nPhasePosition, as these will still be needed + // by SetLevels() should it be called again) + + return; + } + + + // else : !m_bEnvelopeEnded + // Continue playing the same envelope ... + // increments the phaseposition within an envelope. + // also handles looping and resolution appropriately. + // Changes the level of the envelope accordingly + // through calling SetLevels() . This must be called after making + // any changes that will affect the output levels of the env controller!! + // SetLevels also handles left-right channel inverting + + // increment phase position + m_nPhasePosition += m_nResolution; + + // if this means we've gone past 16 (the end of a phase) + // then change phase, and if necessary, loop + // Refer to datasheet for meanings of (3) and (4) in following text + // w.r.t SAA1099 envelopes + + // Note that we will always reach position (3) or (4), even if we keep toggling + // resolution from 4-bit to 3-bit and back, because the counter will always wrap to 0. + // In fact it's quite elegant: + // No matter how you increment and toggle and increment and toggle, the counter + // will at some point be either 0xe (either 4-bit mode or 3-bit mode) or 0xf (4-bit mode only). + // Depending on the mode, even if you change the mode, the next increment, + // or the one after it, will then take it to 0. + // 0xe + 2 (3bit mode) => 0x0 + // 0xe + 1 (4bit mode) => 0xf + // 0xf + 1 (4bit mode) => 0x0 + // 0xe -> (toggle 3bit mode to 4bit mode) => 0xf + // 0xe -> (toggle 4bit mode to 3bit mode) => 0xe + // 0xf -> (toggle 4bit mode to 3bit mode) => 0xe + // + // but there is a subtlety (of course), which is that any changes at point (3) + // can take place immediately you hit point (3), but changes at point (4) are actually + // only acted upon when the counter transitions from 0xe (or 0xf) to 0x0 (which also + // means that, for these looping envelopes, which are the ones that have a point(4), + // immediately after the counter wrapping to 0x0, a write to the env data register will + // NOT set the waveform and will NOT reset the phase/phaseposition (even though it + // will still let you toggle the 4bit/3bit mode, which will change the phaseposition LSB!) + // See test case: envext_34c + + bool bProcessNewDataIfAvailable = false; + if (m_nPhasePosition >= 16) + { + m_nPhase++; + + // if we should loop, then do so - and we've reached position (4) + // otherwise, if we shouldn't loop, + // then we've reached position (3) and so we say that + // we're ok for new data. + if (m_nPhase == m_nNumberOfPhases) + { + // at position (3) or (4) + if (!m_bLooping) + { + // position (3) only + // note that it seems that the sustain level is ALWAYS zero + // in the case of non-looping waveforms + m_bEnvelopeEnded = true; + bProcessNewDataIfAvailable = true; + } + else + { + // position (4) only + // note that any data already latched is ONLY acted upon + // at THIS point. If (after this Tick has completed) any new + // env data is written, it will NOT be acted upon, until + // we get back to position (4) again. + // this is why m_bEnvelopeEnded (which affects the behaviour + // of the SetEnvControl method) is FALSE here. + // See test case: envext_34c (as noted earlier) + m_bEnvelopeEnded = false; + // set phase pointer to start of envelope for loop + // and reset m_nPhasePosition + m_nPhase=0; + m_nPhasePosition -= 16; + bProcessNewDataIfAvailable = true; + } + } + else // (m_nPhase < m_nNumberOfPhases) + { + // not at position (3) or (4) ... + // (i.e., we're in the middle of an envelope with + // more than one phase. Specifically, we're in + // the middle of envelope 4 or 5 - the + // triangle envelopes - but that's not important) + + // any commands sent to this envelope controller + // will be buffered. Set the flag to indicate this. + m_bEnvelopeEnded = false; + m_nPhasePosition -= 16; + } + } + else // (m_nPhasePosition < 16) + { + // still within the same phase; + // but, importantly, we are no longer at the start of the phase ... + // so new data cannot be acted on immediately, and must + // be buffered + m_bEnvelopeEnded = false; + // Phase and PhasePosition have already been updated. + // SetLevels() will need to be called to actually calculate + // the output 'level' of this envelope controller + } + + + // if we have new (buffered) data, now is the time to act on it + if (m_bNewData && bProcessNewDataIfAvailable) + { + m_bNewData = false; + SetNewEnvData(m_nNextData); + } + else + { + // ok, we didn't have any new buffered date to act on, + // so we just call SetLevels() to calculate the output level + // for whatever the current envelope is + SetLevels(); + } + +} + +inline void CSAAEnv::SetLevels(void) +{ + // sets m_nLeftLevel + // Also sets m_nRightLevel in terms of m_nLeftLevel + // and m_bInvertRightChannel + + // m_nResolution: 1 means 4-bit resolution; 2 means 3-bit resolution. Resolution of envelope waveform. + + // Note that this is handled 'immediately', and doesn't wait for synchronisation of + // the envelope waveform (this is important, see test case EnvExt_imm) + // It is therefore possible to switch between 4-bit and 3-bit resolution in the middle of + // an envelope waveform. if you are at an 'odd' phase position, you would be able to hear + // the difference. if you are at an 'even' phase position, the volume level for 4-bit + // and 3-bit would be the same. + // NOTE: additional test cases are required. + + switch (m_nResolution) + { + case 1: // 4 bit res waveforms + default: + { + // special case: if envelope is not a looping one, and we're at the end + // then our level should be zero (all of the non-looping waveforms have + // a sustain level of zero): + if (m_bEnvelopeEnded && !m_bLooping) + m_nLeftLevel = 0; + else + m_nLeftLevel = m_pEnvData->nLevels[0][m_nPhase][m_nPhasePosition]; + + if (m_bInvertRightChannel) + m_nRightLevel = 15-m_nLeftLevel; + else + m_nRightLevel = m_nLeftLevel; + break; + } + case 2: // 3 bit res waveforms + { + // special case: if envelope is not a looping one, and we're at the end + // then our level should be zero (all of the non-looping waveforms have + // a sustain level of zero): + if (m_bEnvelopeEnded && !m_bLooping) + m_nLeftLevel = 0; + else + m_nLeftLevel = m_pEnvData->nLevels[1][m_nPhase][m_nPhasePosition]; + if (m_bInvertRightChannel) + m_nRightLevel = 14-m_nLeftLevel; + else + m_nRightLevel = m_nLeftLevel; + break; + } + } +} + + +inline void CSAAEnv::SetNewEnvData(int nData) +{ + // loads envgenerator's registers according to the bits set + // in nData + + m_nPhase = 0; + m_nPhasePosition = 0; + m_pEnvData = &(cs_EnvData[(nData >> 1) & 0x07]); + m_bInvertRightChannel = ((nData & 0x01) == 0x01); + m_bClockExternally = ((nData & 0x20) == 0x20); + m_nNumberOfPhases = m_pEnvData->nNumberOfPhases; + m_bLooping = m_pEnvData->bLooping; + m_nResolution = (((nData & 0x10)==0x10) ? 2 : 1); + m_bEnabled = ((nData & 0x80) == 0x80); + if (m_bEnabled) + { + m_bEnvelopeEnded = false; + // is this right? + // YES. See test case EnvExt_34c (setting data multiple times + // when at a point (3) resets the waveform so you're no longer + // at a point (3). + } + else + { + // DISABLED - so set stuff accordingly + m_bEnvelopeEnded = true; + m_nPhase = 0; + m_nPhasePosition = 0; + } + + SetLevels(); +} diff --git a/src/sound/saasound/SAAEnv.h b/src/sound/saasound/SAAEnv.h new file mode 100755 index 000000000..131659c06 --- /dev/null +++ b/src/sound/saasound/SAAEnv.h @@ -0,0 +1,54 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAEnv.h: interface for the CSAAEnv class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAAENV_H_INCLUDED +#define SAAENV_H_INCLUDED + +class CSAAEnv +{ +private: + int m_nLeftLevel, m_nRightLevel; + ENVDATA const * m_pEnvData; + + bool m_bEnabled; + bool m_bInvertRightChannel; + BYTE m_nPhase; + BYTE m_nPhasePosition; + bool m_bEnvelopeEnded; + char m_nPhaseAdd[2]; + char m_nCurrentPhaseAdd; + bool m_bLooping; + char m_nNumberOfPhases; + char m_nResolution; + char m_nInitialLevel; + bool m_bNewData; + BYTE m_nNextData; + bool m_bClockExternally; + static const ENVDATA cs_EnvData[8]; + + void Tick(void); + void SetLevels(void); + void SetNewEnvData(int nData); + +public: + CSAAEnv(); + ~CSAAEnv(); + + void InternalClock(void); + void ExternalClock(void); + void SetEnvControl(int nData); // really just a BYTE + int LeftLevel(void) const; + int RightLevel(void) const; + bool IsActive(void) const; + +}; + +inline bool CSAAEnv::IsActive(void) const +{ + return m_bEnabled; +} + +#endif // SAAENV_H_INCLUDED diff --git a/src/sound/saasound/SAAFreq.cpp b/src/sound/saasound/SAAFreq.cpp new file mode 100755 index 000000000..52cbc7a3d --- /dev/null +++ b/src/sound/saasound/SAAFreq.cpp @@ -0,0 +1,280 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAFreq.cpp: implementation of the CSAAFreq class. +// only 7-bit fractional accuracy on oscillator periods. I may consider fixing that. +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" +#include "types.h" +#include "SAANoise.h" +#include "SAAEnv.h" +#include "SAAFreq.h" +#include "defns.h" + +#ifdef SAAFREQ_FIXED_CLOCKRATE +// 'load in' the data for the static frequency lookup table +// precomputed for a fixed clockrate +// See: tools/freqdat.py +const unsigned long CSAAFreq::m_FreqTable[2048] = { +#include "SAAFreq.dat" +}; +#else +unsigned long CSAAFreq::m_FreqTable[2048]; +unsigned long CSAAFreq::m_nClockRate = 0; +#endif // SAAFREQ_FIXED_CLOCKRATE + +const int INITIAL_LEVEL = 1; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSAAFreq::CSAAFreq(CSAANoise * const NoiseGenerator, CSAAEnv * const EnvGenerator) +: +m_nCounter(0), m_nCounter_low(0), m_nAdd(0), +m_nLevel(INITIAL_LEVEL), +m_nOversample(0), m_nCounterLimit_low(1), +m_nCurrentOffset(0), m_nCurrentOctave(0), m_nNextOffset(0), m_nNextOctave(0), +m_bIgnoreOffsetData(false), m_bNewData(false), +m_bSync(false), +m_nSampleRate(SAMPLE_RATE_HZ), +m_pcConnectedNoiseGenerator(NoiseGenerator), +m_pcConnectedEnvGenerator(EnvGenerator), +m_nConnectedMode((NoiseGenerator == NULL) ? ((EnvGenerator == NULL) ? 0 : 1) : 2) +{ + _SetClockRate(EXTERNAL_CLK_HZ); + SetAdd(); // current octave, current offset +} + +CSAAFreq::~CSAAFreq() +{ + // Nothing to do +} + +void CSAAFreq::SetFreqOffset(BYTE nOffset) +{ + // nOffset between 0 and 255 + + if (!m_bSync) + { + m_nNextOffset = nOffset; + m_bNewData=true; + if (m_nNextOctave==m_nCurrentOctave) + { + // According to Philips, if you send the SAA-1099 + // new Octave data and then new Offset data in that + // order, on the next half-cycle of the current frequency + // generator, ONLY the octave data is acted upon. + // The offset data will be acted upon next time. + + // ?? TEST CASE : if you set the octave and then the offset + // but the octave you set it to is the same one it already was. + // Will this ignore the offset data? + // Do you get the same behaviour if you set offset THEN octave + // even if you set octave to the same value it was before? + + m_bIgnoreOffsetData=true; + } + } + else + { + // updates straightaway if m_bSync + m_bNewData=false; + m_bIgnoreOffsetData = false; + m_nCurrentOffset = nOffset; + m_nNextOffset = nOffset; + m_nCurrentOctave = m_nNextOctave; + SetAdd(); + } + +} + +void CSAAFreq::SetFreqOctave(BYTE nOctave) +{ + // nOctave between 0 and 7 + + if (!m_bSync) + { + m_nNextOctave = nOctave; + m_bNewData=true; + m_bIgnoreOffsetData = false; + } + else + { + // updates straightaway if m_bSync + m_bNewData=false; + m_bIgnoreOffsetData = false; + m_nCurrentOctave = nOctave; + m_nNextOctave = nOctave; + m_nCurrentOffset = m_nNextOffset; + SetAdd(); + } +} + +void CSAAFreq::UpdateOctaveOffsetData(void) +{ + // loads the buffered new octave and new offset data into the current registers + // and sets up the new frequency for this frequency generator (i.e. sets up m_nAdd) + // - called during Sync, and called when waveform half-cycle completes + + // How the SAA-1099 really treats new data: + // if only new octave data is present, + // then set new period based on just the octave data + // Otherwise, if only new offset data is present, + // then set new period based on just the offset data + // Otherwise, if new octave data is present, and new offset data is present, + // and the offset data was set BEFORE the octave data, + // then set new period based on both the octave and offset data + // Else, if the offset data came AFTER the new octave data + // then set new period based on JUST THE OCTAVE DATA, and continue + // signalling the offset data as 'new', so it will be acted upon + // next half-cycle + // + // Weird, I know. But that's how it works. Philips even documented as much. + + if (!m_bNewData) + { + // optimise for the most common case! No new data! + return; + } + + m_nCurrentOctave=m_nNextOctave; + if (!m_bIgnoreOffsetData) + { + m_nCurrentOffset=m_nNextOffset; + m_bNewData=false; + } + m_bIgnoreOffsetData=false; + + SetAdd(); +} + +void CSAAFreq::_SetSampleRate(unsigned int nSampleRate) +{ + m_nSampleRate = nSampleRate; +} + +void CSAAFreq::_SetOversample(unsigned int oversample) +{ + // oversample is a power of 2 i.e. + // if oversample == 2 then 4x oversample + // if oversample == 6 then 64x oversample + if (oversample < m_nOversample) + { + m_nCounter_low <<= (m_nOversample - oversample); + } + else + { + m_nCounter_low >>= (oversample - m_nOversample); + } + + m_nCounterLimit_low = 1<= (m_nSampleRate<<12)) + { + m_nCounter -= (m_nSampleRate<<12); + m_nCounter_low++; + if (m_nCounter_low >= m_nCounterLimit_low) + { + // period elapsed for (at least) one half-cycle of + // current frequency + m_nCounter_low = 0; + // flip state - from 0 to 1 or vice versa + m_nLevel = 1 - m_nLevel; + + // trigger any connected devices + switch (m_nConnectedMode) + { + case 1: + // env trigger + m_pcConnectedEnvGenerator->InternalClock(); + break; + + case 2: + // noise trigger + m_pcConnectedNoiseGenerator->Trigger(); + break; + + default: + // do nothing + break; + } + + // get new frequency (set period length m_nAdd) if new data is waiting: + UpdateOctaveOffsetData(); + } + } + + return m_nLevel; +} + +void CSAAFreq::SetAdd(void) +{ + // nOctave between 0 and 7; nOffset between 0 and 255 + + // Used to be: + // m_nAdd = (15625 << nOctave) / (511 - nOffset); + // Now just table lookup: + m_nAdd = m_FreqTable[m_nCurrentOctave<<8 | m_nCurrentOffset]; +} + +void CSAAFreq::Sync(bool bSync) +{ + m_bSync = bSync; + + // update straightaway if m_bSync + if (m_bSync) + { + m_nCounter = 0; + m_nCounter_low = 0; + + // this seems to need to be required to make the Fred59 SPACE DEMO audio work correctly + m_nLevel = INITIAL_LEVEL; + + m_nCurrentOctave=m_nNextOctave; + m_nCurrentOffset=m_nNextOffset; + SetAdd(); + } +} diff --git a/src/sound/saasound/SAAFreq.dat b/src/sound/saasound/SAAFreq.dat new file mode 100755 index 000000000..04fb9081a --- /dev/null +++ b/src/sound/saasound/SAAFreq.dat @@ -0,0 +1,141 @@ +/* +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// Precalculated oscillator frequency period steps +// Higher scaling for better accuracy. +// +// After construction, it's important to SetSampleRate before +// trying to use the generator. +// (Just because the CSAANoise object has a default samplerate +// doesn't mean you should rely on it) +// +////////////////////////////////////////////////////////////////////// +*/ + 250489 , 250980 , 251473 , 251969 , 252465 , 252964 , 253465 , 253968 , 254473 , 254980 , 255489 , 256000 , 256513 , 257028 , 257545 , 258065 , + 258586 , 259109 , 259635 , 260163 , 260692 , 261224 , 261759 , 262295 , 262834 , 263374 , 263918 , 264463 , 265010 , 265560 , 266112 , 266667 , + 267223 , 267782 , 268344 , 268908 , 269474 , 270042 , 270613 , 271186 , 271762 , 272340 , 272921 , 273504 , 274090 , 274678 , 275269 , 275862 , + 276458 , 277056 , 277657 , 278261 , 278867 , 279476 , 280088 , 280702 , 281319 , 281938 , 282561 , 283186 , 283814 , 284444 , 285078 , 285714 , + 286353 , 286996 , 287640 , 288288 , 288939 , 289593 , 290249 , 290909 , 291572 , 292237 , 292906 , 293578 , 294253 , 294931 , 295612 , 296296 , + 296984 , 297674 , 298368 , 299065 , 299766 , 300469 , 301176 , 301887 , 302600 , 303318 , 304038 , 304762 , 305489 , 306220 , 306954 , 307692 , + 308434 , 309179 , 309927 , 310680 , 311436 , 312195 , 312958 , 313725 , 314496 , 315271 , 316049 , 316832 , 317618 , 318408 , 319202 , 320000 , + 320802 , 321608 , 322418 , 323232 , 324051 , 324873 , 325700 , 326531 , 327366 , 328205 , 329049 , 329897 , 330749 , 331606 , 332468 , 333333 , + 334204 , 335079 , 335958 , 336842 , 337731 , 338624 , 339523 , 340426 , 341333 , 342246 , 343164 , 344086 , 345013 , 345946 , 346883 , 347826 , + 348774 , 349727 , 350685 , 351648 , 352617 , 353591 , 354571 , 355556 , 356546 , 357542 , 358543 , 359551 , 360563 , 361582 , 362606 , 363636 , + 364672 , 365714 , 366762 , 367816 , 368876 , 369942 , 371014 , 372093 , 373178 , 374269 , 375367 , 376471 , 377581 , 378698 , 379822 , 380952 , + 382090 , 383234 , 384384 , 385542 , 386707 , 387879 , 389058 , 390244 , 391437 , 392638 , 393846 , 395062 , 396285 , 397516 , 398754 , 400000 , + 401254 , 402516 , 403785 , 405063 , 406349 , 407643 , 408946 , 410256 , 411576 , 412903 , 414239 , 415584 , 416938 , 418301 , 419672 , 421053 , + 422442 , 423841 , 425249 , 426667 , 428094 , 429530 , 430976 , 432432 , 433898 , 435374 , 436860 , 438356 , 439863 , 441379 , 442907 , 444444 , + 445993 , 447552 , 449123 , 450704 , 452297 , 453901 , 455516 , 457143 , 458781 , 460432 , 462094 , 463768 , 465455 , 467153 , 468864 , 470588 , + 472325 , 474074 , 475836 , 477612 , 479401 , 481203 , 483019 , 484848 , 486692 , 488550 , 490421 , 492308 , 494208 , 496124 , 498054 , 500000 , + 500978 , 501961 , 502947 , 503937 , 504931 , 505929 , 506931 , 507937 , 508946 , 509960 , 510978 , 512000 , 513026 , 514056 , 515091 , 516129 , + 517172 , 518219 , 519270 , 520325 , 521385 , 522449 , 523517 , 524590 , 525667 , 526749 , 527835 , 528926 , 530021 , 531120 , 532225 , 533333 , + 534447 , 535565 , 536688 , 537815 , 538947 , 540084 , 541226 , 542373 , 543524 , 544681 , 545842 , 547009 , 548180 , 549356 , 550538 , 551724 , + 552916 , 554113 , 555315 , 556522 , 557734 , 558952 , 560175 , 561404 , 562637 , 563877 , 565121 , 566372 , 567627 , 568889 , 570156 , 571429 , + 572707 , 573991 , 575281 , 576577 , 577878 , 579186 , 580499 , 581818 , 583144 , 584475 , 585812 , 587156 , 588506 , 589862 , 591224 , 592593 , + 593968 , 595349 , 596737 , 598131 , 599532 , 600939 , 602353 , 603774 , 605201 , 606635 , 608076 , 609524 , 610979 , 612440 , 613909 , 615385 , + 616867 , 618357 , 619855 , 621359 , 622871 , 624390 , 625917 , 627451 , 628993 , 630542 , 632099 , 633663 , 635236 , 636816 , 638404 , 640000 , + 641604 , 643216 , 644836 , 646465 , 648101 , 649746 , 651399 , 653061 , 654731 , 656410 , 658098 , 659794 , 661499 , 663212 , 664935 , 666667 , + 668407 , 670157 , 671916 , 673684 , 675462 , 677249 , 679045 , 680851 , 682667 , 684492 , 686327 , 688172 , 690027 , 691892 , 693767 , 695652 , + 697548 , 699454 , 701370 , 703297 , 705234 , 707182 , 709141 , 711111 , 713092 , 715084 , 717087 , 719101 , 721127 , 723164 , 725212 , 727273 , + 729345 , 731429 , 733524 , 735632 , 737752 , 739884 , 742029 , 744186 , 746356 , 748538 , 750733 , 752941 , 755162 , 757396 , 759644 , 761905 , + 764179 , 766467 , 768769 , 771084 , 773414 , 775758 , 778116 , 780488 , 782875 , 785276 , 787692 , 790123 , 792570 , 795031 , 797508 , 800000 , + 802508 , 805031 , 807571 , 810127 , 812698 , 815287 , 817891 , 820513 , 823151 , 825806 , 828479 , 831169 , 833876 , 836601 , 839344 , 842105 , + 844884 , 847682 , 850498 , 853333 , 856187 , 859060 , 861953 , 864865 , 867797 , 870748 , 873720 , 876712 , 879725 , 882759 , 885813 , 888889 , + 891986 , 895105 , 898246 , 901408 , 904594 , 907801 , 911032 , 914286 , 917563 , 920863 , 924188 , 927536 , 930909 , 934307 , 937729 , 941176 , + 944649 , 948148 , 951673 , 955224 , 958801 , 962406 , 966038 , 969697 , 973384 , 977099 , 980843 , 984615 , 988417 , 992248 , 996109 , 1000000 , + 1001957 , 1003922 , 1005894 , 1007874 , 1009862 , 1011858 , 1013861 , 1015873 , 1017893 , 1019920 , 1021956 , 1024000 , 1026052 , 1028112 , 1030181 , 1032258 , + 1034343 , 1036437 , 1038540 , 1040650 , 1042770 , 1044898 , 1047035 , 1049180 , 1051335 , 1053498 , 1055670 , 1057851 , 1060041 , 1062241 , 1064449 , 1066667 , + 1068894 , 1071130 , 1073375 , 1075630 , 1077895 , 1080169 , 1082452 , 1084746 , 1087049 , 1089362 , 1091684 , 1094017 , 1096360 , 1098712 , 1101075 , 1103448 , + 1105832 , 1108225 , 1110629 , 1113043 , 1115468 , 1117904 , 1120350 , 1122807 , 1125275 , 1127753 , 1130243 , 1132743 , 1135255 , 1137778 , 1140312 , 1142857 , + 1145414 , 1147982 , 1150562 , 1153153 , 1155756 , 1158371 , 1160998 , 1163636 , 1166287 , 1168950 , 1171625 , 1174312 , 1177011 , 1179724 , 1182448 , 1185185 , + 1187935 , 1190698 , 1193473 , 1196262 , 1199063 , 1201878 , 1204706 , 1207547 , 1210402 , 1213270 , 1216152 , 1219048 , 1221957 , 1224880 , 1227818 , 1230769 , + 1233735 , 1236715 , 1239709 , 1242718 , 1245742 , 1248780 , 1251834 , 1254902 , 1257985 , 1261084 , 1264198 , 1267327 , 1270471 , 1273632 , 1276808 , 1280000 , + 1283208 , 1286432 , 1289673 , 1292929 , 1296203 , 1299492 , 1302799 , 1306122 , 1309463 , 1312821 , 1316195 , 1319588 , 1322997 , 1326425 , 1329870 , 1333333 , + 1336815 , 1340314 , 1343832 , 1347368 , 1350923 , 1354497 , 1358090 , 1361702 , 1365333 , 1368984 , 1372654 , 1376344 , 1380054 , 1383784 , 1387534 , 1391304 , + 1395095 , 1398907 , 1402740 , 1406593 , 1410468 , 1414365 , 1418283 , 1422222 , 1426184 , 1430168 , 1434174 , 1438202 , 1442254 , 1446328 , 1450425 , 1454545 , + 1458689 , 1462857 , 1467049 , 1471264 , 1475504 , 1479769 , 1484058 , 1488372 , 1492711 , 1497076 , 1501466 , 1505882 , 1510324 , 1514793 , 1519288 , 1523810 , + 1528358 , 1532934 , 1537538 , 1542169 , 1546828 , 1551515 , 1556231 , 1560976 , 1565749 , 1570552 , 1575385 , 1580247 , 1585139 , 1590062 , 1595016 , 1600000 , + 1605016 , 1610063 , 1615142 , 1620253 , 1625397 , 1630573 , 1635783 , 1641026 , 1646302 , 1651613 , 1656958 , 1662338 , 1667752 , 1673203 , 1678689 , 1684211 , + 1689769 , 1695364 , 1700997 , 1706667 , 1712375 , 1718121 , 1723906 , 1729730 , 1735593 , 1741497 , 1747440 , 1753425 , 1759450 , 1765517 , 1771626 , 1777778 , + 1783972 , 1790210 , 1796491 , 1802817 , 1809187 , 1815603 , 1822064 , 1828571 , 1835125 , 1841727 , 1848375 , 1855072 , 1861818 , 1868613 , 1875458 , 1882353 , + 1889299 , 1896296 , 1903346 , 1910448 , 1917603 , 1924812 , 1932075 , 1939394 , 1946768 , 1954198 , 1961686 , 1969231 , 1976834 , 1984496 , 1992218 , 2000000 , + 2003914 , 2007843 , 2011788 , 2015748 , 2019724 , 2023715 , 2027723 , 2031746 , 2035785 , 2039841 , 2043912 , 2048000 , 2052104 , 2056225 , 2060362 , 2064516 , + 2068687 , 2072874 , 2077079 , 2081301 , 2085540 , 2089796 , 2094070 , 2098361 , 2102669 , 2106996 , 2111340 , 2115702 , 2120083 , 2124481 , 2128898 , 2133333 , + 2137787 , 2142259 , 2146751 , 2151261 , 2155789 , 2160338 , 2164905 , 2169492 , 2174098 , 2178723 , 2183369 , 2188034 , 2192719 , 2197425 , 2202151 , 2206897 , + 2211663 , 2216450 , 2221258 , 2226087 , 2230937 , 2235808 , 2240700 , 2245614 , 2250549 , 2255507 , 2260486 , 2265487 , 2270510 , 2275556 , 2280624 , 2285714 , + 2290828 , 2295964 , 2301124 , 2306306 , 2311512 , 2316742 , 2321995 , 2327273 , 2332574 , 2337900 , 2343249 , 2348624 , 2354023 , 2359447 , 2364896 , 2370370 , + 2375870 , 2381395 , 2386946 , 2392523 , 2398126 , 2403756 , 2409412 , 2415094 , 2420804 , 2426540 , 2432304 , 2438095 , 2443914 , 2449761 , 2455635 , 2461538 , + 2467470 , 2473430 , 2479419 , 2485437 , 2491484 , 2497561 , 2503667 , 2509804 , 2515971 , 2522167 , 2528395 , 2534653 , 2540943 , 2547264 , 2553616 , 2560000 , + 2566416 , 2572864 , 2579345 , 2585859 , 2592405 , 2598985 , 2605598 , 2612245 , 2618926 , 2625641 , 2632391 , 2639175 , 2645995 , 2652850 , 2659740 , 2666667 , + 2673629 , 2680628 , 2687664 , 2694737 , 2701847 , 2708995 , 2716180 , 2723404 , 2730667 , 2737968 , 2745308 , 2752688 , 2760108 , 2767568 , 2775068 , 2782609 , + 2790191 , 2797814 , 2805479 , 2813187 , 2820937 , 2828729 , 2836565 , 2844444 , 2852368 , 2860335 , 2868347 , 2876404 , 2884507 , 2892655 , 2900850 , 2909091 , + 2917379 , 2925714 , 2934097 , 2942529 , 2951009 , 2959538 , 2968116 , 2976744 , 2985423 , 2994152 , 3002933 , 3011765 , 3020649 , 3029586 , 3038576 , 3047619 , + 3056716 , 3065868 , 3075075 , 3084337 , 3093656 , 3103030 , 3112462 , 3121951 , 3131498 , 3141104 , 3150769 , 3160494 , 3170279 , 3180124 , 3190031 , 3200000 , + 3210031 , 3220126 , 3230284 , 3240506 , 3250794 , 3261146 , 3271565 , 3282051 , 3292605 , 3303226 , 3313916 , 3324675 , 3335505 , 3346405 , 3357377 , 3368421 , + 3379538 , 3390728 , 3401993 , 3413333 , 3424749 , 3436242 , 3447811 , 3459459 , 3471186 , 3482993 , 3494881 , 3506849 , 3518900 , 3531034 , 3543253 , 3555556 , + 3567944 , 3580420 , 3592982 , 3605634 , 3618375 , 3631206 , 3644128 , 3657143 , 3670251 , 3683453 , 3696751 , 3710145 , 3723636 , 3737226 , 3750916 , 3764706 , + 3778598 , 3792593 , 3806691 , 3820896 , 3835206 , 3849624 , 3864151 , 3878788 , 3893536 , 3908397 , 3923372 , 3938462 , 3953668 , 3968992 , 3984436 , 4000000 , + 4007828 , 4015686 , 4023576 , 4031496 , 4039448 , 4047431 , 4055446 , 4063492 , 4071571 , 4079681 , 4087824 , 4096000 , 4104208 , 4112450 , 4120724 , 4129032 , + 4137374 , 4145749 , 4154158 , 4162602 , 4171079 , 4179592 , 4188139 , 4196721 , 4205339 , 4213992 , 4222680 , 4231405 , 4240166 , 4248963 , 4257796 , 4266667 , + 4275574 , 4284519 , 4293501 , 4302521 , 4311579 , 4320675 , 4329810 , 4338983 , 4348195 , 4357447 , 4366738 , 4376068 , 4385439 , 4394850 , 4404301 , 4413793 , + 4423326 , 4432900 , 4442516 , 4452174 , 4461874 , 4471616 , 4481400 , 4491228 , 4501099 , 4511013 , 4520971 , 4530973 , 4541020 , 4551111 , 4561247 , 4571429 , + 4581655 , 4591928 , 4602247 , 4612613 , 4623025 , 4633484 , 4643991 , 4654545 , 4665148 , 4675799 , 4686499 , 4697248 , 4708046 , 4718894 , 4729792 , 4740741 , + 4751740 , 4762791 , 4773893 , 4785047 , 4796253 , 4807512 , 4818824 , 4830189 , 4841608 , 4853081 , 4864608 , 4876190 , 4887828 , 4899522 , 4911271 , 4923077 , + 4934940 , 4946860 , 4958838 , 4970874 , 4982968 , 4995122 , 5007335 , 5019608 , 5031941 , 5044335 , 5056790 , 5069307 , 5081886 , 5094527 , 5107232 , 5120000 , + 5132832 , 5145729 , 5158690 , 5171717 , 5184810 , 5197970 , 5211196 , 5224490 , 5237852 , 5251282 , 5264781 , 5278351 , 5291990 , 5305699 , 5319481 , 5333333 , + 5347258 , 5361257 , 5375328 , 5389474 , 5403694 , 5417989 , 5432361 , 5446809 , 5461333 , 5475936 , 5490617 , 5505376 , 5520216 , 5535135 , 5550136 , 5565217 , + 5580381 , 5595628 , 5610959 , 5626374 , 5641873 , 5657459 , 5673130 , 5688889 , 5704735 , 5720670 , 5736695 , 5752809 , 5769014 , 5785311 , 5801700 , 5818182 , + 5834758 , 5851429 , 5868195 , 5885057 , 5902017 , 5919075 , 5936232 , 5953488 , 5970845 , 5988304 , 6005865 , 6023529 , 6041298 , 6059172 , 6077151 , 6095238 , + 6113433 , 6131737 , 6150150 , 6168675 , 6187311 , 6206061 , 6224924 , 6243902 , 6262997 , 6282209 , 6301538 , 6320988 , 6340557 , 6360248 , 6380062 , 6400000 , + 6420063 , 6440252 , 6460568 , 6481013 , 6501587 , 6522293 , 6543131 , 6564103 , 6585209 , 6606452 , 6627832 , 6649351 , 6671010 , 6692810 , 6714754 , 6736842 , + 6759076 , 6781457 , 6803987 , 6826667 , 6849498 , 6872483 , 6895623 , 6918919 , 6942373 , 6965986 , 6989761 , 7013699 , 7037801 , 7062069 , 7086505 , 7111111 , + 7135889 , 7160839 , 7185965 , 7211268 , 7236749 , 7262411 , 7288256 , 7314286 , 7340502 , 7366906 , 7393502 , 7420290 , 7447273 , 7474453 , 7501832 , 7529412 , + 7557196 , 7585185 , 7613383 , 7641791 , 7670412 , 7699248 , 7728302 , 7757576 , 7787072 , 7816794 , 7846743 , 7876923 , 7907336 , 7937984 , 7968872 , 8000000 , + 8015656 , 8031373 , 8047151 , 8062992 , 8078895 , 8094862 , 8110891 , 8126984 , 8143141 , 8159363 , 8175649 , 8192000 , 8208417 , 8224900 , 8241449 , 8258065 , + 8274747 , 8291498 , 8308316 , 8325203 , 8342159 , 8359184 , 8376278 , 8393443 , 8410678 , 8427984 , 8445361 , 8462810 , 8480331 , 8497925 , 8515593 , 8533333 , + 8551148 , 8569038 , 8587002 , 8605042 , 8623158 , 8641350 , 8659619 , 8677966 , 8696391 , 8714894 , 8733475 , 8752137 , 8770878 , 8789700 , 8808602 , 8827586 , + 8846652 , 8865801 , 8885033 , 8904348 , 8923747 , 8943231 , 8962801 , 8982456 , 9002198 , 9022026 , 9041943 , 9061947 , 9082040 , 9102222 , 9122494 , 9142857 , + 9163311 , 9183857 , 9204494 , 9225225 , 9246050 , 9266968 , 9287982 , 9309091 , 9330296 , 9351598 , 9372998 , 9394495 , 9416092 , 9437788 , 9459584 , 9481481 , + 9503480 , 9525581 , 9547786 , 9570093 , 9592506 , 9615023 , 9637647 , 9660377 , 9683215 , 9706161 , 9729216 , 9752381 , 9775656 , 9799043 , 9822542 , 9846154 , + 9869880 , 9893720 , 9917676 , 9941748 , 9965937 , 9990244 , 10014670 , 10039216 , 10063882 , 10088670 , 10113580 , 10138614 , 10163772 , 10189055 , 10214464 , 10240000 , + 10265664 , 10291457 , 10317380 , 10343434 , 10369620 , 10395939 , 10422392 , 10448980 , 10475703 , 10502564 , 10529563 , 10556701 , 10583979 , 10611399 , 10638961 , 10666667 , + 10694517 , 10722513 , 10750656 , 10778947 , 10807388 , 10835979 , 10864721 , 10893617 , 10922667 , 10951872 , 10981233 , 11010753 , 11040431 , 11070270 , 11100271 , 11130435 , + 11160763 , 11191257 , 11221918 , 11252747 , 11283747 , 11314917 , 11346260 , 11377778 , 11409471 , 11441341 , 11473389 , 11505618 , 11538028 , 11570621 , 11603399 , 11636364 , + 11669516 , 11702857 , 11736390 , 11770115 , 11804035 , 11838150 , 11872464 , 11906977 , 11941691 , 11976608 , 12011730 , 12047059 , 12082596 , 12118343 , 12154303 , 12190476 , + 12226866 , 12263473 , 12300300 , 12337349 , 12374622 , 12412121 , 12449848 , 12487805 , 12525994 , 12564417 , 12603077 , 12641975 , 12681115 , 12720497 , 12760125 , 12800000 , + 12840125 , 12880503 , 12921136 , 12962025 , 13003175 , 13044586 , 13086262 , 13128205 , 13170418 , 13212903 , 13255663 , 13298701 , 13342020 , 13385621 , 13429508 , 13473684 , + 13518152 , 13562914 , 13607973 , 13653333 , 13698997 , 13744966 , 13791246 , 13837838 , 13884746 , 13931973 , 13979522 , 14027397 , 14075601 , 14124138 , 14173010 , 14222222 , + 14271777 , 14321678 , 14371930 , 14422535 , 14473498 , 14524823 , 14576512 , 14628571 , 14681004 , 14733813 , 14787004 , 14840580 , 14894545 , 14948905 , 15003663 , 15058824 , + 15114391 , 15170370 , 15226766 , 15283582 , 15340824 , 15398496 , 15456604 , 15515152 , 15574144 , 15633588 , 15693487 , 15753846 , 15814672 , 15875969 , 15937743 , 16000000 , + 16031311 , 16062745 , 16094303 , 16125984 , 16157791 , 16189723 , 16221782 , 16253968 , 16286282 , 16318725 , 16351297 , 16384000 , 16416834 , 16449799 , 16482897 , 16516129 , + 16549495 , 16582996 , 16616633 , 16650407 , 16684318 , 16718367 , 16752556 , 16786885 , 16821355 , 16855967 , 16890722 , 16925620 , 16960663 , 16995851 , 17031185 , 17066667 , + 17102296 , 17138075 , 17174004 , 17210084 , 17246316 , 17282700 , 17319239 , 17355932 , 17392781 , 17429787 , 17466951 , 17504274 , 17541756 , 17579399 , 17617204 , 17655172 , + 17693305 , 17731602 , 17770065 , 17808696 , 17847495 , 17886463 , 17925602 , 17964912 , 18004396 , 18044053 , 18083885 , 18123894 , 18164080 , 18204444 , 18244989 , 18285714 , + 18326622 , 18367713 , 18408989 , 18450450 , 18492099 , 18533937 , 18575964 , 18618182 , 18660592 , 18703196 , 18745995 , 18788991 , 18832184 , 18875576 , 18919169 , 18962963 , + 19006961 , 19051163 , 19095571 , 19140187 , 19185012 , 19230047 , 19275294 , 19320755 , 19366430 , 19412322 , 19458432 , 19504762 , 19551313 , 19598086 , 19645084 , 19692308 , + 19739759 , 19787440 , 19835351 , 19883495 , 19931873 , 19980488 , 20029340 , 20078431 , 20127764 , 20177340 , 20227160 , 20277228 , 20327543 , 20378109 , 20428928 , 20480000 , + 20531328 , 20582915 , 20634761 , 20686869 , 20739241 , 20791878 , 20844784 , 20897959 , 20951407 , 21005128 , 21059126 , 21113402 , 21167959 , 21222798 , 21277922 , 21333333 , + 21389034 , 21445026 , 21501312 , 21557895 , 21614776 , 21671958 , 21729443 , 21787234 , 21845333 , 21903743 , 21962466 , 22021505 , 22080863 , 22140541 , 22200542 , 22260870 , + 22321526 , 22382514 , 22443836 , 22505495 , 22567493 , 22629834 , 22692521 , 22755556 , 22818942 , 22882682 , 22946779 , 23011236 , 23076056 , 23141243 , 23206799 , 23272727 , + 23339031 , 23405714 , 23472779 , 23540230 , 23608069 , 23676301 , 23744928 , 23813953 , 23883382 , 23953216 , 24023460 , 24094118 , 24165192 , 24236686 , 24308605 , 24380952 , + 24453731 , 24526946 , 24600601 , 24674699 , 24749245 , 24824242 , 24899696 , 24975610 , 25051988 , 25128834 , 25206154 , 25283951 , 25362229 , 25440994 , 25520249 , 25600000 , + 25680251 , 25761006 , 25842271 , 25924051 , 26006349 , 26089172 , 26172524 , 26256410 , 26340836 , 26425806 , 26511327 , 26597403 , 26684039 , 26771242 , 26859016 , 26947368 , + 27036304 , 27125828 , 27215947 , 27306667 , 27397993 , 27489933 , 27582492 , 27675676 , 27769492 , 27863946 , 27959044 , 28054795 , 28151203 , 28248276 , 28346021 , 28444444 , + 28543554 , 28643357 , 28743860 , 28845070 , 28946996 , 29049645 , 29153025 , 29257143 , 29362007 , 29467626 , 29574007 , 29681159 , 29789091 , 29897810 , 30007326 , 30117647 , + 30228782 , 30340741 , 30453532 , 30567164 , 30681648 , 30796992 , 30913208 , 31030303 , 31148289 , 31267176 , 31386973 , 31507692 , 31629344 , 31751938 , 31875486 , 32000000 , + 32062622 , 32125490 , 32188605 , 32251969 , 32315582 , 32379447 , 32443564 , 32507937 , 32572565 , 32637450 , 32702595 , 32768000 , 32833667 , 32899598 , 32965795 , 33032258 , + 33098990 , 33165992 , 33233266 , 33300813 , 33368635 , 33436735 , 33505112 , 33573770 , 33642710 , 33711934 , 33781443 , 33851240 , 33921325 , 33991701 , 34062370 , 34133333 , + 34204593 , 34276151 , 34348008 , 34420168 , 34492632 , 34565401 , 34638478 , 34711864 , 34785563 , 34859574 , 34933902 , 35008547 , 35083512 , 35158798 , 35234409 , 35310345 , + 35386609 , 35463203 , 35540130 , 35617391 , 35694989 , 35772926 , 35851204 , 35929825 , 36008791 , 36088106 , 36167770 , 36247788 , 36328160 , 36408889 , 36489978 , 36571429 , + 36653244 , 36735426 , 36817978 , 36900901 , 36984199 , 37067873 , 37151927 , 37236364 , 37321185 , 37406393 , 37491991 , 37577982 , 37664368 , 37751152 , 37838337 , 37925926 , + 38013921 , 38102326 , 38191142 , 38280374 , 38370023 , 38460094 , 38550588 , 38641509 , 38732861 , 38824645 , 38916865 , 39009524 , 39102625 , 39196172 , 39290168 , 39384615 , + 39479518 , 39574879 , 39670702 , 39766990 , 39863747 , 39960976 , 40058680 , 40156863 , 40255528 , 40354680 , 40454321 , 40554455 , 40655087 , 40756219 , 40857855 , 40960000 , + 41062657 , 41165829 , 41269521 , 41373737 , 41478481 , 41583756 , 41689567 , 41795918 , 41902813 , 42010256 , 42118252 , 42226804 , 42335917 , 42445596 , 42555844 , 42666667 , + 42778068 , 42890052 , 43002625 , 43115789 , 43229551 , 43343915 , 43458886 , 43574468 , 43690667 , 43807487 , 43924933 , 44043011 , 44161725 , 44281081 , 44401084 , 44521739 , + 44643052 , 44765027 , 44887671 , 45010989 , 45134986 , 45259669 , 45385042 , 45511111 , 45637883 , 45765363 , 45893557 , 46022472 , 46152113 , 46282486 , 46413598 , 46545455 , + 46678063 , 46811429 , 46945559 , 47080460 , 47216138 , 47352601 , 47489855 , 47627907 , 47766764 , 47906433 , 48046921 , 48188235 , 48330383 , 48473373 , 48617211 , 48761905 , + 48907463 , 49053892 , 49201201 , 49349398 , 49498489 , 49648485 , 49799392 , 49951220 , 50103976 , 50257669 , 50412308 , 50567901 , 50724458 , 50881988 , 51040498 , 51200000 , + 51360502 , 51522013 , 51684543 , 51848101 , 52012698 , 52178344 , 52345048 , 52512821 , 52681672 , 52851613 , 53022654 , 53194805 , 53368078 , 53542484 , 53718033 , 53894737 , + 54072607 , 54251656 , 54431894 , 54613333 , 54795987 , 54979866 , 55164983 , 55351351 , 55538983 , 55727891 , 55918089 , 56109589 , 56302405 , 56496552 , 56692042 , 56888889 , + 57087108 , 57286713 , 57487719 , 57690141 , 57893993 , 58099291 , 58306050 , 58514286 , 58724014 , 58935252 , 59148014 , 59362319 , 59578182 , 59795620 , 60014652 , 60235294 , + 60457565 , 60681481 , 60907063 , 61134328 , 61363296 , 61593985 , 61826415 , 62060606 , 62296578 , 62534351 , 62773946 , 63015385 , 63258687 , 63503876 , 63750973 , 64000000 diff --git a/src/sound/saasound/SAAFreq.h b/src/sound/saasound/SAAFreq.h new file mode 100755 index 000000000..478754621 --- /dev/null +++ b/src/sound/saasound/SAAFreq.h @@ -0,0 +1,72 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAFreq.h: interface for the CSAAFreq class. +// Note about Samplerates: 0=44100, 1=22050; 2=11025 +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAAFREQ_H_INCLUDE +#define SAAFREQ_H_INCLUDE + +#include "defns.h" + +class CSAAFreq +{ +private: +#ifdef SAAFREQ_FIXED_CLOCKRATE + // 'load in' the data for the static frequency lookup table + // precomputed for a fixed clockrate + // See: tools/freqdat.py + const static unsigned long m_FreqTable[2048]; +#else + // we'll calculate the frequency lookup table at runtime. + static unsigned long m_FreqTable[2048]; + static unsigned long m_nClockRate; +#endif + + unsigned long m_nCounter; + unsigned long m_nAdd; + unsigned long m_nCounter_low; + unsigned int m_nOversample; + unsigned long m_nCounterLimit_low; + int m_nLevel; + + int m_nCurrentOffset; + int m_nCurrentOctave; + int m_nNextOffset; + int m_nNextOctave; + bool m_bIgnoreOffsetData; + bool m_bNewData; + bool m_bSync; + + unsigned long m_nSampleRate; + CSAANoise * const m_pcConnectedNoiseGenerator; + CSAAEnv * const m_pcConnectedEnvGenerator; + const int m_nConnectedMode; // 0 = nothing; 1 = envgenerator; 2 = noisegenerator + + void UpdateOctaveOffsetData(void); + void SetAdd(void); + +public: + CSAAFreq(CSAANoise * const pcNoiseGenerator, CSAAEnv * const pcEnvGenerator); + ~CSAAFreq(); + void SetFreqOffset(BYTE nOffset); + void SetFreqOctave(BYTE nOctave); + void _SetSampleRate(unsigned int nSampleRate); + void _SetOversample(unsigned int oversample); + void _SetClockRate(int nClockRate); + void Sync(bool bSync); + int Tick(void); + int Level(void) const; + +}; + +inline int CSAAFreq::Level(void) const +{ + if (m_bSync) + return 1; + + return m_nLevel; +} + +#endif // SAAFREQ_H_INCLUDE diff --git a/src/sound/saasound/SAAImpl.cpp b/src/sound/saasound/SAAImpl.cpp new file mode 100644 index 000000000..8545d3849 --- /dev/null +++ b/src/sound/saasound/SAAImpl.cpp @@ -0,0 +1,487 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAAImpl.cpp: implementation of the CSAASound class. +// the bones of the 'virtual SAA-1099' emulation +// +// the actual sound generation is carried out in the other classes; +// this class provides the output stage and the external interface only +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" + +#include "types.h" +#include "SAAImpl.h" +#include "defns.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSAASoundInternal::CSAASoundInternal() + : +m_nClockRate(EXTERNAL_CLK_HZ), +m_bHighpass(false), +m_nSampleRate(SAMPLE_RATE_HZ), +m_nOversample(DEFAULT_OVERSAMPLE), +m_uParam(0), +m_uParamRate(0), +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) +m_nDebugSample(0), +#endif +m_chip() +{ +#ifdef USE_CONFIG_FILE + m_Config.ReadConfig(); +#endif + +#if defined(DEBUGSAA) + m_dbgfile.open(_T(DEBUG_SAA_REGISTER_LOG), std::ios_base::out); + m_pcmfile.open(_T(DEBUG_SAA_PCM_LOG), std::ios_base::out | std::ios_base::binary); +#elif defined(USE_CONFIG_FILE) + if (m_Config.m_bGenerateRegisterLogs) + m_dbgfile.open(m_Config.m_strRegisterLogPath, std::ios_base::out); + if (m_Config.m_bGeneratePcmLogs) + m_pcmfile.open(m_Config.m_strPcmOutputPath, std::ios_base::out | std::ios_base::binary); + + if (m_Config.m_bGeneratePcmLogs && m_Config.m_bGeneratePcmSeparateChannels) + { + for (int i = 0; i < 6; i++) + { + m_channel_pcmfile[i].open(m_Config.getChannelPcmOutputPath(i), std::ios_base::out | std::ios_base::binary); + } + } + + +#endif + // set parameters + // TODO support defaults and overrides from config file + // m_chip.SetSoundParameters(SAAP_FILTER | SAAP_11025 | SAAP_8BIT | SAAP_MONO); + // reset the virtual SAA + // m_chip.Clear(); + + m_chip._SetClockRate(m_nClockRate); + m_chip._SetOversample(m_nOversample); +} + +CSAASoundInternal::~CSAASoundInternal() +{ + // +} + +////////////////////////////////////////////////////////////////////// +// CSAASound members +////////////////////////////////////////////////////////////////////// + +void CSAASoundInternal::SetClockRate(unsigned int nClockRate) +{ + m_nClockRate = nClockRate; + m_chip._SetClockRate(m_nClockRate); +} + +void CSAASoundInternal::Clear(void) +{ + // reinitialises virtual SAA: + // sets reg 28 to 0x02; - sync and disabled + // sets regs 00-31 (except 28) to 0x00; + // sets reg 28 to 0x00; + // sets current reg to 0 + WriteAddressData(28,2); + for (int i=31; i>=0; i--) + { + if (i!=28) WriteAddressData(i,0); + } + WriteAddressData(28,0); + WriteAddress(0); +} + +void CSAASoundInternal::WriteData(BYTE nData) +{ + // originated from an OUT 255,d call + m_chip._WriteData(nData); +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) +#ifdef USE_CONFIG_FILE + if (m_Config.m_bGenerateRegisterLogs) + { +#endif + m_dbgfile << m_nDebugSample << " " << (int)m_chip._ReadAddress() << ":" << (int)nData << std::endl; +#ifdef USE_CONFIG_FILE + } +#endif +#endif +} + +void CSAASoundInternal::WriteAddress(BYTE nReg) +{ + // originated from an OUT 511,r call + m_chip._WriteAddress(nReg); +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) +#ifdef USE_CONFIG_FILE + if (m_Config.m_bGenerateRegisterLogs) + { +#endif + m_dbgfile << m_nDebugSample << " " << (int)nReg << ":"; + if (nReg==24) + { + m_dbgfile << ""; + } + else if (nReg==25) + { + m_dbgfile << ""; + } + m_dbgfile << std::endl; +#ifdef USE_CONFIG_FILE + } +#endif +#endif +} + +void CSAASoundInternal::WriteAddressData(BYTE nReg, BYTE nData) +{ + // performs WriteAddress(nReg) followed by WriteData(nData) + m_chip._WriteAddress(nReg); + m_chip._WriteData(nData); +} + +#if 1 +BYTE CSAASoundInternal::ReadAddress(void) +{ + // Not a real hardware function of the SAA-1099, which is write-only + return(m_chip._ReadAddress()); +} +#else +BYTE CSAASoundInternal::ReadAddress(void) +{ + // Not a real hardware function of the SAA-1099, which is write-only + return(0); +} +#endif + +void CSAASoundInternal::SetSoundParameters(SAAPARAM uParam) +{ + // set samplerate properties from uParam (deprecated but still supported) + unsigned int nSampleRate = m_nSampleRate; + switch (uParam & SAAP_MASK_SAMPLERATE) + { + case SAAP_44100: + nSampleRate = 44100; + m_uParamRate = (m_uParamRate & ~SAAP_MASK_SAMPLERATE) | SAAP_44100; + break; + case SAAP_22050: + nSampleRate = 22050; + m_uParamRate = (m_uParamRate & ~SAAP_MASK_SAMPLERATE) | SAAP_22050; + break; + case SAAP_11025: + nSampleRate = 11025; + m_uParamRate = (m_uParamRate & ~SAAP_MASK_SAMPLERATE) | SAAP_11025; + break; + case 0:// change nothing! + default: + break; + } + + if (nSampleRate != m_nSampleRate) + { + m_nSampleRate = nSampleRate; + m_chip._SetSampleRate(m_nSampleRate); + } + + // set filter properties from uParam + m_uParam = (m_uParam & ~SAAP_MASK_FILTER) | (uParam & SAAP_MASK_FILTER); + + m_bHighpass=true; +} + +void CSAASoundInternal::SetSampleRate(unsigned int nSampleRate) +{ + if (nSampleRate != m_nSampleRate) + { + m_nSampleRate = nSampleRate; + m_chip._SetSampleRate(m_nSampleRate); + } +} + +void CSAASoundInternal::SetOversample(unsigned int nOversample) +{ + if (nOversample != m_nOversample) + { + m_nOversample = nOversample; + m_chip._SetOversample(m_nOversample); + } +} + +SAAPARAM CSAASoundInternal::GetCurrentSoundParameters(void) +{ + return m_uParam | m_uParamRate; +} + +unsigned short CSAASoundInternal::GetCurrentBytesPerSample(void) +{ + // 16 bit stereo => 4 bytes per sample + return 4; +} + +/*static*/ unsigned short CSAASound::GetBytesPerSample(SAAPARAM uParam) +{ + // 16 bit stereo => 4 bytes per sample + switch (uParam & (SAAP_MASK_CHANNELS | SAAP_MASK_BITDEPTH)) + { + case SAAP_STEREO | SAAP_16BIT: + return 4; + default: + return 0; + } +} + +unsigned long CSAASoundInternal::GetCurrentSampleRate(void) +{ + return CSAASound::GetSampleRate(m_uParamRate); +} + +/*static*/ unsigned long CSAASound::GetSampleRate(SAAPARAM uParam) // static member function +{ + switch (uParam & SAAP_MASK_SAMPLERATE) + { + case SAAP_11025: + return 11025; + case SAAP_22050: + return 22050; + case SAAP_44100: + return 44100; + default: + return 0; + } +} + +#if defined(USE_CONFIG_FILE) || (defined(DEFAULT_BOOST) && DEFAULT_BOOST>1) +#define DO_BOOST +#endif + +void scale_for_output(unsigned int left_input, unsigned int right_input, + double oversample_scalar, bool highpass, double boost, + double& filterout_z1_left, double& filterout_z1_right, + BYTE* &pBuffer) +{ + double float_left = (double)left_input; + double float_right = (double)right_input; + float_left /= oversample_scalar; + float_right /= oversample_scalar; + + // scale output into good range + float_left *= DEFAULT_UNBOOSTED_MULTIPLIER; + float_right *= DEFAULT_UNBOOSTED_MULTIPLIER; + + if (highpass) + { + /* cutoff = 5 Hz (say) + const double b1 = exp(-2.0 * M_PI * (Fc/Fs)) + const double a0 = 1.0 - b1; + */ + const double b1 = 0.99928787; + const double a0 = 1.0 - b1; + + filterout_z1_left = float_left * a0 + filterout_z1_left * b1; + filterout_z1_right = float_right * a0 + filterout_z1_right * b1; + float_left -= filterout_z1_left; + float_right -= filterout_z1_right; + } + + // multiply by boost, if defined +#if defined(DO_BOOST) + float_left *= boost; + float_right *= boost; +#endif + // convert to 16-bit signed range with hard clipping + signed short left_output = (signed short)(float_left > 32767 ? 32767 : float_left < -32768 ? -32768 : float_left); + signed short right_output = (signed short)(float_right > 32767 ? 32767 : float_right < -32768 ? -32768 : float_right); + + *pBuffer++ = left_output & 0x00ff; + *pBuffer++ = (left_output >> 8) & 0x00ff; + *pBuffer++ = right_output & 0x00ff; + *pBuffer++ = (right_output >> 8) & 0x00ff; +} + +void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples) +{ + unsigned int left_mixed, right_mixed; + static double filterout_z1_left_mixed = 0, filterout_z1_right_mixed = 0; + +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) + BYTE* pBufferStart = pBuffer; + unsigned long nTotalSamples = nSamples; +#endif + +#if defined(DO_BOOST) +#if defined(USE_CONFIG_FILE) + double nBoost = m_Config.m_nBoost; +#else + double nBoost = DEFAULT_BOOST; +#endif +#else + double nBoost = 1.0; +#endif + + double oversample = double(1 << m_nOversample); + +#if defined(USE_CONFIG_FILE) + static double filterout_z1_left_0 = 0, filterout_z1_right_0 = 0; + static double filterout_z1_left_1 = 0, filterout_z1_right_1 = 0; + static double filterout_z1_left_2 = 0, filterout_z1_right_2 = 0; + static double filterout_z1_left_3 = 0, filterout_z1_right_3 = 0; + static double filterout_z1_left_4 = 0, filterout_z1_right_4 = 0; + static double filterout_z1_left_5 = 0, filterout_z1_right_5 = 0; + + if (m_Config.m_bGeneratePcmLogs && m_Config.m_bGeneratePcmSeparateChannels) + { + unsigned int left0, right0, left1, right1, left2, right2, left3, right3, left4, right4, left5, right5; + BYTE* pChannelBufferPtr[6] = { m_pChannelBuffer[0], m_pChannelBuffer[1], m_pChannelBuffer[2], m_pChannelBuffer[3], m_pChannelBuffer[4], m_pChannelBuffer[5] }; + + while (nSamples--) + { + m_chip._TickAndOutputSeparate(left_mixed, right_mixed, + left0, right0, + left1, right1, + left2, right2, + left3, right3, + left4, right4, + left5, right5); + scale_for_output(left_mixed, right_mixed, oversample, m_bHighpass, nBoost, filterout_z1_left_mixed, filterout_z1_right_mixed, pBuffer); + + // and the separate channels + scale_for_output(left0, right0, oversample, m_bHighpass, nBoost, filterout_z1_left_0, filterout_z1_right_0, pChannelBufferPtr[0]); + scale_for_output(left1, right1, oversample, m_bHighpass, nBoost, filterout_z1_left_1, filterout_z1_right_1, pChannelBufferPtr[1]); + scale_for_output(left2, right2, oversample, m_bHighpass, nBoost, filterout_z1_left_2, filterout_z1_right_2, pChannelBufferPtr[2]); + scale_for_output(left3, right3, oversample, m_bHighpass, nBoost, filterout_z1_left_3, filterout_z1_right_3, pChannelBufferPtr[3]); + scale_for_output(left4, right4, oversample, m_bHighpass, nBoost, filterout_z1_left_4, filterout_z1_right_4, pChannelBufferPtr[4]); + scale_for_output(left5, right5, oversample, m_bHighpass, nBoost, filterout_z1_left_5, filterout_z1_right_5, pChannelBufferPtr[5]); + + // flush channel output PCM buffers when full + if (pChannelBufferPtr[0] >= m_pChannelBuffer[0] + CHANNEL_BUFFER_SIZE) + { + for (int i = 0; i < 6; i++) + { + m_channel_pcmfile[i].write((const char*)m_pChannelBuffer[i], CHANNEL_BUFFER_SIZE); + pChannelBufferPtr[i] = m_pChannelBuffer[i]; + } + } + } + // flush remaining channel PCM output data + if (pChannelBufferPtr[0] >= m_pChannelBuffer[0]) + { + for (int i = 0; i < 6; i++) + { + m_channel_pcmfile[i].write((const char*)m_pChannelBuffer[i], pChannelBufferPtr[i]-m_pChannelBuffer[i]); + } + } + } + else + { +#endif + while (nSamples--) + { + m_chip._TickAndOutputStereo(left_mixed, right_mixed); + scale_for_output(left_mixed, right_mixed, oversample, m_bHighpass, nBoost, filterout_z1_left_mixed, filterout_z1_right_mixed, pBuffer); + } + +#if defined(USE_CONFIG_FILE) + } +#endif + +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) +#ifdef USE_CONFIG_FILE + if (m_Config.m_bGeneratePcmLogs) + { +#endif + m_pcmfile.write((const char *)pBufferStart, nTotalSamples * (unsigned long)GetCurrentBytesPerSample()); + m_nDebugSample += nTotalSamples; +#ifdef USE_CONFIG_FILE + } +#endif + +#endif +} + +/////////////////////////////////////////////////////// + +LPCSAASOUND SAAAPI CreateCSAASound(void) +{ + return (new CSAASoundInternal); +} + +void SAAAPI DestroyCSAASound(LPCSAASOUND object) +{ + delete (object); +} + + +/* thoughts on lowpass filtering as part of oversampling. +I tried this and really it didn't seem to make a lot of (audible) difference. + +// lowpass oversample filter adds complexity and not particularly audibly better than simple averaging. +// use_lowpass_oversample_filter_average_output adds an additional averaging step to the output of the oversample +// filter. this seems critical, because without this, the raw output of the lowpass filter is full of aliases +// If use_lowpass_oversample_filter is False, then the _average_output flag is ignored. +// Default, use_lowpass_oversample_filter is False, it sounds just fine really. + +//#define USE_LOWPASS_OVERSAMPLE_FILTER +#undef USE_LOWPASS_OVERSAMPLE_FILTER +//#define USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT +#undef USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT + +#ifdef USE_LOWPASS_OVERSAMPLE_FILTER +static double oversample_lp_filterout_z1_left_stages[10] = { 0,0,0,0,0,0,0,0,0,0 }; +static double oversample_lp_filterout_z1_right_stages[10] = { 0,0,0,0,0,0,0,0,0,0 }; +double averaged_filterout_left = 0.0, averaged_filterout_right = 0.0; +const int nStages = 10; +for (int i = 0; i < 1 << m_nOversample; i++) +{ + Noise[0]->Tick(); + Noise[1]->Tick(); + f_left = f_right = 0; + for (int c = 0; c < 6; c++) + { + Amp[c]->TickAndOutputStereo(temp_left, temp_right); + f_left += (double)temp_left; + f_right += (double)temp_right; + } + // apply lowpass here. + // HACK: ASSUME m_nOversample is 64 (I was experimenting only using the 64x oversample anyway) + // therefore Fs = 44100*64 + // let's set Fc = 10kHz + // so Fc/Fs = 0.00354308390022675736961451247166 + // const double b1 = exp(-2.0 * M_PI * (Fc/Fs)) + // const double a0 = 1.0 - b1; + // const double b1 = 0.9779841137335348363722276130195; + const double b1 = 0.977; + const double a0 = 1.0 - b1; + + oversample_lp_filterout_z1_left_stages[0] = f_left * a0 + oversample_lp_filterout_z1_left_stages[0] * b1; + for (int stage = 1; stage < nStages; stage++) + oversample_lp_filterout_z1_left_stages[stage] = oversample_lp_filterout_z1_left_stages[stage - 1] * a0 + oversample_lp_filterout_z1_left_stages[stage] * b1; + oversample_lp_filterout_z1_right_stages[0] = f_right * a0 + oversample_lp_filterout_z1_right_stages[0] * b1; + for (int stage = 1; stage < nStages; stage++) + oversample_lp_filterout_z1_right_stages[stage] = oversample_lp_filterout_z1_right_stages[stage - 1] * a0 + oversample_lp_filterout_z1_right_stages[stage] * b1; + +#ifdef USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT + averaged_filterout_left += oversample_lp_filterout_4z1_left; + averaged_filterout_right += oversample_lp_filterout_4z1_right; +#endif +} + +// by the end of this loop we will have computed the oversample lowpass filter m_nOversample times +// and yielded exactly ONE sample output. +#ifdef USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT +f_left = averaged_filterout_left / (1 << m_nOversample); +f_right = averaged_filterout_right / (1 << m_nOversample); +#else +f_left = oversample_lp_filterout_z1_left_stages[nStages - 1]; +f_right = oversample_lp_filterout_z1_right_stages[nStages - 1]; +#endif + +#else + // do the simple 1/N averaging which is easier and sounds good enough + +#endif + +*/ + diff --git a/src/sound/saasound/SAAImpl.h b/src/sound/saasound/SAAImpl.h new file mode 100755 index 000000000..61fa79c58 --- /dev/null +++ b/src/sound/saasound/SAAImpl.h @@ -0,0 +1,75 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// This is the internal implementation (header file) of the SAASound object. +// This is done so that the external interface to the object always stays the same +// (SAASound.h) even though the internal object can change +// .. Meaning future releases don't require relinking everyone elses code against +// the updated saasound stuff +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAAIMPL_H_INCLUDED +#define SAAIMPL_H_INCLUDED + +#include "SAASound.h" +#include "SAADevice.h" +#ifdef USE_CONFIG_FILE +#include "SAAConfig.h" +#endif + +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) +#include +#include +#include + +#if defined(USE_CONFIG_FILE) +const int CHANNEL_BUFFER_SIZE=1024; +#endif +#endif + +class CSAASoundInternal : public CSAASound +{ +private: + CSAADevice m_chip; + int m_uParam, m_uParamRate; + unsigned int m_nClockRate; + unsigned int m_nSampleRate; + unsigned int m_nOversample; + bool m_bHighpass; +#ifdef USE_CONFIG_FILE + SAAConfig m_Config; +#endif +#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) + unsigned long m_nDebugSample; + std::ofstream m_dbgfile, m_pcmfile; +#if defined(USE_CONFIG_FILE) + std::ofstream m_channel_pcmfile[6]; + BYTE m_pChannelBuffer[6][CHANNEL_BUFFER_SIZE]; +#endif +#endif + +public: + CSAASoundInternal(); + ~CSAASoundInternal(); + + void SetClockRate(unsigned int nClockRate); + void SetSampleRate(unsigned int nClockRate); + void SetOversample(unsigned int nOversample); + void SetSoundParameters(SAAPARAM uParam); + void WriteAddress(BYTE nReg); + void WriteData(BYTE nData); + void WriteAddressData(BYTE nReg, BYTE nData); + BYTE ReadAddress(void); + void Clear(void); + + SAAPARAM GetCurrentSoundParameters(void); + unsigned long GetCurrentSampleRate(void); + static unsigned long GetSampleRate(SAAPARAM uParam); + unsigned short GetCurrentBytesPerSample(void); + static unsigned short GetBytesPerSample(SAAPARAM uParam); + + void GenerateMany(BYTE * pBuffer, unsigned long nSamples); + +}; + +#endif // SAAIMPL_H_INCLUDED diff --git a/src/sound/saasound/SAANoise.cpp b/src/sound/saasound/SAANoise.cpp new file mode 100755 index 000000000..895a5a103 --- /dev/null +++ b/src/sound/saasound/SAANoise.cpp @@ -0,0 +1,180 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAANoise.cpp: implementation of the CSAANoise class. +// One noise generator +// +// After construction, it's important to SetSampleRate before +// trying to use the generator. +// (Just because the CSAANoise object has a default samplerate +// doesn't mean you should rely on it) +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" + +#include "types.h" +#include "SAANoise.h" +#include "defns.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSAANoise::CSAANoise() +: +m_nCounter(0), +m_nCounter_low(0), +m_nCounterLimit_low(1), +m_nOversample(0), +m_bSync(false), +m_nSampleRate(SAMPLE_RATE_HZ), +m_nSourceMode(0), +m_nRand(1) +{ + _SetClockRate(EXTERNAL_CLK_HZ); + m_nAdd = m_nAddBase; +} + +CSAANoise::CSAANoise(unsigned long seed) +: +m_nCounter(0), +m_nCounter_low(0), +m_nCounterLimit_low(1), +m_nOversample(0), +m_bSync(false), +m_nSampleRate(SAMPLE_RATE_HZ), +m_nSourceMode(0), +m_nRand(seed) +{ + _SetClockRate(EXTERNAL_CLK_HZ); + m_nAdd = m_nAddBase; +} + +CSAANoise::~CSAANoise() +{ + // Nothing to do +} + +void CSAANoise::_SetClockRate(int nClockRate) +{ + // at 8MHz the clock rate is 31.250kHZ + // This is simply the clock rate divided by 256 i.e. 2^8 + // We then shift this by 2^12 (like the Freq) for better + // period accuracy. So that's the same as shifting by (12-8) + m_nAddBase = nClockRate << (12 - 8); +} + +void CSAANoise::Seed(unsigned long seed) +{ + m_nRand = seed; +} + +void CSAANoise::SetSource(int nSource) +{ + m_nSourceMode = nSource; + m_nAdd = m_nAddBase >> m_nSourceMode; +} + +void CSAANoise::Trigger(void) +{ + // Trigger only does anything useful when we're + // clocking from the frequency generator - i.e + // if bUseFreqGen = true (i.e. SourceMode = 3) + + // So if we're clocking from the noise generator + // clock (ie, SourceMode = 0, 1 or 2) then do nothing + +// No point actually checking m_bSync here ... because if sync is true, +// then frequency generators won't actually be generating Trigger pulses +// so we wouldn't even get here! + // EXCEPT - cool edge case: if sync is set, then actually the Noise Generator + // is triggered on EVERY CLOCK PULSE (i.e. 8MHz noise). So indeed it is correct + // to not check for sync here. NEEDS TEST CASE. + + if (m_nSourceMode == 3) + { + ChangeLevel(); + } +} + +void CSAANoise::Tick(void) +{ + // Tick only does anything useful when we're + // clocking from the noise generator clock + // (ie, SourceMode = 0, 1 or 2) + + // So, if SourceMode = 3 (ie, we're clocking from a + // frequency generator ==> bUseFreqGen = true) + // then do nothing + if ( (!m_bSync) && (m_nSourceMode!=3) ) + { + m_nCounter += m_nAdd; + while (m_nCounter >= (m_nSampleRate<<12)) + { + m_nCounter -= (m_nSampleRate<<12); + m_nCounter_low++; + if (m_nCounter_low >= m_nCounterLimit_low) + { + m_nCounter_low = 0; + ChangeLevel(); + } + } + } +} + +void CSAANoise::Sync(bool bSync) +{ + if (bSync) + { + m_nCounter = 0; + m_nCounter_low = 0; + } + m_bSync = bSync; +} + + +void CSAANoise::_SetSampleRate(int nSampleRate) +{ + m_nSampleRate = nSampleRate; +} + + +void CSAANoise::_SetOversample(unsigned int oversample) +{ + // oversample is a power of 2 i.e. + // if oversample == 2 then 4x oversample + // if oversample == 6 then 64x oversample + if (oversample < m_nOversample) + { + m_nCounter_low <<= (m_nOversample - oversample); + } + else + { + m_nCounter_low >>= (oversample - m_nOversample); + } + + m_nCounterLimit_low = 1<> 1) ^ 0x20400; + } + else + { + m_nRand >>= 1; + } +} diff --git a/src/sound/saasound/SAANoise.h b/src/sound/saasound/SAANoise.h new file mode 100755 index 000000000..61a65dee8 --- /dev/null +++ b/src/sound/saasound/SAANoise.h @@ -0,0 +1,54 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAANoise.h: interface for the CSAANoise class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAANOISE_H_INCLUDED +#define SAANOISE_H_INCLUDED + +class CSAANoise +{ +private: + unsigned long m_nCounter; + unsigned long m_nAdd; + unsigned long m_nCounter_low; + unsigned int m_nOversample; + unsigned long m_nCounterLimit_low; + bool m_bSync; // see description of "SYNC" bit of register 28 + unsigned long m_nSampleRate; // = 44100 when RateMode=0, for example + int m_nSourceMode; + unsigned long m_nAddBase; // nAdd for 31.25 kHz noise at 44.1 kHz samplerate + + // pseudo-random number generator + unsigned long m_nRand; + + void ChangeLevel(void); + + +public: + CSAANoise(); + CSAANoise(unsigned long seed); + ~CSAANoise(); + + void SetSource(int nSource); + void Trigger(void); + void _SetSampleRate(int nSampleRate); + void _SetOversample(unsigned int oversample); + void _SetClockRate(int nClockRate); + void Seed(unsigned long seed); + + void Tick(void); + int Level(void) const; + void Sync(bool bSync); + +}; + +inline int CSAANoise::Level(void) const +{ + // returns 0 or 1 + return (m_nRand & 0x00000001); +} + + +#endif // SAANOISE_H_INCLUDED diff --git a/src/sound/saasound/SAASndC.cpp b/src/sound/saasound/SAASndC.cpp new file mode 100755 index 000000000..9af0d76e7 --- /dev/null +++ b/src/sound/saasound/SAASndC.cpp @@ -0,0 +1,100 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// Thanks to this file (and associated header file) you can now +// use CSAASound from within a standard 'C' program +// +////////////////////////////////////////////////////////////////////// + +#include "SAASound.h" +#include "types.h" +#include "SAAEnv.h" +#include "SAANoise.h" +#include "SAAFreq.h" +#include "SAAAmp.h" +#include "SAASound.h" +#include "SAAImpl.h" + +SAASND SAAAPI newSAASND(void) +{ + return (SAASND)(new CSAASoundInternal()); +} + +void SAAAPI deleteSAASND(SAASND object) +{ + delete (LPCSAASOUND)(object); +} + +void SAAAPI SAASNDSetClockRate(SAASND object, unsigned int nClockRate) +{ + ((LPCSAASOUND)(object))->SetClockRate(nClockRate); +} + +void SAAAPI SAASNDSetSoundParameters(SAASND object, SAAPARAM uParam) +{ + ((LPCSAASOUND)(object))->SetSoundParameters(uParam); +} + +void SAAAPI SAASNDWriteAddress(SAASND object, BYTE nReg) +{ + ((LPCSAASOUND)(object))->WriteAddress(nReg); +} + +void SAAAPI SAASNDWriteData(SAASND object, BYTE nData) +{ + ((LPCSAASOUND)(object))->WriteData(nData); +} + +void SAAAPI SAASNDWriteAddressData(SAASND object, BYTE nReg, BYTE nData) +{ + ((LPCSAASOUND)(object))->WriteAddressData(nReg, nData); +} + +void SAAAPI SAASNDClear(SAASND object) +{ + ((LPCSAASOUND)(object))->Clear(); +} + +SAAPARAM SAAAPI SAASNDGetCurrentSoundParameters(SAASND object) +{ + return ((LPCSAASOUND)(object))->GetCurrentSoundParameters(); +} + +unsigned short SAAAPI SAASNDGetCurrentBytesPerSample(SAASND object) +{ + return ((LPCSAASOUND)(object))->GetCurrentBytesPerSample(); +} + +unsigned short SAAAPI SAASNDGetBytesPerSample(SAAPARAM uParam) +{ + return CSAASound::GetBytesPerSample(uParam); +} + +unsigned long SAAAPI SAASNDGetCurrentSampleRate(SAASND object) +{ + return ((LPCSAASOUND)(object))->GetCurrentSampleRate(); +} + +unsigned long SAAAPI SAASNDGetSampleRate(SAAPARAM uParam) +{ + return CSAASound::GetSampleRate(uParam); +} + +void SAAAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples) +{ + ((LPCSAASOUND)(object))->GenerateMany(pBuffer, nSamples); +} + +void SAAAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate) +{ + return ((LPCSAASOUND)(object))->SetSampleRate(nSampleRate); +} + +void SAAAPI SAASNDSetOversample(SAASND object, unsigned int nOversample) +{ + return ((LPCSAASOUND)(object))->SetOversample(nOversample); +} + +BYTE SAAAPI SAASNDReadAddress(SAASND object) +{ + return ((LPCSAASOUND)(object))->ReadAddress(); +} diff --git a/src/sound/saasound/SAASndC.h b/src/sound/saasound/SAASndC.h new file mode 100644 index 000000000..c6fd65765 --- /dev/null +++ b/src/sound/saasound/SAASndC.h @@ -0,0 +1,102 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// ********** +// * PUBLIC * +// ********** +// +// SAASndC.h: "C-style" interface for the CSAASound class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAASNDC_H_INCLUDED +#define SAASNDC_H_INCLUDED + +#ifdef _MSC_VER +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +#endif + +#ifndef SAASOUND_H_INCLUDED + +// Parameters for use with SetSoundParameters, for example, +// SetSoundParameters(SAAP_NOFILTER | SAAP_44100 | SAAP_16BIT | SAAP_STEREO); +#define SAAP_FILTER_HIGHPASS_SIMPLE 0x00000400 +#define SAAP_FILTER_OVERSAMPLE64x 0x00000300 +#define SAAP_FILTER_OVERSAMPLE2x 0x00000200 +#define SAAP_FILTER SAAP_FILTER_OVERSAMPLE2x +#define SAAP_NOFILTER 0x00000100 +#define SAAP_44100 0x00000030 +#define SAAP_22050 0x00000020 +#define SAAP_11025 0x00000010 +#define SAAP_16BIT 0x0000000c +#define SAAP_8BIT 0x00000004 +#define SAAP_STEREO 0x00000003 +#define SAAP_MONO 0x00000001 + +// Bitmasks for use with GetCurrentSoundParameters, for example, +// unsigned long CurrentSampleRateParameter = GetCurrentSoundParameters() +#define SAAP_MASK_FILTER 0x00000f00 +#define SAAP_MASK_FILTER_HIGHPASS 0x00000c00 +#define SAAP_MASK_FILTER_OVERSAMPLE 0x00000300 +#define SAAP_MASK_SAMPLERATE 0x000000030 +#define SAAP_MASK_BITDEPTH 0x0000000c +#define SAAP_MASK_CHANNELS 0x00000003 + +typedef unsigned long SAAPARAM; + + +#ifndef BYTE +#define BYTE unsigned char +#endif + +#ifdef WIN32 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define EXTAPI __declspec(dllexport) WINAPI +#else // Win32 +#ifndef WINAPI +#define WINAPI /**/ +#endif +#define EXTAPI /**/ +#endif // Win32 + +#endif // SAASOUND_H_INCLUDED + +typedef void * SAASND; + +// the following are implemented as calls, etc, to a class. + +#ifdef __cplusplus +extern "C" { +#endif + +SAASND EXTAPI newSAASND(void); +void EXTAPI deleteSAASND(SAASND object); + +void EXTAPI SAASNDSetSoundParameters(SAASND object, SAAPARAM uParam); +void EXTAPI SAASNDWriteAddress(SAASND object, BYTE nReg); +void EXTAPI SAASNDWriteData(SAASND object, BYTE nData); +void EXTAPI SAASNDWriteAddressData(SAASND object, BYTE nReg, BYTE nData); +void EXTAPI SAASNDClear(SAASND object); +BYTE EXTAPI SAASNDReadAddress(SAASND object); + +SAAPARAM EXTAPI SAASNDGetCurrentSoundParameters(SAASND object); +unsigned short EXTAPI SAASNDGetCurrentBytesPerSample(SAASND object); +unsigned short EXTAPI SAASNDGetBytesPerSample(SAAPARAM uParam); +unsigned long EXTAPI SAASNDGetCurrentSampleRate(SAASND object); +unsigned long EXTAPI SAASNDGetSampleRate(SAAPARAM uParam); + +void EXTAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples); + +void EXTAPI SAASNDSetClockRate(SAASND object, unsigned int nClockRate); +void EXTAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate); +void EXTAPI SAASNDSetOversample(SAASND object, unsigned int nOversample); + + +#ifdef __cplusplus +}; // extern "C" +#endif + +#endif // SAASNDC_H_INCLUDED diff --git a/src/sound/saasound/SAASound.cpp b/src/sound/saasound/SAASound.cpp new file mode 100755 index 000000000..c5e33d862 --- /dev/null +++ b/src/sound/saasound/SAASound.cpp @@ -0,0 +1,13 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAASound.cpp - dummy function +// +////////////////////////////////////////////////////////////////////// + +#include + +// Provide something so the compiler doesn't optimise us out of existance +int SomeFunction () +{ + return 42; +} diff --git a/src/sound/saasound/SAASound.h b/src/sound/saasound/SAASound.h new file mode 100644 index 000000000..a5e9265ac --- /dev/null +++ b/src/sound/saasound/SAASound.h @@ -0,0 +1,130 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// SAASound.h: interface for the CSAASound class. +// +// This corresponds to the public (exported) DLL interface, so all +// APIs and client factory methods belong here. +// +// Compatibility notes : the intention is for this to be fully backwards +// compatible across minor and patch versions. Any backwards breaking changes +// should be reflected as a major version increment. New functionality can be added +// in minor versions so long as backwards compatiblity is maintained +// +// Version 3.3.0 (4th Dec 2018) +// +////////////////////////////////////////////////////////////////////// + +#ifndef SAASOUND_H_INCLUDED +#define SAASOUND_H_INCLUDED + +// define this if you want to output diagnostic text and PCM files +//#define DEBUGSAA + +// Parameters for use with SetSoundParameters, for example, +// SetSoundParameters(SAAP_NOFILTER | SAAP_44100 | SAA_16BIT | SAA_STEREO); +// SAAP_FILTER_HIGHPASS_SIMPLE can be ORd with SAAP_FILTER_OVERSAMPLE64x/2x +#define SAAP_FILTER_HIGHPASS_SIMPLE 0x00000400 +#define SAAP_FILTER_OVERSAMPLE64x 0x00000300 +#define SAAP_FILTER_OVERSAMPLE2x 0x00000200 +#define SAAP_FILTER SAAP_FILTER_OVERSAMPLE2x +#define SAAP_NOFILTER 0x00000100 +#define SAAP_44100 0x00000030 +#define SAAP_22050 0x00000020 +#define SAAP_11025 0x00000010 +#define SAAP_16BIT 0x0000000c +#define SAAP_8BIT 0x00000004 +#define SAAP_STEREO 0x00000003 +#define SAAP_MONO 0x00000001 + +// Bitmasks for use with GetCurrentSoundParameters, for example, +// unsigned long CurrentSampleRateParameter = GetCurrentSoundParameters() +#define SAAP_MASK_FILTER 0x00000f00 +#define SAAP_MASK_FILTER_HIGHPASS 0x00000c00 +#define SAAP_MASK_FILTER_OVERSAMPLE 0x00000300 +#define SAAP_MASK_SAMPLERATE 0x000000030 +#define SAAP_MASK_BITDEPTH 0x0000000c +#define SAAP_MASK_CHANNELS 0x00000003 + +typedef unsigned long SAAPARAM; + + +#ifndef BYTE +#define BYTE unsigned char +#endif + +#ifdef _WIN32 +#define SAAAPI _stdcall +#else +#define SAAAPI +#endif + + +#ifdef __cplusplus + +class CSAASound +{ +public: + virtual ~CSAASound() { } + + virtual void SetSoundParameters (SAAPARAM uParam) = 0; + virtual void WriteAddress (BYTE nReg) = 0; + virtual void WriteData (BYTE nData) = 0; + virtual void WriteAddressData (BYTE nReg, BYTE nData) = 0; + virtual void Clear () = 0; + virtual BYTE ReadAddress () = 0; + + virtual SAAPARAM GetCurrentSoundParameters () = 0; + virtual unsigned long GetCurrentSampleRate () = 0; + static unsigned long GetSampleRate (SAAPARAM uParam); + virtual unsigned short GetCurrentBytesPerSample () = 0; + static unsigned short GetBytesPerSample (SAAPARAM uParam); + + virtual void GenerateMany (BYTE * pBuffer, unsigned long nSamples) = 0; + + virtual void SetClockRate(unsigned int nClockRate) = 0; + virtual void SetSampleRate(unsigned int nSampleRate) = 0; + virtual void SetOversample(unsigned int nOversample) = 0; +}; + +typedef class CSAASound * LPCSAASOUND; + +LPCSAASOUND SAAAPI CreateCSAASound(void); +void SAAAPI DestroyCSAASound(LPCSAASOUND object); + +#endif // __cplusplus + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void * SAASND; + +// "C-style" interface for the CSAASound class +SAASND SAAAPI newSAASND(void); +void SAAAPI deleteSAASND(SAASND object); + +void SAAAPI SAASNDSetSoundParameters(SAASND object, SAAPARAM uParam); +void SAAAPI SAASNDWriteAddress(SAASND object, BYTE nReg); +void SAAAPI SAASNDWriteData(SAASND object, BYTE nData); +void SAAAPI SAASNDWriteAddressData(SAASND object, BYTE nReg, BYTE nData); +void SAAAPI SAASNDClear(SAASND object); + +SAAPARAM SAAAPI SAASNDGetCurrentSoundParameters(SAASND object); +unsigned short SAAAPI SAASNDGetCurrentBytesPerSample(SAASND object); +unsigned short SAAAPI SAASNDGetBytesPerSample(SAAPARAM uParam); +unsigned long SAAAPI SAASNDGetCurrentSampleRate(SAASND object); +unsigned long SAAAPI SAASNDGetSampleRate(SAAPARAM uParam); + +void SAAAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples); +void SAAAPI SAASNDSetClockRate(SAASND object, unsigned int nClockRate); +void SAAAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate); +void SAAAPI SAASNDSetOversample(SAASND object, unsigned int nOversample); + +BYTE SAAAPI SAASNDReadAddress(SAASND object); + +#ifdef __cplusplus +}; // extern "C" +#endif + +#endif // SAASOUND_H_INCLUDED diff --git a/src/sound/saasound/defns.h b/src/sound/saasound/defns.h new file mode 100644 index 000000000..e81d1c819 --- /dev/null +++ b/src/sound/saasound/defns.h @@ -0,0 +1,59 @@ +// Part of SAASound copyright 2020 Dave Hooper +// +// defns.h: compile-time configuration parameters +// +////////////////////////////////////////////////////////////////////// + +#ifndef DEFNS_H_INCLUDED +#define DEFNS_H_INCLUDED + +#define HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H +// using CMAKE +#include "saasound_cmake_config.h" +#else + +// initial default SAA1099 crystal clock rate in HZ (can be changed subsequently by calling SetClockRate) +#define EXTERNAL_CLK_HZ 8000000 + +// define SAAFREQ_FIXED_CLOCKRATE if the above external clock rate is the only supported clock rate +// i.e. only support a single compile-time clock rate (=> this also prevents using the SetClockRate method) +#undef SAAFREQ_FIXED_CLOCKRATE +// #define SAAFREQ_FIXED_CLOCKRATE + +// initial default sample rate (audio samplerate) +#define SAMPLE_RATE_HZ 44100 + +// initial default oversample (audio quality) recommend 0<=oversample<=6 +#define DEFAULT_OVERSAMPLE 6 + +// Whether to dump out a log of all register and value changes and raw output pcm +//#define DEBUGSAA +#undef DEBUGSAA + +// the (default) names of the register output and pcm output log files. +// If you're using a config file, you can change these (or, if you enable +// debugging via the config file settings, but leave the filenames unspecified, +// it will use these defaults) +#define DEBUG_SAA_REGISTER_LOG "debugsaa.txt" +#define DEBUG_SAA_PCM_LOG "debugsaa.pcm" +// Whether to include support for these debug logs via config file (only making +// sense if USE_CONFIG_FILE is also defined) + +// Whether to support a startup configuration file that is parsed at load time +// #undef USE_CONFIG_FILE +#define USE_CONFIG_FILE + +// and if so, what is its location +#ifdef USE_CONFIG_FILE +#define CONFIG_FILE_PATH "SAASound.cfg" +#endif // USE_CONFIG_FILE + +#define DEFAULT_UNBOOSTED_MULTIPLIER 11.35 + +#define DEFAULT_BOOST 1 + + +#endif // HAVE_CONFIG_H + +#endif // DEFNS_H_INCLUDED diff --git a/src/sound/saasound/resource.h b/src/sound/saasound/resource.h new file mode 100755 index 000000000..0b893bf3a --- /dev/null +++ b/src/sound/saasound/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by SAASound.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/sound/saasound/saasound_cmake_config.h b/src/sound/saasound/saasound_cmake_config.h new file mode 100644 index 000000000..da914a71b --- /dev/null +++ b/src/sound/saasound/saasound_cmake_config.h @@ -0,0 +1,14 @@ +#pragma once + +#define EXTERNAL_CLK_HZ 7159090 +/* #undef SAAFREQ_FIXED_CLOCKRATE */ +#define SAMPLE_RATE_HZ 44100 +#define DEFAULT_OVERSAMPLE 6 +#define DEFAULT_UNBOOSTED_MULTIPLIER 11.3 +#define DEFAULT_BOOST 1 +/* #undef DEBUGSAA */ +#define DEBUG_SAA_REGISTER_LOG "debugsaa.txt" +#define DEBUG_SAA_PCM_LOG "debugsaa.pcm" + +/* #undef USE_CONFIG_FILE */ +#define CONFIG_FILE_PATH "SAASound.cfg" diff --git a/src/sound/saasound/types.h b/src/sound/saasound/types.h new file mode 100755 index 000000000..4eb62f485 --- /dev/null +++ b/src/sound/saasound/types.h @@ -0,0 +1,34 @@ +// Part of SAASound copyright 1998-2018 Dave Hooper +// +// handy typedefs +// +////////////////////////////////////////////////////////////////////// + +#ifndef TYPES_H_INCLUDED +#define TYPES_H_INCLUDED + +#if defined(__i386__) || defined(WIN32) || \ + (defined(__alpha__) || defined(__alpha)) || \ + defined(__arm__) || \ + (defined(__mips__) && defined(__MIPSEL__)) +#else +#define __BIG_ENDIAN +#endif + + +#ifndef NULL +#define NULL 0 +#endif + +typedef struct +{ + int nNumberOfPhases; + bool bLooping; + int nLevels[2][2][16]; // [Resolution][Phase][Withinphase] +} ENVDATA; + +#ifdef WIN32 +extern "C" void _stdcall OutputDebugStringA (char*); +#endif + +#endif diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 66dff80f3..60165365d 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -8,6 +8,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "saasound/SAASound.h" #include <86box/snd_cms.h> #include <86box/sound.h> #include <86box/plat_unused.h> @@ -15,62 +16,13 @@ void cms_update(cms_t *cms) { - for (; cms->pos < sound_pos_global; cms->pos++) { - int16_t out_l = 0; - int16_t out_r = 0; - - for (uint8_t c = 0; c < 4; c++) { - switch (cms->noisetype[c >> 1][c & 1]) { - case 0: - cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 256; - break; - case 1: - cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 512; - break; - case 2: - cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 1024; - break; - case 3: - cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; - break; - - default: - break; - } - } - for (uint8_t c = 0; c < 2; c++) { - if (cms->regs[c][0x1C] & 1) { - for (uint8_t d = 0; d < 6; d++) { - if (cms->regs[c][0x14] & (1 << d)) { - if (cms->stat[c][d]) - out_l += (cms->vol[c][d][0] * 90); - if (cms->stat[c][d]) - out_r += (cms->vol[c][d][1] * 90); - cms->count[c][d] += cms->freq[c][d]; - if (cms->count[c][d] >= 24000) { - cms->count[c][d] -= 24000; - cms->stat[c][d] ^= 1; - } - } else if (cms->regs[c][0x15] & (1 << d)) { - if (cms->noise[c][d / 3] & 1) - out_l += (cms->vol[c][d][0] * 90); - if (cms->noise[c][d / 3] & 1) - out_r += (cms->vol[c][d][0] * 90); - } - } - for (uint8_t d = 0; d < 2; d++) { - cms->noisecount[c][d] += cms->noisefreq[c][d]; - while (cms->noisecount[c][d] >= 24000) { - cms->noisecount[c][d] -= 24000; - cms->noise[c][d] <<= 1; - if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40))) - cms->noise[c][d] |= 1; - } - } - } - } - cms->buffer[cms->pos << 1] = out_l; - cms->buffer[(cms->pos << 1) + 1] = out_r; + if (cms->pos < wavetable_pos_global) { + SAASNDGenerateMany(cms->saasound, (unsigned char*)&cms->buffer[cms->pos], wavetable_pos_global - cms->pos); + cms->pos = wavetable_pos_global; + } + if (cms->pos2 < wavetable_pos_global) { + SAASNDGenerateMany(cms->saasound2, (unsigned char*)&cms->buffer2[cms->pos2], wavetable_pos_global - cms->pos2); + cms->pos2 = wavetable_pos_global; } } @@ -87,6 +39,19 @@ cms_get_buffer(int32_t *buffer, int len, void *priv) cms->pos = 0; } +void +cms_get_buffer_2(int32_t *buffer, int len, void *priv) +{ + cms_t *cms = (cms_t *) priv; + + cms_update(cms); + + for (int c = 0; c < len * 2; c++) + buffer[c] += cms->buffer2[c]; + + cms->pos2 = 0; +} + void cms_write(uint16_t addr, uint8_t val, void *priv) { @@ -96,54 +61,19 @@ cms_write(uint16_t addr, uint8_t val, void *priv) switch (addr & 0xf) { case 0x1: /* SAA #1 Register Select Port */ - cms->addrs[0] = val & 31; + SAASNDWriteAddress(cms->saasound, val & 31); break; case 0x3: /* SAA #2 Register Select Port */ - cms->addrs[1] = val & 31; + SAASNDWriteAddress(cms->saasound2, val & 31); break; case 0x0: /* SAA #1 Data Port */ + cms_update(cms); + SAASNDWriteData(cms->saasound, val); + break; case 0x2: /* SAA #2 Data Port */ cms_update(cms); - cms->regs[chip][cms->addrs[chip] & 31] = val; - switch (cms->addrs[chip] & 31) { - case 0x00: - case 0x01: - case 0x02: /*Volume*/ - case 0x03: - case 0x04: - case 0x05: - voice = cms->addrs[chip] & 7; - cms->vol[chip][voice][0] = val & 0xf; - cms->vol[chip][voice][1] = val >> 4; - break; - case 0x08: - case 0x09: - case 0x0A: /*Frequency*/ - case 0x0B: - case 0x0C: - case 0x0D: - voice = cms->addrs[chip] & 7; - cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val; - cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); - break; - case 0x10: - case 0x11: - case 0x12: /*Octave*/ - voice = (cms->addrs[chip] & 3) << 1; - cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8); - cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4); - cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); - cms->freq[chip][voice + 1] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255)); - break; - case 0x16: /*Noise*/ - cms->noisetype[chip][0] = val & 3; - cms->noisetype[chip][1] = (val >> 4) & 3; - break; - - default: - break; - } + SAASNDWriteData(cms->saasound2, val); break; case 0x6: /* GameBlaster Write Port */ @@ -163,9 +93,9 @@ cms_read(uint16_t addr, void *priv) switch (addr & 0xf) { case 0x1: /* SAA #1 Register Select Port */ - return cms->addrs[0]; + return SAASNDReadAddress(cms->saasound); case 0x3: /* SAA #2 Register Select Port */ - return cms->addrs[1]; + return SAASNDReadAddress(cms->saasound2); case 0x4: /* GameBlaster Read port (Always returns 0x7F) */ return 0x7f; case 0xa: /* GameBlaster Read Port */ @@ -185,7 +115,12 @@ cms_init(UNUSED(const device_t *info)) uint16_t addr = device_get_config_hex16("base"); io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); - sound_add_handler(cms_get_buffer, cms); + cms->saasound = newSAASND(); + SAASNDSetSoundParameters(cms->saasound, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); + cms->saasound2 = newSAASND(); + SAASNDSetSoundParameters(cms->saasound2, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); + wavetable_add_handler(cms_get_buffer, cms); + wavetable_add_handler(cms_get_buffer_2, cms); return cms; } @@ -194,6 +129,9 @@ cms_close(void *priv) { cms_t *cms = (cms_t *) priv; + deleteSAASND(cms->saasound); + deleteSAASND(cms->saasound2); + free(cms); } From b644016d1e0a7a917637c2fadcf8d8056d09b4ab Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 1 Apr 2025 23:11:09 +0600 Subject: [PATCH 0649/1190] Port Sound Blaster 1.x/2.x SAA1099 emulation to SAASound --- src/sound/snd_sb.c | 65 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index e89946486..4a17fe20b 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -41,6 +41,7 @@ #include <86box/sound.h> #include "cpu.h" #include <86box/timer.h> +#include "saasound/SAASound.h" #include <86box/snd_sb.h> #include <86box/plat_unused.h> @@ -145,6 +146,42 @@ sb_log(const char *fmt, ...) # define sb_log(fmt, ...) #endif +void +sb_cms_get_buffer(int32_t *buffer, int len, void *priv) +{ + sb_t *sb = (sb_t *) priv; + + cms_update(&sb->cms); + + for (int c = 0; c < len * 2; c++) { + if (sb->mixer_enabled) { + buffer[c] += sb->cms.buffer[c] * sb->mixer_sb2.fm; + } + else + buffer[c] += sb->cms.buffer[c]; + } + + sb->cms.pos = 0; +} + +void +sb_cms_get_buffer_2(int32_t *buffer, int len, void *priv) +{ + sb_t *sb = (sb_t *) priv; + + cms_update(&sb->cms); + + for (int c = 0; c < len * 2; c++) { + if (sb->mixer_enabled) { + buffer[c] += sb->cms.buffer2[c] * sb->mixer_sb2.fm; + } + else + buffer[c] += sb->cms.buffer2[c]; + } + + sb->cms.pos2 = 0; +} + /* SB 1, 1.5, MCV, and 2 do not have a mixer, so signal is hardwired. */ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) @@ -155,23 +192,10 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) sb_dsp_update(&sb->dsp); - if (sb->cms_enabled) - cms_update(&sb->cms); - for (int c = 0; c < len * 2; c += 2) { double out_l = 0.0; double out_r = 0.0; - if (sb->cms_enabled) { - out_l += sb->cms.buffer[c]; - out_r += sb->cms.buffer[c + 1]; - } - - if (sb->cms_enabled && sb->mixer_enabled) { - out_l *= mixer->fm; - out_r *= mixer->fm; - } - /* TODO: Recording: I assume it has direct mic and line in like SB2. It is unclear from the docs if it has a filter, but it probably does. */ /* TODO: Recording: Mic and line In with AGC. */ @@ -192,9 +216,6 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) } sb->dsp.pos = 0; - - if (sb->cms_enabled) - sb->cms.pos = 0; } static void @@ -2890,6 +2911,13 @@ sb_init(UNUSED(const device_t *info)) cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + + sb->cms.saasound = newSAASND(); + SAASNDSetSoundParameters(sb->cms.saasound, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); + sb->cms.saasound2 = newSAASND(); + SAASNDSetSoundParameters(sb->cms.saasound2, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); + wavetable_add_handler(sb_cms_get_buffer, sb); + wavetable_add_handler(sb_cms_get_buffer_2, sb); } if (mixer_addr > 0x000) { @@ -4044,6 +4072,11 @@ sb_close(void *priv) sb_t *sb = (sb_t *) priv; sb_dsp_close(&sb->dsp); + if (sb->cms_enabled) { + deleteSAASND(sb->cms.saasound); + deleteSAASND(sb->cms.saasound2); + } + free(sb); } From ee71952e02a272422cfe39cd00265c2cfc7d23f2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 2 Apr 2025 00:33:24 +0600 Subject: [PATCH 0650/1190] Don't attempt altering window position if fullscreen --- 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 b3d0d9fa9..4c04ce76e 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -803,7 +803,7 @@ MainWindow::resizeEvent(QResizeEvent *event) { //qDebug() << pos().x() + event->size().width(); //qDebug() << pos().y() + event->size().height(); - if (vid_resize == 1) + if (vid_resize == 1 || video_fullscreen) return; int newX = pos().x(); From 3956032b94e20d47175b940c19c2830228f55357 Mon Sep 17 00:00:00 2001 From: Emlyn Corrin Date: Tue, 1 Apr 2025 20:05:08 +0100 Subject: [PATCH 0651/1190] Display ISABugger status in monospace font with colour for the LED bits --- src/device/bugger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/device/bugger.c b/src/device/bugger.c index b56937a43..6b9ed43cc 100644 --- a/src/device/bugger.c +++ b/src/device/bugger.c @@ -84,7 +84,7 @@ static uint8_t bug_spcfg; /* serial port configuration */ #define FIFO_LEN 256 static uint8_t bug_buff[FIFO_LEN]; /* serial port data buffer */ static uint8_t *bug_bptr; -#define UISTR_LEN 24 +#define UISTR_LEN 91 static char bug_str[UISTR_LEN]; /* UI output string */ extern void ui_sb_bugui(char *__str); @@ -112,7 +112,7 @@ static void bug_setui(void) { /* Format all current info in a string. */ - sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c", + sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c", bug_seg2, bug_seg1, (bug_ledg & 0x80) ? 'G' : 'g', (bug_ledg & 0x40) ? 'G' : 'g', (bug_ledg & 0x20) ? 'G' : 'g', (bug_ledg & 0x10) ? 'G' : 'g', From 5e61b78b782dfaf8b4139c598deecc40ad412cd8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 2 Apr 2025 01:10:21 +0600 Subject: [PATCH 0652/1190] Make sure that floppy icons and options do not appear if there's no floppy controller available --- src/floppy/fdc.c | 6 ++++++ src/qt/qt_machinestatus.cpp | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 51c3aa24a..e656e639c 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -79,6 +79,8 @@ int floppyrate[4]; int fdc_current[FDC_MAX] = { 0, 0 }; +volatile int fdcinited = 0; + #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; @@ -2337,6 +2339,8 @@ fdc_close(void *priv) fifo_close(fdc->fifo_p); + fdcinited = 0; + free(fdc); } @@ -2382,6 +2386,8 @@ fdc_init(const device_t *info) fdc_reset(fdc); + fdcinited = 1; + return fdc; } diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index d555be360..aba7fc1d4 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -40,6 +40,8 @@ extern "C" { #include <86box/ui.h> #include <86box/machine_status.h> #include <86box/config.h> + +extern volatile int fdcinited; }; #include @@ -303,6 +305,9 @@ MachineStatus::hasSCSI() void MachineStatus::iterateFDD(const std::function &cb) { + if (!fdcinited) + return; + for (int i = 0; i < FDD_NUM; ++i) { if (fdd_get_type(i) != 0) { cb(i); From dd5a25aad39830c9c674b26b5c3beaba8a405f11 Mon Sep 17 00:00:00 2001 From: Emlyn Corrin Date: Tue, 1 Apr 2025 21:56:41 +0100 Subject: [PATCH 0653/1190] Only set LED colour when it is lit --- src/device/bugger.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/device/bugger.c b/src/device/bugger.c index 6b9ed43cc..6a30df7be 100644 --- a/src/device/bugger.c +++ b/src/device/bugger.c @@ -84,7 +84,10 @@ static uint8_t bug_spcfg; /* serial port configuration */ #define FIFO_LEN 256 static uint8_t bug_buff[FIFO_LEN]; /* serial port data buffer */ static uint8_t *bug_bptr; -#define UISTR_LEN 91 + +static char LED_R[] = "R"; +static char LED_G[] = "G"; +#define UISTR_LEN (17 + 8 * sizeof(LED_G) + 8 * sizeof(LED_R)) static char bug_str[UISTR_LEN]; /* UI output string */ extern void ui_sb_bugui(char *__str); @@ -112,16 +115,16 @@ static void bug_setui(void) { /* Format all current info in a string. */ - sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c", + sprintf(bug_str, "%02X:%02X %s%s%s%s%s%s%s%s-%s%s%s%s%s%s%s%s", bug_seg2, bug_seg1, - (bug_ledg & 0x80) ? 'G' : 'g', (bug_ledg & 0x40) ? 'G' : 'g', - (bug_ledg & 0x20) ? 'G' : 'g', (bug_ledg & 0x10) ? 'G' : 'g', - (bug_ledg & 0x08) ? 'G' : 'g', (bug_ledg & 0x04) ? 'G' : 'g', - (bug_ledg & 0x02) ? 'G' : 'g', (bug_ledg & 0x01) ? 'G' : 'g', - (bug_ledr & 0x80) ? 'R' : 'r', (bug_ledr & 0x40) ? 'R' : 'r', - (bug_ledr & 0x20) ? 'R' : 'r', (bug_ledr & 0x10) ? 'R' : 'r', - (bug_ledr & 0x08) ? 'R' : 'r', (bug_ledr & 0x04) ? 'R' : 'r', - (bug_ledr & 0x02) ? 'R' : 'r', (bug_ledr & 0x01) ? 'R' : 'r'); + (bug_ledg & 0x80) ? LED_G : "g", (bug_ledg & 0x40) ? LED_G : "g", + (bug_ledg & 0x20) ? LED_G : "g", (bug_ledg & 0x10) ? LED_G : "g", + (bug_ledg & 0x08) ? LED_G : "g", (bug_ledg & 0x04) ? LED_G : "g", + (bug_ledg & 0x02) ? LED_G : "g", (bug_ledg & 0x01) ? LED_G : "g", + (bug_ledr & 0x80) ? LED_R : "r", (bug_ledr & 0x40) ? LED_R : "r", + (bug_ledr & 0x20) ? LED_R : "r", (bug_ledr & 0x10) ? LED_R : "r", + (bug_ledr & 0x08) ? LED_R : "r", (bug_ledr & 0x04) ? LED_R : "r", + (bug_ledr & 0x02) ? LED_R : "r", (bug_ledr & 0x01) ? LED_R : "r"); /* Send formatted string to the UI. */ ui_sb_bugui(bug_str); From 2a8e4d5a68cfc04debdfad855df2331a1d61d15a Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 2 Apr 2025 08:34:34 +0200 Subject: [PATCH 0654/1190] PCI and ACPI - when resetting all devices, also reset (ie. zero) all of the emulated RAM as well, fixes Windows 2000 after soft reset on later machines such as the ASUS P2B-LS. --- src/acpi.c | 4 +++- src/include/86box/mem.h | 1 + src/mem/mem.c | 13 +++++++++++++ src/pci.c | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/acpi.c b/src/acpi.c index ccd51ebca..963f26ae6 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1025,8 +1025,10 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p nvr_reg_write(0x000f, 0xff, dev->nvr); } - if (sus_typ & SUS_RESET_PCI) + if (sus_typ & SUS_RESET_PCI) { device_reset_all(DEVICE_PCI); + mem_zero(); + } if (sus_typ & SUS_RESET_CPU) cpu_alt_reset = 0; diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 81b46b2fa..f8d0f659a 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -459,6 +459,7 @@ extern void mem_a20_recalc(void); extern void mem_init(void); extern void mem_close(void); +extern void mem_zero(void); extern void mem_reset(void); extern void mem_remap_top_ex(int kb, uint32_t start); extern void mem_remap_top_ex_nomid(int kb, uint32_t start); diff --git a/src/mem/mem.c b/src/mem/mem.c index 074b44bda..c4d11300b 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -2792,6 +2792,17 @@ mem_init_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) mem_add_ram_mapping(mapping, base, size); } +void +mem_zero(void) +{ +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) + memset(ram2, 0x00, ram2_size + 16); +#endif + + memset(ram, 0x00, ram_size + 16); +} + /* Reset the memory state. */ void mem_reset(void) @@ -2867,8 +2878,10 @@ mem_reset(void) return; } memset(ram, 0x00, ram_size + 16); +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (mem_size > 1048576) ram2 = &(ram[1 << 30]); +#endif } /* diff --git a/src/pci.c b/src/pci.c index ab585c456..c2e4ca237 100644 --- a/src/pci.c +++ b/src/pci.c @@ -419,6 +419,8 @@ pci_trc_reset(uint8_t val) mem_a20_recalc(); flushmmucache(); + + mem_zero(); } #ifdef USE_DYNAREC From de04870db26175dfd065a5708d85a337ca07aad4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 2 Apr 2025 08:58:16 +0200 Subject: [PATCH 0655/1190] CMS/SAA: Fix warnings. --- src/sound/saasound/SAADevice.cpp | 2 +- src/sound/saasound/SAAEnv.cpp | 8 ++++---- src/sound/saasound/SAAFreq.cpp | 17 ++++++++++++----- src/sound/saasound/SAAImpl.cpp | 14 ++++++++------ src/sound/saasound/SAANoise.cpp | 4 ++-- src/sound/snd_cms.c | 2 -- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/sound/saasound/SAADevice.cpp b/src/sound/saasound/SAADevice.cpp index 306aa477a..718b05a95 100644 --- a/src/sound/saasound/SAADevice.cpp +++ b/src/sound/saasound/SAADevice.cpp @@ -107,7 +107,7 @@ void CSAADevice::_SetSampleRate(unsigned int nSampleRate) void CSAADevice::_SetOversample(unsigned int nOversample) { - if (nOversample != m_nOversample) + if (((int) nOversample) != m_nOversample) { m_nOversample = nOversample; m_Osc0._SetOversample(nOversample); diff --git a/src/sound/saasound/SAAEnv.cpp b/src/sound/saasound/SAAEnv.cpp index ae8191112..049f51f96 100755 --- a/src/sound/saasound/SAAEnv.cpp +++ b/src/sound/saasound/SAAEnv.cpp @@ -40,12 +40,12 @@ const ENVDATA CSAAEnv::cs_EnvData[8] = CSAAEnv::CSAAEnv() : m_bEnabled(false), -m_bNewData(false), -m_nNextData(0), -m_bEnvelopeEnded(true), m_nPhase(0), m_nPhasePosition(0), -m_nResolution(1) +m_bEnvelopeEnded(true), +m_nResolution(1), +m_bNewData(false), +m_nNextData(0) { // initialise itself with the value 'zero' SetEnvControl(0); diff --git a/src/sound/saasound/SAAFreq.cpp b/src/sound/saasound/SAAFreq.cpp index 52cbc7a3d..61a04f6ad 100755 --- a/src/sound/saasound/SAAFreq.cpp +++ b/src/sound/saasound/SAAFreq.cpp @@ -32,11 +32,18 @@ const int INITIAL_LEVEL = 1; CSAAFreq::CSAAFreq(CSAANoise * const NoiseGenerator, CSAAEnv * const EnvGenerator) : -m_nCounter(0), m_nCounter_low(0), m_nAdd(0), +m_nCounter(0), +m_nAdd(0), +m_nCounter_low(0), +m_nOversample(0), +m_nCounterLimit_low(1), m_nLevel(INITIAL_LEVEL), -m_nOversample(0), m_nCounterLimit_low(1), -m_nCurrentOffset(0), m_nCurrentOctave(0), m_nNextOffset(0), m_nNextOctave(0), -m_bIgnoreOffsetData(false), m_bNewData(false), +m_nCurrentOffset(0), +m_nCurrentOctave(0), +m_nNextOffset(0), +m_nNextOctave(0), +m_bIgnoreOffsetData(false), +m_bNewData(false), m_bSync(false), m_nSampleRate(SAMPLE_RATE_HZ), m_pcConnectedNoiseGenerator(NoiseGenerator), @@ -194,7 +201,7 @@ void CSAAFreq::_SetClockRate(int nClockRate) // Finally, note that the standard formula corresponds to a 8MHz base clock // so we rescale the final result by the ratio nClockRate/8000000 - if (nClockRate != m_nClockRate) + if (((unsigned long) nClockRate) != m_nClockRate) { m_nClockRate = nClockRate; int ix = 0; diff --git a/src/sound/saasound/SAAImpl.cpp b/src/sound/saasound/SAAImpl.cpp index 8545d3849..f136eefc6 100644 --- a/src/sound/saasound/SAAImpl.cpp +++ b/src/sound/saasound/SAAImpl.cpp @@ -20,16 +20,18 @@ CSAASoundInternal::CSAASoundInternal() : -m_nClockRate(EXTERNAL_CLK_HZ), -m_bHighpass(false), -m_nSampleRate(SAMPLE_RATE_HZ), -m_nOversample(DEFAULT_OVERSAMPLE), +m_chip(), m_uParam(0), m_uParamRate(0), +m_nClockRate(EXTERNAL_CLK_HZ), +m_nSampleRate(SAMPLE_RATE_HZ), +m_nOversample(DEFAULT_OVERSAMPLE), #if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) -m_nDebugSample(0), +m_bHighpass(false), +m_nDebugSample(0) +#else +m_bHighpass(false) #endif -m_chip() { #ifdef USE_CONFIG_FILE m_Config.ReadConfig(); diff --git a/src/sound/saasound/SAANoise.cpp b/src/sound/saasound/SAANoise.cpp index 895a5a103..1cf3458dd 100755 --- a/src/sound/saasound/SAANoise.cpp +++ b/src/sound/saasound/SAANoise.cpp @@ -25,8 +25,8 @@ CSAANoise::CSAANoise() : m_nCounter(0), m_nCounter_low(0), -m_nCounterLimit_low(1), m_nOversample(0), +m_nCounterLimit_low(1), m_bSync(false), m_nSampleRate(SAMPLE_RATE_HZ), m_nSourceMode(0), @@ -40,8 +40,8 @@ CSAANoise::CSAANoise(unsigned long seed) : m_nCounter(0), m_nCounter_low(0), -m_nCounterLimit_low(1), m_nOversample(0), +m_nCounterLimit_low(1), m_bSync(false), m_nSampleRate(SAMPLE_RATE_HZ), m_nSourceMode(0), diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 60165365d..c6591b1fc 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -56,8 +56,6 @@ void cms_write(uint16_t addr, uint8_t val, void *priv) { cms_t *cms = (cms_t *) priv; - int voice; - int chip = (addr & 2) >> 1; switch (addr & 0xf) { case 0x1: /* SAA #1 Register Select Port */ From 420a08ee2c8755dc1ba6785cbd5e31247aac1c1f Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 2 Apr 2025 17:18:44 +0200 Subject: [PATCH 0656/1190] mem.c: Do not initialize the > 1 GB mapping on 64-bit binaries where it is not necessary. --- src/mem/mem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mem/mem.c b/src/mem/mem.c index c4d11300b..8c2cfd6cc 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -2976,6 +2976,7 @@ mem_reset(void) else if (cpu_16bitbus && is6117 && mem_size > 65408) mem_init_ram_mapping(&ram_high_mapping, 0x100000, (65408 - 1024) * 1024); else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (mem_size > 1048576) { mem_init_ram_mapping(&ram_high_mapping, 0x100000, (1048576 - 1024) * 1024); @@ -2988,6 +2989,9 @@ mem_reset(void) ram2, MEM_MAPPING_INTERNAL, NULL); } else mem_init_ram_mapping(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024); +#else + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024); +#endif } } From 98efd05ddaa32823028c2130ffeb26ea40bbc6a2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 2 Apr 2025 18:45:27 +0200 Subject: [PATCH 0657/1190] Alfredo, Batman's Renvenge, and Plato: Pre-initialize NVR to 0x00 instead of 0xFF and give them the correct Phoenix keyboard controller, fixes hang after the first soft reset. --- src/machine/m_at_386dx_486.c | 4 +++- src/machine/m_at_socket4.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0ee353f53..572cebc2e 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1249,6 +1249,8 @@ machine_at_alfredo_init(const machine_t *model) return ret; machine_at_common_init(model); + + device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); @@ -1258,7 +1260,7 @@ machine_at_alfredo_init(const machine_t *model) pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_pci_device); + device_add(&keyboard_ps2_phoenix_device); device_add(&sio_device); device_add(&fdc37c663_device); device_add(&intel_flash_bxt_ami_device); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 78df5b0cb..072d52e01 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -44,7 +44,9 @@ void machine_at_premiere_common_init(const machine_t *model, int pci_switch) { - machine_at_common_init(model); + machine_at_common_init_ex(model); + + device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | pci_switch); @@ -54,7 +56,7 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&keyboard_ps2_phoenix_device); device_add(&sio_zb_device); device_add(&fdc37c665_device); device_add(&intel_flash_bxt_ami_device); From babac318944a5aa80daedd99d76f3abaf651f915 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 2 Apr 2025 18:46:35 +0200 Subject: [PATCH 0658/1190] Fixed a compile-breaking mistake. --- src/machine/m_at_386dx_486.c | 2 +- src/machine/m_at_socket4.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 572cebc2e..7f285af65 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1248,7 +1248,7 @@ machine_at_alfredo_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 072d52e01..0d78c6de3 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -44,7 +44,7 @@ void machine_at_premiere_common_init(const machine_t *model, int pci_switch) { - machine_at_common_init_ex(model); + machine_at_common_init_ex(model, 2); device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); From 57851e7606d02ed15fb470641158d2b1dfb98c66 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 2 Apr 2025 16:21:50 -0300 Subject: [PATCH 0659/1190] AD1848: Logging and clean-ups I forgot to commit --- src/sound/snd_ad1848.c | 78 +++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index 87755a96c..202fd891a 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -19,11 +19,12 @@ * Copyright 2021-2025 RichardG. */ #include +#include #include #include #include #include - +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/dma.h> #include <86box/pic.h> @@ -36,6 +37,24 @@ #define CS4232 0x02 #define CS4236 0x03 +#ifdef ENABLE_AD1848_LOG +int ad1848_do_log = ENABLE_AD1848_LOG; + +static void +ad1848_log(const char *fmt, ...) +{ + va_list ap; + + if (ad1848_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ad1848_log(fmt, ...) +#endif + static int ad1848_vols_7bits[128]; static double ad1848_vols_5bits_aux_gain[32]; @@ -46,12 +65,14 @@ extern uint8_t adjustMap4[64]; void ad1848_setirq(ad1848_t *ad1848, int irq) { + ad1848_log("AD1848: setirq(%d)\n", irq); ad1848->irq = irq; } void ad1848_setdma(ad1848_t *ad1848, int newdma) { + ad1848_log("AD1848: setdma(%d)\n", newdma); ad1848->dma = newdma; } @@ -62,6 +83,7 @@ ad1848_updatevolmask(ad1848_t *ad1848) ad1848->wave_vol_mask = 0x7f; else ad1848->wave_vol_mask = 0x3f; + ad1848_log("AD1848: updatevolmask(%02X)\n", ad1848->wave_vol_mask); } static double @@ -99,6 +121,8 @@ ad1848_get_default_freq(ad1848_t *ad1848) break; } + ad1848_log("AD1848: Frequency %f through default path\n", freq); + return freq; } @@ -136,6 +160,8 @@ ad1848_updatefreq(ad1848_t *ad1848) freq /= 2558.0; break; } + + ad1848_log("AD1848: Frequency %f through CS4236B+ path\n", freq); } else if (ad1848->regs[22] & 0x80) { const uint8_t set = (ad1848->regs[22] >> 1) & 0x3f; freq = (ad1848->regs[22] & 1) ? 33868800.0 : 49152000.0; @@ -153,6 +179,8 @@ ad1848_updatefreq(ad1848_t *ad1848) freq /= 256 * set; break; } + + ad1848_log("AD1848: Frequency %f through CS4232+ path\n", freq); } else freq = ad1848_get_default_freq(ad1848); } else @@ -182,18 +210,16 @@ ad1848_read(uint16_t addr, void *priv) ad1848->regs[ad1848->index] = ret; break; - case 18: - case 19: + case 18 ... 19: if (ad1848->type >= AD1848_TYPE_CS4236B) { if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */ - ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */ + ret = ad1848->xregs[6 | (ad1848->index & 1)]; /* real FM volume on registers 6 and 7 */ else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */ - ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */ + ret = ad1848->xregs[16 | (ad1848->index & 1)]; /* real wavetable volume on registers 16 and 17 */ } break; - case 20: - case 21: + case 20 ... 21: /* Backdoor to the Control/RAM registers on CS4235+. */ if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv); @@ -229,13 +255,16 @@ ad1848_read(uint16_t addr, void *priv) default: break; } + ad1848_log("AD1848: read(X%d) = %02X\n", ad1848->xindex, ret); + return ret; } break; default: break; } - break; + ad1848_log("AD1848: read(I%d) = %02X\n", ad1848->index, ret); + return ret; case 2: ret = ad1848->status; @@ -245,6 +274,8 @@ ad1848_read(uint16_t addr, void *priv) break; } + ad1848_log("AD1848: read(%04X) = %02X\n", addr, ret); + return ret; } @@ -295,7 +326,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) break; case 11: - return; + goto readonly_i; case 12: if (ad1848->type >= AD1848_TYPE_CS4248) { @@ -307,19 +338,19 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) ad1848->fmt_mask &= ~0x80; } } - return; + goto readonly_i; case 14: ad1848->count = ad1848->regs[15] | (val << 8); break; - case 18: - case 19: + case 18 ... 19: if (ad1848->type >= AD1848_TYPE_CS4236B) { if (ad1848->type >= AD1848_TYPE_CS4235) { if (ad1848->xregs[18] & 0x20) /* AUX1 remapping */ ad1848->regs[ad1848->index & 3] = val; /* also controls AUX1 on registers 2 and 3 */ } else { + temp = 0; if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */ ad1848->xregs[6 | (ad1848->index & 1)] = val; /* real FM volume on extended registers 6 and 7 */ temp = 1; @@ -343,7 +374,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) /* Stop here if any remapping is enabled. */ if (temp) - return; + goto readonly_i; } /* HACK: the Windows 9x driver's "Synth" control writes to this @@ -362,8 +393,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) } break; - case 20: - case 21: + case 20 ... 21: /* Backdoor to the Control/RAM registers on CS4235+. */ if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) { ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv); @@ -421,7 +451,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) break; case 25: - return; + goto readonly_x; case 26 ... 28: case 30: @@ -438,6 +468,8 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) if (updatefreq) ad1848_updatefreq(ad1848); +readonly_x: + ad1848_log("AD1848: write(X%d, %02X)\n", ad1848->xindex, val); return; } break; @@ -451,14 +483,14 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) break; case 25: - return; + goto readonly_i; case 27: if ((ad1848->type != AD1848_TYPE_CS4232) && (ad1848->type != AD1848_TYPE_CS4236)) - return; + goto readonly_i; break; case 29: if ((ad1848->type != AD1848_TYPE_CS4232) && (ad1848->type != AD1848_TYPE_CS4236)) - return; + goto readonly_i; break; default: @@ -480,7 +512,9 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) else ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f]; - break; +readonly_i: + ad1848_log("AD1848: write(I%d, %02X)\n", ad1848->index, val); + return; case 2: ad1848->status &= 0xfe; @@ -490,6 +524,8 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) default: break; } + + ad1848_log("AD1848: write(%04X, %02X)\n", addr, val); } void @@ -743,6 +779,8 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) uint8_t c; double attenuation; + ad1848_log("AD1848: init(%02X)\n", type); + ad1848->status = 0xcc; ad1848->index = ad1848->trd = 0; ad1848->mce = 0x40; From f56f636248aea56ce4dafabbf0a18597d167ce02 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 2 Apr 2025 16:27:10 -0300 Subject: [PATCH 0660/1190] Report 4 GB cacheable memory on Deschutes CPUs, fixes modern Linux limiting itself to 512 MB on some machines --- src/cpu/cpu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 910d40765..61bd8bf36 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2649,6 +2649,11 @@ cpu_ven_reset(void) case CPU_PENTIUM2: case CPU_PENTIUM2D: msr.mtrr_cap = 0x00000508ULL; + + /* 4 GB cacheable space on Deschutes 651h and later (including the 1632h + Overdrive) according to the Pentium II Processor Specification Update. */ + if (cpu_s->cpuid_model >= 0x651) + msr.bbl_cr_ctl3 |= 0x00300000; break; case CPU_CYRIX3S: @@ -4103,7 +4108,7 @@ pentium_invalid_wrmsr: break; /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ case 0x11e: - msr.bbl_cr_ctl3 = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_ctl3 = (msr.bbl_cr_ctl3 & 0x02f00000) | (EAX & ~0x02f00000) | ((uint64_t) EDX << 32); break; /* Unknown */ case 0x131: From 5432c1dd1382331b94985283b5034daafef4c37d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 2 Apr 2025 21:33:26 +0200 Subject: [PATCH 0661/1190] 8514/A compatible changes of the day (April 2nd, 2025) 1. Aliases are aliases, period. 2. Actually make the ports using bit 15 of their range use the command FIFO. 3. Improved the special ATI command 0xc2b5 in the IBM bitblt side, fixes cursor issues in 24bpp mode using OS/2. 4. When the FIFO is empty, clear the busy and available flags. 5. Also reapply a workaround for 24bpp foreground color patterns in ATI command Scan To X command, fixes patterns in OS/2 and possibly elsewhere. 6. Accelerated HiColor mode, in the IBM passthrough mode, should always be enabled, for now, as well as the Extended ATI Mach32 8bpp mode when prompted, fixes OS/2 booting into the GUI in HiColor mode. 7. Dummy data path configuration values on direct linedraw should not trigger a pixtrans read when it's not needed, fixes possible hang ups in IBM/ATI mode when the busy flag remains enabled. --- src/video/vid_8514a.c | 171 +++++++++------ src/video/vid_ati_mach8.c | 438 +++++++++++++++++++++++--------------- 2 files changed, 375 insertions(+), 234 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 7c0bf9702..8925f01da 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -334,6 +334,13 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + if (port & 0x8000) { + if ((port != 0xe2e8) && (port != 0xe2e9) && (port != 0xe6e8) && (port != 0xe6e9)) { + if (port & 0x4000) + port &= ~0x4000; + } + } + switch (port) { case 0x2e8: WRITE8(port, dev->htotal, val); @@ -499,19 +506,16 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x82e8: - case 0xc2e8: if (len == 2) dev->accel.cur_y = val & 0x7ff; break; case 0x86e8: - case 0xc6e8: if (len == 2) dev->accel.cur_x = val & 0x7ff; break; case 0x8ae8: - case 0xcae8: if (len == 2) { dev->accel.desty = val & 0x7ff; dev->accel.desty_axstp = val & 0x3fff; @@ -521,7 +525,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x8ee8: - case 0xcee8: if (len == 2) { dev->accel.destx = val & 0x7ff; dev->accel.destx_distp = val & 0x3fff; @@ -531,12 +534,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x92e8: - if (len == 2) - dev->test = val; - fallthrough; - - case 0xd2e8: if (len == 2) { + dev->test = val; dev->accel.err_term = val & 0x3fff; if (val & 0x2000) dev->accel.err_term |= ~0x1fff; @@ -544,7 +543,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x96e8: - case 0xd6e8: if (len == 2) { dev->accel.maj_axis_pcnt = val & 0x7ff; dev->accel.maj_axis_pcnt_no_limit = val; @@ -552,7 +550,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x9ae8: - case 0xdae8: dev->accel.ssv_state = 0; if (len == 2) { dev->data_available = 0; @@ -562,13 +559,12 @@ 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, 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_log("8514/A CMD=%04x, frgd color=%04x, frgdmix=%02x, pixcntl=%02x.\n", dev->accel.cmd, 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->accel.ssv_state = 1; if (len == 2) { dev->accel.short_stroke = val; @@ -628,35 +624,29 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0xaae8: - case 0xeae8: if (len == 2) dev->accel.wrt_mask = val; break; case 0xaee8: - case 0xeee8: if (len == 2) dev->accel.rd_mask = val; break; case 0xb2e8: - case 0xf2e8: if (len == 2) dev->accel.color_cmp = val; break; case 0xb6e8: - case 0xf6e8: dev->accel.bkgd_mix = val & 0xff; break; case 0xbae8: - case 0xfae8: dev->accel.frgd_mix = val & 0xff; break; case 0xbee8: - case 0xfee8: if (len == 2) { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; @@ -765,10 +755,12 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (dev->accel.cmd_back) { - dev->fifo_idx++; - if (dev->fifo_idx > 8) - dev->fifo_idx = 8; + if (port & 0x8000) { + 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); @@ -799,13 +791,11 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) switch (port) { case 0x82e8: - case 0xc2e8: if (len == 2) temp = dev->accel.cur_y; break; case 0x86e8: - case 0xc6e8: if (len == 2) temp = dev->accel.cur_x; break; @@ -821,7 +811,6 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) break; case 0x9ae8: - case 0xdae8: if (len == 2) { if (dev->fifo_idx <= 8) { for (int i = 1; i <= dev->fifo_idx; i++) @@ -835,9 +824,6 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) if (dev->force_busy) temp |= 0x0200; /*Hardware busy*/ - if (dev->accel.cmd_back) - dev->force_busy = 0; - if (dev->data_available) { temp |= 0x0100; /*Read Data available*/ switch (dev->accel.cmd >> 13) { @@ -857,7 +843,6 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) } break; case 0x9ae9: - case 0xdae9: if (len == 1) { dev->fifo_idx = 0; @@ -974,7 +959,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) temp |= INT_GE_BSY; } - if (dev->accel.cmd_back) { + if (!dev->fifo_idx) { dev->force_busy = 0; dev->force_busy2 = 0; dev->data_available = 0; @@ -1033,6 +1018,8 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t dev->accel.ssv_len_back = dev->accel.ssv_len; if (ibm8514_cpu_src(svga)) { + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ @@ -1079,11 +1066,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat rd_mask_polygon &= 0xff; } - if (!dev->accel.cmd_back) { - dev->force_busy = 1; - dev->force_busy2 = 1; - } - frgd_mix = (dev->accel.frgd_mix >> 5) & 3; bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; @@ -1251,8 +1233,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat cpu_dat >>= 8; if (!dev->accel.ssv_len) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1348,8 +1334,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat cpu_dat >>= 8; if (!dev->accel.ssv_len) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1413,10 +1403,14 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.output = 1; } } + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ } else if (ibm8514_cpu_dest(svga)) { + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 1; dev->data_available2 = 1; return; @@ -1524,8 +1518,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } if (!dev->accel.sy) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; if (!cpu_input) { dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1645,8 +1643,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat cpu_dat >>= 8; if (!dev->accel.sy) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1749,8 +1751,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat cpu_dat >>= 8; if (!dev->accel.sy) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; if (!cpu_input) { dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1855,6 +1861,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } } + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ @@ -1872,6 +1880,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } ibm8514_log("INPUT=%d.\n", dev->accel.input); + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 1; dev->data_available2 = 1; return; /*Wait for data from CPU*/ @@ -2031,8 +2041,10 @@ skip_vector_rect_write: dev->accel.x_count = 0; if (dev->accel.sy < 0) { - dev->accel.cmd_back = 1; + dev->force_busy = 0; + dev->force_busy2 = 0; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; } return; } @@ -2043,6 +2055,7 @@ skip_vector_rect_write: ibm8514_log("Vectored Rectangle with normal processing (TODO).\n"); } else { /*Normal Rectangle*/ if (cpu_input) { + ibm8514_log("Normal Pixel Rectangle Fill Transfer SY=%d.\n", dev->accel.sy); while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && @@ -2192,9 +2205,11 @@ skip_nibble_rect_write: dev->accel.x_count = 0; if (dev->accel.sy < 0) { - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; } + dev->force_busy = 0; + dev->force_busy2 = 0; return; } } @@ -2280,8 +2295,8 @@ skip_nibble_rect_write: dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; } return; } @@ -2366,8 +2381,8 @@ skip_nibble_rect_write: dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; } - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -2478,10 +2493,10 @@ 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; + dev->accel.cmd_back = 1; return; } } @@ -2568,8 +2583,8 @@ skip_nibble_rect_write: dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; } - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -2599,10 +2614,14 @@ skip_nibble_rect_write: ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, clip_l, clip_r, clip_t, clip_b, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ } else if (ibm8514_cpu_dest(svga)) { + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 1; dev->data_available2 = 1; return; @@ -2671,8 +2690,12 @@ skip_nibble_rect_write: cpu_dat >>= 8; if (!dev->accel.sy) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -2776,8 +2799,12 @@ skip_nibble_rect_write: cpu_dat >>= 8; if (!dev->accel.sy) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -2869,10 +2896,14 @@ skip_nibble_rect_write: } } } + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ } else if (ibm8514_cpu_dest(svga)) { + dev->force_busy = 1; + dev->force_busy2 = 1; dev->data_available = 1; dev->data_available2 = 1; return; /*Wait for data from CPU*/ @@ -3036,6 +3067,8 @@ skip_nibble_bitblt_write: if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->force_busy = 0; + dev->force_busy2 = 0; dev->fifo_idx = 0; } return; @@ -3234,8 +3267,8 @@ skip_nibble_bitblt_write: if (dev->accel.sy < 0) { dev->accel.destx = dev->accel.dx; dev->accel.desty = dev->accel.dy; - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -3254,9 +3287,29 @@ skip_nibble_bitblt_write: (dx <= (((uint64_t)clip_r) * 3)) && (dev->accel.dy >= (clip_t << 1)) && (dev->accel.dy <= (clip_b << 1))) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = 0; + break; + case 3: + READ(dev->accel.src + cx, src_dat); + break; + + default: + break; + } + READ(dev->accel.src + cx, src_dat); READ(dev->accel.dest + dx, dest_dat); - dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); + 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 + dx, dest_dat); } @@ -3265,8 +3318,8 @@ skip_nibble_bitblt_write: dev->accel.sx--; if (dev->accel.sx < 0) { - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -3321,15 +3374,8 @@ 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); - } - } else { - WRITE(dev->accel.dest + dev->accel.dx, 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, dev->accel.dy, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); - } + WRITE(dev->accel.dest + dev->accel.dx, 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, dev->accel.dy, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); } } @@ -3380,8 +3426,8 @@ skip_nibble_bitblt_write: if (dev->accel.sy < 0) { dev->accel.destx = dev->accel.dx; dev->accel.desty = dev->accel.dy; - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -4020,6 +4066,7 @@ ibm8514_init(const device_t *info) default: dev->extensions = 0; ibm8514_io_set(svga); + dev->accel.cmd_back = 1; if (dev->type & DEVICE_MCA) { dev->pos_regs[0] = 0x7f; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 474ae5660..9f92ebde1 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -69,6 +69,7 @@ static uint8_t ati8514_accel_inb(uint16_t port, void *priv); static uint16_t ati8514_accel_inw(uint16_t port, void *priv); static uint32_t ati8514_accel_inl(uint16_t port, void *priv); +static void mach_set_resolution(mach_t *mach, svga_t *svga); 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); @@ -326,12 +327,6 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 bkgd_sel = (mach->accel.dp_config >> 7) & 3; mono_src = (mach->accel.dp_config >> 5) & 3; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { - mach->force_busy = 1; - dev->force_busy = 1; - dev->force_busy2 = 1; - } - if (cpu_input) { if (dev->bpp) { if ((mach->accel.dp_config & 0x200) && (count == 2)) @@ -339,12 +334,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } - if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) - mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monopattern = %x.\n", - 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, dpconfig = %04x.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config); + mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i, dpconfig = %04x, cur_x = %d, cur_y = %d.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config, dev->accel.cur_x, dev->accel.cur_y); switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ @@ -376,12 +366,18 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.linedraw_opt, mach->accel.dp_config, mach->accel.max_waitstates & 0x100); - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 0; dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 1; dev->data_available2 = 1; return; @@ -550,12 +546,22 @@ 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; + if (cpu_input) { + mach->force_busy = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) { - dev->accel.cmd_back = 1; + if (cpu_input) { + mach->force_busy = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -777,12 +783,22 @@ 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; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -976,12 +992,18 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 0; dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 1; dev->data_available2 = 1; return; @@ -1000,16 +1022,26 @@ 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; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } if ((mono_src == 3) || (bkgd_sel == 3) || (frgd_sel == 3)) { if (mach->accel.sx_end == mach->accel.sx_start) { + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } mach_log("No SRC.\n"); - dev->accel.cmd_back = 1; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -1020,8 +1052,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mono_src, frgd_sel, bkgd_sel, dev->pitch); if (dev->accel.sy == mach->accel.height) { mach_log("No Blit on DPCONFIG=3251.\n"); - dev->accel.cmd_back = 1; + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; dev->fifo_idx = 0; + dev->accel.cmd_back = 1; return; } } @@ -1238,8 +1273,13 @@ 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; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; 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)) @@ -1279,14 +1319,20 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.cur_x, dev->accel.cur_y, dev->accel.dx, dev->accel.dy, mach->accel.cx_end_line, mach->accel.cy_end_line, mach->accel.bleft, mach->accel.bright, mach->accel.btop, mach->accel.bbottom); - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { mach_log("Write PIXTRANS.\n"); + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 0; dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { mach_log("Read PIXTRANS.\n"); + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 1; dev->data_available2 = 1; return; @@ -1398,8 +1444,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); if (!count) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1569,8 +1620,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); if (dev->accel.sx >= mach->accel.width) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1694,8 +1750,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); if (!count) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1853,8 +1914,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); if (dev->accel.sx >= mach->accel.width) { - dev->accel.cmd_back = 1; + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + } dev->fifo_idx = 0; + dev->accel.cmd_back = 1; break; } @@ -1986,14 +2052,38 @@ 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: 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 ((dev->accel_bpp >= 24) && (frgd_sel == 5)) { + if (mach->accel.patt_len == 0x17) + mach->accel.color_pattern_idx = 0; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + dev->accel.x1 = dev->accel.dx + mach->accel.width; + if (dev->accel.x1 == dev->pitch) + dev->accel.x2 = mach->accel.width & 1; + else if ((dev->accel.x1 == mach->accel.width) && (dev->accel.dy & 1) && !dev->accel.y1 && dev->accel.x2) { + if (mach->accel.patt_len == 0x17) + mach->accel.color_pattern_idx = 3; + + dev->accel.x3 = 1; + } else + dev->accel.x3 = 0; + } + dev->accel.y1 = 0; + + mach_log("ScanToX: Parameters=%04x: xbit=%d, ybit=%d, widthbit=%d, DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, srcwidth=%d, height=%d, frmix=%02x.\n", + mach->accel.dp_config, dev->accel.dx & 1, dev->accel.dy & 1, mach->accel.width & 1, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.src_width, dev->accel.sy, dev->accel.frgd_mix & 0x1f); + + if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 0; dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { + dev->force_busy = 1; + dev->force_busy2 = 1; + mach->force_busy = 1; dev->data_available = 1; dev->data_available2 = 1; return; @@ -2132,10 +2222,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.sx++; if (mach->accel.sx >= mach->accel.src_width) { mach->accel.sx = 0; - if (mach->accel.src_stepx == -1) { + if (mach->accel.src_stepx == -1) dev->accel.cx += mach->accel.src_width; - } else + else dev->accel.cx -= mach->accel.src_width; + dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); if (dev->bpp) dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); @@ -2143,13 +2234,24 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); } + mach_log("ColorIdx=%d, data=%02x, DestX=%d, DestY=%d.\n", mach->accel.color_pattern_idx, mach->accel.color_pattern[mach->accel.color_pattern_idx], dev->accel.dx, dev->accel.dy & 1); if (dev->bpp) mach->accel.color_pattern_idx += 2; else mach->accel.color_pattern_idx++; - if (mach->accel.color_pattern_idx > mach->accel.patt_len) - mach->accel.color_pattern_idx = 0; + if ((dev->accel_bpp >= 24) && (frgd_sel == 5) && (mach->accel.patt_len == 0x17)) { + if (dev->accel.x3) { + if (mach->accel.color_pattern_idx == 9) + mach->accel.color_pattern_idx = 3; + } else { + if (mach->accel.color_pattern_idx == 6) + mach->accel.color_pattern_idx = 0; + } + } else { + if (mach->accel.color_pattern_idx > mach->accel.patt_len) + mach->accel.color_pattern_idx = 0; + } dev->accel.dx += mach->accel.stepx; dev->accel.sx++; @@ -2167,11 +2269,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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; + dev->accel.cmd_back = 1; return; } } @@ -2368,7 +2470,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach_log("Extended 8514/A mode.\n"); dev->vendor_mode = 1; dev->on |= 0x01; - svga_recalctimings(svga); + mach_set_resolution(mach, svga); mach32_updatemapping(mach, svga); } if (dev->on) @@ -2395,7 +2497,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach_log("VGA mode.\n"); dev->vendor_mode = 0; dev->on &= ~0x01; - svga_recalctimings(svga); + mach_set_resolution(mach, svga); mach32_updatemapping(mach, svga); } if (dev->on) @@ -2688,30 +2790,11 @@ mach_set_resolution(mach_t *mach, svga_t *svga) dev->v_syncstart >>= 1; mach_log("Shadow set ATI=%x, shadow set 8514/A=%x, resolution h=%d, v=%d, vtotal=%d, vsyncstart=%d.\n", mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp, dev->v_total, dev->v_syncstart); - 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*/ - switch (mach->shadow_set & 0x03) { - case 0x00: /*Primary CRT Register set*/ - if (dev->on) { - if (mach->crt_resolution == 0x01) { - if (ATI_8514A_ULTRA) { - if (dev->accel.advfunc_cntl & 0x04) { - if (dev->hdisp == 640) { - dev->hdisp = 1024; - dev->vdisp = 768; - svga_recalctimings(svga); - } - } else { - if (dev->hdisp == 1024) { - dev->hdisp = 640; - dev->vdisp = 480; - svga_recalctimings(svga); - } - } - } else - svga_recalctimings(svga); - } else if (mach->crt_resolution == 0x02) { + switch (mach->shadow_set & 0x03) { + case 0x00: /*Primary CRT Register set*/ + if (dev->on) { + if (mach->crt_resolution == 0x01) { + if (ATI_8514A_ULTRA) { if (dev->accel.advfunc_cntl & 0x04) { if (dev->hdisp == 640) { dev->hdisp = 1024; @@ -2727,33 +2810,48 @@ mach_set_resolution(mach_t *mach, svga_t *svga) } } else svga_recalctimings(svga); - } - break; - case 0x01: /*Shadow 640x480 CRT register set*/ - if (dev->on) { - if (!(dev->accel.advfunc_cntl & 0x04)) { - if (dev->hdisp == 1024) { - dev->hdisp = 640; - dev->vdisp = 480; - } - } - svga_recalctimings(svga); - } - break; - case 0x02: /*Shadow 1024x768 CRT register set*/ - if (dev->on) { + } else if (mach->crt_resolution == 0x02) { if (dev->accel.advfunc_cntl & 0x04) { if (dev->hdisp == 640) { dev->hdisp = 1024; dev->vdisp = 768; + svga_recalctimings(svga); + } + } else { + if (dev->hdisp == 1024) { + dev->hdisp = 640; + dev->vdisp = 480; + svga_recalctimings(svga); } } + } else svga_recalctimings(svga); + } + break; + case 0x01: /*Shadow 640x480 CRT register set*/ + if (dev->on) { + if (!(dev->accel.advfunc_cntl & 0x04)) { + if (dev->hdisp == 1024) { + dev->hdisp = 640; + dev->vdisp = 480; + } } - break; - default: - break; - } + svga_recalctimings(svga); + } + break; + case 0x02: /*Shadow 1024x768 CRT register set*/ + if (dev->on) { + if (dev->accel.advfunc_cntl & 0x04) { + if (dev->hdisp == 640) { + dev->hdisp = 1024; + dev->vdisp = 768; + } + } + svga_recalctimings(svga); + } + break; + default: + break; } } @@ -2855,7 +2953,7 @@ mach_recalctimings(svga_t *svga) svga->ati_4color = 0; } - mach_log("ON?=%d, override=%d, gelo=%04x, gehi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, svga->hdisp); + mach_log("ON=%d, override=%d, gelo=%04x, gehi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, svga->hdisp); if (dev->on) { dev->ma_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ dev->pitch = dev->ext_pitch; @@ -3015,6 +3113,15 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u int bkgd_sel; int mono_src; + if (port & 0x8000) { + if ((port & 0x06) != 0x06) { + if ((port != 0xe2e8) && (port != 0xe2e9) && (port != 0xe6e8) && (port != 0xe6e9)) { + if (port & 0x4000) + port &= ~0x4000; + } + } + } + mach_log("[%04X:%08X]: Port FIFO OUT=%04x, val=%04x, len=%d.\n", CS, cpu_state.pc, port, val, len); switch (port) { @@ -3240,12 +3347,16 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x4ae8: dev->accel.advfunc_cntl = val; - dev->on = dev->accel.advfunc_cntl & 0x01; + dev->on = val & 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); + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d, extmode=%02x.\n", + CS, cpu_state.pc, port, val & 0x01, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp, mach->regs[0xb0] & 0x20); if (ATI_MACH32) { + if ((mach->regs[0xb0] & 0x20) || (dev->accel_bpp >= 15)) { /*Account for the extended ATI 8514/A mode here too*/ + dev->on |= 0x01; + dev->vendor_mode = 1; + } mach_set_resolution(mach, svga); mach32_updatemapping(mach, svga); } else { @@ -3257,14 +3368,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x82e8: case 0x86e8: - case 0xc2e8: - case 0xc6e8: - case 0xf6ee: ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x8ae8: - case 0xcae8: ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { mach_log("SRCY=%d.\n", val & 0x07ff); @@ -3273,7 +3380,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x8ee8: - case 0xcee8: ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { mach_log("SRCX=%d.\n", val & 0x07ff); @@ -3282,64 +3388,55 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x92e8: - case 0xd2e8: ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x96e8: - case 0xd6e8: ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) mach->accel.test = val & 0x1fff; break; case 0x9ae8: - case 0xdae8: mach->accel.cmd_type = -1; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x9ee8: - case 0xdee8: ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xa2e8: case 0xe2e8: if (port == 0xe2e8) { + mach_log("%04X: Background Color=%04x.\n", port, val); if (len == 2) { - 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.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 (!dev->accel.cmd_back) { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach_log("ATI transfer.\n"); mach_accel_out_pixtrans(svga, mach, dev, val); } else { if (ibm8514_cpu_dest(svga)) break; + mach_log("IBM transfer.\n"); ibm8514_accel_out_pixtrans(svga, port, val, len); } + } else { + dev->accel.bkgd_color = val; + mach_log("%04X: CMDBack BKGDCOLOR, sy=%d, height=%d, cmdtype=%d, val=%04x.\n", port, dev->accel.sy, mach->accel.height, mach->accel.cmd_type, val); } } else { - if (mach->accel.cmd_type >= 0) { - if (mach_pixel_read(mach)) - break; + if (dev->accel.cmd & 0x100) { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; - mach->accel.pix_trans[1] = val; + mach->accel.pix_trans[1] = val; + } } } } else { @@ -3353,42 +3450,39 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xa6e8: case 0xe6e8: if (port == 0xe6e8) { + mach_log("%04X: Foreground Color=%04x.\n", port, val); if (len == 2) { - 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 (!dev->accel.cmd_back) { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach_log("ATI transfer.\n"); mach_accel_out_pixtrans(svga, mach, dev, val); } else { if (ibm8514_cpu_dest(svga)) break; + mach_log("IBM transfer.\n"); ibm8514_accel_out_pixtrans(svga, port, val, len); } - } + } else + dev->accel.frgd_color = val; } else { - if (mach->accel.cmd_type >= 0) { - if (mach_pixel_read(mach)) - break; + if (!dev->accel.cmd_back) { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; - mach->accel.pix_trans[1] = val; + mach->accel.pix_trans[1] = val; + } } } } else { if (len == 2) dev->accel.frgd_color = val; + + mach_log("%04X: Foreground Color=%04x.\n", port, val); } break; @@ -3396,40 +3490,42 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xe6e9: 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; + if (!dev->accel.cmd_back) { + 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; - mono_src = (mach->accel.dp_config >> 5) & 3; + mach->accel.pix_trans[0] = val; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; - switch (mach->accel.dp_config & 0x200) { - case 0x000: /*8-bit size*/ - if (mono_src == 2) { - if ((frgd_sel != 2) && (bkgd_sel != 2)) { - mach_accel_start(mach->accel.cmd_type, 1, 8, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, svga, mach, dev); + switch (mach->accel.dp_config & 0x200) { + case 0x000: /*8-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + mach_accel_start(mach->accel.cmd_type, 1, 8, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, svga, mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), svga, mach, dev); } else mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), svga, mach, dev); - } else - mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), svga, mach, dev); - break; - case 0x200: /*16-bit size*/ - if (mono_src == 2) { - if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if (mach->accel.dp_config & 0x1000) - mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[1] | (mach->accel.pix_trans[0] << 8), 0, svga, mach, dev); - else - mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, svga, mach, dev); + break; + case 0x200: /*16-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + if (mach->accel.dp_config & 0x1000) + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[1] | (mach->accel.pix_trans[0] << 8), 0, svga, mach, dev); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, svga, mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), svga, mach, dev); } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), svga, mach, dev); - } else - mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), svga, mach, dev); - break; + break; - default: - break; + default: + break; + } } } } @@ -3441,16 +3537,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xb2e8: case 0xb6e8: case 0xbae8: - case 0xeae8: - case 0xeee8: - case 0xf2e8: - case 0xf6e8: - case 0xfae8: ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xbee8: - case 0xfee8: ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { if ((dev->accel.multifunc_cntl >> 12) == 5) { @@ -3728,10 +3818,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } if (ATI_MACH32) { + mach_log("Load both SRC/DST GE Offset/Pitch=%03x, offset=%08x.\n", mach->shadow_set & 0x300, dev->accel.ge_offset); if ((mach->shadow_set & 0x300) == 0x000) { - mach_log("Load both SRC/DST GE Offset/Pitch.\n"); - mach->accel.ge_offset_lo = 0; - mach->accel.ge_offset_hi = 0; + mach->accel.ge_offset_lo = 0x0000; + mach->accel.ge_offset_hi = 0x0000; } } break; @@ -3856,10 +3946,14 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x8eee: if (len == 2) { + frgd_sel = (mach->accel.dp_config >> 13) & 7; + 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); + if ((dev->accel_bpp >= 24) && (frgd_sel == 5) && (mach->accel.patt_len == 0x17)) + dev->accel.y1 = 1; } 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; @@ -4103,6 +4197,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) dev->accel.cmd_back = 0; + if ((mach->accel.cmd_type == 3) && !dev->accel.cmd_back && (mach->accel.dp_config == 0x0000)) /*Avoid a hang with a dummy command.*/ + dev->accel.cmd_back = 1; + 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; @@ -4165,9 +4262,6 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in if (dev->force_busy) temp |= 0x0200; /*Hardware busy*/ - if (dev->accel.cmd_back) - dev->force_busy = 0; - if (dev->data_available) { temp |= 0x0100; /*Read Data available*/ if (mach->accel.cmd_type >= 0) { @@ -4623,7 +4717,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) } } - if (dev->accel.cmd_back) { + if (!dev->fifo_idx) { dev->force_busy = 0; dev->force_busy2 = 0; mach->force_busy = 0; @@ -4661,7 +4755,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) 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; + mach->accel.dp_config = 0x2011; break; case 0x22ee: @@ -4761,7 +4855,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) if (mach->force_busy) temp |= 0x20; - mach->force_busy = 0; if (ati_eeprom_read(&mach->eeprom)) temp |= 0x40; @@ -6076,7 +6169,8 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) if (svga->attrregs[0x10] & 0x40) { dev->vendor_mode = 0; dev->on &= ~0x01; - svga_recalctimings(svga); + mach_log("No 8514/A mode on b8000.\n"); + mach_set_resolution(mach, svga); } } } @@ -6892,7 +6986,6 @@ 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 (ATI_MACH32) { if (mach->pci_bus) { @@ -7016,6 +7109,7 @@ mach8_init(const device_t *info) io_sethandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); mach_io_set(mach); mach->accel.cmd_type = -2; + dev->accel.cmd_back = 1; if (ATI_MACH32) { svga->decode_mask = (4 << 20) - 1; @@ -7077,12 +7171,12 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) mach->accel.clock_sel = 0x1c; mach->shadow_set = 0x02; mach->crt_resolution = 0x02; + dev->accel.cmd_back = 1; 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 = 0x08 | 0x80; From 9c8c1a6f406aec432756ca19fdb4b8451bcd7260 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 2 Apr 2025 21:47:32 +0200 Subject: [PATCH 0662/1190] Trantor SCSI changes of the day (April 2nd, 2025) 1. The PAS SCSI controller driver mamv1.sys dislikes having bits 0-6 set when a transfer has completed, take account from this, fixes mamv1.sys incomplete CD transfers (bits 0-6 get re-enabled when the transfer is ongoing). 2. I now understand why the T128 doesn't have a block count register, it does the block count manually from the SCSI layer directly, this fixes Pseudo-DMA transfers when using, e.g.: CD transfers using a sector size of 2340 bytes. --- src/include/86box/scsi_device.h | 3 ++- src/include/86box/scsi_t128.h | 3 ++- src/scsi/scsi_t128.c | 29 +++++++++++------------------ src/sound/snd_pas16.c | 9 ++++++++- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 62da8b7dc..289201b04 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -467,9 +467,10 @@ typedef struct scsi_bus_t { int msgout_pos; int is_msgout; int state; - int dma_on_pio_enabled; uint32_t bus_phase; + uint32_t total_len; + uint32_t data_repeat; double period; double speed; diff --git a/src/include/86box/scsi_t128.h b/src/include/86box/scsi_t128.h index 65148a5d1..a3bc79335 100644 --- a/src/include/86box/scsi_t128.h +++ b/src/include/86box/scsi_t128.h @@ -30,7 +30,7 @@ typedef struct t128_t { uint8_t status; uint8_t buffer[512]; uint8_t ext_ram[0x80]; - uint8_t block_count; + uint32_t block_count; int block_loaded; int pos, host_pos; @@ -39,6 +39,7 @@ typedef struct t128_t { int bios_enabled; uint8_t pos_regs[8]; + int type; pc_timer_t timer; } t128_t; diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 3f273d1bb..94166054c 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -130,12 +130,12 @@ t128_read(uint32_t addr, void *priv) (t128->host_pos < MIN(512, dev->buffer_length))) { ret = t128->buffer[t128->host_pos++]; - t128_log("T128 Read transfer: pos=%i, addr=%x.\n", - t128->host_pos, addr & 0x1ff); + t128_log("T128 Read transfer: pos=%i, addr=%x, enabled timer=%d.\n", + t128->host_pos, addr & 0x1ff, timer_is_enabled(&t128->timer)); if (t128->host_pos == MIN(512, dev->buffer_length)) { - t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n", - t128->status, scsi_bus->period, timer_is_enabled(&t128->timer)); + t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d, block=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), scsi_bus->data_pos); t128->status &= ~0x04; if (!t128->block_loaded) { @@ -192,10 +192,6 @@ t128_dma_send_ext(void *priv, void *ext_priv) t128_log("T128 DMA OUT, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); t128->host_pos = 0; - t128->block_count = dev->buffer_length >> 9; - - if (dev->buffer_length < 512) - t128->block_count = 1; t128->block_loaded = 1; t128->status |= 0x04; @@ -215,10 +211,6 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) t128_log("T128 DMA IN, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); t128->host_pos = MIN(512, dev->buffer_length); - t128->block_count = dev->buffer_length >> 9; - - if (dev->buffer_length < 512) - t128->block_count = 1; t128->block_loaded = 1; t128->status &= ~0x04; @@ -295,9 +287,9 @@ t128_callback(void *priv) t128->status &= ~0x02; t128->pos = 0; t128->host_pos = 0; - t128->block_count = (t128->block_count - 1) & 0xff; + scsi_bus->data_repeat = 0; t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); - if (!t128->block_count) { + if (scsi_bus->data_pos >= dev->buffer_length) { t128->block_loaded = 0; ncr->tcr |= TCR_LAST_BYTE_SENT; ncr->isr |= STATUS_END_OF_DMA; @@ -344,11 +336,11 @@ t128_callback(void *priv) t128->status &= ~0x02; t128->pos = 0; t128->host_pos = 0; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be read=%d\n", t128->block_count); - if (!t128->block_count) { - t128->block_loaded = 0; + scsi_bus->data_repeat = 0; + t128_log("T128 blocks read=%d, total len=%d\n", scsi_bus->data_pos, dev->buffer_length); + if (scsi_bus->data_pos >= dev->buffer_length) { scsi_bus->bus_out |= BUS_REQ; + t128->block_loaded = 0; timer_on_auto(&t128->timer, 10.0); t128_log("IO End of read transfer\n"); } @@ -472,6 +464,7 @@ t128_init(const device_t *info) ncr->bus = scsi_get_bus(); scsi_bus = &ncr->scsibus; + t128->type = info->local; if (info->flags & DEVICE_MCA) { rom_init(&t128->bios_rom, T128_ROM, diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 675582367..dd95eac4c 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -792,7 +792,14 @@ pas16_in(uint16_t port, void *priv) if ((scsi_bus->tx_mode == PIO_TX_BUS) && !(ret & 0x80)) ret |= 0x80; - pas16_log("5C01 read ret=%02x, status=%02x, txmode=%x.\n", ret, pas16->scsi->status & 0x06, scsi_bus->tx_mode); + if (ret & 0x80) { + if (scsi_bus->data_repeat < MIN(511, scsi_bus->total_len)) + scsi_bus->data_repeat++; + } else { + if (scsi_bus->data_repeat == MIN(511, scsi_bus->total_len)) + ret = 0x00; + } + pas16_log("%04X:%08X: Port %04x read ret=%02x, status=%02x, txmode=%x, repeat=%d.\n", CS, cpu_state.pc, port + pas16->base, ret, pas16->scsi->status & 0x06, scsi_bus->tx_mode, scsi_bus->data_repeat); } break; case 0x5c03: From 4bd374a7dfcceebac5249fb01409c7395762bb6d Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 2 Apr 2025 16:55:57 -0300 Subject: [PATCH 0663/1190] Don't apply the Deschutes cacheability fix to Covington --- src/cpu/cpu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 61bd8bf36..ffe582604 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2651,8 +2651,9 @@ cpu_ven_reset(void) msr.mtrr_cap = 0x00000508ULL; /* 4 GB cacheable space on Deschutes 651h and later (including the 1632h - Overdrive) according to the Pentium II Processor Specification Update. */ - if (cpu_s->cpuid_model >= 0x651) + Overdrive) according to the Pentium II Processor Specification Update. + Covington 651h (no L2 cache) reports the same 512 MB value as Klamath. */ + if (CPUID >= (!strncmp(cpu_f->internal_name, "celeron", 7) ? 0x660 : 0x651)) msr.bbl_cr_ctl3 |= 0x00300000; break; From cfc8e0dc4e6780bbdbbfb81ef6ac267730e21fb9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 3 Apr 2025 06:17:27 +0200 Subject: [PATCH 0664/1190] Settings Storage Devices: No longer cut off the second SCSI controller. --- src/qt/qt_settingsstoragecontrollers.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index eebed79e2..002b9e1d3 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -195,12 +195,10 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) if (scsi_card_available(c)) { if (device_is_valid(scsi_card_getdevice(c), machineId)) { for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { - if ((c != 1) || ((i == 0) && m_has_scsi)) { - int row = Models::AddEntry(models[i], name, c); + int row = Models::AddEntry(models[i], name, c); - if (c == scsi_card_current[i]) - selectedRows[i] = row - removeRows_[i]; - } + if (c == scsi_card_current[i]) + selectedRows[i] = row - removeRows_[i]; } } } From df7acc618bccd33d504e8a5fa5d1a0e53e72ee0b Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 3 Apr 2025 06:19:36 +0200 Subject: [PATCH 0665/1190] Remove the now unused variable m_has_scsi. --- src/qt/qt_settingsstoragecontrollers.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 002b9e1d3..9bd1bda6f 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -176,7 +176,6 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) QAbstractItemModel *models[SCSI_CARD_MAX] = { 0 }; int removeRows_[SCSI_CARD_MAX] = { 0 }; int selectedRows[SCSI_CARD_MAX] = { 0 }; - int m_has_scsi = machine_has_flags(machineId, MACHINE_SCSI); for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) { cbox[i] = findChild(QString("comboBoxSCSI%1").arg(i + 1)); From c63d900a9383b74fbd8a5fa7209a0b2a6364a913 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 3 Apr 2025 06:35:53 +0200 Subject: [PATCH 0666/1190] CMS: Divide SAA samples by 2 so that the sum remains within the -32767 to 32768 range and avoids clipping. --- src/sound/snd_cms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index c6591b1fc..9491e3076 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -34,7 +34,7 @@ cms_get_buffer(int32_t *buffer, int len, void *priv) cms_update(cms); for (int c = 0; c < len * 2; c++) - buffer[c] += cms->buffer[c]; + buffer[c] += (cms->buffer[c] / 2); cms->pos = 0; } @@ -47,7 +47,7 @@ cms_get_buffer_2(int32_t *buffer, int len, void *priv) cms_update(cms); for (int c = 0; c < len * 2; c++) - buffer[c] += cms->buffer2[c]; + buffer[c] += (cms->buffer2[c] / 2); cms->pos2 = 0; } From fc06d3de89dfd58eb497f1e6b8d09cb0dbbfaa13 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:16:58 +0900 Subject: [PATCH 0667/1190] PS55DA2: add char drawing func in BitBlt This build is still in work. * Added character drawing function to support for DOS/V Extension DSPXDA2 driver. * Implement CRTC regs: start address, end address, line compare to support line compare scrolling in DOS/V Extension. * Enable updating CRTC regs when output is disabled. --- src/video/vid_ps55da2.c | 424 +++++++++++++++++++++++++++------------- 1 file changed, 290 insertions(+), 134 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1f00b7cc5..1875726b5 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -66,7 +66,7 @@ #define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */ #define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ #define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */ -#define DA2_BLT_MEMSIZE 0x100 +#define DA2_BLT_MEMSIZE 0x1000 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) #define DA2_DEBUG_BLTLOG_MAX (256 * 1024) @@ -112,8 +112,8 @@ EFD8h * Display Adapter/J [Atlas-SP2] [Japanese DOS and Display Adapter compatibility] - | | | K3.31 | J4.04 | J4.08 | OS2J1.3 | Win3.02 | DOSVExt | - | POS ID | Adapter Name | 5605JBK | 5605PAA | 5605PCA | 5605PDE | 5605PAW | 5605PXA | + | | | 5605JBK | 5605PAA | 5605PCA | 5605PDE | 5605PAW | 5605PXB | + | POS ID | Adapter Name | K3.31 | J4.05 | J4.08 | J1.33 | 3.02 | 2.0 | |------------|-----------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| | EFFFh | Display Adapter | X | | | | | | | FFEDh | ? [Atlas EVT] | X | | | | | | @@ -124,7 +124,14 @@ | ECECh | Display Adapter IV,B1 | | X | X | X | X | X | | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | X | | EFD8h | Display Adapter /J | | | X | X | X | X | -*/ + + - 5605JBK : Japanese DOS K3.3, K3.4 (for PS/55 model 55xx-S, T, V, Z) + - 5605PAA : DOS J4.0 + - 5605PCA : DOS J4.0 (with MKK) + - 5605PDE : OS/2 Extended Edition J1.3 + - 5605PAW : Japanese Microsoft Windows 3.0 (IBMJ OEM) + - 5605PXB : DOS/V Extension V2.0 + */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ #define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ // #define Mon_ID3 0x10 @@ -163,8 +170,10 @@ #define LF_INDEX 0x3e2 #define LF_DATA 0x3e3 #define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_09 0x09 /* added */ #define LF_MMIO_ADDR 0x0A /* added */ #define LF_MMIO_MODE 0x0B /* added */ +#define LF_PD_RESET 0x18 /* added */ #define LC_INDEX 0x3E4 #define LC_DATA 0x3E5 #define LC_HORIZONTAL_TOTAL 0x00 @@ -251,12 +260,12 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -// #define ENABLE_DA2_LOG 1 +#define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG // # define ENABLE_DA2_DEBUGIO 1 -// # define ENABLE_DA2_DEBUGBLT 1 +# define ENABLE_DA2_DEBUGBLT 1 // # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 @@ -328,7 +337,7 @@ typedef struct da2_t { int vtotal, dispend, vsyncstart, split, vblankstart; int hdisp, htotal, hdisp_time, rowoffset; - int lowres, interlace; + int lowres; int rowcount; double clock; uint32_t ma_latch, ca_adj; @@ -343,7 +352,7 @@ typedef struct da2_t { uint32_t ma, maback, ca; int vc; int sc; - int linepos, vslines, linecountff, oddeven; + int linepos, vslines, linecountff; int con, cursoron, blink, blinkconf; int scrollcache; int char_width; @@ -457,6 +466,53 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) da2->vram[addr] = val; return; } +/* get font data for bitblt operation */ +static uint32_t +getFontIBMJ(int32_t code, int line, int x, void *p) +{ + da2_t *da2 = (da2_t *) p; + uint32_t font = 0; + int fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ + if (code < 0x100) { /* SBCS 13x29 */ + code *= 0x40; + code += DA2_GAIJIRAM_SBCS + (line * 2) + x; + font = da2->mmio.ram[code]; + font <<= 8; + font |= da2->mmio.ram[code + 1]; + font <<= 16; + return font; + } + if ((code >= 0x8000) && (code <= 0x8183)) + code -= 0x6000; /* shift for IBM extended characters */ + if ((code < (DA2_FONTROM_SIZE / 72)) && (fline >= 0) && (fline < 24)) { /* DBCS 24x24 */ + code = (code * 72) + (fline * 3) + x; + // font = da2->mmio.font[code]; /* 0000 0000 0000 0000 0000 0000 1111 1111 */ + // font <<= 8; /* 0000 0000 0000 0000 1111 1111 0000 0000 */ + // font |= da2->mmio.font[code + 1] & 0xf0; /* 0000 0000 0000 0000 1111 1111 2222 0000 */ + // font <<= 3; /* 0000 0000 0000 0111 1111 1222 2000 0000 */ + // font |= da2->mmio.font[code + 1] & 0x0f; /* 0000 0000 0000 0111 1111 1222 2000 2222 */ + // font <<= 8; /* 0000 0111 1111 1222 2000 2222 0000 0000 */ + // font |= da2->mmio.font[code + 2]; /* 0000 0111 1111 1222 2000 2222 3333 3333 */ + // font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ + } else if ((code >= 0xb000) && (code <= 0xb75f)) { /* DBCS 26x29 */ + /* convert code->address in gaiji memory */ + code -= 0xb000; + code = (code * 0x80) + (line * 4) + x; + font = da2->mmio.ram[code]; + font <<= 8; + font |= da2->mmio.ram[code + 1]; + font <<= 8; + font |= da2->mmio.ram[code + 2]; + font <<= 8; + font |= da2->mmio.ram[code + 3]; + // font <<= 16; + } else if (code > (DA2_FONTROM_SIZE / 72)) + font = 0xffffffffu; + else + font = 0; + return font; +} + /* write pixel data with rop (Note: bitmask must be in big endian) */ static void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) @@ -482,6 +538,11 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s for (int i = 0; i < 8; i++) { if (da2->bitblt.bitshift_destr > 0) srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; +// #ifdef ENABLE_DA2_DEBUGBLT +// if (i == 0) { +// pclog("writeplane: src %08X mask %08X dest %08X\n", srcpx->p8[i], mask32.d, writepx[i]); +// } +// #endif if (da2->bitblt.raster_op & 0x2010) /* NOT Src or NOT Pattern */ srcpx->p8[i] = ~srcpx->p8[i] & mask32.d; if (da2->bitblt.raster_op & 0x20) /* Dest NOT */ @@ -560,24 +621,68 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } +/* Reverse the bit order of attribute code IBGR to IRGB(used in Mode 3 and Cursor Color) */ +static int8_t +IBGRtoIRGB(uint8_t attr) +{ + attr = ((attr & 0x01) << 6) | ((attr & 0x02) << 4) | ((attr & 0x04) << 2) | ((attr & 0x08) << 4); + return attr >>= 4; +} static void -DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) +DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, uint32_t destaddr, uint16_t maskl, uint16_t maskr, da2_t *da2) { pixel32 srcpx; - if (srcaddr >= DA2_FONTROM_SIZE) { - da2_log("DA2 Putchar Addr Error %x\n", srcaddr); - return; + // if (codeIBMJ >= DA2_FONTROM_SIZE / 72) { + // da2_log("DA2 Putchar Addr Error %x\n", srcaddr); + // return; + // } + uint8_t color = (~attr >> 8) & 0x0f; + // color = IBGRtoIRGB(color); + uint8_t bg = (~attr >> 12) & 0x0f; + // bg = 0x00; + // bg = IBGRtoIRGB(bg); + uint32_t font = getFontIBMJ(codeIBMJ, line, 0, da2); + uint32_t fontinv; + if (width == 1) { + fontinv = ~font; + for (int i = 0; i < 8; i++) { + srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0; + srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; + } + pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); + DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); + for (int i = 0; i < 8; i++) { + srcpx.p8[i] = (color & (1 << i)) ? font : 0; + srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; + } + pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); + DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); + } else { + font = (font & 0xfff80000) | ((font & 0x0000ffff) << 3); + fontinv = ~font; + pclog("putchar: ft %08X shftr %X\n", font, da2->bitblt.bitshift_destr); + for (int i = 0; i < 8; i++) { + srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0; + srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; + } + // pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskl); + DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); + for (int i = 0; i < 8; i++) { + srcpx.p8[i] = (color & (1 << i)) ? font : 0; + srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; + } + // pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskr); + DA2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); + for (int i = 0; i < 8; i++) { + srcpx.p8[i] = (color & (1 << i)) ? font << 16 : 0; + srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0; + } + // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[3], maskl, maskr); + DA2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2); } - for (int i = 0; i < 8; i++) - srcpx.p8[i] = ((uint32_t) da2->mmio.font[srcaddr] << 24) - | ((uint32_t) da2->mmio.font[srcaddr + 1] << 16) - | ((uint32_t) da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t) da2->mmio.font[srcaddr + 3] << 0); - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } #ifdef ENABLE_DA2_DEBUGBLT -uint8_t +static uint8_t pixel1tohex(uint32_t addr, int index, da2_t *da2) { uint8_t pixeldata = 0; @@ -587,14 +692,14 @@ pixel1tohex(uint32_t addr, int index, da2_t *da2) } return pixeldata; } -void +static void print_pixelbyte(uint32_t addr, da2_t *da2) { for (int i = 0; i < 8; i++) { pclog("%X", pixel1tohex(addr, i, da2)); } } -void +static void print_bytetobin(uint8_t b) { for (int i = 0; i < 8; i++) { @@ -606,17 +711,17 @@ print_bytetobin(uint8_t b) } } /* Convert internal char code to Shift JIS code */ -inline int +static int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } -inline int +static int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } -uint16_t +static uint16_t IBMJtoSJIS(uint16_t knj) { if (knj < 0x100) @@ -710,6 +815,27 @@ da2_bitblt_load(da2_t *da2) // da2->gdcreg[da2->bitblt.payload[i + 1]] = value64; i += 7; break; + case 0xa1: + value64 = da2->bitblt.payload[i + 9]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 8]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7], da2->bitblt.payload[i + 8], da2->bitblt.payload[i + 9]); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + i += 9; + break; case 0x00: break; default: @@ -734,14 +860,15 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.debug_reg_ip = 0; da2->bitblt.debug_exesteps = 0; #endif - da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ + da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0xb], CS, cpu_state.pc); + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x03] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b]; da2->bitblt.destaddr = da2->bitblt.reg[0x29]; da2->bitblt.size_x = da2->bitblt.reg[0x33]; da2->bitblt.size_y = da2->bitblt.reg[0x35]; da2->bitblt.destpitch = da2->bitblt.reg[0x21]; da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + /* 80h = 128d = 10000000b, 90h = 144d = 10010000b, B0h = 176d = 10110000 */ if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; @@ -757,7 +884,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.exec = DA2_BLT_CDONE; /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ - if (da2->bitblt.reg[0x10] == 0xbc04) { + if (!(da2->bitblt.reg[0xb] & 0x08)) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ // if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ @@ -767,29 +894,22 @@ da2_bitblt_load(da2_t *da2) // da2->bitblt.destpitch += 2; // da2->bitblt.srcpitch += 2; // } - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; + da2->bitblt.fcolor = da2->bitblt.reg[0x1]; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; - da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; - da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); -#endif - } - /* Put SBCS char used by OS/2 */ - else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { - da2->bitblt.exec = DA2_BLT_CPUTCHAR; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; - da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; - da2->bitblt.bitshift_destr += 1; -#ifdef ENABLE_DA2_DEBUGBLT - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + uint8_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint8_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + if (da2->bitblt.reg[0x12] < 0x100) { + sjis_h = 0x20; + sjis_l = da2->bitblt.reg[0x12]; + } else { + if (!(isKanji1(sjis_h))) + sjis_h = 0x3f; + if (!(isKanji2(sjis_l))) + sjis_l = 0x3f; + } da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), @@ -1040,49 +1160,35 @@ da2_bitblt_exec(void *p) da2->bitblt.srcaddr -= 2; break; case DA2_BLT_CPUTCHAR: /* used in OS/2 J1.3 wo ROM patch. TODO: still not work */ - // da2->bitblt.y += 2; - da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - // pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.y * 130; // da2->bitblt.srcaddr += 2; - if (da2->bitblt.reg[0x12] < 0x100) - da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; - else - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - // print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - // print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - // pclog("\n"); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - // if (1) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 3) { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; + // if (da2->bitblt.reg[0x12] < 0x100) + // da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + // else + // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + pclog("scr %x dest %x x %x y %x\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.y >= da2->bitblt.size_y) { + da2->bitblt.exec = DA2_BLT_CDONE; + } else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2); + } da2->bitblt.y++; da2->bitblt.destaddr += 130; - // da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - // da2->bitblt.srcaddr += -1; - } else if (da2->bitblt.x == 0) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - // da2->bitblt.x++; - } else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - // da2->bitblt.x++; - } + // } // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; ////da2->bitblt.srcaddr += 2; // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; break; case DA2_BLT_CDONE: - if (!(da2->bitblt.reg[0x20] & 0x20)) { - /* initialize regs and set magic value for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) - da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } - } else /* without init regs */ + // if (!(da2->bitblt.reg[0x20] & 0x20)) { + // /* initialize regs and set magic value for debug dump */ + // for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + // if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) + // da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + // } + // } else /* without init regs */ da2->bitblt.reg[0x20] = 0; /* need to stop execution */ if (da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; @@ -1193,6 +1299,10 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) { da2_iolog("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + } else if ((da2->fctladdr == LF_PD_RESET) && ((val & 0x7) == 7)) { + /* Reset Bitblt busy */ + da2->bitblt.indata = 0; + da2->bitblt.exec = DA2_BLT_CIDLE; } break; case LC_INDEX: @@ -1214,10 +1324,12 @@ da2_out(uint16_t addr, uint16_t val, void *p) val = 0; break; case LC_START_ADDRESS_HIGH: + // if (val == 0xff) /* adjust (need to confirm) */ + // val = 0; case LC_START_ADDRESS_LOW: /* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00. OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */ - val = 0; + // val = 0; break; case LC_VERTICAL_TOTALJ: /* Vertical Total */ case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ @@ -1227,25 +1339,21 @@ da2_out(uint16_t addr, uint16_t val, void *p) val = 0x400; /* for debugging bitblt in Win 3.x */ #endif break; - case LC_VIEWPORT_SELECT: /* ViewPort Select? */ - // return; - break; - case LC_VIEWPORT_NUMBER: /* Compatibility? */ - break; } da2->crtc[da2->crtcaddr] = val; switch (da2->crtcaddr) { case LC_H_DISPLAY_ENABLE_END: case LC_VERTICAL_TOTALJ: case LC_MAXIMUM_SCAN_LINE: - // case LC_START_ADDRESS_HIGH: - // case LC_START_ADDRESS_LOW: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: case LC_VERTICAL_SYNC_START: case LC_V_DISPLAY_ENABLE_END: case LC_START_VERTICAL_BLANK: case LC_START_H_DISPLAY_ENAB: case LC_START_V_DISPLAY_ENAB: case LC_VIEWPORT_PRIORITY: + case LC_LINE_COMPAREJ: da2->fullchange = changeframecount; da2_recalctimings(da2); break; @@ -1432,7 +1540,7 @@ da2_in(uint16_t addr, void *p) // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } - if (da2->bitblt.indata) temp |= 0x08; + // if (da2->bitblt.indata) temp |= 0x08; #ifdef ENABLE_DA2_DEBUGMONWAIT da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); #endif @@ -1464,6 +1572,10 @@ da2_in(uint16_t addr, void *p) da2->cgastat &= ~0x30; else da2->cgastat ^= 0x30; /* toggle */ + if (da2->cgastat & 0x08) + da2->cgastat &= ~0x08; + else + da2->cgastat ^= 0x08; /* toggle */ temp = da2->cgastat; } else temp = da2->attrc[da2->attraddr]; @@ -1496,7 +1608,7 @@ static void da2_outb(uint16_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; - // 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_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: @@ -2195,17 +2307,18 @@ da2_recalctimings(da2_t *da2) double crtcconst; double _dispontime, _dispofftime, disptime; - /* if output disabled or VGA passthrough */ - if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { - da2->render = da2_render_blank; - return; - } + // /* if output disabled or VGA passthrough */ + // if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { + // da2->render = da2_render_blank; + // return; + // } da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff; da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff; - da2->split = 0xfff; + da2->split -= 1; + // da2->split = 0xfff; da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; @@ -2225,17 +2338,23 @@ da2_recalctimings(da2_t *da2) // da2->interlace = 0; - // da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW];//w + b + if (da2->crtc[LC_VIEWPORT_SELECT] & 0x80 || da2->split == 0) + da2->ma_latch = 0; + else + da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; // w + b + da2->ca_adj = 0; - da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; - da2->hdisp_time = da2->hdisp; da2->render = da2_render_blank; /* determine display mode */ // if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + /* if output disabled or VGA passthrough */ + if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { + da2->render = da2_render_blank; + // return; /* 16 color graphics mode */ - if (!(da2->ioctl[LS_MODE] & 0x01)) { + } else if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { @@ -2294,7 +2413,7 @@ da2_recalctimings(da2_t *da2) 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("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); + da2_log("da2 linecompare %d\n", da2->split); } static void @@ -2452,7 +2571,7 @@ da2_mmio_read(uint32_t addr, void *p) uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x40; + addr += index * 0x80; } // da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { @@ -2475,6 +2594,7 @@ da2_mmio_read(uint32_t addr, void *p) return da2->mmio.font[addr]; break; default: + da2_log("PS55_MemHnd: Invalid read mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return DA2_INVALIDACCESS8; /* invalid memory access */ break; } @@ -2549,35 +2669,56 @@ da2_mmio_readw(uint32_t addr, void *p) return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } } - +static void +da2_bitblt_addpayload(uint8_t val, void *p) +{ + da2_t *da2 = (da2_t *) p; + da2->bitblt.indata = 1; + if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! addr %x, val %x\n", da2->bitblt.payload_addr, val); + else { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + } +} static void da2_mmio_write(uint32_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; + uint32_t index = 0; // da2_log("da2_mmio_write %x %x\n", addr, val); // if ((addr & ~DA2_MASK_MMIO) != 0xA0000) // return; addr &= DA2_MASK_MMIO; - if (da2->ioctl[LS_MMIO] & 0x10) { + if (da2->ioctl[LS_MMIO] == 0x1f) {/* write bitblt fifo data */ + da2_bitblt_addpayload(val, da2); + } + else if (da2->ioctl[LS_MMIO] & 0x10) { /* access to gaiji ram */ // if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); /* Gaiji RAM */ if (da2->fctl[LF_MMIO_SEL] == 0x80) addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); /* xxxy yyyy yyyy yyyy yyyy */ - else { - uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + else { + index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x40; + // addr += index * 0x40; + // addr += index * 0x80; + // da2_log("da2_mmio_w io %x, sl %x, 09 %x, ad %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO],da2->fctl[LF_MMIO_SEL], + // da2->fctl[LF_MMIO_09],da2->fctl[LF_MMIO_ADDR], da2->fctl[LF_MMIO_MODE], addr, val); } - switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0: /* Gaiji RAM 1011 0000 */ + switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { + case 0xb0: /* Gaiji RAM 1011 0000 */ + addr += index * 0x80; da2->mmio.ram[addr & DA2_MASK_GAIJIRAM] = val; break; case 0x10: /* Font ROM 0001 0000 */ /* Read-Only */ break; - case 0x00: + case 0x00: /* SBCS in Gaiji RAM (used by DOS/V Extension DSPXDA2 driver) */ + addr += index * 0x40; + da2->mmio.ram[(DA2_GAIJIRAM_SBCS + addr) & DA2_MASK_GAIJIRAM] = val; // da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); // addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ // if (addr >= DA2_BLT_MEMSIZE) @@ -2585,16 +2726,9 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); // return; // } - da2->bitblt.indata = 1; - if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) - da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - else { - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - } break; default: - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + da2_log("da2_mmio_write failed io %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO] ,da2->fctl[LF_MMIO_MODE], addr, val); break; } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ @@ -2802,15 +2936,21 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) // return; // if ((addr & ~0x1ffff) != 0xA0000) return; if (da2->ioctl[LS_MMIO] & 0x10) { - // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); +#ifdef ENABLE_DA2_DEBUGVRAM + da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); +#endif da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ - // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); +#ifdef ENABLE_DA2_DEBUGVRAM + da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); +#endif da2_mmio_gc_writeW(addr, val, da2); } else { /* mode 3h text */ +#ifdef ENABLE_DA2_DEBUGVRAM // if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_log("da2_mmio_write3W %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); +#endif da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } @@ -2836,7 +2976,7 @@ da2_code_writeb(uint32_t addr, uint8_t val, void *p) static void da2_code_writew(uint32_t addr, uint16_t val, void *p) { - // da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + // da2_log("DA2_code_writ ew: Write to %x, val %x\n", addr, val); da2_t *da2 = (da2_t *) p; cycles -= video_timing_write_w; da2_code_write(addr, val & 0xff, da2); @@ -2945,8 +3085,6 @@ da2_poll(void *priv) da2->sc = 0; da2->maback += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */ - if (da2->interlace) - da2->maback += (da2->rowoffset << 1); da2->maback &= da2->vram_display_mask; da2->ma = da2->maback; } else { @@ -2959,6 +3097,13 @@ da2_poll(void *priv) da2->vc++; da2->vc &= 2047; + if (da2->vc == da2->split) { + // da2->ma = da2->maback = da2->hblank_sub; + da2->ma = da2->maback = 0; + da2->sc = 0; + // da2->displine = 0; + } + if (da2->vc == da2->dispend) { da2->dispon = 0; // if (da2->crtc[10] & 0x20) da2->cursoron = 0; @@ -3002,13 +3147,11 @@ da2_poll(void *priv) da2->firstline_draw = 2000; da2->lastline_draw = 0; - da2->oddeven ^= 1; - - changeframecount = da2->interlace ? 3 : 2; + changeframecount = 2; da2->vslines = 0; da2->ma - = da2->maback = da2->ma_latch; + = da2->maback = da2->ma_latch << 1; da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; da2->ca <<= 1; @@ -3020,7 +3163,7 @@ da2_poll(void *priv) da2->vc = 0; da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; - da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + da2->displine = 0; da2->scrollcache = da2->attrc[LV_PANNING] & 7; } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) @@ -3111,7 +3254,6 @@ da2_reset(void *priv) da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ da2->ma_latch = 0; - da2->interlace = 0; da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ @@ -3245,6 +3387,12 @@ da2_close(void *p) fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); fclose(f); } + f = fopen("ram_low.dmp", "wb"); + if (f != NULL) { + fwrite(&ram[0x0], 0x100000, 1, f); + fclose(f); + } + pclog("closed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); #endif #ifdef ENABLE_DA2_DEBUGBLT f = fopen("da2_bltdump.csv", "w"); @@ -3262,8 +3410,16 @@ da2_close(void *p) ; else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) fprintf(f, "\"\"\t"); - else + else { fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); + if (y == 0x12) { + int chr = da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + 0x12]; + if ((chr >= 0x20) && (chr < 0x7f)) + fprintf(f, "\"%c\"\t", chr); + else + fprintf(f, "\"\"\t"); + } + } } fprintf(f, "\n"); } From 837f86a291e5bf696cd327b01a6d544901e052f4 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 3 Apr 2025 22:17:24 +0900 Subject: [PATCH 0668/1190] PS55DA2: Parse Bitblt data sequential --- src/video/vid_ps55da2.c | 212 +++++++++++++++++++++++----------------- 1 file changed, 124 insertions(+), 88 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1875726b5..613eb5888 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -66,7 +66,7 @@ #define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */ #define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ #define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */ -#define DA2_BLT_MEMSIZE 0x1000 +#define DA2_BLT_MEMSIZE 0x10 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) #define DA2_DEBUG_BLTLOG_MAX (256 * 1024) @@ -264,7 +264,7 @@ #endif #ifdef ENABLE_DA2_LOG -// # define ENABLE_DA2_DEBUGIO 1 +# define ENABLE_DA2_DEBUGIO 1 # define ENABLE_DA2_DEBUGBLT 1 // # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 @@ -292,6 +292,12 @@ da2_log(const char *fmt, ...) #endif #ifdef ENABLE_DA2_DEBUGBLT # define da2_bltlog da2_log +# define ENABLE_DA2_DEBUGBLT_DETAIL 1 +# ifdef ENABLE_DA2_DEBUGBLT_DETAIL +# define da2_bltreglog da2_log +# else +# define da2_bltreglog(fmt, ...) +# endif #else # define da2_bltlog(fmt, ...) #endif @@ -390,6 +396,7 @@ typedef struct da2_t { int raster_op; uint8_t payload[DA2_BLT_MEMSIZE]; int payload_addr; + int payload_opsize; int32_t reg[DA2_BLT_REGSIZE]; // must be signed int #ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug @@ -643,24 +650,24 @@ DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui // bg = IBGRtoIRGB(bg); uint32_t font = getFontIBMJ(codeIBMJ, line, 0, da2); uint32_t fontinv; - if (width == 1) { + if (width <= 2) { fontinv = ~font; for (int i = 0; i < 8; i++) { srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } - pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); + // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); for (int i = 0; i < 8; i++) { srcpx.p8[i] = (color & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } - pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); + // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); } else { font = (font & 0xfff80000) | ((font & 0x0000ffff) << 3); fontinv = ~font; - pclog("putchar: ft %08X shftr %X\n", font, da2->bitblt.bitshift_destr); + // pclog("putchar: ft %08X shftr %X\n", font, da2->bitblt.bitshift_destr); for (int i = 0; i < 8; i++) { srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; @@ -752,106 +759,103 @@ IBMJtoSJIS(uint16_t knj) return knj; } #endif + static void -da2_bitblt_load(da2_t *da2) +da2_bitblt_parse(da2_t *da2) { uint32_t value32; uint64_t value64; #ifdef ENABLE_DA2_DEBUGBLT - da2_log("bltload: loading params\n"); - da2_log("BitBlt memory:\n"); - if (da2->bitblt.payload[0] != 0) - for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - { - int i = j * 8; - da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - } + // da2_log("bltload: loading params\n"); + // da2_log("BitBlt memory:\n"); + // if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], + // da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7]); + // } #endif - int i = 0; - while (i < da2->bitblt.payload_addr) { - if (da2->bitblt.reg[0x20] & 0x1) - break; - switch (da2->bitblt.payload[i]) { + switch (da2->bitblt.payload[0]) { case 0x88: case 0x89: case 0x95: - value32 = da2->bitblt.payload[i + 3]; + value32 = da2->bitblt.payload[3]; value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_bltlog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - // da2->gdcreg[da2->bitblt.payload[i + 1]] = value32; - i += 3; + value32 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[0], da2->bitblt.payload[1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[1]] = value32; break; case 0x91: - value32 = da2->bitblt.payload[i + 5]; + value32 = da2->bitblt.payload[5]; value32 <<= 8; - value32 |= da2->bitblt.payload[i + 4]; + value32 |= da2->bitblt.payload[4]; value32 <<= 8; - value32 |= da2->bitblt.payload[i + 3]; + value32 |= da2->bitblt.payload[3]; value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_bltlog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - // da2->gdcreg[da2->bitblt.payload[i + 1]] = value32; - i += 5; + value32 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[0], da2->bitblt.payload[1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[1]] = value32; break; case 0x99: - value64 = da2->bitblt.payload[i + 7]; + value64 = da2->bitblt.payload[7]; value64 <<= 8; - value64 = da2->bitblt.payload[i + 6]; + value64 = da2->bitblt.payload[6]; value64 <<= 8; - value64 = da2->bitblt.payload[i + 5]; + value64 = da2->bitblt.payload[5]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 4]; + value64 |= da2->bitblt.payload[4]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 3]; + value64 |= da2->bitblt.payload[3]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 2]; - da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - // da2->gdcreg[da2->bitblt.payload[i + 1]] = value64; - i += 7; + value64 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[0], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], + da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7]); + da2->bitblt.reg[da2->bitblt.payload[1]] = value64; break; case 0xa1: - value64 = da2->bitblt.payload[i + 9]; + value64 = da2->bitblt.payload[9]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 8]; + value64 |= da2->bitblt.payload[8]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 7]; + value64 |= da2->bitblt.payload[7]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 6]; + value64 |= da2->bitblt.payload[6]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 5]; + value64 |= da2->bitblt.payload[5]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 4]; + value64 |= da2->bitblt.payload[4]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 3]; + value64 |= da2->bitblt.payload[3]; value64 <<= 8; - value64 |= da2->bitblt.payload[i + 2]; - da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7], da2->bitblt.payload[i + 8], da2->bitblt.payload[i + 9]); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - i += 9; + value64 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[0], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], + da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7], da2->bitblt.payload[8], da2->bitblt.payload[9]); + da2->bitblt.reg[da2->bitblt.payload[1]] = value64; break; - case 0x00: + case 0x00: /* Win 3.0 Clock writes invalid zero data. */ break; default: da2_log("bltload: Unknown PreOP!\n"); break; } - i++; + if (da2->bitblt.reg[0x20] & 0x01) { /* Execute Bitblt immediately (for OS/2 J1.3) */ + da2->bitblt.exec = DA2_BLT_CLOAD; + da2_bitblt_exec(da2); } - da2->bitblt.exec = DA2_BLT_CIDLE; /* clear payload memory */ memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); da2->bitblt.payload_addr = 0; + da2->bitblt.indata = 0; +} + +static void +da2_bitblt_load(da2_t *da2) +{ /* [89] 20: 0001 (1) then execute payload */ - if (da2->bitblt.reg[0x20] & 0x1) { + // if (da2->bitblt.reg[0x20] & 0x1) { + da2->bitblt.reg[0x20] = 0; /* need to stop execution */ #ifdef ENABLE_DA2_DEBUGBLT - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + for (int i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; } da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; @@ -860,7 +864,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.debug_reg_ip = 0; da2->bitblt.debug_exesteps = 0; #endif - da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0xb], CS, cpu_state.pc); da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x03] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b]; da2->bitblt.destaddr = da2->bitblt.reg[0x29]; @@ -869,7 +872,11 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.destpitch = da2->bitblt.reg[0x21]; da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; /* 80h = 128d = 10000000b, 90h = 144d = 10010000b, B0h = 176d = 10110000 */ - if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ + /* + DOS/V Extension 1040x725 some DBCS uses 0xB0 others 0x90 + B0: BitShift is 1-6 + */ + if (da2->bitblt.reg[0x2F] & 0x10) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; da2->bitblt.size_x += 1; @@ -897,7 +904,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.fcolor = da2->bitblt.reg[0x1]; da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; + // da2->bitblt.srcpitch = 0; #ifdef ENABLE_DA2_DEBUGBLT uint8_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; uint8_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; @@ -914,6 +921,11 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); +#else +da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); #endif } /* Draw a line */ @@ -1002,17 +1014,19 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.size_x, da2->bitblt.size_y); // da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); } - } + // } } static void da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGBLT_DETAIL if(!(da2->bitblt.debug_exesteps & 0xff)) da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); da2->bitblt.debug_exesteps++; +#else + da2_log("bltload_exec: %x, CS:PC=%4x:%4x\n", da2->bitblt.exec, CS, cpu_state.pc); #endif switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: @@ -1020,7 +1034,7 @@ da2_bitblt_exec(void *p) break; case DA2_BLT_CLOAD: da2_bitblt_load(da2); - da2->bitblt.indata = 0; + // da2->bitblt.indata = 0; break; case DA2_BLT_CLINE: /* Draw a dot */ @@ -1160,22 +1174,22 @@ da2_bitblt_exec(void *p) da2->bitblt.srcaddr -= 2; break; case DA2_BLT_CPUTCHAR: /* used in OS/2 J1.3 wo ROM patch. TODO: still not work */ - da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.y * 130; + // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.y * 130; // da2->bitblt.srcaddr += 2; // if (da2->bitblt.reg[0x12] < 0x100) // da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; // else // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; - da2->bitblt.size_x = da2->bitblt.reg[0x33]; - pclog("scr %x dest %x x %x y %x\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + // da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; + // da2->bitblt.size_x = da2->bitblt.reg[0x33]; + // pclog("scr %x dest %x x %x y %x\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); if (da2->bitblt.y >= da2->bitblt.size_y) { da2->bitblt.exec = DA2_BLT_CDONE; } else { DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2); } da2->bitblt.y++; - da2->bitblt.destaddr += 130; + da2->bitblt.destaddr += da2->bitblt.size_x * 2 + da2->bitblt.destpitch + 2; // } // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; ////da2->bitblt.srcaddr += 2; @@ -1189,10 +1203,9 @@ da2_bitblt_exec(void *p) // da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; // } // } else /* without init regs */ - da2->bitblt.reg[0x20] = 0; /* need to stop execution */ - if (da2->bitblt.indata) - da2->bitblt.exec = DA2_BLT_CLOAD; - else + // if (da2->bitblt.indata) + // da2->bitblt.exec = DA2_BLT_CLOAD; + // else da2->bitblt.exec = DA2_BLT_CIDLE; break; } @@ -1206,7 +1219,7 @@ da2_bitblt_dopayload(void *priv) if (da2->bitblt.exec != DA2_BLT_CIDLE) { while (da2->bitblt.exec != DA2_BLT_CIDLE) /* this disables async operation */ da2_bitblt_exec(da2); - } else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { + } else if ((da2->bitblt.reg[0x20] & 0x01) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); } else { @@ -1532,13 +1545,7 @@ 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_iolog("exec:%x\n", da2->bitblt.exec); - temp |= 0x01; /* wait (bit 3 + bit 0) ? need verify */ - // if (!da2->bitblt.timer.enabled) - //{ - // da2_iolog("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); - // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - // } + temp |= 0x09; /* wait (bit 3 + bit 0) ? need verify */ } // if (da2->bitblt.indata) temp |= 0x08; #ifdef ENABLE_DA2_DEBUGMONWAIT @@ -2677,8 +2684,37 @@ da2_bitblt_addpayload(uint8_t val, void *p) if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) da2_log("da2_mmio_write payload overflow! addr %x, val %x\n", da2->bitblt.payload_addr, val); else { - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; + if (da2->bitblt.payload_addr == 0) { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + switch (val) { + case 0x88: + case 0x89: + case 0x95: + da2->bitblt.payload_opsize = 3; + break; + case 0x91: + da2->bitblt.payload_opsize = 5; + break; + case 0x99: + da2->bitblt.payload_opsize = 7; + break; + case 0xa1: + da2->bitblt.payload_opsize = 9; + break; + default: + da2_log("addpayload: Unknown PreOP! %x\n", val); + da2->bitblt.payload_addr = 0; /* ignore input */ + break; + } + } else if (da2->bitblt.payload_addr < da2->bitblt.payload_opsize) { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + } else if (da2->bitblt.payload_addr == da2->bitblt.payload_opsize) { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_opsize = 0; /* reset */ + da2_bitblt_parse(da2); + } } } static void From b4f3e06c1ed4aa9d57768e548a6ce4c3d96acb7a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 4 Apr 2025 08:23:32 +0900 Subject: [PATCH 0669/1190] PS55DA2: Fix some issues in DSPX and OS/2 dosbox --- src/video/vid_ps55da2.c | 96 +++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 613eb5888..52eccc575 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -307,7 +307,9 @@ typedef struct da2_t { uint8_t ioctl[16]; uint8_t fctl[32]; - uint16_t crtc[128]; + uint16_t crtc[32]; + uint16_t crtc_vpreg[128]; + uint8_t crtc_vpsel; uint8_t gdcreg[64]; uint8_t reg3ee[16]; int gdcaddr; @@ -420,6 +422,7 @@ typedef struct da2_t { int32_t maskl, maskr; int32_t count; int32_t d; + int8_t destoption; int octdir; int x, y, wx1, wx2, wy1, wy2; } bitblt; @@ -679,13 +682,17 @@ DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } // pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskr); - DA2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); - for (int i = 0; i < 8; i++) { - srcpx.p8[i] = (color & (1 << i)) ? font << 16 : 0; - srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0; + if (da2->bitblt.destoption & 0x20) { + DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); + } else { + DA2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); + for (int i = 0; i < 8; i++) { + srcpx.p8[i] = (color & (1 << i)) ? font << 16 : 0; + srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0; + } + // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[3], maskl, maskr); + DA2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2); } - // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[3], maskl, maskr); - DA2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2); } } #ifdef ENABLE_DA2_DEBUGBLT @@ -876,7 +883,8 @@ da2_bitblt_load(da2_t *da2) DOS/V Extension 1040x725 some DBCS uses 0xB0 others 0x90 B0: BitShift is 1-6 */ - if (da2->bitblt.reg[0x2F] & 0x10) /* destaddr -= 2, length += 1; */ + da2->bitblt.destoption = da2->bitblt.reg[0x2F]; + if (da2->bitblt.destoption & 0x10) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; da2->bitblt.size_x += 1; @@ -1336,14 +1344,6 @@ da2_out(uint16_t addr, uint16_t val, void *p) if (!(da2->ioctl[LS_MODE] & 0x01)) /* 16 or 256 color graphics mode */ val = 0; break; - case LC_START_ADDRESS_HIGH: - // if (val == 0xff) /* adjust (need to confirm) */ - // val = 0; - case LC_START_ADDRESS_LOW: - /* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00. - OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */ - // val = 0; - break; case LC_VERTICAL_TOTALJ: /* Vertical Total */ case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ @@ -1352,8 +1352,36 @@ da2_out(uint16_t addr, uint16_t val, void *p) val = 0x400; /* for debugging bitblt in Win 3.x */ #endif break; + // case LC_START_ADDRESS_HIGH: + // if (val == 0xff) /* adjust (need to confirm) */ + // val = 0; + // case LC_START_ADDRESS_LOW: + // val = 0; + // break; } da2->crtc[da2->crtcaddr] = val; + switch (da2->crtcaddr) { + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + /* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00. + OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */ + outb(0x680, da2->crtc[LC_START_ADDRESS_LOW]); + outb(0x680, da2->crtc[LC_START_ADDRESS_HIGH]); + break; + case LC_VIEWPORT_SELECT: + /* backup some current crtc regs */ + for (int i = LC_START_ADDRESS_HIGH; i <= LC_START_ADDRESS_LOW; i++) { + da2->crtc_vpreg[(da2->crtc_vpsel * 0x20) + i] = da2->crtc[i]; + } + da2->crtc_vpsel = (val >> 6) & 3; + /* restore crtc regs */ + for (int i = LC_START_ADDRESS_HIGH; i <= LC_START_ADDRESS_LOW; i++) { + da2->crtc[i] = da2->crtc_vpreg[(da2->crtc_vpsel * 0x20) + i]; + } + break; + default: + break; + } switch (da2->crtcaddr) { case LC_H_DISPLAY_ENABLE_END: case LC_VERTICAL_TOTALJ: @@ -1363,10 +1391,11 @@ 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_LINE_COMPAREJ: case LC_START_H_DISPLAY_ENAB: case LC_START_V_DISPLAY_ENAB: + case LC_VIEWPORT_SELECT: case LC_VIEWPORT_PRIORITY: - case LC_LINE_COMPAREJ: da2->fullchange = changeframecount; da2_recalctimings(da2); break; @@ -1567,7 +1596,11 @@ da2_in(uint16_t addr, void *p) case LC_DATA: if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS16; - temp = da2->crtc[da2->crtcaddr]; + // if ((da2->crtcaddr == LC_START_ADDRESS_HIGH || da2->crtcaddr == LC_START_ADDRESS_LOW) + // & (da2->crtc[LC_VIEWPORT_SELECT] & 0x80)) + // temp = 0; + // else + temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: temp = da2->attraddr | da2->attr_palette_enable; @@ -2345,7 +2378,14 @@ da2_recalctimings(da2_t *da2) // da2->interlace = 0; - if (da2->crtc[LC_VIEWPORT_SELECT] & 0x80 || da2->split == 0) + // if (da2->crtc[LC_VIEWPORT_SELECT] & 0x80 || da2->split == 0) + if (da2->vtotal == 0) + da2->vtotal = da2->vsyncstart = da2->vblankstart = 256; + if (da2->htotal == 0) + da2->htotal = da2->dispend = da2->hdisp = 64; + if (da2->rowoffset == 0) + da2->rowoffset = 64 * 2; /* To avoid causing a DBZ error */ + if (da2->split == 0) da2->ma_latch = 0; else da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; // w + b @@ -2568,6 +2608,7 @@ static uint8_t da2_mmio_read(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; + uint32_t index = 0; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) @@ -2575,14 +2616,14 @@ da2_mmio_read(uint32_t addr, void *p) addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); else { /* 64k bank switch access */ - uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x80; } // da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { case 0xb0: /* Gaiji RAM */ + addr += index * 0x80; addr &= DA2_MASK_GAIJIRAM; /* safety access */ // da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); return da2->mmio.ram[addr]; @@ -2600,6 +2641,11 @@ da2_mmio_read(uint32_t addr, void *p) // da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; break; + case 0x00: /* SBCS in Gaiji RAM (used in the downward writing mode of DOS/V Extension) */ + addr += DA2_GAIJIRAM_SBCS + index * 0x40; + addr &= DA2_MASK_GAIJIRAM; + return da2->mmio.ram[addr]; + break; default: da2_log("PS55_MemHnd: Invalid read mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return DA2_INVALIDACCESS8; /* invalid memory access */ @@ -2741,8 +2787,8 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) index |= da2->fctl[LF_MMIO_ADDR]; // addr += index * 0x40; // addr += index * 0x80; - // da2_log("da2_mmio_w io %x, sl %x, 09 %x, ad %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO],da2->fctl[LF_MMIO_SEL], - // da2->fctl[LF_MMIO_09],da2->fctl[LF_MMIO_ADDR], da2->fctl[LF_MMIO_MODE], addr, val); + da2_log("da2_mmio_w io %x, sl %x, 09 %x, ad %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO],da2->fctl[LF_MMIO_SEL], + da2->fctl[LF_MMIO_09],da2->fctl[LF_MMIO_ADDR], da2->fctl[LF_MMIO_MODE], addr, val); } switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { case 0xb0: /* Gaiji RAM 1011 0000 */ @@ -3421,6 +3467,10 @@ da2_close(void *p) fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); for (int i = 0; i < 0x10; i++) fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + for (int i = 0; i < 0x20; i++) { + fprintf(f, "vp %02X: %4X %4X %4X %4X\n", i, + da2->crtc_vpreg[0 + i], da2->crtc_vpreg[0x20 + i], da2->crtc_vpreg[0x40 + i], da2->crtc_vpreg[0x60 + i]); + } fclose(f); } f = fopen("ram_low.dmp", "wb"); From beb417cc85b8e4e1d42f040a58351a6ab4824fcd Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 4 Apr 2025 08:55:14 +0900 Subject: [PATCH 0670/1190] PS55DA2: cleanup, remove unused code --- src/video/vid_ps55da2.c | 162 +++++++--------------------------------- 1 file changed, 26 insertions(+), 136 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 52eccc575..09e3471a5 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -490,20 +490,6 @@ getFontIBMJ(int32_t code, int line, int x, void *p) font <<= 8; font |= da2->mmio.ram[code + 1]; font <<= 16; - return font; - } - if ((code >= 0x8000) && (code <= 0x8183)) - code -= 0x6000; /* shift for IBM extended characters */ - if ((code < (DA2_FONTROM_SIZE / 72)) && (fline >= 0) && (fline < 24)) { /* DBCS 24x24 */ - code = (code * 72) + (fline * 3) + x; - // font = da2->mmio.font[code]; /* 0000 0000 0000 0000 0000 0000 1111 1111 */ - // font <<= 8; /* 0000 0000 0000 0000 1111 1111 0000 0000 */ - // font |= da2->mmio.font[code + 1] & 0xf0; /* 0000 0000 0000 0000 1111 1111 2222 0000 */ - // font <<= 3; /* 0000 0000 0000 0111 1111 1222 2000 0000 */ - // font |= da2->mmio.font[code + 1] & 0x0f; /* 0000 0000 0000 0111 1111 1222 2000 2222 */ - // font <<= 8; /* 0000 0111 1111 1222 2000 2222 0000 0000 */ - // font |= da2->mmio.font[code + 2]; /* 0000 0111 1111 1222 2000 2222 3333 3333 */ - // font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ } else if ((code >= 0xb000) && (code <= 0xb75f)) { /* DBCS 26x29 */ /* convert code->address in gaiji memory */ code -= 0xb000; @@ -515,9 +501,7 @@ getFontIBMJ(int32_t code, int line, int x, void *p) font |= da2->mmio.ram[code + 2]; font <<= 8; font |= da2->mmio.ram[code + 3]; - // font <<= 16; - } else if (code > (DA2_FONTROM_SIZE / 72)) - font = 0xffffffffu; + } else font = 0; return font; @@ -594,7 +578,7 @@ Param Desc 01 Color 03 Bit Shift 04 Select plane? -05 Dir(1000h or 1100h) + Command?(40 or 48) +05 Direction (1000h or 1100h) + Command? (40 or 48) 08 Mask Left 09 Mask Right 0A Plane Mask? @@ -607,15 +591,19 @@ Param Desc 0-3 Bit op (0 None, 1 AND, 2 OR, 3 XOR) 0D 20 Exec (1) or Exec without reset regs? (21h) -21 ? -22 ? +21 Dest Pitch +22 Src Pitch 23 Tile W 28 Tile H 29 Dest Addr 2A Src Addr 2B Tile Addr -33 Size W -35 Size H +2D Octant for line drawing +2F Dest Write Option +32 wx1, Dest X +33 wx2, Size W +34 wy1, Dest Y +35 wy2, Size H */ static void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) @@ -642,55 +630,42 @@ static void DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, uint32_t destaddr, uint16_t maskl, uint16_t maskr, da2_t *da2) { pixel32 srcpx; - // if (codeIBMJ >= DA2_FONTROM_SIZE / 72) { - // da2_log("DA2 Putchar Addr Error %x\n", srcaddr); - // return; - // } - uint8_t color = (~attr >> 8) & 0x0f; - // color = IBGRtoIRGB(color); + uint8_t fg = (~attr >> 8) & 0x0f; uint8_t bg = (~attr >> 12) & 0x0f; - // bg = 0x00; - // bg = IBGRtoIRGB(bg); uint32_t font = getFontIBMJ(codeIBMJ, line, 0, da2); uint32_t fontinv; if (width <= 2) { fontinv = ~font; for (int i = 0; i < 8; i++) { - srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0; + srcpx.p8[i] = (fg & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } - // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); for (int i = 0; i < 8; i++) { - srcpx.p8[i] = (color & (1 << i)) ? font : 0; + srcpx.p8[i] = (fg & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } - // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr); DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); } else { font = (font & 0xfff80000) | ((font & 0x0000ffff) << 3); fontinv = ~font; - // pclog("putchar: ft %08X shftr %X\n", font, da2->bitblt.bitshift_destr); for (int i = 0; i < 8; i++) { - srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0; + srcpx.p8[i] = (fg & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } - // pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskl); DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); for (int i = 0; i < 8; i++) { - srcpx.p8[i] = (color & (1 << i)) ? font : 0; + srcpx.p8[i] = (fg & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } - // pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskr); if (da2->bitblt.destoption & 0x20) { DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); } else { DA2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); for (int i = 0; i < 8; i++) { - srcpx.p8[i] = (color & (1 << i)) ? font << 16 : 0; + srcpx.p8[i] = (fg & (1 << i)) ? font << 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0; } - // pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[3], maskl, maskr); DA2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2); } } @@ -772,16 +747,6 @@ da2_bitblt_parse(da2_t *da2) { uint32_t value32; uint64_t value64; -#ifdef ENABLE_DA2_DEBUGBLT - // da2_log("bltload: loading params\n"); - // da2_log("BitBlt memory:\n"); - // if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], - // da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7]); - // } -#endif switch (da2->bitblt.payload[0]) { case 0x88: case 0x89: @@ -858,8 +823,6 @@ da2_bitblt_parse(da2_t *da2) static void da2_bitblt_load(da2_t *da2) { - /* [89] 20: 0001 (1) then execute payload */ - // if (da2->bitblt.reg[0x20] & 0x1) { da2->bitblt.reg[0x20] = 0; /* need to stop execution */ #ifdef ENABLE_DA2_DEBUGBLT for (int i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { @@ -878,10 +841,8 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.size_y = da2->bitblt.reg[0x35]; da2->bitblt.destpitch = da2->bitblt.reg[0x21]; da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; - /* 80h = 128d = 10000000b, 90h = 144d = 10010000b, B0h = 176d = 10110000 */ /* DOS/V Extension 1040x725 some DBCS uses 0xB0 others 0x90 - B0: BitShift is 1-6 */ da2->bitblt.destoption = da2->bitblt.reg[0x2F]; if (da2->bitblt.destoption & 0x10) /* destaddr -= 2, length += 1; */ @@ -898,21 +859,12 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.y = 0; da2->bitblt.exec = DA2_BLT_CDONE; - /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ + /* Put DBCS char used by OS/2 and DOS/V Extension */ if (!(da2->bitblt.reg[0xb] & 0x08)) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; - /* Todo: addressing */ - // if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ - //{ - // da2->bitblt.destaddr += 2; - // da2->bitblt.size_x -= 1; - // da2->bitblt.destpitch += 2; - // da2->bitblt.srcpitch += 2; - // } da2->bitblt.fcolor = da2->bitblt.reg[0x1]; da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; da2->bitblt.destaddr += 2; - // da2->bitblt.srcpitch = 0; #ifdef ENABLE_DA2_DEBUGBLT uint8_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; uint8_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; @@ -1020,9 +972,7 @@ da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d\n", da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); - // da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); } - // } } static void da2_bitblt_exec(void *p) @@ -1046,7 +996,6 @@ da2_bitblt_exec(void *p) break; case DA2_BLT_CLINE: /* Draw a dot */ - // outb(0x680, da2->bitblt.octdir); da2_bltlog("point: %d %d %d %d %d\n", da2->bitblt.x, da2->bitblt.y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; int pixelmask = da2->bitblt.x % 16; @@ -1061,7 +1010,6 @@ da2_bitblt_exec(void *p) ; else DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); - // da2_log("draw: %x %x %x\n", destaddr, da2->bitblt.fcolor, pixelmask); da2->bitblt.count++; /* calculate the next position with Bresenham's line algorithm */ @@ -1182,26 +1130,14 @@ da2_bitblt_exec(void *p) da2->bitblt.srcaddr -= 2; break; case DA2_BLT_CPUTCHAR: /* used in OS/2 J1.3 wo ROM patch. TODO: still not work */ - // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.y * 130; - // da2->bitblt.srcaddr += 2; - // if (da2->bitblt.reg[0x12] < 0x100) - // da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; - // else - // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - // da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; - // da2->bitblt.size_x = da2->bitblt.reg[0x33]; // pclog("scr %x dest %x x %x y %x\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); if (da2->bitblt.y >= da2->bitblt.size_y) { da2->bitblt.exec = DA2_BLT_CDONE; } else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2); + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2); } - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.size_x * 2 + da2->bitblt.destpitch + 2; - // } - // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; - ////da2->bitblt.srcaddr += 2; - // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.size_x * 2 + da2->bitblt.destpitch + 2; break; case DA2_BLT_CDONE: // if (!(da2->bitblt.reg[0x20] & 0x20)) { @@ -1352,12 +1288,6 @@ da2_out(uint16_t addr, uint16_t val, void *p) val = 0x400; /* for debugging bitblt in Win 3.x */ #endif break; - // case LC_START_ADDRESS_HIGH: - // if (val == 0xff) /* adjust (need to confirm) */ - // val = 0; - // case LC_START_ADDRESS_LOW: - // val = 0; - // break; } da2->crtc[da2->crtcaddr] = val; switch (da2->crtcaddr) { @@ -1406,7 +1336,6 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LV_PORT: // 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; if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) { da2->fullchange = 3; @@ -1596,11 +1525,7 @@ da2_in(uint16_t addr, void *p) case LC_DATA: if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS16; - // if ((da2->crtcaddr == LC_START_ADDRESS_HIGH || da2->crtcaddr == LC_START_ADDRESS_LOW) - // & (da2->crtc[LC_VIEWPORT_SELECT] & 0x80)) - // temp = 0; - // else - temp = da2->crtc[da2->crtcaddr]; + temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: temp = da2->attraddr | da2->attr_palette_enable; @@ -1699,9 +1624,6 @@ da2_outw(uint16_t addr, uint16_t val, void *p) break; case 0x3EC: // 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); /* reset masks for compatibility with Win 3.1 solitaire */ if (da2->gdcaddr == LG_MODE) { @@ -2347,18 +2269,11 @@ da2_recalctimings(da2_t *da2) double crtcconst; double _dispontime, _dispofftime, disptime; - // /* if output disabled or VGA passthrough */ - // if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { - // da2->render = da2_render_blank; - // return; - // } - da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff; da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff; da2->split -= 1; - // da2->split = 0xfff; da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; @@ -2374,21 +2289,16 @@ da2_recalctimings(da2_t *da2) da2->clock = da2->da2const; - // da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - - // da2->interlace = 0; - - // if (da2->crtc[LC_VIEWPORT_SELECT] & 0x80 || da2->split == 0) if (da2->vtotal == 0) da2->vtotal = da2->vsyncstart = da2->vblankstart = 256; if (da2->htotal == 0) da2->htotal = da2->dispend = da2->hdisp = 64; if (da2->rowoffset == 0) da2->rowoffset = 64 * 2; /* To avoid causing a DBZ error */ - if (da2->split == 0) + if (da2->split == 0) /* To avoid a glitch in MODE 1 of OS/2 J1.3 DOSBox. */ da2->ma_latch = 0; else - da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; // w + b + da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; da2->ca_adj = 0; da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; @@ -2427,15 +2337,6 @@ da2_recalctimings(da2_t *da2) da2->hdisp *= 13; da2->char_width = 13; } - // if (!da2->scrblank && da2->attr_palette_enable) - //{ - // da2->render = da2_draw_text; - //} - - // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - - // if (da2->recalctimings_ex) - // da2->recalctimings_ex(da2); if (da2->vblankstart < da2->dispend) da2->dispend = da2->vblankstart; @@ -2446,7 +2347,7 @@ da2_recalctimings(da2_t *da2) _dispontime = da2->hdisp_time; da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); - // if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; _dispofftime *= crtcconst; @@ -2785,10 +2686,8 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; - // addr += index * 0x40; - // addr += index * 0x80; - da2_log("da2_mmio_w io %x, sl %x, 09 %x, ad %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO],da2->fctl[LF_MMIO_SEL], - da2->fctl[LF_MMIO_09],da2->fctl[LF_MMIO_ADDR], da2->fctl[LF_MMIO_MODE], addr, val); + // da2_log("da2_mmio_w io %x, sl %x, 09 %x, ad %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO],da2->fctl[LF_MMIO_SEL], + // da2->fctl[LF_MMIO_09],da2->fctl[LF_MMIO_ADDR], da2->fctl[LF_MMIO_MODE], addr, val); } switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { case 0xb0: /* Gaiji RAM 1011 0000 */ @@ -2802,12 +2701,6 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) addr += index * 0x40; da2->mmio.ram[(DA2_GAIJIRAM_SBCS + addr) & DA2_MASK_GAIJIRAM] = val; // da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - // addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ - // if (addr >= DA2_BLT_MEMSIZE) - //{ - // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - // return; - // } break; default: da2_log("da2_mmio_write failed io %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO] ,da2->fctl[LF_MMIO_MODE], addr, val); @@ -3138,8 +3031,6 @@ da2_poll(void *priv) // da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); da2->displine++; - // if (da2->interlace) - // da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { // da2_log("Vsync off at line %i\n",displine); da2->cgastat &= ~8; @@ -3153,7 +3044,6 @@ da2_poll(void *priv) // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); timer_advance_u64(&da2->timer, da2->dispontime); - // if (output) printf("Display on %f\n",vidtime); if (da2->dispon) da2->cgastat &= ~1; da2->hdisp_on = 0; From 392e3156bb47fbf2f5857a248c093a04e7b22e4e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:10:49 +0900 Subject: [PATCH 0671/1190] disable debug code --- src/video/vid_ps55da2.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 09e3471a5..ec25db7c7 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -260,7 +260,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 @@ -300,6 +300,7 @@ da2_log(const char *fmt, ...) # endif #else # define da2_bltlog(fmt, ...) +# define da2_bltreglog(fmt, ...) #endif typedef struct da2_t { @@ -1291,13 +1292,13 @@ da2_out(uint16_t addr, uint16_t val, void *p) } da2->crtc[da2->crtcaddr] = val; switch (da2->crtcaddr) { - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: + // case LC_START_ADDRESS_HIGH: + // case LC_START_ADDRESS_LOW: /* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00. OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */ - outb(0x680, da2->crtc[LC_START_ADDRESS_LOW]); - outb(0x680, da2->crtc[LC_START_ADDRESS_HIGH]); - break; + // outb(0x680, da2->crtc[LC_START_ADDRESS_LOW]); + // outb(0x680, da2->crtc[LC_START_ADDRESS_HIGH]); + // break; case LC_VIEWPORT_SELECT: /* backup some current crtc regs */ for (int i = LC_START_ADDRESS_HIGH; i <= LC_START_ADDRESS_LOW; i++) { From 4a4a7a342a89e963046a3f4ddd40994995560736 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:42:22 +0900 Subject: [PATCH 0672/1190] PS55DA2: formatting, sorting --- src/video/vid_ps55da2.c | 852 ++++++++++++++++++++-------------------- 1 file changed, 427 insertions(+), 425 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ec25db7c7..39adc3607 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -449,12 +449,12 @@ 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); +static uint16_t da2_rightrotate(uint16_t data, uint8_t count); typedef union { uint32_t d; uint8_t b[4]; -} DA2_VidSeq32; +} vidseq32; typedef struct { uint32_t p8[8]; @@ -462,7 +462,7 @@ typedef struct { /* safety read for internal functions */ static uint32_t -DA2_vram_r(uint32_t addr, da2_t *da2) +da2_vram_r(uint32_t addr, da2_t *da2) { if (addr & ~DA2_MASK_VRAM) return DA2_INVALIDACCESS32; @@ -470,110 +470,14 @@ DA2_vram_r(uint32_t addr, da2_t *da2) } /* safety write for internal functions */ static void -DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) +da2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) { if (addr & ~DA2_MASK_VRAM) return; da2->vram[addr] = val; return; } -/* get font data for bitblt operation */ -static uint32_t -getFontIBMJ(int32_t code, int line, int x, void *p) -{ - da2_t *da2 = (da2_t *) p; - uint32_t font = 0; - int fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ - if (code < 0x100) { /* SBCS 13x29 */ - code *= 0x40; - code += DA2_GAIJIRAM_SBCS + (line * 2) + x; - font = da2->mmio.ram[code]; - font <<= 8; - font |= da2->mmio.ram[code + 1]; - font <<= 16; - } else if ((code >= 0xb000) && (code <= 0xb75f)) { /* DBCS 26x29 */ - /* convert code->address in gaiji memory */ - code -= 0xb000; - code = (code * 0x80) + (line * 4) + x; - font = da2->mmio.ram[code]; - font <<= 8; - font |= da2->mmio.ram[code + 1]; - font <<= 8; - font |= da2->mmio.ram[code + 2]; - font <<= 8; - font |= da2->mmio.ram[code + 3]; - } - else - font = 0; - return font; -} -/* write pixel data with rop (Note: bitmask must be in big endian) */ -static void -DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) -{ - uint32_t writepx[8]; - destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ - // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; - destaddr <<= 3; - /* read destination data with big endian order */ - for (int i = 0; i < 8; i++) - writepx[i] = DA2_vram_r((destaddr + 24) | i, da2) - | (DA2_vram_r((destaddr + 16) | i, da2) << 8) - | (DA2_vram_r((destaddr + 8) | i, da2) << 16) - | (DA2_vram_r((destaddr + 0) | i, da2) << 24); - - DA2_VidSeq32 mask32in; - mask32in.d = (uint32_t) mask; - DA2_VidSeq32 mask32; - mask32.b[3] = mask32in.b[0]; - mask32.b[2] = mask32in.b[1]; - mask32.d &= 0xffff0000; - for (int i = 0; i < 8; i++) { - if (da2->bitblt.bitshift_destr > 0) - srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; -// #ifdef ENABLE_DA2_DEBUGBLT -// if (i == 0) { -// pclog("writeplane: src %08X mask %08X dest %08X\n", srcpx->p8[i], mask32.d, writepx[i]); -// } -// #endif - if (da2->bitblt.raster_op & 0x2010) /* NOT Src or NOT Pattern */ - srcpx->p8[i] = ~srcpx->p8[i] & mask32.d; - if (da2->bitblt.raster_op & 0x20) /* Dest NOT */ - writepx[i] = (~writepx[i] & mask32.d) | (writepx[i] & ~mask32.d); - switch (da2->bitblt.raster_op & 0x03) { - case 0x00: /* None */ - writepx[i] &= ~mask32.d; - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x01: /* AND */ - writepx[i] &= srcpx->p8[i] | ~mask32.d; - break; - case 0x02: /* OR */ - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x03: /* XOR */ - writepx[i] ^= srcpx->p8[i] & mask32.d; - break; - } - } - for (int i = 0; i < 8; i++) { - DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); - DA2_vram_w((destaddr + 8) | i, (writepx[i] >> 16) & 0xff, da2); - } -} - -static void -DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2) -{ - pixel32 srcpx; - /* fill data with input color */ - for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0; /* read in word */ - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} /* Param Desc 01 Color @@ -606,19 +510,115 @@ Param Desc 34 wy1, Dest Y 35 wy2, Size H */ +/* write pixel data with rop (Note: bitmask must be in big endian) */ static void -DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) +da2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) +{ + uint32_t writepx[8]; + destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ + // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; + destaddr <<= 3; + /* read destination data with big endian order */ + for (int i = 0; i < 8; i++) + writepx[i] = da2_vram_r((destaddr + 24) | i, da2) + | (da2_vram_r((destaddr + 16) | i, da2) << 8) + | (da2_vram_r((destaddr + 8) | i, da2) << 16) + | (da2_vram_r((destaddr + 0) | i, da2) << 24); + + vidseq32 mask32in; + mask32in.d = (uint32_t) mask; + vidseq32 mask32; + mask32.b[3] = mask32in.b[0]; + mask32.b[2] = mask32in.b[1]; + mask32.d &= 0xffff0000; + for (int i = 0; i < 8; i++) { + if (da2->bitblt.bitshift_destr > 0) + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; +// #ifdef ENABLE_DA2_DEBUGBLT +// if (i == 0) { +// pclog("writeplane: src %08X mask %08X dest %08X\n", srcpx->p8[i], mask32.d, writepx[i]); +// } +// #endif + if (da2->bitblt.raster_op & 0x2010) /* NOT Src or NOT Pattern */ + srcpx->p8[i] = ~srcpx->p8[i] & mask32.d; + if (da2->bitblt.raster_op & 0x20) /* Dest NOT */ + writepx[i] = (~writepx[i] & mask32.d) | (writepx[i] & ~mask32.d); + switch (da2->bitblt.raster_op & 0x03) { + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; + } + } + for (int i = 0; i < 8; i++) { + da2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); + da2_vram_w((destaddr + 8) | i, (writepx[i] >> 16) & 0xff, da2); + } +} + +static void +da2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2) +{ + pixel32 srcpx; + /* fill data with input color */ + for (int i = 0; i < 8; i++) + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0; /* read in word */ + + da2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +static void +da2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; srcaddr &= 0xfffffffe; srcaddr <<= 3; for (int i = 0; i < 8; i++) - srcpx.p8[i] = DA2_vram_r((srcaddr + 24) | i, da2) - | (DA2_vram_r((srcaddr + 16) | i, da2) << 8) - | (DA2_vram_r((srcaddr + 8) | i, da2) << 16) - | (DA2_vram_r((srcaddr + 0) | i, da2) << 24); + srcpx.p8[i] = da2_vram_r((srcaddr + 24) | i, da2) + | (da2_vram_r((srcaddr + 16) | i, da2) << 8) + | (da2_vram_r((srcaddr + 8) | i, da2) << 16) + | (da2_vram_r((srcaddr + 0) | i, da2) << 24); - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +/* get font data for bitblt operation */ +static uint32_t +getRAMFont(int32_t code, int line, int x, void *p) +{ + da2_t *da2 = (da2_t *) p; + uint32_t font = 0; + int fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ + if (code < 0x100) { /* SBCS 13x29 */ + code *= 0x40; + code += DA2_GAIJIRAM_SBCS + (line * 2) + x; + font = da2->mmio.ram[code]; + font <<= 8; + font |= da2->mmio.ram[code + 1]; + font <<= 16; + } else if ((code >= 0xb000) && (code <= 0xb75f)) { /* DBCS 26x29 */ + /* convert code->address in gaiji memory */ + code -= 0xb000; + code = (code * 0x80) + (line * 4) + x; + font = da2->mmio.ram[code]; + font <<= 8; + font |= da2->mmio.ram[code + 1]; + font <<= 8; + font |= da2->mmio.ram[code + 2]; + font <<= 8; + font |= da2->mmio.ram[code + 3]; + } + else + font = 0; + return font; } /* Reverse the bit order of attribute code IBGR to IRGB(used in Mode 3 and Cursor Color) */ static int8_t @@ -628,12 +628,12 @@ IBGRtoIRGB(uint8_t attr) return attr >>= 4; } static void -DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, uint32_t destaddr, uint16_t maskl, uint16_t maskr, da2_t *da2) +da2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, uint32_t destaddr, uint16_t maskl, uint16_t maskr, da2_t *da2) { pixel32 srcpx; uint8_t fg = (~attr >> 8) & 0x0f; uint8_t bg = (~attr >> 12) & 0x0f; - uint32_t font = getFontIBMJ(codeIBMJ, line, 0, da2); + uint32_t font = getRAMFont(codeIBMJ, line, 0, da2); uint32_t fontinv; if (width <= 2) { fontinv = ~font; @@ -641,12 +641,12 @@ DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui srcpx.p8[i] = (fg & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } - DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); for (int i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } - DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); } else { font = (font & 0xfff80000) | ((font & 0x0000ffff) << 3); fontinv = ~font; @@ -654,20 +654,20 @@ DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui srcpx.p8[i] = (fg & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } - DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); for (int i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } if (da2->bitblt.destoption & 0x20) { - DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); } else { - DA2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); for (int i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font << 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0; } - DA2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2); + da2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2); } } } @@ -677,7 +677,7 @@ pixel1tohex(uint32_t addr, int index, da2_t *da2) { uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { - if (DA2_vram_r(((addr << 3) | j) & (1 << (7 - index)), da2)) + if (da2_vram_r(((addr << 3) | j) & (1 << (7 - index)), da2)) pixeldata++; } return pixeldata; @@ -748,69 +748,69 @@ da2_bitblt_parse(da2_t *da2) { uint32_t value32; uint64_t value64; - switch (da2->bitblt.payload[0]) { - case 0x88: - case 0x89: - case 0x95: - value32 = da2->bitblt.payload[3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[2]; - da2_bltreglog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[0], da2->bitblt.payload[1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[1]] = value32; - break; - case 0x91: - value32 = da2->bitblt.payload[5]; - value32 <<= 8; - value32 |= da2->bitblt.payload[4]; - value32 <<= 8; - value32 |= da2->bitblt.payload[3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[2]; - da2_bltreglog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[0], da2->bitblt.payload[1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[1]] = value32; - break; - case 0x99: - value64 = da2->bitblt.payload[7]; - value64 <<= 8; - value64 = da2->bitblt.payload[6]; - value64 <<= 8; - value64 = da2->bitblt.payload[5]; - value64 <<= 8; - value64 |= da2->bitblt.payload[4]; - value64 <<= 8; - value64 |= da2->bitblt.payload[3]; - value64 <<= 8; - value64 |= da2->bitblt.payload[2]; - da2_bltreglog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[0], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], - da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7]); - da2->bitblt.reg[da2->bitblt.payload[1]] = value64; - break; - case 0xa1: - value64 = da2->bitblt.payload[9]; - value64 <<= 8; - value64 |= da2->bitblt.payload[8]; - value64 <<= 8; - value64 |= da2->bitblt.payload[7]; - value64 <<= 8; - value64 |= da2->bitblt.payload[6]; - value64 <<= 8; - value64 |= da2->bitblt.payload[5]; - value64 <<= 8; - value64 |= da2->bitblt.payload[4]; - value64 <<= 8; - value64 |= da2->bitblt.payload[3]; - value64 <<= 8; - value64 |= da2->bitblt.payload[2]; - da2_bltreglog("[%02x] %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[0], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], - da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7], da2->bitblt.payload[8], da2->bitblt.payload[9]); - da2->bitblt.reg[da2->bitblt.payload[1]] = value64; - break; - case 0x00: /* Win 3.0 Clock writes invalid zero data. */ - break; - default: - da2_log("bltload: Unknown PreOP!\n"); - break; - } + switch (da2->bitblt.payload[0]) { + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[0], da2->bitblt.payload[1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[1]] = value32; + break; + case 0x91: + value32 = da2->bitblt.payload[5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[0], da2->bitblt.payload[1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[1]] = value32; + break; + case 0x99: + value64 = da2->bitblt.payload[7]; + value64 <<= 8; + value64 = da2->bitblt.payload[6]; + value64 <<= 8; + value64 = da2->bitblt.payload[5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[0], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], + da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7]); + da2->bitblt.reg[da2->bitblt.payload[1]] = value64; + break; + case 0xa1: + value64 = da2->bitblt.payload[9]; + value64 <<= 8; + value64 |= da2->bitblt.payload[8]; + value64 <<= 8; + value64 |= da2->bitblt.payload[7]; + value64 <<= 8; + value64 |= da2->bitblt.payload[6]; + value64 <<= 8; + value64 |= da2->bitblt.payload[5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[2]; + da2_bltreglog("[%02x] %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[0], da2->bitblt.payload[1], da2->bitblt.payload[2], da2->bitblt.payload[3], + da2->bitblt.payload[4], da2->bitblt.payload[5], da2->bitblt.payload[6], da2->bitblt.payload[7], da2->bitblt.payload[8], da2->bitblt.payload[9]); + da2->bitblt.reg[da2->bitblt.payload[1]] = value64; + break; + case 0x00: /* Win 3.0 Clock writes invalid zero data. */ + break; + default: + da2_log("bltload: Unknown PreOP!\n"); + break; + } if (da2->bitblt.reg[0x20] & 0x01) { /* Execute Bitblt immediately (for OS/2 J1.3) */ da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); @@ -818,162 +818,162 @@ da2_bitblt_parse(da2_t *da2) /* clear payload memory */ memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); da2->bitblt.payload_addr = 0; - da2->bitblt.indata = 0; + da2->bitblt.indata = 0; } static void da2_bitblt_load(da2_t *da2) { - da2->bitblt.reg[0x20] = 0; /* need to stop execution */ + da2->bitblt.reg[0x20] = 0; /* need to stop execution */ #ifdef ENABLE_DA2_DEBUGBLT - for (int i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; - } - da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; - da2->bitblt.debug_reg_ip++; - if ((DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip) >= DA2_DEBUG_BLTLOG_MAX) - da2->bitblt.debug_reg_ip = 0; - da2->bitblt.debug_exesteps = 0; + for (int i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; + } + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; + da2->bitblt.debug_reg_ip++; + if ((DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip) >= DA2_DEBUG_BLTLOG_MAX) + da2->bitblt.debug_reg_ip = 0; + da2->bitblt.debug_exesteps = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x03] >> 4) & 0x0f); /* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b]; - da2->bitblt.destaddr = da2->bitblt.reg[0x29]; - da2->bitblt.size_x = da2->bitblt.reg[0x33]; - da2->bitblt.size_y = da2->bitblt.reg[0x35]; - da2->bitblt.destpitch = da2->bitblt.reg[0x21]; - da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; - /* - DOS/V Extension 1040x725 some DBCS uses 0xB0 others 0x90 - */ - da2->bitblt.destoption = da2->bitblt.reg[0x2F]; - if (da2->bitblt.destoption & 0x10) /* destaddr -= 2, length += 1; */ - { - da2->bitblt.destaddr -= 2; - da2->bitblt.size_x += 1; - da2->bitblt.destpitch -= 2; - da2->bitblt.srcpitch -= 2; - } - da2->bitblt.fcolor = da2->bitblt.reg[0x0]; - da2->bitblt.maskl = da2->bitblt.reg[0x8]; - da2->bitblt.maskr = da2->bitblt.reg[0x9]; - da2->bitblt.x = 0; - da2->bitblt.y = 0; - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x03] >> 4) & 0x0f); /* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b]; + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destpitch = da2->bitblt.reg[0x21]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + /* + DOS/V Extension 1040x725 some DBCS uses 0xB0 others 0x90 + */ + da2->bitblt.destoption = da2->bitblt.reg[0x2F]; + if (da2->bitblt.destoption & 0x10) /* destaddr -= 2, length += 1; */ + { + da2->bitblt.destaddr -= 2; + da2->bitblt.size_x += 1; + da2->bitblt.destpitch -= 2; + da2->bitblt.srcpitch -= 2; + } + da2->bitblt.fcolor = da2->bitblt.reg[0x0]; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; - /* Put DBCS char used by OS/2 and DOS/V Extension */ - if (!(da2->bitblt.reg[0xb] & 0x08)) { - da2->bitblt.exec = DA2_BLT_CPUTCHAR; - da2->bitblt.fcolor = da2->bitblt.reg[0x1]; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; - da2->bitblt.destaddr += 2; + /* Put DBCS char used by OS/2 and DOS/V Extension */ + if (!(da2->bitblt.reg[0xb] & 0x08)) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + da2->bitblt.fcolor = da2->bitblt.reg[0x1]; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12]; + da2->bitblt.destaddr += 2; #ifdef ENABLE_DA2_DEBUGBLT - uint8_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint8_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; - if (da2->bitblt.reg[0x12] < 0x100) { - sjis_h = 0x20; - sjis_l = da2->bitblt.reg[0x12]; - } else { - if (!(isKanji1(sjis_h))) - sjis_h = 0x3f; - if (!(isKanji2(sjis_l))) - sjis_l = 0x3f; - } - da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + uint8_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint8_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + if (da2->bitblt.reg[0x12] < 0x100) { + sjis_h = 0x20; + sjis_l = da2->bitblt.reg[0x12]; + } else { + if (!(isKanji1(sjis_h))) + sjis_h = 0x3f; + if (!(isKanji2(sjis_l))) + sjis_l = 0x3f; + } + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #else -da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); #endif - } - /* Draw a line */ - else if (da2->bitblt.reg[0x5] == 0x43) { - da2->bitblt.exec = DA2_BLT_CLINE; - da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0xffff); - da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0xffff); - da2->bitblt.wx1 = (da2->bitblt.reg[0x32]) >> 16; - da2->bitblt.wx2 = (da2->bitblt.reg[0x33]) >> 16; - da2->bitblt.wy1 = (da2->bitblt.reg[0x34]) >> 16; - da2->bitblt.wy2 = (da2->bitblt.reg[0x35]) >> 16; - da2->bitblt.size_x = abs((int16_t)(da2->bitblt.reg[0x33] & 0xffff) - da2->bitblt.dest_x); - da2->bitblt.size_y = abs((int16_t)(da2->bitblt.reg[0x35] & 0xffff) - da2->bitblt.dest_y); - da2->bitblt.count = 0; - da2->bitblt.octdir = da2->bitblt.reg[0x2D]; - da2->bitblt.bitshift_destr = 0; - if (da2->bitblt.octdir & 0x04) /* dX > dY */ - da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x; - else - da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y; - da2->bitblt.x = da2->bitblt.dest_x; - da2->bitblt.y = da2->bitblt.dest_y; - da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%dn", - da2->bitblt.dest_x, da2->bitblt.dest_y, - da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); - da2_log(" x1=%d, x2=%d, y1=%d, y2=%d\n", - da2->bitblt.reg[0x32] & 0x7ff, da2->bitblt.reg[0x33] & 0x7ff, - da2->bitblt.reg[0x34] & 0x7ff, da2->bitblt.reg[0x35] & 0x7ff); - da2_log(" ux1=%d,ux2=%d,uy1=%d,uy2=%d\n", - (da2->bitblt.reg[0x32] >> 16) & 0x7ff, (da2->bitblt.reg[0x33] >> 16) & 0x7ff, - (da2->bitblt.reg[0x34] >> 16) & 0x7ff, (da2->bitblt.reg[0x35] >> 16) & 0x7ff); - } - /* Fill a rectangle (or draw a horizontal / vertical line) */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { - da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); - da2->bitblt.exec = DA2_BLT_CFILLRECT; - da2->bitblt.destaddr += 2; - } - /* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) { - da2->bitblt.exec = DA2_BLT_CFILLTILE; - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; - da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - /* Tiling a rectangle (transfer tile data multiple times) */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { - da2->bitblt.exec = DA2_BLT_CFILLTILE; - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; - da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - /* Block copy */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { - da2->bitblt.exec = DA2_BLT_CCOPYF; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; - da2->bitblt.destaddr += 2; - da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - /* Block copy but reversed direction */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { - da2->bitblt.exec = DA2_BLT_CCOPYR; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } + } + /* Draw a line */ + else if (da2->bitblt.reg[0x5] == 0x43) { + da2->bitblt.exec = DA2_BLT_CLINE; + da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0xffff); + da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0xffff); + da2->bitblt.wx1 = (da2->bitblt.reg[0x32]) >> 16; + da2->bitblt.wx2 = (da2->bitblt.reg[0x33]) >> 16; + da2->bitblt.wy1 = (da2->bitblt.reg[0x34]) >> 16; + da2->bitblt.wy2 = (da2->bitblt.reg[0x35]) >> 16; + da2->bitblt.size_x = abs((int16_t) (da2->bitblt.reg[0x33] & 0xffff) - da2->bitblt.dest_x); + da2->bitblt.size_y = abs((int16_t) (da2->bitblt.reg[0x35] & 0xffff) - da2->bitblt.dest_y); + da2->bitblt.count = 0; + da2->bitblt.octdir = da2->bitblt.reg[0x2D]; + da2->bitblt.bitshift_destr = 0; + if (da2->bitblt.octdir & 0x04) /* dX > dY */ + da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x; + else + da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y; + da2->bitblt.x = da2->bitblt.dest_x; + da2->bitblt.y = da2->bitblt.dest_y; + da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%dn", + da2->bitblt.dest_x, da2->bitblt.dest_y, + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); + da2_log(" x1=%d, x2=%d, y1=%d, y2=%d\n", + da2->bitblt.reg[0x32] & 0x7ff, da2->bitblt.reg[0x33] & 0x7ff, + da2->bitblt.reg[0x34] & 0x7ff, da2->bitblt.reg[0x35] & 0x7ff); + da2_log(" ux1=%d,ux2=%d,uy1=%d,uy2=%d\n", + (da2->bitblt.reg[0x32] >> 16) & 0x7ff, (da2->bitblt.reg[0x33] >> 16) & 0x7ff, + (da2->bitblt.reg[0x34] >> 16) & 0x7ff, (da2->bitblt.reg[0x35] >> 16) & 0x7ff); + } + /* Fill a rectangle (or draw a horizontal / vertical line) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { + da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.exec = DA2_BLT_CFILLRECT; + da2->bitblt.destaddr += 2; + } + /* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) { + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + /* Tiling a rectangle (transfer tile data multiple times) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + /* Block copy */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { + da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr += 2; + da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + /* Block copy but reversed direction */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { + da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } } static void da2_bitblt_exec(void *p) @@ -981,7 +981,7 @@ da2_bitblt_exec(void *p) da2_t *da2 = (da2_t *) p; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); #ifdef ENABLE_DA2_DEBUGBLT_DETAIL - if(!(da2->bitblt.debug_exesteps & 0xff)) + if (!(da2->bitblt.debug_exesteps & 0xff)) da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); da2->bitblt.debug_exesteps++; #else @@ -998,19 +998,19 @@ da2_bitblt_exec(void *p) case DA2_BLT_CLINE: /* Draw a dot */ da2_bltlog("point: %d %d %d %d %d\n", da2->bitblt.x, da2->bitblt.y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); - int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; + int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; int pixelmask = da2->bitblt.x % 16; if (pixelmask >= 8) pixelmask = (0x8000 >> (pixelmask - 8)); else pixelmask = (0x80 >> pixelmask); - + /* check the current position is inside the window */ if (da2->bitblt.x < da2->bitblt.wx1 || da2->bitblt.x > da2->bitblt.wx2 || da2->bitblt.y < da2->bitblt.wy1 || da2->bitblt.y > da2->bitblt.wy2) ; else - DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); + da2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); da2->bitblt.count++; /* calculate the next position with Bresenham's line algorithm */ @@ -1053,7 +1053,7 @@ da2_bitblt_exec(void *p) case DA2_BLT_CFILLRECT: // da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + da2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); if (da2->bitblt.y >= da2->bitblt.size_y - 1) { da2->bitblt.exec = DA2_BLT_CDONE; } @@ -1061,36 +1061,38 @@ da2_bitblt_exec(void *p) da2->bitblt.y++; da2->bitblt.destaddr += da2->bitblt.destpitch + 2; } else if (da2->bitblt.x == 0) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); da2->bitblt.x++; } else { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); da2->bitblt.x++; } da2->bitblt.destaddr += 2; break; - case DA2_BLT_CFILLTILE: { - int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) { - da2->bitblt.exec = DA2_BLT_CDONE; + case DA2_BLT_CFILLTILE: + { + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + da2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } else if (da2->bitblt.x == 0) { + da2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + da2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } else { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; + da2->bitblt.destaddr += 2; + break; } - da2->bitblt.destaddr += 2; - break; - } case DA2_BLT_CCOPYF: + case DA2_BLT_CCOPYF: if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + da2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); if (da2->bitblt.y >= da2->bitblt.size_y - 1) { da2->bitblt.exec = DA2_BLT_CDONE; } @@ -1099,10 +1101,10 @@ da2_bitblt_exec(void *p) da2->bitblt.destaddr += da2->bitblt.destpitch + 2; da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; } else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); da2->bitblt.x++; } else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); da2->bitblt.x++; } da2->bitblt.destaddr += 2; @@ -1110,7 +1112,7 @@ da2_bitblt_exec(void *p) break; case DA2_BLT_CCOPYR: if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + da2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); if (da2->bitblt.y >= da2->bitblt.size_y - 1) { da2->bitblt.exec = DA2_BLT_CDONE; } @@ -1121,10 +1123,10 @@ da2_bitblt_exec(void *p) da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; } else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); da2->bitblt.x++; } else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); da2->bitblt.x++; } da2->bitblt.destaddr -= 2; @@ -1135,7 +1137,7 @@ da2_bitblt_exec(void *p) if (da2->bitblt.y >= da2->bitblt.size_y) { da2->bitblt.exec = DA2_BLT_CDONE; } else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2); + da2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2); } da2->bitblt.y++; da2->bitblt.destaddr += da2->bitblt.size_x * 2 + da2->bitblt.destpitch + 2; @@ -1151,7 +1153,7 @@ da2_bitblt_exec(void *p) // if (da2->bitblt.indata) // da2->bitblt.exec = DA2_BLT_CLOAD; // else - da2->bitblt.exec = DA2_BLT_CIDLE; + da2->bitblt.exec = DA2_BLT_CIDLE; break; } } @@ -1171,6 +1173,47 @@ da2_bitblt_dopayload(void *priv) // timer_disable(&da2->bitblt.timer); } } +static void +da2_bitblt_addpayload(uint8_t val, void *p) +{ + da2_t *da2 = (da2_t *) p; + da2->bitblt.indata = 1; + if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! addr %x, val %x\n", da2->bitblt.payload_addr, val); + else { + if (da2->bitblt.payload_addr == 0) { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + switch (val) { + case 0x88: + case 0x89: + case 0x95: + da2->bitblt.payload_opsize = 3; + break; + case 0x91: + da2->bitblt.payload_opsize = 5; + break; + case 0x99: + da2->bitblt.payload_opsize = 7; + break; + case 0xa1: + da2->bitblt.payload_opsize = 9; + break; + default: + da2_log("addpayload: Unknown PreOP! %x\n", val); + da2->bitblt.payload_addr = 0; /* ignore input */ + break; + } + } else if (da2->bitblt.payload_addr < da2->bitblt.payload_opsize) { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + } else if (da2->bitblt.payload_addr == da2->bitblt.payload_opsize) { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_opsize = 0; /* reset */ + da2_bitblt_parse(da2); + } + } +} static void da2_out(uint16_t addr, uint16_t val, void *p) @@ -2052,9 +2095,9 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = DA2_vram_r(DA2_VM03_BASECHR + da2->ma, da2); - attr = DA2_vram_r(DA2_VM03_BASECHR + da2->ma + 1, da2); - extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + da2->ma + 1, da2); + chr = da2_vram_r(DA2_VM03_BASECHR + da2->ma, da2); + attr = da2_vram_r(DA2_VM03_BASECHR + da2->ma + 1, da2); + extattr = da2_vram_r(DA2_VM03_BASEEXATTR + da2->ma + 1, da2); // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; @@ -2072,7 +2115,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + da2->ma + 2, da2); + chr_dbcs = da2_vram_r(DA2_VM03_BASECHR + da2->ma + 2, da2); chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -2443,19 +2486,19 @@ da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) case 0: /*Set*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->gdcsrc[i] & ~bitmask); // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); - DA2_vram_w(addr | i, (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); + da2_vram_w(addr | i, (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 1: /*AND*/ // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask) & da2->gdcsrc[i]; - DA2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); + da2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 2: /*OR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | da2->gdcsrc[i]; - DA2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); + da2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 3: /*XOR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) ^ da2->gdcsrc[i]; - DA2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); + da2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; } } @@ -2465,8 +2508,8 @@ da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) { - if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = rightRotate(bitmask, 8); - // if((addr & 8)) bitmask = rightRotate(bitmask, 8); + if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2_rightrotate(bitmask, 8); + // if((addr & 8)) bitmask = da2_rightrotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { @@ -2476,29 +2519,29 @@ da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) case 0: /*Set*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - DA2_vram_w(addr | i, (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); - DA2_vram_w((addr + 8) | i, ((da2->gdcinput[i] >> 8) & bitmask_h) + da2_vram_w(addr | i, (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + da2_vram_w((addr + 8) | i, ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 1: /*AND*/ // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - DA2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); - DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + da2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + da2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 2: /*OR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - DA2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); - DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + da2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + da2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 3: /*XOR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - DA2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); - DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + da2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + da2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; } @@ -2625,47 +2668,6 @@ da2_mmio_readw(uint32_t addr, void *p) } } static void -da2_bitblt_addpayload(uint8_t val, void *p) -{ - da2_t *da2 = (da2_t *) p; - da2->bitblt.indata = 1; - if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) - da2_log("da2_mmio_write payload overflow! addr %x, val %x\n", da2->bitblt.payload_addr, val); - else { - if (da2->bitblt.payload_addr == 0) { - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - switch (val) { - case 0x88: - case 0x89: - case 0x95: - da2->bitblt.payload_opsize = 3; - break; - case 0x91: - da2->bitblt.payload_opsize = 5; - break; - case 0x99: - da2->bitblt.payload_opsize = 7; - break; - case 0xa1: - da2->bitblt.payload_opsize = 9; - break; - default: - da2_log("addpayload: Unknown PreOP! %x\n", val); - da2->bitblt.payload_addr = 0; /* ignore input */ - break; - } - } else if (da2->bitblt.payload_addr < da2->bitblt.payload_opsize) { - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - } else if (da2->bitblt.payload_addr == da2->bitblt.payload_opsize) { - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_opsize = 0; /* reset */ - da2_bitblt_parse(da2); - } - } -} -static void da2_mmio_write(uint32_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; @@ -2765,7 +2767,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) if (da2->planemask & (1 << i)) - DA2_vram_w(addr | i, da2->gdcsrc[i], da2); + da2_vram_w(addr | i, da2->gdcsrc[i], da2); break; case 0:/* equiv to vga write mode 0 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) @@ -2773,7 +2775,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) if (bitmask == 0xff && !(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, da2); + da2_vram_w(addr | i, val, da2); } else { for (int i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) @@ -2800,12 +2802,12 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else { /* mode 3h text */ cycles -= video_timing_write_b; - DA2_vram_w(addr, val, da2); + da2_vram_w(addr, val, da2); da2->fullchange = 2; } } static uint16_t -rightRotate(uint16_t data, uint8_t count) +da2_rightrotate(uint16_t data, uint8_t count) { return (data >> count) | (data << (sizeof(data) * 8 - count)); } @@ -2863,18 +2865,18 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) case 2: for (int i = 0; i < 8; i++) if (da2->planemask & (1 << i)) { - DA2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); - DA2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); + da2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); + da2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); } break; case 0: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); + val = da2_rightrotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); if (bitmask == 0xffff && !(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 & 0xff, da2); - DA2_vram_w((addr + 8) | i, val >> 8, da2); + da2_vram_w(addr | i, val & 0xff, da2); + da2_vram_w((addr + 8) | i, val >> 8, da2); } } else { for (int i = 0; i < 8; i++) @@ -2893,7 +2895,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) break; case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); + val = da2_rightrotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); bitmask &= val; for (int i = 0; i < 8; i++) From b484bf1b45fd8c3c177a4d6cdaa5eccd7e182784 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:04:43 +0900 Subject: [PATCH 0673/1190] PS55DA2: Add a bracket to avoid compile warning --- src/video/vid_ps55da2.c | 92 +++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 39adc3607..7abdae157 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -996,60 +996,62 @@ da2_bitblt_exec(void *p) // da2->bitblt.indata = 0; break; case DA2_BLT_CLINE: - /* Draw a dot */ - da2_bltlog("point: %d %d %d %d %d\n", da2->bitblt.x, da2->bitblt.y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); - int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; - int pixelmask = da2->bitblt.x % 16; - if (pixelmask >= 8) - pixelmask = (0x8000 >> (pixelmask - 8)); - else - pixelmask = (0x80 >> pixelmask); + { + /* Draw a dot */ + da2_bltlog("point: %d %d %d %d %d\n", da2->bitblt.x, da2->bitblt.y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; + int pixelmask = da2->bitblt.x % 16; + if (pixelmask >= 8) + pixelmask = (0x8000 >> (pixelmask - 8)); + else + pixelmask = (0x80 >> pixelmask); - /* check the current position is inside the window */ - if (da2->bitblt.x < da2->bitblt.wx1 || da2->bitblt.x > da2->bitblt.wx2 - || da2->bitblt.y < da2->bitblt.wy1 || da2->bitblt.y > da2->bitblt.wy2) - ; - else - da2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); - da2->bitblt.count++; + /* check the current position is inside the window */ + if (da2->bitblt.x < da2->bitblt.wx1 || da2->bitblt.x > da2->bitblt.wx2 + || da2->bitblt.y < da2->bitblt.wy1 || da2->bitblt.y > da2->bitblt.wy2) + ; + else + da2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); + da2->bitblt.count++; - /* calculate the next position with Bresenham's line algorithm */ - if (da2->bitblt.octdir & 0x04) { /* dX > dY */ - if (da2->bitblt.octdir & 0x02) { - da2->bitblt.x++; - } else { - da2->bitblt.x--; - } - if (da2->bitblt.d >= 0) { - da2->bitblt.d -= (2 * da2->bitblt.size_x); - if (da2->bitblt.octdir & 0x01) { - da2->bitblt.y++; - } else { - da2->bitblt.y--; - } - } - da2->bitblt.d += (2 * da2->bitblt.size_y); - if (da2->bitblt.count >= da2->bitblt.size_x) - da2->bitblt.exec = DA2_BLT_CDONE; - } else { - if (da2->bitblt.octdir & 0x01) { - da2->bitblt.y++; - } else { - da2->bitblt.y--; - } - if (da2->bitblt.d >= 0) { - da2->bitblt.d -= (2 * da2->bitblt.size_y); + /* calculate the next position with Bresenham's line algorithm */ + if (da2->bitblt.octdir & 0x04) { /* dX > dY */ if (da2->bitblt.octdir & 0x02) { da2->bitblt.x++; } else { da2->bitblt.x--; } + if (da2->bitblt.d >= 0) { + da2->bitblt.d -= (2 * da2->bitblt.size_x); + if (da2->bitblt.octdir & 0x01) { + da2->bitblt.y++; + } else { + da2->bitblt.y--; + } + } + da2->bitblt.d += (2 * da2->bitblt.size_y); + if (da2->bitblt.count >= da2->bitblt.size_x) + da2->bitblt.exec = DA2_BLT_CDONE; + } else { + if (da2->bitblt.octdir & 0x01) { + da2->bitblt.y++; + } else { + da2->bitblt.y--; + } + if (da2->bitblt.d >= 0) { + da2->bitblt.d -= (2 * da2->bitblt.size_y); + if (da2->bitblt.octdir & 0x02) { + da2->bitblt.x++; + } else { + da2->bitblt.x--; + } + } + da2->bitblt.d += (2 * da2->bitblt.size_x); + if (da2->bitblt.count >= da2->bitblt.size_y) + da2->bitblt.exec = DA2_BLT_CDONE; } - da2->bitblt.d += (2 * da2->bitblt.size_x); - if (da2->bitblt.count >= da2->bitblt.size_y) - da2->bitblt.exec = DA2_BLT_CDONE; + break; } - break; case DA2_BLT_CFILLRECT: // da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); if (da2->bitblt.x >= da2->bitblt.size_x - 1) { From d3d5d3e7805d8c01b80d714057089b6deead4614 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 4 Apr 2025 18:19:28 +0200 Subject: [PATCH 0674/1190] Fix the calculation of the number of sectors per packet and stop the transfer when the total sector count has reached zero, fixes #5432. --- src/scsi/scsi_cdrom.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 9ae65be74..e5689dd76 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1055,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 < num) && (ret > 0); i++) { + for (int i = 0; (i < num) && (ret > 0) && (dev->sector_len > 0); i++) { ret = cdrom_readsector_raw(dev->drv, dev->buffer + dev->buffer_pos, dev->sector_pos, msf, type, flags, &temp_len, vendor_type); @@ -1070,7 +1070,11 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int if ((dev->drv->bus_type != CDROM_BUS_SCSI) && (scsi_cdrom_current_mode(dev) != 2)) { - num = (dev->packet_len / dev->block_len); + num = (dev->tf->request_length < dev->block_len) ? + dev->block_len : dev->tf->request_length; + num = (num / dev->block_len) * dev->block_len; + if (num > dev->sector_len) + num = dev->sector_len; } } From 1c38e059c4b9074ad17729a2dfe981e90d1a000c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 4 Apr 2025 18:29:28 +0200 Subject: [PATCH 0675/1190] PS/55 DA2: Fix warnings. --- src/video/vid_ps55da2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 7abdae157..9a95e6ce6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -596,7 +596,9 @@ getRAMFont(int32_t code, int line, int x, void *p) { da2_t *da2 = (da2_t *) p; uint32_t font = 0; +#ifdef RESERVED_FOR_FUTURE_USE int fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ +#endif if (code < 0x100) { /* SBCS 13x29 */ code *= 0x40; code += DA2_GAIJIRAM_SBCS + (line * 2) + x; @@ -620,6 +622,7 @@ getRAMFont(int32_t code, int line, int x, void *p) font = 0; return font; } +#ifdef RESERVED_FOR_FUTURE_USE /* Reverse the bit order of attribute code IBGR to IRGB(used in Mode 3 and Cursor Color) */ static int8_t IBGRtoIRGB(uint8_t attr) @@ -627,6 +630,7 @@ IBGRtoIRGB(uint8_t attr) attr = ((attr & 0x01) << 6) | ((attr & 0x02) << 4) | ((attr & 0x04) << 2) | ((attr & 0x08) << 4); return attr >>= 4; } +#endif static void da2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, uint32_t destaddr, uint16_t maskl, uint16_t maskr, da2_t *da2) { From fd2214f54471c02bea2c99deda54ac138f5d4f43 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 4 Apr 2025 18:55:22 +0200 Subject: [PATCH 0676/1190] Intel Classic/PCI: Return input port (P1) bit 4 clear, fixes #5435. --- src/device/kbc_at.c | 59 +++++++++++++++++++++++++++++++----- src/machine/m_at_386dx_486.c | 5 +-- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index abb10d108..f8fd33e62 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1070,10 +1070,14 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 8; /* (B0 or F0) | (0x04 or 0x0c) */ kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00); - } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) + } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) { /* (B0 or F0) | (0x08 or 0x0c) */ - kbc_delay_to_ob(dev, ((dev->p1 | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00); - else if (kbc_ven == KBC_VEN_COMPAQ) + uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) | + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c); + if (!strcmp(machine_get_internal_name(), "alfredo")) + p1_out &= 0xef; + kbc_delay_to_ob(dev, p1_out, 0, 0x00); + } else if (kbc_ven == KBC_VEN_COMPAQ) kbc_delay_to_ob(dev, dev->p1 | (hasfpu ? 0x00 : 0x04), 0, 0x00); else /* (B0 or F0) | (0x04 or 0x44) */ @@ -1578,8 +1582,13 @@ write64_phoenix(void *priv, uint8_t val) case 0xd5: /* Read MultiKey code revision level */ kbc_at_log("ATkbc: Phoenix - Read MultiKey code revision level\n"); if (dev->misc_flags & FLAG_PS2) { - kbc_at_queue_add(dev, 0x04); - kbc_at_queue_add(dev, 0x16); + if (dev->flags & DEVICE_PCI) { + kbc_at_queue_add(dev, 0x04); + kbc_at_queue_add(dev, 0x16); + } else { + kbc_at_queue_add(dev, 0x01); + kbc_at_queue_add(dev, 0x38); + } } else { kbc_at_queue_add(dev, 0x01); kbc_at_queue_add(dev, 0x29); @@ -1598,9 +1607,15 @@ write64_phoenix(void *priv, uint8_t val) case 0xd7: /* Read MultiKey model numbers */ kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n"); if (dev->misc_flags & FLAG_PS2) { - kbc_at_queue_add(dev, 0x02); - kbc_at_queue_add(dev, 0x87); - kbc_at_queue_add(dev, 0x02); + if (dev->flags & DEVICE_PCI) { + kbc_at_queue_add(dev, 0x02); + kbc_at_queue_add(dev, 0x87); + kbc_at_queue_add(dev, 0x02); + } else { + kbc_at_queue_add(dev, 0x99); + kbc_at_queue_add(dev, 0x75); + kbc_at_queue_add(dev, 0x01); + } } else { kbc_at_queue_add(dev, 0x90); kbc_at_queue_add(dev, 0x88); @@ -2608,6 +2623,20 @@ const device_t keyboard_ps2_ami_device = { .config = NULL }; +const device_t keyboard_ps2_compaq_device = { + .name = "PS/2 Keyboard (Compaq)", + .internal_name = "keyboard_at_compaq", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_COMPAQ, + .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_holtek_device = { .name = "PS/2 Keyboard (Holtek)", .internal_name = "keyboard_ps2_holtek", @@ -2775,3 +2804,17 @@ const device_t keyboard_ps2_acer_pci_device = { .force_redraw = NULL, .config = NULL }; + +const device_t keyboard_ps2_phoenix_pci_device = { + .name = "PS/2 Keyboard (Phoenix)", + .internal_name = "keyboard_ps2_acer_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | 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 +}; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 7f285af65..4e659dd77 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1281,14 +1281,15 @@ machine_at_ninja_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 1, 2, 1); - device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&keyboard_ps2_phoenix_device); device_add(&intel_flash_bxt_ami_device); device_add(&i420ex_device); From 14ffb89f4d01fe01353e97edf7b874d9f6944477 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 5 Apr 2025 01:49:54 +0600 Subject: [PATCH 0677/1190] SAASound filter fixes --- src/sound/saasound/SAAImpl.cpp | 1 - src/sound/saasound/SAAImpl.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sound/saasound/SAAImpl.cpp b/src/sound/saasound/SAAImpl.cpp index f136eefc6..cb5d8f739 100644 --- a/src/sound/saasound/SAAImpl.cpp +++ b/src/sound/saasound/SAAImpl.cpp @@ -306,7 +306,6 @@ void scale_for_output(unsigned int left_input, unsigned int right_input, void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples) { unsigned int left_mixed, right_mixed; - static double filterout_z1_left_mixed = 0, filterout_z1_right_mixed = 0; #if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) BYTE* pBufferStart = pBuffer; diff --git a/src/sound/saasound/SAAImpl.h b/src/sound/saasound/SAAImpl.h index 61fa79c58..6cd3048fe 100755 --- a/src/sound/saasound/SAAImpl.h +++ b/src/sound/saasound/SAAImpl.h @@ -36,6 +36,8 @@ private: unsigned int m_nSampleRate; unsigned int m_nOversample; bool m_bHighpass; + double filterout_z1_left_mixed = 0; + double filterout_z1_right_mixed = 0; #ifdef USE_CONFIG_FILE SAAConfig m_Config; #endif From 6d2128ab0573cfdc0cf5d31a4437d051de91123c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 5 Apr 2025 23:59:49 +0600 Subject: [PATCH 0678/1190] Make Qt shortcuts actually work in fullscreen Also removes hacks related to fullscreen. --- src/qt/qt_main.cpp | 4 --- src/qt/qt_mainwindow.cpp | 59 +++++++++++++++++++--------------------- src/qt/qt_mainwindow.hpp | 1 - 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 2ef797bd1..1f1dd6b49 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -194,8 +194,6 @@ win_keyboard_handle(uint32_t scancode, int up, int e0, int e1) it's not an invalid scan code. */ if (scancode != 0xFFFF) keyboard_input(!up, scancode); - - main_window->checkFullscreenHotkey(); } } @@ -370,8 +368,6 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) else if ((lpKdhs->scanCode == 0x3e) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) ret = TRUE; - else if ((lpKdhs->scanCode == 0x49) && bCtrlDown && !(lpKdhs->flags & LLKHF_UP)) - ret = TRUE; else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) ret = TRUE; else if (inhibit_multimedia_keys diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 4c04ce76e..806e8e0e6 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -674,6 +674,13 @@ MainWindow::MainWindow(QWidget *parent) /* Remove default Shift+F10 handler, which unfocuses keyboard input even with no context menu. */ connect(new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F10), this), &QShortcut::activated, this, [](){}); + auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_PageDown), this); + windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); + connect(windowedShortcut, &QShortcut::activated, this, [this] () { + if (video_fullscreen) + ui->actionFullscreen->trigger(); + }); + connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot); connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection); connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot); @@ -696,6 +703,22 @@ MainWindow::MainWindow(QWidget *parent) }); #endif + QTimer::singleShot(0, this, [this]() { + for (auto curObj : this->menuBar()->children()) { + if (qobject_cast(curObj)) { + auto menu = qobject_cast(curObj); + for (auto curObj2 : menu->children()) { + if (qobject_cast(curObj2)) { + auto action = qobject_cast(curObj2); + if (!action->shortcut().isEmpty()) { + this->insertAction(nullptr, action); + } + } + } + } + } + }); + actGroup = new QActionGroup(this); actGroup->addAction(ui->actionCursor_Puck); actGroup->addAction(ui->actionPen); @@ -833,6 +856,11 @@ MainWindow::initRendererMonitorSlot(int monitor_index) }); secondaryRenderer->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); secondaryRenderer->setWindowTitle(QObject::tr("86Box Monitor #") + QString::number(monitor_index + 1)); + secondaryRenderer->setContextMenuPolicy(Qt::PreventContextMenu); + + for (int i = 0; i < this->actions().size(); i++) { + secondaryRenderer->addAction(this->actions()[i]); + } if (vid_resize == 2) secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); @@ -1360,18 +1388,9 @@ MainWindow::keyPressEvent(QKeyEvent *event) #endif } - checkFullscreenHotkey(); - if (keyboard_ismsexit()) plat_mouse_capture(0); - if ((video_fullscreen > 0) && (keyboard_recv_ui(0x1D) || keyboard_recv_ui(0x11D))) { - if (keyboard_recv_ui(0x57)) - ui->actionTake_screenshot->trigger(); - else if (keyboard_recv_ui(0x58)) - pc_send_cad(); - } - event->accept(); } @@ -1403,28 +1422,6 @@ MainWindow::keyReleaseEvent(QKeyEvent *event) processKeyboardInput(false, event->nativeScanCode()); #endif } - - checkFullscreenHotkey(); -} - -void -MainWindow::checkFullscreenHotkey() -{ - if (!fs_off_signal && video_fullscreen && keyboard_isfsexit()) { - /* Signal "exit fullscreen mode". */ - fs_off_signal = true; - } else if (fs_off_signal && video_fullscreen && keyboard_isfsexit_up()) { - ui->actionFullscreen->trigger(); - fs_off_signal = false; - } - - if (!fs_on_signal && !video_fullscreen && keyboard_isfsenter()) { - /* Signal "enter fullscreen mode". */ - fs_on_signal = true; - } else if (fs_on_signal && !video_fullscreen && keyboard_isfsenter_up()) { - ui->actionFullscreen->trigger(); - fs_on_signal = false; - } } QSize diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index f1c6cadf6..5c8bd388b 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -31,7 +31,6 @@ public: void blitToWidget(int x, int y, int w, int h, int monitor_index); QSize getRenderWidgetSize(); void setSendKeyboardInput(bool enabled); - void checkFullscreenHotkey(); void reloadAllRenderers(); std::array, 8> renderers; From 375590b93b0939154513e248d46d281bf0a3f0c9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 6 Apr 2025 01:05:12 +0200 Subject: [PATCH 0679/1190] Bochs SVGA: Add some sanity check to avoid the LFB and BIOS being mapped to either at the very bottom or top of the memory space. --- src/video/vid_bochs_vbe.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index 84fb110c6..ac7bc00cb 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -686,7 +686,7 @@ bochs_vbe_pci_read(const int func, const int addr, void *priv) ret = dev->pci_rom_enable & 0x01; break; case 0x32: - ret = dev->rom_addr & 0xff; + ret = dev->rom_addr & 0xfc; break; case 0x33: ret = (dev->rom_addr & 0xff00) >> 8; @@ -743,6 +743,7 @@ bochs_vbe_pci_write(const int func, const int addr, const uint8_t val, void *pri mem_mapping_disable(&dev->linear_mapping_2); mem_mapping_disable(&dev->linear_mapping); mem_mapping_disable(&dev->svga.mapping); + mem_mapping_disable(&dev->bios_rom.mapping); if (dev->pci_conf_status & PCI_COMMAND_IO) { io_sethandler(0x03c0, 0x0020, bochs_vbe_in, NULL, NULL, bochs_vbe_out, NULL, NULL, dev); @@ -751,11 +752,13 @@ bochs_vbe_pci_write(const int func, const int addr, const uint8_t val, void *pri } if (dev->pci_conf_status & PCI_COMMAND_MEM) { mem_mapping_enable(&dev->svga.mapping); - if (dev->pci_regs[0x13] != 0x00) { + if ((dev->pci_regs[0x13] != 0x00) && (dev->pci_regs[0x13] != 0xff)) { mem_mapping_enable(&dev->linear_mapping); if (dev->pci_regs[0x13] != 0xe0) mem_mapping_enable(&dev->linear_mapping_2); } + if (dev->pci_rom_enable && (dev->rom_addr != 0x0000) && (dev->rom_addr < 0xfff8)) + mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); } break; case 0x13: @@ -764,7 +767,7 @@ bochs_vbe_pci_write(const int func, const int addr, const uint8_t val, void *pri mem_mapping_disable(&dev->linear_mapping_2); mem_mapping_disable(&dev->linear_mapping); - if ((dev->pci_conf_status & PCI_COMMAND_MEM) && (val != 0x00)) { + if ((dev->pci_conf_status & PCI_COMMAND_MEM) && (val != 0x00) && (val != 0xff)) { mem_mapping_set_addr(&dev->linear_mapping, val << 24, 0x01000000); if (val != 0xe0) mem_mapping_set_addr(&dev->linear_mapping_2, 0xe0000000, 0x01000000); @@ -776,18 +779,26 @@ bochs_vbe_pci_write(const int func, const int addr, const uint8_t val, void *pri case 0x30: dev->pci_rom_enable = val & 0x01; mem_mapping_disable(&dev->bios_rom.mapping); - if (dev->pci_rom_enable) + if (dev->pci_rom_enable && (dev->pci_conf_status & PCI_COMMAND_MEM) && + (dev->rom_addr != 0x0000) && (dev->rom_addr < 0xfff8)) { mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); + } break; case 0x32: dev->rom_addr = (dev->rom_addr & 0xff00) | (val & 0xfc); - if (dev->pci_rom_enable) + mem_mapping_disable(&dev->bios_rom.mapping); + if (dev->pci_rom_enable && (dev->pci_conf_status & PCI_COMMAND_MEM) && + (dev->rom_addr != 0x0000) && (dev->rom_addr < 0xfff8)) { mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); + } break; case 0x33: dev->rom_addr = (dev->rom_addr & 0x00ff) | (val << 8); - if (dev->pci_rom_enable) + mem_mapping_disable(&dev->bios_rom.mapping); + if (dev->pci_rom_enable && (dev->pci_conf_status & PCI_COMMAND_MEM) && + (dev->rom_addr != 0x0000) && (dev->rom_addr < 0xfff8)) { mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); + } break; } } From 06bacb6912be8688cb3f617a4e4edb02195ae3f0 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 7 Apr 2025 01:01:26 +0600 Subject: [PATCH 0680/1190] Bochs SVGA: Buffer window switching now works properly --- src/video/vid_bochs_vbe.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index ac7bc00cb..6dc015fb0 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -338,20 +338,13 @@ bochs_vbe_recalctimings(svga_t* svga) svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); + + svga->fullchange = 3; } else { svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + - (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); - } - if (svga->ma_latch != dev->ma_latch_old) { - if (svga->bpp == 4) { - svga->maback = (svga->maback - (dev->ma_latch_old << 2)) + - (svga->ma_latch << 2); - } else { - svga->maback = (svga->maback - (dev->ma_latch_old)) + - (svga->ma_latch); - dev->ma_latch_old = svga->ma_latch; - } + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); + svga->fullchange = 3; } if (svga->bpp == 4) @@ -482,18 +475,10 @@ bochs_vbe_outw(const uint16_t addr, const uint16_t val, void *priv) } else { svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + - (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); - } - if (svga->ma_latch != dev->ma_latch_old) { - if (svga->bpp == 4) { - svga->maback = (svga->maback - (dev->ma_latch_old << 2)) + - (svga->ma_latch << 2); - } else { - svga->maback = (svga->maback - (dev->ma_latch_old)) + - (svga->ma_latch); - dev->ma_latch_old = svga->ma_latch; - } + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); } + + svga->fullchange = 3; } else svga_recalctimings(&dev->svga); From 449c224ff7dd4640088321c3befa65c4a13ab5f7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 6 Apr 2025 21:23:53 +0200 Subject: [PATCH 0681/1190] SiS 471: Fix array out of bounds writes. --- src/chipset/sis_85c4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 6e26a4751..537675a85 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -375,7 +375,7 @@ sis_85c4xx_init(const device_t *info) dev->reg_base = info->local & 0xff; if (dev->is_471) { - dev->reg_last = dev->reg_base + 0x76; + dev->reg_last = 0x76; dev->smram = smram_add(); From e48d64de4572e8a42217f51e2c69327f0d1fec64 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 01:44:12 +0200 Subject: [PATCH 0682/1190] SCSI CD-ROM/Disk/MO/ZIP: Treat data commands with request length 0 in ATAPI PIO mode as non-data commands, also allow WIN_SRST to go through BSY, fixes the regressions introduced in build 6731 reported by JVERNET. --- src/disk/hdc_ide.c | 51 +++++++++++++++++++++++++++++++------------ src/disk/mo.c | 5 ++++- src/disk/zip.c | 5 ++++- src/scsi/scsi_cdrom.c | 20 ++++++++++++----- src/scsi/scsi_disk.c | 5 ++++- 5 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 01690cd70..04e580e72 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1208,7 +1208,9 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) 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_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read"); + ide_log("%i bytes %s, command done, %i sectors left\n", ide->tf->pos, out ? "written" : "read", + dev->sector_len); ide->tf->pos = dev->request_pos = 0; @@ -1262,13 +1264,12 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) 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); - ide_atapi_callback(ide); + if ((ide->sc->packet_status == PHASE_COMPLETE) && + (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); } } } else { @@ -1280,10 +1281,9 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) if (ide->command_stop != NULL) ide->command_stop(dev); - ide->sc->packet_status = PHASE_COMPLETE; - ide->sc->callback = 0.0; - - ide_atapi_callback(ide); + if ((ide->sc->packet_status == PHASE_COMPLETE) && + (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); } } else if (ide->read != NULL) ide->read(dev); @@ -1299,8 +1299,8 @@ ide_atapi_packet_read(ide_t *ide) uint16_t ret = 0; if (dev && dev->temp_buffer && (dev->packet_status == PHASE_DATA_IN)) { - ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n", - dev->request_pos, dev->max_transfer_len, ide->tf->pos, dev->packet_len); + /* ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n", + dev->request_pos, dev->max_transfer_len, ide->tf->pos, dev->packet_len); */ bufferw = (uint16_t *) dev->temp_buffer; @@ -1722,7 +1722,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) break; case 0x7: /* Command register */ - if (ide->tf->atastat & (BSY_STAT | DRQ_STAT)) + if ((ide->tf->atastat & (BSY_STAT | DRQ_STAT)) && + ((val != WIN_SRST) || (ide->type != IDE_ATAPI))) break; if ((ide->type == IDE_NONE) || ((ide->type & IDE_SHADOW) && (val != WIN_DRIVE_DIAGNOSTICS))) @@ -2158,7 +2159,8 @@ ide_read_alt_status(UNUSED(const uint16_t addr), void *priv) if (!(addr & 0x0001)) ret = ide_status(ide, ide_drives[ch ^ 1], ch); - ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + // ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + // ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); return ret; } @@ -3159,6 +3161,13 @@ ide_init(const device_t *info) ide_board_init(1, HDC_SECONDARY_IRQ, HDC_SECONDARY_BASE, HDC_SECONDARY_SIDE, info->local, info->flags); break; + case 8 ... 0x0d: + ide_board_init(2, -1, 0, 0, info->local, info->flags); + + if (info->local & 1) + ide_board_init(3, -1, 0, 0, info->local, info->flags); + break; + default: break; } @@ -3540,7 +3549,7 @@ const device_t mcide_device = { .name = "MCA McIDE Controller", .internal_name = "ide_mcide", .flags = DEVICE_MCA, - .local = 3, + .local = 1, .init = mcide_init, .close = mcide_close, .reset = mcide_reset, @@ -3661,3 +3670,17 @@ const device_t ide_qua_pnp_device = { .force_redraw = NULL, .config = NULL }; + +const device_t ide_pci_ter_qua_2ch_device = { + .name = "PCI IDE Controller (Dual-Channel Tertiary/Quaternary)", + .internal_name = "ide_pci_ter_qua_2ch", + .flags = DEVICE_PCI, + .local = 0x0d, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/disk/mo.c b/src/disk/mo.c index f1cd3b983..a20333404 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -584,7 +584,10 @@ mo_data_command_finish(mo_t *dev, int len, const int block_len, mo_command_write_dma(dev); } else { mo_update_request_length(dev, len, block_len); - if (direction == 0) + if ((dev->drv->bus_type != MO_BUS_SCSI) && + (dev->tf->request_length == 0)) + mo_command_complete(dev); + else if (direction == 0) mo_command_read(dev); else mo_command_write(dev); diff --git a/src/disk/zip.c b/src/disk/zip.c index eecafb802..7a407c5fe 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -665,7 +665,10 @@ zip_data_command_finish(zip_t *dev, int len, const int block_len, zip_command_write_dma(dev); } else { zip_update_request_length(dev, len, block_len); - if (direction == 0) + if ((dev->drv->bus_type != ZIP_BUS_SCSI) && + (dev->tf->request_length == 0)) + zip_command_complete(dev); + else if (direction == 0) zip_command_read(dev); else zip_command_write(dev); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index e5689dd76..2b37eeaca 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 @@ -689,6 +690,7 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) bytes_per_second *= (double) dev->drv->cur_speed; } else { bytes_per_second = scsi_cdrom_bus_speed(dev); + pclog("%lf bytes per second\n", bytes_per_second); if (bytes_per_second == 0.0) { dev->callback = -1; /* Speed depends on SCSI controller */ return; @@ -698,19 +700,24 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) period = 1000000.0 / bytes_per_second; scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", (uint64_t) period); + pclog("Byte transfer period: %lf us (%i bytes)\n", period, dev->packet_len); if (dev->was_cached == -1) period *= (double) dev->packet_len; else { + int atapi_num = (dev->tf->request_length < dev->block_len) ? + dev->block_len : dev->tf->request_length; + atapi_num = (atapi_num / dev->block_len) * dev->block_len; + if (atapi_num > dev->sector_len) + atapi_num = dev->sector_len; 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)); + (dev->block_len == 0)) ? dev->requested_blocks : + ((scsi_cdrom_current_mode(dev) == 2) ? 1 : atapi_num); period *= ((double) num) * 2352.0; } scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); + pclog("Data transfer period: %lf us\n", period); dev->callback += period; } scsi_cdrom_set_callback(dev); @@ -800,7 +807,10 @@ scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int al scsi_cdrom_command_write_dma(dev); } else { scsi_cdrom_update_request_length(dev, len, block_len); - if (direction == 0) + if ((dev->drv->bus_type != CDROM_BUS_SCSI) && + (dev->tf->request_length == 0)) + scsi_cdrom_command_complete(dev); + else if (direction == 0) scsi_cdrom_command_read(dev); else scsi_cdrom_command_write(dev); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 8528db1fb..0a035a23d 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -570,7 +570,10 @@ scsi_disk_data_command_finish(scsi_disk_t *dev, int len, const int block_len, scsi_disk_command_write_dma(dev); } else { scsi_disk_update_request_length(dev, len, block_len); - if (direction == 0) + if ((dev->drv->bus_type != HDD_BUS_SCSI) && + (dev->tf->request_length == 0)) + scsi_disk_command_complete(dev); + else if (direction == 0) scsi_disk_command_read(dev); else scsi_disk_command_write(dev); From b93af353efc0f9a93690d4011ad0e4b456ae7412 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 01:46:09 +0200 Subject: [PATCH 0683/1190] SCSI CD-ROM: Remove leftover excess logging. --- src/scsi/scsi_cdrom.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 2b37eeaca..306eed884 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 @@ -681,8 +680,7 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) /* 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: %lf us\n", period); dev->callback += period; /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ @@ -690,7 +688,6 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) bytes_per_second *= (double) dev->drv->cur_speed; } else { bytes_per_second = scsi_cdrom_bus_speed(dev); - pclog("%lf bytes per second\n", bytes_per_second); if (bytes_per_second == 0.0) { dev->callback = -1; /* Speed depends on SCSI controller */ return; @@ -698,9 +695,7 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) } period = 1000000.0 / bytes_per_second; - scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", - (uint64_t) period); - pclog("Byte transfer period: %lf us (%i bytes)\n", period, dev->packet_len); + scsi_cdrom_log(dev->log, "Byte transfer period: %lf us\n", period); if (dev->was_cached == -1) period *= (double) dev->packet_len; else { @@ -715,9 +710,7 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) period *= ((double) num) * 2352.0; } - scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", - (uint64_t) period); - pclog("Data transfer period: %lf us\n", period); + scsi_cdrom_log(dev->log, "Sector transfer period: %lf us\n", period); dev->callback += period; } scsi_cdrom_set_callback(dev); From 018ff46253293e39dc6c7aa9140c3425b6609825 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 05:42:41 +0200 Subject: [PATCH 0684/1190] CD-ROM: Actually remember and use the correct number of sectors for the period, fixes... well, any kind of data reading. --- src/include/86box/scsi_cdrom.h | 1 + src/scsi/scsi_cdrom.c | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/include/86box/scsi_cdrom.h b/src/include/86box/scsi_cdrom.h index 7bb39d9db..c01f347a8 100644 --- a/src/include/86box/scsi_cdrom.h +++ b/src/include/86box/scsi_cdrom.h @@ -70,6 +70,7 @@ typedef struct scsi_cdrom_t { int was_cached; int toc_cached; int media_access; + int sectors_num; uint8_t vendor_type; uint8_t ven_cmd_is_data[256]; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 306eed884..246f185e8 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -699,14 +699,9 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) if (dev->was_cached == -1) period *= (double) dev->packet_len; else { - int atapi_num = (dev->tf->request_length < dev->block_len) ? - dev->block_len : dev->tf->request_length; - atapi_num = (atapi_num / dev->block_len) * dev->block_len; - if (atapi_num > dev->sector_len) - atapi_num = dev->sector_len; const int num = ((dev->drv->bus_type == CDROM_BUS_SCSI) || - (dev->block_len == 0)) ? dev->requested_blocks : - ((scsi_cdrom_current_mode(dev) == 2) ? 1 : atapi_num); + (dev->block_len == 0)) ? dev->sectors_num : + ((scsi_cdrom_current_mode(dev) == 2) ? 1 : dev->sectors_num); period *= ((double) num) * 2352.0; } @@ -1051,6 +1046,8 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? dev->requested_blocks : 1; + dev->sectors_num = 0; + if (dev->drv->cd_status == CD_STATUS_EMPTY) scsi_cdrom_not_ready(dev); else if (dev->sector_pos > dev->drv->cdrom_capacity) { @@ -1085,6 +1082,7 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int dev->drv->seek_pos = dev->sector_pos; dev->sector_len--; + dev->sectors_num++; dev->buffer_pos += temp_len; } @@ -2423,6 +2421,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) int32_t *BufLen; dev->was_cached = -1; + dev->sectors_num = 1; if (dev->drv->bus_type == CDROM_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; From 3b5966eb465830b4fdb367d89cd44a930cb098ea Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 06:03:19 +0200 Subject: [PATCH 0685/1190] LDS/LES/LFS/LGS/LSS: Fix segment wraparounds in 16-bit address mode. --- src/codegen/codegen_ops_x86-64.h | 7 ++++ src/codegen/codegen_ops_x86.h | 7 ++++ src/codegen_new/codegen_backend_arm64_uops.c | 2 + src/codegen_new/codegen_backend_arm_uops.c | 2 + src/codegen_new/codegen_backend_x86-64_uops.c | 9 +++- src/codegen_new/codegen_backend_x86_uops.c | 9 +++- src/codegen_new/codegen_ir_defs.h | 10 ++++- src/codegen_new/codegen_ops_misc.c | 8 ++-- src/codegen_new/codegen_reg.c | 2 + src/codegen_new/codegen_reg.h | 4 +- src/cpu/386_common.h | 26 ++++++++++++ src/cpu/cpu.h | 5 ++- src/cpu/x86_ops_mov_seg.h | 41 +++++++++++-------- src/cpu/x86_ops_ret.h | 2 +- src/cpu/x86_ops_ret_2386.h | 2 +- 15 files changed, 105 insertions(+), 31 deletions(-) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index e46f55a05..1be5dfdce 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -1054,6 +1054,13 @@ MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) addbyte(0x83); /*ADD EAX, offset*/ addbyte(0xc0); addbyte(offset); + if (!(op_32 & 0x200)) { + addbyte(0x25) /* AND EAX, ffffh */ + addbyte(0xff); + addbyte(0xff); + addbyte(0x00); + addbyte(0x00); + } MEM_LOAD_ADDR_EA_W(seg); } static __inline void diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index c48324c2a..7a56b5fe1 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -802,6 +802,13 @@ MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) addbyte(0x83); /*ADD EAX, offset*/ addbyte(0xc0); addbyte(offset); + if (!(op_32 & 0x200)) { + addbyte(0x25) /* AND EAX, ffffh */ + addbyte(0xff); + addbyte(0xff); + addbyte(0x00); + addbyte(0x00); + } addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ addlong(mem_load_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index deaf53c20..82cc79cfd 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -931,6 +931,8 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); if (uop->imm_data) host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + if (uop->is_a16) + host_arm64_AND_IMM(block, REG_X0, REG_X0, 0xffff); if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { host_arm64_call(block, codegen_mem_load_byte); } else if (REG_IS_W(dest_size)) { diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c index d8c223884..b6963562c 100644 --- a/src/codegen_new/codegen_backend_arm_uops.c +++ b/src/codegen_new/codegen_backend_arm_uops.c @@ -995,6 +995,8 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); if (uop->imm_data) host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + if (uop->is_a16) + host_arm_AND_IMM(block, REG_R0, REG_R0, 0xffff); if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { host_arm_BL(block, (uintptr_t) codegen_mem_load_byte); } else if (REG_IS_W(dest_size)) { diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 46af68e75..0233a4636 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -997,8 +997,13 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (uop->imm_data) { + if (uop->is_a16) { + host_x86_ADD16_REG_IMM(block, REG_SI, uop->imm_data); + } else { + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + } + } if (REG_IS_B(dest_size)) { host_x86_CALL(block, codegen_mem_load_byte); } else if (REG_IS_W(dest_size)) { diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index cd79b9b47..beaf85c17 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -981,8 +981,13 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (uop->imm_data) { + if (uop->is_a16) { + host_x86_ADD16_REG_IMM(block, REG_SI, uop->imm_data); + } else { + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + } + } if (REG_IS_B(dest_size)) { host_x86_CALL(block, codegen_mem_load_byte); } else if (REG_IS_W(dest_size)) { diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index 9bd2f9afe..ff84c7ccd 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -340,6 +340,7 @@ typedef struct uop_t { void *p; ir_host_reg_t dest_reg_a_real; ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; + int is_a16; int jump_dest_uop; int jump_list_next; void *jump_dest; @@ -364,6 +365,8 @@ uop_alloc(ir_data_t *ir, uint32_t uop_type) uop = &ir->uops[ir->wr_pos++]; + uop->is_a16 = 0; + uop->dest_reg_a = invalid_ir_reg; uop->src_reg_a = invalid_ir_reg; uop->src_reg_b = invalid_ir_reg; @@ -489,7 +492,12 @@ uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->is_a16 = 0; + if (src_reg_b == IREG_eaa16) { + uop->src_reg_b = codegen_reg_read(IREG_eaaddr); + uop->is_a16 = 1; + } else + uop->src_reg_b = codegen_reg_read(src_reg_b); uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->imm_data = imm; } diff --git a/src/codegen_new/codegen_ops_misc.c b/src/codegen_new/codegen_ops_misc.c index 91e0f5d63..33e01d951 100644 --- a/src/codegen_new/codegen_ops_misc.c +++ b/src/codegen_new/codegen_ops_misc.c @@ -533,8 +533,8 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSE uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16, 2); \ uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ \ @@ -556,8 +556,8 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSE uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16, 4); \ uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ \ diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index a3f000826..de67fde5a 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -169,6 +169,8 @@ struct [IREG_GS_limit_high] = { REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT}, [IREG_SS_limit_high] = { REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_eaa16] = { REG_WORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ diff --git a/src/codegen_new/codegen_reg.h b/src/codegen_new/codegen_reg.h index ebb90b42f..fd3cf279a 100644 --- a/src/codegen_new/codegen_reg.h +++ b/src/codegen_new/codegen_reg.h @@ -132,7 +132,9 @@ enum { IREG_GS_limit_high = 86, IREG_SS_limit_high = 87, - IREG_COUNT = 88, + IREG_eaa16 = 88, + + IREG_COUNT = 89, IREG_INVALID = 255, diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index ec40612ee..a4ea5802b 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -248,6 +248,19 @@ int checkio(uint32_t port, int mask); return 1; \ } +#define CHECK_READ_2OP(chseg, low, high, low2, high2) \ + if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || (low2 < (chseg)->limit_low) || (high2 > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) { \ + x86gpf("Limit check (READ)", 0); \ + return 1; \ + } \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ + if ((chseg) == &cpu_state.seg_ss) \ + x86ss(NULL, (chseg)->seg & 0xfffc); \ + else \ + x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ + return 1; \ + } + #define CHECK_READ_REP(chseg, low, high) \ if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \ x86gpf("Limit check (READ)", 0); \ @@ -277,6 +290,19 @@ int checkio(uint32_t port, int mask); #define CHECK_WRITE(chseg, low, high) \ CHECK_WRITE_COMMON(chseg, low, high) +#define CHECK_WRITE_2OP(chseg, low, high, low2, high2) \ + if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || (low2 < (chseg)->limit_low) || (high2 > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) { \ + x86gpf("Limit check (WRITE)", 0); \ + return 1; \ + } \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ + if ((chseg) == &cpu_state.seg_ss) \ + x86ss(NULL, (chseg)->seg & 0xfffc); \ + else \ + x86np("Write to seg not present", (chseg)->seg & 0xfffc); \ + return 1; \ + } + #define CHECK_WRITE_REP(chseg, low, high) \ if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \ x86gpf("Limit check (WRITE REP)", 0); \ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 80097294d..0e49704fd 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -335,7 +335,10 @@ typedef struct { uint8_t tag[8]; x86seg *ea_seg; - uint32_t eaaddr; + union { + uint32_t eaaddr; + uint16_t eaa16[2]; + }; int flags_op; uint32_t flags_res; diff --git a/src/cpu/x86_ops_mov_seg.h b/src/cpu/x86_ops_mov_seg.h index 7fcc92312..a34bc0c70 100644 --- a/src/cpu/x86_ops_mov_seg.h +++ b/src/cpu/x86_ops_mov_seg.h @@ -272,9 +272,10 @@ opLDS_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); + CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, + ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); + addr = readmemw(easeg, cpu_state.eaa16[0]); + seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ds); @@ -318,9 +319,10 @@ opLDS_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); + CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, + ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); + addr = readmeml(easeg, cpu_state.eaa16[0]); + seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ds); @@ -365,9 +367,10 @@ opLSS_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); + CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, + ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); + addr = readmemw(easeg, cpu_state.eaa16[0]); + seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ss); @@ -411,9 +414,11 @@ opLSS_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); + CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, + ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 5) & 0xffff)); + addr = readmeml(easeg, cpu_state.eaa16[0]); + seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ss); @@ -457,9 +462,9 @@ opLSS_l_a32(uint32_t fetchdat) fetch_ea_16(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ - addr = readmemw(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 2); \ + CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); \ + addr = readmemw(easeg, cpu_state.eaa16[0]); \ + seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); \ if (cpu_state.abrt) \ return 1; \ op_loadseg(seg, &sel); \ @@ -502,9 +507,9 @@ opLSS_l_a32(uint32_t fetchdat) fetch_ea_16(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \ - addr = readmeml(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 4); \ + CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); \ + addr = readmeml(easeg, cpu_state.eaa16[0]); \ + seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); \ if (cpu_state.abrt) \ return 1; \ op_loadseg(seg, &sel); \ diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index 935fb5aa0..8bf72e9ed 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -15,7 +15,7 @@ op_loadcs(readmemw(ss, ESP + 2)); \ } else { \ cpu_state.pc = readmemw(ss, SP); \ - op_loadcs(readmemw(ss, SP + 2)); \ + op_loadcs(readmemw(ss, (SP + 2) & 0xffff)); \ } \ if (cpu_state.abrt) \ return 1; \ diff --git a/src/cpu/x86_ops_ret_2386.h b/src/cpu/x86_ops_ret_2386.h index 155925dfe..02233fd1d 100644 --- a/src/cpu/x86_ops_ret_2386.h +++ b/src/cpu/x86_ops_ret_2386.h @@ -15,7 +15,7 @@ op_loadcs(readmemw(ss, ESP + 2)); \ } else { \ cpu_state.pc = readmemw(ss, SP); \ - op_loadcs(readmemw(ss, SP + 2)); \ + op_loadcs(readmemw(ss, (SP + 2) & 0xffff)); \ } \ if (cpu_state.abrt) \ return 1; \ From 6884dc573688c4e16b71c218ccc676d8e5796d50 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 06:23:22 +0200 Subject: [PATCH 0686/1190] Old recompiler: Fix compile-breaking mistakes. --- src/codegen/codegen_ops_x86-64.h | 2 +- src/codegen/codegen_ops_x86.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 1be5dfdce..1d9b29de2 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -1055,7 +1055,7 @@ MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) addbyte(0xc0); addbyte(offset); if (!(op_32 & 0x200)) { - addbyte(0x25) /* AND EAX, ffffh */ + addbyte(0x25); /* AND EAX, ffffh */ addbyte(0xff); addbyte(0xff); addbyte(0x00); diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index 7a56b5fe1..5e7165939 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -803,7 +803,7 @@ MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) addbyte(0xc0); addbyte(offset); if (!(op_32 & 0x200)) { - addbyte(0x25) /* AND EAX, ffffh */ + addbyte(0x25); /* AND EAX, ffffh */ addbyte(0xff); addbyte(0xff); addbyte(0x00); From 576d643c4f655affdc0b5d041d3ec97263c64bb2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 06:29:57 +0200 Subject: [PATCH 0687/1190] And fix the op_32 stuff. --- src/codegen/codegen_ops_mov.h | 4 ++-- src/codegen/codegen_ops_x86-64.h | 2 +- src/codegen/codegen_ops_x86.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codegen/codegen_ops_mov.h b/src/codegen/codegen_ops_mov.h index 6a5054b81..eb2a0202c 100644 --- a/src/codegen/codegen_ops_mov.h +++ b/src/codegen/codegen_ops_mov.h @@ -600,12 +600,12 @@ ropMOV_seg_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t MEM_LOAD_ADDR_EA_L(target_seg); \ STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, 0); \ LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4, op_32); \ } else { \ MEM_LOAD_ADDR_EA_W(target_seg); \ STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, 0); \ LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2, op_32); \ } \ LOAD_SEG(0, &rseg); \ if (op_32 & 0x100) { \ diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 1d9b29de2..129d9a740 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -1049,7 +1049,7 @@ MEM_LOAD_ADDR_EA_W(x86seg *seg) /*done:*/ } static __inline void -MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset, int op_32) { addbyte(0x83); /*ADD EAX, offset*/ addbyte(0xc0); diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index 5e7165939..3fbefdeaa 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -789,7 +789,7 @@ MEM_LOAD_ADDR_EA_W(x86seg *seg) host_reg_mapping[0] = 8; } static __inline void -MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset, int op_32) { if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { addbyte(0x31); /*XOR EDX, EDX*/ From fb449f39a44529f0cea0d1842145595f1425ee17 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Apr 2025 07:41:59 +0200 Subject: [PATCH 0688/1190] Intel Premiere/PCI and Premiere/PCI II: Use a dual-channel IDE controller, fixes #5442. --- src/machine/m_at_socket4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 0d78c6de3..c747d8cc0 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -47,7 +47,7 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) machine_at_common_init_ex(model, 2); device_add(&amstrad_megapc_nvr_device); - device_add(&ide_pci_device); + device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | pci_switch); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); From 44db8bb478eba862d66acbc4f9cc90336ff5d35c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 7 Apr 2025 11:42:03 +0600 Subject: [PATCH 0689/1190] Fix compilation on Qt6 --- src/qt/qt_mainwindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 806e8e0e6..e9ebdaad8 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -674,7 +674,11 @@ MainWindow::MainWindow(QWidget *parent) /* Remove default Shift+F10 handler, which unfocuses keyboard input even with no context menu. */ connect(new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F10), this), &QShortcut::activated, this, [](){}); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_PageDown), this); +#else auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_PageDown), this); +#endif windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); connect(windowedShortcut, &QShortcut::activated, this, [this] () { if (video_fullscreen) From ebf125082a951752f3b3a819daf6e115a2fc1175 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 7 Apr 2025 20:33:50 +0200 Subject: [PATCH 0690/1190] Revert a minor commit from Spock. (April 7th, 2025) This fixes OS/2 Warp on a PS/2 machine using the Spock/Tribble during the file copy phase (the bug was probably too many IRQ's being fired). --- src/scsi/scsi_spock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index c500abfbc..6f0b7aacb 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1050,7 +1050,7 @@ spock_callback(void *priv) spock_execute_cmd(scsi, scb); } - if (scsi->attention_wait) { + if (scsi->attention_wait && ((scsi->scb_state == 0) || (scsi->attention_pending & 0xf0) == 0xe0)) { scsi->attention_wait--; if (!scsi->attention_wait) { scsi->attention = scsi->attention_pending; From 9032af002de12ca93282f6c8778ce0a0089d6362 Mon Sep 17 00:00:00 2001 From: Torinde <97228894+Torinde@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:17:50 +0200 Subject: [PATCH 0691/1190] VIA Cyrix III (Samuel) - add codename To distinguish from Cyrix-heritage Joshua CPUs. #5451 --- src/cpu/cpu_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e5c91b1a8..8524306dc 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -7793,7 +7793,7 @@ const cpu_family_t cpu_families[] = { { .package = CPU_PKG_SOCKET370, .manufacturer = "VIA", - .name = "Cyrix III", + .name = "Cyrix III (Samuel)", .internal_name = "c3_samuel", .cpus = (const CPU[]) { { /* out of multiplier range */ From f5fcebfbaa7552fc5533a1752ab0f0ea8e953fb8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Apr 2025 12:19:24 +0200 Subject: [PATCH 0692/1190] Default the language to the system language. --- src/config.c | 2 ++ src/include/86box/86box.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 8ff7d548c..f38b5aa2c 100644 --- a/src/config.c +++ b/src/config.c @@ -1840,6 +1840,8 @@ config_load(void) cassette_pcm = 0; cassette_ui_writeprot = 0; + lang_id = DEFAULT_LANGUAGE; + config_log("Config file not present or invalid!\n"); } else { load_general(); /* General */ diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 61de69cf3..ddca937f1 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -45,7 +45,7 @@ #define MAX_UUID_LEN 64 /* Default language 0xFFFF = from system, 0x409 = en-US */ -#define DEFAULT_LANGUAGE 0x0409 +#define DEFAULT_LANGUAGE 0xffff #define POSTCARDS_NUM 4 #define POSTCARD_MASK (POSTCARDS_NUM - 1) From 8ac9d5d9cf79f7f2bde419300b9a4687889a57ad Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Apr 2025 17:39:26 +0200 Subject: [PATCH 0693/1190] Default language to system also when the configuration file is present and the language option is not. --- src/config.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config.c b/src/config.c index f38b5aa2c..6f023cf67 100644 --- a/src/config.c +++ b/src/config.c @@ -185,6 +185,8 @@ load_general(void) p = ini_section_get_string(cat, "language", NULL); if (p != NULL) lang_id = plat_language_code(p); + else + lang_id = 0xffff; mouse_sensitivity = ini_section_get_double(cat, "mouse_sensitivity", 1.0); if (mouse_sensitivity < 0.1) From e2f8a58d957ccbb22e59fc48cf98c70c72385650 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 10 Apr 2025 01:08:21 +0200 Subject: [PATCH 0694/1190] Fix the LxS fix on the new recompiler. --- src/codegen_new/codegen_backend_x86-64_uops.c | 5 ++--- src/codegen_new/codegen_backend_x86_uops.c | 5 ++--- src/codegen_new/codegen_ir_defs.h | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 0233a4636..655896b54 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -998,10 +998,9 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) { + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); if (uop->is_a16) { - host_x86_ADD16_REG_IMM(block, REG_SI, uop->imm_data); - } else { - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_AND32_REG_IMM(block, REG_ESI, 0x0000ffff); } } if (REG_IS_B(dest_size)) { diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index beaf85c17..02c441234 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -982,10 +982,9 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) { + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); if (uop->is_a16) { - host_x86_ADD16_REG_IMM(block, REG_SI, uop->imm_data); - } else { - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_AND32_REG_IMM(block, REG_ESI, 0x0000ffff); } } if (REG_IS_B(dest_size)) { diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index ff84c7ccd..d55e57f3d 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -491,13 +491,14 @@ uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); uop->is_a16 = 0; + uop->src_reg_a = codegen_reg_read(src_reg_a); if (src_reg_b == IREG_eaa16) { uop->src_reg_b = codegen_reg_read(IREG_eaaddr); uop->is_a16 = 1; } else uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->is_a16 = 0; uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->imm_data = imm; } From daca37aac926f7de5f11c9eba84730d65596a219 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 10 Apr 2025 23:46:38 +0200 Subject: [PATCH 0695/1190] Media historyy manager: Remove comment and fix the limits. --- src/qt/qt_mediahistorymanager.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_mediahistorymanager.cpp b/src/qt/qt_mediahistorymanager.cpp index d548c0779..5892c55cd 100644 --- a/src/qt/qt_mediahistorymanager.cpp +++ b/src/qt/qt_mediahistorymanager.cpp @@ -101,15 +101,20 @@ MediaHistoryManager::getImageForSlot(int index, int slot, ui::MediaType type) return image_name; } -// These are hardcoded since we can't include the various -// header files where they are defined (e.g., fdd.h, mo.h). -// However, all in ui::MediaType support 4 except cassette. int MediaHistoryManager::maxDevicesSupported(ui::MediaType type) { switch (type) { default: return 4; + case ui::MediaType::Optical: + return CDROM_NUM; + case ui::MediaType::Floppy: + return FDD_NUM; + case ui::MediaType::Zip: + return ZIP_NUM; + case ui::MediaType::Mo: + return MO_NUM; case ui::MediaType::Cassette: return 1; case ui::MediaType::Cartridge: From f41848bbee691d2cd9462bce2355799a7025ff14 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 11 Apr 2025 00:35:28 +0200 Subject: [PATCH 0696/1190] Settings: Recalculate CD-ROM model list on CD-ROM selection change and select the correct CD-ROM type. --- src/qt/qt_settingsfloppycdrom.cpp | 34 +++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index 52d737ae6..5e0ec7bed 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -200,7 +200,7 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { QString name = CDROMName(j); Models::AddEntry(modelType, name, j); - if ((cdrom[cdromIdx].bus_type == bus_type) && (cdrom[cdromIdx].type == j)) + if (cdrom[cdromIdx].type == j) selectedTypeRow = eligibleRows; ++eligibleRows; } @@ -256,9 +256,9 @@ SettingsFloppyCDROM::onFloppyRowChanged(const QModelIndex ¤t) void SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) { - uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); - uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); - int type = current.siblingAtColumn(2).data(Qt::UserRole).toInt(); + uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); + uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); + uint32_t type = current.siblingAtColumn(2).data(Qt::UserRole).toUInt(); ui->comboBoxBus->setCurrentIndex(-1); auto* model = ui->comboBoxBus->model(); @@ -279,7 +279,29 @@ SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) ui->comboBoxSpeed->setEnabled(false); ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1); - ui->comboBoxCDROMType->setCurrentIndex(type); + auto *modelType = ui->comboBoxCDROMType->model(); + int removeRows = modelType->rowCount(); + + uint32_t j = 0; + int selectedTypeRow = 0; + int eligibleRows = 0; + while (cdrom_drive_types[j].bus_type != BUS_TYPE_NONE) { + if (((bus == CDROM_BUS_ATAPI) || (bus == CDROM_BUS_SCSI)) && + ((cdrom_drive_types[j].bus_type == bus) || + (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { + QString name = CDROMName(j); + Models::AddEntry(modelType, name, j); + if (type == j) + selectedTypeRow = eligibleRows; + ++eligibleRows; + } + ++j; + } + modelType->removeRows(0, removeRows); + ui->comboBoxCDROMType->setEnabled(eligibleRows > 1); + ui->comboBoxCDROMType->setCurrentIndex(-1); + ui->comboBoxCDROMType->setCurrentIndex(selectedTypeRow); + enableCurrentlySelectedChannel(); } @@ -371,7 +393,7 @@ SettingsFloppyCDROM::on_comboBoxBus_activated(int) (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { QString name = CDROMName(j); Models::AddEntry(modelType, name, j); - if ((cdrom[cdromIdx].bus_type == bus_type) && (cdrom[cdromIdx].type == j)) + if (cdrom[cdromIdx].type == j) selectedTypeRow = eligibleRows; ++eligibleRows; } From 95a6aa0bdff59dd9352f171644054d178ac66c90 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 11 Apr 2025 19:29:40 +0200 Subject: [PATCH 0697/1190] Fix the LxS fix again. --- src/cpu/386_common.h | 13 ---------- src/cpu/x86_ops_mov_seg.h | 53 ++++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index a4ea5802b..83ef4e72b 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -248,19 +248,6 @@ int checkio(uint32_t port, int mask); return 1; \ } -#define CHECK_READ_2OP(chseg, low, high, low2, high2) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || (low2 < (chseg)->limit_low) || (high2 > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) { \ - x86gpf("Limit check (READ)", 0); \ - return 1; \ - } \ - if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL, (chseg)->seg & 0xfffc); \ - else \ - x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ - return 1; \ - } - #define CHECK_READ_REP(chseg, low, high) \ if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \ x86gpf("Limit check (READ)", 0); \ diff --git a/src/cpu/x86_ops_mov_seg.h b/src/cpu/x86_ops_mov_seg.h index a34bc0c70..f5bd02923 100644 --- a/src/cpu/x86_ops_mov_seg.h +++ b/src/cpu/x86_ops_mov_seg.h @@ -272,10 +272,13 @@ opLDS_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, - ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); addr = readmemw(easeg, cpu_state.eaa16[0]); - seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); + if (cpu_state.abrt) + return 1; + cpu_state.eaa16[0] += 2; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); + seg = readmemw(easeg, cpu_state.eaa16[0]); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ds); @@ -319,10 +322,13 @@ opLDS_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, - ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 3) & 0xffff)); addr = readmeml(easeg, cpu_state.eaa16[0]); - seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); + if (cpu_state.abrt) + return 1; + cpu_state.eaa16[0] += 4; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); + seg = readmemw(easeg, cpu_state.eaa16[0]); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ds); @@ -367,10 +373,13 @@ opLSS_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, - ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); addr = readmemw(easeg, cpu_state.eaa16[0]); - seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); + if (cpu_state.abrt) + return 1; + cpu_state.eaa16[0] += 2; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); + seg = readmemw(easeg, cpu_state.eaa16[0]); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ss); @@ -414,11 +423,13 @@ opLSS_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, - ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 5) & 0xffff)); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 3) & 0xffff)); addr = readmeml(easeg, cpu_state.eaa16[0]); - seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); + if (cpu_state.abrt) + return 1; + cpu_state.eaa16[0] += 4; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); + seg = readmemw(easeg, cpu_state.eaa16[0]); if (cpu_state.abrt) return 1; op_loadseg(seg, &cpu_state.seg_ss); @@ -462,9 +473,13 @@ opLSS_l_a32(uint32_t fetchdat) fetch_ea_16(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); \ addr = readmemw(easeg, cpu_state.eaa16[0]); \ - seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.eaa16[0] += 2; \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); \ + seg = readmemw(easeg, cpu_state.eaa16[0]); \ if (cpu_state.abrt) \ return 1; \ op_loadseg(seg, &sel); \ @@ -507,9 +522,13 @@ opLSS_l_a32(uint32_t fetchdat) fetch_ea_16(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 3) & 0xffff)); \ addr = readmeml(easeg, cpu_state.eaa16[0]); \ - seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.eaa16[0] += 4; \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); \ + seg = readmemw(easeg, cpu_state.eaa16[0]); \ if (cpu_state.abrt) \ return 1; \ op_loadseg(seg, &sel); \ From e21c86d46cbd243fe68f909c94488d6e4c5e0cda Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 11 Apr 2025 19:58:30 +0200 Subject: [PATCH 0698/1190] PCI TRC Reset: Only zero the RAM on 686 systems, fixes #5462. --- src/acpi.c | 4 +--- src/pci.c | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 963f26ae6..ccd51ebca 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1025,10 +1025,8 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p nvr_reg_write(0x000f, 0xff, dev->nvr); } - if (sus_typ & SUS_RESET_PCI) { + if (sus_typ & SUS_RESET_PCI) device_reset_all(DEVICE_PCI); - mem_zero(); - } if (sus_typ & SUS_RESET_CPU) cpu_alt_reset = 0; diff --git a/src/pci.c b/src/pci.c index c2e4ca237..c3020ca73 100644 --- a/src/pci.c +++ b/src/pci.c @@ -420,7 +420,8 @@ pci_trc_reset(uint8_t val) flushmmucache(); - mem_zero(); + if (is_p6) + mem_zero(); } #ifdef USE_DYNAREC From 8aa15fa21fd70ac01bcacfb12d69e9e01ba00edb Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 11 Apr 2025 20:27:41 +0200 Subject: [PATCH 0699/1190] The update value handler should be at Pentium Pro, not Cyrix Cx6x86. --- src/cpu/cpu.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index ffe582604..d13dfe041 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2448,11 +2448,6 @@ cpu_CPUID(void) EAX = CPUID; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; - /* - Return anything non-zero in bits 32-63 of the BIOS signature MSR - to indicate there has been an update. - */ - msr.bbl_cr_dx[3] = 0xffffffff00000000ULL; } else EAX = EBX = ECX = EDX = 0; break; @@ -2467,6 +2462,11 @@ cpu_CPUID(void) EAX = CPUID; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; + /* + Return anything non-zero in bits 32-63 of the BIOS signature MSR + to indicate there has been an update. + */ + msr.bbl_cr_dx[3] = 0xffffffff00000000ULL; } else if (EAX == 2) { EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries @@ -3301,7 +3301,6 @@ pentium_invalid_rdmsr: case 0x88 ... 0x8b: EAX = msr.bbl_cr_dx[ECX - 0x88] & 0xffffffff; EDX = msr.bbl_cr_dx[ECX - 0x88] >> 32; - // EDX |= 0xffffffff; break; /* Unknown */ case 0xae: From 9b11091c8e282336dc8f9ac81355f81565ff0b48 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 7 Apr 2025 15:58:44 +0500 Subject: [PATCH 0700/1190] qt: Remove the keyboard shortcut translation hack No longer needed since the Win32 UI is gone and Qt can handle the key names since the base translations are embedded --- src/qt/languages/86box.pot | 10 +++++----- src/qt/languages/ca-ES.po | 20 ++++++++++---------- src/qt/languages/cs-CZ.po | 20 ++++++++++---------- src/qt/languages/de-DE.po | 20 ++++++++++---------- src/qt/languages/es-ES.po | 20 ++++++++++---------- src/qt/languages/fi-FI.po | 20 ++++++++++---------- src/qt/languages/fr-FR.po | 20 ++++++++++---------- src/qt/languages/hr-HR.po | 20 ++++++++++---------- src/qt/languages/hu-HU.po | 20 ++++++++++---------- src/qt/languages/it-IT.po | 20 ++++++++++---------- src/qt/languages/ja-JP.po | 20 ++++++++++---------- src/qt/languages/ko-KR.po | 20 ++++++++++---------- src/qt/languages/nl-NL.po | 20 ++++++++++---------- src/qt/languages/pl-PL.po | 20 ++++++++++---------- src/qt/languages/pt-BR.po | 20 ++++++++++---------- src/qt/languages/pt-PT.po | 20 ++++++++++---------- src/qt/languages/ru-RU.po | 20 ++++++++++---------- src/qt/languages/sk-SK.po | 20 ++++++++++---------- src/qt/languages/sl-SI.po | 20 ++++++++++---------- src/qt/languages/tr-TR.po | 20 ++++++++++---------- src/qt/languages/uk-UA.po | 20 ++++++++++---------- src/qt/languages/vi-VN.po | 20 ++++++++++---------- src/qt/languages/zh-CN.po | 20 ++++++++++---------- src/qt/languages/zh-TW.po | 20 ++++++++++---------- src/qt/qt_progsettings.hpp | 17 +---------------- 25 files changed, 236 insertions(+), 251 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 93a47a1cb..6e610d715 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -18,7 +18,7 @@ msgstr "" msgid "&Hard Reset..." msgstr "" -msgid "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" msgstr "" msgid "Ctrl+Alt+&Esc" @@ -111,7 +111,7 @@ msgstr "" msgid "Hi&DPI scaling" msgstr "" -msgid "&Fullscreen\tCtrl+Alt+PgUp" +msgid "&Fullscreen" msgstr "" msgid "Fullscreen &stretch mode" @@ -186,7 +186,7 @@ msgstr "" msgid "&Update status bar icons" msgstr "" -msgid "Take s&creenshot\tCtrl+F11" +msgid "Take s&creenshot" msgstr "" msgid "&Preferences..." @@ -198,10 +198,10 @@ msgstr "" msgid "Sound &gain..." msgstr "" -msgid "Begin trace\tCtrl+T" +msgid "Begin trace" msgstr "" -msgid "End trace\tCtrl+T" +msgid "End trace" msgstr "" msgid "&Help" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index cf3d5c7f7..8c89c6bad 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -18,8 +18,8 @@ msgstr "CTRL &dret és ALT esquerre" msgid "&Hard Reset..." msgstr "&Reinicialització completa ..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineal" msgid "Hi&DPI scaling" msgstr "&Escalat alta densitat" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Pantalla completa\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Pantalla completa" msgid "Fullscreen &stretch mode" msgstr "Escalat pantalla completa" @@ -186,8 +186,8 @@ msgstr "&Ajustaments ..." msgid "&Update status bar icons" msgstr "&Actualitzar icones a la barra d'estat" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Prendre c&aptura\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Prendre c&aptura" msgid "&Preferences..." msgstr "&Preferències ..." @@ -198,11 +198,11 @@ msgstr "Activar la integració amb el &Discord" msgid "Sound &gain..." msgstr "&Guany de so ..." -msgid "Begin trace\tCtrl+T" -msgstr "Començar traça\tCtrl+T" +msgid "Begin trace" +msgstr "Començar traça" -msgid "End trace\tCtrl+T" -msgstr "Acabar traça\tCtrl+T" +msgid "End trace" +msgstr "Acabar traça" msgid "&Help" msgstr "&Ajuda" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index e3d85dd09..2a26f7ef6 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -18,8 +18,8 @@ msgstr "&Pravý Ctrl je levý Alt" msgid "&Hard Reset..." msgstr "&Resetovat" -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineární" msgid "Hi&DPI scaling" msgstr "Š&kálování HiDPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Celá obrazovka\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Celá obrazovka" msgid "Fullscreen &stretch mode" msgstr "Režím roztá&hnutí při celé obrazovce" @@ -186,8 +186,8 @@ msgstr "&Nastavení..." msgid "&Update status bar icons" msgstr "&Aktualizovat ikony stavového řádku" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Pořídit &screenshot\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Pořídit &screenshot" msgid "&Preferences..." msgstr "&Předvolby..." @@ -198,11 +198,11 @@ msgstr "Povolit integraci s &Discordem" msgid "Sound &gain..." msgstr "&Zesílení zvuku" -msgid "Begin trace\tCtrl+T" -msgstr "Začít trace\tCtrl+T" +msgid "Begin trace" +msgstr "Začít trace" -msgid "End trace\tCtrl+T" -msgstr "Zastavit trace\tCtrl+T" +msgid "End trace" +msgstr "Zastavit trace" msgid "&Help" msgstr "Ná&pověda" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index c904cad0d..fbb97a990 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -18,8 +18,8 @@ msgstr "&Die rechte Strg-Taste ist die Linke Alt-Taste" msgid "&Hard Reset..." msgstr "&Kaltstart..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Strg+Alt+Entf\tStrg+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Strg+Alt+Entf" msgid "Ctrl+Alt+&Esc" msgstr "Strg+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Linear" msgid "Hi&DPI scaling" msgstr "Hi&DPI-Skalierung" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Vollbild\tStrg+Alt+Bild auf" +msgid "&Fullscreen" +msgstr "&Vollbild" msgid "Fullscreen &stretch mode" msgstr "&Vollbild-Skalierungsmodus" @@ -186,8 +186,8 @@ msgstr "&Optionen..." msgid "&Update status bar icons" msgstr "&Statusleistenicons aktualisieren" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "S&creenshot aufnehmen\tStrg+F11" +msgid "Take s&creenshot" +msgstr "S&creenshot aufnehmen" msgid "&Preferences..." msgstr "&Einstellungen..." @@ -198,11 +198,11 @@ msgstr "&Discord-Integration einschalten" msgid "Sound &gain..." msgstr "&Klangverstärkung..." -msgid "Begin trace\tCtrl+T" -msgstr "Tracing starten\tStrg+T" +msgid "Begin trace" +msgstr "Tracing starten" -msgid "End trace\tCtrl+T" -msgstr "Tracing beenden\tStrg+T" +msgid "End trace" +msgstr "Tracing beenden" msgid "&Help" msgstr "&Hilfe" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index ca7a3ad53..1a5550065 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -18,8 +18,8 @@ msgstr "CTRL &derecho es ALT izquierdo" msgid "&Hard Reset..." msgstr "&Hard Reset..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineal" msgid "Hi&DPI scaling" msgstr "&Escalado alta densidad" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Pantalla completa\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Pantalla completa" msgid "Fullscreen &stretch mode" msgstr "Escalado pantalla completa" @@ -186,8 +186,8 @@ msgstr "&Configuraciones..." msgid "&Update status bar icons" msgstr "&Actualizar iconos en barra de estado" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Tomar c&aptura\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Tomar c&aptura" msgid "&Preferences..." msgstr "&Preferencias..." @@ -198,11 +198,11 @@ msgstr "Habilitar integración con &Discord" msgid "Sound &gain..." msgstr "&Ganancia de sonido..." -msgid "Begin trace\tCtrl+T" -msgstr "Comenzar traza\tCtrl+T" +msgid "Begin trace" +msgstr "Comenzar traza" -msgid "End trace\tCtrl+T" -msgstr "Terminar traza\tCtrl+T" +msgid "End trace" +msgstr "Terminar traza" msgid "&Help" msgstr "&Ayuda" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index f044365f0..5222ccc45 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -18,8 +18,8 @@ msgstr "&Oikea CTRL on vasen ALT" msgid "&Hard Reset..." msgstr "&Uudelleenkäynnistys (kylmä)..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "Li&neaarinen interpolaatio" msgid "Hi&DPI scaling" msgstr "&Suuri DPI-skaalaus" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Koko näytön tila\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Koko näytön tila" msgid "Fullscreen &stretch mode" msgstr "Koko näytön &skaalaustila" @@ -186,8 +186,8 @@ msgstr "&Kokoonpano..." msgid "&Update status bar icons" msgstr "&Päivitä tilapalkin kuvakkeita" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Ota &kuvakaappaus\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Ota &kuvakaappaus" msgid "&Preferences..." msgstr "&Sovellusasetukset..." @@ -198,11 +198,11 @@ msgstr "Käytä &Discord-integraatiota" msgid "Sound &gain..." msgstr "&Äänitasot..." -msgid "Begin trace\tCtrl+T" -msgstr "Aloita jäljitys\tCtrl+T" +msgid "Begin trace" +msgstr "Aloita jäljitys" -msgid "End trace\tCtrl+T" -msgstr "Lopeta jäljitys\tCtrl+T" +msgid "End trace" +msgstr "Lopeta jäljitys" msgid "&Help" msgstr "&Ohje" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 590674a29..9937cecd4 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -18,8 +18,8 @@ msgstr "CTRL &Droite devient ALT Gauche" msgid "&Hard Reset..." msgstr "&Hard Reset..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineaire" msgid "Hi&DPI scaling" msgstr "Mise à l'échelle Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Plein Ecran\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Plein Ecran" msgid "Fullscreen &stretch mode" msgstr "Mode &Elargi plein écran" @@ -186,8 +186,8 @@ msgstr "&Réglages..." msgid "&Update status bar icons" msgstr "Mettre à jour la barre de stat&us" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Copie &Ecran\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Copie &Ecran" msgid "&Preferences..." msgstr "&Préférences..." @@ -198,11 +198,11 @@ msgstr "Activer intégration &Discord" msgid "Sound &gain..." msgstr "&Gain Son..." -msgid "Begin trace\tCtrl+T" -msgstr "Démarrer traces\tCtrl+T" +msgid "Begin trace" +msgstr "Démarrer traces" -msgid "End trace\tCtrl+T" -msgstr "Finir traces\tCtrl+T" +msgid "End trace" +msgstr "Finir traces" msgid "&Help" msgstr "&Aide" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index ed4fdf621..7a8aa53e4 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -18,8 +18,8 @@ msgstr "&Desni CTRL je lijevi ALT" msgid "&Hard Reset..." msgstr "&Ponovno pokretanje..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Linearna" msgid "Hi&DPI scaling" msgstr "&HiDPI skaliranje" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Cijelozaslonski način\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Cijelozaslonski način" msgid "Fullscreen &stretch mode" msgstr "&Način cijelozaslonskog rastezanja" @@ -186,8 +186,8 @@ msgstr "&Opcije..." msgid "&Update status bar icons" msgstr "&Ažuriraj ikone statusnog redka" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Napravi &snimku zaslona\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Napravi &snimku zaslona" msgid "&Preferences..." msgstr "&Postavke..." @@ -198,11 +198,11 @@ msgstr "Omogući integraciju sa programom &Discord" msgid "Sound &gain..." msgstr "&Pojačavanje zvuka..." -msgid "Begin trace\tCtrl+T" -msgstr "Z&apočni praćenje\tCtrl+T" +msgid "Begin trace" +msgstr "Z&apočni praćenje" -msgid "End trace\tCtrl+T" -msgstr "&Svrši praćenje\tCtrl+T" +msgid "End trace" +msgstr "&Svrši praćenje" msgid "&Help" msgstr "&Pomoć" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index b4afd8010..c777c6dd7 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -18,8 +18,8 @@ msgstr "A &jobb oldali CTRL a bal ALT" msgid "&Hard Reset..." msgstr "Hardveres &újraindítás..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineáris" msgid "Hi&DPI scaling" msgstr "Hi&DPI méretezés" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Teljes képernyő\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Teljes képernyő" msgid "Fullscreen &stretch mode" msgstr "Teljes képernyős &méretezés" @@ -186,8 +186,8 @@ msgstr "&Konfigurálás..." msgid "&Update status bar icons" msgstr "Állapotsori ikonok &frissítése" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "&Képernyőkép készítése\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "&Képernyőkép készítése" msgid "&Preferences..." msgstr "&Beállítások..." @@ -198,11 +198,11 @@ msgstr "&Discord integráció engedélyezése" msgid "Sound &gain..." msgstr "&Hangerőszabályzó..." -msgid "Begin trace\tCtrl+T" -msgstr "Nyomkövetés megkezdése\tCtrl+T" +msgid "Begin trace" +msgstr "Nyomkövetés megkezdése" -msgid "End trace\tCtrl+T" -msgstr "Nyomkövetés befejezése\tCtrl+T" +msgid "End trace" +msgstr "Nyomkövetés befejezése" msgid "&Help" msgstr "&Súgó" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 73ec57ec0..adf5b0471 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -18,8 +18,8 @@ msgstr "&CTRL destro è ALT sinistro" msgid "&Hard Reset..." msgstr "&Riavvia..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineare" msgid "Hi&DPI scaling" msgstr "Scala Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Schermo intero\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Schermo intero" msgid "Fullscreen &stretch mode" msgstr "Modalità adattamento &schermo intero" @@ -186,8 +186,8 @@ msgstr "&Impostazioni..." msgid "&Update status bar icons" msgstr "&Aggiorna icone della barra di stato" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Cattura schermata\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Cattura schermata" msgid "&Preferences..." msgstr "&Preferenze..." @@ -198,11 +198,11 @@ msgstr "Abilita &integrazione Discord" msgid "Sound &gain..." msgstr "Guadagno &suono..." -msgid "Begin trace\tCtrl+T" -msgstr "Inizia traccia\tCtrl+T" +msgid "Begin trace" +msgstr "Inizia traccia" -msgid "End trace\tCtrl+T" -msgstr "Ferma traccia\tCtrl+T" +msgid "End trace" +msgstr "Ferma traccia" msgid "&Help" msgstr "&?" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 6132a8db1..d51be2536 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -18,8 +18,8 @@ msgstr "右CTRLを左ALTへ変換(&R)" msgid "&Hard Reset..." msgstr "ハード リセット(&H)..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "Ctrl+Alt+Del(&C)\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del(&C)" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+Esc(&E)" @@ -111,8 +111,8 @@ msgstr "線形補間(&L)" msgid "Hi&DPI scaling" msgstr "HiDPIスケーリング(&D)" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "全画面表示(&F)\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "全画面表示(&F)" msgid "Fullscreen &stretch mode" msgstr "全画面の拡大表示モード(&S)" @@ -186,8 +186,8 @@ msgstr "設定(&S)..." msgid "&Update status bar icons" msgstr "ステータスバーのアイコンを更新(&U)" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "スクリーンショットを撮る(&C)\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "スクリーンショットを撮る(&C)" msgid "&Preferences..." msgstr "環境設定(&P)..." @@ -198,11 +198,11 @@ msgstr "Discord連携機能(&D)" msgid "Sound &gain..." msgstr "音量調整(&G)..." -msgid "Begin trace\tCtrl+T" -msgstr "トレース開始\tCtrl+T" +msgid "Begin trace" +msgstr "トレース開始" -msgid "End trace\tCtrl+T" -msgstr "トレース終了\tCtrl+T" +msgid "End trace" +msgstr "トレース終了" msgid "&Help" msgstr "ヘルプ(&H)" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index ec4b20d0d..859183fc1 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -18,8 +18,8 @@ msgstr "우측CTRL로 좌측ALT 입력(&R)" msgid "&Hard Reset..." msgstr "재시작(&H)..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "Ctrl+Alt+Del(&C)\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del(&C)" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+Esc(&E)" @@ -111,8 +111,8 @@ msgstr "선형 보간법(&L)" msgid "Hi&DPI scaling" msgstr "HiDPI 스케일링(&D)" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "전체 화면(&F)\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "전체 화면(&F)" msgid "Fullscreen &stretch mode" msgstr "전체 화면 비율(&S)" @@ -186,8 +186,8 @@ msgstr "설정(&S)..." msgid "&Update status bar icons" msgstr "상태 바 아이콘 갱신하기(&U)" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "스크린샷 찍기(&C)\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "스크린샷 찍기(&C)" msgid "&Preferences..." msgstr "환경설정(&P)..." @@ -198,11 +198,11 @@ msgstr "디스코드 연동 활성화하기(&D)" msgid "Sound &gain..." msgstr "음량 증폭(&G)..." -msgid "Begin trace\tCtrl+T" -msgstr "추적 시작하기\tCtrl+T" +msgid "Begin trace" +msgstr "추적 시작하기" -msgid "End trace\tCtrl+T" -msgstr "추적 끝내기\tCtrl+T" +msgid "End trace" +msgstr "추적 끝내기" msgid "&Help" msgstr "도움말(&H)" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index c601197ac..cce4dfdc9 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -18,8 +18,8 @@ msgstr "&Rechtse CTRL is linkse ALT" msgid "&Hard Reset..." msgstr "&Harde Reset..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineair" msgid "Hi&DPI scaling" msgstr "Hi&DPI-schaling" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Fullscreen\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Fullscreen" msgid "Fullscreen &stretch mode" msgstr "Volledig scherm &uitrekmodus" @@ -186,8 +186,8 @@ msgstr "&Instellingen..." msgid "&Update status bar icons" msgstr "&Statusbalkpictogrammen bijwerken" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Maak een schermafbeelding\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Maak een schermafbeelding" msgid "&Preferences..." msgstr "&Voorkeuren..." @@ -198,11 +198,11 @@ msgstr "&Discord integratie inschakelen" msgid "Sound &gain..." msgstr "&Geluidsversterking..." -msgid "Begin trace\tCtrl+T" -msgstr "Begin traceren\tCtrl+T" +msgid "Begin trace" +msgstr "Begin traceren" -msgid "End trace\tCtrl+T" -msgstr "Traceren beëindigen\tCtrl+T" +msgid "End trace" +msgstr "Traceren beëindigen" msgid "&Help" msgstr "&Help" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 78ded239f..26cc4bae6 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -18,8 +18,8 @@ msgstr "&Prawy CTRL to lewy Alt" msgid "&Hard Reset..." msgstr "&Twardy reset..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Linear" msgid "Hi&DPI scaling" msgstr "Skalowanie Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Pełny ekran\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Pełny ekran" msgid "Fullscreen &stretch mode" msgstr "Tryb rozciągania na pełnym ekranie" @@ -186,8 +186,8 @@ msgstr "&Ustawienia..." msgid "&Update status bar icons" msgstr "&Aktualizuj ikony na pasku statusu" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Zrób &zrzut ekranu\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Zrób &zrzut ekranu" msgid "&Preferences..." msgstr "&Preferencje..." @@ -198,11 +198,11 @@ msgstr "Włącz integrację z &Discord" msgid "Sound &gain..." msgstr "Wzmocnienie &dźwięku..." -msgid "Begin trace\tCtrl+T" -msgstr "Rozpocznij śledzenie\tCtrl+T" +msgid "Begin trace" +msgstr "Rozpocznij śledzenie" -msgid "End trace\tCtrl+T" -msgstr "Zakończ śledzenie\tCtrl+T" +msgid "End trace" +msgstr "Zakończ śledzenie" msgid "&Help" msgstr "&Pomoc" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 1594e30ab..b453d0f97 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -18,8 +18,8 @@ msgstr "&CTRL direito é o ALT esquerdo" msgid "&Hard Reset..." msgstr "&Reinicialização completa..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Linear" msgid "Hi&DPI scaling" msgstr "Escala Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Tela cheia\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Tela cheia" msgid "Fullscreen &stretch mode" msgstr "Modo de &redimensionamento da tela cheia" @@ -186,8 +186,8 @@ msgstr "&Configurações..." msgid "&Update status bar icons" msgstr "&Atualizar ícones da barra de status" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Capturar &tela\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Capturar &tela" msgid "&Preferences..." msgstr "&Preferências..." @@ -198,11 +198,11 @@ msgstr "Ativar integração com o &Discord" msgid "Sound &gain..." msgstr "&Ganho de som..." -msgid "Begin trace\tCtrl+T" -msgstr "Inicio do rastreamento\tCtrl+T" +msgid "Begin trace" +msgstr "Inicio do rastreamento" -msgid "End trace\tCtrl+T" -msgstr "Finalizar rastreamento\tCtrl+T" +msgid "End trace" +msgstr "Finalizar rastreamento" msgid "&Help" msgstr "&Ajuda" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index b31f020d4..d732532ed 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -18,8 +18,8 @@ msgstr "&CTRL direito é ALT esquerdo" msgid "&Hard Reset..." msgstr "&Reinicialização completa..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Linear" msgid "Hi&DPI scaling" msgstr "Escala Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "E&crã cheio\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "E&crã cheio" msgid "Fullscreen &stretch mode" msgstr "Modo &de estiramento na tela cheia" @@ -186,8 +186,8 @@ msgstr "&Definições..." msgid "&Update status bar icons" msgstr "&Atualizar ícones da barra de estado" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Gravar imagem de ecrã\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Gravar imagem de ecrã" msgid "&Preferences..." msgstr "&Preferências..." @@ -198,11 +198,11 @@ msgstr "Ativar integração com &Discord" msgid "Sound &gain..." msgstr "&Ganho de som..." -msgid "Begin trace\tCtrl+T" -msgstr "Iniciar o rastreio\tCtrl+T" +msgid "Begin trace" +msgstr "Iniciar o rastreio" -msgid "End trace\tCtrl+T" -msgstr "Terminar o rastreio\tCtrl+T" +msgid "End trace" +msgstr "Terminar o rastreio" msgid "&Help" msgstr "&Ajuda" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a8a4b7794..e68e6bb10 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -18,8 +18,8 @@ msgstr "&Правый CTRL - это левый ALT" msgid "&Hard Reset..." msgstr "&Холодная перезагрузка..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Линейный" msgid "Hi&DPI scaling" msgstr "Масштабирование Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Полноэкранный режим\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Полноэкранный режим" msgid "Fullscreen &stretch mode" msgstr "&Растягивание в полноэкранном режиме" @@ -186,8 +186,8 @@ msgstr "&Настройки машины..." msgid "&Update status bar icons" msgstr "&Обновление значков строки состояния" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Сделать с&криншот\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Сделать с&криншот" msgid "&Preferences..." msgstr "&Параметры..." @@ -198,11 +198,11 @@ msgstr "Включить интеграцию &Discord" msgid "Sound &gain..." msgstr "&Усиление звука..." -msgid "Begin trace\tCtrl+T" -msgstr "Начать трассировку\tCtrl+T" +msgid "Begin trace" +msgstr "Начать трассировку" -msgid "End trace\tCtrl+T" -msgstr "Завершить трассировку\tCtrl+T" +msgid "End trace" +msgstr "Завершить трассировку" msgid "&Help" msgstr "&Помощь" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index e789d9ef9..c091780c2 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -18,8 +18,8 @@ msgstr "&Pravý Ctrl je ľavý Alt" msgid "&Hard Reset..." msgstr "&Resetovať" -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Lineárny" msgid "Hi&DPI scaling" msgstr "Š&kálovanie HiDPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Celá obrazovka\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Celá obrazovka" msgid "Fullscreen &stretch mode" msgstr "Režim roztia&hnutia na celú obrazovku" @@ -186,8 +186,8 @@ msgstr "&Nastavenia..." msgid "&Update status bar icons" msgstr "&Aktualizovať ikony na stavovom riadku" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Urobiť snímku &obrazovky\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Urobiť snímku &obrazovky" msgid "&Preferences..." msgstr "&Predvoľby..." @@ -198,11 +198,11 @@ msgstr "Povolenie integrácie s &Discordem" msgid "Sound &gain..." msgstr "&Zosilnenie zvuku" -msgid "Begin trace\tCtrl+T" -msgstr "Začať trace\tCtrl+T" +msgid "Begin trace" +msgstr "Začať trace" -msgid "End trace\tCtrl+T" -msgstr "Zastaviť trace\tCtrl+T" +msgid "End trace" +msgstr "Zastaviť trace" msgid "&Help" msgstr "&Pomoc" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 1394a3635..15041a4aa 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -18,8 +18,8 @@ msgstr "&Desni CTRL je levi ALT" msgid "&Hard Reset..." msgstr "&Ponovni zagon..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Linearna" msgid "Hi&DPI scaling" msgstr "&Raztezanje za visok DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Celozaslonski način\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Celozaslonski način" msgid "Fullscreen &stretch mode" msgstr "&Način celozaslonskega raztezanja" @@ -186,8 +186,8 @@ msgstr "&Nastavitve..." msgid "&Update status bar icons" msgstr "&Posodabljaj ikone statusne vrstice" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "&Zajemi posnetek zaslona\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "&Zajemi posnetek zaslona" msgid "&Preferences..." msgstr "&Možnosti..." @@ -198,11 +198,11 @@ msgstr "Omogoči integracijo s programom &Discord" msgid "Sound &gain..." msgstr "&Ojačanje zvoka..." -msgid "Begin trace\tCtrl+T" -msgstr "Z&ačni sledenje\tCtrl+T" +msgid "Begin trace" +msgstr "Z&ačni sledenje" -msgid "End trace\tCtrl+T" -msgstr "&Končaj sledenje\tCtrl+T" +msgid "End trace" +msgstr "&Končaj sledenje" msgid "&Help" msgstr "&Pomoč" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 81866b3ce..c16cc12e4 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -18,8 +18,8 @@ msgstr "&Sağ CTRL tuşunu sol ALT tuşu olarak ayarla" msgid "&Hard Reset..." msgstr "Yeniden başlamaya &zorla" -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+&Alt+Esc" @@ -111,8 +111,8 @@ msgstr "Doğ&rusal" msgid "Hi&DPI scaling" msgstr "HiDPI ölçekle&mesi" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "Tam ekran\tCtrl+Alt+Pg&Up" +msgid "&Fullscreen" +msgstr "Tam ekran" msgid "Fullscreen &stretch mode" msgstr "Tam e&kran germe modu" @@ -186,8 +186,8 @@ msgstr "&Ayarlar..." msgid "&Update status bar icons" msgstr "Durum &çubuğu simgelerini güncelle" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "&Ekran görüntüsü al\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "&Ekran görüntüsü al" msgid "&Preferences..." msgstr "&Tercihler..." @@ -198,11 +198,11 @@ msgstr "&Discord entegrasyonunu etkinleştir" msgid "Sound &gain..." msgstr "&Ses düzeyi artışı..." -msgid "Begin trace\tCtrl+T" -msgstr "İzlemeyi başlat\tCtrl+T" +msgid "Begin trace" +msgstr "İzlemeyi başlat" -msgid "End trace\tCtrl+T" -msgstr "İzlemeyi bitir\tCtrl+T" +msgid "End trace" +msgstr "İzlemeyi bitir" msgid "&Help" msgstr "&Yardım" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 9b57ac03e..bde9a4f51 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -18,8 +18,8 @@ msgstr "&Правий CTRL - це лівий ALT" msgid "&Hard Reset..." msgstr "&Холодне перезавантаження..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "&Лінійний" msgid "Hi&DPI scaling" msgstr "Масштабування Hi&DPI" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Повноекранний режим\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "&Повноекранний режим" msgid "Fullscreen &stretch mode" msgstr "&Розстягування у повноекранному режимі" @@ -186,8 +186,8 @@ msgstr "&Налаштування машини..." msgid "&Update status bar icons" msgstr "&Обновлення значків рядка стану" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Зробити &знімок\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Зробити &знімок" msgid "&Preferences..." msgstr "&Параметри..." @@ -198,11 +198,11 @@ msgstr "Увімкнути інтеграцію &Discord" msgid "Sound &gain..." msgstr "&Посилення звуку..." -msgid "Begin trace\tCtrl+T" -msgstr "Почати трасування\tCtrl+T" +msgid "Begin trace" +msgstr "Почати трасування" -msgid "End trace\tCtrl+T" -msgstr "Завершити трасування\tCtrl+T" +msgid "End trace" +msgstr "Завершити трасування" msgid "&Help" msgstr "&Допомога" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index abf9a1dea..fa9384d8f 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -18,8 +18,8 @@ msgstr "Gắn ALT trái vào CTRL ph&ải" msgid "&Hard Reset..." msgstr "Buộc khởi độn&g lại" -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" @@ -111,8 +111,8 @@ msgstr "Tu&yến tính" msgid "Hi&DPI scaling" msgstr "Tỷ lệ hinh ảnh phân giải cao" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "Toàn màn &hình\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "Toàn màn &hình" msgid "Fullscreen &stretch mode" msgstr "&Chế độ kéo giãn hình" @@ -186,8 +186,8 @@ msgstr "&Cài đặt..." msgid "&Update status bar icons" msgstr "Cậ&p nhật biểu tượng thanh trạng thái" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Chụp &màn hình\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "Chụp &màn hình" msgid "&Preferences..." msgstr "&Tùy biến..." @@ -198,11 +198,11 @@ msgstr "Bật trình trạng thái cho Discord" msgid "Sound &gain..." msgstr "Bộ &tăng âm..." -msgid "Begin trace\tCtrl+T" -msgstr "Bắt đầu dò\tCtrl+T" +msgid "Begin trace" +msgstr "Bắt đầu dò" -msgid "End trace\tCtrl+T" -msgstr "Ngưng dò\tCtrl+T" +msgid "End trace" +msgstr "Ngưng dò" msgid "&Help" msgstr "&Trợ giúp" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index ec5d2c252..4cccc071a 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -18,8 +18,8 @@ msgstr "将右 CTRL 键映射为左 ALT 键(&R)" msgid "&Hard Reset..." msgstr "硬重置(&H)..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "Ctrl+Alt+Del(&C)\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del(&C)" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+Esc(&E)" @@ -111,8 +111,8 @@ msgstr "线性(&L)" msgid "Hi&DPI scaling" msgstr "HiDPI 缩放(&D)" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "全屏(&F)\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "全屏(&F)" msgid "Fullscreen &stretch mode" msgstr "全屏拉伸模式(&S)" @@ -186,8 +186,8 @@ msgstr "设置(&S)..." msgid "&Update status bar icons" msgstr "更新状态栏图标(&U)" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "截图(&C)\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "截图(&C)" msgid "&Preferences..." msgstr "首选项(&P)..." @@ -198,11 +198,11 @@ msgstr "启用 Discord 集成(&D)" msgid "Sound &gain..." msgstr "音量增益(&G)..." -msgid "Begin trace\tCtrl+T" -msgstr "开始追踪\tCtrl+T" +msgid "Begin trace" +msgstr "开始追踪" -msgid "End trace\tCtrl+T" -msgstr "结束追踪\tCtrl+T" +msgid "End trace" +msgstr "结束追踪" msgid "&Help" msgstr "帮助(&H)" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index b0d8163cb..92c6502ea 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -18,8 +18,8 @@ msgstr "將右 CTRL 鍵映射為左 ALT 鍵(&R)" msgid "&Hard Reset..." msgstr "硬重設(&H)..." -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "Ctrl+Alt+Del(&C)\tCtrl+F12" +msgid "&Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del(&C)" msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+Esc(&E)" @@ -111,8 +111,8 @@ msgstr "線性(&L)" msgid "Hi&DPI scaling" msgstr "HiDPI 縮放(&D)" -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "全螢幕(&F)\tCtrl+Alt+PgUp" +msgid "&Fullscreen" +msgstr "全螢幕(&F)" msgid "Fullscreen &stretch mode" msgstr "全螢幕拉伸模式(&S)" @@ -186,8 +186,8 @@ msgstr "設定(&S)..." msgid "&Update status bar icons" msgstr "更新狀態列圖示(&U)" -msgid "Take s&creenshot\tCtrl+F11" -msgstr "擷圖(&C)\tCtrl+F11" +msgid "Take s&creenshot" +msgstr "擷圖(&C)" msgid "&Preferences..." msgstr "偏好設定(&P)..." @@ -198,11 +198,11 @@ msgstr "啟用 Discord 整合(&D)" msgid "Sound &gain..." msgstr "音量增益(&G)..." -msgid "Begin trace\tCtrl+T" -msgstr "開始追踪\tCtrl+T" +msgid "Begin trace" +msgstr "開始追踪" -msgid "End trace\tCtrl+T" -msgstr "結束追踪\tCtrl+T" +msgid "End trace" +msgstr "結束追踪" msgid "&Help" msgstr "說明(&H)" diff --git a/src/qt/qt_progsettings.hpp b/src/qt/qt_progsettings.hpp index b4e59e02d..1c7295f56 100644 --- a/src/qt/qt_progsettings.hpp +++ b/src/qt/qt_progsettings.hpp @@ -28,22 +28,7 @@ public: QString translate(const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1) const override { - if (strcmp(sourceText, "&Fullscreen") == 0) - sourceText = "&Fullscreen\tCtrl+Alt+PgUp"; - if (strcmp(sourceText, "&Ctrl+Alt+Del") == 0) - sourceText = "&Ctrl+Alt+Del\tCtrl+F12"; - if (strcmp(sourceText, "Take s&creenshot") == 0) - sourceText = "Take s&creenshot\tCtrl+F11"; - if (strcmp(sourceText, "Begin trace") == 0) - sourceText = "Begin trace\tCtrl+T"; - if (strcmp(sourceText, "End trace") == 0) - sourceText = "End trace\tCtrl+T"; - QString finalstr = QTranslator::translate("", sourceText, disambiguation, n); -#ifdef Q_OS_MACOS - if (finalstr.contains('\t')) - finalstr.truncate(finalstr.indexOf('\t')); -#endif - return finalstr; + return QTranslator::translate("", sourceText, disambiguation, n); } }; static CustomTranslator *translator; From 8f1fa1e5da5171912849b2830e260e9815d66181 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 7 Apr 2025 19:47:07 +0500 Subject: [PATCH 0701/1190] qt: Remove unused string translations --- src/qt/languages/86box.pot | 54 -------------------------------------- src/qt/languages/ca-ES.po | 54 -------------------------------------- src/qt/languages/cs-CZ.po | 54 -------------------------------------- src/qt/languages/de-DE.po | 54 -------------------------------------- src/qt/languages/en-GB.po | 12 --------- src/qt/languages/es-ES.po | 54 -------------------------------------- src/qt/languages/fi-FI.po | 51 ----------------------------------- src/qt/languages/fr-FR.po | 54 -------------------------------------- src/qt/languages/hr-HR.po | 54 -------------------------------------- src/qt/languages/hu-HU.po | 54 -------------------------------------- src/qt/languages/it-IT.po | 54 -------------------------------------- src/qt/languages/ja-JP.po | 54 -------------------------------------- src/qt/languages/ko-KR.po | 54 -------------------------------------- src/qt/languages/nl-NL.po | 54 -------------------------------------- src/qt/languages/pl-PL.po | 54 -------------------------------------- src/qt/languages/pt-BR.po | 54 -------------------------------------- src/qt/languages/pt-PT.po | 54 -------------------------------------- src/qt/languages/ru-RU.po | 54 -------------------------------------- src/qt/languages/sk-SK.po | 53 ------------------------------------- src/qt/languages/sl-SI.po | 54 -------------------------------------- src/qt/languages/tr-TR.po | 54 -------------------------------------- src/qt/languages/uk-UA.po | 54 -------------------------------------- src/qt/languages/vi-VN.po | 54 -------------------------------------- src/qt/languages/zh-CN.po | 54 -------------------------------------- src/qt/languages/zh-TW.po | 54 -------------------------------------- 25 files changed, 1304 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 6e610d715..15c605449 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -306,18 +306,12 @@ msgstr "" msgid "Cancel" msgstr "" -msgid "Save these settings as &global defaults" -msgstr "" - msgid "&Default" msgstr "" msgid "Language:" msgstr "" -msgid "Icon set:" -msgstr "" - msgid "Gain" msgstr "" @@ -753,9 +747,6 @@ msgstr "" msgid "KB" msgstr "" -msgid "Could not initialize the video renderer." -msgstr "" - msgid "Default" msgstr "" @@ -906,9 +897,6 @@ msgstr "" msgid "OpenGL Shaders" msgstr "" -msgid "OpenGL options" -msgstr "" - msgid "You are loading an unsupported configuration" msgstr "" @@ -930,12 +918,6 @@ msgstr "" msgid "Cartridge images" msgstr "" -msgid "Error initializing renderer" -msgstr "" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "" - msgid "Resume execution" msgstr "" @@ -1293,21 +1275,6 @@ msgstr "" msgid "NIC %02i (%ls) %ls" msgstr "" -msgid "Error opening \"%1\": %2" -msgstr "" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "" - -msgid "Error linking shader program in file \"%1\"" -msgstr "" - -msgid "OpenGL 3.0 renderer options" -msgstr "" - msgid "Render behavior" msgstr "" @@ -1320,9 +1287,6 @@ msgstr "" msgid "VSync" msgstr "" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "" - msgid "Synchronize with video" msgstr "" @@ -1332,21 +1296,9 @@ msgstr "" msgid "Remove" msgstr "" -msgid "No shader selected" -msgstr "" - msgid "Browse..." msgstr "" -msgid "Shader error" -msgstr "" - -msgid "Could not load shaders." -msgstr "" - -msgid "More information in details." -msgstr "" - msgid "Couldn't create OpenGL context." msgstr "" @@ -1356,18 +1308,12 @@ msgstr "" msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "" -msgid "OpenGL initialization failed. Error %1." -msgstr "" - msgid "Error initializing OpenGL" msgstr "" msgid "Falling back to software rendering.\n" msgstr "" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "" - msgid "<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>" msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 8c89c6bad..26e51fe68 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -306,18 +306,12 @@ msgstr "D'acord" msgid "Cancel" msgstr "Anuŀlació" -msgid "Save these settings as &global defaults" -msgstr "Salvar aquests paràmetres com per &defecte globalment" - msgid "&Default" msgstr "&Per defecte" msgid "Language:" msgstr "Idioma:" -msgid "Icon set:" -msgstr "Conjunt d'icones:" - msgid "Gain" msgstr "Guany" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "No has estat possible inicialitzar el renderitzador de vídeo." - msgid "Default" msgstr "Per defecte" @@ -906,9 +897,6 @@ msgstr "Monitor en mode estalvi" msgid "OpenGL Shaders" msgstr "Shaders OpenGL" -msgid "OpenGL options" -msgstr "Opcions OpenGL" - msgid "You are loading an unsupported configuration" msgstr "S'està carregant una configuració no suportada" @@ -930,12 +918,6 @@ msgstr "Cartutx %i: %ls" msgid "Cartridge images" msgstr "Imatges de cartutx" -msgid "Error initializing renderer" -msgstr "Error en inicialitzar el renderitzador" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "No has estat possible inicialitzar el renderitzador OpenGL (3.0 Core). Utilitzar un altre renderitzador." - msgid "Resume execution" msgstr "Reprendre l'execució" @@ -1293,21 +1275,6 @@ msgstr "Controlador nul" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Error d'obertura \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Error en recopilar el vertex shader al fitxer \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Error en recopilar el fragment shader al fitxer \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Error en enllaçar el programa de shader al fitxer \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opcions del renderitzador OpenGL 3.0" - msgid "Render behavior" msgstr "Comportament del renderitzador" @@ -1320,9 +1287,6 @@ msgstr " fotogrames/s" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Feu que cada fotograma sigui immediatament, en sincronització amb la pantalla emulada.</p><p><span style=" font-style:italic;">Aquesta és l’opció recomanada si els shaders en ús no utilitzen FrameTime per a efectes animats.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sincronitzar amb vídeo" @@ -1332,21 +1296,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Supressió" -msgid "No shader selected" -msgstr "Cap shader seleccionat" - msgid "Browse..." msgstr "Navegació..." -msgid "Shader error" -msgstr "Error del shader" - -msgid "Could not load shaders." -msgstr "No has estat possible carregar els shaders." - -msgid "More information in details." -msgstr "Més informació en els detalls." - msgid "Couldn't create OpenGL context." msgstr "No has estat possible crear un context d'OpenGL." @@ -1356,18 +1308,12 @@ msgstr "No has estat possible canviar al context d'OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Es requereix la versió 3.0 o superior d'OpenGL. La versió actual és %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "No has estat possible inicialitzar OpenGL. Error %1." - msgid "Error initializing OpenGL" msgstr "Error en inicialitzar OpenGL" msgid "Falling back to software rendering.\n" msgstr "Tornant al renderitzador software.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "No has estat possible assignar la memòria per a un buffer de desempaquetament.\n" - msgid "<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>" msgstr "<html><head/><body><p>Quan seleccioneu imatges de suports (CD-ROM, disquet, etc.), el diàleg obert s’iniciarà al mateix directori que el fitxer de configuració 86Box. Aquesta configuració només farà una diferència en les macOS.</p></body></html>" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 2a26f7ef6..099245033 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Storno" -msgid "Save these settings as &global defaults" -msgstr "Uložit toto nastavení jako &globální výchozí stav" - msgid "&Default" msgstr "&Výchozí" msgid "Language:" msgstr "Jazyk:" -msgid "Icon set:" -msgstr "Sada ikon:" - msgid "Gain" msgstr "Zesílení" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Nastala chyba při inicializaci video rendereru." - msgid "Default" msgstr "Výchozí" @@ -906,9 +897,6 @@ msgstr "Monitor je v režimu spánku" msgid "OpenGL Shaders" msgstr "Shadery OpenGL" -msgid "OpenGL options" -msgstr "Možnosti OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Pokoušíte se spustit nepodporovanou konfiguraci" @@ -930,12 +918,6 @@ msgstr "Cartridge %i: %ls" msgid "Cartridge images" msgstr "Obrazy cartridge" -msgid "Error initializing renderer" -msgstr "Chyba při inicializaci vykreslovače" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Vykreslovač OpenGL (3.0 Core) se nepodařilo inicializovat. Použijte jiný renderer." - msgid "Resume execution" msgstr "Obnovit" @@ -1293,21 +1275,6 @@ msgstr "Nulový ovladač" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Chyba při otevírání \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Chyba při kompilaci vertex shaderu v souboru \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Chyba při kompilaci fragment shaderu v souboru \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Chyba při linkování shader programu v souboru \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Možnosti vykreslovače OpenGL 3.0" - msgid "Render behavior" msgstr "Chování vykreslování" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Každý snímek se vykreslí okamžitě, synchronizovaně s emulovaným displejem.</p><p><span style=" font-style:italic;">Tuto možnost doporučujeme, pokud používané shadery nevyužívají frametime pro animované efekty.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Synchronizovat s obrazem" @@ -1332,21 +1296,9 @@ msgstr "Shadery" msgid "Remove" msgstr "Odstraň" -msgid "No shader selected" -msgstr "Není vybrán žádný shader" - msgid "Browse..." msgstr "Prohlížejte..." -msgid "Shader error" -msgstr "Chyba shaderu" - -msgid "Could not load shaders." -msgstr "Nepodařilo se načíst shadery." - -msgid "More information in details." -msgstr "Více informací v podrobnostech." - msgid "Couldn't create OpenGL context." msgstr "Nepodařilo se vytvořit kontext OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Nepodařilo se přepnout na kontext OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Je vyžadována verze OpenGL 3.0 nebo vyšší. Aktuální verze je %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Inicializace OpenGL se nezdařila. Chyba %1." - msgid "Error initializing OpenGL" msgstr "Chyba při inicializaci OpenGL" msgid "Falling back to software rendering.\n" msgstr "Návrat k softwarovému vykreslování.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Alokace paměti pro rozbalovací vyrovnávací paměť se nezdařila.\n" - msgid "<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>" msgstr "<html><head/><body><p>Při výběru obrazů médií (CD-ROM, disketa atd.) se otevřené dialogové okno spustí ve stejném adresáři jako konfigurační soubor 86Box. Toto nastavení bude mít pravděpodobně význam pouze v systému MacOS.</p></body></html>" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index fbb97a990..eae29f084 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Abbrechen" -msgid "Save these settings as &global defaults" -msgstr "Einstellungen als &globalen Standard speichern" - msgid "&Default" msgstr "&Standard" msgid "Language:" msgstr "Sprache:" -msgid "Icon set:" -msgstr "Icon-Satz:" - msgid "Gain" msgstr "Verstärkung" @@ -756,9 +750,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Der Videorenderer konnte nicht initialisiert werden." - msgid "Default" msgstr "Standard" @@ -909,9 +900,6 @@ msgstr "Monitor im Standbymodus" msgid "OpenGL Shaders" msgstr "OpenGL-Shader" -msgid "OpenGL options" -msgstr "OpenGL-Optionen" - msgid "You are loading an unsupported configuration" msgstr "Zur Zeit wird eine nicht unterstützte Konfiguration geladen" @@ -933,12 +921,6 @@ msgstr "Cartridge %i: %ls" msgid "Cartridge images" msgstr "Cartridgeabbilder" -msgid "Error initializing renderer" -msgstr "Fehler bei der Initialisierung des Renderer" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Der OpenGL (3.0-Kern)-Renderer konnte nicht initialisiert werden. Benutze einen anderen Renderer." - msgid "Resume execution" msgstr "Fortsetzen" @@ -1296,21 +1278,6 @@ msgstr "Nulltreiber" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Fehler beim Öffnen \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Fehler beim Kompilieren des Vertex-Shaders in der Datei \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Fehler beim Kompilieren des Fragment-Shaders in der Datei \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Fehler beim Linken des Shader-Programms in der Datei \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 Renderer-Optionen" - msgid "Render behavior" msgstr "Rendering-Verhalten" @@ -1323,9 +1290,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Jedes Bild sofort rendern, synchron mit der emulierten Monitor.</p><p><span style=" font-style:italic;">Dies ist die empfohlene Option, wenn die verwendeten Shader die Bildzeit für animierte Effekte nicht nutzen.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Mit Videoausgabe synchronisieren" @@ -1335,21 +1299,9 @@ msgstr "Shader" msgid "Remove" msgstr "Entfernen" -msgid "No shader selected" -msgstr "Kein Shader ausgewählt" - msgid "Browse..." msgstr "Durchsuchen..." -msgid "Shader error" -msgstr "Shader-Fehler" - -msgid "Could not load shaders." -msgstr "Shader konnten nicht geladen werden." - -msgid "More information in details." -msgstr "Weitere Informationen im Einzelnen." - msgid "Couldn't create OpenGL context." msgstr "OpenGL-Kontext konnte nicht erstellt werden." @@ -1359,18 +1311,12 @@ msgstr "Konnte nicht in den OpenGL-Kontext wechseln." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGL-Version 3.0 oder höher ist erforderlich. Die aktuelle Version ist %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL-Initialisierung fehlgeschlagen. Fehler %1." - msgid "Error initializing OpenGL" msgstr "Fehler beim Initialisieren von OpenGL" msgid "Falling back to software rendering.\n" msgstr "Rückgriff auf Software-Rendering.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Nicht genug Speicher zum Entpacken.\n" - msgid "<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>" msgstr "<html><head/><body><p>Bei der Auswahl von Medien-Abbildern (CD-ROM, Diskette usw.) wird der Öffnungsdialog im selben Verzeichnis wie die 86Box-Konfigurationsdatei gestartet. Diese Einstellung macht wahrscheinlich nur unter macOS einen Unterschied.</p></body></html>" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index bd3a5ba99..b9f79882f 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -15,15 +15,6 @@ msgstr "&RGB Greyscale" msgid "Time synchronization" msgstr "Time synchronisation" -msgid "Could not initialize the video renderer." -msgstr "Could not initialise the video renderer." - -msgid "Error initializing renderer" -msgstr "Error initialising renderer" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialised. Use another renderer." - msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behaviour will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." @@ -33,9 +24,6 @@ msgstr "Apply fullscreen stretch mode when maximised" msgid "Render behavior" msgstr "Render behaviour" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilise frametime for animated effects.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Synchronise with video" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 1a5550065..14d6a6383 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -306,18 +306,12 @@ msgstr "Aceptar" msgid "Cancel" msgstr "Cancelar" -msgid "Save these settings as &global defaults" -msgstr "Salvar estos configuraciones como por &defecto globalmente" - msgid "&Default" msgstr "&Por defecto" msgid "Language:" msgstr "Idioma:" -msgid "Icon set:" -msgstr "Juego de iconos:" - msgid "Gain" msgstr "Ganancia" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "No fué posible inicializar el renderizador de vídeo." - msgid "Default" msgstr "Por defecto" @@ -906,9 +897,6 @@ msgstr "Monitor en modo ahorro" msgid "OpenGL Shaders" msgstr "Shaders OpenGL" -msgid "OpenGL options" -msgstr "Opciones OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Está cargando una configuración no soportada" @@ -930,12 +918,6 @@ msgstr "Cartucho %i: %ls" msgid "Cartridge images" msgstr "Imágenes de Cartucho" -msgid "Error initializing renderer" -msgstr "Error al inicializar el renderizador" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "No fué posible inicializar el renderizador OpenGL (3.0 Core). Utilice otro renderizador." - msgid "Resume execution" msgstr "Retomar la ejecución" @@ -1292,21 +1274,6 @@ msgstr "Controlador nulo" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Error al abrir \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Error al compilar el vertex shader en el archivo \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Error al compilar el fragmentshader en el archivo \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Error al enlazar el programa shader en el archivo \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opciones del renderizador OpenGL 3.0" - msgid "Render behavior" msgstr "Comportamiento del renderizador" @@ -1319,9 +1286,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Renderiza cada fotograma inmediatamente, en sincronía con la pantalla emulada.</p><p><span style=" font-style:italic;">Esta es la opción recomendada si los shaders en uso no utilizan frametime para efectos animados.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sincronizar con los gráficos" @@ -1331,21 +1295,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Eliminar" -msgid "No shader selected" -msgstr "Ningun shader seleccionado" - msgid "Browse..." msgstr "Buscar..." -msgid "Shader error" -msgstr "Error del shader" - -msgid "Could not load shaders." -msgstr "No ha sido posible carregar los shaders." - -msgid "More information in details." -msgstr "Más informaciones en los detalles." - msgid "Couldn't create OpenGL context." msgstr "No ha sido posible crear el contexto OpenGL." @@ -1355,18 +1307,12 @@ msgstr "No ha sido posible cambiar al contexto OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Es requerida la versión 3.0 o más alta de OpenGL. La versión actual es %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "La inicialización de OpenGL no tuvo éxito. Error %1." - msgid "Error initializing OpenGL" msgstr "Error al inicializar OpenGL" msgid "Falling back to software rendering.\n" msgstr "Recurrir al renderizado por software.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "La allocación de memoria para el búfer de desempaquetado no tuvo éxito.\n" - msgid "<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>" msgstr "<html><head/><body><p>Al seleccionar imágenes multimedia (CD-ROM, disquete, etc.), el diálogo de apertura se iniciará en el mismo directorio que el archivo de configuración de 86Box. Es probable que este ajuste sólo suponga una diferencia en macOS.</p></body></html>" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 5222ccc45..1408522fc 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Peruuta" -msgid "Save these settings as &global defaults" -msgstr "Tallenna nämä asetukset &globaaleiksi oletuksiksi" - msgid "&Default" msgstr "&Oletus" msgid "Language:" msgstr "Kieli:" -msgid "Icon set:" -msgstr "Kuvakkeet:" - msgid "Gain" msgstr "Taso" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "Kt" -msgid "Could not initialize the video renderer." -msgstr "Videorenderöijän alustus epäonnistui" - msgid "Default" msgstr "Oletus" @@ -906,9 +897,6 @@ msgstr "Näyttö lepotilassa" msgid "OpenGL Shaders" msgstr "OpenGL-varjostinohjelmat" -msgid "OpenGL options" -msgstr "OpenGL-asetukset" - msgid "You are loading an unsupported configuration" msgstr "Olet lataamassa ei-tuettuja määrittelyjä" @@ -930,12 +918,6 @@ msgstr "ROM-moduuli %i: %ls" msgid "Cartridge images" msgstr "ROM-moduulikuvat" -msgid "Error initializing renderer" -msgstr "Virhe renderöijän alustuksessa" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core)-renderöijän alustus epäonnistui. Käytä toista renderöijää." - msgid "Resume execution" msgstr "Jatka suoritusta" @@ -1293,21 +1275,6 @@ msgstr "Nolla-ajuri" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Virhe \"%1\" avaamisessa: %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Virhe vertex-shaderin kääntämisessä tiedostossa \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Virhe fragmenttivarjostimen kääntämisessä tiedostossa \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Virhe varjostinohjelman linkittämisessä tiedostoon \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0-alustusasetukset" - msgid "Render behavior" msgstr "Renderöintikäyttäytyminen" @@ -1320,9 +1287,6 @@ msgstr " ruutua/s" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Renderöi jokainen ruutu välittömästi synkronoidusti emuloidun näytön kanssa.</p><p><span style=" font-style:italic;">Tämä on suositeltava vaihtoehto, jos käytössä olevat varjostimet eivät käytä frametimeä animaatioefekteihin.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Synkronisoi videoon" @@ -1338,15 +1302,6 @@ msgstr "Ei valittu varjostinohjelmatta" msgid "Browse..." msgstr "Selaa..." -msgid "Shader error" -msgstr "Varjostinohjelmatvirhe" - -msgid "Could not load shaders." -msgstr "Varjostinohjelmateita ei voitu ladata." - -msgid "More information in details." -msgstr "Lisätietoja yksityiskohtaisesti." - msgid "Couldn't create OpenGL context." msgstr "OpenGL-kontekstia ei voitu luoda." @@ -1356,18 +1311,12 @@ msgstr "Ei voitu siirtyä OpenGL-kontekstiin." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Tarvitaan OpenGL-versio 3.0 tai uudempi. Nykyinen versio on %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL:n alustaminen epäonnistui. Virhe %1." - msgid "Error initializing OpenGL" msgstr "Virhe OpenGL:n alustamisessa" msgid "Falling back to software rendering.\n" msgstr "Paluu ohjelmistoalustusöintiin.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Pakkauspuskurin muistin varaaminen epäonnistui.\n" - msgid "<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>" msgstr "<html><head/><body><p>Kun valitset mediakuvia (CD-ROM, levykkeet jne.), avausikkuna käynnistyy samaan hakemistoon kuin 86Boxin konfigurointitiedosto. Tällä asetuksella on todennäköisesti merkitystä vain macOS-käyttöjärjestelmässä.</p></body></html>" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 9937cecd4..829a9658b 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Annuler" -msgid "Save these settings as &global defaults" -msgstr "Sauvegarder ces paramètres comme valeurs par défaut &globales" - msgid "&Default" msgstr "&Défaut" msgid "Language:" msgstr "Langue:" -msgid "Icon set:" -msgstr "Ensemble d'icônes:" - msgid "Gain" msgstr "Gain" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "Ko" -msgid "Could not initialize the video renderer." -msgstr "Impossible d'initialiser le moteur de rendu vidéo." - msgid "Default" msgstr "Défaut" @@ -906,9 +897,6 @@ msgstr "Moniteur en mode veille" msgid "OpenGL Shaders" msgstr "Shaders OpenGL" -msgid "OpenGL options" -msgstr "Options OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Vous chargez une configuration non prise en charge" @@ -930,12 +918,6 @@ msgstr "Cartouche %i: %ls" msgid "Cartridge images" msgstr "Images cartouche" -msgid "Error initializing renderer" -msgstr "Erreur d'initialisation du moteur de rendu" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Le moteur de rendu OpenGL (3.0 Core) n'a pas pu être initialisé. Utilisez un autre moteur de rendu." - msgid "Resume execution" msgstr "Reprendre l'exécution" @@ -1293,21 +1275,6 @@ msgstr "Pilote nul" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Erreur d'ouverture de \"%1\" : %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Erreur de compilation du vertex shader dans le fichier \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Erreur de compilation du fragment shader dans le fichier \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Erreur de liaison du programme shader dans le fichier \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Options de rendu OpenGL 3.0" - msgid "Render behavior" msgstr "Comportement de rendu" @@ -1320,9 +1287,6 @@ msgstr " mages par seconde" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Rendre chaque image immédiatement, en synchronisation avec l'affichage émulé.</p><p><span style=" font-style:italic;">C'est l'option recommandée si les shaders utilisés n'utilisent pas le frametime pour les effets animés.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Synchronisation avec la vidéo" @@ -1332,21 +1296,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Retirer" -msgid "No shader selected" -msgstr "Pas de shader sélectionné" - msgid "Browse..." msgstr "Parcourir..." -msgid "Shader error" -msgstr "Erreur de shader" - -msgid "Could not load shaders." -msgstr "Impossible de charger les shaders." - -msgid "More information in details." -msgstr "Plus d'informations dans les détails." - msgid "Couldn't create OpenGL context." msgstr "Impossible de créer un contexte OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Impossible de passer au contexte OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "La version 3.0 ou supérieure d'OpenGL est requise. La version actuelle est %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "L'initialisation d'OpenGL a échoué. Erreur %1." - msgid "Error initializing OpenGL" msgstr "Erreur d'initialisation d'OpenGL" msgid "Falling back to software rendering.\n" msgstr "Se rabattre sur le rendu logiciel.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "L'allocation de mémoire pour le tampon de décompression a échoué.\n" - msgid "<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>" msgstr "<html><head/><body><p>Lors de la sélection d'images multimédia (CD-ROM, disquette, etc.), la boîte de dialogue d'ouverture démarrera dans le même répertoire que le fichier de configuration de 86Box. Ce paramètre ne fera probablement une différence que sur macOS.</p></body></html>" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 7a8aa53e4..6ca3ad8f5 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -306,18 +306,12 @@ msgstr "U redu" msgid "Cancel" msgstr "Otkaži" -msgid "Save these settings as &global defaults" -msgstr "Spremite ove postavke kao &globalne zadane postavke" - msgid "&Default" msgstr "Zadano" msgid "Language:" msgstr "Jezik:" -msgid "Icon set:" -msgstr "Paket ikona:" - msgid "Gain" msgstr "Pojačavanje" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Nije moguće inicijalizirati renderer." - msgid "Default" msgstr "Standard" @@ -906,9 +897,6 @@ msgstr "Ekran u stanju mirovanja" msgid "OpenGL Shaders" msgstr "OpenGL shaderi" -msgid "OpenGL options" -msgstr "OpenGL opcije" - msgid "You are loading an unsupported configuration" msgstr "Učitavate nepodržanu konfiguraciju" @@ -930,12 +918,6 @@ msgstr "Kaseta %i: %ls" msgid "Cartridge images" msgstr "Slike kasete" -msgid "Error initializing renderer" -msgstr "Nije moguće inicijalizirati renderer" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Nije moguće inicijalizirati OpenGL (3.0 jezgra) renderer. Molimte koristite drugi renderer." - msgid "Resume execution" msgstr "Nastavi" @@ -1293,21 +1275,6 @@ msgstr "Nulti upravljački program" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Nije moguće otvoriti \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Nije moguće sastaviti vertex shader u datoteci \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Nije moguće sastaviti framgent shader u datoteci \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Nije moguće povezati program shader u datoteci \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opcije renderera OpenGL 3.0" - msgid "Render behavior" msgstr "Ponašanje rendera" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Odmah napravi svaki okvir, sinkronizirano s emuliranim zaslonom.</p><p><span style=" font-style:italic;">Ovo je preporučena opcija, ako korišćeni shader ne koristi vreme okvira za animirane efekte.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sinkroniziraj s videom" @@ -1332,21 +1296,9 @@ msgstr "Shaderi" msgid "Remove" msgstr "Ukloni" -msgid "No shader selected" -msgstr "Bez odabranog shadera" - msgid "Browse..." msgstr "Pregledajte..." -msgid "Shader error" -msgstr "Greška shadera" - -msgid "Could not load shaders." -msgstr "Nije moguće učitati shadere." - -msgid "More information in details." -msgstr "Više informacija u detaljima." - msgid "Couldn't create OpenGL context." msgstr "Nije moguće stvoriti kontekst OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Nije se moguće prebaciti na kontekst OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Potrebna je OpenGL verzija 3.0 ili više. Trenutna verzija je %1. %2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Nije moguće inicijalizirati OpenGL. Greška %1." - msgid "Error initializing OpenGL" msgstr "Nije moguće inicijalizirati OpenGL" msgid "Falling back to software rendering.\n" msgstr "Vraća se na softverski renderer.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Nije moguće idodijeliti memoriju za međuspremnik za raspakiranje.\n" - msgid "<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>" msgstr "<html><head/><body><p>Prilikom odabira medijskih slika (CD-ROM, diskete itd.), otvoreni dijalog zopočet će u istom direktoriju kao i konfiguracijska datoteka 86Box-a. Razlika će vjerojatno biti primjetna samo na macOS-u.</p></body></html>" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index c777c6dd7..7d6a434f7 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Mégse" -msgid "Save these settings as &global defaults" -msgstr "Beállítások mentése &globális alapértékként" - msgid "&Default" msgstr "&Alapértelmezett" msgid "Language:" msgstr "Nyelv:" -msgid "Icon set:" -msgstr "Ikonkészlet:" - msgid "Gain" msgstr "Hangerő" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Nem sikerült inicializálni a videó megjelenítőt." - msgid "Default" msgstr "Alapértelmezett" @@ -906,9 +897,6 @@ msgstr "Képernyő alvó módban" msgid "OpenGL Shaders" msgstr "OpenGL Shaderek" -msgid "OpenGL options" -msgstr "OpenGL beállítások" - msgid "You are loading an unsupported configuration" msgstr "Egy nem támogatott konfigurációt tölt be" @@ -930,12 +918,6 @@ msgstr "ROM-kazetta %i: %ls" msgid "Cartridge images" msgstr "ROM-kazetta képek" -msgid "Error initializing renderer" -msgstr "Hiba történt a renderelő inicializálásakor" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Az OpenGL (3.0 Core) megjelenítő-motort nem sikerült inicializálni. Kérem használjon másik renderelőt." - msgid "Resume execution" msgstr "Folytassa a végrehajtást" @@ -1293,21 +1275,6 @@ msgstr "Null Driver" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Hiba a \"%1\" megnyitásakor: %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Hiba a vertex shader fordításában a \"%1\" fájlban" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Hiba a fragment shader fordításában a \"%1\" fájlban" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Hiba a shader program összekapcsolásában a \"%1\" fájlban" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 renderelési beállítások" - msgid "Render behavior" msgstr "Renderelési viselkedés" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Az egyes képkockák azonnali, az emulált kijelzővel szinkronizált megjelenítése.</p><p><span style=" font-style:italic;"">Ez az ajánlott opció, ha a használt shaderek nem használják a frametime-ot az animált effektusokhoz.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Szinkronizálás a videóval" @@ -1332,21 +1296,9 @@ msgstr "Shaderek" msgid "Remove" msgstr "Távolítsa el a" -msgid "No shader selected" -msgstr "Nincs shader kiválasztva" - msgid "Browse..." msgstr "Böngésszen..." -msgid "Shader error" -msgstr "Shader hiba" - -msgid "Could not load shaders." -msgstr "Nem sikerült betölteni a shadereket." - -msgid "More information in details." -msgstr "További információ a részletekről." - msgid "Couldn't create OpenGL context." msgstr "Nem sikerült OpenGL-kontextust létrehozni." @@ -1356,18 +1308,12 @@ msgstr "Nem tudott OpenGL-kontextusra váltani." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Az OpenGL 3.0 vagy magasabb verziója szükséges. Az aktuális verzió %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Az OpenGL inicializálása sikertelen. Hiba %1." - msgid "Error initializing OpenGL" msgstr "Hiba az OpenGL inicializálásában" msgid "Falling back to software rendering.\n" msgstr "Visszatérés a szoftveres rendereléshez.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "A memória kiosztása a kicsomagolási pufferhez sikertelen.\n" - msgid "<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>" msgstr "<html><head/><body><p>A médiaképek (CD-ROM, floppy stb.) kiválasztásakor a megnyitási párbeszédpanel ugyanabban a könyvtárban indul, mint a 86Box konfigurációs fájl. Ez a beállítás valószínűleg csak a macOS rendszerben jelent különbséget.</p></body></html>" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index adf5b0471..256337a0d 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Annulla" -msgid "Save these settings as &global defaults" -msgstr "Salva queste impostazioni come &predefinite globali" - msgid "&Default" msgstr "&Predefinito" msgid "Language:" msgstr "Lingua:" -msgid "Icon set:" -msgstr "Pacchetto di icone:" - msgid "Gain" msgstr "Guadagno" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Impossibile inizializzare il renderer video." - msgid "Default" msgstr "Predefinito" @@ -906,9 +897,6 @@ msgstr "Monitor in modalità riposo" msgid "OpenGL Shaders" msgstr "Shader OpenGL" -msgid "OpenGL options" -msgstr "Impostazioni OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Stai caricando una configurazione non supportata" @@ -930,12 +918,6 @@ msgstr "Cartuccia %i: %ls" msgid "Cartridge images" msgstr "Immagini cartuccia" -msgid "Error initializing renderer" -msgstr "Errore nell'inizializzazione del renderer" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Non è stato possibile inizializzare il renderer OpenGL (3.0 Core). Utilizzare un altro renderer." - msgid "Resume execution" msgstr "Riprendere l'esecuzione" @@ -1293,21 +1275,6 @@ msgstr "Driver nullo" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Errore nell'apertura di \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Errore nella compilazione di vertex shader nel file \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Errore nella compilazione dello shader dei frammenti nel file \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Errore nel collegamento del programma shader nel file \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opzioni del renderer OpenGL 3.0" - msgid "Render behavior" msgstr "Comportamento di rendering" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Renderizza ogni fotogramma immediatamente, in sincronia con la visualizzazione emulata.</p><p><span style=" font-style:italic;">Questa è l'opzione consigliata se gli shader in uso non utilizzano il frametime per gli effetti animati.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sincronizza col video" @@ -1332,21 +1296,9 @@ msgstr "Shader" msgid "Remove" msgstr "Rimuovere" -msgid "No shader selected" -msgstr "Nessuno shader selezionato" - msgid "Browse..." msgstr "Sfoglia..." -msgid "Shader error" -msgstr "Errore dello shader" - -msgid "Could not load shaders." -msgstr "Impossibile caricare gli shader." - -msgid "More information in details." -msgstr "Maggiori informazioni in dettaglio." - msgid "Couldn't create OpenGL context." msgstr "Impossibile creare un contesto OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Impossibile passare al contesto OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "È richiesta la versione OpenGL 3.0 o superiore. La versione attuale è %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Inizializzazione OpenGL non riuscita. Errore %1." - msgid "Error initializing OpenGL" msgstr "Errore nell'inizializzazione di OpenGL" msgid "Falling back to software rendering.\n" msgstr "Ricaduta sul rendering software." -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "L'allocazione della memoria per il buffer di disimballaggio non è riuscita." - msgid "<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>" msgstr "<html><head/><body><p>Quando si selezionano immagini multimediali (CD-ROM, floppy, ecc.) la finestra di dialogo di apertura si avvia nella stessa directory del file di configurazione di 86Box. Questa impostazione probabilmente farà la differenza solo su macOS.</p></body></html>" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index d51be2536..d38760f15 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "キャンセル" -msgid "Save these settings as &global defaults" -msgstr "これらの設定をグローバル既定値として保存(&G)" - msgid "&Default" msgstr "既定値(&D)" msgid "Language:" msgstr "言語:" -msgid "Icon set:" -msgstr "アイコンセット:" - msgid "Gain" msgstr "音量" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "ビデオレンダラーが初期化できません。" - msgid "Default" msgstr "既定値" @@ -906,9 +897,6 @@ msgstr "モニターのスリープモード" msgid "OpenGL Shaders" msgstr "OpenGLシェーダー" -msgid "OpenGL options" -msgstr "OpenGL設定" - msgid "You are loading an unsupported configuration" msgstr "サポートされていないコンフィグを読み込んでいます" @@ -930,12 +918,6 @@ msgstr "カートリッジ %i: %ls" msgid "Cartridge images" msgstr "カートリッジイメージ" -msgid "Error initializing renderer" -msgstr "レンダラーの初期化エラー" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) レンダラーが初期化できません。別のレンダラーを使用してください。" - msgid "Resume execution" msgstr "実行を再開" @@ -1293,21 +1275,6 @@ msgstr "ヌル・ドライバー" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "\"%1\"を開く際にエラーが発生しました: %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "ファイル\"%1\"の頂点シェーダのコンパイルエラー。" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "ファイル\"%1\"のフラグメント・シェーダのコンパイル・エラー。" - -msgid "Error linking shader program in file \"%1\"" -msgstr "ファイル\"%1\"のシェーダープログラムのリンクエラー。" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0レンダラー設定" - msgid "Render behavior" msgstr "レンダリング動作" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSシンク" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>エミュレートされたディスプレイと同期して、各フレームを即座にレンダリングします。</p><p><span style=" font-style:italic;">これは、使用中のシェーダがアニメーション効果のためにフレームタイムを利用しない場合に推奨されるオプションです。</span></p></body></html>" - msgid "Synchronize with video" msgstr "ビデオと同期" @@ -1332,21 +1296,9 @@ msgstr "シェーダー" msgid "Remove" msgstr "削除" -msgid "No shader selected" -msgstr "シェーダーが選択されていない" - msgid "Browse..." msgstr "ブラウズ..." -msgid "Shader error" -msgstr "シェーダーエラー" - -msgid "Could not load shaders." -msgstr "シェーダーをロードできませんでした。" - -msgid "More information in details." -msgstr "詳細はこちら。" - msgid "Couldn't create OpenGL context." msgstr "OpenGLコンテキストを作成できませんでした。" @@ -1356,18 +1308,12 @@ msgstr "OpenGLコンテキストに切り替えられなかった。" msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGLのバージョン3.0以上が必要です。現在のバージョンは %1.%2 です。" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL の初期化に失敗しました。エラー %1。" - msgid "Error initializing OpenGL" msgstr "OpenGLの初期化エラー" msgid "Falling back to software rendering.\n" msgstr "ソフトウェアレンダリングに逆戻り。" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "アンパックバッファのメモリ確保に失敗しました。" - msgid "<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>" msgstr "<html><head/><body><p>メディアイメージ(CD-ROM、フロッピーなど)を選択するとき、オープンダイアログは86Box設定ファイルと同じディレクトリで開始します。この設定は、おそらく macOS でのみ違いがあります。</p></body></html>" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 859183fc1..dbf77106b 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -306,18 +306,12 @@ msgstr "확인" msgid "Cancel" msgstr "취소" -msgid "Save these settings as &global defaults" -msgstr "이 설정들을 전역 기본값으로 저장하기(&G)" - msgid "&Default" msgstr "기본값(&D)" msgid "Language:" msgstr "언어:" -msgid "Icon set:" -msgstr "아이콘셋:" - msgid "Gain" msgstr "증가값" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "비디오 렌더러를 초기화할 수 없습니다." - msgid "Default" msgstr "기본값" @@ -906,9 +897,6 @@ msgstr "모니터 절전 모드" msgid "OpenGL Shaders" msgstr "OpenGL 쉐이더" -msgid "OpenGL options" -msgstr "OpenGL 설정" - msgid "You are loading an unsupported configuration" msgstr "지원하지 않는 설정입니다" @@ -930,12 +918,6 @@ msgstr "카트리지 %i: %ls" msgid "Cartridge images" msgstr "카트리지 이미지" -msgid "Error initializing renderer" -msgstr "렌더러 초기화 오류" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) 렌더러를 초기화할 수 없습니다. 다른 렌더러를 사용하십시오." - msgid "Resume execution" msgstr "실행 재개" @@ -1293,21 +1275,6 @@ msgstr "Null 드라이버" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "열기 오류 \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "파일 \"%1\"에서 버텍스 셰이더를 컴파일하는 동안 오류가 발생했습니다." - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "파일에서 조각 셰이더 컴파일 중 오류 발생 \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "파일에서 셰이더 프로그램 연결 중 오류 \"%1\"\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 렌더러 옵션" - msgid "Render behavior" msgstr "렌더링 동작" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>;에뮬레이트된 디스플레이와 동기화하여 각 프레임을 즉시 렌더링합니다.</p><p><span style=" font-style:italic;">사용 중인 셰이더가 애니메이션 효과에 프레임 시간을 활용하지 않는 경우 권장되는 옵션입니다.</span></p></body></html>" - msgid "Synchronize with video" msgstr "비디오와 동기" @@ -1332,21 +1296,9 @@ msgstr "셰이더" msgid "Remove" msgstr "제거" -msgid "No shader selected" -msgstr "셰이더를 선택하지 않음" - msgid "Browse..." msgstr "찾아보기..." -msgid "Shader error" -msgstr "셰이더 오류" - -msgid "Could not load shaders." -msgstr "셰이더를 로드할 수 없습니다." - -msgid "More information in details." -msgstr "자세한 내용은 자세히 알아보세요." - msgid "Couldn't create OpenGL context." msgstr "OpenGL 컨텍스트를 만들 수 없습니다." @@ -1356,18 +1308,12 @@ msgstr "OpenGL 컨텍스트로 전환할 수 없습니다." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGL 버전 3.0 이상이 필요합니다. 현재 버전은 %1.%2입니다." -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL 초기화에 실패했습니다. 오류 %1입니다." - msgid "Error initializing OpenGL" msgstr "OpenGL 초기화 중 오류 발생" msgid "Falling back to software rendering.\n" msgstr "소프트웨어 렌더링으로 돌아가기.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "압축 해제 버퍼에 메모리를 할당하지 못했습니다.\n" - msgid "<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>" msgstr "<html><head/><body><p>미디어 이미지(CD-ROM, 플로피 등)를 선택하면 86Box 구성 파일과 동일한 디렉터리에서 열기 대화 상자가 시작됩니다. 이 설정은 macOS에서만 차이가 있을 수 있습니다.</p></body></html>" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index cce4dfdc9..65e59331b 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Annuleren" -msgid "Save these settings as &global defaults" -msgstr "Sla deze instellingen op als &globale standaardinstellingen" - msgid "&Default" msgstr "&Standaard" msgid "Language:" msgstr "Taal:" -msgid "Icon set:" -msgstr "Pictogrammenset:" - msgid "Gain" msgstr "Versterking" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Kan de videorenderer niet initialiseren." - msgid "Default" msgstr "Standaard" @@ -906,9 +897,6 @@ msgstr "Monitor in slaapstand" msgid "OpenGL Shaders" msgstr "OpenGL Shaders" -msgid "OpenGL options" -msgstr "OpenGL-opties" - msgid "You are loading an unsupported configuration" msgstr "U laadt een configuratie die niet wordt ondersteund" @@ -930,12 +918,6 @@ msgstr "Cartridge %i: %ls" msgid "Cartridge images" msgstr "Cartridge-images" -msgid "Error initializing renderer" -msgstr "Fout bij het initialiseren van renderer" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer kon niet worden geïnitialiseerd. Gebruik een andere renderer." - msgid "Resume execution" msgstr "Hervat executie" @@ -1293,21 +1275,6 @@ msgstr "Null Driver" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Fout bij het openen van \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Fout bij het compileren van vertex shader in bestand \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Fout bij het compileren van fragment shader in bestand \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Fout bij koppelen shaderprogramma in bestand \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 renderer opties" - msgid "Render behavior" msgstr "Rendergedrag" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Onmiddellijk elk frame synchroon met het geëmuleerde beeldscherm renderen.</p><p><span style=" font-style:italic;">Dit is de aanbevolen optie als de gebruikte shaders geen frametime gebruiken voor geanimeerde effecten.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Synchroniseren met video" @@ -1332,21 +1296,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Verwijderen" -msgid "No shader selected" -msgstr "Geen shader geselecteerd" - msgid "Browse..." msgstr "Bladeren..." -msgid "Shader error" -msgstr "Shader-fout" - -msgid "Could not load shaders." -msgstr "Kan shaders niet laden." - -msgid "More information in details." -msgstr "Meer informatie in details." - msgid "Couldn't create OpenGL context." msgstr "Kan OpenGL context niet maken." @@ -1356,18 +1308,12 @@ msgstr "Kan niet overschakelen naar OpenGL context." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGL versie 3.0 of hoger is vereist. De huidige versie is %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL initialisatie mislukt. Fout %1." - msgid "Error initializing OpenGL" msgstr "Fout bij het initialiseren van OpenGL" msgid "Falling back to software rendering.\n" msgstr "Terugvallen op software rendering.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Toewijzen van geheugen voor uitpakbuffer mislukt.\n" - msgid "<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>" msgstr "<html><head/><body><p>Bij het selecteren van media-images (CD-ROM, floppy, etc.) zal de \"open dialoog\" starten in dezelfde map als het 86Box configuratiebestand. Deze instelling is doet er waarschijnlijk alleen toe op macOS.</p></body></html>" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 26cc4bae6..bed21af24 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Anuluj" -msgid "Save these settings as &global defaults" -msgstr "Zapisz ustawienia jako &globalne ustawienia domyślne" - msgid "&Default" msgstr "&Domyślny" msgid "Language:" msgstr "Język:" -msgid "Icon set:" -msgstr "Zestaw ikon:" - msgid "Gain" msgstr "Wzmacniacz" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Nie można zainicjować renderera wideo." - msgid "Default" msgstr "Domyślny" @@ -906,9 +897,6 @@ msgstr "Monitor w trybie czuwania" msgid "OpenGL Shaders" msgstr "Shadery OpenGL" -msgid "OpenGL options" -msgstr "Opcje OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Ładujesz nieobsługiwaną konfigurację" @@ -930,12 +918,6 @@ msgstr "Kartrydż %i: %ls" msgid "Cartridge images" msgstr "Obrazy kartrydżu" -msgid "Error initializing renderer" -msgstr "Błąd inicjalizacji renderera" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Nie można zainicjować renderera OpenGL (3.0 Core). Użyj innego." - msgid "Resume execution" msgstr "Wznów wykonywanie" @@ -1293,21 +1275,6 @@ msgstr "Null Driver" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Błąd otwarcia \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Błąd kompilacji shadera wierzchołków w pliku \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Błąd kompilacji shadera fragmentów w pliku \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Błąd łączenia programu shader w pliku \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opcje renderowania OpenGL 3.0" - msgid "Render behavior" msgstr "Zachowanie renderowania" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Renderuj każdą klatkę natychmiast, w synchronizacji z emulowanym wyświetlaczem.</p><p><span style=" font-style:italic;">Jest to zalecana opcja, jeśli używane shadery nie wykorzystują frametime do animowanych efektów.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Zsynchronizuj z wideo" @@ -1332,21 +1296,9 @@ msgstr "Shadery" msgid "Remove" msgstr "Usuń" -msgid "No shader selected" -msgstr "Nie wybrano shadera" - msgid "Browse..." msgstr "Przeglądaj..." -msgid "Shader error" -msgstr "Błąd shadera" - -msgid "Could not load shaders." -msgstr "Nie można załadować shaderów." - -msgid "More information in details." -msgstr "Więcej informacji w szczegółach." - msgid "Couldn't create OpenGL context." msgstr "Nie można utworzyć kontekstu OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Nie można przełączyć na kontekst OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Wymagana jest wersja OpenGL 3.0 lub wyższa. Aktualna wersja to %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Inicjalizacja OpenGL nie powiodła się. Błąd %1." - msgid "Error initializing OpenGL" msgstr "Błąd inicjalizacji OpenGL" msgid "Falling back to software rendering.\n" msgstr "Powrót do renderowania oprogramowania.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Przydzielenie pamięci dla bufora rozpakowywania nie powiodło się.\n" - msgid "<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>" msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itp.) otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index b453d0f97..df606a635 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Cancelar" -msgid "Save these settings as &global defaults" -msgstr "Salvar estas configurações como &padrões globais" - msgid "&Default" msgstr "&Padrão" msgid "Language:" msgstr "Idioma:" -msgid "Icon set:" -msgstr "Conjunto de ícones:" - msgid "Gain" msgstr "Ganho" @@ -753,9 +747,6 @@ msgstr "SE" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Não foi possível inicializar o renderizador de vídeo." - msgid "Default" msgstr "Padrão" @@ -906,9 +897,6 @@ msgstr "Monitor em modo de suspensão" msgid "OpenGL Shaders" msgstr "Shaders OpenGL" -msgid "OpenGL options" -msgstr "Opções do OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Você está carregando uma configuração não suportada" @@ -930,12 +918,6 @@ msgstr "Cartucho %i: %ls" msgid "Cartridge images" msgstr "Imagens de cartucho" -msgid "Error initializing renderer" -msgstr "Erro ao inicializar o renderizador" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "O renderizador OpenGL (Núcleo 3.0) não pôde ser inicializado. Use outro renderizador." - msgid "Resume execution" msgstr "Continuar a execução" @@ -1293,21 +1275,6 @@ msgstr "Driver nulo" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Erro ao abrir \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Erro ao compilar o sombreador de vértice no arquivo \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Erro ao compilar o fragment shader no arquivo \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Erro ao vincular o programa de shader no arquivo \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opções do renderizador OpenGL 3.0" - msgid "Render behavior" msgstr "Comportamento de renderização" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Renderize cada quadro imediatamente, em sincronia com a tela emulada.</p><p><span style=" font-style:italic;">Essa é a opção recomendada se os shaders em uso não utilizarem o frametime para efeitos animados.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sincronizar com o vídeo" @@ -1332,21 +1296,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Remover" -msgid "No shader selected" -msgstr "Nenhum shader selecionado" - msgid "Browse..." msgstr "Procurar..." -msgid "Shader error" -msgstr "Erro do sombreador" - -msgid "Could not load shaders." -msgstr "Não foi possível carregar os shaders." - -msgid "More information in details." -msgstr "Mais informações em detalhes." - msgid "Couldn't create OpenGL context." msgstr "Não foi possível criar o contexto OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Não foi possível alternar para o contexto OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "É necessária a versão 3.0 ou superior do OpenGL. A versão atual é %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Falha na inicialização do OpenGL. Erro %1." - msgid "Error initializing OpenGL" msgstr "Erro ao inicializar o OpenGL" msgid "Falling back to software rendering.\n" msgstr "Voltando à renderização de software.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Falha na alocação de memória para o buffer de descompactação.\n" - msgid "<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>" msgstr "<html><head/><body><p>Ao selecionar imagens de mídia (CD-ROM, disquete, etc.), a caixa de diálogo de abertura será iniciada no mesmo diretório do arquivo de configuração do 86Box. Essa configuração provavelmente só fará diferença no macOS.</p></body></html>" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index d732532ed..b3458bcdf 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Cancelar" -msgid "Save these settings as &global defaults" -msgstr "Guardar estas definições como padrões &globais" - msgid "&Default" msgstr "&Padrão" msgid "Language:" msgstr "Idioma:" -msgid "Icon set:" -msgstr "Pacote de ícones:" - msgid "Gain" msgstr "Ganho" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Não foi possível inicializar o renderizador vídeo." - msgid "Default" msgstr "Padrão" @@ -906,9 +897,6 @@ msgstr "Ecrã em modo de sono" msgid "OpenGL Shaders" msgstr "Shaders OpenGL" -msgid "OpenGL options" -msgstr "Opções de OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Está a carregar uma configuração sem suporte!" @@ -930,12 +918,6 @@ msgstr "Cartucho %i: %ls" msgid "Cartridge images" msgstr "Imagens de cartucho" -msgid "Error initializing renderer" -msgstr "Erro na inicialização do renderizador" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Não foi possível inicializar o renderizador OpenGL (3.0 Core). Utilize outro renderizador." - msgid "Resume execution" msgstr "Retomar execução" @@ -1293,21 +1275,6 @@ msgstr "Condutor nulo" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Erro ao abrir \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Erro ao compilar o sombreador de vértice no ficheiro \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Erro ao compilar o shader de fragmento no ficheiro \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Erro ao ligar o programa de shader no ficheiro \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Opções do renderizador OpenGL 3.0" - msgid "Render behavior" msgstr "Comportamento de renderização" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Renderiza cada frame imediatamente, em sincronia com o ecrã emulado.</p><p><span style=" font-style:italic;">Esta é a opção recomendada se os shaders em uso não utilizam frametime para efeitos animados.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sincronizar com vídeo" @@ -1332,21 +1296,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Remover" -msgid "No shader selected" -msgstr "Nenhum sombreador selecionado" - msgid "Browse..." msgstr "Navegar..." -msgid "Shader error" -msgstr "Erro de shader" - -msgid "Could not load shaders." -msgstr "Não foi possível carregar os shaders." - -msgid "More information in details." -msgstr "Mais informações em pormenor." - msgid "Couldn't create OpenGL context." msgstr "Não foi possível criar o contexto OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Não foi possível mudar para o contexto OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "É necessária a versão 3.0 ou superior do OpenGL. A versão atual é %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Falha na inicialização do OpenGL. Erro %1." - msgid "Error initializing OpenGL" msgstr "Erro ao inicializar o OpenGL" msgid "Falling back to software rendering.\n" msgstr "Recuando para a renderização de software." -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Falha na atribuição de memória para a memória intermédia de descompactação.\n" - msgid "<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>" msgstr "<html><head/><body><p>Ao selecionar imagens multimédia (CD-ROM, disquete, etc.) a caixa de diálogo de abertura irá começar no mesmo diretório que o ficheiro de configuração da 86Box. Esta configuração provavelmente só fará diferença no macOS.</p></body></html>" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index e68e6bb10..6104d064f 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Отмена" -msgid "Save these settings as &global defaults" -msgstr "Сохранить эти параметры как &глобальные по умолчанию" - msgid "&Default" msgstr "&По умолчанию" msgid "Language:" msgstr "Язык:" -msgid "Icon set:" -msgstr "Набор иконок:" - msgid "Gain" msgstr "Усиление" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "КБ" -msgid "Could not initialize the video renderer." -msgstr "Не удалось инициализировать рендерер видео." - msgid "Default" msgstr "По умолчанию" @@ -906,9 +897,6 @@ msgstr "Монитор в спящем режиме" msgid "OpenGL Shaders" msgstr "Шейдеры OpenGL" -msgid "OpenGL options" -msgstr "Параметры OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Вы загружаете неподдерживаемую конфигурацию" @@ -930,12 +918,6 @@ msgstr "Картридж %i: %ls" msgid "Cartridge images" msgstr "Образы картриджей" -msgid "Error initializing renderer" -msgstr "Ошибка инициализации рендерера" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Невозможно инициализировать рендерер OpenGL (3.0). Пожалуйста, используйте другой рендерер." - msgid "Resume execution" msgstr "Возобновить выполнение" @@ -1293,21 +1275,6 @@ msgstr "Нулевой драйвер" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Ошибка при открытии \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Ошибка компиляции вершинного шейдера в файле \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Ошибка компиляции фрагментного шейдера в файле \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Ошибка компоновки программы шейдера в файле \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Параметры рендеринга OpenGL 3.0" - msgid "Render behavior" msgstr "Режим рендеринга" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "Вертикальная синхронизация" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Рендерить каждый кадр немедленно, синхронно с эмулируемым дисплеем.</p><p><span style="font-style:italic;">Это рекомендуемый вариант, если используемые шейдеры не используют время кадров для анимированных эффектов.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Синхронизация с видео" @@ -1332,21 +1296,9 @@ msgstr "Шейдеры" msgid "Remove" msgstr "Удалить" -msgid "No shader selected" -msgstr "Шейдер не выбран" - msgid "Browse..." msgstr "Обзор..." -msgid "Shader error" -msgstr "Ошибка шейдера" - -msgid "Could not load shaders." -msgstr "Не удалось загрузить шейдеры." - -msgid "More information in details." -msgstr "Более подробная информация в деталях." - msgid "Couldn't create OpenGL context." msgstr "Не удалось создать контекст OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Не удалось переключиться на контекст Ope msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Требуется OpenGL версии 3.0 или выше. Текущая версия %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Не удалось выполнить инициализацию OpenGL. Ошибка %1." - msgid "Error initializing OpenGL" msgstr "Ошибка инициализации OpenGL" msgid "Falling back to software rendering.\n" msgstr "Переключение на программный рендеринг.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Выделение памяти для буфера распаковки не удалось.\n" - msgid "<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>" msgstr "<html><head/><body><p>При выборе образов носителей (CD-ROM, дискет и т. д.) диалог открытия будет запускаться в том же каталоге, что и файл конфигурации 86Box. Эта настройка, скорее всего, будет иметь значение только на macOS.</p></body></html>" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index c091780c2..9e6532267 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Storno" -msgid "Save these settings as &global defaults" -msgstr "Uložiť toto nastavenie ako &globálny východiskový stav" - msgid "&Default" msgstr "&Východiskové" msgid "Language:" msgstr "Jazyk:" -msgid "Icon set:" -msgstr "Súprava ikon:" - msgid "Gain" msgstr "Zosilnenie" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Nastala chyba pri inicializácii video renderera." - msgid "Default" msgstr "Východiskové" @@ -906,9 +897,6 @@ msgstr "Monitor je v režime spánku" msgid "OpenGL Shaders" msgstr "Shadery OpenGL" -msgid "OpenGL options" -msgstr "Možnosti OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Pokúšate sa spustiť nepodporovanú konfiguráciu" @@ -930,12 +918,6 @@ msgstr "Cartridge %i: %ls" msgid "Cartridge images" msgstr "Obrazy cartridge" -msgid "Error initializing renderer" -msgstr "Chyba pri inicializácii vykresľovača" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Vykresľovač OpenGL (3.0 Core) sa nepodarilo inicializovať. Použite iný renderer." - msgid "Resume execution" msgstr "Obnoviť" @@ -1293,20 +1275,6 @@ msgstr "Nulový ovládač" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Chyba pri otváraní \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Chyba kompilácie vertex shadera v súbore \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Chyba kompilácie fragment shadera v súbore \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Chyba pri prepojení shader programu v súbore \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Možnosti vykresľovania OpenGL 3.0" msgid "Render behavior" msgstr "Správanie pri vykresľovaní" @@ -1320,9 +1288,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Okamžite vykresliť každú snímku v synchronizácii s emulovaným displejom.</p><p><span style=" font-style:italic;">Toto je odporúčaná možnosť, ak používané shadery nevyužívajú frametime pre animované efekty.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Synchronizovať s obrazom" @@ -1332,21 +1297,9 @@ msgstr "Shadery" msgid "Remove" msgstr "Odstránenie stránky" -msgid "No shader selected" -msgstr "Nie je vybraný žiadny tieňovač" - msgid "Browse..." msgstr "Prehľadávať..." -msgid "Shader error" -msgstr "Chyba shadera" - -msgid "Could not load shaders." -msgstr "Nepodarilo sa načítať shadery." - -msgid "More information in details." -msgstr "Viac informácií v detailoch." - msgid "Couldn't create OpenGL context." msgstr "Nepodarilo sa vytvoriť kontext OpenGL." @@ -1356,18 +1309,12 @@ msgstr "Nepodarilo sa prepnúť na kontext OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Vyžaduje sa verzia OpenGL 3.0 alebo vyššia. Aktuálna verzia je %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Inicializácia OpenGL zlyhala. Chyba %1." - msgid "Error initializing OpenGL" msgstr "Chyba pri inicializácii OpenGL" msgid "Falling back to software rendering.\n" msgstr "Návrat k softvérovému vykresľovaniu.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Alokácia pamäte pre rozbaľovaciu vyrovnávaciu pamäť zlyhala.\n" - msgid "<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>" msgstr "<html><head/><body><p>Pri výbere multimediálnych obrazov (CD-ROM, disketa atď.) sa dialógové okno otvorenia spustí v rovnakom adresári ako konfiguračný súbor 86Box. Toto nastavenie bude mať pravdepodobne význam len v systéme MacOS.</p></body></html>" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 15041a4aa..efb62153a 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -306,18 +306,12 @@ msgstr "V redu" msgid "Cancel" msgstr "Prekliči" -msgid "Save these settings as &global defaults" -msgstr "Shrani te nastavitve kot globalne privzete" - msgid "&Default" msgstr "Privzeto" msgid "Language:" msgstr "Jezik:" -msgid "Icon set:" -msgstr "Komplet ikon:" - msgid "Gain" msgstr "Ojačanje" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Ne morem inicializirati sistema za upodabljanje." - msgid "Default" msgstr "Privzeto" @@ -906,9 +897,6 @@ msgstr "Zaslon v načinu spanja" msgid "OpenGL Shaders" msgstr "Senčilniki OpenGL" -msgid "OpenGL options" -msgstr "Možnosti OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Nalagate nepodprto konfiguracijo" @@ -930,12 +918,6 @@ msgstr "Spominski vložek %i: %ls" msgid "Cartridge images" msgstr "Slike spominskega vložka" -msgid "Error initializing renderer" -msgstr "Napaka pri zagonu sistema za upodabljanje" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Sistema za upodabljanje OpenGL (3.0 Core) ni bilo mogoče zagnati. Uporabite drug sistem za upodabljanje." - msgid "Resume execution" msgstr "Nadaljuj izvajanje" @@ -1293,21 +1275,6 @@ msgstr "Ničelni gonilnik" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Napaka pri odpiranju \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Napaka pri sestavljanju senčilnika vrhov v datoteki \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Napaka pri sestavljanju shaderja fragmentov v datoteki \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Napaka pri povezovanju programa shader v datoteki \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Možnosti sistema za upodabljanje OpenGL 3.0" - msgid "Render behavior" msgstr "Obnašanje pri upodabljanju" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Vsako sličico prikažite takoj, sinhronizirano z emuliranim zaslonom.</p><p><span style=" font-style:italic;">To je priporočljiva možnost, če uporabljeni senčilniki ne uporabljajo časa okvirja za animirane učinke.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Sinhroniziraj z videom" @@ -1332,21 +1296,9 @@ msgstr "Senčilniki" msgid "Remove" msgstr "Odstrani" -msgid "No shader selected" -msgstr "Ni izbran noben senčnik" - msgid "Browse..." msgstr "Brskaj..." -msgid "Shader error" -msgstr "Napaka senčilnika" - -msgid "Could not load shaders." -msgstr "Ni bilo mogoče naložiti senčilnikov." - -msgid "More information in details." -msgstr "Več informacij v podrobnostih." - msgid "Couldn't create OpenGL context." msgstr "Ni bilo mogoče ustvariti konteksta OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Ni bilo mogoče preklopiti na kontekst OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Zahteva se različica OpenGL 3.0 ali novejša. Trenutna različica je %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Inicializacija OpenGL ni uspela. Napaka %1." - msgid "Error initializing OpenGL" msgstr "Napaka pri inicializaciji OpenGL" msgid "Falling back to software rendering.\n" msgstr "Vrnitev k programskemu upodabljanju.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Dodelitev pomnilnika za razpakirni predpomnilnik ni uspela.\n" - msgid "<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>" msgstr "<html><head/><body><p>Pri izbiri medijskih slik (CD-ROM, disketa itd.) se bo odprto pogovorno okno začelo v istem imeniku kot konfiguracijska datoteka 86Box. Ta nastavitev bo verjetno imela pomen le v operacijskem sistemu MacOS.</p></body></html>" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index c16cc12e4..e3d692537 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -306,18 +306,12 @@ msgstr "Tamam" msgid "Cancel" msgstr "İptal" -msgid "Save these settings as &global defaults" -msgstr "Ayarları &varsayılan olarak kaydet" - msgid "&Default" msgstr "&Varsayılan" msgid "Language:" msgstr "Dil:" -msgid "Icon set:" -msgstr "Simge seti:" - msgid "Gain" msgstr "Artış" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Video işleyici başlatılamadı." - msgid "Default" msgstr "Varsayılan" @@ -906,9 +897,6 @@ msgstr "Monitör uyku modunda" msgid "OpenGL Shaders" msgstr "OpenGL gölgelendiricileri" -msgid "OpenGL options" -msgstr "OpenGL ayarları" - msgid "You are loading an unsupported configuration" msgstr "Desteklenmeyen bir konfigürasyon kullanıyorsunuz" @@ -930,12 +918,6 @@ msgstr "Kartuş %i: %ls" msgid "Cartridge images" msgstr "Kartuş imajları" -msgid "Error initializing renderer" -msgstr "İşleyici başlatılırken hata oluştu" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) işleyici başlatılamadı. Başka bir görüntüleyici kullanın." - msgid "Resume execution" msgstr "Çalıştırmaya devam et" @@ -1293,21 +1275,6 @@ msgstr "Null sürücü" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "\"%1\": %2 açılırken hata oluştu" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "\"%1\" dosyasında tepe gölgelendirici derlenirken hata oluştu" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "\"%1\" dosyasında parça gölgelendirici derlenirken hata oluştu" - -msgid "Error linking shader program in file \"%1\"" -msgstr "\"%1\" dosyasında gölgelendirici programı bağlanırken hata oluştu" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 işleyici seçenekleri" - msgid "Render behavior" msgstr "İşleyiş davranışı" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Emüle edilen ekranla senkronize olarak her kareyi hemen işleyin.</p><p><span style=" font-style:italic;">Kullanılan gölgelendiriciler animasyonlu efektler için kare zamanını kullanmıyorsa bu önerilen seçenektir.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Video ile senkronize et" @@ -1332,21 +1296,9 @@ msgstr "Gölgelendiriciler" msgid "Remove" msgstr "Kaldır" -msgid "No shader selected" -msgstr "Gölgelendirici seçili değil" - msgid "Browse..." msgstr "Göz at..." -msgid "Shader error" -msgstr "Gölgelendirici hatası" - -msgid "Could not load shaders." -msgstr "Gölgelendiriciler yüklenemedi." - -msgid "More information in details." -msgstr "Daha fazla bilgi detaylardadır." - msgid "Couldn't create OpenGL context." msgstr "OpenGL bağlamı oluşturulamadı." @@ -1356,18 +1308,12 @@ msgstr "OpenGL bağlamına geçilemedi." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGL sürüm 3.0 veya üstü gereklidir. Geçerli sürüm %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL başlatılamadı. Hata %1." - msgid "Error initializing OpenGL" msgstr "OpenGL başlatılırken hata oluştu" msgid "Falling back to software rendering.\n" msgstr "Yazılım işleyicisine geri dönülüyor.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Paket açma arabelleği için bellek ayırma başarısız oldu.\n" - msgid "<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>" msgstr "<html><head/><body><p>Medya görüntüsü (CD-ROM, disket, vb.) seçme diyaloğu 86Box yapılandırma dosyasıyla aynı dizinde başlayacaktır. Bu ayar muhtemelen sadece macOS üzerinde bir fark meydana getirecektir.</p></body></html>" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index bde9a4f51..687186f56 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -306,18 +306,12 @@ msgstr "OK" msgid "Cancel" msgstr "Відміна" -msgid "Save these settings as &global defaults" -msgstr "Зберегти ці параметри як &глобальні за замовчуванням" - msgid "&Default" msgstr "&За замовчуванням" msgid "Language:" msgstr "Мова:" -msgid "Icon set:" -msgstr "Набір іконок:" - msgid "Gain" msgstr "Посилення" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "КБ" -msgid "Could not initialize the video renderer." -msgstr "Не вдалося ініціалізувати рендер відео." - msgid "Default" msgstr "За замовчуванням" @@ -906,9 +897,6 @@ msgstr "Монітор у сплячому режимі" msgid "OpenGL Shaders" msgstr "Шейдери OpenGL" -msgid "OpenGL options" -msgstr "Параметри OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Ви завантажуєте непідтримувану конфігурацію" @@ -930,12 +918,6 @@ msgstr "Картридж %i: %ls" msgid "Cartridge images" msgstr "Образи картриджів" -msgid "Error initializing renderer" -msgstr "Помилка ініціалізації рендерера" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Неможливо ініціалізувати рендерер OpenGL (3.0). Будь ласка, використовуйте інший рендерер." - msgid "Resume execution" msgstr "Відновити виконання" @@ -1293,21 +1275,6 @@ msgstr "Нульовий драйвер" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Помилка відкриття \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Помилка компіляції вершинного шейдера у файлі \"%1\"." - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Помилка компіляції фрагментного шейдера у файлі \"%1\"." - -msgid "Error linking shader program in file \"%1\"" -msgstr "Помилка зв'язування шейдерної програми у файлі \"%1\"." - -msgid "OpenGL 3.0 renderer options" -msgstr "Параметри рендерингу OpenGL 3.0" - msgid "Render behavior" msgstr "Поведінка рендерингу" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Відображати кожен кадр миттєво, синхронно з емульованим дисплеєм.</p><p><span style=" font-style:italic;">Це рекомендований варіант, якщо використовувані шейдери не використовують час кадру для анімованих ефектів.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Синхронізація з відео" @@ -1332,21 +1296,9 @@ msgstr "Шейдери" msgid "Remove" msgstr "Видалити" -msgid "No shader selected" -msgstr "Не вибрано шейдер" - msgid "Browse..." msgstr "Переглянути..." -msgid "Shader error" -msgstr "Помилка шейдеру" - -msgid "Could not load shaders." -msgstr "Не вдалося завантажити шейдери." - -msgid "More information in details." -msgstr "Більше інформації в деталях." - msgid "Couldn't create OpenGL context." msgstr "Не вдалося створити контекст OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Не вдалося переключитися на контекст Ope msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "Потрібна версія OpenGL 3.0 або новіша. Поточна версія %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Не вдалося ініціалізувати OpenGL. Помилка %1." - msgid "Error initializing OpenGL" msgstr "Помилка ініціалізації OpenGL" msgid "Falling back to software rendering.\n" msgstr "Повернення до програмного рендерингу.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Не вдалося виділити пам'ять для буфера розпакування.\n" - msgid "<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>" msgstr "<html><head/><body><p>При виборі медіа-образів (CD-ROM, дискета і т.д.) діалогове вікно буде відкриватися в тому ж каталозі, що і файл конфігурації 86Box. Цей параметр, швидше за все, матиме значення лише на macOS.</p></body></html>" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index fa9384d8f..55a70991c 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -306,18 +306,12 @@ msgstr "Đồng ý" msgid "Cancel" msgstr "Thôi" -msgid "Save these settings as &global defaults" -msgstr "Lưu cài đặt làm mặc định chung" - msgid "&Default" msgstr "&Mặc định" msgid "Language:" msgstr "Ngôn ngữ:" -msgid "Icon set:" -msgstr "Bộ biểu tượng:" - msgid "Gain" msgstr "Tăng" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "Không thể khởi tạo trình kết xuất (renderer) video ." - msgid "Default" msgstr "Mặc định" @@ -906,9 +897,6 @@ msgstr "Màn hình chế độ chờ/ngủ" msgid "OpenGL Shaders" msgstr "Shader OpenGL" -msgid "OpenGL options" -msgstr "Tùy chọn OpenGL" - msgid "You are loading an unsupported configuration" msgstr "Bạn đang load tinh chỉnh không được hỗ trợ." @@ -930,12 +918,6 @@ msgstr "Băng cartridge %i: %ls" msgid "Cartridge images" msgstr "Ảnh đĩa băng cartridge" -msgid "Error initializing renderer" -msgstr "Lỗi khởi tạo renderer (trình kết xuất)" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "Không khởi tạo được renderer OpenGL (3.0 Core). Hãy dùng renderer khác." - msgid "Resume execution" msgstr "Tiếp tục chạy thực thi" @@ -1293,21 +1275,6 @@ msgstr "Trình điều khiển NULL" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i ( %ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "Mở lỗi \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "Lỗi biên dịch shader đỉnh trong tệp \"%1\"" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "Lỗi biên dịch shader fragment trong tệp \"%1\"" - -msgid "Error linking shader program in file \"%1\"" -msgstr "Lỗi liên kết chương trình shader trong tệp \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "Tùy chọn kết xuất OpenGL 3.0" - msgid "Render behavior" msgstr "Hành vi kết xuất" @@ -1320,9 +1287,6 @@ msgstr " khung hình / giây" msgid "VSync" msgstr "Vsync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không tối ưu frametime cho các hiệu ứng động.</span></p></body></html>" - msgid "Synchronize with video" msgstr "Đồng bộ với video" @@ -1332,21 +1296,9 @@ msgstr "Shaders" msgid "Remove" msgstr "Loại bỏ" -msgid "No shader selected" -msgstr "Không có shader được chọn" - msgid "Browse..." msgstr "Duyệt..." -msgid "Shader error" -msgstr "Lỗi shader" - -msgid "Could not load shaders." -msgstr "Không thể tải shader." - -msgid "More information in details." -msgstr "Thêm thông tin chi tiết." - msgid "Couldn't create OpenGL context." msgstr "Không thể tạo bối cảnh OpenGL." @@ -1356,18 +1308,12 @@ msgstr "Không thể chuyển sang bối cảnh OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGL phiên bản 3.0 trở lên là bắt buộc. Phiên bản hiện tại là %1. %2" -msgid "OpenGL initialization failed. Error %1." -msgstr "Khởi tạo OpenGL không thành công. Lỗi %1." - msgid "Error initializing OpenGL" msgstr "Lỗi khởi tạo OpenGL" msgid "Falling back to software rendering.\n" msgstr "Quay trở lại kết xuất phần mềm.\n" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "Phân bổ bộ nhớ cho bộ đệm giải nén không thành công.\n" - msgid "<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>" msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 4cccc071a..cd720c0ee 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -306,18 +306,12 @@ msgstr "确定" msgid "Cancel" msgstr "取消" -msgid "Save these settings as &global defaults" -msgstr "将以上设置存储为全局默认值(&G)" - msgid "&Default" msgstr "默认(&D)" msgid "Language:" msgstr "语言:" -msgid "Icon set:" -msgstr "图标集:" - msgid "Gain" msgstr "增益" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "无法初始化视频渲染器。" - msgid "Default" msgstr "默认" @@ -906,9 +897,6 @@ msgstr "显示器处在睡眠状态" msgid "OpenGL Shaders" msgstr "OpenGL 着色器" -msgid "OpenGL options" -msgstr "OpenGL 选项" - msgid "You are loading an unsupported configuration" msgstr "正在载入一个不受支持的配置" @@ -930,12 +918,6 @@ msgstr "卡带 %i: %ls" msgid "Cartridge images" msgstr "卡带映像" -msgid "Error initializing renderer" -msgstr "初始化渲染器时出错" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "无法初始化 OpenGL (3.0 Core) 渲染器。请使用其他渲染器。" - msgid "Resume execution" msgstr "恢复执行" @@ -1293,21 +1275,6 @@ msgstr "空驱动程序" msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "打开 \"%1\": %2 时出错" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "文件 \"%1\" 中的顶点着色器编译出错" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "文件 \"%1\" 中的片段着色器编译出错" - -msgid "Error linking shader program in file \"%1\"" -msgstr "文件 \"%1\" 中的着色器程序链接出错" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 渲染器选项" - msgid "Render behavior" msgstr "渲染行为" @@ -1320,9 +1287,6 @@ msgstr " fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>与模拟显示同步,即时渲染每一帧。</p><p><span style=" font-style:italic;">如果使用的着色器不使用帧时间来产生动画效果,则建议使用此选项。</span></p></body></html>" - msgid "Synchronize with video" msgstr "与视频同步" @@ -1332,21 +1296,9 @@ msgstr "着色器" msgid "Remove" msgstr "移除" -msgid "No shader selected" -msgstr "未选择着色器" - msgid "Browse..." msgstr "浏览..." -msgid "Shader error" -msgstr "着色器错误" - -msgid "Could not load shaders." -msgstr "无法加载着色器。" - -msgid "More information in details." -msgstr "更多详细信息。" - msgid "Couldn't create OpenGL context." msgstr "无法创建 OpenGL 上下文。" @@ -1356,18 +1308,12 @@ msgstr "无法切换到 OpenGL 上下文。" msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "需要 OpenGL 3.0 或更高版本。当前版本为 %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL 初始化失败。错误 %1." - msgid "Error initializing OpenGL" msgstr "初始化 OpenGL 时出错" msgid "Falling back to software rendering.\n" msgstr "回到软件渲染。" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "为解包缓冲区分配内存失败.\n" - msgid "<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>" msgstr "<html><head/><body><p>选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。</p></body></html>;" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 92c6502ea..a11ef8d44 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -306,18 +306,12 @@ msgstr "確定" msgid "Cancel" msgstr "取消" -msgid "Save these settings as &global defaults" -msgstr "將以上設定存儲為全局預設值(&G)" - msgid "&Default" msgstr "預設(&D)" msgid "Language:" msgstr "語言:" -msgid "Icon set:" -msgstr "圖示集:" - msgid "Gain" msgstr "增益" @@ -753,9 +747,6 @@ msgstr "S" msgid "KB" msgstr "KB" -msgid "Could not initialize the video renderer." -msgstr "無法初始化視訊渲染器。" - msgid "Default" msgstr "預設" @@ -906,9 +897,6 @@ msgstr "顯示器處在睡眠狀態" msgid "OpenGL Shaders" msgstr "OpenGL 著色器" -msgid "OpenGL options" -msgstr "OpenGL 選項" - msgid "You are loading an unsupported configuration" msgstr "正在載入一個不受支援的設定" @@ -930,12 +918,6 @@ msgstr "卡帶 %i: %ls" msgid "Cartridge images" msgstr "卡帶映像" -msgid "Error initializing renderer" -msgstr "初始化渲染器時出錯" - -msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "無法初始化 OpenGL (3.0 Core) 渲染器。請使用其他渲染器。" - msgid "Resume execution" msgstr "恢復執行" @@ -1293,21 +1275,6 @@ msgstr "空驅動程式" msgid "NIC %02i (%ls) %ls" msgstr "網路卡 %02i (%ls) %ls" -msgid "Error opening \"%1\": %2" -msgstr "錯誤開啟 \"%1\": %2" - -msgid "Error compiling vertex shader in file \"%1\"" -msgstr "編譯檔案 \"%1\" 中的頂點著色器時發生錯誤" - -msgid "Error compiling fragment shader in file \"%1\"" -msgstr "編譯檔案 \"%1\" 中的片段著色器出錯" - -msgid "Error linking shader program in file \"%1\"" -msgstr "在檔案中連結shader程式出錯 \"%1\"" - -msgid "OpenGL 3.0 renderer options" -msgstr "OpenGL 3.0 渲染器選項" - msgid "Render behavior" msgstr "渲染行為" @@ -1320,9 +1287,6 @@ msgstr "fps" msgid "VSync" msgstr "VSync" -msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>" -msgstr "<html><head/><body><p>立即渲染每個畫面,與模擬顯示同步。</p><p><span style=" font-style:italic;">如果使用中的著色器不利用影格時間製作動畫效果,建議使用此選項。</span></p></body></html>" - msgid "Synchronize with video" msgstr "與視訊同步" @@ -1332,21 +1296,9 @@ msgstr "著色器" msgid "Remove" msgstr "移除" -msgid "No shader selected" -msgstr "未選擇著色器" - msgid "Browse..." msgstr "瀏覽..." -msgid "Shader error" -msgstr "著色器錯誤" - -msgid "Could not load shaders." -msgstr "無法載入著色器。" - -msgid "More information in details." -msgstr "更多詳細資訊。" - msgid "Couldn't create OpenGL context." msgstr "無法建立 OpenGL 上下文。" @@ -1356,18 +1308,12 @@ msgstr "無法切換至 OpenGL 上下文。" msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "需要 OpenGL 版本 3.0 或更高。目前版本為 %1.%2" -msgid "OpenGL initialization failed. Error %1." -msgstr "OpenGL 初始化失敗。錯誤 %1." - msgid "Error initializing OpenGL" msgstr "初始化 OpenGL 出錯" msgid "Falling back to software rendering.\n" msgstr "回退到軟體渲染。" -msgid "Allocating memory for unpack buffer failed.\n" -msgstr "為解除封包緩衝區分配記憶體失敗。\n" - msgid "<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>" msgstr "<html><head/><body><p>當選擇媒體映像 (CD-ROM、軟碟等) 時,開啟對話方塊會在與 86Box 設定檔相同的目錄中開始。此設定可能只會在 macOS 上有所影響。</p></body></html>" From c08775becfd721f587c3196b2a3b4d1378646e99 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 7 Apr 2025 19:50:42 +0500 Subject: [PATCH 0702/1190] qt: Use `util::DlgFilter` for the shader picker Also fix the translation for its filter --- src/qt/languages/86box.pot | 2 +- src/qt/languages/ca-ES.po | 4 ++-- src/qt/languages/cs-CZ.po | 4 ++-- src/qt/languages/de-DE.po | 4 ++-- src/qt/languages/es-ES.po | 4 ++-- src/qt/languages/fi-FI.po | 4 ++-- src/qt/languages/fr-FR.po | 4 ++-- src/qt/languages/hr-HR.po | 4 ++-- src/qt/languages/hu-HU.po | 4 ++-- src/qt/languages/it-IT.po | 4 ++-- src/qt/languages/ja-JP.po | 4 ++-- src/qt/languages/ko-KR.po | 4 ++-- src/qt/languages/nl-NL.po | 4 ++-- src/qt/languages/pl-PL.po | 4 ++-- src/qt/languages/pt-BR.po | 4 ++-- src/qt/languages/pt-PT.po | 4 ++-- src/qt/languages/ru-RU.po | 4 ++-- src/qt/languages/sk-SK.po | 4 ++-- src/qt/languages/sl-SI.po | 4 ++-- src/qt/languages/tr-TR.po | 4 ++-- src/qt/languages/uk-UA.po | 4 ++-- src/qt/languages/vi-VN.po | 4 ++-- src/qt/languages/zh-CN.po | 4 ++-- src/qt/languages/zh-TW.po | 4 ++-- src/qt/qt_openglshadermanagerdialog.cpp | 5 ++++- 25 files changed, 51 insertions(+), 48 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 15c605449..264060afe 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -894,7 +894,7 @@ msgstr "" msgid "Monitor in sleep mode" msgstr "" -msgid "OpenGL Shaders" +msgid "GLSL shaders" msgstr "" msgid "You are loading an unsupported configuration" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 26e51fe68..1d03316b6 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -894,8 +894,8 @@ msgstr "Configuració de Dispositiu %1" msgid "Monitor in sleep mode" msgstr "Monitor en mode estalvi" -msgid "OpenGL Shaders" -msgstr "Shaders OpenGL" +msgid "GLSL shaders" +msgstr "Shaders GLSL" msgid "You are loading an unsupported configuration" msgstr "S'està carregant una configuració no suportada" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 099245033..a5378a978 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -894,8 +894,8 @@ msgstr "Nastavení zařízení %1" msgid "Monitor in sleep mode" msgstr "Monitor je v režimu spánku" -msgid "OpenGL Shaders" -msgstr "Shadery OpenGL" +msgid "GLSL shaders" +msgstr "Shadery GLSL" msgid "You are loading an unsupported configuration" msgstr "Pokoušíte se spustit nepodporovanou konfiguraci" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index eae29f084..c3ca0953a 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -897,8 +897,8 @@ msgstr "%1-Gerätekonfiguration" msgid "Monitor in sleep mode" msgstr "Monitor im Standbymodus" -msgid "OpenGL Shaders" -msgstr "OpenGL-Shader" +msgid "GLSL shaders" +msgstr "GLSL-Shader" msgid "You are loading an unsupported configuration" msgstr "Zur Zeit wird eine nicht unterstützte Konfiguration geladen" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 14d6a6383..20a6eb351 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -894,8 +894,8 @@ msgstr "%1 Configuración de Dispositivo" msgid "Monitor in sleep mode" msgstr "Monitor en modo ahorro" -msgid "OpenGL Shaders" -msgstr "Shaders OpenGL" +msgid "GLSL shaders" +msgstr "Shaders GLSL" msgid "You are loading an unsupported configuration" msgstr "Está cargando una configuración no soportada" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 1408522fc..e12e27db4 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -894,8 +894,8 @@ msgstr "%1 - Laitteen määritykset" msgid "Monitor in sleep mode" msgstr "Näyttö lepotilassa" -msgid "OpenGL Shaders" -msgstr "OpenGL-varjostinohjelmat" +msgid "GLSL shaders" +msgstr "GLSL-varjostinohjelmat" msgid "You are loading an unsupported configuration" msgstr "Olet lataamassa ei-tuettuja määrittelyjä" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 829a9658b..8900dbf2d 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -894,8 +894,8 @@ msgstr "Configuration du dispositif %1" msgid "Monitor in sleep mode" msgstr "Moniteur en mode veille" -msgid "OpenGL Shaders" -msgstr "Shaders OpenGL" +msgid "GLSL shaders" +msgstr "Shaders GLSL" msgid "You are loading an unsupported configuration" msgstr "Vous chargez une configuration non prise en charge" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 6ca3ad8f5..ffa21efd1 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -894,8 +894,8 @@ msgstr "Konfiguracija uređaja %1" msgid "Monitor in sleep mode" msgstr "Ekran u stanju mirovanja" -msgid "OpenGL Shaders" -msgstr "OpenGL shaderi" +msgid "GLSL shaders" +msgstr "GLSL shaderi" msgid "You are loading an unsupported configuration" msgstr "Učitavate nepodržanu konfiguraciju" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 7d6a434f7..bbcfbd814 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -894,8 +894,8 @@ msgstr "%1 eszközkonfiguráció" msgid "Monitor in sleep mode" msgstr "Képernyő alvó módban" -msgid "OpenGL Shaders" -msgstr "OpenGL Shaderek" +msgid "GLSL shaders" +msgstr "GLSL shaderek" msgid "You are loading an unsupported configuration" msgstr "Egy nem támogatott konfigurációt tölt be" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 256337a0d..8c2322bb0 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -894,8 +894,8 @@ msgstr "Configurazione del dispositivo %1" msgid "Monitor in sleep mode" msgstr "Monitor in modalità riposo" -msgid "OpenGL Shaders" -msgstr "Shader OpenGL" +msgid "GLSL shaders" +msgstr "Shader GLSL" msgid "You are loading an unsupported configuration" msgstr "Stai caricando una configurazione non supportata" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index d38760f15..03c1f5fdc 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -894,8 +894,8 @@ msgstr "%1 のデバイス設定" msgid "Monitor in sleep mode" msgstr "モニターのスリープモード" -msgid "OpenGL Shaders" -msgstr "OpenGLシェーダー" +msgid "GLSL shaders" +msgstr "GLSLシェーダー" msgid "You are loading an unsupported configuration" msgstr "サポートされていないコンフィグを読み込んでいます" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index dbf77106b..ee2e5db5f 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -894,8 +894,8 @@ msgstr "%1 장치 설정" msgid "Monitor in sleep mode" msgstr "모니터 절전 모드" -msgid "OpenGL Shaders" -msgstr "OpenGL 쉐이더" +msgid "GLSL shaders" +msgstr "GLSL 쉐이더" msgid "You are loading an unsupported configuration" msgstr "지원하지 않는 설정입니다" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 65e59331b..3e95f69de 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -894,8 +894,8 @@ msgstr "%1 Apparaatconfiguratie" msgid "Monitor in sleep mode" msgstr "Monitor in slaapstand" -msgid "OpenGL Shaders" -msgstr "OpenGL Shaders" +msgid "GLSL shaders" +msgstr "GLSL Shaders" msgid "You are loading an unsupported configuration" msgstr "U laadt een configuratie die niet wordt ondersteund" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index bed21af24..472c29d41 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -894,8 +894,8 @@ msgstr "Konfiguracja urządzenia %1" msgid "Monitor in sleep mode" msgstr "Monitor w trybie czuwania" -msgid "OpenGL Shaders" -msgstr "Shadery OpenGL" +msgid "GLSL shaders" +msgstr "Shadery GLSL" msgid "You are loading an unsupported configuration" msgstr "Ładujesz nieobsługiwaną konfigurację" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index df606a635..b9c391083 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -894,8 +894,8 @@ msgstr "Configuração do dispositivo %1" msgid "Monitor in sleep mode" msgstr "Monitor em modo de suspensão" -msgid "OpenGL Shaders" -msgstr "Shaders OpenGL" +msgid "GLSL shaders" +msgstr "Shaders GLSL" msgid "You are loading an unsupported configuration" msgstr "Você está carregando uma configuração não suportada" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index b3458bcdf..a9c6a6810 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -894,8 +894,8 @@ msgstr "Configuração de dispositivo %1" msgid "Monitor in sleep mode" msgstr "Ecrã em modo de sono" -msgid "OpenGL Shaders" -msgstr "Shaders OpenGL" +msgid "GLSL shaders" +msgstr "Shaders GLSL" msgid "You are loading an unsupported configuration" msgstr "Está a carregar uma configuração sem suporte!" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 6104d064f..9bf253eca 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -894,8 +894,8 @@ msgstr "Конфигурация устройства %1" msgid "Monitor in sleep mode" msgstr "Монитор в спящем режиме" -msgid "OpenGL Shaders" -msgstr "Шейдеры OpenGL" +msgid "GLSL shaders" +msgstr "Шейдеры GLSL" msgid "You are loading an unsupported configuration" msgstr "Вы загружаете неподдерживаемую конфигурацию" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 9e6532267..172332178 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -894,8 +894,8 @@ msgstr "Konfigurácia zariadenia %1" msgid "Monitor in sleep mode" msgstr "Monitor je v režime spánku" -msgid "OpenGL Shaders" -msgstr "Shadery OpenGL" +msgid "GLSL shaders" +msgstr "Shadery GLSL" msgid "You are loading an unsupported configuration" msgstr "Pokúšate sa spustiť nepodporovanú konfiguráciu" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index efb62153a..3ca041b7c 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -894,8 +894,8 @@ msgstr "Konfiguracija naprave %1" msgid "Monitor in sleep mode" msgstr "Zaslon v načinu spanja" -msgid "OpenGL Shaders" -msgstr "Senčilniki OpenGL" +msgid "GLSL shaders" +msgstr "Senčilniki GLSL" msgid "You are loading an unsupported configuration" msgstr "Nalagate nepodprto konfiguracijo" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index e3d692537..0408a5cbe 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -894,8 +894,8 @@ msgstr "%1 cihaz konfigürasyonu" msgid "Monitor in sleep mode" msgstr "Monitör uyku modunda" -msgid "OpenGL Shaders" -msgstr "OpenGL gölgelendiricileri" +msgid "GLSL shaders" +msgstr "GLSL gölgelendiricileri" msgid "You are loading an unsupported configuration" msgstr "Desteklenmeyen bir konfigürasyon kullanıyorsunuz" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 687186f56..641c454ce 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -894,8 +894,8 @@ msgstr "Конфігурація пристрою %1" msgid "Monitor in sleep mode" msgstr "Монітор у сплячому режимі" -msgid "OpenGL Shaders" -msgstr "Шейдери OpenGL" +msgid "GLSL shaders" +msgstr "Шейдери GLSL" msgid "You are loading an unsupported configuration" msgstr "Ви завантажуєте непідтримувану конфігурацію" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 55a70991c..ce2967007 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -894,8 +894,8 @@ msgstr "Tinh chỉnh thiết bị %1" msgid "Monitor in sleep mode" msgstr "Màn hình chế độ chờ/ngủ" -msgid "OpenGL Shaders" -msgstr "Shader OpenGL" +msgid "GLSL shaders" +msgstr "Shader GLSL" msgid "You are loading an unsupported configuration" msgstr "Bạn đang load tinh chỉnh không được hỗ trợ." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index cd720c0ee..f30dc48f3 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -894,8 +894,8 @@ msgstr "%1 设备配置" msgid "Monitor in sleep mode" msgstr "显示器处在睡眠状态" -msgid "OpenGL Shaders" -msgstr "OpenGL 着色器" +msgid "GLSL shaders" +msgstr "GLSL 着色器" msgid "You are loading an unsupported configuration" msgstr "正在载入一个不受支持的配置" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index a11ef8d44..9116bf09d 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -894,8 +894,8 @@ msgstr "%1 裝置設定" msgid "Monitor in sleep mode" msgstr "顯示器處在睡眠狀態" -msgid "OpenGL Shaders" -msgstr "OpenGL 著色器" +msgid "GLSL shaders" +msgstr "GLSL 著色器" msgid "You are loading an unsupported configuration" msgstr "正在載入一個不受支援的設定" diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 72f58f9cb..2a03b46f7 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -2,6 +2,7 @@ #include "ui_qt_openglshadermanagerdialog.h" #include "qt_mainwindow.hpp" +#include "qt_util.hpp" extern MainWindow* main_window; #include "qt_openglshaderconfig.hpp" @@ -9,6 +10,7 @@ extern MainWindow* main_window; #include #include #include +#include extern "C" { #include <86box/86box.h> @@ -166,7 +168,8 @@ void OpenGLShaderManagerDialog::on_buttonMoveDown_clicked() void OpenGLShaderManagerDialog::on_buttonAdd_clicked() { - auto res = QFileDialog::getOpenFileName(this, QString(), QString(), "GLSL Shaders (*.glslp *.glsl);;All files (*.*)"); + auto res = QFileDialog::getOpenFileName(this, QString(), QString(), + tr("GLSL shaders") % util::DlgFilter({ "glslp", "glsl" }) % tr("All files") % util::DlgFilter({ "*" }, true)); if (!res.isEmpty()) { auto glslp_file = res.toUtf8(); glslp_t* shaderfile = glslp_parse(glslp_file.data()); From f16265e2a418cab4f10ffc63527aaa5944c4faee Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 7 Apr 2025 19:55:07 +0500 Subject: [PATCH 0703/1190] qt: Remove the translation for the LBA Enhancer It wasn't supposed to be translated due to being a company name and a product name --- src/qt/languages/86box.pot | 3 --- src/qt/languages/ca-ES.po | 3 --- src/qt/languages/cs-CZ.po | 3 --- src/qt/languages/de-DE.po | 3 --- src/qt/languages/es-ES.po | 3 --- src/qt/languages/fi-FI.po | 3 --- src/qt/languages/fr-FR.po | 3 --- src/qt/languages/hr-HR.po | 3 --- src/qt/languages/hu-HU.po | 3 --- src/qt/languages/it-IT.po | 3 --- src/qt/languages/ja-JP.po | 3 --- src/qt/languages/ko-KR.po | 3 --- src/qt/languages/nl-NL.po | 3 --- src/qt/languages/pl-PL.po | 3 --- src/qt/languages/pt-BR.po | 3 --- src/qt/languages/pt-PT.po | 3 --- src/qt/languages/ru-RU.po | 3 --- src/qt/languages/sk-SK.po | 3 --- src/qt/languages/sl-SI.po | 3 --- src/qt/languages/tr-TR.po | 3 --- src/qt/languages/uk-UA.po | 3 --- src/qt/languages/vi-VN.po | 3 --- src/qt/languages/zh-CN.po | 3 --- src/qt/languages/zh-TW.po | 3 --- 24 files changed, 72 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 264060afe..a2eb3c4c3 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -1380,9 +1380,6 @@ msgstr "" msgid "Serial port passthrough 4" msgstr "" -msgid "Vision Systems LBA Enhancer" -msgstr "" - msgid "Renderer options..." msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 1d03316b6..64e314124 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -1380,9 +1380,6 @@ msgstr "Pas del port sèrie 3" msgid "Serial port passthrough 4" msgstr "Pas del port sèrie 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Opcions del renderitzador ..." diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index a5378a978..fcc6e7baf 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -1380,9 +1380,6 @@ msgstr "Průchod sériového portu 3" msgid "Serial port passthrough 4" msgstr "Průchod sériového portu 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Možnosti vykreslovače..." diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index c3ca0953a..12ec816be 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1383,9 +1383,6 @@ msgstr "Durchreichung der Serielle Schnittstelle 3" msgid "Serial port passthrough 4" msgstr "Durchreichung der Serielle Schnittstelle 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Renderer-Optionen..." diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 20a6eb351..9eb413d12 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -1379,9 +1379,6 @@ msgstr "Paso de puerto serie 3" msgid "Serial port passthrough 4" msgstr "Paso de puerto serie 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Opciones del renderizador..." diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index e12e27db4..19b0c1ae1 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -1383,9 +1383,6 @@ msgstr "Sarjaportin läpivienti 3" msgid "Serial port passthrough 4" msgstr "Sarjaportin läpivienti 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Alustusasetukset..." diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 8900dbf2d..1636356e2 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -1380,9 +1380,6 @@ msgstr "Passage du port série 3" msgid "Serial port passthrough 4" msgstr "Passage du port série 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Options de rendu..." diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index ffa21efd1..f30d973e2 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -1380,9 +1380,6 @@ msgstr "Prolaz serijskih vrata 3" msgid "Serial port passthrough 4" msgstr "Prolaz serijskih vrata 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Opcije rendera..." diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index bbcfbd814..7dc86fd66 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -1380,9 +1380,6 @@ msgstr "Soros port áthaladás 3" msgid "Serial port passthrough 4" msgstr "Soros port áthaladás 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Renderer opciók..." diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 8c2322bb0..7e91d6f8f 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -1380,9 +1380,6 @@ msgstr "Passaggio della porta seriale 3" msgid "Serial port passthrough 4" msgstr "Passaggio della porta seriale 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Opzioni del renderer..." diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 03c1f5fdc..7bd0eb2db 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -1380,9 +1380,6 @@ msgstr "シリアル・ポート・パススルー 3" msgid "Serial port passthrough 4" msgstr "シリアル・ポート・パススルー 4" -msgid "Vision Systems LBA Enhancer" -msgstr "ビジョン・システムズ LBAエンハンサー" - msgid "Renderer options..." msgstr "レンダラー設定..." diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index ee2e5db5f..3650bd39e 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -1380,9 +1380,6 @@ msgstr "직렬 포트 패스스루 3" msgid "Serial port passthrough 4" msgstr "직렬 포트 패스스루 4" -msgid "Vision Systems LBA Enhancer" -msgstr "비전 시스템 LBA 인핸서" - msgid "Renderer options..." msgstr "렌더러 옵션..." diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 3e95f69de..54e3422ea 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -1380,9 +1380,6 @@ msgstr "Seriële poort doorvoer 3" msgid "Serial port passthrough 4" msgstr "Seriële poort doorvoer 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Renderer-opties..." diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 472c29d41..0e00ea6be 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -1380,9 +1380,6 @@ msgstr "Przełączanie portu szeregowego 3" msgid "Serial port passthrough 4" msgstr "Przełączanie portu szeregowego 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Opcje renderowania..." diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index b9c391083..d7092c6d0 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -1380,9 +1380,6 @@ msgstr "Passagem de porta serial 3" msgid "Serial port passthrough 4" msgstr "Passagem de porta serial 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Opções do renderizador..." diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index a9c6a6810..e04d93c54 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -1380,9 +1380,6 @@ msgstr "Passagem da porta de série 3" msgid "Serial port passthrough 4" msgstr "Passagem da porta de série 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Sistemas de visão Melhorador LBA" - msgid "Renderer options..." msgstr "Opções do renderizador..." diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 9bf253eca..a67583a74 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1380,9 +1380,6 @@ msgstr "Сквозной последовательный порт COM3" msgid "Serial port passthrough 4" msgstr "Сквозной последовательный порт COM4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Параметры рендеринга..." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 172332178..f976147b8 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -1381,9 +1381,6 @@ msgstr "Priechod sériového portu 3" msgid "Serial port passthrough 4" msgstr "Priechod cez sériový port 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Možnosti vykresľovača..." diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 3ca041b7c..7022ad7b0 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -1380,9 +1380,6 @@ msgstr "Prepust za serijska vrata 3" msgid "Serial port passthrough 4" msgstr "Prepust za serijska vrata 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Možnosti sistema za upodabljanje..." diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 0408a5cbe..6f8359823 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -1380,9 +1380,6 @@ msgstr "Seri port geçişi 3" msgid "Serial port passthrough 4" msgstr "Seri port geçişi 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "İşleyici seçenekleri..." diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 641c454ce..c42e72e2b 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -1380,9 +1380,6 @@ msgstr "Пропуск послідовного порту 3" msgid "Serial port passthrough 4" msgstr "Пропуск послідовного порту 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Параметри рендерингу..." diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index ce2967007..dacd8efac 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -1380,9 +1380,6 @@ msgstr "Thông qua cổng serial 3" msgid "Serial port passthrough 4" msgstr "Thông qua cổng serial 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "Tùy chọn kết xuất ..." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index f30dc48f3..1a78b8abc 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1380,9 +1380,6 @@ msgstr "串行端口直通 3" msgid "Serial port passthrough 4" msgstr "串行端口直通 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA 增强器" - msgid "Renderer options..." msgstr "渲染器选项..." diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 9116bf09d..a9e73c563 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -1380,9 +1380,6 @@ msgstr "序列埠的直通 3" msgid "Serial port passthrough 4" msgstr "序列埠的直通 4" -msgid "Vision Systems LBA Enhancer" -msgstr "Vision Systems LBA Enhancer" - msgid "Renderer options..." msgstr "渲染器選項..." From bc8aae429ec6398b4f79a18cfe294192756f4357 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 7 Apr 2025 19:57:18 +0500 Subject: [PATCH 0704/1190] qt: Update the British English translation More ize -> ise spelling changes --- src/qt/languages/en-GB.po | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index b9f79882f..6043c10d9 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -15,18 +15,30 @@ msgstr "&RGB Greyscale" msgid "Time synchronization" msgstr "Time synchronisation" +msgid "Unable to initialize Ghostscript" +msgstr "Unable to initialise Ghostscript" + +msgid "Unable to initialize GhostPCL" +msgstr "Unable to initialise GhostPCL" + msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behaviour will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." msgid "Apply fullscreen stretch mode when maximized" msgstr "Apply fullscreen stretch mode when maximised" +msgid "Failed to initialize network driver" +msgstr "Failed to initialise network driver" + msgid "Render behavior" msgstr "Render behaviour" msgid "Synchronize with video" msgstr "Synchronise with video" +msgid "Error initializing OpenGL" +msgstr "Error initialising OpenGL" + msgid "<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>" msgstr "<html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialogue will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html>" From 890362131d1953f108a74dcf34a119732d26f334 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 8 Apr 2025 11:57:33 +0500 Subject: [PATCH 0705/1190] qt: Fix translations for "Falling back to software renderer" --- src/qt/languages/86box.pot | 2 +- src/qt/languages/ca-ES.po | 4 ++-- src/qt/languages/cs-CZ.po | 4 ++-- src/qt/languages/de-DE.po | 4 ++-- src/qt/languages/es-ES.po | 4 ++-- src/qt/languages/fi-FI.po | 4 ++-- src/qt/languages/fr-FR.po | 4 ++-- src/qt/languages/hr-HR.po | 4 ++-- src/qt/languages/hu-HU.po | 4 ++-- src/qt/languages/it-IT.po | 4 ++-- src/qt/languages/ja-JP.po | 4 ++-- src/qt/languages/ko-KR.po | 4 ++-- src/qt/languages/nl-NL.po | 4 ++-- src/qt/languages/pl-PL.po | 4 ++-- src/qt/languages/pt-BR.po | 4 ++-- src/qt/languages/pt-PT.po | 4 ++-- src/qt/languages/ru-RU.po | 4 ++-- src/qt/languages/sk-SK.po | 4 ++-- src/qt/languages/sl-SI.po | 4 ++-- src/qt/languages/tr-TR.po | 4 ++-- src/qt/languages/uk-UA.po | 4 ++-- src/qt/languages/vi-VN.po | 4 ++-- src/qt/languages/zh-CN.po | 4 ++-- src/qt/languages/zh-TW.po | 4 ++-- src/qt/qt_rendererstack.cpp | 2 +- 25 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index a2eb3c4c3..83e021d2a 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -1311,7 +1311,7 @@ msgstr "" msgid "Error initializing OpenGL" msgstr "" -msgid "Falling back to software rendering.\n" +msgid "\nFalling back to software rendering." msgstr "" msgid "<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>" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 64e314124..48c2a777d 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -1311,8 +1311,8 @@ msgstr "Es requereix la versió 3.0 o superior d'OpenGL. La versió actual és % msgid "Error initializing OpenGL" msgstr "Error en inicialitzar OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Tornant al renderitzador software.\n" +msgid "\nFalling back to software rendering." +msgstr "\nTornant al renderitzador software." msgid "<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>" msgstr "<html><head/><body><p>Quan seleccioneu imatges de suports (CD-ROM, disquet, etc.), el diàleg obert s’iniciarà al mateix directori que el fitxer de configuració 86Box. Aquesta configuració només farà una diferència en les macOS.</p></body></html>" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index fcc6e7baf..bcb7cc714 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -1311,8 +1311,8 @@ msgstr "Je vyžadována verze OpenGL 3.0 nebo vyšší. Aktuální verze je %1.% msgid "Error initializing OpenGL" msgstr "Chyba při inicializaci OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Návrat k softwarovému vykreslování.\n" +msgid "\nFalling back to software rendering." +msgstr "\nNávrat k softwarovému vykreslování." msgid "<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>" msgstr "<html><head/><body><p>Při výběru obrazů médií (CD-ROM, disketa atd.) se otevřené dialogové okno spustí ve stejném adresáři jako konfigurační soubor 86Box. Toto nastavení bude mít pravděpodobně význam pouze v systému MacOS.</p></body></html>" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 12ec816be..6255deef7 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1314,8 +1314,8 @@ msgstr "OpenGL-Version 3.0 oder höher ist erforderlich. Die aktuelle Version is msgid "Error initializing OpenGL" msgstr "Fehler beim Initialisieren von OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Rückgriff auf Software-Rendering.\n" +msgid "\nFalling back to software rendering." +msgstr "\nRückgriff auf Software-Rendering." msgid "<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>" msgstr "<html><head/><body><p>Bei der Auswahl von Medien-Abbildern (CD-ROM, Diskette usw.) wird der Öffnungsdialog im selben Verzeichnis wie die 86Box-Konfigurationsdatei gestartet. Diese Einstellung macht wahrscheinlich nur unter macOS einen Unterschied.</p></body></html>" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 9eb413d12..285809cc5 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -1310,8 +1310,8 @@ msgstr "Es requerida la versión 3.0 o más alta de OpenGL. La versión actual e msgid "Error initializing OpenGL" msgstr "Error al inicializar OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Recurrir al renderizado por software.\n" +msgid "\nFalling back to software rendering." +msgstr "\nRecurrir al renderizado por software." msgid "<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>" msgstr "<html><head/><body><p>Al seleccionar imágenes multimedia (CD-ROM, disquete, etc.), el diálogo de apertura se iniciará en el mismo directorio que el archivo de configuración de 86Box. Es probable que este ajuste sólo suponga una diferencia en macOS.</p></body></html>" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 19b0c1ae1..5419b9c5a 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -1314,8 +1314,8 @@ msgstr "Tarvitaan OpenGL-versio 3.0 tai uudempi. Nykyinen versio on %1.%2" msgid "Error initializing OpenGL" msgstr "Virhe OpenGL:n alustamisessa" -msgid "Falling back to software rendering.\n" -msgstr "Paluu ohjelmistoalustusöintiin.\n" +msgid "\nFalling back to software rendering." +msgstr "\nPaluu ohjelmistoalustusöintiin." msgid "<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>" msgstr "<html><head/><body><p>Kun valitset mediakuvia (CD-ROM, levykkeet jne.), avausikkuna käynnistyy samaan hakemistoon kuin 86Boxin konfigurointitiedosto. Tällä asetuksella on todennäköisesti merkitystä vain macOS-käyttöjärjestelmässä.</p></body></html>" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 1636356e2..39479b40f 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -1311,8 +1311,8 @@ msgstr "La version 3.0 ou supérieure d'OpenGL est requise. La version actuelle msgid "Error initializing OpenGL" msgstr "Erreur d'initialisation d'OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Se rabattre sur le rendu logiciel.\n" +msgid "\nFalling back to software rendering." +msgstr "\nSe rabattre sur le rendu logiciel." msgid "<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>" msgstr "<html><head/><body><p>Lors de la sélection d'images multimédia (CD-ROM, disquette, etc.), la boîte de dialogue d'ouverture démarrera dans le même répertoire que le fichier de configuration de 86Box. Ce paramètre ne fera probablement une différence que sur macOS.</p></body></html>" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index f30d973e2..634523c5c 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -1311,8 +1311,8 @@ msgstr "Potrebna je OpenGL verzija 3.0 ili više. Trenutna verzija je %1. %2" msgid "Error initializing OpenGL" msgstr "Nije moguće inicijalizirati OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Vraća se na softverski renderer.\n" +msgid "\nFalling back to software rendering." +msgstr "\nVraća se na softverski renderer." msgid "<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>" msgstr "<html><head/><body><p>Prilikom odabira medijskih slika (CD-ROM, diskete itd.), otvoreni dijalog zopočet će u istom direktoriju kao i konfiguracijska datoteka 86Box-a. Razlika će vjerojatno biti primjetna samo na macOS-u.</p></body></html>" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 7dc86fd66..db6354680 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -1311,8 +1311,8 @@ msgstr "Az OpenGL 3.0 vagy magasabb verziója szükséges. Az aktuális verzió msgid "Error initializing OpenGL" msgstr "Hiba az OpenGL inicializálásában" -msgid "Falling back to software rendering.\n" -msgstr "Visszatérés a szoftveres rendereléshez.\n" +msgid "\nFalling back to software rendering." +msgstr "\nVisszatérés a szoftveres rendereléshez." msgid "<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>" msgstr "<html><head/><body><p>A médiaképek (CD-ROM, floppy stb.) kiválasztásakor a megnyitási párbeszédpanel ugyanabban a könyvtárban indul, mint a 86Box konfigurációs fájl. Ez a beállítás valószínűleg csak a macOS rendszerben jelent különbséget.</p></body></html>" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 7e91d6f8f..effbee5bd 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -1311,8 +1311,8 @@ msgstr "È richiesta la versione OpenGL 3.0 o superiore. La versione attuale è msgid "Error initializing OpenGL" msgstr "Errore nell'inizializzazione di OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Ricaduta sul rendering software." +msgid "\nFalling back to software rendering." +msgstr "\nRicaduta sul rendering software." msgid "<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>" msgstr "<html><head/><body><p>Quando si selezionano immagini multimediali (CD-ROM, floppy, ecc.) la finestra di dialogo di apertura si avvia nella stessa directory del file di configurazione di 86Box. Questa impostazione probabilmente farà la differenza solo su macOS.</p></body></html>" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 7bd0eb2db..4ef8d01de 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -1311,8 +1311,8 @@ msgstr "OpenGLのバージョン3.0以上が必要です。現在のバージョ msgid "Error initializing OpenGL" msgstr "OpenGLの初期化エラー" -msgid "Falling back to software rendering.\n" -msgstr "ソフトウェアレンダリングに逆戻り。" +msgid "\nFalling back to software rendering." +msgstr "\nソフトウェアレンダリングに逆戻り。" msgid "<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>" msgstr "<html><head/><body><p>メディアイメージ(CD-ROM、フロッピーなど)を選択するとき、オープンダイアログは86Box設定ファイルと同じディレクトリで開始します。この設定は、おそらく macOS でのみ違いがあります。</p></body></html>" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 3650bd39e..e9e4b99e6 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -1311,8 +1311,8 @@ msgstr "OpenGL 버전 3.0 이상이 필요합니다. 현재 버전은 %1.%2입 msgid "Error initializing OpenGL" msgstr "OpenGL 초기화 중 오류 발생" -msgid "Falling back to software rendering.\n" -msgstr "소프트웨어 렌더링으로 돌아가기.\n" +msgid "\nFalling back to software rendering." +msgstr "\n소프트웨어 렌더링으로 돌아가기." msgid "<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>" msgstr "<html><head/><body><p>미디어 이미지(CD-ROM, 플로피 등)를 선택하면 86Box 구성 파일과 동일한 디렉터리에서 열기 대화 상자가 시작됩니다. 이 설정은 macOS에서만 차이가 있을 수 있습니다.</p></body></html>" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 54e3422ea..10e4c2bd2 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -1311,8 +1311,8 @@ msgstr "OpenGL versie 3.0 of hoger is vereist. De huidige versie is %1.%2" msgid "Error initializing OpenGL" msgstr "Fout bij het initialiseren van OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Terugvallen op software rendering.\n" +msgid "\nFalling back to software rendering." +msgstr "\nTerugvallen op software rendering." msgid "<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>" msgstr "<html><head/><body><p>Bij het selecteren van media-images (CD-ROM, floppy, etc.) zal de \"open dialoog\" starten in dezelfde map als het 86Box configuratiebestand. Deze instelling is doet er waarschijnlijk alleen toe op macOS.</p></body></html>" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 0e00ea6be..f8367176d 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -1311,8 +1311,8 @@ msgstr "Wymagana jest wersja OpenGL 3.0 lub wyższa. Aktualna wersja to %1.%2" msgid "Error initializing OpenGL" msgstr "Błąd inicjalizacji OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Powrót do renderowania oprogramowania.\n" +msgid "\nFalling back to software rendering." +msgstr "\nPowrót do renderowania oprogramowania." msgid "<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>" msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itp.) otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index d7092c6d0..9f0370f5e 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -1311,8 +1311,8 @@ msgstr "É necessária a versão 3.0 ou superior do OpenGL. A versão atual é % msgid "Error initializing OpenGL" msgstr "Erro ao inicializar o OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Voltando à renderização de software.\n" +msgid "\nFalling back to software rendering." +msgstr "\nVoltando à renderização de software." msgid "<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>" msgstr "<html><head/><body><p>Ao selecionar imagens de mídia (CD-ROM, disquete, etc.), a caixa de diálogo de abertura será iniciada no mesmo diretório do arquivo de configuração do 86Box. Essa configuração provavelmente só fará diferença no macOS.</p></body></html>" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index e04d93c54..f665424e0 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -1311,8 +1311,8 @@ msgstr "É necessária a versão 3.0 ou superior do OpenGL. A versão atual é % msgid "Error initializing OpenGL" msgstr "Erro ao inicializar o OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Recuando para a renderização de software." +msgid "\nFalling back to software rendering." +msgstr "\nRecuando para a renderização de software." msgid "<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>" msgstr "<html><head/><body><p>Ao selecionar imagens multimédia (CD-ROM, disquete, etc.) a caixa de diálogo de abertura irá começar no mesmo diretório que o ficheiro de configuração da 86Box. Esta configuração provavelmente só fará diferença no macOS.</p></body></html>" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a67583a74..92542b70d 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1311,8 +1311,8 @@ msgstr "Требуется OpenGL версии 3.0 или выше. Текуща msgid "Error initializing OpenGL" msgstr "Ошибка инициализации OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Переключение на программный рендеринг.\n" +msgid "\nFalling back to software rendering." +msgstr "\nПереключение на программный рендеринг." msgid "<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>" msgstr "<html><head/><body><p>При выборе образов носителей (CD-ROM, дискет и т. д.) диалог открытия будет запускаться в том же каталоге, что и файл конфигурации 86Box. Эта настройка, скорее всего, будет иметь значение только на macOS.</p></body></html>" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index f976147b8..36298269d 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -1312,8 +1312,8 @@ msgstr "Vyžaduje sa verzia OpenGL 3.0 alebo vyššia. Aktuálna verzia je %1.%2 msgid "Error initializing OpenGL" msgstr "Chyba pri inicializácii OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Návrat k softvérovému vykresľovaniu.\n" +msgid "\nFalling back to software rendering." +msgstr "\nNávrat k softvérovému vykresľovaniu." msgid "<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>" msgstr "<html><head/><body><p>Pri výbere multimediálnych obrazov (CD-ROM, disketa atď.) sa dialógové okno otvorenia spustí v rovnakom adresári ako konfiguračný súbor 86Box. Toto nastavenie bude mať pravdepodobne význam len v systéme MacOS.</p></body></html>" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 7022ad7b0..0eeca62f8 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -1311,8 +1311,8 @@ msgstr "Zahteva se različica OpenGL 3.0 ali novejša. Trenutna različica je %1 msgid "Error initializing OpenGL" msgstr "Napaka pri inicializaciji OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Vrnitev k programskemu upodabljanju.\n" +msgid "\nFalling back to software rendering." +msgstr "\nVrnitev k programskemu upodabljanju." msgid "<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>" msgstr "<html><head/><body><p>Pri izbiri medijskih slik (CD-ROM, disketa itd.) se bo odprto pogovorno okno začelo v istem imeniku kot konfiguracijska datoteka 86Box. Ta nastavitev bo verjetno imela pomen le v operacijskem sistemu MacOS.</p></body></html>" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 6f8359823..41930bd96 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -1311,8 +1311,8 @@ msgstr "OpenGL sürüm 3.0 veya üstü gereklidir. Geçerli sürüm %1.%2" msgid "Error initializing OpenGL" msgstr "OpenGL başlatılırken hata oluştu" -msgid "Falling back to software rendering.\n" -msgstr "Yazılım işleyicisine geri dönülüyor.\n" +msgid "\nFalling back to software rendering." +msgstr "\nYazılım işleyicisine geri dönülüyor." msgid "<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>" msgstr "<html><head/><body><p>Medya görüntüsü (CD-ROM, disket, vb.) seçme diyaloğu 86Box yapılandırma dosyasıyla aynı dizinde başlayacaktır. Bu ayar muhtemelen sadece macOS üzerinde bir fark meydana getirecektir.</p></body></html>" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index c42e72e2b..4632d001b 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -1311,8 +1311,8 @@ msgstr "Потрібна версія OpenGL 3.0 або новіша. Поточ msgid "Error initializing OpenGL" msgstr "Помилка ініціалізації OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Повернення до програмного рендерингу.\n" +msgid "\nFalling back to software rendering." +msgstr "\nПовернення до програмного рендерингу." msgid "<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>" msgstr "<html><head/><body><p>При виборі медіа-образів (CD-ROM, дискета і т.д.) діалогове вікно буде відкриватися в тому ж каталозі, що і файл конфігурації 86Box. Цей параметр, швидше за все, матиме значення лише на macOS.</p></body></html>" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index dacd8efac..b8322d600 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -1311,8 +1311,8 @@ msgstr "OpenGL phiên bản 3.0 trở lên là bắt buộc. Phiên bản hiện msgid "Error initializing OpenGL" msgstr "Lỗi khởi tạo OpenGL" -msgid "Falling back to software rendering.\n" -msgstr "Quay trở lại kết xuất phần mềm.\n" +msgid "\nFalling back to software rendering." +msgstr "\nQuay trở lại kết xuất phần mềm." msgid "<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>" msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 1a78b8abc..308cbe5b3 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1311,8 +1311,8 @@ msgstr "需要 OpenGL 3.0 或更高版本。当前版本为 %1.%2" msgid "Error initializing OpenGL" msgstr "初始化 OpenGL 时出错" -msgid "Falling back to software rendering.\n" -msgstr "回到软件渲染。" +msgid "\nFalling back to software rendering." +msgstr "\n回到软件渲染。" msgid "<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>" msgstr "<html><head/><body><p>选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。</p></body></html>;" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index a9e73c563..1ffb9843e 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -1311,8 +1311,8 @@ msgstr "需要 OpenGL 版本 3.0 或更高。目前版本為 %1.%2" msgid "Error initializing OpenGL" msgstr "初始化 OpenGL 出錯" -msgid "Falling back to software rendering.\n" -msgstr "回退到軟體渲染。" +msgid "\nFalling back to software rendering." +msgstr "\n回退到軟體渲染。" msgid "<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>" msgstr "<html><head/><body><p>當選擇媒體映像 (CD-ROM、軟碟等) 時,開啟對話方塊會在與 86Box 設定檔相同的目錄中開始。此設定可能只會在 macOS 上有所影響。</p></body></html>" diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index aed932e92..610d89d17 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -375,7 +375,7 @@ RendererStack::createRenderer(Renderer renderer) try { hw = new VulkanWindowRenderer(this); } catch (std::runtime_error &e) { - auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", e.what() + QString("\nFalling back to software rendering."), QMessageBox::Ok); + auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", e.what() + tr("\nFalling back to software rendering."), QMessageBox::Ok); msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->show(); imagebufs = {}; From ba6694f9f2c102876aa7f1b9d49cecdd57c6d7c1 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 8 Apr 2025 12:01:05 +0500 Subject: [PATCH 0706/1190] qt: Make "Failed to init Vulkan" error translatable --- src/qt/languages/86box.pot | 3 +++ src/qt/languages/en-GB.po | 3 +++ src/qt/qt_rendererstack.cpp | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 83e021d2a..6327cf1f3 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2087,3 +2087,6 @@ msgstr "" msgid "Inhibit multimedia keys on Windows" msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index 6043c10d9..8cc29a71a 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -71,3 +71,6 @@ msgstr "Grey" msgid "Color" msgstr "Colour" + +msgid "Failed to initialize Vulkan renderer." +msgstr "Failed to initialise Vulkan renderer." diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 610d89d17..b5b910fe9 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef __APPLE__ # include @@ -393,7 +394,7 @@ RendererStack::createRenderer(Renderer renderer) }); connect(hw, &VulkanWindowRenderer::errorInitializing, [=]() { /* Renderer could not initialize, fallback to software. */ - auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", QString("Failed to initialize Vulkan renderer.\nFalling back to software rendering."), QMessageBox::Ok); + auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", tr("Failed to initialize Vulkan renderer.") % tr("\nFalling back to software rendering."), QMessageBox::Ok); msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->show(); imagebufs = {}; From 377381a8fadf5fc358712925561a44e55e662fde Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 8 Apr 2025 15:28:09 +0500 Subject: [PATCH 0707/1190] qt: Fix an error with the "%i Wait state(s)" string --- src/qt/languages/86box.pot | 2 +- src/qt/languages/ca-ES.po | 2 +- src/qt/languages/nl-NL.po | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 6327cf1f3..856888d7c 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -750,7 +750,7 @@ msgstr "" msgid "Default" msgstr "" -msgid "%i estat(s) d'espera" +msgid "%i Wait state(s)" msgstr "" msgid "Type" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 48c2a777d..ae9a22622 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -750,7 +750,7 @@ msgstr "KB" msgid "Default" msgstr "Per defecte" -msgid "%i estat(s) d'espera" +msgid "%i Wait state(s)" msgstr "%i estado(s) de Espera" msgid "Type" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 10e4c2bd2..8326ef49d 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Standaard" -msgid "%i estat(s) d'espera" -msgstr "%i estat(s) d'espera" +msgid "%i Wait state(s)" +msgstr "%i Wachttoestand(en)" msgid "Type" msgstr "Type" From 0a2d15db9bbb9a69327b5f40b5bd86c10d9f5d92 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 8 Apr 2025 15:29:07 +0500 Subject: [PATCH 0708/1190] qt: Reword some error messages slightly --- src/qt/languages/86box.pot | 2 +- src/qt/qt_glsl_parser.cpp | 2 +- src/qt/qt_openglrenderer.cpp | 2 +- src/qt/qt_openglshadermanagerdialog.cpp | 2 +- src/qt/qt_progsettings.cpp | 2 +- src/qt/qt_progsettings.ui | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 856888d7c..382e00835 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2085,7 +2085,7 @@ msgstr "" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "" -msgid "Inhibit multimedia keys on Windows" +msgid "Inhibit multimedia keys" msgstr "" msgid "Failed to initialize Vulkan renderer." diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index fa45267a7..6e107bc19 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -214,7 +214,7 @@ static glslp_t *glsl_parse(const char *f) { strcpy(shader->shader_fn, f); shader->shader_program = load_file(f); if (!shader->shader_program) { - QMessageBox::critical((QWidget *) qApp->findChild(), QObject::tr("GLSL error"), QObject::tr("Could not load shader %1").arg(shader->shader_fn)); + QMessageBox::critical((QWidget *) qApp->findChild(), QObject::tr("GLSL error"), QObject::tr("Could not load shader: %1").arg(shader->shader_fn)); //wx_simple_messagebox("GLSL error", "Could not load shader %s\n", shader->shader_fn); glslp_free(glslp); return 0; diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index cc48ca06e..2e8869c09 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -633,7 +633,7 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) if (!load_texture(file, &tex->texture)) { //QMessageBox::critical(main_window, tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load texture: %1").arg(file)); pclog("Could not load texture %s!\n", file); failed = 1; break; diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 2a03b46f7..90f38f40f 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -184,7 +184,7 @@ void OpenGLShaderManagerDialog::on_buttonAdd_clicked() ui->buttonAdd->setDisabled(ui->shaderListWidget->count() >= MAX_USER_SHADERS); } } else { - QMessageBox::critical(this, tr("GLSL error"), tr("Could not load filename %1").arg(res)); + QMessageBox::critical(this, tr("GLSL error"), tr("Could not load file %1").arg(res)); } } } diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 2fd108186..0fce0d705 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -80,7 +80,7 @@ ProgSettings::accept() 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(); + inhibit_multimedia_keys = ui->checkBoxMultimediaKeys->isChecked() ? 1 : 0; loadTranslators(QCoreApplication::instance()); reloadStrings(); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index d3ebf8c85..b01199dfd 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -140,7 +140,7 @@ - Inhibit multimedia keys on Windows + Inhibit multimedia keys From 0fd0c9adee4ce712b7c11520736c024f5290de3c Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 10 Apr 2025 02:05:50 +0500 Subject: [PATCH 0709/1190] qt: Miscellaneous translation corrections --- src/qt/languages/fr-FR.po | 4 ++-- src/qt/languages/hu-HU.po | 2 +- src/qt/languages/it-IT.po | 4 ++-- src/qt/languages/nl-NL.po | 2 +- src/qt/languages/pl-PL.po | 2 +- src/qt/languages/sk-SK.po | 2 +- src/qt/languages/zh-CN.po | 2 +- src/qt/languages/zh-TW.po | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 39479b40f..b0afd8ae2 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -220,7 +220,7 @@ msgid "&Existing image..." msgstr "Image &Existante..." msgid "Existing image (&Write-protected)..." -msgstr "Image Existante(&Lecture seule)..." +msgstr "Image Existante (&Lecture seule)..." msgid "&Record" msgstr "En®istrer" @@ -235,7 +235,7 @@ msgid "&Fast forward to the end" msgstr "Aller à la &Fin" msgid "E&ject" -msgstr "E&jecter" +msgstr "É&jecter" msgid "&Image..." msgstr "&Image..." diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index db6354680..8c9dc67dd 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -1252,7 +1252,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "Gazdag CD/DVD-meghajtó (%1:)" msgid "&Connected" -msgstr "&Connected" +msgstr "" msgid "Clear image history" msgstr "Törölje a kép előzményeit" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index effbee5bd..4f9137d77 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -1267,7 +1267,7 @@ msgid "Host CD/DVD Drive (%1)" msgstr "Unità CD/DVD host (%1)" msgid "Unknown Bus" -msgstr "Autobus sconosciuto" +msgstr "Bus sconosciuto" msgid "Null Driver" msgstr "Driver nullo" @@ -2062,7 +2062,7 @@ msgid "RAM Disk (max. speed)" msgstr "Disco RAM (velocità massima)" msgid "IBM 8514/A clone (ISA)" -msgstr "Clone IBM 8514/A(ISA)" +msgstr "Clone IBM 8514/A (ISA)" msgid "Vendor" msgstr "Fabricante" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 8326ef49d..f7d64a413 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -235,7 +235,7 @@ msgid "&Fast forward to the end" msgstr "&Snel vooruit naar het einde" msgid "E&ject" -msgstr "E&ject" +msgstr "&Uitwerpen" msgid "&Image..." msgstr "&Image..." diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index f8367176d..3b29c3415 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -1252,7 +1252,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "Napęd CD/DVD hosta (%1:)" msgid "&Connected" -msgstr "&Connected" +msgstr "" msgid "Clear image history" msgstr "Wyczyść historię obrazów" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 36298269d..1d8768dd8 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -1252,7 +1252,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "Hostiteľská jednotka CD/DVD (%1:)" msgid "&Connected" -msgstr "&Connected" +msgstr "" msgid "Clear image history" msgstr "Vymazanie histórie obrázkov" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 308cbe5b3..32358584e 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1252,7 +1252,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "主机 CD/DVD 驱动器 (%1:)" msgid "&Connected" -msgstr "&Connected" +msgstr "" msgid "Clear image history" msgstr "清除映像历史记录" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 1ffb9843e..6b7420bc7 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2050,7 +2050,7 @@ msgid "Eject %s" msgstr "退出 %s" msgid "&Unmute" -msgstr "解除靜音 (&U)" +msgstr "解除靜音(&U)" msgid "Softfloat FPU" msgstr "Softfloat FPU" From cc01d7c3b8ee0b837feb59467eea1678642e63eb Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 10 Apr 2025 02:51:04 +0500 Subject: [PATCH 0710/1190] =?UTF-8?q?qt=5Fmediamenu.cpp:=20Get=20rid=20of?= =?UTF-8?q?=20pointless=20QString=20=E2=86=94=20C=20string=20conversions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/qt/qt_mediamenu.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index f7abebdf1..478f64c2a 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -263,7 +263,7 @@ void MediaMenu::cassetteMenuSelect(int slot) { QString filename = mhm.getImageForSlot(0, slot, ui::MediaType::Cassette); - cassetteMount(filename.toUtf8().constData(), 0); + cassetteMount(filename, 0); cassetteUpdateMenu(); ui_sb_update_tip(SB_CASSETTE); } @@ -365,7 +365,7 @@ void MediaMenu::cartridgeMenuSelect(int index, int slot) { QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Cartridge); - cartridgeMount(index, filename.toUtf8().constData()); + cartridgeMount(index, filename); cartridgeUpdateMenu(index); ui_sb_update_tip(SB_CARTRIDGE | index); } @@ -507,7 +507,7 @@ void MediaMenu::floppyMenuSelect(int index, int slot) { QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Floppy); - floppyMount(index, filename.toUtf8().constData(), false); + floppyMount(index, filename, false); floppyUpdateMenu(index); ui_sb_update_tip(SB_FLOPPY | index); } @@ -594,7 +594,7 @@ void MediaMenu::cdromReload(int index, int slot) { const QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Optical); - cdromMount(index, filename.toUtf8().constData()); + cdromMount(index, filename); cdromUpdateMenu(index); ui_sb_update_tip(SB_CDROM | index); } @@ -630,7 +630,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) switch (type) { default: - menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); return; case ui::MediaType::Cassette: if (!MachineStatus::hasCassette()) @@ -639,7 +639,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cassetteImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); break; case ui::MediaType::Cartridge: if (!machine_has_cartridge(machine)) @@ -648,7 +648,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cartridgeImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); break; case ui::MediaType::Floppy: if (!floppyMenus.contains(index)) @@ -657,7 +657,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[floppyImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); break; case ui::MediaType::Optical: if (!cdromMenus.contains(index)) @@ -668,14 +668,14 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) if (fn.left(8) == "ioctl://") { 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(); + menu_item_name = tr("Host CD/DVD Drive (%1)").arg(fn.right(2)); #else menu_item_name = tr("Host CD/DVD Drive (%1)").arg(fn.right(fn.length() - 8)); #endif } else { fi.setFile(fn); 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(); + menu_item_name = fn.isEmpty() ? tr("previous image") : fn; } imageHistoryUpdatePos->setIcon(menu_icon); break; @@ -686,7 +686,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[zipImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); break; case ui::MediaType::Mo: if (!moMenus.contains(index)) @@ -695,11 +695,11 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[moImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); break; } - imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), menu_item_name.toUtf8().constData())); + imageHistoryUpdatePos->setText(menu_item_name); if (fn.left(8) == "ioctl://") imageHistoryUpdatePos->setVisible(true); @@ -735,7 +735,7 @@ MediaMenu::cdromUpdateMenu(int i) QString menu_item_name; if (name.left(8) == "ioctl://") { #ifdef Q_OS_WINDOWS - menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(2)).toUtf8().constData(); + menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(2)); #else menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(name.length() - 8)); #endif @@ -744,7 +744,7 @@ MediaMenu::cdromUpdateMenu(int i) } else { QFileInfo fi(cdrom[i].image_path); - menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : name.toUtf8().constData(); + menu_item_name = name.isEmpty() ? QString() : name; name2 = name; menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico"); } From 5ff206e493153471088aa96755d76c2b44bc6f17 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 10 Apr 2025 04:34:37 +0500 Subject: [PATCH 0711/1190] qt: Get rid of most uses of `QString::asprintf()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the Win32 UI is out of the way, we can rewrite the strings to use QString::arg() instead and avoid even more QString ↔ C string conversions --- src/qt/languages/86box.pot | 20 +++++++++--------- src/qt/languages/ca-ES.po | 40 +++++++++++++++++------------------ src/qt/languages/cs-CZ.po | 40 +++++++++++++++++------------------ src/qt/languages/de-DE.po | 40 +++++++++++++++++------------------ src/qt/languages/es-ES.po | 40 +++++++++++++++++------------------ src/qt/languages/fi-FI.po | 40 +++++++++++++++++------------------ src/qt/languages/fr-FR.po | 40 +++++++++++++++++------------------ src/qt/languages/hr-HR.po | 40 +++++++++++++++++------------------ src/qt/languages/hu-HU.po | 40 +++++++++++++++++------------------ src/qt/languages/it-IT.po | 40 +++++++++++++++++------------------ src/qt/languages/ja-JP.po | 38 ++++++++++++++++----------------- src/qt/languages/ko-KR.po | 40 +++++++++++++++++------------------ src/qt/languages/nl-NL.po | 40 +++++++++++++++++------------------ src/qt/languages/pl-PL.po | 40 +++++++++++++++++------------------ src/qt/languages/pt-BR.po | 40 +++++++++++++++++------------------ src/qt/languages/pt-PT.po | 40 +++++++++++++++++------------------ src/qt/languages/ru-RU.po | 40 +++++++++++++++++------------------ src/qt/languages/sk-SK.po | 40 +++++++++++++++++------------------ src/qt/languages/sl-SI.po | 40 +++++++++++++++++------------------ src/qt/languages/tr-TR.po | 40 +++++++++++++++++------------------ src/qt/languages/uk-UA.po | 40 +++++++++++++++++------------------ src/qt/languages/vi-VN.po | 40 +++++++++++++++++------------------ src/qt/languages/zh-CN.po | 40 +++++++++++++++++------------------ src/qt/languages/zh-TW.po | 40 +++++++++++++++++------------------ src/qt/qt_harddiskdialog.cpp | 3 +-- src/qt/qt_mediamenu.cpp | 36 ++++++++++++++----------------- src/qt/qt_settingsmachine.cpp | 2 +- 27 files changed, 487 insertions(+), 492 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 382e00835..a778f9f6d 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -642,7 +642,7 @@ msgstr "" msgid "Speed" msgstr "" -msgid "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" msgstr "" msgid "ZIP images" @@ -750,7 +750,7 @@ msgstr "" msgid "Default" msgstr "" -msgid "%i Wait state(s)" +msgid "%1 Wait state(s)" msgstr "" msgid "Type" @@ -795,10 +795,10 @@ msgstr "" msgid "None" msgstr "" -msgid "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" msgstr "" -msgid "Floppy %i (%s): %ls" +msgid "Floppy %1 (%2): %3" msgstr "" msgid "Advanced sector images" @@ -819,7 +819,7 @@ msgstr "" msgid "Unable to initialize GhostPCL" msgstr "" -msgid "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" msgstr "" msgid "MO images" @@ -906,13 +906,13 @@ msgstr "" msgid "Continue" msgstr "" -msgid "Cassette: %s" +msgid "Cassette: %1" msgstr "" msgid "Cassette images" msgstr "" -msgid "Cartridge %i: %ls" +msgid "Cartridge %1: %2" msgstr "" msgid "Cartridge images" @@ -1080,7 +1080,7 @@ msgstr "" msgid "ATAPI" msgstr "" -msgid "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" msgstr "" msgid "160 KB" @@ -1272,7 +1272,7 @@ msgstr "" msgid "Null Driver" msgstr "" -msgid "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" msgstr "" msgid "Render behavior" @@ -2046,7 +2046,7 @@ msgstr "" msgid "Host Serial Passthrough" msgstr "" -msgid "Eject %s" +msgid "E&ject %1" msgstr "" msgid "&Unmute" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index ae9a22622..808799859 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -642,8 +642,8 @@ msgstr "Premeu Ctrl+Alt+PgDn per tornar al mode de finestra." msgid "Speed" msgstr "Velocitat" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Imatges ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Per defecte" -msgid "%i Wait state(s)" -msgstr "%i estado(s) de Espera" +msgid "%1 Wait state(s)" +msgstr "%1 estado(s) de Espera" msgid "Type" msgstr "Tipus" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Cap" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disquet %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disquet %1 (%2): %3" msgid "Advanced sector images" msgstr "Imatges avançates del sector" @@ -819,8 +819,8 @@ msgstr "No es pot inicialitzar Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "No es pot inicialitzar GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Imatges MO" @@ -906,14 +906,14 @@ msgstr "El Filtratge de tipus de CPU basat en màquina seleccionada està deshab msgid "Continue" msgstr "Continuar" -msgid "Cassette: %s" -msgstr "Casset: %s" +msgid "Cassette: %1" +msgstr "Casset: %1" msgid "Cassette images" msgstr "Imatges de casset" -msgid "Cartridge %i: %ls" -msgstr "Cartutx %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartutx %1: %2" msgid "Cartridge images" msgstr "Imatges de cartutx" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Bus desconegut" msgid "Null Driver" msgstr "Controlador nul" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Comportament del renderitzador" @@ -2046,8 +2046,8 @@ msgstr "Pipe anomenat (servidor)" msgid "Host Serial Passthrough" msgstr "Pas del port sèrie amfitrió" -msgid "Eject %s" -msgstr "Extreure %s" +msgid "E&ject %1" +msgstr "E&xtreure %1" msgid "&Unmute" msgstr "&Saver" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index bcb7cc714..d3985b67a 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -642,8 +642,8 @@ msgstr "Stiskněte Ctrl+Alt+PgDn pro návrat z režimu celé obrazovky." msgid "Speed" msgstr "Rychlost" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Obrazy ZIP disků" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Výchozí" -msgid "%i Wait state(s)" -msgstr "%i čekací stav(y)" +msgid "%1 Wait state(s)" +msgstr "%1 čekací stav(y)" msgid "Type" msgstr "Typ" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Žadné" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disketová mechanika %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disketová mechanika %1 (%2): %3" msgid "Advanced sector images" msgstr "Rozšířené sektorové obrazy" @@ -819,8 +819,8 @@ msgstr "Nastala chyba při inicializaci knihovny Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Nastala chyba při inicializaci knihovny GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Obrazy MO" @@ -906,14 +906,14 @@ msgstr "Pro tuto konfiguraci bylo vypnuto filtrování procesorů podle zvolené msgid "Continue" msgstr "Pokračovat" -msgid "Cassette: %s" -msgstr "Kazeta: %s" +msgid "Cassette: %1" +msgstr "Kazeta: %1" msgid "Cassette images" msgstr "Kazetové nahrávky" -msgid "Cartridge %i: %ls" -msgstr "Cartridge %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartridge %1: %2" msgid "Cartridge images" msgstr "Obrazy cartridge" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Neznámá sběrnice" msgid "Null Driver" msgstr "Nulový ovladač" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Chování vykreslování" @@ -2046,8 +2046,8 @@ msgstr "Pojmenované potrubí (server)" msgid "Host Serial Passthrough" msgstr "Průchod sériového portu hostitele" -msgid "Eject %s" -msgstr "Vyjmout %s" +msgid "E&ject %1" +msgstr "&Vyjmout %1" msgid "&Unmute" msgstr "&Roztišit" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 6255deef7..781269af9 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -642,8 +642,8 @@ msgstr "Strg+Alt+Bild ab, zur Rückkehr in den Fenstermodus." msgid "Speed" msgstr "Geschwindigkeit" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP-Abbilder" @@ -753,8 +753,8 @@ msgstr "KB" msgid "Default" msgstr "Standard" -msgid "%i Wait state(s)" -msgstr "%i Wartezustände" +msgid "%1 Wait state(s)" +msgstr "%1 Wartezustände" msgid "Type" msgstr "Typ" @@ -798,11 +798,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Ohne" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Diskette %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Diskette %1 (%2): %3" msgid "Advanced sector images" msgstr "Fortgeschrittene Sektorabbilder" @@ -822,8 +822,8 @@ msgstr "Ghostscript konnte nicht initialisiert werden" msgid "Unable to initialize GhostPCL" msgstr "GhostPCL konnte nicht initialisiert werden" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "MO-Abbilder" @@ -909,14 +909,14 @@ msgstr "Das Filtern der CPU-Typen basierend auf dem ausgewählten System ist fü msgid "Continue" msgstr "Fortfahren" -msgid "Cassette: %s" -msgstr "Kassette: %s" +msgid "Cassette: %1" +msgstr "Kassette: %1" msgid "Cassette images" msgstr "Kassettenabbilder" -msgid "Cartridge %i: %ls" -msgstr "Cartridge %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartridge %1: %2" msgid "Cartridge images" msgstr "Cartridgeabbilder" @@ -1083,8 +1083,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1275,8 +1275,8 @@ msgstr "Unbekannter Bus" msgid "Null Driver" msgstr "Nulltreiber" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Rendering-Verhalten" @@ -2049,8 +2049,8 @@ msgstr "Benanntes Pipe (Server)" msgid "Host Serial Passthrough" msgstr "Durchreichung der seriellen Schnittstelle des Hosts" -msgid "Eject %s" -msgstr "Auswerfen %s" +msgid "E&ject %1" +msgstr "A&uswerfen %1" msgid "&Unmute" msgstr "&Ton einschalten" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 285809cc5..3cdcedd98 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -642,8 +642,8 @@ msgstr "Pulsa Ctrl+Alt+PgDn para volver a modo ventana." msgid "Speed" msgstr "Velocidad" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Imagenes ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Por defecto" -msgid "%i Wait state(s)" -msgstr "%i estado(s) de Espera" +msgid "%1 Wait state(s)" +msgstr "%1 estado(s) de Espera" msgid "Type" msgstr "Tipo" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Ninguno" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disquete %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disquete %1 (%2): %3" msgid "Advanced sector images" msgstr "Imágenes avanzadas de sector" @@ -819,8 +819,8 @@ msgstr "No fué posible inicializar Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "No fué posible inicializar GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Imágenes de MO" @@ -906,14 +906,14 @@ msgstr "El Filtrado de tipo de CPU basado en máquina seleccionada está deshabi msgid "Continue" msgstr "Continuar" -msgid "Cassette: %s" -msgstr "Cassette: %s" +msgid "Cassette: %1" +msgstr "Cassette: %1" msgid "Cassette images" msgstr "Imágenes de Cassette" -msgid "Cartridge %i: %ls" -msgstr "Cartucho %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartucho %1: %2" msgid "Cartridge images" msgstr "Imágenes de Cartucho" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1271,8 +1271,8 @@ msgstr "Bus desconocido" msgid "Null Driver" msgstr "Controlador nulo" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Comportamiento del renderizador" @@ -2045,8 +2045,8 @@ msgstr "Tubería con nombre (servidor)" msgid "Host Serial Passthrough" msgstr "Paso del puerto serie del host" -msgid "Eject %s" -msgstr "Extraer %s" +msgid "E&ject %1" +msgstr "E&xtraer %1" msgid "&Unmute" msgstr "&Reactivar sonido" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 5419b9c5a..ddae5c2ba 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -642,8 +642,8 @@ msgstr "Paina Ctrl+Alt+PgDn palataksesi ikkunoituun tilaan." msgid "Speed" msgstr "Nopeus" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP-levykuvat" @@ -750,8 +750,8 @@ msgstr "Kt" msgid "Default" msgstr "Oletus" -msgid "%i Wait state(s)" -msgstr "%i odotustilaa" +msgid "%1 Wait state(s)" +msgstr "%1 odotustilaa" msgid "Type" msgstr "Tyyppi" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Ei mikään" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u Mt (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 Mt (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Levyke %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Levyke %1 (%2): %3" msgid "Advanced sector images" msgstr "Kehittyneet sektorilevykuvat" @@ -819,8 +819,8 @@ msgstr "Ghostscriptin alustus epäonnistui" msgid "Unable to initialize GhostPCL" msgstr "GhostPCLin alustus epäonnistui" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "MO-levykuvat" @@ -906,14 +906,14 @@ msgstr "Valittuun tietokoneeseen perustuva suoritintyypin suodatus ei ole käyt msgid "Continue" msgstr "Jatka" -msgid "Cassette: %s" -msgstr "Kasetti: %s" +msgid "Cassette: %1" +msgstr "Kasetti: %1" msgid "Cassette images" msgstr "Kasettitiedostot" -msgid "Cartridge %i: %ls" -msgstr "ROM-moduuli %i: %ls" +msgid "Cartridge %1: %2" +msgstr "ROM-moduuli %1: %2" msgid "Cartridge images" msgstr "ROM-moduulikuvat" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 Kt" @@ -1272,8 +1272,8 @@ msgstr "Tuntematon väylä" msgid "Null Driver" msgstr "Nolla-ajuri" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Renderöintikäyttäytyminen" @@ -2049,8 +2049,8 @@ msgstr "Nimetty putki (palvelin)" msgid "Host Serial Passthrough" msgstr "Isännän sarjaportin läpivienti" -msgid "Eject %s" -msgstr "Poista kasettipesästä %s" +msgid "E&ject %1" +msgstr "&Poista kasettipesästä %1" msgid "&Unmute" msgstr "&Poista mykistys" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index b0afd8ae2..df5bf7ef6 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -642,8 +642,8 @@ msgstr "Appuyez sur Ctrl+Alt+PgDn pour revenir au mode fenêtré." msgid "Speed" msgstr "Vitesse" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Images ZIP" @@ -750,8 +750,8 @@ msgstr "Ko" msgid "Default" msgstr "Défaut" -msgid "%i Wait state(s)" -msgstr "%i état(s) d'attente" +msgid "%1 Wait state(s)" +msgstr "%1 état(s) d'attente" msgid "Type" msgstr "Type" @@ -795,11 +795,11 @@ msgstr "Système de contrôle de vol Thrustmaster" msgid "None" msgstr "Aucun" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u Mo (CTS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 Mo (CTS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disquette %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disquette %1 (%2): %3" msgid "Advanced sector images" msgstr "Images du secteur avancés" @@ -819,8 +819,8 @@ msgstr "Impossible d'initialiser Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Impossible d'initialiser GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "Magnéto-optique %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "Magnéto-optique %1 (%2): %3" msgid "MO images" msgstr "Images magnéto-optiques" @@ -906,14 +906,14 @@ msgstr "La filtrage du type du processeur sur la base de la machine sélectionn msgid "Continue" msgstr "Continuer" -msgid "Cassette: %s" -msgstr "Cassette: %s" +msgid "Cassette: %1" +msgstr "Cassette: %1" msgid "Cassette images" msgstr "Images cassette" -msgid "Cartridge %i: %ls" -msgstr "Cartouche %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartouche %1: %2" msgid "Cartridge images" msgstr "Images cartouche" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 Ko" @@ -1272,8 +1272,8 @@ msgstr "Bus inconnu" msgid "Null Driver" msgstr "Pilote nul" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Comportement de rendu" @@ -2046,8 +2046,8 @@ msgstr "Tuyau nommé (serveur)" msgid "Host Serial Passthrough" msgstr "Passage du port série de l'hôte" -msgid "Eject %s" -msgstr "Éjecter %s" +msgid "E&ject %1" +msgstr "É&jecter %1" msgid "&Unmute" msgstr "&Réactiver son" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 634523c5c..ecfd0c696 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -642,8 +642,8 @@ msgstr "Pritisnite Ctrl+Alt+PgDn za povratak u prozorski način rada." msgid "Speed" msgstr "Brzina" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP slike" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Standard" -msgid "%i Wait state(s)" -msgstr "%i stanje čekanja" +msgid "%1 Wait state(s)" +msgstr "%1 stanje čekanja" msgid "Type" msgstr "Tip" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Bez" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disketa %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disketa %1 (%2): %3" msgid "Advanced sector images" msgstr "Napredne sektorske slike" @@ -819,8 +819,8 @@ msgstr "Nije moguće inicijalizirati GhostScript" msgid "Unable to initialize GhostPCL" msgstr "Nije moguće inicijalizirati GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "MO slike" @@ -906,14 +906,14 @@ msgstr "Filtriranje tipa CPU-a na temelju odabranog sistema onemogućeno je za o msgid "Continue" msgstr "Nastavi" -msgid "Cassette: %s" -msgstr "Audio kaseta: %s" +msgid "Cassette: %1" +msgstr "Audio kaseta: %1" msgid "Cassette images" msgstr "Slike audio kasete" -msgid "Cartridge %i: %ls" -msgstr "Kaseta %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Kaseta %1: %2" msgid "Cartridge images" msgstr "Slike kasete" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Nepoznata sabirnica" msgid "Null Driver" msgstr "Nulti upravljački program" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Ponašanje rendera" @@ -2046,8 +2046,8 @@ msgstr "Imenovani vod (server)" msgid "Host Serial Passthrough" msgstr "Prolaz serijskih vrata nositelja" -msgid "Eject %s" -msgstr "Izbaci %s" +msgid "E&ject %1" +msgstr "&Izbaci %1" msgid "&Unmute" msgstr "&Uključi zvuk" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 8c9dc67dd..79e0dd5e6 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -642,8 +642,8 @@ msgstr "Használja a Ctrl+Alt+PgDn gombokat az ablakhoz való visszatéréshez." msgid "Speed" msgstr "Sebesség" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP-lemezképek" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Alapértelmezett" -msgid "%i Wait state(s)" -msgstr "%i várakozási ciklus(ok)" +msgid "%1 Wait state(s)" +msgstr "%1 várakozási ciklus(ok)" msgid "Type" msgstr "Típus" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Nincs" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Floppy %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Floppy %1 (%2): %3" msgid "Advanced sector images" msgstr "Továbbfejlesztett szektor képek" @@ -819,8 +819,8 @@ msgstr "Nem sikerült inicializálni a Ghostscript-et" msgid "Unable to initialize GhostPCL" msgstr "Nem sikerült inicializálni a GhostPCL-et" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "MO-képfájlok" @@ -906,14 +906,14 @@ msgstr "A kiválasztott gépen alapuló CPU-típusszűrés le van tiltva ezen az msgid "Continue" msgstr "Folytatás" -msgid "Cassette: %s" -msgstr "Magnókazetta: %s" +msgid "Cassette: %1" +msgstr "Magnókazetta: %1" msgid "Cassette images" msgstr "Magnókazetta-képek" -msgid "Cartridge %i: %ls" -msgstr "ROM-kazetta %i: %ls" +msgid "Cartridge %1: %2" +msgstr "ROM-kazetta %1: %2" msgid "Cartridge images" msgstr "ROM-kazetta képek" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Ismeretlen busz" msgid "Null Driver" msgstr "Null Driver" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Renderelési viselkedés" @@ -2046,8 +2046,8 @@ msgstr "Megnevezett cső (kiszolgáló)" msgid "Host Serial Passthrough" msgstr "Az állomás soros portjának áthaladása" -msgid "Eject %s" -msgstr "%s kiadás" +msgid "E&ject %1" +msgstr "%1 &kiadás" msgid "&Unmute" msgstr "&Hang újra bekapcsolása" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 4f9137d77..832c5b3fc 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -642,8 +642,8 @@ msgstr "Usa Ctrl+Alt+PgDn per tornare alla modalità finestra." msgid "Speed" msgstr "Velocità" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Immagini ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Predefinito" -msgid "%i Wait state(s)" -msgstr "%i stati d'attesa" +msgid "%1 Wait state(s)" +msgstr "%1 stati d'attesa" msgid "Type" msgstr "Tipo" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Nessuno" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Floppy %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Floppy %1 (%2): %3" msgid "Advanced sector images" msgstr "Immagini da settori avanzati" @@ -819,8 +819,8 @@ msgstr "Impossibile inizializzare Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Impossibile inizializzare GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Immagini MO" @@ -906,14 +906,14 @@ msgstr "Il filtraggio della tipologia di CPU è disabilitato per la macchina sel msgid "Continue" msgstr "Continua" -msgid "Cassette: %s" -msgstr "Cassetta: %s" +msgid "Cassette: %1" +msgstr "Cassetta: %1" msgid "Cassette images" msgstr "Immagini cassetta" -msgid "Cartridge %i: %ls" -msgstr "Cartuccia %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartuccia %1: %2" msgid "Cartridge images" msgstr "Immagini cartuccia" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Bus sconosciuto" msgid "Null Driver" msgstr "Driver nullo" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Comportamento di rendering" @@ -2046,8 +2046,8 @@ msgstr "Tubo denominato (Server)" msgid "Host Serial Passthrough" msgstr "Passaggio della porta seriale host" -msgid "Eject %s" -msgstr "Espelli %s" +msgid "E&ject %1" +msgstr "&Espelli %1" msgid "&Unmute" msgstr "&Riattiva l'audio" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 4ef8d01de..4bf10f7fc 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -642,8 +642,8 @@ msgstr "Ctrl+Alt+PgDnでウィンドウ モードに戻ります。" msgid "Speed" msgstr "速度" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIPイメージ" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "既定値" -msgid "%i Wait state(s)" -msgstr "%iつのウェイト ステート" +msgid "%1 Wait state(s)" +msgstr "%1つのウェイト ステート" msgid "Type" msgstr "タイプ" @@ -795,11 +795,11 @@ msgstr "Thrustmaster飛行制御システム" msgid "None" msgstr "なし" -msgid "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" msgstr "%u MB (CHS値: %i、%i、%i)" -msgid "Floppy %i (%s): %ls" -msgstr "フロッピー %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "フロッピー %1 (%2): %3" msgid "Advanced sector images" msgstr "アドバンスドセクターイメージ" @@ -819,8 +819,8 @@ msgstr "Ghostscriptが初期化できません" msgid "Unable to initialize GhostPCL" msgstr "GhostPCLが初期化できません" -msgid "MO %i (%ls): %ls" -msgstr "光磁気 %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "光磁気 %1 (%2): %3" msgid "MO images" msgstr "光磁気イメージ" @@ -906,14 +906,14 @@ msgstr "選択したマシンに基づくCPUタイプのフィルター機能は msgid "Continue" msgstr "続行" -msgid "Cassette: %s" -msgstr "カセット: %s" +msgid "Cassette: %1" +msgstr "カセット: %1" msgid "Cassette images" msgstr "カセットイメージ" -msgid "Cartridge %i: %ls" -msgstr "カートリッジ %i: %ls" +msgid "Cartridge %1: %2" +msgstr "カートリッジ %1: %2" msgid "Cartridge images" msgstr "カートリッジイメージ" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "不明なバス" msgid "Null Driver" msgstr "ヌル・ドライバー" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "レンダリング動作" @@ -2046,8 +2046,8 @@ msgstr "名前付きパイプ(サーバー)" msgid "Host Serial Passthrough" msgstr "ホストシリアルポートのパススルー" -msgid "Eject %s" -msgstr "%sを取り出す" +msgid "E&ject %1" +msgstr "%1を取り出す(&J)" msgid "&Unmute" msgstr "ミュート解除(&U)" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index e9e4b99e6..d6a0c234a 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -642,8 +642,8 @@ msgstr "Ctrl+Alt+PgDn 키를 누르면 창 모드로 전환합니다." msgid "Speed" msgstr "속도" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP 이미지" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "기본값" -msgid "%i Wait state(s)" -msgstr "%i 대기 상태" +msgid "%1 Wait state(s)" +msgstr "%1 대기 상태" msgid "Type" msgstr "형식" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "없음" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "플로피 %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "플로피 %1 (%2): %3" msgid "Advanced sector images" msgstr "어드밴스드 섹터 이미지" @@ -819,8 +819,8 @@ msgstr "Ghostscript를 초기화할 수 없습니다" msgid "Unable to initialize GhostPCL" msgstr "GhostPCL를 초기화할 수 없습니다" -msgid "MO %i (%ls): %ls" -msgstr "광자기 %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "광자기 %1 (%2): %3" msgid "MO images" msgstr "광자기 이미지" @@ -906,14 +906,14 @@ msgstr "이 에뮬레이트된 기종에 대해 선택한 기종을 기반으로 msgid "Continue" msgstr "계속" -msgid "Cassette: %s" -msgstr "카세트: %s" +msgid "Cassette: %1" +msgstr "카세트: %1" msgid "Cassette images" msgstr "카세트 이미지" -msgid "Cartridge %i: %ls" -msgstr "카트리지 %i: %ls" +msgid "Cartridge %1: %2" +msgstr "카트리지 %1: %2" msgid "Cartridge images" msgstr "카트리지 이미지" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "알 수 없는 버스" msgid "Null Driver" msgstr "Null 드라이버" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "렌더링 동작" @@ -2046,8 +2046,8 @@ msgstr "네임드 파이프(서버)" msgid "Host Serial Passthrough" msgstr "호스트 직렬 포트 패스스루" -msgid "Eject %s" -msgstr "%s 꺼내기" +msgid "E&ject %1" +msgstr "%1 꺼내기(&J)" msgid "&Unmute" msgstr "음소거 해제(&U)" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index f7d64a413..d57c389e1 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -642,8 +642,8 @@ msgstr "Druk op Ctrl+Alt+PgDn om terug te gaan naar de venstermodus." msgid "Speed" msgstr "Snelheid" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP-images" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Standaard" -msgid "%i Wait state(s)" -msgstr "%i Wachttoestand(en)" +msgid "%1 Wait state(s)" +msgstr "%1 Wachttoestand(en)" msgid "Type" msgstr "Type" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control systeem" msgid "None" msgstr "Geen" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Floppy %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Floppy %1 (%2): %3" msgid "Advanced sector images" msgstr "Geavanceerde sector-images" @@ -819,8 +819,8 @@ msgstr "Kan Ghostscript niet initialiseren" msgid "Unable to initialize GhostPCL" msgstr "Kan GhostPCL niet initialiseren" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "MO-images" @@ -906,14 +906,14 @@ msgstr "Filteren op CPU type voor de geselecteerde machine is niet mogelijk met msgid "Continue" msgstr "Doorgaan" -msgid "Cassette: %s" -msgstr "Cassette: %s" +msgid "Cassette: %1" +msgstr "Cassette: %1" msgid "Cassette images" msgstr "Cassette-images" -msgid "Cartridge %i: %ls" -msgstr "Cartridge %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartridge %1: %2" msgid "Cartridge images" msgstr "Cartridge-images" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Onbekende bus" msgid "Null Driver" msgstr "Null Driver" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Rendergedrag" @@ -2046,8 +2046,8 @@ msgstr "Named Pipe (Server)" msgid "Host Serial Passthrough" msgstr "Host seriële doorgave" -msgid "Eject %s" -msgstr "Uitwerpen %s" +msgid "E&ject %1" +msgstr "&Uitwerpen %1" msgid "&Unmute" msgstr "&Geluid aanzetten" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 3b29c3415..a72810b01 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -642,8 +642,8 @@ msgstr "Naciśnij klawisze Ctrl+Alt+PgDn aby wrócić to trybu okna." msgid "Speed" msgstr "Szybkość" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Obrazy ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Domyślny" -msgid "%i Wait state(s)" -msgstr "%i Stany oczekiwania" +msgid "%1 Wait state(s)" +msgstr "%1 Stany oczekiwania" msgid "Type" msgstr "Rodzaj" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Żaden" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Dyskietka %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Dyskietka %1 (%2): %3" msgid "Advanced sector images" msgstr "Zaawansowane obrazy sektorów" @@ -819,8 +819,8 @@ msgstr "Nie można zainicjować Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Nie można zainicjować GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Obrazy MO" @@ -906,14 +906,14 @@ msgstr "Wybór rodzaju procesora oparty na wybranej maszynie jest wyłączony dl msgid "Continue" msgstr "Kontynuuj" -msgid "Cassette: %s" -msgstr "Kaseta: %s" +msgid "Cassette: %1" +msgstr "Kaseta: %1" msgid "Cassette images" msgstr "Obrazy kaset" -msgid "Cartridge %i: %ls" -msgstr "Kartrydż %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Kartrydż %1: %2" msgid "Cartridge images" msgstr "Obrazy kartrydżu" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Nieznana magistrala" msgid "Null Driver" msgstr "Null Driver" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Zachowanie renderowania" @@ -2046,8 +2046,8 @@ msgstr "Nazwana rura (serwer)" msgid "Host Serial Passthrough" msgstr "Przejście przez port szeregowy hosta" -msgid "Eject %s" -msgstr "Wyjmij %s" +msgid "E&ject %1" +msgstr "W&yjmij %1" msgid "&Unmute" msgstr "&Wycisz" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 9f0370f5e..3535f63b9 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -642,8 +642,8 @@ msgstr "Use Ctrl+Alt+PgDn para retornar ao modo janela" msgid "Speed" msgstr "Velocidade" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Imagens ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Padrão" -msgid "%i Wait state(s)" -msgstr "%i estado(s) de espera" +msgid "%1 Wait state(s)" +msgstr "%1 estado(s) de espera" msgid "Type" msgstr "Tipo" @@ -795,11 +795,11 @@ msgstr "Sistema de Controle de Voo Thrustmaster" msgid "None" msgstr "Nenhum" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CCS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CCS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disquete %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disquete %1 (%2): %3" msgid "Advanced sector images" msgstr "Imagens de setor avançado" @@ -819,8 +819,8 @@ msgstr "Não foi possível inicializar o Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Não foi possível inicializar o GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "Magneto-óptico %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "Magneto-óptico %1 (%2): %3" msgid "MO images" msgstr "Imagens magneto-ópticas" @@ -906,14 +906,14 @@ msgstr "A filtragem do tipo de CPU baseada na máquina selecionada está desativ msgid "Continue" msgstr "Continuar" -msgid "Cassette: %s" -msgstr "Cassete: %s" +msgid "Cassette: %1" +msgstr "Cassete: %1" msgid "Cassette images" msgstr "Imagens de cassete" -msgid "Cartridge %i: %ls" -msgstr "Cartucho %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartucho %1: %2" msgid "Cartridge images" msgstr "Imagens de cartucho" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Barramento desconhecido" msgid "Null Driver" msgstr "Driver nulo" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Comportamento de renderização" @@ -2046,8 +2046,8 @@ msgstr "Tubo nomeado (servidor)" msgid "Host Serial Passthrough" msgstr "Passagem da porta serial do host" -msgid "Eject %s" -msgstr "Ejetar %s" +msgid "E&ject %1" +msgstr "E&jetar %1" msgid "&Unmute" msgstr "&Reativar som" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index f665424e0..ea6856347 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -642,8 +642,8 @@ msgstr "Pressione Ctrl+Alt+PgDn para voltar ao modo de janela." msgid "Speed" msgstr "Velocidade" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Imagens ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Padrão" -msgid "%i Wait state(s)" -msgstr "%i estado(s) de espera" +msgid "%1 Wait state(s)" +msgstr "%1 estado(s) de espera" msgid "Type" msgstr "Tipo" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Nenhum" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CCS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CCS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disquete %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disquete %1 (%2): %3" msgid "Advanced sector images" msgstr "Imagens avançadas de sector" @@ -819,8 +819,8 @@ msgstr "Não foi possível inicializar o Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Não foi possível inicializar o GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "Magneto-óptico %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "Magneto-óptico %1 (%2): %3" msgid "MO images" msgstr "Imagens magneto-ópticas" @@ -906,14 +906,14 @@ msgstr "A filtragem do tipo de CPU baseada na máquina escolhida está desativad msgid "Continue" msgstr "Continuar" -msgid "Cassette: %s" -msgstr "Cassete: %s" +msgid "Cassette: %1" +msgstr "Cassete: %1" msgid "Cassette images" msgstr "Imagens de cassete" -msgid "Cartridge %i: %ls" -msgstr "Cartucho %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartucho %1: %2" msgid "Cartridge images" msgstr "Imagens de cartucho" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Autocarro desconhecido" msgid "Null Driver" msgstr "Condutor nulo" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Comportamento de renderização" @@ -2046,8 +2046,8 @@ msgstr "Tubo nomeado (servidor)" msgid "Host Serial Passthrough" msgstr "Passagem da porta de série do anfitrião" -msgid "Eject %s" -msgstr "Ejetar %s" +msgid "E&ject %1" +msgstr "E&jetar %1" msgid "&Unmute" msgstr "&Reativar som" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 92542b70d..fd6a1d72a 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -642,8 +642,8 @@ msgstr "Нажмите Ctrl+Alt+PgDn для возврата в оконный msgid "Speed" msgstr "Скорость" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Образы ZIP" @@ -750,8 +750,8 @@ msgstr "КБ" msgid "Default" msgstr "По умолчанию" -msgid "%i Wait state(s)" -msgstr "%i WS" +msgid "%1 Wait state(s)" +msgstr "%1 WS" msgid "Type" msgstr "Тип" @@ -795,11 +795,11 @@ msgstr "Система управления полётом Thrustmaster" msgid "None" msgstr "Нет" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u МБ (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 МБ (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Дисковод %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Дисковод %1 (%2): %3" msgid "Advanced sector images" msgstr "Расширенные образы секторов" @@ -819,8 +819,8 @@ msgstr "Невозможно инициализировать Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Невозможно инициализировать GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "Магнитооптический %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "Магнитооптический %1 (%2): %3" msgid "MO images" msgstr "Образы магнитооптических дисков" @@ -906,14 +906,14 @@ msgstr "Выбор типов ЦП для этой системной платы msgid "Continue" msgstr "Продолжить" -msgid "Cassette: %s" -msgstr "Кассета: %s" +msgid "Cassette: %1" +msgstr "Кассета: %1" msgid "Cassette images" msgstr "Образы кассет" -msgid "Cartridge %i: %ls" -msgstr "Картридж %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Картридж %1: %2" msgid "Cartridge images" msgstr "Образы картриджей" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 КБ" @@ -1272,8 +1272,8 @@ msgstr "Неизвестная шина" msgid "Null Driver" msgstr "Нулевой драйвер" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Режим рендеринга" @@ -2046,8 +2046,8 @@ msgstr "Именованный пайп (Сервер)" msgid "Host Serial Passthrough" msgstr "Последовательный порт хоста" -msgid "Eject %s" -msgstr "Извлечь %s" +msgid "E&ject %1" +msgstr "И&звлечь %1" msgid "&Unmute" msgstr "В&ключить звук" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 1d8768dd8..b77ff5695 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -642,8 +642,8 @@ msgstr "Stlačte Ctrl+Alt+PgDn pre návrat z režimu celej obrazovky." msgid "Speed" msgstr "Rýchlosť" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Obrazy ZIP diskov" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Východiskové" -msgid "%i Wait state(s)" -msgstr "%i čakací stav(y)" +msgid "%1 Wait state(s)" +msgstr "%1 čakací stav(y)" msgid "Type" msgstr "Typ" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Žiadne" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disketová mechanika %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disketová mechanika %1 (%2): %3" msgid "Advanced sector images" msgstr "Rozšírené sektorové obrazy" @@ -819,8 +819,8 @@ msgstr "Nastala chyba pri inicializácii knižnice Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Nastala chyba pri inicializácii knižnice GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Obrazy MO" @@ -906,14 +906,14 @@ msgstr "Pre túto konfiguráciu bolo vypnuté filtrovanie procesorov podľa zvol msgid "Continue" msgstr "Pokračovať" -msgid "Cassette: %s" -msgstr "Kazeta: %s" +msgid "Cassette: %1" +msgstr "Kazeta: %1" msgid "Cassette images" msgstr "Kazetové nahrávky" -msgid "Cartridge %i: %ls" -msgstr "Cartridge %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Cartridge %1: %2" msgid "Cartridge images" msgstr "Obrazy cartridge" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Neznáma zbernica" msgid "Null Driver" msgstr "Nulový ovládač" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" @@ -2047,8 +2047,8 @@ msgstr "Pomenované potrubie (server)" msgid "Host Serial Passthrough" msgstr "Priechod sériového portu hostiteľa" -msgid "Eject %s" -msgstr "Vystrihnúť %s" +msgid "E&ject %1" +msgstr "&Vystrihnúť %1" msgid "&Unmute" msgstr "&Roztíšiť" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 0eeca62f8..9bedaa6cf 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -642,8 +642,8 @@ msgstr "Pritisnite Ctrl+Alt+PgDn za povratek iz celozaslonskega načina." msgid "Speed" msgstr "Hitrost" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP slike" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Privzeto" -msgid "%i Wait state(s)" -msgstr "%i stanj čakanja" +msgid "%1 Wait state(s)" +msgstr "%1 stanj čakanja" msgid "Type" msgstr "Vrsta" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Brez" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disketa %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disketa %1 (%2): %3" msgid "Advanced sector images" msgstr "Napredne sektorske slike" @@ -819,8 +819,8 @@ msgstr "Ghostscript-a ni bilo mogoče inicializirati" msgid "Unable to initialize GhostPCL" msgstr "GhostPCL-ja ni bilo mogoče inicializirati" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Slike MO" @@ -906,14 +906,14 @@ msgstr "Filtriranje vrste procesorja glede na izbran sistem je onemogočeno za t msgid "Continue" msgstr "Nadaljuj" -msgid "Cassette: %s" -msgstr "Kaseta: %s" +msgid "Cassette: %1" +msgstr "Kaseta: %1" msgid "Cassette images" msgstr "Slike kaset" -msgid "Cartridge %i: %ls" -msgstr "Spominski vložek %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Spominski vložek %1: %2" msgid "Cartridge images" msgstr "Slike spominskega vložka" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Neznano vodilo" msgid "Null Driver" msgstr "Ničelni gonilnik" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Obnašanje pri upodabljanju" @@ -2046,8 +2046,8 @@ msgstr "Poimenovana cev (Strežnik)" msgid "Host Serial Passthrough" msgstr "Prepustno serijskih vrat gostitelja" -msgid "Eject %s" -msgstr "Izvrzi %s" +msgid "E&ject %1" +msgstr "I&zvrzi %1" msgid "&Unmute" msgstr "&Vklopi zvok" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 41930bd96..5936f39c9 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -642,8 +642,8 @@ msgstr "Pencere moduna geri dönmek için Ctrl+Alt+PgDn tuşlarına basın." msgid "Speed" msgstr "Hız" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP imajları" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Varsayılan" -msgid "%i Wait state(s)" -msgstr "%i Bekleme durumları" +msgid "%1 Wait state(s)" +msgstr "%1 Bekleme durumları" msgid "Type" msgstr "Tür" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Hiçbiri" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Disket %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Disket %1 (%2): %3" msgid "Advanced sector images" msgstr "Gelişmiş sektör imajları" @@ -819,8 +819,8 @@ msgstr "Ghostscript başlatılamadı" msgid "Unable to initialize GhostPCL" msgstr "GhostPCL başlatılamadı" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "MO imajları" @@ -906,14 +906,14 @@ msgstr "Seçtiğiniz makineye uygun işlemci türü filtrelemesi bu emüle edile msgid "Continue" msgstr "Devam et" -msgid "Cassette: %s" -msgstr "Kaset: %s" +msgid "Cassette: %1" +msgstr "Kaset: %1" msgid "Cassette images" msgstr "Kaset imajları" -msgid "Cartridge %i: %ls" -msgstr "Kartuş %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Kartuş %1: %2" msgid "Cartridge images" msgstr "Kartuş imajları" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Bilinmeyen veri yolu" msgid "Null Driver" msgstr "Null sürücü" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "İşleyiş davranışı" @@ -2046,8 +2046,8 @@ msgstr "Adlandırılmış boru (Sunucu)" msgid "Host Serial Passthrough" msgstr "Ana bilgisayar seri port geçişi" -msgid "Eject %s" -msgstr "%s diskini çıkar" +msgid "E&ject %1" +msgstr "%1 diskini &çıkar" msgid "&Unmute" msgstr "&Sesi aç" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 4632d001b..36e227d6f 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -642,8 +642,8 @@ msgstr "Натисніть Ctrl+Alt+PgDn для повернення у віко msgid "Speed" msgstr "Швидкість" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Образи ZIP" @@ -750,8 +750,8 @@ msgstr "КБ" msgid "Default" msgstr "За замовчуванням" -msgid "%i Wait state(s)" -msgstr "%i WS" +msgid "%1 Wait state(s)" +msgstr "%1 WS" msgid "Type" msgstr "Тип" @@ -795,11 +795,11 @@ msgstr "Система управління польотом Thrustmaster" msgid "None" msgstr "Ні" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u МБ (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 МБ (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Дисковод %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Дисковод %1 (%2): %3" msgid "Advanced sector images" msgstr "Розширені образи секторів" @@ -819,8 +819,8 @@ msgstr "Неможливо ініціалізувати Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Неможливо ініціалізувати GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "Магнітооптичний %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "Магнітооптичний %1 (%2): %3" msgid "MO images" msgstr "Образи магнітооптичних дисків" @@ -906,14 +906,14 @@ msgstr "Вибір типів ЦП для цієї системної плати msgid "Continue" msgstr "Продовжити" -msgid "Cassette: %s" -msgstr "Касета: %s" +msgid "Cassette: %1" +msgstr "Касета: %1" msgid "Cassette images" msgstr "Образи касет" -msgid "Cartridge %i: %ls" -msgstr "Картридж %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Картридж %1: %2" msgid "Cartridge images" msgstr "Образи картриджів" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 КБ" @@ -1272,8 +1272,8 @@ msgstr "Невідома шина" msgid "Null Driver" msgstr "Нульовий драйвер" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Поведінка рендерингу" @@ -2046,8 +2046,8 @@ msgstr "Іменований пайп (сервер)" msgid "Host Serial Passthrough" msgstr "Пропуск послідовного порту хоста" -msgid "Eject %s" -msgstr "Вилучити %s" +msgid "E&ject %1" +msgstr "&Вилучити %1" msgid "&Unmute" msgstr "&Увімкнути звук" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index b8322d600..1d1a3697e 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -642,8 +642,8 @@ msgstr "Bấm Ctrl+Alt+PgDn để quay lại chế độ cửa sổ." msgid "Speed" msgstr "Vận tốc" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "Ảnh đĩa ZIP" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "Mặc định" -msgid "%i Wait state(s)" -msgstr "%i trạng thái chờ" +msgid "%1 Wait state(s)" +msgstr "%1 trạng thái chờ" msgid "Type" msgstr "Loại" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Không có" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "Đĩa mềm %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "Đĩa mềm %1 (%2): %3" msgid "Advanced sector images" msgstr "Ảnh (đĩa) sector nâng cao" @@ -819,8 +819,8 @@ msgstr "Không thể khởi tạo Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "Không thể khởi tạo GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" msgid "MO images" msgstr "Ảnh đĩa MO" @@ -906,14 +906,14 @@ msgstr "Phần chọn loại CPU dựa trên mẫu máy đã chọn bị vô hi msgid "Continue" msgstr "Tiếp tục" -msgid "Cassette: %s" -msgstr "Cassette: %s" +msgid "Cassette: %1" +msgstr "Cassette: %1" msgid "Cassette images" msgstr "Ảnh đĩa Cassette" -msgid "Cartridge %i: %ls" -msgstr "Băng cartridge %i: %ls" +msgid "Cartridge %1: %2" +msgstr "Băng cartridge %1: %2" msgid "Cartridge images" msgstr "Ảnh đĩa băng cartridge" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "CD-ROM %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "Bus không xác định" msgid "Null Driver" msgstr "Trình điều khiển NULL" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i ( %ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "Hành vi kết xuất" @@ -2046,8 +2046,8 @@ msgstr "Đường ống có tên (máy chủ)" msgid "Host Serial Passthrough" msgstr "Thông qua cổng serial của máy chủ" -msgid "Eject %s" -msgstr "Đẩy đĩa ra %s" +msgid "E&ject %1" +msgstr "Đẩy đĩ&a ra %1" msgid "&Unmute" msgstr "&Mở tiếng" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 32358584e..b39c64563 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -642,8 +642,8 @@ msgstr "按下 Ctrl+Alt+PgDn 返回到窗口模式。" msgid "Speed" msgstr "速度" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP 映像" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "默认" -msgid "%i Wait state(s)" -msgstr "%i 等待状态 (WS)" +msgid "%1 Wait state(s)" +msgstr "%1 等待状态 (WS)" msgid "Type" msgstr "类型" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "无" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "软盘 %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "软盘 %1 (%2): %3" msgid "Advanced sector images" msgstr "高级扇区映像" @@ -819,8 +819,8 @@ msgstr "无法初始化 Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "无法初始化 GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "磁光盘 %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "磁光盘 %1 (%2): %3" msgid "MO images" msgstr "磁光盘映像" @@ -906,14 +906,14 @@ msgstr "此模拟计算机禁用了基于选定计算机的 CPU 类型过滤。\ msgid "Continue" msgstr "继续" -msgid "Cassette: %s" -msgstr "磁带: %s" +msgid "Cassette: %1" +msgstr "磁带: %1" msgid "Cassette images" msgstr "磁带映像" -msgid "Cartridge %i: %ls" -msgstr "卡带 %i: %ls" +msgid "Cartridge %1: %2" +msgstr "卡带 %1: %2" msgid "Cartridge images" msgstr "卡带映像" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "光盘 %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "光盘 %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "未知总线" msgid "Null Driver" msgstr "空驱动程序" -msgid "NIC %02i (%ls) %ls" -msgstr "NIC %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" msgid "Render behavior" msgstr "渲染行为" @@ -2046,8 +2046,8 @@ msgstr "命名管道(服务器)" msgid "Host Serial Passthrough" msgstr "主机串行端口直通" -msgid "Eject %s" -msgstr "弹出 %s" +msgid "E&ject %1" +msgstr "弹出 %1(&J)" msgid "&Unmute" msgstr "解除静音(&U)" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 6b7420bc7..3526f696d 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -642,8 +642,8 @@ msgstr "按下 Ctrl+Alt+PgDn 返回到視窗模式。" msgid "Speed" msgstr "速度" -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP 映像" @@ -750,8 +750,8 @@ msgstr "KB" msgid "Default" msgstr "預設" -msgid "%i Wait state(s)" -msgstr "%i 等待狀態 (WS)" +msgid "%1 Wait state(s)" +msgstr "%1 等待狀態 (WS)" msgid "Type" msgstr "類型" @@ -795,11 +795,11 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "無" -msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %i (%s): %ls" -msgstr "軟碟 %i (%s): %ls" +msgid "Floppy %1 (%2): %3" +msgstr "軟碟 %1 (%2): %3" msgid "Advanced sector images" msgstr "進階磁區映像" @@ -819,8 +819,8 @@ msgstr "無法初始化 Ghostscript" msgid "Unable to initialize GhostPCL" msgstr "無法初始化 GhostPCL" -msgid "MO %i (%ls): %ls" -msgstr "磁光碟 %i (%ls): %ls" +msgid "MO %1 (%2): %3" +msgstr "磁光碟 %1 (%2): %3" msgid "MO images" msgstr "磁光碟映像" @@ -906,14 +906,14 @@ msgstr "此模擬電腦停用了基於選定電腦的 CPU 類型過濾。\n\n能 msgid "Continue" msgstr "繼續" -msgid "Cassette: %s" -msgstr "磁帶: %s" +msgid "Cassette: %1" +msgstr "磁帶: %1" msgid "Cassette images" msgstr "磁帶映像" -msgid "Cartridge %i: %ls" -msgstr "卡帶 %i: %ls" +msgid "Cartridge %1: %2" +msgstr "卡帶 %1: %2" msgid "Cartridge images" msgstr "卡帶映像" @@ -1080,8 +1080,8 @@ msgstr "IDE" msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %i (%s): %s" -msgstr "光碟 %i (%s): %s" +msgid "CD-ROM %1 (%2): %3" +msgstr "光碟 %1 (%2): %3" msgid "160 KB" msgstr "160 KB" @@ -1272,8 +1272,8 @@ msgstr "未知匯流排" msgid "Null Driver" msgstr "空驅動程式" -msgid "NIC %02i (%ls) %ls" -msgstr "網路卡 %02i (%ls) %ls" +msgid "NIC %1 (%2) %3" +msgstr "網路卡 %1 (%2) %3" msgid "Render behavior" msgstr "渲染行為" @@ -2046,8 +2046,8 @@ msgstr "已命名管道 (伺服器)" msgid "Host Serial Passthrough" msgstr "主機序列埠的直通" -msgid "Eject %s" -msgstr "退出 %s" +msgid "E&ject %1" +msgstr "退出 %1(&J)" msgid "&Unmute" msgstr "解除靜音(&U)" diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index 2acaaeacc..9e5563536 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -77,8 +77,7 @@ HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent) for (int i = 0; i < 127; i++) { uint64_t size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; uint32_t size_mb = size >> 11LL; - // QString text = QString("%1 MiB (CHS: %2, %3, %4)").arg(size_mb).arg(hdd_table[i][0]).arg(hdd_table[i][1]).arg(hdd_table[i][2]); - QString text = QString::asprintf(tr("%u MB (CHS: %i, %i, %i)").toUtf8().constData(), size_mb, (hdd_table[i][0]), (hdd_table[i][1]), (hdd_table[i][2])); + QString text = tr("%1 MB (CHS: %2, %3, %4)").arg(size_mb).arg(hdd_table[i][0]).arg(hdd_table[i][1]).arg(hdd_table[i][2]); Models::AddEntry(model, text, i); } Models::AddEntry(model, tr("Custom..."), 127); diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 478f64c2a..3e7c84ca7 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -93,7 +93,7 @@ MediaMenu::refresh(QMenu *parentMenu) cassetteMenu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { cassetteImageHistoryPos[slot] = cassetteMenu->children().count(); - cassetteMenu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, slot]() { cassetteMenuSelect(slot); })->setCheckable(false); + cassetteMenu->addAction(tr("Image %1").arg(slot), [this, slot]() { cassetteMenuSelect(slot); })->setCheckable(false); } cassetteMenu->addSeparator(); cassetteRecordPos = cassetteMenu->children().count(); @@ -118,7 +118,7 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { cartridgeImageHistoryPos[slot] = menu->children().count(); - menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { cartridgeMenuSelect(i, slot); })->setCheckable(false); + menu->addAction(tr("Image %1").arg(slot), [this, i, slot]() { cartridgeMenuSelect(i, slot); })->setCheckable(false); } menu->addSeparator(); cartridgeEjectPos = menu->children().count(); @@ -138,7 +138,7 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { floppyImageHistoryPos[slot] = menu->children().count(); - menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { floppyMenuSelect(i, slot); })->setCheckable(false); + menu->addAction(tr("Image %1").arg(slot), [this, i, slot]() { floppyMenuSelect(i, slot); })->setCheckable(false); } menu->addSeparator(); floppyExportPos = menu->children().count(); @@ -161,7 +161,7 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { cdromImageHistoryPos[slot] = menu->children().count(); - menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { cdromReload(i, slot); })->setCheckable(false); + menu->addAction(tr("Image %1").arg(slot), [this, i, slot]() { cdromReload(i, slot); })->setCheckable(false); } menu->addSeparator(); #ifdef Q_OS_WINDOWS @@ -191,7 +191,7 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { zipImageHistoryPos[slot] = menu->children().count(); - menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { zipReload(i, slot); })->setCheckable(false); + menu->addAction(tr("Image %1").arg(slot), [this, i, slot]() { zipReload(i, slot); })->setCheckable(false); } menu->addSeparator(); zipEjectPos = menu->children().count(); @@ -210,7 +210,7 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { moImageHistoryPos[slot] = menu->children().count(); - menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { moReload(i, slot); })->setCheckable(false); + menu->addAction(tr("Image %1").arg(slot), [this, i, slot]() { moReload(i, slot); })->setCheckable(false); } menu->addSeparator(); moEjectPos = menu->children().count(); @@ -323,8 +323,7 @@ MediaMenu::cassetteUpdateMenu() recordMenu->setChecked(isSaving); playMenu->setChecked(!isSaving); - cassetteMenu->setTitle(QString::asprintf(tr("Cassette: %s").toUtf8().constData(), - (name.isEmpty() ? tr("(empty)") : name).toUtf8().constData())); + cassetteMenu->setTitle(tr("Cassette: %1").arg(name.isEmpty() ? tr("(empty)") : name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { updateImageHistory(0, slot, ui::MediaType::Cassette); @@ -389,8 +388,7 @@ MediaMenu::cartridgeUpdateMenu(int i) auto childs = menu->children(); auto *ejectMenu = dynamic_cast(childs[cartridgeEjectPos]); ejectMenu->setEnabled(!name.isEmpty()); - // menu->setTitle(tr("Cartridge %1: %2").arg(QString::number(i+1), name.isEmpty() ? tr("(empty)") : name)); - menu->setTitle(QString::asprintf(tr("Cartridge %i: %ls").toUtf8().constData(), i + 1, name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + menu->setTitle(tr("Cartridge %1: %2").arg(QString::number(i + 1), name.isEmpty() ? tr("(empty)") : name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { updateImageHistory(i, slot, ui::MediaType::Cartridge); @@ -491,7 +489,7 @@ MediaMenu::floppyUpdateMenu(int i) auto *ejectMenu = dynamic_cast(childs[floppyEjectPos]); auto *exportMenu = dynamic_cast(childs[floppyExportPos]); ejectMenu->setEnabled(!name.isEmpty()); - ejectMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData())); + ejectMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(fi.fileName())); exportMenu->setEnabled(!name.isEmpty()); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { @@ -499,8 +497,8 @@ MediaMenu::floppyUpdateMenu(int i) } int type = fdd_get_type(i); - // floppyMenus[i]->setTitle(tr("Floppy %1 (%2): %3").arg(QString::number(i+1), fdd_getname(type), name.isEmpty() ? tr("(empty)") : name)); - floppyMenus[i]->setTitle(QString::asprintf(tr("Floppy %i (%s): %ls").toUtf8().constData(), i + 1, fdd_getname(type), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + floppyMenus[i]->setTitle(tr("Floppy %1 (%2): %3").arg(QString::number(i + 1), fdd_getname(type), name.isEmpty() ? tr("(empty)") : name)); + } void @@ -749,7 +747,7 @@ MediaMenu::cdromUpdateMenu(int i) 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())); + imageMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(menu_item_name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) updateImageHistory(i, slot, ui::MediaType::Optical); @@ -769,8 +767,7 @@ MediaMenu::cdromUpdateMenu(int i) break; } - // menu->setTitle(tr("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); - menu->setTitle(QString::asprintf(tr("CD-ROM %i (%s): %s").toUtf8().constData(), i + 1, busName.toUtf8().data(), name.isEmpty() ? tr("(empty)").toUtf8().data() : name2.toUtf8().data())); + menu->setTitle(tr("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name2)); } void @@ -899,8 +896,7 @@ MediaMenu::zipUpdateMenu(int i) break; } - // menu->setTitle(tr("ZIP %1 %2 (%3): %4").arg((zip_drives[i].is_250 > 0) ? "250" : "100", QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); - menu->setTitle(QString::asprintf(tr("ZIP %03i %i (%s): %ls").toUtf8().constData(), (zip_drives[i].is_250 > 0) ? 250 : 100, i + 1, busName.toUtf8().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + menu->setTitle(tr("ZIP %1 %2 (%3): %4").arg((zip_drives[i].is_250 > 0) ? QString("250") : QString("100"), QString::number(i + 1), busName, name.isEmpty() ? tr("(empty)") : name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) updateImageHistory(i, slot, ui::MediaType::Zip); @@ -1035,7 +1031,7 @@ MediaMenu::moUpdateMenu(int i) break; } - menu->setTitle(QString::asprintf(tr("MO %i (%ls): %ls").toUtf8().constData(), i + 1, busName.toStdU16String().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + menu->setTitle(tr("MO %1 (%2): %3").arg(QString::number(i + 1), busName, name.isEmpty() ? tr("(empty)") : name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) updateImageHistory(i, slot, ui::MediaType::Mo); @@ -1087,7 +1083,7 @@ MediaMenu::nicUpdateMenu(int i) auto *connectedAction = dynamic_cast(childs[netDisconnPos]); connectedAction->setChecked(network_is_connected(i)); - menu->setTitle(QString::asprintf(tr("NIC %02i (%ls) %ls").toUtf8().constData(), i + 1, netType.toStdU16String().data(), devName.toStdU16String().data())); + menu->setTitle(tr("NIC %1 (%2) %3").arg(QString::number(i + 1), netType, devName)); } QString diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 34968b288..939cd9eb2 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -69,7 +69,7 @@ SettingsMachine::SettingsMachine(QWidget *parent) waitStatesModel->setData(idx, 0, Qt::UserRole); for (int i = 0; i < 8; ++i) { idx = waitStatesModel->index(i + 1, 0); - waitStatesModel->setData(idx, QString::asprintf(tr("%i Wait state(s)").toUtf8().constData(), i), Qt::DisplayRole); + waitStatesModel->setData(idx, tr("%1 Wait state(s)").arg(i), Qt::DisplayRole); waitStatesModel->setData(idx, i + 1, Qt::UserRole); } From 1819539c976659fb5ba24bd32be5e5d39ad9f8df Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 11 Apr 2025 05:16:39 +0500 Subject: [PATCH 0712/1190] qt: Make filename/path display consistent across media menus - All media history entries now display the full path - All "Eject" menu items now display the file name --- src/qt/languages/86box.pot | 5 +---- src/qt/languages/ca-ES.po | 7 ++----- src/qt/languages/cs-CZ.po | 7 ++----- src/qt/languages/de-DE.po | 7 ++----- src/qt/languages/es-ES.po | 7 ++----- src/qt/languages/fi-FI.po | 7 ++----- src/qt/languages/fr-FR.po | 7 ++----- src/qt/languages/hr-HR.po | 7 ++----- src/qt/languages/hu-HU.po | 7 ++----- src/qt/languages/it-IT.po | 7 ++----- src/qt/languages/ja-JP.po | 7 ++----- src/qt/languages/ko-KR.po | 7 ++----- src/qt/languages/nl-NL.po | 7 ++----- src/qt/languages/pl-PL.po | 7 ++----- src/qt/languages/pt-BR.po | 7 ++----- src/qt/languages/pt-PT.po | 7 ++----- src/qt/languages/ru-RU.po | 7 ++----- src/qt/languages/sk-SK.po | 7 ++----- src/qt/languages/sl-SI.po | 7 ++----- src/qt/languages/tr-TR.po | 7 ++----- src/qt/languages/uk-UA.po | 7 ++----- src/qt/languages/vi-VN.po | 7 ++----- src/qt/languages/zh-CN.po | 7 ++----- src/qt/languages/zh-TW.po | 7 ++----- src/qt/qt_mediamenu.cpp | 43 ++++++++++++++++++++++---------------- src/qt/qt_mediamenu.hpp | 3 +-- 26 files changed, 73 insertions(+), 139 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index a778f9f6d..07dfb7cc5 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -249,7 +249,7 @@ msgstr "" msgid "E&mpty" msgstr "" -msgid "&Reload previous image" +msgid "Reload previous image" msgstr "" msgid "&Folder..." @@ -1260,9 +1260,6 @@ msgstr "" msgid "Create..." msgstr "" -msgid "previous image" -msgstr "" - msgid "Host CD/DVD Drive (%1)" msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 808799859..dc0a9df2a 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -249,8 +249,8 @@ msgstr "&Silenciar" msgid "E&mpty" msgstr "E&xtreure disc" -msgid "&Reload previous image" -msgstr "&Recarregar imatge anterior" +msgid "Reload previous image" +msgstr "Recarregar imatge anterior" msgid "&Folder..." msgstr "&Carpeta ..." @@ -1260,9 +1260,6 @@ msgstr "Esborrar la història de imatges" msgid "Create..." msgstr "Crear ..." -msgid "previous image" -msgstr "imatge anterior" - msgid "Host CD/DVD Drive (%1)" msgstr "Unitat CD/DVD d'amfitrió (%1)" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index d3985b67a..7e76d3760 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -249,8 +249,8 @@ msgstr "&Ztišit" msgid "E&mpty" msgstr "&Vyjmout" -msgid "&Reload previous image" -msgstr "&Načíst znova předchozí obraz" +msgid "Reload previous image" +msgstr "Načíst znova předchozí obraz" msgid "&Folder..." msgstr "&Složka..." @@ -1260,9 +1260,6 @@ msgstr "Vymaž historie snímků" msgid "Create..." msgstr "Vytvoř..." -msgid "previous image" -msgstr "předchozí obraz" - msgid "Host CD/DVD Drive (%1)" msgstr "Jednotka CD/DVD hostitele (%1)" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 781269af9..f545729a8 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -249,8 +249,8 @@ msgstr "&Stummschalten" msgid "E&mpty" msgstr "L&eer" -msgid "&Reload previous image" -msgstr "&Voriges Abbild neu laden" +msgid "Reload previous image" +msgstr "Voriges Abbild neu laden" msgid "&Folder..." msgstr "&Verzeichnis..." @@ -1263,9 +1263,6 @@ msgstr "Abbildverlauf löschen" msgid "Create..." msgstr "Erstellen..." -msgid "previous image" -msgstr "Vorheriges Abbild" - msgid "Host CD/DVD Drive (%1)" msgstr "Host-CD/DVD-Laufwerk (%1)" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 3cdcedd98..0733f46ec 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -249,8 +249,8 @@ msgstr "&Silenciar" msgid "E&mpty" msgstr "E&xtraer disco" -msgid "&Reload previous image" -msgstr "&Recargar imagen previa" +msgid "Reload previous image" +msgstr "Recargar imagen previa" msgid "&Folder..." msgstr "&Carpeta..." @@ -1259,9 +1259,6 @@ msgstr "Eliminar historia de imágenes" msgid "Create..." msgstr "Crear..." -msgid "previous image" -msgstr "imagen previa" - msgid "Host CD/DVD Drive (%1)" msgstr "Unidad de CD/DVD anfitriona (%1)" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index ddae5c2ba..a7ac64eff 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -249,8 +249,8 @@ msgstr "&Mykistä" msgid "E&mpty" msgstr "&Tyhjä" -msgid "&Reload previous image" -msgstr "&Lataa edellinen levykuva uudelleen" +msgid "Reload previous image" +msgstr "Lataa edellinen levykuva uudelleen" msgid "&Folder..." msgstr "&Kansio..." @@ -1260,9 +1260,6 @@ msgstr "Tyhjennä kuvahistoria" msgid "Create..." msgstr "Luo..." -msgid "previous image" -msgstr "edellinen levykuva" - msgid "Host CD/DVD Drive (%1)" msgstr "Isäntä CD/DVD-asema (%1)" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index df5bf7ef6..434e8c31b 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -249,8 +249,8 @@ msgstr "&Couper" msgid "E&mpty" msgstr "E&jecter" -msgid "&Reload previous image" -msgstr "&Recharger image précedente" +msgid "Reload previous image" +msgstr "Recharger image précedente" msgid "&Folder..." msgstr "&Dossier..." @@ -1260,9 +1260,6 @@ msgstr "Effacer l'historique de l'image" msgid "Create..." msgstr "Créer..." -msgid "previous image" -msgstr "image précedente" - msgid "Host CD/DVD Drive (%1)" msgstr "Lecteur CD/DVD hôte (%1)" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index ecfd0c696..b202b39b5 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -249,8 +249,8 @@ msgstr "&Isključi zvuk" msgid "E&mpty" msgstr "&Prazno" -msgid "&Reload previous image" -msgstr "&Ponovo učitaj prethodnu sliku" +msgid "Reload previous image" +msgstr "Ponovo učitaj prethodnu sliku" msgid "&Folder..." msgstr "&Mapa..." @@ -1260,9 +1260,6 @@ msgstr "Očisti povijest slika" msgid "Create..." msgstr "Stvori..." -msgid "previous image" -msgstr "prethodna slika" - msgid "Host CD/DVD Drive (%1)" msgstr "CD/DVD pogon nositelja (%1)" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 79e0dd5e6..e9aa6a4ff 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -249,8 +249,8 @@ msgstr "&Némítás" msgid "E&mpty" msgstr "&Kiadás" -msgid "&Reload previous image" -msgstr "Előző képfájl &újratöltése" +msgid "Reload previous image" +msgstr "Előző képfájl újratöltése" msgid "&Folder..." msgstr "&Mappa..." @@ -1260,9 +1260,6 @@ msgstr "Törölje a kép előzményeit" msgid "Create..." msgstr "Hozzon létre..." -msgid "previous image" -msgstr "előző képfájl" - msgid "Host CD/DVD Drive (%1)" msgstr "Gazdag CD/DVD-meghajtó (%1)" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 832c5b3fc..2f31a9dba 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -249,8 +249,8 @@ msgstr "&Muto" msgid "E&mpty" msgstr "&Espelli" -msgid "&Reload previous image" -msgstr "&Ricarica l'immagine precedente" +msgid "Reload previous image" +msgstr "Ricarica l'immagine precedente" msgid "&Folder..." msgstr "&Cartella..." @@ -1260,9 +1260,6 @@ msgstr "Cancella la cronologia delle immagini" msgid "Create..." msgstr "Creare..." -msgid "previous image" -msgstr "immagine precedente" - msgid "Host CD/DVD Drive (%1)" msgstr "Unità CD/DVD host (%1)" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 4bf10f7fc..318d0dca5 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -249,8 +249,8 @@ msgstr "ミュート(&M)" msgid "E&mpty" msgstr "なし(&M)" -msgid "&Reload previous image" -msgstr "前のイメージを再読み込み(&R)" +msgid "Reload previous image" +msgstr "前のイメージを再読み込み" msgid "&Folder..." msgstr "フォルダ(&F)..." @@ -1260,9 +1260,6 @@ msgstr "クリア画像履歴" msgid "Create..." msgstr "作成..." -msgid "previous image" -msgstr "前の画像" - msgid "Host CD/DVD Drive (%1)" msgstr "ホスト CD/DVD ドライブ (%1)" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index d6a0c234a..027c5a778 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -249,8 +249,8 @@ msgstr "음소거(&M)" msgid "E&mpty" msgstr "비었음(&M)" -msgid "&Reload previous image" -msgstr "이전 이미지 다시 불러오기(&R)" +msgid "Reload previous image" +msgstr "이전 이미지 다시 불러오기" msgid "&Folder..." msgstr "폴더(&F)..." @@ -1260,9 +1260,6 @@ msgstr "이미지 기록 지우기" msgid "Create..." msgstr "만들기..." -msgid "previous image" -msgstr "이전 이미지" - msgid "Host CD/DVD Drive (%1)" msgstr "호스트 CD/DVD 드라이브 (%1)" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index d57c389e1..65e589b2b 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -249,8 +249,8 @@ msgstr "&Mute" msgid "E&mpty" msgstr "E&mpty" -msgid "&Reload previous image" -msgstr "&Herlaad vorige image" +msgid "Reload previous image" +msgstr "Herlaad vorige image" msgid "&Folder..." msgstr "&Map..." @@ -1260,9 +1260,6 @@ msgstr "Imagegeschiedenis verwijderen" msgid "Create..." msgstr "Creëer..." -msgid "previous image" -msgstr "vorige image" - msgid "Host CD/DVD Drive (%1)" msgstr "Host CD/DVD-station (%1)" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index a72810b01..4e93f9dd1 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -249,8 +249,8 @@ msgstr "&Ścisz" msgid "E&mpty" msgstr "P&usty" -msgid "&Reload previous image" -msgstr "&Przeładuj poprzedni obraz" +msgid "Reload previous image" +msgstr "Przeładuj poprzedni obraz" msgid "&Folder..." msgstr "&Teczka..." @@ -1260,9 +1260,6 @@ msgstr "Wyczyść historię obrazów" msgid "Create..." msgstr "Stwórz..." -msgid "previous image" -msgstr "poprzedni obraz" - msgid "Host CD/DVD Drive (%1)" msgstr "Napęd CD/DVD hosta (%1)" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 3535f63b9..3e0ec7ff1 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -249,8 +249,8 @@ msgstr "&Silenciar" msgid "E&mpty" msgstr "&Vazio" -msgid "&Reload previous image" -msgstr "&Recarregar imagem anterior" +msgid "Reload previous image" +msgstr "Recarregar imagem anterior" msgid "&Folder..." msgstr "&Pasta..." @@ -1260,9 +1260,6 @@ msgstr "Limpar histórico de imagens" msgid "Create..." msgstr "Criar..." -msgid "previous image" -msgstr "imagem anterior" - msgid "Host CD/DVD Drive (%1)" msgstr "Unidade de CD/DVD do anfitrião (%1)" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index ea6856347..9fb1ce342 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -249,8 +249,8 @@ msgstr "&Desativar som" msgid "E&mpty" msgstr "&CDROM vazio" -msgid "&Reload previous image" -msgstr "&Recarregar imagem anterior" +msgid "Reload previous image" +msgstr "Recarregar imagem anterior" msgid "&Folder..." msgstr "&Pasta..." @@ -1260,9 +1260,6 @@ msgstr "Limpar o histórico de imagens" msgid "Create..." msgstr "Criar..." -msgid "previous image" -msgstr "imagem anterior" - msgid "Host CD/DVD Drive (%1)" msgstr "Unidade de CD/DVD do anfitrião (%1)" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index fd6a1d72a..725f7adf6 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -249,8 +249,8 @@ msgstr "О&тключить звук" msgid "E&mpty" msgstr "П&устой" -msgid "&Reload previous image" -msgstr "&Снова загрузить предыдущий образ" +msgid "Reload previous image" +msgstr "Загрузить предыдущий образ" msgid "&Folder..." msgstr "&Папка..." @@ -1260,9 +1260,6 @@ msgstr "Очистить историю образов" msgid "Create..." msgstr "Создайте..." -msgid "previous image" -msgstr "предыдущее изображение" - msgid "Host CD/DVD Drive (%1)" msgstr "Главный CD/DVD-привод (%1)" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index b77ff5695..937b067fe 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -249,8 +249,8 @@ msgstr "&Stíšiť" msgid "E&mpty" msgstr "&Vystrihnúť" -msgid "&Reload previous image" -msgstr "&Načítať znova predchádzajúci obraz" +msgid "Reload previous image" +msgstr "Načítať znova predchádzajúci obraz" msgid "&Folder..." msgstr "&Zložka..." @@ -1260,9 +1260,6 @@ msgstr "Vymazanie histórie obrázkov" msgid "Create..." msgstr "Vytvorte..." -msgid "previous image" -msgstr "predchádzajúca snímka" - msgid "Host CD/DVD Drive (%1)" msgstr "Hostiteľská jednotka CD/DVD (%1)" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 9bedaa6cf..b28954b19 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -249,8 +249,8 @@ msgstr "&Utišaj" msgid "E&mpty" msgstr "&Prazen" -msgid "&Reload previous image" -msgstr "&Naloži zadnjo sliko" +msgid "Reload previous image" +msgstr "Naloži zadnjo sliko" msgid "&Folder..." msgstr "&Mapa..." @@ -1260,9 +1260,6 @@ msgstr "Jasna zgodovina slik" msgid "Create..." msgstr "Ustvari..." -msgid "previous image" -msgstr "zadnja slika" - msgid "Host CD/DVD Drive (%1)" msgstr "Pogon CD/DVD gostitelja (%1)" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 5936f39c9..54bdac06e 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -249,8 +249,8 @@ msgstr "&Sesi kapat" msgid "E&mpty" msgstr "İmajı &çıkar" -msgid "&Reload previous image" -msgstr "&Önceki imajı yeniden seç" +msgid "Reload previous image" +msgstr "Önceki imajı yeniden seç" msgid "&Folder..." msgstr "&Klasör..." @@ -1260,9 +1260,6 @@ msgstr "İmaj geçmişini temizleyin" msgid "Create..." msgstr "Oluştur..." -msgid "previous image" -msgstr "önceki imaj" - msgid "Host CD/DVD Drive (%1)" msgstr "Ana bilgisayar CD/DVD sürücüsü (%1)" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 36e227d6f..b78bb0661 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -249,8 +249,8 @@ msgstr "&Відключити звук" msgid "E&mpty" msgstr "&Пустий" -msgid "&Reload previous image" -msgstr "&Знову завантажити попередній образ" +msgid "Reload previous image" +msgstr "Знову завантажити попередній образ" msgid "&Folder..." msgstr "&Тека..." @@ -1260,9 +1260,6 @@ msgstr "Очистити історію образів" msgid "Create..." msgstr "Створити..." -msgid "previous image" -msgstr "попередній образ" - msgid "Host CD/DVD Drive (%1)" msgstr "CD/DVD привід хоста (%1)" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 1d1a3697e..e4b15a971 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -249,8 +249,8 @@ msgstr "Tắt tiến&g" msgid "E&mpty" msgstr "Làm trố&ng đĩa" -msgid "&Reload previous image" -msgstr "Load đĩ&a trước đó" +msgid "Reload previous image" +msgstr "Load đĩa trước đó" msgid "&Folder..." msgstr "Thư mụ&c" @@ -1260,9 +1260,6 @@ msgstr "Xóa lịch sử ảnh đĩa" msgid "Create..." msgstr "Tạo..." -msgid "previous image" -msgstr "đĩa trước đó" - msgid "Host CD/DVD Drive (%1)" msgstr "Máy chủ CD/DVD Drive (%1)" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index b39c64563..b02f41bbb 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -249,8 +249,8 @@ msgstr "静音(&M)" msgid "E&mpty" msgstr "空置驱动器(&M)" -msgid "&Reload previous image" -msgstr "载入上一个映像(&R)" +msgid "Reload previous image" +msgstr "载入上一个映像" msgid "&Folder..." msgstr "文件夹(&F)..." @@ -1260,9 +1260,6 @@ msgstr "清除映像历史记录" msgid "Create..." msgstr "创建..." -msgid "previous image" -msgstr "上一张" - msgid "Host CD/DVD Drive (%1)" msgstr "主机 CD/DVD 驱动器 (%1)" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 3526f696d..2662770b8 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -249,8 +249,8 @@ msgstr "靜音(&M)" msgid "E&mpty" msgstr "空置光碟機(&M)" -msgid "&Reload previous image" -msgstr "載入上一個映像(&R)" +msgid "Reload previous image" +msgstr "載入上一個映像" msgid "&Folder..." msgstr "資料夾(&F)..." @@ -1260,9 +1260,6 @@ msgstr "清除映像歷史記錄" msgid "Create..." msgstr "建立..." -msgid "previous image" -msgstr "上一個映像" - msgid "Host CD/DVD Drive (%1)" msgstr "主機 CD/DVD 光碟機 (%1)" diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 3e7c84ca7..351012d1e 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -174,8 +174,7 @@ MediaMenu::refresh(QMenu *parentMenu) } menu->addSeparator(); #endif // Q_OS_WINDOWS - cdromImagePos = menu->children().count(); - cdromDirPos = menu->children().count(); + cdromEjectPos = menu->children().count(); menu->addAction(tr("E&ject"), [this, i]() { cdromEject(i); })->setCheckable(false); cdromMenus[i] = menu; cdromUpdateMenu(i); @@ -304,7 +303,8 @@ MediaMenu::cassetteEject() void MediaMenu::cassetteUpdateMenu() { - QString name = cassette_fname; + QString name = cassette_fname; + QFileInfo fi(cassette_fname); const QString mode = cassette_mode; auto childs = cassetteMenu->children(); auto *recordMenu = dynamic_cast(childs[cassetteRecordPos]); @@ -318,6 +318,7 @@ MediaMenu::cassetteUpdateMenu() rewindMenu->setEnabled(!name.isEmpty()); fastFwdMenu->setEnabled(!name.isEmpty()); ejectMenu->setEnabled(!name.isEmpty()); + ejectMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(fi.fileName())); const bool isSaving = (mode == QStringLiteral("save")); recordMenu->setChecked(isSaving); @@ -384,10 +385,12 @@ void MediaMenu::cartridgeUpdateMenu(int i) { const QString name = cart_fns[i]; - auto *menu = cartridgeMenus[i]; + QFileInfo fi(cart_fns[i]); + auto *menu = cartridgeMenus[i]; auto childs = menu->children(); auto *ejectMenu = dynamic_cast(childs[cartridgeEjectPos]); ejectMenu->setEnabled(!name.isEmpty()); + ejectMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(fi.fileName())); menu->setTitle(tr("Cartridge %1: %2").arg(QString::number(i + 1), name.isEmpty() ? tr("(empty)") : name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { @@ -628,7 +631,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) switch (type) { default: - menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); + menu_item_name = fi.fileName().isEmpty() ? tr("Reload previous image") : fn; return; case ui::MediaType::Cassette: if (!MachineStatus::hasCassette()) @@ -637,7 +640,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cassetteImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); + menu_item_name = fi.fileName().isEmpty() ? tr("Reload previous image") : fn; break; case ui::MediaType::Cartridge: if (!machine_has_cartridge(machine)) @@ -646,7 +649,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cartridgeImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); + menu_item_name = fi.fileName().isEmpty() ? tr("Reload previous image") : fn; break; case ui::MediaType::Floppy: if (!floppyMenus.contains(index)) @@ -655,7 +658,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[floppyImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); + menu_item_name = fi.fileName().isEmpty() ? tr("Reload previous image") : fn; break; case ui::MediaType::Optical: if (!cdromMenus.contains(index)) @@ -673,7 +676,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) } else { fi.setFile(fn); 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") : fn; + menu_item_name = fn.isEmpty() ? tr("Reload previous image") : fn; } imageHistoryUpdatePos->setIcon(menu_icon); break; @@ -684,7 +687,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[zipImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); + menu_item_name = fi.fileName().isEmpty() ? tr("Reload previous image") : fn; break; case ui::MediaType::Mo: if (!moMenus.contains(index)) @@ -693,7 +696,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[moImageHistoryPos[slot]]); fi.setFile(fn); - menu_item_name = fi.fileName().isEmpty() ? tr("previous image") : fi.fileName(); + menu_item_name = fi.fileName().isEmpty() ? tr("Reload previous image") : fn; break; } @@ -728,8 +731,8 @@ MediaMenu::cdromUpdateMenu(int i) 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]); - imageMenu->setEnabled(!name.isEmpty()); + auto *ejectMenu = dynamic_cast(childs[cdromEjectPos]); + ejectMenu->setEnabled(!name.isEmpty()); QString menu_item_name; if (name.left(8) == "ioctl://") { #ifdef Q_OS_WINDOWS @@ -742,12 +745,12 @@ MediaMenu::cdromUpdateMenu(int i) } else { QFileInfo fi(cdrom[i].image_path); - menu_item_name = name.isEmpty() ? QString() : name; + menu_item_name = name.isEmpty() ? QString() : fi.fileName(); name2 = name; menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico"); } - imageMenu->setIcon(menu_icon); - imageMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(menu_item_name)); + ejectMenu->setIcon(menu_icon); + ejectMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(menu_item_name)); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) updateImageHistory(i, slot, ui::MediaType::Optical); @@ -876,6 +879,7 @@ MediaMenu::zipUpdateMenu(int i) { const QString name = zip_drives[i].image_path; const QString prev_name = zip_drives[i].prev_image_path; + QFileInfo fi(zip_drives[i].image_path); if (!zipMenus.contains(i)) return; auto *menu = zipMenus[i]; @@ -883,6 +887,7 @@ MediaMenu::zipUpdateMenu(int i) auto *ejectMenu = dynamic_cast(childs[zipEjectPos]); ejectMenu->setEnabled(!name.isEmpty()); + ejectMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(fi.fileName())); QString busName = tr("Unknown Bus"); switch (zip_drives[i].bus_type) { @@ -1009,8 +1014,9 @@ MediaMenu::moReload(int index, int slot) void MediaMenu::moUpdateMenu(int i) { - QString name = mo_drives[i].image_path; - QString prev_name = mo_drives[i].prev_image_path; + QString name = mo_drives[i].image_path; + QString prev_name = mo_drives[i].prev_image_path; + QFileInfo fi(mo_drives[i].image_path); if (!moMenus.contains(i)) return; auto *menu = moMenus[i]; @@ -1018,6 +1024,7 @@ MediaMenu::moUpdateMenu(int i) auto *ejectMenu = dynamic_cast(childs[moEjectPos]); ejectMenu->setEnabled(!name.isEmpty()); + ejectMenu->setText(name.isEmpty() ? tr("E&ject") : tr("E&ject %1").arg(fi.fileName())); QString busName = tr("Unknown Bus"); switch (mo_drives[i].bus_type) { diff --git a/src/qt/qt_mediamenu.hpp b/src/qt/qt_mediamenu.hpp index b069c67d9..ed97a0a50 100644 --- a/src/qt/qt_mediamenu.hpp +++ b/src/qt/qt_mediamenu.hpp @@ -108,8 +108,7 @@ private: int floppyImageHistoryPos[MAX_PREV_IMAGES]; int cdromMutePos; - int cdromImagePos; - int cdromDirPos; + int cdromEjectPos; int cdromImageHistoryPos[MAX_PREV_IMAGES]; int zipEjectPos; From 40ee98d6f3837b311c4573d1daf1b9d98143ebb1 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 11 Apr 2025 05:26:01 +0500 Subject: [PATCH 0713/1190] qt: The sound icon's menu is now a submenu of the Tools menu Replaces (and includes) the standalone Sound gain option --- src/qt/languages/86box.pot | 3 +++ src/qt/languages/ca-ES.po | 3 +++ src/qt/languages/cs-CZ.po | 3 +++ src/qt/languages/de-DE.po | 3 +++ src/qt/languages/es-ES.po | 3 +++ src/qt/languages/fi-FI.po | 3 +++ src/qt/languages/fr-FR.po | 3 +++ src/qt/languages/hr-HR.po | 3 +++ src/qt/languages/hu-HU.po | 3 +++ src/qt/languages/it-IT.po | 3 +++ src/qt/languages/ja-JP.po | 3 +++ src/qt/languages/ko-KR.po | 3 +++ src/qt/languages/nl-NL.po | 3 +++ src/qt/languages/pl-PL.po | 3 +++ src/qt/languages/pt-BR.po | 3 +++ src/qt/languages/pt-PT.po | 3 +++ src/qt/languages/ru-RU.po | 3 +++ src/qt/languages/sk-SK.po | 3 +++ src/qt/languages/sl-SI.po | 3 +++ src/qt/languages/tr-TR.po | 3 +++ src/qt/languages/uk-UA.po | 3 +++ src/qt/languages/vi-VN.po | 3 +++ src/qt/languages/zh-CN.po | 3 +++ src/qt/languages/zh-TW.po | 3 +++ src/qt/qt_machinestatus.cpp | 36 +++++++++--------------------------- src/qt/qt_machinestatus.hpp | 5 ++--- src/qt/qt_mainwindow.cpp | 14 ++++++++++++-- src/qt/qt_mainwindow.hpp | 1 + src/qt/qt_mainwindow.ui | 15 ++++++++++++++- 29 files changed, 110 insertions(+), 33 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 07dfb7cc5..066e98167 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -189,6 +189,9 @@ msgstr "" msgid "Take s&creenshot" msgstr "" +msgid "S&ound" +msgstr "" + msgid "&Preferences..." msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index dc0a9df2a..93ad884bd 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -189,6 +189,9 @@ msgstr "&Actualitzar icones a la barra d'estat" msgid "Take s&creenshot" msgstr "Prendre c&aptura" +msgid "S&ound" +msgstr "S&o" + msgid "&Preferences..." msgstr "&Preferències ..." diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 7e76d3760..9205839aa 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -189,6 +189,9 @@ msgstr "&Aktualizovat ikony stavového řádku" msgid "Take s&creenshot" msgstr "Pořídit &screenshot" +msgid "S&ound" +msgstr "&Zvuk" + msgid "&Preferences..." msgstr "&Předvolby..." diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index f545729a8..a90c29ac0 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -189,6 +189,9 @@ msgstr "&Statusleistenicons aktualisieren" msgid "Take s&creenshot" msgstr "S&creenshot aufnehmen" +msgid "S&ound" +msgstr "S&ound" + msgid "&Preferences..." msgstr "&Einstellungen..." diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 0733f46ec..3b90772c0 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -189,6 +189,9 @@ msgstr "&Actualizar iconos en barra de estado" msgid "Take s&creenshot" msgstr "Tomar c&aptura" +msgid "S&ound" +msgstr "S&onido" + msgid "&Preferences..." msgstr "&Preferencias..." diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index a7ac64eff..6460ce286 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -189,6 +189,9 @@ msgstr "&Päivitä tilapalkin kuvakkeita" msgid "Take s&creenshot" msgstr "Ota &kuvakaappaus" +msgid "S&ound" +msgstr "&Ääni" + msgid "&Preferences..." msgstr "&Sovellusasetukset..." diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 434e8c31b..d83bd81a3 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -189,6 +189,9 @@ msgstr "Mettre à jour la barre de stat&us" msgid "Take s&creenshot" msgstr "Copie &Ecran" +msgid "S&ound" +msgstr "S&on" + msgid "&Preferences..." msgstr "&Préférences..." diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index b202b39b5..1bc6d4d25 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -189,6 +189,9 @@ msgstr "&Ažuriraj ikone statusnog redka" msgid "Take s&creenshot" msgstr "Napravi &snimku zaslona" +msgid "S&ound" +msgstr "&Zvuk" + msgid "&Preferences..." msgstr "&Postavke..." diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index e9aa6a4ff..23229893a 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -189,6 +189,9 @@ msgstr "Állapotsori ikonok &frissítése" msgid "Take s&creenshot" msgstr "&Képernyőkép készítése" +msgid "S&ound" +msgstr "&Hang" + msgid "&Preferences..." msgstr "&Beállítások..." diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 2f31a9dba..690af0a68 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -189,6 +189,9 @@ msgstr "&Aggiorna icone della barra di stato" msgid "Take s&creenshot" msgstr "Cattura schermata" +msgid "S&ound" +msgstr "A&udio" + msgid "&Preferences..." msgstr "&Preferenze..." diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 318d0dca5..502ccda20 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -189,6 +189,9 @@ msgstr "ステータスバーのアイコンを更新(&U)" msgid "Take s&creenshot" msgstr "スクリーンショットを撮る(&C)" +msgid "S&ound" +msgstr "サウンド(&O)" + msgid "&Preferences..." msgstr "環境設定(&P)..." diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 027c5a778..b149b62bb 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -189,6 +189,9 @@ msgstr "상태 바 아이콘 갱신하기(&U)" msgid "Take s&creenshot" msgstr "스크린샷 찍기(&C)" +msgid "S&ound" +msgstr "사운드(&O)" + msgid "&Preferences..." msgstr "환경설정(&P)..." diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 65e589b2b..0fe316550 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -189,6 +189,9 @@ msgstr "&Statusbalkpictogrammen bijwerken" msgid "Take s&creenshot" msgstr "Maak een schermafbeelding" +msgid "S&ound" +msgstr "&Geluid" + msgid "&Preferences..." msgstr "&Voorkeuren..." diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 4e93f9dd1..81b9f9b04 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -189,6 +189,9 @@ msgstr "&Aktualizuj ikony na pasku statusu" msgid "Take s&creenshot" msgstr "Zrób &zrzut ekranu" +msgid "S&ound" +msgstr "Dź&więk" + msgid "&Preferences..." msgstr "&Preferencje..." diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 3e0ec7ff1..0b1ab46e4 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -189,6 +189,9 @@ msgstr "&Atualizar ícones da barra de status" msgid "Take s&creenshot" msgstr "Capturar &tela" +msgid "S&ound" +msgstr "&Som" + msgid "&Preferences..." msgstr "&Preferências..." diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 9fb1ce342..c83ac3655 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -189,6 +189,9 @@ msgstr "&Atualizar ícones da barra de estado" msgid "Take s&creenshot" msgstr "Gravar imagem de ecrã" +msgid "S&ound" +msgstr "&Som" + msgid "&Preferences..." msgstr "&Preferências..." diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 725f7adf6..b466c6624 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -189,6 +189,9 @@ msgstr "&Обновление значков строки состояния" msgid "Take s&creenshot" msgstr "Сделать с&криншот" +msgid "S&ound" +msgstr "&Звук" + msgid "&Preferences..." msgstr "&Параметры..." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 937b067fe..d70d14e56 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -189,6 +189,9 @@ msgstr "&Aktualizovať ikony na stavovom riadku" msgid "Take s&creenshot" msgstr "Urobiť snímku &obrazovky" +msgid "S&ound" +msgstr "&Zvuk" + msgid "&Preferences..." msgstr "&Predvoľby..." diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index b28954b19..419d7dcc5 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -189,6 +189,9 @@ msgstr "&Posodabljaj ikone statusne vrstice" msgid "Take s&creenshot" msgstr "&Zajemi posnetek zaslona" +msgid "S&ound" +msgstr "Z&vok" + msgid "&Preferences..." msgstr "&Možnosti..." diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 54bdac06e..d134be6d0 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -195,6 +195,9 @@ msgstr "&Tercihler..." msgid "Enable &Discord integration" msgstr "&Discord entegrasyonunu etkinleştir" +msgid "S&ound" +msgstr "&Ses" + msgid "Sound &gain..." msgstr "&Ses düzeyi artışı..." diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index b78bb0661..d475fa201 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -189,6 +189,9 @@ msgstr "&Обновлення значків рядка стану" msgid "Take s&creenshot" msgstr "Зробити &знімок" +msgid "S&ound" +msgstr "&Звук" + msgid "&Preferences..." msgstr "&Параметри..." diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index e4b15a971..b4c72ec26 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -189,6 +189,9 @@ msgstr "Cậ&p nhật biểu tượng thanh trạng thái" msgid "Take s&creenshot" msgstr "Chụp &màn hình" +msgid "S&ound" +msgstr "&Thanh âm" + msgid "&Preferences..." msgstr "&Tùy biến..." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index b02f41bbb..8e5dd1a4b 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -189,6 +189,9 @@ msgstr "更新状态栏图标(&U)" msgid "Take s&creenshot" msgstr "截图(&C)" +msgid "S&ound" +msgstr "声音(&O)" + msgid "&Preferences..." msgstr "首选项(&P)..." diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 2662770b8..584c18dc9 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -189,6 +189,9 @@ msgstr "更新狀態列圖示(&U)" msgid "Take s&creenshot" msgstr "擷圖(&C)" +msgid "S&ound" +msgstr "聲音(&O)" + msgid "&Preferences..." msgstr "偏好設定(&P)..." diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index aba7fc1d4..d86dae7b9 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -270,7 +270,6 @@ MachineStatus::MachineStatus(QObject *parent) , refreshTimer(new QTimer(this)) { d = std::make_unique(this); - muteUnmuteAction = nullptr; soundMenu = nullptr; connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons); refreshTimer->start(75); @@ -279,9 +278,9 @@ MachineStatus::MachineStatus(QObject *parent) MachineStatus::~MachineStatus() = default; void -MachineStatus::setSoundGainAction(QAction* action) +MachineStatus::setSoundMenu(QMenu* menu) { - soundGainAction = action; + soundMenu = menu; } bool @@ -519,28 +518,6 @@ MachineStatus::refresh(QStatusBar *sbar) } sbar->removeWidget(d->sound.get()); - if (!muteUnmuteAction) { - muteUnmuteAction = new QAction; - connect(muteUnmuteAction, &QAction::triggered, this, [this]() { - sound_muted ^= 1; - config_save(); - if (d->sound) - d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); - - muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); - }); - } - - if (!soundMenu) { - soundMenu = new QMenu((QWidget*)parent()); - - soundMenu->addAction(muteUnmuteAction); - soundMenu->addSeparator(); - soundMenu->addAction(soundGainAction); - - muteUnmuteAction->setParent(soundMenu); - } - if (cassette_enable) { d->cassette.label = std::make_unique(); d->cassette.setEmpty(QString(cassette_fname).isEmpty()); @@ -710,8 +687,6 @@ MachineStatus::refresh(QStatusBar *sbar) d->sound = std::make_unique(); d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); - 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())); @@ -727,6 +702,13 @@ MachineStatus::refresh(QStatusBar *sbar) refreshEmptyIcons(); } +void +MachineStatus::updateSoundIcon() +{ + if (d->sound) + d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); +} + void MachineStatus::message(const QString &msg) { diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index 90b420763..ad6425b5a 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -73,20 +73,19 @@ public: QString getMessage(); void clearActivity(); - void setSoundGainAction(QAction* action); + void setSoundMenu(QMenu* menu); public slots: void refresh(QStatusBar *sbar); void message(const QString &msg); void updateTip(int tag); void refreshEmptyIcons(); void refreshIcons(); + void updateSoundIcon(); private: struct States; std::unique_ptr d; QTimer *refreshTimer; - QAction *soundGainAction; - QAction *muteUnmuteAction; QMenu *soundMenu; }; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e9ebdaad8..886f84dcd 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -180,7 +180,8 @@ MainWindow::MainWindow(QWidget *parent) extern MainWindow *main_window; main_window = this; ui->setupUi(this); - status->setSoundGainAction(ui->actionSound_gain); + status->setSoundMenu(ui->menuSound); + ui->actionMute_Unmute->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); ui->menuEGA_S_VGA_settings->menuAction()->setMenuRole(QAction::NoRole); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); @@ -1334,7 +1335,7 @@ void MainWindow::refreshMediaMenu() { mm->refresh(ui->menuMedia); - status->setSoundGainAction(ui->actionSound_gain); + status->setSoundMenu(ui->menuSound); status->refresh(ui->statusbar); ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled); @@ -1937,6 +1938,15 @@ MainWindow::on_actionTake_screenshot_triggered() device_force_redraw(); } +void +MainWindow::on_actionMute_Unmute_triggered() +{ + sound_muted ^= 1; + config_save(); + status->updateSoundIcon(); + ui->actionMute_Unmute->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); +} + void MainWindow::on_actionSound_gain_triggered() { diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 5c8bd388b..4b3f9ecae 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -116,6 +116,7 @@ private slots: void on_actionHide_tool_bar_triggered(); void on_actionUpdate_status_bar_icons_triggered(); void on_actionTake_screenshot_triggered(); + void on_actionMute_Unmute_triggered(); void on_actionSound_gain_triggered(); void on_actionPreferences_triggered(); void on_actionEnable_Discord_integration_triggered(bool checked); diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index ef3cf16c6..83a80342b 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -87,13 +87,21 @@ &Tools + + + S&ound + + + + + - + @@ -725,6 +733,11 @@ false + + + &Mute + + Sound &gain... From 91531529903a4295b254bd4241b1d58d83dd25ca Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 11 Apr 2025 06:35:18 +0500 Subject: [PATCH 0714/1190] qt: Redesign hard disk dialog to accommodate drive models --- src/disk/hdd.c | 16 +-- src/qt/languages/86box.pot | 26 +++- src/qt/languages/ca-ES.po | 4 +- src/qt/languages/cs-CZ.po | 4 +- src/qt/languages/de-DE.po | 4 +- src/qt/languages/es-ES.po | 4 +- src/qt/languages/fi-FI.po | 4 +- src/qt/languages/fr-FR.po | 4 +- src/qt/languages/hr-HR.po | 4 +- src/qt/languages/hu-HU.po | 4 +- src/qt/languages/it-IT.po | 4 +- src/qt/languages/ja-JP.po | 4 +- src/qt/languages/ko-KR.po | 4 +- src/qt/languages/nl-NL.po | 4 +- src/qt/languages/pl-PL.po | 4 +- src/qt/languages/pt-BR.po | 4 +- src/qt/languages/pt-PT.po | 4 +- src/qt/languages/ru-RU.po | 7 +- src/qt/languages/sk-SK.po | 4 +- src/qt/languages/sl-SI.po | 4 +- src/qt/languages/tr-TR.po | 4 +- src/qt/languages/uk-UA.po | 4 +- src/qt/languages/vi-VN.po | 4 +- src/qt/languages/zh-CN.po | 4 +- src/qt/languages/zh-TW.po | 4 +- src/qt/qt_harddiskdialog.ui | 232 ++++++++++++++++----------------- src/qt/qt_settingsharddisks.ui | 2 +- 27 files changed, 199 insertions(+), 172 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 8292dc472..8a02173ce 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -407,14 +407,14 @@ hdd_zones_init(hard_disk_t *hdd) static hdd_preset_t hdd_speed_presets[] = { // clang-format off - { .name = "RAM Disk (max. speed)", .internal_name = "ramdisk", .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, - { .name = "[1989] 3500 RPM", .internal_name = "1989_3500rpm", .zones = 1, .avg_spt = 35, .heads = 2, .rpm = 3500, .full_stroke_ms = 40, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 16, .max_multiple = 8 }, - { .name = "[1992] 3600 RPM", .internal_name = "1992_3600rpm", .zones = 1, .avg_spt = 45, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 6, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, - { .name = "[1994] 4500 RPM", .internal_name = "1994_4500rpm", .zones = 8, .avg_spt = 80, .heads = 4, .rpm = 4500, .full_stroke_ms = 26, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 16 }, - { .name = "[1996] 5400 RPM", .internal_name = "1996_5400rpm", .zones = 16, .avg_spt = 135, .heads = 4, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, - { .name = "[1997] 5400 RPM", .internal_name = "1997_5400rpm", .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 }, - { .name = "[1998] 5400 RPM", .internal_name = "1998_5400rpm", .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, - { .name = "[2000] 7200 RPM", .internal_name = "2000_7200rpm", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[Generic] RAM Disk (max. speed)", .internal_name = "ramdisk", .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[Generic] 1989 (3500 RPM)", .internal_name = "1989_3500rpm", .zones = 1, .avg_spt = 35, .heads = 2, .rpm = 3500, .full_stroke_ms = 40, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 16, .max_multiple = 8 }, + { .name = "[Generic] 1992 (3600 RPM)", .internal_name = "1992_3600rpm", .zones = 1, .avg_spt = 45, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 6, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, + { .name = "[Generic] 1994 (4500 RPM)", .internal_name = "1994_4500rpm", .zones = 8, .avg_spt = 80, .heads = 4, .rpm = 4500, .full_stroke_ms = 26, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 16 }, + { .name = "[Generic] 1996 (5400 RPM)", .internal_name = "1996_5400rpm", .zones = 16, .avg_spt = 135, .heads = 4, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, + { .name = "[Generic] 1997 (5400 RPM)", .internal_name = "1997_5400rpm", .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 }, + { .name = "[Generic] 1998 (5400 RPM)", .internal_name = "1998_5400rpm", .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[Generic] 2000 (7200 RPM)", .internal_name = "2000_7200rpm", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, { .name = "[PIO IDE] IBM WDA-L42", .internal_name = "WDAL42", .model = "WDA-L42", .zones = 1, .avg_spt = 85, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 2.5, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 1 }, { .name = "[ATA-1] Conner CP3024", .internal_name = "CP3024", .model = "Conner Peripherals 20MB - CP3024", .zones = 1, .avg_spt = 33, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3044", .internal_name = "CP3044", .model = "Conner Peripherals 40MB - CP3044", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 066e98167..fde3f921c 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2058,7 +2058,28 @@ msgstr "" msgid "High performance impact" msgstr "" -msgid "RAM Disk (max. speed)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "" + +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" msgstr "" msgid "IBM 8514/A clone (ISA)" @@ -2088,5 +2109,8 @@ msgstr "" msgid "Inhibit multimedia keys" msgstr "" +msgid "Model:" +msgstr "" + msgid "Failed to initialize Vulkan renderer." msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 93ad884bd..f39be48ca 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Alt impact en el rendiment" -msgid "RAM Disk (max. speed)" -msgstr "Disc RAM (velocitat màxima)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disc RAM (velocitat màxima)" msgid "IBM 8514/A clone (ISA)" msgstr "Clon IBM 8514/A (ISA)" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 9205839aa..34b5dfa6d 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Vysoký dopad na výkon" -msgid "RAM Disk (max. speed)" -msgstr "Disk RAM (max. rychlost)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disk RAM (max. rychlost)" msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index a90c29ac0..e69d496a7 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -2061,8 +2061,8 @@ msgstr "Softfloat-FPU" msgid "High performance impact" msgstr "Hohe Auswirkung auf die Leistung" -msgid "RAM Disk (max. speed)" -msgstr "RAM-Diskette (maximale Geschwindigkeit)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM-Diskette (maximale Geschwindigkeit)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-Klon (ISA)" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 3b90772c0..1e9bc1c23 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -2057,8 +2057,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Alto impact en el rendimiento" -msgid "RAM Disk (max. speed)" -msgstr "Disco RAM (velocidad máxima)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disco RAM (velocidad máxima)" msgid "IBM 8514/A clone (ISA)" msgstr "Clon IBM 8514/A (ISA)" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 6460ce286..d35e45b21 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -2061,8 +2061,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Suuri vaikutus suorituskykyyn" -msgid "RAM Disk (max. speed)" -msgstr "RAM-levy (maksiminopeus)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM-levy (maksiminopeus)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-klooni (ISA)" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index d83bd81a3..50de1f001 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Impact important sur la performance" -msgid "RAM Disk (max. speed)" -msgstr "Disque RAM (vitesse maximale)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disque RAM (vitesse maximale)" msgid "IBM 8514/A clone (ISA)" msgstr "Clon IBM 8514/A (ISA)" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 1bc6d4d25..93c247319 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Visoki učinak na brzinu izvršavanja" -msgid "RAM Disk (max. speed)" -msgstr "Disk RAM (najviša brzina)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disk RAM (najviša brzina)" msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 23229893a..b92b9c11b 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Nagy hatással van a teljesítményre" -msgid "RAM Disk (max. speed)" -msgstr "RAM lemez (max. sebesség)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM lemez (max. sebesség)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A klón (ISA)" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 690af0a68..b85bb64bd 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Impatto elevato sulla prestazione" -msgid "RAM Disk (max. speed)" -msgstr "Disco RAM (velocità massima)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disco RAM (velocità massima)" msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 502ccda20..07c783dd1 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "パフォーマンスへの影響が大きい" -msgid "RAM Disk (max. speed)" -msgstr "RAMディスク(最高速度)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAMディスク(最高速度)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A クローン(ISA)" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index b149b62bb..cea372b7f 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -2058,8 +2058,8 @@ msgstr "소프트플로트 FPU" msgid "High performance impact" msgstr "성능에 미치는 영향" -msgid "RAM Disk (max. speed)" -msgstr "RAM 디스크(최대 속도)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM 디스크(최대 속도)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 클론(ISA)" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 0fe316550..97634842b 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Hoge prestatie-impact" -msgid "RAM Disk (max. speed)" -msgstr "RAM-schijf (max. snelheid)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM-schijf (max. snelheid)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-kloon (ISA)" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 81b9f9b04..980ee69f1 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Wysoki wpływ na wydajność" -msgid "RAM Disk (max. speed)" -msgstr "Dysk RAM (maks. prędkość)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Dysk RAM (maks. prędkość)" msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 0b1ab46e4..c48e7a07f 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Alto impacto no desempenho" -msgid "RAM Disk (max. speed)" -msgstr "Disco RAM (velocidade máxima)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disco RAM (velocidade máxima)" msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index c83ac3655..1900a42d9 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Elevado impacto no desempenho" -msgid "RAM Disk (max. speed)" -msgstr "Disco RAM (velocidade máxima)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disco RAM (velocidade máxima)" msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index b466c6624..afc4c72a4 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Сильное влияние на производительность" -msgid "RAM Disk (max. speed)" -msgstr "RAM-диск (макс. скорость)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Стандартный] RAM-диск (макс. скорость)" msgid "IBM 8514/A clone (ISA)" msgstr "Клон IBM 8514/A (ISA)" @@ -2084,3 +2084,6 @@ msgstr "Невозможно найти матричные шрифты" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P." + +msgid "Model:" +msgstr "Модель:" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index d70d14e56..f1a6144a6 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -2059,8 +2059,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Vysoký vplyv na výkon" -msgid "RAM Disk (max. speed)" -msgstr "Disk RAM (max. rýchlosť)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Disk RAM (max. rýchlosť)" msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 419d7dcc5..94c241dea 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Visok učinek na hitrost delovanja" -msgid "RAM Disk (max. speed)" -msgstr "Pogon RAM (največja hitrost)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Pogon RAM (največja hitrost)" msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index d134be6d0..1be214342 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Ciddi performans düşüklüğüne neden olabilir" -msgid "RAM Disk (max. speed)" -msgstr "RAM Disk (maks. hız)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM Disk (maks. hız)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A klonu (ISA)" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index d475fa201..6acb947cf 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -2058,8 +2058,8 @@ msgstr "FPU Softfloat" msgid "High performance impact" msgstr "Високий вплив на продуктивність" -msgid "RAM Disk (max. speed)" -msgstr "Диск оперативної пам'яті (макс. швидкість)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Диск оперативної пам'яті (макс. швидкість)" msgid "IBM 8514/A clone (ISA)" msgstr "Клон IBM 8514/A (ISA)" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index b4c72ec26..c1d461fb7 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "Ảnh hưởng lớn đến hiệu suất" -msgid "RAM Disk (max. speed)" -msgstr "Đĩa RAM (tốc độ tối đa)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] Đĩa RAM (tốc độ tối đa)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A bản nhái (ISA)" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 8e5dd1a4b..0ce76cff9 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "重大性能影响" -msgid "RAM Disk (max. speed)" -msgstr "RAM 磁盘 (最大速度)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM 磁盘 (最大速度)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 584c18dc9..d50449aa2 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2058,8 +2058,8 @@ msgstr "Softfloat FPU" msgid "High performance impact" msgstr "對效能影響大" -msgid "RAM Disk (max. speed)" -msgstr "RAM 磁碟 (最大速度)" +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Generic] RAM 磁碟 (最大速度)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" diff --git a/src/qt/qt_harddiskdialog.ui b/src/qt/qt_harddiskdialog.ui index 91499d2cb..cba835134 100644 --- a/src/qt/qt_harddiskdialog.ui +++ b/src/qt/qt_harddiskdialog.ui @@ -32,27 +32,16 @@ Dialog - - - - - - - Channel: + + + + false - - - - - - Speed: + + 0 - - - - - - 30 + + true @@ -63,86 +52,34 @@ - - + + - Type: + Image Format: - - - - - 0 - 0 - - - - - 64 - 16777215 - - - - - - - - - 0 - 0 - - - - - 64 - 16777215 - - - - - - - - Size (MB): - - - - - + + 30 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + Bus: - - - - Qt::Vertical - - - - 20 - 20 - - - + + - - + + - Cylinders: + Type: @@ -165,10 +102,29 @@ - - - - Image Format: + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + 0 + 0 + + + + + 64 + 16777215 + @@ -179,31 +135,47 @@ - - + + + + + 0 + 0 + + + + + 64 + 16777215 + + + + + + 30 - - + + - Bus: + Cylinders: - - - - 30 + + + + File name: - - - - 30 + + + + Size (MB): @@ -226,37 +198,65 @@ - - + + + + Channel: + + + + + 30 - + Block Size: - - + + + + Qt::Vertical + + + + 20 + 20 + + + + + + - File name: + Model: - - - - false + + + + 30 - - 0 + + + + + + 30 - - true + + + + + + 30 diff --git a/src/qt/qt_settingsharddisks.ui b/src/qt/qt_settingsharddisks.ui index 3ae20fee1..ea69edc5b 100644 --- a/src/qt/qt_settingsharddisks.ui +++ b/src/qt/qt_settingsharddisks.ui @@ -78,7 +78,7 @@ - Speed: + Model: From bfec519a015839e9a901d9e11dfd23970ad2d2a0 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 11 Apr 2025 06:36:18 +0500 Subject: [PATCH 0715/1190] nl-NL.po: Remove trailing whitespace --- src/qt/languages/nl-NL.po | 1376 ++++++++++++++++++------------------- 1 file changed, 688 insertions(+), 688 deletions(-) diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 97634842b..20c193afe 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -6,2071 +6,2071 @@ msgstr "" "X-Language: nl_NL\n" "X-Source-Language: en_US\n" -msgid "&Action" +msgid "&Action" msgstr "&Actie" -msgid "&Keyboard requires capture" +msgid "&Keyboard requires capture" msgstr "&Keyboard vereist vastleggen" -msgid "&Right CTRL is left ALT" +msgid "&Right CTRL is left ALT" msgstr "&Rechtse CTRL is linkse ALT" -msgid "&Hard Reset..." +msgid "&Hard Reset..." msgstr "&Harde Reset..." -msgid "&Ctrl+Alt+Del" +msgid "&Ctrl+Alt+Del" msgstr "&Ctrl+Alt+Del" -msgid "Ctrl+Alt+&Esc" +msgid "Ctrl+Alt+&Esc" msgstr "Ctrl+Alt+&Esc" -msgid "&Pause" +msgid "&Pause" msgstr "&Pauze" -msgid "E&xit..." +msgid "E&xit..." msgstr "&Afsluiten..." -msgid "&View" +msgid "&View" msgstr "&Beeld" -msgid "&Hide status bar" +msgid "&Hide status bar" msgstr "&Statusbalk verbergen" -msgid "Hide &toolbar" +msgid "Hide &toolbar" msgstr "Verberg &toolbar" -msgid "&Resizeable window" +msgid "&Resizeable window" msgstr "&Venster met aanpasbare grootte" -msgid "R&emember size && position" +msgid "R&emember size && position" msgstr "&Onthoud grootte && positie" -msgid "Re&nderer" +msgid "Re&nderer" msgstr "Re&nderer" -msgid "&Qt (Software)" +msgid "&Qt (Software)" msgstr "&Qt (software)" -msgid "Qt (&OpenGL)" +msgid "Qt (&OpenGL)" msgstr "Qt (&OpenGL)" -msgid "Open&GL (3.0 Core)" +msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" -msgid "&VNC" +msgid "&VNC" msgstr "&VNC" -msgid "Specify dimensions..." +msgid "Specify dimensions..." msgstr "Afmetingen opgeven..." -msgid "F&orce 4:3 display ratio" +msgid "F&orce 4:3 display ratio" msgstr "F&orceer 4:3 beeldverhouding" -msgid "&Window scale factor" +msgid "&Window scale factor" msgstr "&Venster schaalfactor" -msgid "&0.5x" +msgid "&0.5x" msgstr "&0,5x" -msgid "&1x" +msgid "&1x" msgstr "&1x" -msgid "1.&5x" +msgid "1.&5x" msgstr "1,&5x" -msgid "&2x" +msgid "&2x" msgstr "&2x" -msgid "&3x" +msgid "&3x" msgstr "&3x" -msgid "&4x" +msgid "&4x" msgstr "&4x" -msgid "&5x" +msgid "&5x" msgstr "&5x" -msgid "&6x" +msgid "&6x" msgstr "&6x" -msgid "&7x" +msgid "&7x" msgstr "&7x" -msgid "&8x" +msgid "&8x" msgstr "&8x" -msgid "Filter method" +msgid "Filter method" msgstr "Filtermethode" -msgid "&Nearest" +msgid "&Nearest" msgstr "&Dichtsbijzijnde" -msgid "&Linear" +msgid "&Linear" msgstr "&Lineair" -msgid "Hi&DPI scaling" +msgid "Hi&DPI scaling" msgstr "Hi&DPI-schaling" -msgid "&Fullscreen" +msgid "&Fullscreen" msgstr "&Fullscreen" -msgid "Fullscreen &stretch mode" +msgid "Fullscreen &stretch mode" msgstr "Volledig scherm &uitrekmodus" -msgid "&Full screen stretch" +msgid "&Full screen stretch" msgstr "&Volledig scherm uitrekken" -msgid "&4:3" +msgid "&4:3" msgstr "&4:3" -msgid "&Square pixels (Keep ratio)" +msgid "&Square pixels (Keep ratio)" msgstr "&Vierkante pixels (behoud verhouding)" -msgid "&Integer scale" +msgid "&Integer scale" msgstr "&Integerschaal" -msgid "4:&3 Integer scale" +msgid "4:&3 Integer scale" msgstr "4:&3 integerschaal" -msgid "E&GA/(S)VGA settings" +msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA-instellingen" -msgid "&Inverted VGA monitor" +msgid "&Inverted VGA monitor" msgstr "Ge&ïnverteerde VGA-monitor" -msgid "VGA screen &type" +msgid "VGA screen &type" msgstr "VGA-scherm &type" -msgid "RGB &Color" +msgid "RGB &Color" msgstr "RGB &Kleur" -msgid "&RGB Grayscale" +msgid "&RGB Grayscale" msgstr "&RGB grijstinten" -msgid "&Amber monitor" +msgid "&Amber monitor" msgstr "&Amber monitor" -msgid "&Green monitor" +msgid "&Green monitor" msgstr "&Groene monitor" -msgid "&White monitor" +msgid "&White monitor" msgstr "&Witte monitor" -msgid "Grayscale &conversion type" +msgid "Grayscale &conversion type" msgstr "Grijstinten &conversietype" -msgid "BT&601 (NTSC/PAL)" +msgid "BT&601 (NTSC/PAL)" msgstr "BT&601 (NTSC/PAL)" -msgid "BT&709 (HDTV)" +msgid "BT&709 (HDTV)" msgstr "BT&709 (HDTV)" -msgid "&Average" +msgid "&Average" msgstr "&Gemiddelde" -msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" msgstr "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" -msgid "Change contrast for &monochrome display" +msgid "Change contrast for &monochrome display" msgstr "Contrast wijzigen voor &monochroom beeldscherm" -msgid "&Media" +msgid "&Media" msgstr "&Media" -msgid "&Tools" +msgid "&Tools" msgstr "&Tools" -msgid "&Settings..." +msgid "&Settings..." msgstr "&Instellingen..." -msgid "&Update status bar icons" +msgid "&Update status bar icons" msgstr "&Statusbalkpictogrammen bijwerken" -msgid "Take s&creenshot" +msgid "Take s&creenshot" msgstr "Maak een schermafbeelding" -msgid "S&ound" +msgid "S&ound" msgstr "&Geluid" -msgid "&Preferences..." +msgid "&Preferences..." msgstr "&Voorkeuren..." -msgid "Enable &Discord integration" +msgid "Enable &Discord integration" msgstr "&Discord integratie inschakelen" -msgid "Sound &gain..." +msgid "Sound &gain..." msgstr "&Geluidsversterking..." -msgid "Begin trace" +msgid "Begin trace" msgstr "Begin traceren" -msgid "End trace" +msgid "End trace" msgstr "Traceren beëindigen" -msgid "&Help" +msgid "&Help" msgstr "&Help" -msgid "&Documentation..." +msgid "&Documentation..." msgstr "&Documentatie..." -msgid "&About 86Box..." +msgid "&About 86Box..." msgstr "&Over 86Box..." -msgid "&New image..." +msgid "&New image..." msgstr "&Nieuw image..." -msgid "&Existing image..." +msgid "&Existing image..." msgstr "&Bestaande image..." -msgid "Existing image (&Write-protected)..." +msgid "Existing image (&Write-protected)..." msgstr "Bestaande image (&Schrijfbeveiligd)..." -msgid "&Record" +msgid "&Record" msgstr "&Opnemen" -msgid "&Play" +msgid "&Play" msgstr "&Play" -msgid "&Rewind to the beginning" +msgid "&Rewind to the beginning" msgstr "&Terugspoelen naar het begin" -msgid "&Fast forward to the end" +msgid "&Fast forward to the end" msgstr "&Snel vooruit naar het einde" -msgid "E&ject" +msgid "E&ject" msgstr "&Uitwerpen" -msgid "&Image..." +msgid "&Image..." msgstr "&Image..." -msgid "E&xport to 86F..." +msgid "E&xport to 86F..." msgstr "E&xporteer naar 86F..." -msgid "&Mute" +msgid "&Mute" msgstr "&Mute" -msgid "E&mpty" +msgid "E&mpty" msgstr "E&mpty" -msgid "Reload previous image" +msgid "Reload previous image" msgstr "Herlaad vorige image" -msgid "&Folder..." +msgid "&Folder..." msgstr "&Map..." -msgid "Target &framerate" +msgid "Target &framerate" msgstr "Doel &framerate" -msgid "&Sync with video" +msgid "&Sync with video" msgstr "&Synchroniseer met video" -msgid "&25 fps" +msgid "&25 fps" msgstr "&25 fps" -msgid "&30 fps" +msgid "&30 fps" msgstr "&30 fps" -msgid "&50 fps" +msgid "&50 fps" msgstr "&50 fps" -msgid "&60 fps" +msgid "&60 fps" msgstr "&60 fps" -msgid "&75 fps" +msgid "&75 fps" msgstr "&75 fps" -msgid "&VSync" +msgid "&VSync" msgstr "&VSync" -msgid "&Select shader..." +msgid "&Select shader..." msgstr "&Selecteer shader..." -msgid "&Remove shader" +msgid "&Remove shader" msgstr "&Remove shader" -msgid "Preferences" +msgid "Preferences" msgstr "Voorkeuren" -msgid "Sound Gain" +msgid "Sound Gain" msgstr "Geluidsversterking" -msgid "New Image" +msgid "New Image" msgstr "Nieuw image" -msgid "Settings" +msgid "Settings" msgstr "Instellingen" -msgid "Specify Main Window Dimensions" +msgid "Specify Main Window Dimensions" msgstr "Afmetingen hoofdvenster opgeven" -msgid "OK" +msgid "OK" msgstr "OK" -msgid "Cancel" +msgid "Cancel" msgstr "Annuleren" -msgid "&Default" +msgid "&Default" msgstr "&Standaard" -msgid "Language:" +msgid "Language:" msgstr "Taal:" -msgid "Gain" +msgid "Gain" msgstr "Versterking" -msgid "File name:" +msgid "File name:" msgstr "Bestandsnaam:" -msgid "Disk size:" +msgid "Disk size:" msgstr "Schijfgrootte:" -msgid "RPM mode:" +msgid "RPM mode:" msgstr "RPM-modus:" -msgid "Progress:" +msgid "Progress:" msgstr "Vooruitgang:" -msgid "Width:" +msgid "Width:" msgstr "Breedte:" -msgid "Height:" +msgid "Height:" msgstr "Hoogte:" -msgid "Lock to this size" +msgid "Lock to this size" msgstr "Leg vast op deze grootte" -msgid "Machine type:" +msgid "Machine type:" msgstr "Machinetype:" -msgid "Machine:" +msgid "Machine:" msgstr "Machine:" -msgid "Configure" +msgid "Configure" msgstr "Configureren" -msgid "CPU type:" +msgid "CPU type:" msgstr "CPU type:" -msgid "Speed:" +msgid "Speed:" msgstr "Snelheid:" -msgid "Frequency:" +msgid "Frequency:" msgstr "Frequentie:" -msgid "FPU:" +msgid "FPU:" msgstr "FPU:" -msgid "Wait states:" +msgid "Wait states:" msgstr "Wachttoestanden:" -msgid "MB" +msgid "MB" msgstr "MB" -msgid "Memory:" +msgid "Memory:" msgstr "Geheugen:" -msgid "Time synchronization" +msgid "Time synchronization" msgstr "Tijdsynchronisatie" -msgid "Disabled" +msgid "Disabled" msgstr "Uitgeschakeld" -msgid "Enabled (local time)" +msgid "Enabled (local time)" msgstr "Ingeschakeld (lokale tijd)" -msgid "Enabled (UTC)" +msgid "Enabled (UTC)" msgstr "Ingeschakeld (UTC)" -msgid "Dynamic Recompiler" +msgid "Dynamic Recompiler" msgstr "Dynamische Recompiler" -msgid "Video:" +msgid "Video:" msgstr "Video:" -msgid "Video #2:" +msgid "Video #2:" msgstr "Video #2:" -msgid "Voodoo 1 or 2 Graphics" +msgid "Voodoo 1 or 2 Graphics" msgstr "Voodoo 1 of 2 graphics" -msgid "IBM 8514/A Graphics" +msgid "IBM 8514/A Graphics" msgstr "IBM 8514/A-graphics" -msgid "XGA Graphics" +msgid "XGA Graphics" msgstr "XGA Graphics" -msgid "Mouse:" +msgid "Mouse:" msgstr "Muis:" -msgid "Joystick:" +msgid "Joystick:" msgstr "Joystick:" -msgid "Joystick 1..." +msgid "Joystick 1..." msgstr "Joystick 1..." -msgid "Joystick 2..." +msgid "Joystick 2..." msgstr "Joystick 2..." -msgid "Joystick 3..." +msgid "Joystick 3..." msgstr "Joystick 3..." -msgid "Joystick 4..." +msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card #1:" +msgid "Sound card #1:" msgstr "Geluidskaart #1:" -msgid "Sound card #2:" +msgid "Sound card #2:" msgstr "Geluidskaart #2:" -msgid "Sound card #3:" +msgid "Sound card #3:" msgstr "Geluidskaart #3:" -msgid "Sound card #4:" +msgid "Sound card #4:" msgstr "Geluidskaart #4:" -msgid "MIDI Out Device:" +msgid "MIDI Out Device:" msgstr "MIDI Out-apparaat:" -msgid "MIDI In Device:" +msgid "MIDI In Device:" msgstr "MIDI In-apparaat:" -msgid "Standalone MPU-401" +msgid "Standalone MPU-401" msgstr "Standalone MPU-401" -msgid "Use FLOAT32 sound" +msgid "Use FLOAT32 sound" msgstr "Gebruik FLOAT32-geluid" -msgid "FM synth driver" +msgid "FM synth driver" msgstr "FM-synthesizer" -msgid "Nuked (more accurate)" +msgid "Nuked (more accurate)" msgstr "Nuked (nauwkeuriger)" -msgid "YMFM (faster)" +msgid "YMFM (faster)" msgstr "YMFM (sneller)" -msgid "Network type:" +msgid "Network type:" msgstr "Type netwerk:" -msgid "PCap device:" +msgid "PCap device:" msgstr "PCap-apparaat:" -msgid "Network adapter:" +msgid "Network adapter:" msgstr "Netwerkadapter:" -msgid "COM1 Device:" +msgid "COM1 Device:" msgstr "COM1-apparaat:" -msgid "COM2 Device:" +msgid "COM2 Device:" msgstr "COM2-apparaat:" -msgid "COM3 Device:" +msgid "COM3 Device:" msgstr "COM3-apparaat:" -msgid "COM4 Device:" +msgid "COM4 Device:" msgstr "COM4-apparaat:" -msgid "LPT1 Device:" +msgid "LPT1 Device:" msgstr "LPT1-apparaat:" -msgid "LPT2 Device:" +msgid "LPT2 Device:" msgstr "LPT2-apparaat:" -msgid "LPT3 Device:" +msgid "LPT3 Device:" msgstr "LPT3-apparaat:" -msgid "LPT4 Device:" +msgid "LPT4 Device:" msgstr "LPT4-apparaat:" -msgid "Serial port 1" +msgid "Serial port 1" msgstr "Seriële poort 1" -msgid "Serial port 2" +msgid "Serial port 2" msgstr "Seriële poort 2" -msgid "Serial port 3" +msgid "Serial port 3" msgstr "Seriële poort 3" -msgid "Serial port 4" +msgid "Serial port 4" msgstr "Seriële poort 4" -msgid "Parallel port 1" +msgid "Parallel port 1" msgstr "Parallelle poort 1" -msgid "Parallel port 2" +msgid "Parallel port 2" msgstr "Parallelle poort 2" -msgid "Parallel port 3" +msgid "Parallel port 3" msgstr "Parallelle poort 3" -msgid "Parallel port 4" +msgid "Parallel port 4" msgstr "Parallelle poort 4" -msgid "HD Controller:" +msgid "HD Controller:" msgstr "HD-controller:" -msgid "FD Controller:" +msgid "FD Controller:" msgstr "FD-Controller:" -msgid "Tertiary IDE Controller" +msgid "Tertiary IDE Controller" msgstr "Tertiaire IDE-controller" -msgid "Quaternary IDE Controller" +msgid "Quaternary IDE Controller" msgstr "Quaternaire IDE-controller" -msgid "SCSI" +msgid "SCSI" msgstr "SCSI" -msgid "Controller 1:" +msgid "Controller 1:" msgstr "Controller 1:" -msgid "Controller 2:" +msgid "Controller 2:" msgstr "Controller 2:" -msgid "Controller 3:" +msgid "Controller 3:" msgstr "Controller 3:" -msgid "Controller 4:" +msgid "Controller 4:" msgstr "Controller 4:" -msgid "Cassette" +msgid "Cassette" msgstr "Cassette" -msgid "Hard disks:" +msgid "Hard disks:" msgstr "Harde schijven:" -msgid "&New..." +msgid "&New..." msgstr "&Nieuw..." -msgid "&Existing..." +msgid "&Existing..." msgstr "&Bestaande..." -msgid "&Remove" +msgid "&Remove" msgstr "&Verwijderen" -msgid "Bus:" +msgid "Bus:" msgstr "Bus:" -msgid "Channel:" +msgid "Channel:" msgstr "Kanaal:" -msgid "ID:" +msgid "ID:" msgstr "ID:" -msgid "&Specify..." +msgid "&Specify..." msgstr "&Specificeer..." -msgid "Sectors:" +msgid "Sectors:" msgstr "Sectoren:" -msgid "Heads:" +msgid "Heads:" msgstr "Heads:" -msgid "Cylinders:" +msgid "Cylinders:" msgstr "Cilinders:" -msgid "Size (MB):" +msgid "Size (MB):" msgstr "Grootte (MB):" -msgid "Type:" +msgid "Type:" msgstr "Type:" -msgid "Image Format:" +msgid "Image Format:" msgstr "Imageformaat:" -msgid "Block Size:" +msgid "Block Size:" msgstr "Blokgrootte:" -msgid "Floppy drives:" +msgid "Floppy drives:" msgstr "Floppy-schijfstations:" -msgid "Turbo timings" +msgid "Turbo timings" msgstr "Turbo timings" -msgid "Check BPB" +msgid "Check BPB" msgstr "Controleer BPB" -msgid "CD-ROM drives:" +msgid "CD-ROM drives:" msgstr "CD-ROM-stations:" -msgid "MO drives:" +msgid "MO drives:" msgstr "MO-schijven:" -msgid "ZIP drives:" +msgid "ZIP drives:" msgstr "ZIP-schijven:" -msgid "ZIP 250" +msgid "ZIP 250" msgstr "ZIP 250" -msgid "ISA RTC:" +msgid "ISA RTC:" msgstr "ISA RTC:" -msgid "ISA Memory Expansion" +msgid "ISA Memory Expansion" msgstr "ISA-geheugenuitbreiding" -msgid "Card 1:" +msgid "Card 1:" msgstr "Kaart 1:" -msgid "Card 2:" +msgid "Card 2:" msgstr "Kaart 2:" -msgid "Card 3:" +msgid "Card 3:" msgstr "Kaart 3:" -msgid "Card 4:" +msgid "Card 4:" msgstr "Kaart 4:" -msgid "ISABugger device" +msgid "ISABugger device" msgstr "ISABugger-apparaat" -msgid "POST card" +msgid "POST card" msgstr "POST-kaart" -msgid "86Box" +msgid "86Box" msgstr "86Box" -msgid "Error" +msgid "Error" msgstr "Fout" -msgid "Fatal error" +msgid "Fatal error" msgstr "Fatale fout" -msgid " - PAUSED" +msgid " - PAUSED" msgstr " - GEPAUZEERD" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgid "Press Ctrl+Alt+PgDn to return to windowed mode." msgstr "Druk op Ctrl+Alt+PgDn om terug te gaan naar de venstermodus." -msgid "Speed" +msgid "Speed" msgstr "Snelheid" -msgid "ZIP %1 %2 (%3): %4" +msgid "ZIP %1 %2 (%3): %4" msgstr "ZIP %1 %2 (%3): %4" -msgid "ZIP images" +msgid "ZIP images" msgstr "ZIP-images" -msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." msgstr "86Box kon geen bruikbare ROM images vinden.\n\nDownload een ROM set en pak deze uit in de map \"roms\"." -msgid "(empty)" +msgid "(empty)" msgstr "(leeg)" -msgid "All files" +msgid "All files" msgstr "Alle bestanden" -msgid "Turbo" +msgid "Turbo" msgstr "Turbo" -msgid "On" +msgid "On" msgstr "Aan" -msgid "Off" +msgid "Off" msgstr "Uit" -msgid "All images" +msgid "All images" msgstr "Alle schijfimages" -msgid "Basic sector images" +msgid "Basic sector images" msgstr "Basissectorimages" -msgid "Surface images" +msgid "Surface images" msgstr "Oppervlakte-images" -msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." +msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." msgstr "Machine \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/machines. Overschakelen naar een beschikbare machine." -msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." msgstr "Videokaart \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Overschakel over naar een beschikbare videokaart." -msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." msgstr "Videokaart #2 \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Uitschakel de tweede videokaart." msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." msgstr "Het apparaat \"%hs\" is niet beschikbaar door ontbrekende ROMs. Negeer het apparaat." -msgid "Machine" +msgid "Machine" msgstr "Machine" -msgid "Display" +msgid "Display" msgstr "Scherm" -msgid "Input devices" +msgid "Input devices" msgstr "Invoerapparaten" -msgid "Sound" +msgid "Sound" msgstr "Geluid" -msgid "Network" +msgid "Network" msgstr "Netwerk" -msgid "Ports (COM & LPT)" +msgid "Ports (COM & LPT)" msgstr "Poorten (COM & LPT)" -msgid "Storage controllers" +msgid "Storage controllers" msgstr "Opslagcontrollers" -msgid "Hard disks" +msgid "Hard disks" msgstr "Harde schijven" -msgid "Floppy & CD-ROM drives" +msgid "Floppy & CD-ROM drives" msgstr "Floppy- en CD-ROM-stations" -msgid "Other removable devices" +msgid "Other removable devices" msgstr "Andere verwijderbare apparaten" -msgid "Other peripherals" +msgid "Other peripherals" msgstr "Andere randapparatuur" -msgid "Click to capture mouse" +msgid "Click to capture mouse" msgstr "Klik om muis vast te leggen" -msgid "Press %1 to release mouse" +msgid "Press %1 to release mouse" msgstr "Druk op %1 om de muis los te laten" -msgid "Press %1 or middle button to release mouse" +msgid "Press %1 or middle button to release mouse" msgstr "Druk op %1 of middelste knop om de muis los te laten" -msgid "Bus" +msgid "Bus" msgstr "Bus" -msgid "File" +msgid "File" msgstr "Bestand" -msgid "C" +msgid "C" msgstr "C" -msgid "H" +msgid "H" msgstr "H" -msgid "S" +msgid "S" msgstr "S" -msgid "KB" +msgid "KB" msgstr "KB" -msgid "Default" +msgid "Default" msgstr "Standaard" -msgid "%1 Wait state(s)" +msgid "%1 Wait state(s)" msgstr "%1 Wachttoestand(en)" -msgid "Type" +msgid "Type" msgstr "Type" -msgid "No PCap devices found" +msgid "No PCap devices found" msgstr "Geen PCap-apparaten gevonden" -msgid "Invalid PCap device" +msgid "Invalid PCap device" msgstr "Ongeldig PCap-apparaat" -msgid "2-axis, 2-button joystick(s)" +msgid "2-axis, 2-button joystick(s)" msgstr "Joystick(s) met 2 assen en 2 knoppen" -msgid "2-axis, 4-button joystick" +msgid "2-axis, 4-button joystick" msgstr "Joystick met 2 assen en 4 knoppen" -msgid "2-axis, 6-button joystick" +msgid "2-axis, 6-button joystick" msgstr "Joystick met 2 assen en 6 knoppen" -msgid "2-axis, 8-button joystick" +msgid "2-axis, 8-button joystick" msgstr "Joystick met 2 assen en 8 knoppen" -msgid "3-axis, 2-button joystick" +msgid "3-axis, 2-button joystick" msgstr "Joystick met 3 assen en 2 knoppen" -msgid "3-axis, 4-button joystick" +msgid "3-axis, 4-button joystick" msgstr "Joystick met 3 assen en 4 knoppen" -msgid "4-axis, 4-button joystick" +msgid "4-axis, 4-button joystick" msgstr "Joystick met 4 assen en 4 knoppen" -msgid "CH Flightstick Pro" +msgid "CH Flightstick Pro" msgstr "CH Flightstick Pro" -msgid "Microsoft SideWinder Pad" +msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" -msgid "Thrustmaster Flight Control System" +msgid "Thrustmaster Flight Control System" msgstr "Thrustmaster Flight Control systeem" -msgid "None" +msgid "None" msgstr "Geen" -msgid "%1 MB (CHS: %2, %3, %4)" +msgid "%1 MB (CHS: %2, %3, %4)" msgstr "%1 MB (CHS: %2, %3, %4)" -msgid "Floppy %1 (%2): %3" +msgid "Floppy %1 (%2): %3" msgstr "Floppy %1 (%2): %3" -msgid "Advanced sector images" +msgid "Advanced sector images" msgstr "Geavanceerde sector-images" -msgid "Flux images" +msgid "Flux images" msgstr "Flux images" -msgid "Are you sure you want to hard reset the emulated machine?" +msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Weet je zeker dat je de geëmuleerde machine wilt resetten?" -msgid "Are you sure you want to exit 86Box?" +msgid "Are you sure you want to exit 86Box?" msgstr "Weet je zeker dat je 86Box wilt verlaten?" -msgid "Unable to initialize Ghostscript" +msgid "Unable to initialize Ghostscript" msgstr "Kan Ghostscript niet initialiseren" -msgid "Unable to initialize GhostPCL" +msgid "Unable to initialize GhostPCL" msgstr "Kan GhostPCL niet initialiseren" -msgid "MO %1 (%2): %3" +msgid "MO %1 (%2): %3" msgstr "MO %1 (%2): %3" -msgid "MO images" +msgid "MO images" msgstr "MO-images" -msgid "Welcome to 86Box!" +msgid "Welcome to 86Box!" msgstr "Welkom bij 86Box!" -msgid "Internal device" +msgid "Internal device" msgstr "Intern apparaat" -msgid "Exit" +msgid "Exit" msgstr "&Afsluiten" -msgid "No ROMs found" +msgid "No ROMs found" msgstr "Geen ROMs gevonden" -msgid "Do you want to save the settings?" +msgid "Do you want to save the settings?" msgstr "Wil je de instellingen opslaan?" -msgid "This will hard reset the emulated machine." +msgid "This will hard reset the emulated machine." msgstr "Dit zal de geëmuleerde machine een hard reset geven." -msgid "Save" +msgid "Save" msgstr "Opslaan" -msgid "About 86Box" +msgid "About 86Box" msgstr "Over 86Box" -msgid "86Box v" +msgid "86Box v" msgstr "86Box v" -msgid "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." +msgid "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." msgstr "Een emulator van oude computers\n\nAuteurs: 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\nMet eerdere bijdragen van Sarah Walker, leilei, JohnElliott, greatpsycho en anderen.\n\nUitgebracht onder de GNU General Public License versie 2 of later. Zie LICENSE voor meer informatie." -msgid "Hardware not available" +msgid "Hardware not available" msgstr "Hardware niet beschikbaar" -msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." msgstr "Zorg ervoor dat %1 is geïnstalleerd en dat je een %1-compatibele netwerkverbinding hebt." -msgid "Invalid configuration" +msgid "Invalid configuration" msgstr "Ongeldige configuratie" -msgid "%1 is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." +msgid "%1 is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr "%1 is vereist voor automatische conversie van PostScript-bestanden naar PDF.\n\nAlle documenten die naar de generieke PostScript-printer worden gestuurd, worden opgeslagen als PostScript-bestanden (.ps)." -msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." +msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 is vereist voor automatische conversie van PCL-bestanden naar PDF.\n\nAlle documenten die naar de generieke PCL-printer worden gestuurd, worden opgeslagen als Printer Command Language (.pcl) bestanden." -msgid "Entering fullscreen mode" +msgid "Entering fullscreen mode" msgstr "Volledig scherm modus openen" -msgid "Don't show this message again" +msgid "Don't show this message again" msgstr "Dit bericht niet meer tonen" -msgid "Don't exit" +msgid "Don't exit" msgstr "Niet afsluiten" -msgid "Reset" +msgid "Reset" msgstr "Reset" -msgid "Don't reset" +msgid "Don't reset" msgstr "Niet resetten" -msgid "CD-ROM images" +msgid "CD-ROM images" msgstr "CD-ROM-images" -msgid "%1 Device Configuration" +msgid "%1 Device Configuration" msgstr "%1 Apparaatconfiguratie" -msgid "Monitor in sleep mode" +msgid "Monitor in sleep mode" msgstr "Monitor in slaapstand" -msgid "GLSL shaders" +msgid "GLSL shaders" msgstr "GLSL Shaders" -msgid "You are loading an unsupported configuration" +msgid "You are loading an unsupported configuration" msgstr "U laadt een configuratie die niet wordt ondersteund" -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." +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 "Filteren op CPU type voor de geselecteerde machine is niet mogelijk met de geselecteerde machine.\n\nDit maakt het mogelijk een CPU te kunnen kiezen die anders niet compatible zou zijn met de geselecteerde machine. Je kunt hiermee echter compatibiliteitsproblemen krijgen met de BIOS van de machine of met andere software.\n\nHet inschakelen van deze instelling wordt niet officieel ondersteund en bugrapporten die worden ingediend kunnen als ongeldig worden gesloten." -msgid "Continue" +msgid "Continue" msgstr "Doorgaan" -msgid "Cassette: %1" +msgid "Cassette: %1" msgstr "Cassette: %1" -msgid "Cassette images" +msgid "Cassette images" msgstr "Cassette-images" -msgid "Cartridge %1: %2" +msgid "Cartridge %1: %2" msgstr "Cartridge %1: %2" -msgid "Cartridge images" +msgid "Cartridge images" msgstr "Cartridge-images" -msgid "Resume execution" +msgid "Resume execution" msgstr "Hervat executie" -msgid "Pause execution" +msgid "Pause execution" msgstr "Pauze executie" -msgid "Press Ctrl+Alt+Del" +msgid "Press Ctrl+Alt+Del" msgstr "Druk op Ctrl+Alt+Del" -msgid "Press Ctrl+Alt+Esc" +msgid "Press Ctrl+Alt+Esc" msgstr "Druk op Ctrl+Alt+Esc" -msgid "Hard reset" +msgid "Hard reset" msgstr "Harde reset" -msgid "ACPI shutdown" +msgid "ACPI shutdown" msgstr "ACPI uitschakeling" -msgid "Hard disk (%1)" +msgid "Hard disk (%1)" msgstr "Harde schijf (%1)" -msgid "MFM/RLL or ESDI CD-ROM drives never existed" +msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL of ESDI CD-ROM-stations hebben nooit bestaan" -msgid "Custom..." +msgid "Custom..." msgstr "Aangepast..." -msgid "Custom (large)..." +msgid "Custom (large)..." msgstr "Aangepast (groot)..." -msgid "Add New Hard Disk" +msgid "Add New Hard Disk" msgstr "Nieuwe harde schijf toevoegen" -msgid "Add Existing Hard Disk" +msgid "Add Existing Hard Disk" msgstr "Bestaande harde schijf toevoegen" -msgid "HDI disk images cannot be larger than 4 GB." +msgid "HDI disk images cannot be larger than 4 GB." msgstr "HDI-schijfimages kunnen niet groter zijn dan 4 GB." -msgid "Disk images cannot be larger than 127 GB." +msgid "Disk images cannot be larger than 127 GB." msgstr "Schijfimages kunnen niet groter zijn dan 127 GB." -msgid "Hard disk images" +msgid "Hard disk images" msgstr "Harde schijf-image" -msgid "Unable to read file" +msgid "Unable to read file" msgstr "Kan bestand niet lezen" -msgid "Unable to write file" +msgid "Unable to write file" msgstr "Kan bestand niet schrijven" -msgid "HDI or HDX images with a sector size other than 512 are not supported." +msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "HDI- of HDX-image met een andere sectorgrootte dan 512 worden niet ondersteund." -msgid "Disk image file already exists" +msgid "Disk image file already exists" msgstr "Schijfimagebestand bestaat al" -msgid "Please specify a valid file name." +msgid "Please specify a valid file name." msgstr "Geef een geldige bestandsnaam op." -msgid "Disk image created" +msgid "Disk image created" msgstr "Schijfimage gemaakt" -msgid "Make sure the file exists and is readable." +msgid "Make sure the file exists and is readable." msgstr "Controleer of het bestand bestaat en leesbaar is." -msgid "Make sure the file is being saved to a writable directory." +msgid "Make sure the file is being saved to a writable directory." msgstr "Zorg ervoor dat het bestand wordt opgeslagen in een schrijfbare map." -msgid "Disk image too large" +msgid "Disk image too large" msgstr "Schijfimage te groot" -msgid "Remember to partition and format the newly-created drive." +msgid "Remember to partition and format the newly-created drive." msgstr "Vergeet niet om de nieuw aangemaakte schijf te partitioneren en te formatteren." -msgid "The selected file will be overwritten. Are you sure you want to use it?" +msgid "The selected file will be overwritten. Are you sure you want to use it?" msgstr "Het geselecteerde bestand wordt overschreven. Weet u zeker dat u het wilt gebruiken?" -msgid "Unsupported disk image" +msgid "Unsupported disk image" msgstr "Niet-ondersteunde schijfimage" -msgid "Overwrite" +msgid "Overwrite" msgstr "Overschrijven" -msgid "Don't overwrite" +msgid "Don't overwrite" msgstr "Niet overschrijven" -msgid "Raw image" +msgid "Raw image" msgstr "Ruw image" -msgid "HDI image" +msgid "HDI image" msgstr "HDI-image" -msgid "HDX image" +msgid "HDX image" msgstr "HDX-image" -msgid "Fixed-size VHD" +msgid "Fixed-size VHD" msgstr "VHD met vaste grootte" -msgid "Dynamic-size VHD" +msgid "Dynamic-size VHD" msgstr "VHD met dynamisch grootte" -msgid "Differencing VHD" +msgid "Differencing VHD" msgstr "Verschil-VHD" -msgid "(N/A)" +msgid "(N/A)" msgstr "(N/A)" -msgid "Raw image (.img)" +msgid "Raw image (.img)" msgstr "Ruw image (.img)" -msgid "HDI image (.hdi)" +msgid "HDI image (.hdi)" msgstr "HDI-image (.hdi)" -msgid "HDX image (.hdx)" +msgid "HDX image (.hdx)" msgstr "HDX-image (.hdx)" -msgid "Fixed-size VHD (.vhd)" +msgid "Fixed-size VHD (.vhd)" msgstr "VHD met vaste grootte (.vhd)" -msgid "Dynamic-size VHD (.vhd)" +msgid "Dynamic-size VHD (.vhd)" msgstr "VHD met dynamisch grootte (.vhd)" -msgid "Differencing VHD (.vhd)" +msgid "Differencing VHD (.vhd)" msgstr "Verschil-VHD (.vhd)" -msgid "Large blocks (2 MB)" +msgid "Large blocks (2 MB)" msgstr "Grote blokken (2 MB)" -msgid "Small blocks (512 KB)" +msgid "Small blocks (512 KB)" msgstr "Kleine blokken (512 KB)" -msgid "VHD files" +msgid "VHD files" msgstr "VHD-bestanden" -msgid "Select the parent VHD" +msgid "Select the parent VHD" msgstr "Selecteer de bovenliggende VHD" -msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" +msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" msgstr "Dit kan betekenen dat de bovenliggende image is gewijzigd nadat de verschil-image is gemaakt.\n\nDit kan ook gebeuren als de imagebestanden zijn verplaatst of gekopieerd, of door een fout in het programma waarmee deze schijf is gemaakt.\n\nWil je de tijdstempels herstellen?" -msgid "Parent and child disk timestamps do not match" +msgid "Parent and child disk timestamps do not match" msgstr "Bovenliggende en onderliggende schijf tijdstempels komen niet overeen" -msgid "Could not fix VHD timestamp." +msgid "Could not fix VHD timestamp." msgstr "Kan VHD tijdstempel niet herstellen." -msgid "MFM/RLL" +msgid "MFM/RLL" msgstr "MFM/RLL" -msgid "XTA" +msgid "XTA" msgstr "XTA" -msgid "ESDI" +msgid "ESDI" msgstr "ESDI" -msgid "IDE" +msgid "IDE" msgstr "IDE" -msgid "ATAPI" +msgid "ATAPI" msgstr "ATAPI" -msgid "CD-ROM %1 (%2): %3" +msgid "CD-ROM %1 (%2): %3" msgstr "CD-ROM %1 (%2): %3" -msgid "160 KB" +msgid "160 KB" msgstr "160 KB" -msgid "180 KB" +msgid "180 KB" msgstr "180 KB" -msgid "320 KB" +msgid "320 KB" msgstr "320 KB" -msgid "360 KB" +msgid "360 KB" msgstr "360 KB" -msgid "640 KB" +msgid "640 KB" msgstr "640 KB" -msgid "720 KB" +msgid "720 KB" msgstr "720 KB" -msgid "1.2 MB" +msgid "1.2 MB" msgstr "1,2 MB" -msgid "1.25 MB" +msgid "1.25 MB" msgstr "1,25 MB" -msgid "1.44 MB" +msgid "1.44 MB" msgstr "1,44 MB" -msgid "DMF (cluster 1024)" +msgid "DMF (cluster 1024)" msgstr "DMF (cluster 1024)" -msgid "DMF (cluster 2048)" +msgid "DMF (cluster 2048)" msgstr "DMF (cluster 2048)" -msgid "2.88 MB" +msgid "2.88 MB" msgstr "2,88 MB" -msgid "ZIP 100" +msgid "ZIP 100" msgstr "ZIP 100" -msgid "3.5\" 128 MB (ISO 10090)" +msgid "3.5\" 128 MB (ISO 10090)" msgstr "3,5\" 128 MB (ISO 10090)" -msgid "3.5\" 230 MB (ISO 13963)" +msgid "3.5\" 230 MB (ISO 13963)" msgstr "3,5\" 230 MB (ISO 13963)" -msgid "3.5\" 540 MB (ISO 15498)" +msgid "3.5\" 540 MB (ISO 15498)" msgstr "3,5\" 540 MB (ISO 15498)" -msgid "3.5\" 640 MB (ISO 15498)" +msgid "3.5\" 640 MB (ISO 15498)" msgstr "3,5\" 640 MB (ISO 15498)" -msgid "3.5\" 1.3 GB (GigaMO)" +msgid "3.5\" 1.3 GB (GigaMO)" msgstr "3,5\" 1,3 GB (GigaMO)" -msgid "3.5\" 2.3 GB (GigaMO 2)" +msgid "3.5\" 2.3 GB (GigaMO 2)" msgstr "3,5\" 2,3 GB (GigaMO 2)" -msgid "5.25\" 600 MB" +msgid "5.25\" 600 MB" msgstr "5,25\" 600 MB" -msgid "5.25\" 650 MB" +msgid "5.25\" 650 MB" msgstr "5,25\" 650 MB" -msgid "5.25\" 1 GB" +msgid "5.25\" 1 GB" msgstr "5,25\" 1 GB" -msgid "5.25\" 1.3 GB" +msgid "5.25\" 1.3 GB" msgstr "5,25\" 1,3 GB" -msgid "Perfect RPM" +msgid "Perfect RPM" msgstr "Perfecte RPM" -msgid "1% below perfect RPM" +msgid "1% below perfect RPM" msgstr "1% onder perfecte RPM" -msgid "1.5% below perfect RPM" +msgid "1.5% below perfect RPM" msgstr "1,5% onder perfecte RPM" -msgid "2% below perfect RPM" +msgid "2% below perfect RPM" msgstr "2% onder perfecte RPM" -msgid "(System Default)" +msgid "(System Default)" msgstr "(Systeemstandaard)" -msgid "Failed to initialize network driver" +msgid "Failed to initialize network driver" msgstr "Netwerkstuurprogramma niet geïnitialiseerd" -msgid "The network configuration will be switched to the null driver" +msgid "The network configuration will be switched to the null driver" msgstr "De netwerkconfiguratie wordt overgeschakeld naar de nul-driver" -msgid "Mouse sensitivity:" +msgid "Mouse sensitivity:" msgstr "Muisgevoeligheid:" -msgid "Select media images from program working directory" +msgid "Select media images from program working directory" msgstr "Selecteer media-images uit de werkmap van het programma" -msgid "PIT mode:" +msgid "PIT mode:" msgstr "PIT-modus:" -msgid "Auto" +msgid "Auto" msgstr "Auto" -msgid "Slow" +msgid "Slow" msgstr "Langzaam" -msgid "Fast" +msgid "Fast" msgstr "Snel" -msgid "&Auto-pause on focus loss" +msgid "&Auto-pause on focus loss" msgstr "&Autopauze bij focusverlies" -msgid "WinBox is no longer supported" +msgid "WinBox is no longer supported" msgstr "WinBox wordt niet langer ondersteund" -msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." msgstr "De ontwikkeling van de WinBox manager is gestopt in 2022 door een gebrek aan beheerders. Omdat we onze inspanningen richten op het nog beter maken van 86Box, hebben we de beslissing genomen om WinBox niet langer te ondersteunen als een manager.\n\nEr zullen geen verdere updates worden geleverd door WinBox. Je kunt onjuist gedrag tegenkomen als je het blijft gebruiken met nieuwere versies van 86Box. Alle bugrapporten gerelateerd aan het gedrag van WinBox zullen worden gesloten als ongeldig.\n\nGa naar 86box.net voor een lijst van andere managers die je kunt gebruiken." -msgid "Generate" +msgid "Generate" msgstr "Genereren" -msgid "Joystick configuration" +msgid "Joystick configuration" msgstr "Joystick configuratie " -msgid "Device" +msgid "Device" msgstr "Apparaat" -msgid "%1 (X axis)" +msgid "%1 (X axis)" msgstr "%1 (X-as)" -msgid "%1 (Y axis)" +msgid "%1 (Y axis)" msgstr "%1 (Y-as)" -msgid "MCA devices" +msgid "MCA devices" msgstr "MCA-apparaten" -msgid "List of MCA devices:" +msgid "List of MCA devices:" msgstr "Lijst van MCA-apparaten:" -msgid "Tablet tool" +msgid "Tablet tool" msgstr "Tablet-hulpmiddel" -msgid "Qt (OpenGL &ES)" +msgid "Qt (OpenGL &ES)" msgstr "Qt (OpenGL &ES)" -msgid "About Qt" +msgid "About Qt" msgstr "Over Qt" -msgid "MCA devices..." +msgid "MCA devices..." msgstr "MCA-apparaten..." -msgid "Show non-primary monitors" +msgid "Show non-primary monitors" msgstr "Toon niet-primaire monitors" -msgid "Open screenshots folder..." +msgid "Open screenshots folder..." msgstr "Map met schermafbeeldingen openen..." -msgid "Apply fullscreen stretch mode when maximized" +msgid "Apply fullscreen stretch mode when maximized" msgstr "Pas fullscreen stretchmodus toe wanneer gemaximaliseerd" -msgid "Cursor/Puck" +msgid "Cursor/Puck" msgstr "Cursor/Puck" -msgid "Pen" +msgid "Pen" msgstr "Pen" -msgid "Host CD/DVD Drive (%1:)" +msgid "Host CD/DVD Drive (%1:)" msgstr "Host cd/dvd-station (%1:)" -msgid "&Connected" +msgid "&Connected" msgstr "&Verbonden" -msgid "Clear image history" +msgid "Clear image history" msgstr "Imagegeschiedenis verwijderen" -msgid "Create..." +msgid "Create..." msgstr "Creëer..." -msgid "Host CD/DVD Drive (%1)" +msgid "Host CD/DVD Drive (%1)" msgstr "Host CD/DVD-station (%1)" -msgid "Unknown Bus" +msgid "Unknown Bus" msgstr "Onbekende bus" -msgid "Null Driver" +msgid "Null Driver" msgstr "Null Driver" -msgid "NIC %1 (%2) %3" +msgid "NIC %1 (%2) %3" msgstr "NIC %1 (%2) %3" -msgid "Render behavior" +msgid "Render behavior" msgstr "Rendergedrag" -msgid "Use target framerate:" +msgid "Use target framerate:" msgstr "Gebruik doelframerate:" -msgid " fps" +msgid " fps" msgstr " fps" -msgid "VSync" +msgid "VSync" msgstr "VSync" -msgid "Synchronize with video" +msgid "Synchronize with video" msgstr "Synchroniseren met video" -msgid "Shaders" +msgid "Shaders" msgstr "Shaders" -msgid "Remove" +msgid "Remove" msgstr "Verwijderen" -msgid "Browse..." +msgid "Browse..." msgstr "Bladeren..." -msgid "Couldn't create OpenGL context." +msgid "Couldn't create OpenGL context." msgstr "Kan OpenGL context niet maken." -msgid "Couldn't switch to OpenGL context." +msgid "Couldn't switch to OpenGL context." msgstr "Kan niet overschakelen naar OpenGL context." -msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" +msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" msgstr "OpenGL versie 3.0 of hoger is vereist. De huidige versie is %1.%2" -msgid "Error initializing OpenGL" +msgid "Error initializing OpenGL" msgstr "Fout bij het initialiseren van OpenGL" -msgid "\nFalling back to software rendering." +msgid "\nFalling back to software rendering." msgstr "\nTerugvallen op software rendering." -msgid "<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>" +msgid "<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>" msgstr "<html><head/><body><p>Bij het selecteren van media-images (CD-ROM, floppy, etc.) zal de \"open dialoog\" starten in dezelfde map als het 86Box configuratiebestand. Deze instelling is doet er waarschijnlijk alleen toe op macOS.</p></body></html>" -msgid "This machine might have been moved or copied." +msgid "This machine might have been moved or copied." msgstr "Deze machine is misschien verplaatst of gekopieerd." -msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure." +msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure." msgstr "Om een goede netwerkfunctionaliteit te garanderen, moet 86Box weten of deze machine verplaatst of gekopieerd is.\n\nSelecteer \"Ik heb het gekopieerd\" als u het niet zeker weet." -msgid "I Moved It" +msgid "I Moved It" msgstr "Ik heb het verplaatst" -msgid "I Copied It" +msgid "I Copied It" msgstr "Ik heb het gekopieerd" -msgid "86Box Monitor #" +msgid "86Box Monitor #" msgstr "86Box Monitor #" -msgid "No MCA devices." +msgid "No MCA devices." msgstr "Geen MCA-apparaten." -msgid "MiB" +msgid "MiB" msgstr "MiB" -msgid "Network Card #1" +msgid "Network Card #1" msgstr "Netwerkkaart #1" -msgid "Network Card #2" +msgid "Network Card #2" msgstr "Netwerkkaart #2" -msgid "Network Card #3" +msgid "Network Card #3" msgstr "Netwerkkaart #3" -msgid "Network Card #4" +msgid "Network Card #4" msgstr "Netwerkkaart #4" -msgid "Mode" +msgid "Mode" msgstr "Modus" -msgid "Interface" +msgid "Interface" msgstr "Interface" -msgid "Adapter" +msgid "Adapter" msgstr "Adapter" -msgid "VDE Socket" +msgid "VDE Socket" msgstr "VDE-socket" -msgid "86Box Unit Tester" +msgid "86Box Unit Tester" msgstr "86Box apparaattester" -msgid "Novell NetWare 2.x Key Card" +msgid "Novell NetWare 2.x Key Card" msgstr "Novell NetWare 2.x Key Card" -msgid "Serial port passthrough 1" +msgid "Serial port passthrough 1" msgstr "Seriële poort doorvoer 1" -msgid "Serial port passthrough 2" +msgid "Serial port passthrough 2" msgstr "Seriële poort doorvoer 2" -msgid "Serial port passthrough 3" +msgid "Serial port passthrough 3" msgstr "Seriële poort doorvoer 3" -msgid "Serial port passthrough 4" +msgid "Serial port passthrough 4" msgstr "Seriële poort doorvoer 4" -msgid "Renderer options..." +msgid "Renderer options..." msgstr "Renderer-opties..." -msgid "Logitech/Microsoft Bus Mouse" +msgid "Logitech/Microsoft Bus Mouse" msgstr "Logitech/Microsoft busmuis" -msgid "Microsoft Bus Mouse (InPort)" +msgid "Microsoft Bus Mouse (InPort)" msgstr "Microsoft busmuis (InPort)" -msgid "Mouse Systems Serial Mouse" +msgid "Mouse Systems Serial Mouse" msgstr "Mouse Systems seriële muis" -msgid "Microsoft Serial Mouse" +msgid "Microsoft Serial Mouse" msgstr "Microsoft seriële muis" -msgid "Logitech Serial Mouse" +msgid "Logitech Serial Mouse" msgstr "Logitech seriële muis" -msgid "PS/2 Mouse" +msgid "PS/2 Mouse" msgstr "PS/2-muis" -msgid "3M MicroTouch (Serial)" +msgid "3M MicroTouch (Serial)" msgstr "3M MicroTouch (serieel)" -msgid "[COM] Standard Hayes-compliant Modem" +msgid "[COM] Standard Hayes-compliant Modem" msgstr "COM] Standaard Hayes-compatibele modem " -msgid "Roland MT-32 Emulation" +msgid "Roland MT-32 Emulation" msgstr "Roland MT-32-emulatie" -msgid "Roland MT-32 (New) Emulation" +msgid "Roland MT-32 (New) Emulation" msgstr "Roland MT-32 (nieuwe) emulatie" -msgid "Roland CM-32L Emulation" +msgid "Roland CM-32L Emulation" msgstr "Roland CM-32L-emulatie" -msgid "Roland CM-32LN Emulation" +msgid "Roland CM-32LN Emulation" msgstr "Roland CM-32LN-emulatie" -msgid "OPL4-ML Daughterboard" +msgid "OPL4-ML Daughterboard" msgstr "OPL4-ML-dochterbord" -msgid "System MIDI" +msgid "System MIDI" msgstr "Systeem MIDI" -msgid "MIDI Input Device" +msgid "MIDI Input Device" msgstr "MIDI-ingangsapparaat" -msgid "BIOS Address" +msgid "BIOS Address" msgstr "BIOS-adres" -msgid "Enable BIOS extension ROM Writes" +msgid "Enable BIOS extension ROM Writes" msgstr "BIOS-extensie ROM Writes inschakelen" -msgid "Address" +msgid "Address" msgstr "Adres" -msgid "IRQ" +msgid "IRQ" msgstr "IRQ" -msgid "BIOS Revision" +msgid "BIOS Revision" msgstr "BIOS Revisie" -msgid "Translate 26 -> 17" +msgid "Translate 26 -> 17" msgstr "Vertaal 26 -> 17" -msgid "Language" +msgid "Language" msgstr "Taal" -msgid "Enable backlight" +msgid "Enable backlight" msgstr "Backlight inschakelen" -msgid "Invert colors" +msgid "Invert colors" msgstr "Kleuren omkeren" -msgid "BIOS size" +msgid "BIOS size" msgstr "BIOS-grootte" -msgid "Map C0000-C7FFF as UMB" +msgid "Map C0000-C7FFF as UMB" msgstr "Geheugenadres C0000-C7FFF toewijzen aan UMB" -msgid "Map C8000-CFFFF as UMB" +msgid "Map C8000-CFFFF as UMB" msgstr "Geheugenadres C8000-CFFFF toewijzen aan UMB" -msgid "Map D0000-D7FFF as UMB" +msgid "Map D0000-D7FFF as UMB" msgstr "Geheugenadres D0000-D7FFF toewijzen aan UMB" -msgid "Map D8000-DFFFF as UMB" +msgid "Map D8000-DFFFF as UMB" msgstr "Geheugenadres D8000-DFFFF toewijzen aan UMB" -msgid "Map E0000-E7FFF as UMB" +msgid "Map E0000-E7FFF as UMB" msgstr "Geheugenadres E0000-E7FFF toewijzen aan UMB" -msgid "Map E8000-EFFFF as UMB" +msgid "Map E8000-EFFFF as UMB" msgstr "Geheugenadres E8000-EFFFF toewijzen aan UMB" -msgid "JS9 Jumper (JIM)" +msgid "JS9 Jumper (JIM)" msgstr "JS9 Jumper (JIM)" -msgid "MIDI Output Device" +msgid "MIDI Output Device" msgstr "MIDI-uitgangsapparaat" -msgid "MIDI Real time" +msgid "MIDI Real time" msgstr "MIDI real-time" -msgid "MIDI Thru" +msgid "MIDI Thru" msgstr "MIDI doorvoer" -msgid "MIDI Clockout" +msgid "MIDI Clockout" msgstr "MIDI Clockout" -msgid "SoundFont" +msgid "SoundFont" msgstr "SoundFont" -msgid "Output Gain" +msgid "Output Gain" msgstr "Output Gain" -msgid "Chorus" +msgid "Chorus" msgstr "Chorus" -msgid "Chorus Voices" +msgid "Chorus Voices" msgstr "Chorus-stemmen" -msgid "Chorus Level" +msgid "Chorus Level" msgstr "Chorus-niveau" -msgid "Chorus Speed" +msgid "Chorus Speed" msgstr "Chorus-snelheid" -msgid "Chorus Depth" +msgid "Chorus Depth" msgstr "Chorus-diepte" -msgid "Chorus Waveform" +msgid "Chorus Waveform" msgstr "Chorus-golfvorm" -msgid "Reverb" +msgid "Reverb" msgstr "Reverb" -msgid "Reverb Room Size" +msgid "Reverb Room Size" msgstr "Reverbkamer afmetingen" -msgid "Reverb Damping" +msgid "Reverb Damping" msgstr "Reverbdemping" -msgid "Reverb Width" +msgid "Reverb Width" msgstr "Reverbbreedte" -msgid "Reverb Level" +msgid "Reverb Level" msgstr "Reverbniveau" -msgid "Interpolation Method" +msgid "Interpolation Method" msgstr "Interpolatiemethode" -msgid "Reverb Output Gain" +msgid "Reverb Output Gain" msgstr "Reverbuitgang Versterking" -msgid "Reversed stereo" +msgid "Reversed stereo" msgstr "Omgekeerde stereo" -msgid "Nice ramp" +msgid "Nice ramp" msgstr "Mooie helling" -msgid "Hz" +msgid "Hz" msgstr "Hz" -msgid "Buttons" +msgid "Buttons" msgstr "Knoppen" -msgid "Serial Port" +msgid "Serial Port" msgstr "Seriële poort" -msgid "RTS toggle" +msgid "RTS toggle" msgstr "RTS toggle" -msgid "Revision" +msgid "Revision" msgstr "Revisie" -msgid "Controller" +msgid "Controller" msgstr "Controller" -msgid "Show Crosshair" +msgid "Show Crosshair" msgstr "Toon dradenkruis" -msgid "DMA" +msgid "DMA" msgstr "DMA" -msgid "MAC Address" +msgid "MAC Address" msgstr "MAC-adres" -msgid "MAC Address OUI" +msgid "MAC Address OUI" msgstr "MAC-adres OUI" -msgid "Enable BIOS" +msgid "Enable BIOS" msgstr "BIOS inschakelen" -msgid "Baud Rate" +msgid "Baud Rate" msgstr "Baud-snelheid" -msgid "TCP/IP listening port" +msgid "TCP/IP listening port" msgstr "TCP/IP-luisterpoort" -msgid "Phonebook File" +msgid "Phonebook File" msgstr "Telefoonboekbestand" -msgid "Telnet emulation" +msgid "Telnet emulation" msgstr "Telnet-emulatie" -msgid "RAM Address" +msgid "RAM Address" msgstr "RAM-adres" -msgid "RAM size" +msgid "RAM size" msgstr "RAM-grootte" -msgid "Initial RAM size" +msgid "Initial RAM size" msgstr "Oorspronkelijke RAM-grootte" -msgid "Serial Number" +msgid "Serial Number" msgstr "Serienummer" -msgid "Host ID" +msgid "Host ID" msgstr "Host-ID" -msgid "FDC Address" +msgid "FDC Address" msgstr "FDC Adres" -msgid "MPU-401 Address" +msgid "MPU-401 Address" msgstr "MPU-401 Adres" -msgid "MPU-401 IRQ" +msgid "MPU-401 IRQ" msgstr "MPU-401 IRQ" -msgid "Receive MIDI input" +msgid "Receive MIDI input" msgstr "MIDI-ingang ontvangen" -msgid "Low DMA" +msgid "Low DMA" msgstr "Lage DMA" -msgid "Enable Game port" +msgid "Enable Game port" msgstr "Game-poort inschakelen" -msgid "Surround module" +msgid "Surround module" msgstr "Surroundmodule" -msgid "CODEC" +msgid "CODEC" msgstr "Codec" -msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)" +msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)" msgstr "Verhoog CODEC interrupt bij CODEC setup (nodig voor sommige stuurprogramma's)" -msgid "SB Address" +msgid "SB Address" msgstr "SB-adres" -msgid "WSS IRQ" +msgid "WSS IRQ" msgstr "WSS IRQ" -msgid "WSS DMA" +msgid "WSS DMA" msgstr "WSS DMA" -msgid "Enable OPL" +msgid "Enable OPL" msgstr "OPL inschakelen" -msgid "Receive MIDI input (MPU-401)" +msgid "Receive MIDI input (MPU-401)" msgstr "MIDI-ingang ontvangen (MPU-401)" -msgid "SB low DMA" +msgid "SB low DMA" msgstr "SB lage DMA" -msgid "6CH variant (6-channel)" +msgid "6CH variant (6-channel)" msgstr "6CH-variant (6-kanaals)" -msgid "Enable CMS" +msgid "Enable CMS" msgstr "CMS inschakelen" -msgid "Mixer" +msgid "Mixer" msgstr "Mixer" -msgid "High DMA" +msgid "High DMA" msgstr "Hoge DMA" -msgid "Control PC speaker" +msgid "Control PC speaker" msgstr "Bestuur pc-luidspreker" -msgid "Memory size" +msgid "Memory size" msgstr "Geheugengrootte" -msgid "EMU8000 Address" +msgid "EMU8000 Address" msgstr "EMU8000 Adres" -msgid "IDE Controller" +msgid "IDE Controller" msgstr "IDE-controller" -msgid "Codec" +msgid "Codec" msgstr "Codec" -msgid "GUS type" +msgid "GUS type" msgstr "GUS-type" -msgid "Enable 0x04 \"Exit 86Box\" command" +msgid "Enable 0x04 \"Exit 86Box\" command" msgstr "Schakel het commando 0x04 \"Exit 86Box\" in" -msgid "Display type" +msgid "Display type" msgstr "Scherm type" -msgid "Composite type" +msgid "Composite type" msgstr "Composite type" -msgid "RGB type" +msgid "RGB type" msgstr "RGB-type" -msgid "Line doubling type" +msgid "Line doubling type" msgstr "Type lijnverdubbeling" -msgid "Snow emulation" +msgid "Snow emulation" msgstr "Sneeuwemulatie" -msgid "Monitor type" +msgid "Monitor type" msgstr "Type monitor" -msgid "Character set" +msgid "Character set" msgstr "Tekenset" -msgid "XGA type" +msgid "XGA type" msgstr "XGA-type" -msgid "Instance" +msgid "Instance" msgstr "Instantie" -msgid "MMIO Address" +msgid "MMIO Address" msgstr "MMIO-adres" -msgid "RAMDAC type" +msgid "RAMDAC type" msgstr "RAMDAC type" -msgid "Blend" +msgid "Blend" msgstr "Mengen" -msgid "Bilinear filtering" +msgid "Bilinear filtering" msgstr "Bilineaire filtering" -msgid "Dithering" +msgid "Dithering" msgstr "Dithering" -msgid "Enable NMI for CGA emulation" +msgid "Enable NMI for CGA emulation" msgstr "NMI inschakelen voor CGA-emulatie" -msgid "Voodoo type" +msgid "Voodoo type" msgstr "Voodoo-type" -msgid "Framebuffer memory size" +msgid "Framebuffer memory size" msgstr "Framebuffer geheugengrootte" -msgid "Texture memory size" +msgid "Texture memory size" msgstr "Grootte textuurgeheugen" -msgid "Dither subtraction" +msgid "Dither subtraction" msgstr "Dither aftrekken" -msgid "Screen Filter" +msgid "Screen Filter" msgstr "Schermfilter" -msgid "Render threads" +msgid "Render threads" msgstr "Render threads" -msgid "SLI" +msgid "SLI" msgstr "SLI" -msgid "Start Address" +msgid "Start Address" msgstr "Startadres" -msgid "Contiguous Size" +msgid "Contiguous Size" msgstr "Aaneengesloten grootte" -msgid "I/O Width" +msgid "I/O Width" msgstr "I/O-breedte" -msgid "Transfer Speed" +msgid "Transfer Speed" msgstr "Overdrachtssnelheid" -msgid "EMS mode" +msgid "EMS mode" msgstr "EMS-modus" -msgid "Address for > 2 MB" +msgid "Address for > 2 MB" msgstr "Adres voor > 2 MB" -msgid "Frame Address" +msgid "Frame Address" msgstr "Frameadres" -msgid "USA" +msgid "USA" msgstr "USA" -msgid "Danish" +msgid "Danish" msgstr "Deens" -msgid "Always at selected speed" +msgid "Always at selected speed" msgstr "Altijd op geselecteerde snelheid" -msgid "BIOS setting + Hotkeys (off during POST)" +msgid "BIOS setting + Hotkeys (off during POST)" msgstr "BIOS-instelling + Sneltoetsen (niet actief tijdens POST)" -msgid "64 kB starting from F0000" +msgid "64 kB starting from F0000" msgstr "64 kB vanaf F0000" -msgid "128 kB starting from E0000 (address MSB inverted, last 64KB first)" +msgid "128 kB starting from E0000 (address MSB inverted, last 64KB first)" msgstr "128 kB vanaf E0000 (geïnverteerd MSB adres, laatste 64KB eerst)" -msgid "Sine" +msgid "Sine" msgstr "Sinus" -msgid "Triangle" +msgid "Triangle" msgstr "Driehoek" -msgid "Linear" +msgid "Linear" msgstr "Lineair" -msgid "4th Order" +msgid "4th Order" msgstr "4e Orde" -msgid "7th Order" +msgid "7th Order" msgstr "7e Orde" -msgid "Non-timed (original)" +msgid "Non-timed (original)" msgstr "Niet-getimed (origineel)" -msgid "45 Hz (JMP2 not populated)" +msgid "45 Hz (JMP2 not populated)" msgstr "45 Hz (JMP2 niet gezet)" -msgid "Two" +msgid "Two" msgstr "Twee" -msgid "Three" +msgid "Three" msgstr "Drie" -msgid "Wheel" +msgid "Wheel" msgstr "Wiel" -msgid "Five + Wheel" +msgid "Five + Wheel" msgstr "Vijf + Wiel" -msgid "A3 - SMT2 Serial / SMT3(R)V" +msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serieel / SMT3(R)V" -msgid "Q1 - SMT3(R) Serial" +msgid "Q1 - SMT3(R) Serial" msgstr "Q1 - SMT3(R) Serieel" -msgid "8 KB" +msgid "8 KB" msgstr "8 KB" -msgid "32 KB" +msgid "32 KB" msgstr "32 KB" -msgid "16 KB" +msgid "16 KB" msgstr "16 KB" -msgid "64 KB" +msgid "64 KB" msgstr "64 KB" -msgid "Disable BIOS" +msgid "Disable BIOS" msgstr "BIOS uitschakelen" -msgid "512 KB" +msgid "512 KB" msgstr "512 KB" -msgid "2 MB" +msgid "2 MB" msgstr "2 MB" -msgid "8 MB" +msgid "8 MB" msgstr "8 MB" -msgid "28 MB" +msgid "28 MB" msgstr "28 MB" -msgid "1 MB" +msgid "1 MB" msgstr "1 MB" -msgid "4 MB" +msgid "4 MB" msgstr "4 MB" -msgid "12 MB" +msgid "12 MB" msgstr "12 MB" -msgid "16 MB" +msgid "16 MB" msgstr "16 MB" -msgid "20 MB" +msgid "20 MB" msgstr "20 MB" -msgid "24 MB" +msgid "24 MB" msgstr "24 MB" -msgid "SigmaTel STAC9721T (stereo)" +msgid "SigmaTel STAC9721T (stereo)" msgstr "SigmaTel STAC9721T (stereo)" -msgid "Classic" +msgid "Classic" msgstr "Klassiek" -msgid "256 KB" +msgid "256 KB" msgstr "256 KB" -msgid "Composite" +msgid "Composite" msgstr "Composite" -msgid "Old" +msgid "Old" msgstr "Oud" -msgid "New" +msgid "New" msgstr "Nieuw" -msgid "Color (generic)" +msgid "Color (generic)" msgstr "Kleur (algemeen)" -msgid "Green Monochrome" +msgid "Green Monochrome" msgstr "Groen monochroom" -msgid "Amber Monochrome" +msgid "Amber Monochrome" msgstr "Amber Monochroom" -msgid "Gray Monochrome" +msgid "Gray Monochrome" msgstr "Grijs monochroom" -msgid "Color (no brown)" +msgid "Color (no brown)" msgstr "Kleur (geen bruin)" -msgid "Color (IBM 5153)" +msgid "Color (IBM 5153)" msgstr "Kleur (IBM 5153)" -msgid "Simple doubling" +msgid "Simple doubling" msgstr "Eenvoudige verdubbeling" -msgid "sRGB interpolation" +msgid "sRGB interpolation" msgstr "sRGB-interpolatie" -msgid "Linear interpolation" +msgid "Linear interpolation" msgstr "Lineaire interpolatie" -msgid "128 KB" +msgid "128 KB" msgstr "128 KB" -msgid "Monochrome (5151/MDA) (white)" +msgid "Monochrome (5151/MDA) (white)" msgstr "Monochroom (5151/MDA) (wit)" -msgid "Monochrome (5151/MDA) (green)" +msgid "Monochrome (5151/MDA) (green)" msgstr "Monochroom (5151/MDA) (groen)" -msgid "Monochrome (5151/MDA) (amber)" +msgid "Monochrome (5151/MDA) (amber)" msgstr "Monochroom (5151/MDA) (amber)" -msgid "Color 40x25 (5153/CGA)" +msgid "Color 40x25 (5153/CGA)" msgstr "Kleur 40x25 (5153/CGA)" -msgid "Color 80x25 (5153/CGA)" +msgid "Color 80x25 (5153/CGA)" msgstr "Kleur 80x25 (5153/CGA)" -msgid "Enhanced Color - Normal Mode (5154/ECD)" +msgid "Enhanced Color - Normal Mode (5154/ECD)" msgstr "Verbeterde kleur - normale modus (5154/ECD)" -msgid "Enhanced Color - Enhanced Mode (5154/ECD)" +msgid "Enhanced Color - Enhanced Mode (5154/ECD)" msgstr "Verbeterde kleur - Verbeterde modus (5154/ECD)" -msgid "Green" +msgid "Green" msgstr "Groen" -msgid "Amber" +msgid "Amber" msgstr "Amber" -msgid "Gray" +msgid "Gray" msgstr "Grijs" -msgid "Color" +msgid "Color" msgstr "Kleur" -msgid "U.S. English" +msgid "U.S. English" msgstr "Amerikaans Engels" -msgid "Scandinavian" +msgid "Scandinavian" msgstr "Scandinavisch" -msgid "Other languages" +msgid "Other languages" msgstr "Andere talen" -msgid "Bochs latest" +msgid "Bochs latest" msgstr "Bochs nieuwste" -msgid "Mono Non-Interlaced" +msgid "Mono Non-Interlaced" msgstr "Mono Non-Interlaced" -msgid "Color Interlaced" +msgid "Color Interlaced" msgstr "Kleur interlaced" -msgid "Color Non-Interlaced" +msgid "Color Non-Interlaced" msgstr "Kleur non-interlaced" -msgid "3Dfx Voodoo Graphics" +msgid "3Dfx Voodoo Graphics" msgstr "3Dfx Voodoo Graphics" -msgid "Obsidian SB50 + Amethyst (2 TMUs)" +msgid "Obsidian SB50 + Amethyst (2 TMUs)" msgstr "Obsidian SB50 + Amethyst (2 TMU's)" -msgid "8-bit" +msgid "8-bit" msgstr "8-bit" -msgid "16-bit" +msgid "16-bit" msgstr "16-bit" -msgid "Standard (150ns)" +msgid "Standard (150ns)" msgstr "Standaard (150ns)" -msgid "High-Speed (120ns)" +msgid "High-Speed (120ns)" msgstr "Hoge snelheid (120ns)" -msgid "Enabled" +msgid "Enabled" msgstr "Ingeschakeld" -msgid "Standard" +msgid "Standard" msgstr "Standaard" -msgid "High-Speed" +msgid "High-Speed" msgstr "Hoge snelheid" -msgid "Stereo LPT DAC" +msgid "Stereo LPT DAC" msgstr "Stereo LPT DAC" -msgid "Generic Text Printer" +msgid "Generic Text Printer" msgstr "Generieke tekstprinter" -msgid "Generic ESC/P Dot-Matrix Printer" +msgid "Generic ESC/P Dot-Matrix Printer" msgstr "Generieke ESC/P dot-matrix-printer" -msgid "Generic PostScript Printer" +msgid "Generic PostScript Printer" msgstr "Generieke PostScript-printer" -msgid "Generic PCL5e Printer" +msgid "Generic PCL5e Printer" msgstr "Generieke PCL5e-printer" -msgid "Parallel Line Internet Protocol" +msgid "Parallel Line Internet Protocol" msgstr "Internetprotocol voor parallelle lijnen" -msgid "Protection Dongle for Savage Quest" +msgid "Protection Dongle for Savage Quest" msgstr "Beschermingsdongle voor Savage Quest" -msgid "Serial Passthrough Device" +msgid "Serial Passthrough Device" msgstr "Serieel doorvoerapparaat" -msgid "Passthrough Mode" +msgid "Passthrough Mode" msgstr "Doorgeefmodus" -msgid "Host Serial Device" +msgid "Host Serial Device" msgstr "Host Serieel Apparaat" -msgid "Name of pipe" +msgid "Name of pipe" msgstr "Naam van de pipe" -msgid "Data bits" +msgid "Data bits" msgstr "Databits" -msgid "Stop bits" +msgid "Stop bits" msgstr "Stopbits" -msgid "Baud Rate of Passthrough" +msgid "Baud Rate of Passthrough" msgstr "Baud-snelheid van doorvoer" -msgid "Named Pipe (Server)" +msgid "Named Pipe (Server)" msgstr "Named Pipe (Server)" -msgid "Host Serial Passthrough" +msgid "Host Serial Passthrough" msgstr "Host seriële doorgave" -msgid "E&ject %1" +msgid "E&ject %1" msgstr "&Uitwerpen %1" -msgid "&Unmute" +msgid "&Unmute" msgstr "&Geluid aanzetten" -msgid "Softfloat FPU" +msgid "Softfloat FPU" msgstr "Softfloat FPU" -msgid "High performance impact" +msgid "High performance impact" msgstr "Hoge prestatie-impact" -msgid "[Generic] RAM Disk (max. speed)" +msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM-schijf (max. snelheid)" -msgid "IBM 8514/A clone (ISA)" +msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-kloon (ISA)" -msgid "Vendor" +msgid "Vendor" msgstr "Verkoper" -msgid "Generic PC/XT Memory Expansion" +msgid "Generic PC/XT Memory Expansion" msgstr "Generieke PC/XT geheugenuitbreiding" -msgid "Generic PC/AT Memory Expansion" +msgid "Generic PC/AT Memory Expansion" msgstr "Generieke PC/AT geheugenuitbreiding" msgid "Unable to find Dot-Matrix fonts" From d0d2ba29ec71d8de86def03f9f363f16d54ff165 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 11 Apr 2025 06:37:01 +0500 Subject: [PATCH 0716/1190] qt: Add the remaining untranslated strings to the template --- src/qt/languages/86box.pot | 51 ++++++++++++++++++++++++ src/qt/languages/ca-ES.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/cs-CZ.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/de-DE.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/es-ES.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/fi-FI.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/fr-FR.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/hr-HR.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/hu-HU.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/it-IT.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/ja-JP.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/ko-KR.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/nl-NL.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/pl-PL.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/pt-BR.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/pt-PT.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/ru-RU.po | 78 ++++++++++++++++++++++++++++++++++++ src/qt/languages/sk-SK.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/sl-SI.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/tr-TR.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/uk-UA.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/vi-VN.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/zh-CN.po | 81 ++++++++++++++++++++++++++++++++++++++ src/qt/languages/zh-TW.po | 81 ++++++++++++++++++++++++++++++++++++++ 24 files changed, 1911 insertions(+) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index fde3f921c..1d151a9d9 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2109,8 +2109,59 @@ msgstr "" msgid "Inhibit multimedia keys" msgstr "" +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + msgid "Model:" msgstr "" msgid "Failed to initialize Vulkan renderer." msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index f39be48ca..9dec41c32 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -2061,6 +2061,27 @@ msgstr "Alt impact en el rendiment" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disc RAM (velocitat màxima)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Clon IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "No es pot trobar tipus de lletra de matriu de punts" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Els tipus de lletra TrueType al directori \"roms/printer/fonts\" són necessaris per a l'emulació de la impressora de matriu de punts ESC/P genèrica." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 34b5dfa6d..2098fe018 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -2061,6 +2061,27 @@ msgstr "Vysoký dopad na výkon" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disk RAM (max. rychlost)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Nastala chyba při nachození jehličkových písem" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Pro emulaci obecné jehličkové tiskárny ESC/P jsou vyžadována písma TrueType ve složce \"roms/printer/fonts\"." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index e69d496a7..2088e4141 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -2064,6 +2064,27 @@ msgstr "Hohe Auswirkung auf die Leistung" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM-Diskette (maximale Geschwindigkeit)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-Klon (ISA)" @@ -2081,3 +2102,63 @@ msgstr "Nadel-Schriften konnten nicht gefunden werden" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "TrueType-Schriften in das \"roms/printer/fonts\"-Verzeichnis sind für die Allgemeines ESC/P Nadel-Druckers erforderlich." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 1e9bc1c23..bc11a4d4c 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -2060,6 +2060,27 @@ msgstr "Alto impact en el rendimiento" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disco RAM (velocidad máxima)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Clon IBM 8514/A (ISA)" @@ -2077,3 +2098,63 @@ msgstr "No fué posible encontrar las fuentes matriciales" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Las fuentes TrueType en el directorio \"roms/printer/fonts\" son necesarias para la emulación de la impresora matricial ESC/P genérica." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index d35e45b21..34e9aeead 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -2064,6 +2064,27 @@ msgstr "Suuri vaikutus suorituskykyyn" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM-levy (maksiminopeus)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-klooni (ISA)" @@ -2081,3 +2102,63 @@ msgstr "Pistematriisifontteja ei löydy" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "TrueType-fontteja kansiossa \"roms/printer/fonts\"-hakemistoon yleinen ESC/P pistematriisitulostin emulointiin." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 50de1f001..ebb181a30 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -2061,6 +2061,27 @@ msgstr "Impact important sur la performance" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disque RAM (vitesse maximale)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Clon IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Impossible de trouver les polices à matrice à points" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Les polices TrueType dans le répertoire \"roms/printer/fonts\" sont nécessaires à l'émulation de l'imprimante générique ESC/P à matrice à points." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 93c247319..c1f6480c2 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -2061,6 +2061,27 @@ msgstr "Visoki učinak na brzinu izvršavanja" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disk RAM (najviša brzina)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Nije moguće pronaći matrične fontove" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "TrueType fontovi u mapi \"roms/printer/fonts\" potrebni su za emulaciju generičnog matričnog pisača ESC/P." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index b92b9c11b..09f914860 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -2061,6 +2061,27 @@ msgstr "Nagy hatással van a teljesítményre" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM lemez (max. sebesség)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A klón (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Nem találja a Dot-Matrix betűtípusokat" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Az általános ESC/P pontmátrixnyomtató emulációjához a \"roms/printer/fonts\" könyvtárban található TrueType betűtípusok szükségesek." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index b85bb64bd..c9694c3be 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -2061,6 +2061,27 @@ msgstr "Impatto elevato sulla prestazione" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disco RAM (velocità massima)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Impossibile trovare i font a matrice di punti" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "I font TrueType presenti nella directory \"roms/printer/fonts\" sono necessari per l'emulazione della stampante a matrice di punti ESC/P generica." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 07c783dd1..1c139aaec 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -2061,6 +2061,27 @@ msgstr "パフォーマンスへの影響が大きい" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAMディスク(最高速度)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A クローン(ISA)" @@ -2078,3 +2099,63 @@ msgstr "ドットマトリクスフォントが見つかりません" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "汎用ESC/Pドットマトリクスプリンタのエミュレーションには、roms/printer/fontsディレクトリ内のTrueTypeフォントが必要です。" + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index cea372b7f..941bd740a 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -2061,6 +2061,27 @@ msgstr "성능에 미치는 영향" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM 디스크(최대 속도)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 클론(ISA)" @@ -2078,3 +2099,63 @@ msgstr "도트 매트릭스 글꼴을 찾을 수 없습니다" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "일반 ESC/P 도트 매트릭스 프린터의 에뮬레이션을 사용하려면 \"roms/printer/fonts\" 디렉터리에 있는 트루타입 글꼴이 필요합니다." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 20c193afe..fd2b66245 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -2061,6 +2061,27 @@ msgstr "Hoge prestatie-impact" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM-schijf (max. snelheid)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-kloon (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Dot-matrix-lettertypen niet gevonden" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "TrueType lettertypen in de map \"roms/printer/fonts\" zijn nodig voor de emulatie van de generieke ESC/P dot-matrix-printer." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 980ee69f1..ab50711f6 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -2061,6 +2061,27 @@ msgstr "Wysoki wpływ na wydajność" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Dysk RAM (maks. prędkość)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Nie można znaleźć czcionek igłowych" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Czcionki TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generyczniej drukarki igłowej ESC/P." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index c48e7a07f..db07a69ae 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2061,6 +2061,27 @@ msgstr "Alto impacto no desempenho" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disco RAM (velocidade máxima)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Não foi possível localizar os fontes matriciais de pontos" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 1900a42d9..f67ddbdf8 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -2061,6 +2061,27 @@ msgstr "Elevado impacto no desempenho" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disco RAM (velocidade máxima)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Não foi possível encontrar os fontes matriciais de pontos" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica" + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index afc4c72a4..a8cd0295a 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2061,6 +2061,27 @@ msgstr "Сильное влияние на производительность" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Стандартный] RAM-диск (макс. скорость)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Клон IBM 8514/A (ISA)" @@ -2085,5 +2106,62 @@ msgstr "Невозможно найти матричные шрифты" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P." +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + msgid "Model:" msgstr "Модель:" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index f1a6144a6..5080c49b5 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -2062,6 +2062,27 @@ msgstr "Vysoký vplyv na výkon" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disk RAM (max. rýchlosť)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" @@ -2079,3 +2100,63 @@ msgstr "Nastala chyba pri hľadaní ihličkových písem" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Písma TrueType v adresári \"roms/printer/fonts\" sú potrebné na emuláciu generickej ihličkovej tlačiarne ESC/P." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 94c241dea..c34fb6f7e 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -2061,6 +2061,27 @@ msgstr "Visok učinek na hitrost delovanja" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Pogon RAM (največja hitrost)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Matričnih pisav ni bilo mogoče najti" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Matrične pisave v imeniku \"roms/printer/fonts\" so potrebne za emulacijo generičnega matričnega tiskalnika ESC/P." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 1be214342..b7a59b620 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -2061,6 +2061,27 @@ msgstr "Ciddi performans düşüklüğüne neden olabilir" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM Disk (maks. hız)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A klonu (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Dot Matrix yazı tipleri bulunamıyor" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Sıradan ESC/P Dot Matrix Yazıcının emülasyonu için \"roms/printer/fonts\" dizinindeki TrueType yazı tipleri gereklidir." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 6acb947cf..3145f5e34 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -2061,6 +2061,27 @@ msgstr "Високий вплив на продуктивність" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Диск оперативної пам'яті (макс. швидкість)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "Клон IBM 8514/A (ISA)" @@ -2084,3 +2105,63 @@ msgstr "Неможливо знайти матричні шрифти" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Шрифти TrueType у каталозі \"roms/printer/fonts\" потрібні для емуляції загального матричного принтера Generic ESC/P." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index c1d461fb7..932150f7b 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -2061,6 +2061,27 @@ msgstr "Ảnh hưởng lớn đến hiệu suất" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Đĩa RAM (tốc độ tối đa)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A bản nhái (ISA)" @@ -2078,3 +2099,63 @@ msgstr "Không tìm thấy phông chữ ma trận chấm" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "Cần có phông chữ TrueType trong thư mục \"roms/printer/fonts\" để mô phỏng máy in generic ESC/P ma trận chấm." + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 0ce76cff9..18f5a8fb8 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -2061,6 +2061,27 @@ msgstr "重大性能影响" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM 磁盘 (最大速度)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" @@ -2078,3 +2099,63 @@ msgstr "无法找到点阵字体" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。" + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index d50449aa2..9dbf51c70 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2061,6 +2061,27 @@ msgstr "對效能影響大" msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM 磁碟 (最大速度)" +msgid "[Generic] 1989 (3500 RPM)" +msgstr "" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "" + msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" @@ -2078,3 +2099,63 @@ msgstr "無法找到點矩陣字型" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." msgstr "通用 ESC/P 點矩陣印表機的模擬需要 \"roms/printer/fonts\" 目錄中的 TrueType 字體。" + +msgid "Inhibit multimedia keys" +msgstr "" + +msgid "Ask for confirmation before saving settings" +msgstr "" + +msgid "Ask for confirmation before hard resetting" +msgstr "" + +msgid "Ask for confirmation before quitting" +msgstr "" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Model:" +msgstr "" + +msgid "Failed to initialize Vulkan renderer." +msgstr "" + +msgid "GLSL Error" +msgstr "" + +msgid "Could not load shader: %1" +msgstr "" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "" + +msgid "Could not load texture: %1" +msgstr "" + +msgid "Could not compile shader:\n\n%1" +msgstr "" + +msgid "Program not linked:\n\n%1" +msgstr "" + +msgid "Shader Manager" +msgstr "" + +msgid "Shader Configuration" +msgstr "" + +msgid "Add" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Could not load file %1" +msgstr "" From 12eefc9519a8882da723389d9cc5ff6e13fade25 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 11 Apr 2025 06:38:46 +0500 Subject: [PATCH 0717/1190] qt: Update the Russian translation --- src/qt/languages/ru-RU.po | 74 +++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a8cd0295a..fb1908f60 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1252,19 +1252,19 @@ msgid "Pen" msgstr "Ручка" msgid "Host CD/DVD Drive (%1:)" -msgstr "Главный CD/DVD-привод (%1:)" +msgstr "CD/DVD-привод хоста (%1:)" msgid "&Connected" -msgstr "&Connected" +msgstr "&Кабель подключен" msgid "Clear image history" msgstr "Очистить историю образов" msgid "Create..." -msgstr "Создайте..." +msgstr "Создать..." msgid "Host CD/DVD Drive (%1)" -msgstr "Главный CD/DVD-привод (%1)" +msgstr "CD/DVD-привод хоста (%1)" msgid "Unknown Bus" msgstr "Неизвестная шина" @@ -1288,7 +1288,7 @@ msgid "VSync" msgstr "Вертикальная синхронизация" msgid "Synchronize with video" -msgstr "Синхронизация с видео" +msgstr "Синхронизировать с видео" msgid "Shaders" msgstr "Шейдеры" @@ -1384,25 +1384,25 @@ msgid "Renderer options..." msgstr "Параметры рендеринга..." msgid "Logitech/Microsoft Bus Mouse" -msgstr "Шинная мышь Logitech/Microsoft" +msgstr "Bus-мышь Logitech/Microsoft" msgid "Microsoft Bus Mouse (InPort)" -msgstr "Шинная мышь Microsoft (InPort)" +msgstr "Bus-мышь Microsoft (InPort)" msgid "Mouse Systems Serial Mouse" -msgstr "Последовательная мышь Mouse Systems" +msgstr "COM-мышь Mouse Systems" msgid "Microsoft Serial Mouse" -msgstr "Последовательная мышь Microsoft" +msgstr "COM-мышь Microsoft" msgid "Logitech Serial Mouse" -msgstr "Последовательная мышь Logitech" +msgstr "COM-мышь Logitech" msgid "PS/2 Mouse" msgstr "Мышь PS/2" msgid "3M MicroTouch (Serial)" -msgstr "3M MicroTouch (последовательная)" +msgstr "3M MicroTouch (последовательный)" msgid "[COM] Standard Hayes-compliant Modem" msgstr "[COM] Стандартный Hayes-совместимый модем" @@ -2062,25 +2062,25 @@ msgid "[Generic] RAM Disk (max. speed)" msgstr "[Стандартный] RAM-диск (макс. скорость)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Стандартный] 1989 (3500 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "Клон IBM 8514/A (ISA)" @@ -2107,61 +2107,61 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Перехватывать мультимедиа-клавиши" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Спрашивать подтверждения перед сохранением настроек" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Спрашивать подтверждения перед холодной перезагрузкой" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Спрашивать подтвержждения перед выходом" msgid "Display hotkey message when entering full-screen mode" -msgstr "" +msgstr "Показывать сообщение о горячих клавишах при включении полноэкранного режима" msgid "Options" -msgstr "" +msgstr "Параметры" msgid "Model:" msgstr "Модель:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Не удалось инициализировать рендерер Vulkan." msgid "GLSL Error" -msgstr "" +msgstr "Ошибка GLSL" msgid "Could not load shader: %1" -msgstr "" +msgstr "Не удалось загрузить шейдер: %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "Требуется OpenGL версии 3.0 или выше. Текущая версия GLSL %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "Не удалось загрузить текстуру: %1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "Не удалось скомпилировать шейдер:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "Не удалось скомпоновать шейдер:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "Управление шейдерами" msgid "Shader Configuration" -msgstr "" +msgstr "Конфигурация шейдера" msgid "Add" -msgstr "" +msgstr "Добавить" msgid "Move up" -msgstr "" +msgstr "Вверх" msgid "Move down" -msgstr "" +msgstr "Вниз" msgid "Could not load file %1" -msgstr "" +msgstr "Не удалось загрузить файл %1" From a0f0c42f4aec8d8ae2a4f427d54113b0a01ced7d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 12 Apr 2025 14:34:36 +0600 Subject: [PATCH 0718/1190] Microtouch touch points now work properly in fullscreen/maximized with scaling changes --- src/qt/qt_renderercommon.cpp | 3 ++ src/qt/qt_renderercommon.hpp | 2 + src/qt/qt_rendererstack.cpp | 85 ++++++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 3a34452e6..56217b611 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -132,6 +132,9 @@ RendererCommon::onResize(int width, int height) monitors[r_monitor_index].mon_res_x = (double) destination.width(); monitors[r_monitor_index].mon_res_y = (double) destination.height(); + + destinationF.setRect((double)destination.x() / (double)width, (double)destination.y() / (double)height, + (double)destination.width() / (double)width, (double)destination.height() / (double)height); } bool diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index 333b9df0a..6bfa51a8d 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ public: virtual bool rendererTakeScreenshot() { return false; } int r_monitor_index = 0; + QRectF destinationF = QRectF(0, 0, 1, 1); /* normalized to 0.0-1.0 range. */ protected: bool eventDelegate(QEvent *event, bool &result); diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index b5b910fe9..431b3609b 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -488,6 +488,17 @@ RendererStack::event(QEvent* event) mouse_y_abs = (mouse_event->localPos().y()) / (double)height(); if (!mouse_tablet_in_proximity) mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity; + mouse_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; } return QStackedWidget::event(event); } @@ -496,12 +507,34 @@ RendererStack::event(QEvent* event) if (mouse_input_mode == 0) { mouse_x_abs = (mouse_event->localPos().x()) / (double)width(); mouse_y_abs = (mouse_event->localPos().y()) / (double)height(); + mouse_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; return QStackedWidget::event(event); } #endif mouse_x_abs = (mouse_event->localPos().x()) / (double)width(); mouse_y_abs = (mouse_event->localPos().y()) / (double)height(); + mouse_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity; } else switch (event->type()) { case QEvent::TouchBegin: @@ -511,8 +544,19 @@ RendererStack::event(QEvent* event) 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_x_abs = (touchevent->touchPoints()[0].pos().x()) / (double)width(); + mouse_y_abs = (touchevent->touchPoints()[0].pos().y()) / (double)height(); + mouse_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; } mouse_set_buttons_ex(mouse_get_buttons_ex() | 1); touchevent->accept(); @@ -521,8 +565,19 @@ RendererStack::event(QEvent* event) 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_x_abs = (touchevent->point(0).position().x()) / (double)width(); + mouse_y_abs = (touchevent->point(0).position().y()) / (double)height(); + mouse_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; } mouse_set_buttons_ex(mouse_get_buttons_ex() | 1); touchevent->accept(); @@ -538,6 +593,17 @@ RendererStack::event(QEvent* event) 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_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; } mouse_set_buttons_ex(mouse_get_buttons_ex() & ~1); touchevent->accept(); @@ -548,6 +614,17 @@ RendererStack::event(QEvent* event) if (touchevent->pointCount()) { mouse_x_abs = (touchevent->point(0).position().x()) / (double)width(); mouse_y_abs = (touchevent->point(0).position().y()) / (double)height(); + mouse_x_abs -= rendererWindow->destinationF.left(); + mouse_y_abs -= rendererWindow->destinationF.top(); + + if (mouse_x_abs < 0) mouse_x_abs = 0; + if (mouse_y_abs < 0) mouse_y_abs = 0; + + mouse_x_abs /= rendererWindow->destinationF.width(); + mouse_y_abs /= rendererWindow->destinationF.height(); + + if (mouse_x_abs > 1) mouse_x_abs = 1; + if (mouse_y_abs > 1) mouse_y_abs = 1; } mouse_set_buttons_ex(mouse_get_buttons_ex() & ~1); touchevent->accept(); From 1f9f0a0d6e3703ff111395d8210e1001466debf4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 12 Apr 2025 14:54:35 +0200 Subject: [PATCH 0719/1190] NEAT: The chipset has its own A20 toggle, it cannot alter the external one as that's an input to the chipset, fixes #5332. --- src/chipset/neat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 1146ecbff..0661f89ee 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -956,8 +956,9 @@ neat_write(uint16_t port, uint8_t val, void *priv) dev->ems_size); } - mem_a20_key = !(val & RB12_GA20); + mem_a20_alt = !(val & RB12_GA20); mem_a20_recalc(); + flushmmucache(); break; default: @@ -987,7 +988,7 @@ neat_read(uint16_t port, void *priv) if ((dev->indx >= 0x60) && (dev->indx <= 0x6e)) ret = dev->regs[dev->indx]; else if (dev->indx == 0x6f) - ret = (dev->regs[dev->indx] & 0xfd) | (mem_a20_key & 2); + ret = (dev->regs[dev->indx] & 0xfd) | ~(mem_a20_alt & 0x02); break; default: From b91986499daabb9a96f1cdb9f986c135af2102e2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 12 Apr 2025 17:54:36 +0200 Subject: [PATCH 0720/1190] The forgotten keyboard.h. --- src/include/86box/keyboard.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 9142fbfe1..e495cb0df 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -245,6 +245,7 @@ extern const device_t keyboard_ps2_ps1_device; extern const device_t keyboard_ps2_ps1_pci_device; extern const device_t keyboard_ps2_xi8088_device; extern const device_t keyboard_ps2_ami_device; +extern const device_t keyboard_ps2_compaq_device; extern const device_t keyboard_ps2_holtek_device; extern const device_t keyboard_ps2_mca_1_device; extern const device_t keyboard_ps2_mca_2_device; @@ -258,6 +259,7 @@ extern const device_t keyboard_ps2_ami_pci_device; extern const device_t keyboard_ps2_intel_ami_pci_device; extern const device_t keyboard_ps2_acer_pci_device; extern const device_t keyboard_ps2_ali_pci_device; +extern const device_t keyboard_ps2_phoenix_pci_device; extern const device_t keyboard_ps2_tg_ami_pci_device; extern const device_t keyboard_at_generic_device; @@ -284,6 +286,7 @@ extern int keyboard_isfsexit_up(void); extern int keyboard_ismsexit(void); extern void keyboard_set_is_amstrad(int ams); extern void kbc_at_set_ps2(void *priv, uint8_t ps2); +extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t val); extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); extern void kbc_at_handler(int set, void *priv); From 08437a4d335530fc0b7c6e115b2a37cc40f4a099 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 13 Apr 2025 16:53:03 +0200 Subject: [PATCH 0721/1190] WD76C10: Implement the interleave modes complete with row and column calculation, fixes #5465. --- src/chipset/wd76c10.c | 425 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 404 insertions(+), 21 deletions(-) diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index a375c8eb6..48bb56483 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -65,9 +65,10 @@ wd76c10_log(const char *fmt, ...) #endif typedef struct { - uint32_t enable; + uint32_t phys_on, enable; uint32_t virt_addr, phys_addr; uint32_t virt_size, phys_size; + uint32_t adj_virt_addr, adj_virt_size; } ram_bank_t; typedef struct { @@ -103,6 +104,7 @@ typedef struct int locked; uint32_t mem_top, hmwp_base; + uint32_t fast; ram_bank_t ram_banks[5]; @@ -121,6 +123,40 @@ static uint32_t bank_sizes[4] = { 0x00020000, /* 64 Kbit X 16 = 1024 Kbit 0x00200000, /* 1 Mbit X 16 = 16 Mbit = 2 MB, 10x10 */ 0x00800000 }; /* 4 Mbit X 16 = 64 Mbit = 8 MB, 11x11 */ +static uint32_t +wd76c10_calc_phys(uint32_t row, uint32_t col, uint32_t size, uint32_t a0) +{ + uint32_t ret = WD76C10_ADDR_INVALID; + + switch (size) { + default: + ret = WD76C10_ADDR_INVALID; + break; + case 0x00020000: + row = (row & 0x0000ff) << 9; + col = (col & 0x0000ff) << 1; + ret = row | col | a0; + break; + case 0x00080000: + row = (row & 0x0001ff) << 10; + col = (col & 0x0001ff) << 1; + ret = row | col | a0; + break; + case 0x00200000: + row = (row & 0x0003ff) << 11; + col = (col & 0x0003ff) << 1; + ret = row | col | a0; + break; + case 0x00800000: + row = (row & 0x0007ff) << 12; + col = (col & 0x0007ff) << 1; + ret = row | col | a0; + break; + } + + return ret; +} + static uint32_t wd76c10_calc_addr(wd76c10_t *dev, uint32_t addr) { @@ -159,20 +195,303 @@ wd76c10_calc_addr(wd76c10_t *dev, uint32_t addr) ret = WD76C10_ADDR_INVALID; /* Then, handle the physical memory banks. */ + int ilv4 = (dev->mem_ctl >> 8) & 4; + int8_t add = 0; + uint32_t pg = (dev->mem_ctl & 0x0800); + uint32_t nrt = WD76C10_ADDR_INVALID; + + if (ret != WD76C10_ADDR_INVALID) { + if (dev->fast) for (int8_t i = 0; i < 4; i++) { + rb = &(dev->ram_banks[i]); + + uint32_t ret2 = ret - rb->phys_addr; + + if (rb->phys_on && (ret >= rb->phys_addr) && + (ret < (rb->phys_addr + rb->phys_size))) { + if (ret2 < rb->phys_size) + nrt = ret2 + rb->phys_addr; + break; + } + } else for (int8_t i = 0; i < 4; i++) { + rb = &(dev->ram_banks[i]); + + int ilv2 = (dev->mem_ctl >> 8) & (1 << (i >> 1)); + uint32_t size = rb->virt_size; + uint32_t ret2 = ret - rb->virt_addr; + uint32_t ret4 = ret2; + uint32_t row = WD76C10_ADDR_INVALID; + uint32_t col = WD76C10_ADDR_INVALID; + uint32_t rb_or = 0; + + if (ilv4) { + size <<= 2; + switch (rb->virt_size) { + default: + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00020000: + if (pg) { + row = (ret2 >> 9) & 0x0000fc; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 9) & 0x000003; + } else + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00080000: + if (pg) { + row = (ret2 >> 9) & 0x0000f8; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 21) & 0x000001) << 2; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 10) & 0x000003; + } else + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00200000: + if (pg) { + row = (ret2 >> 9) & 0x0000f0; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 21) & 0x000001) << 2; + row |= ((ret2 >> 23) & 0x000001) << 3; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 11) & 0x000003; + } else + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00800000: + if (pg) { + row = (ret2 >> 9) & 0x0000e0; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 21) & 0x000001) << 2; + row |= ((ret2 >> 23) & 0x000001) << 3; + row |= ((ret2 >> 24) & 0x000001) << 4; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 12) & 0x000003; + } else + ret4 = WD76C10_ADDR_INVALID; + break; + } + add = 3; + } else if (ilv2) { + size <<= 1; + switch (rb->virt_size) { + default: + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00020000: + if (pg) { + row = (ret2 >> 9) & 0x0000fe; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 9) & 0x000001; + } else { + row = (ret2 >> 1) & 0x0007fe; + row |= (ret2 >> 13) & 0x000001; + col = (ret2 >> 9) & 0x0000ef; + col |= ((ret2 >> 17) & 0x000001) << 4; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + rb_or = (ret2 >> 1) & 0x000001; + } + break; + case 0x00080000: + if (pg) { + row = (ret2 >> 9) & 0x0000fc; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 10) & 0x000001; + } else { + row = (ret2 >> 1) & 0x0007fe; + row |= (ret2 >> 13) & 0x000001; + col = (ret2 >> 9) & 0x0000ee; + col |= (ret2 >> 17) & 0x000001; + col |= ((ret2 >> 19) & 0x000001) << 4; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + rb_or = (ret2 >> 1) & 0x000001; + } + break; + case 0x00200000: + if (pg) { + row = (ret2 >> 9) & 0x0000f8; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 21) & 0x000001) << 2; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 11) & 0x000001; + } else { + row = (ret2 >> 1) & 0x0007fe; + row |= (ret2 >> 13) & 0x000001; + col = (ret2 >> 9) & 0x0000ec; + col |= (ret2 >> 17) & 0x000001; + col |= ((ret2 >> 19) & 0x000001) << 1; + col |= ((ret2 >> 21) & 0x000001) << 4; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + rb_or = (ret2 >> 1) & 0x000001; + } + break; + case 0x00800000: + if (pg) { + row = (ret2 >> 9) & 0x0000f0; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 21) & 0x000001) << 2; + row |= ((ret2 >> 23) & 0x000001) << 3; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x000007ff; + rb_or = (ret2 >> 12) & 0x000001; + } else { + row = (ret2 >> 1) & 0x0007fe; + row |= (ret2 >> 13) & 0x000001; + col = (ret2 >> 9) & 0x0000e0; + col |= (ret2 >> 17) & 0x000001; + col |= ((ret2 >> 19) & 0x000001) << 1; + col |= ((ret2 >> 21) & 0x000001) << 2; + col |= ((ret2 >> 23) & 0x000001) << 3; + col |= ((ret2 >> 12) & 0x000001) << 4; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + rb_or = (ret2 >> 1) & 0x000001; + } + break; + } + add = 1; + } else if (pg) switch (rb->virt_size) { + default: + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00020000: + row = (ret2 >> 9) & 0x0000ff; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x0007ff; + break; + case 0x00080000: + row = (ret2 >> 9) & 0x0000fe; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x0007ff; + break; + case 0x00200000: + row = (ret2 >> 9) & 0x0000fc; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x0007ff; + break; + case 0x00800000: + row = (ret2 >> 9) & 0x0000f8; + row |= (ret2 >> 17) & 0x000001; + row |= ((ret2 >> 19) & 0x000001) << 1; + row |= ((ret2 >> 21) & 0x000001) << 2; + row |= ((ret2 >> 18) & 0x000001) << 8; + row |= ((ret2 >> 20) & 0x000001) << 9; + row |= ((ret2 >> 22) & 0x000001) << 10; + col = (ret2 >> 1) & 0x0007ff; + break; + } else switch (rb->virt_size) { + default: + ret4 = WD76C10_ADDR_INVALID; + break; + case 0x00020000: + row = (ret2 >> 1) & 0x0007ff; + col = (ret2 >> 9) & 0x0000ff; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + break; + case 0x00080000: + row = (ret2 >> 1) & 0x0007ff; + col = (ret2 >> 9) & 0x0000fe; + col |= (ret2 >> 17) & 0x000001; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + break; + case 0x00200000: + row = (ret2 >> 1) & 0x0007ff; + col = (ret2 >> 9) & 0x0000fc; + col |= (ret2 >> 17) & 0x000001; + col |= ((ret2 >> 19) & 0x000001) << 1; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + break; + case 0x00800000: + row = (ret2 >> 1) & 0x0007ff; + col = (ret2 >> 9) & 0x0000f8; + col |= (ret2 >> 17) & 0x000001; + col |= ((ret2 >> 19) & 0x000001) << 1; + col |= ((ret2 >> 21) & 0x000001) << 2; + col |= ((ret2 >> 18) & 0x000001) << 8; + col |= ((ret2 >> 20) & 0x000001) << 9; + col |= ((ret2 >> 22) & 0x000001) << 10; + break; + } + + if (row != WD76C10_ADDR_INVALID) { + ret4 = wd76c10_calc_phys(row & 0x0007ff, col & 0x0007ff, + rb->phys_size, ret2 & 0x000001); + + if (ilv4 || ilv2) + rb = &(dev->ram_banks[i | rb_or]); + + i += add; + } + + if (rb->enable && (ret >= rb->virt_addr) && + (ret < (rb->virt_addr + size))) { + if ((ret4 != WD76C10_ADDR_INVALID) && (rb->phys_size > 0x00000000)) + nrt = ret4 + rb->phys_addr; + break; + } + } + + ret = nrt; + } + if (ret >= (mem_size << 10)) /* The physical memory address is too high or disabled, which is invalid. */ ret = WD76C10_ADDR_INVALID; - /* Otherwise, map it to the correct bank so the BIOS can auto-size it correctly. */ - else for (uint8_t i = 0; i < 4; i++) { - rb = &(dev->ram_banks[i]); - if (rb->enable && (ret >= rb->virt_addr) && (ret < (rb->virt_addr + rb->virt_size))) { - if (rb->phys_size == 0x00000000) - ret = WD76C10_ADDR_INVALID; - else - ret = ((ret - rb->virt_addr) % rb->phys_size) + rb->phys_addr; - break; - } - } return ret; } @@ -185,8 +504,12 @@ wd76c10_read_ram(uint32_t addr, void *priv) addr = wd76c10_calc_addr(dev, addr); - if (addr != WD76C10_ADDR_INVALID) - ret = mem_read_ram(addr, priv); + if (addr != WD76C10_ADDR_INVALID) { + if (dev->fast) + ret = mem_read_ram(addr, priv); + else + ret = ram[addr]; + } return ret; } @@ -199,8 +522,12 @@ wd76c10_read_ramw(uint32_t addr, void *priv) addr = wd76c10_calc_addr(dev, addr); - if (addr != WD76C10_ADDR_INVALID) - ret = mem_read_ramw(addr, priv); + if (addr != WD76C10_ADDR_INVALID) { + if (dev->fast) + ret = mem_read_ramw(addr, priv); + else + ret = *(uint16_t *) &(ram[addr]); + } return ret; } @@ -212,8 +539,12 @@ wd76c10_write_ram(uint32_t addr, uint8_t val, void *priv) addr = wd76c10_calc_addr(dev, addr); - if (addr != WD76C10_ADDR_INVALID) - mem_write_ram(addr, val, priv); + if (addr != WD76C10_ADDR_INVALID) { + if (dev->fast) + mem_write_ram(addr, val, priv); + else + ram[addr] = val; + } } static void @@ -223,8 +554,12 @@ wd76c10_write_ramw(uint32_t addr, uint16_t val, void *priv) addr = wd76c10_calc_addr(dev, addr); - if (addr != WD76C10_ADDR_INVALID) - mem_write_ramw(addr, val, priv); + if (addr != WD76C10_ADDR_INVALID) { + if (dev->fast) + mem_write_ramw(addr, val, priv); + else + *(uint16_t *) &(ram[addr]) = val; + } } static void @@ -258,6 +593,9 @@ wd76c10_recalc_exec(wd76c10_t *dev, uint32_t base, uint32_t size) static void wd76c10_banks_recalc(wd76c10_t *dev) { + int match = 0; + dev->fast = 0; + for (uint8_t i = 0; i < 4; i++) { ram_bank_t *rb = &(dev->ram_banks[i]); uint8_t bit = i << 1; @@ -266,8 +604,42 @@ wd76c10_banks_recalc(wd76c10_t *dev) rb->enable = (dev->split_sa >> bit) & 0x01; rb->virt_addr = ((uint32_t) dev->bank_bases[i]) << 17; + if (rb->enable) { + rb->adj_virt_addr = rb->virt_addr; + rb->adj_virt_size = rb->virt_size; + + if (dev->mem_ctl & 0x0400) + rb->adj_virt_addr += (i * rb->adj_virt_size); + else if ((dev->mem_ctl >> 8) & (1 << (i >> 1))) + rb->adj_virt_addr += ((i & 1) * rb->adj_virt_size); + } else { + rb->adj_virt_addr = WD76C10_ADDR_INVALID; + rb->adj_virt_size = 0x00000000; + } + + if ((rb->enable == rb->phys_on) && + (rb->adj_virt_addr == rb->phys_addr) && + (rb->adj_virt_size == rb->phys_size)) + match++; + } + + dev->fast = (match == 4); + + for (uint8_t i = 0; i < 4; i++) { + ram_bank_t *rb = &(dev->ram_banks[i]); + if (cpu_use_exec) wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size); + + wd76c10_log("Bank %i (%s), physical: %i, %08X-%08X, " + "virtual: %i, %08X-%08X, adj.: %i, %08X-%08X\n", + i, dev->fast ? "FAST" : "SLOW", + rb->phys_on, + rb->phys_addr, rb->phys_addr + rb->phys_size - 1, + rb->enable, + rb->virt_addr, rb->virt_addr + rb->virt_size - 1, + rb->enable, + rb->adj_virt_addr, rb->adj_virt_addr + rb->adj_virt_size - 1); } } @@ -899,11 +1271,22 @@ wd76c10_init(UNUSED(const device_t *info)) } } if (size != 0x00000000) { + rb->phys_on = 1; rb->phys_addr = accum_mem; rb->phys_size = size; + wd76c10_log("Bank %i size: %5i KiB, starting at %5i KiB\n", i, rb->phys_size >> 10, rb->phys_addr >> 10); total_mem -= size; accum_mem += size; - } + } else + rb->phys_addr = WD76C10_ADDR_INVALID; + } + + if (mem_size == 3072) { + /* Reorganize the banks a bit so, we have 2048, 0, 512, 512. */ + ram_bank_t rt = dev->ram_banks[3]; + dev->ram_banks[3] = dev->ram_banks[2]; + dev->ram_banks[2] = dev->ram_banks[1]; + dev->ram_banks[1] = rt; } rb = &(dev->ram_banks[4]); From d07038961fa6e428f58493660484d0d3e0849907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:15:42 +0200 Subject: [PATCH 0722/1190] Add win11arm job --- .github/workflows/cmake_windows_msys2.yml | 35 +++++++---------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index abe25b949..495937b10 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -18,7 +18,6 @@ on: - cmake/** - "**/CMakeLists.txt" - "CMakePresets.json" - - .github/workflows/** - .github/workflows/cmake_windows_msys2.yml - vcpkg.json - "!**/Makefile*" @@ -26,9 +25,9 @@ on: jobs: msys2: - name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}" + name: "${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}" - runs-on: windows-2022 + runs-on: ${{ matrix.environment.runner }} env: BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed @@ -41,8 +40,6 @@ jobs: fail-fast: true matrix: build: -# - name: Regular -# preset: regular - name: Debug preset: dev_debug slug: -Debug @@ -56,26 +53,15 @@ jobs: - name: NDR new: on slug: -NDR - ui: - - name: Qt GUI - qt: on - static: on - slug: -Qt - packages: >- - qt5-static:p - vulkan-headers:p environment: -# - msystem: MSYS -# toolchain: ./cmake/flags-gcc-x86_64.cmake - msystem: MINGW64 - prefix: mingw-w64-x86_64 toolchain: ./cmake/flags-gcc-x86_64.cmake -# - msystem: CLANG64 -# prefix: mingw-w64-clang-x86_64 -# toolchain: ./cmake/llvm-win32-x86_64.cmake -# - msystem: UCRT64 -# prefix: mingw-w64-ucrt-x86_64 -# toolchain: ./cmake/flags-gcc-x86_64.cmake + slug: -x64 + runner: windows-2022 + - msystem: CLANGARM64 + toolchain: ./cmake/flags-gcc-aarch64.cmake + slug: -ARM64 + runner: windows-11-arm steps: - name: Prepare MSYS2 environment @@ -98,7 +84,8 @@ jobs: libslirp:p fluidsynth:p libserialport:p - ${{ matrix.ui.packages }} + qt5-static:p + vulkan-headers:p - name: Checkout repository uses: actions/checkout@v4 @@ -114,8 +101,6 @@ jobs: --toolchain ${{ matrix.environment.toolchain }} -D NEW_DYNAREC=${{ matrix.dynarec.new }} -D CMAKE_INSTALL_PREFIX=./build/artifacts - -D QT=${{ matrix.ui.qt }} - -D STATIC_BUILD=${{ matrix.ui.static }} - name: Build run: | From 775c7bd3d61c356d74fa51b7dd865fd77559a861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:26:14 +0200 Subject: [PATCH 0723/1190] Try to fix the job --- .github/workflows/cmake_windows_msys2.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 495937b10..f3262c4d5 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -40,11 +40,10 @@ jobs: fail-fast: true matrix: build: - - name: Debug - preset: dev_debug - slug: -Debug + - name: Regular + preset: regular - name: Dev - preset: development + preset: dev_debug slug: -Dev dynarec: - name: ODR @@ -60,14 +59,19 @@ jobs: runner: windows-2022 - msystem: CLANGARM64 toolchain: ./cmake/flags-gcc-aarch64.cmake - slug: -ARM64 + slug: -arm64 runner: windows-11-arm + exclude: + - dynarec: + new: off + environment: + msystem: CLANGARM64 steps: - name: Prepare MSYS2 environment uses: msys2/setup-msys2@v2 with: - release: false + release: true update: true msystem: ${{ matrix.environment.msystem }} pacboy: >- From 1080389bfd403b561935b8fe8ae43bd99f680f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:35:48 +0200 Subject: [PATCH 0724/1190] Fix number 2 --- .github/workflows/cmake_windows_msys2.yml | 26 ++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index f3262c4d5..b2bb9b3a6 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -96,8 +96,8 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Install sonar-scanner and build-wrapper - uses: SonarSource/sonarcloud-github-c-cpp@v3 + # - name: Install sonar-scanner and build-wrapper + # uses: SonarSource/sonarcloud-github-c-cpp@v3 - name: Configure CMake run: >- @@ -106,17 +106,19 @@ jobs: -D NEW_DYNAREC=${{ matrix.dynarec.new }} -D CMAKE_INSTALL_PREFIX=./build/artifacts - - name: Build - run: | - .sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build + # - name: Build + # run: | + # .sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build - - name: Run sonar-scanner - if: 0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: | - .sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" + - name: Build + run: cmake --build build + + # - name: Run sonar-scanner + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + # run: | + # .sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" - name: Generate package run: cmake --install build From 52458f78439c255886b8e54de95beb9d0c7e4770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:43:11 +0200 Subject: [PATCH 0725/1190] Fix number 3 --- .github/workflows/cmake_windows_msys2.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index b2bb9b3a6..f94853279 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -90,6 +90,7 @@ jobs: libserialport:p qt5-static:p vulkan-headers:p + openmp:p - name: Checkout repository uses: actions/checkout@v4 From fe9f6a7f1daafa8cf7747f4270bb6af8baf1bef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:54:21 +0200 Subject: [PATCH 0726/1190] Artifact names in line with Jenkins --- .github/workflows/cmake_windows_msys2.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index f94853279..d9cd37d0d 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -48,14 +48,13 @@ jobs: dynarec: - name: ODR new: off - slug: -ODR - name: NDR new: on slug: -NDR environment: - msystem: MINGW64 toolchain: ./cmake/flags-gcc-x86_64.cmake - slug: -x64 + slug: "-64" runner: windows-2022 - msystem: CLANGARM64 toolchain: ./cmake/flags-gcc-aarch64.cmake @@ -127,5 +126,5 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}' + name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}${{ matrix.environment.slug }}-gha${{ github.run_number }}' path: build/artifacts/** From 1b61f58bf00ce333c7baf4d6235b1cfd0816f486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:55:11 +0200 Subject: [PATCH 0727/1190] Fix --- .github/workflows/cmake_windows_msys2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index d9cd37d0d..44d982e16 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -126,5 +126,5 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}${{ matrix.environment.slug }}-gha${{ github.run_number }}' + name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows${{ matrix.environment.slug }}-gha${{ github.run_number }}' path: build/artifacts/** From e4d7911f857695cd956280b9050173d14d03c5ab Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 15 Apr 2025 14:06:02 -0300 Subject: [PATCH 0728/1190] Fix Conner name in one model preset --- src/disk/hdd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 8a02173ce..e051cc841 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -469,7 +469,7 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "AC22100", .model = "WDC AC22100H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "AC31200", .model = "WDC AC31200F", .zones = 8, .avg_spt = 210, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, - { .name = "[ATA-3] Connor CFS1275A", .internal_name = "CFS1275A", .model = "Connor Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, // Either ATA-2 or ATA-3 + { .name = "[ATA-3] Conner CFS1275A", .internal_name = "CFS1275A", .model = "Conner Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, // Either ATA-2 or ATA-3 { .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 195, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 195, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 195, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, From 9b54021061a09ebf5588425279f95d2428faefb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:10:18 +0200 Subject: [PATCH 0729/1190] Use debug instead of release --- .github/workflows/cmake_windows_msys2.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 44d982e16..9dda6a695 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -40,8 +40,9 @@ jobs: fail-fast: true matrix: build: - - name: Regular - preset: regular + - name: Debug + preset: debug + slug: -Debug - name: Dev preset: dev_debug slug: -Dev From 90134095b95b36f9635d036bb8aababcb784256a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:16:59 +0200 Subject: [PATCH 0730/1190] Fix the presets once again --- .github/workflows/cmake_windows_msys2.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 9dda6a695..98aae1883 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -40,11 +40,11 @@ jobs: fail-fast: true matrix: build: - - name: Debug + - name: Dev Debug preset: debug - slug: -Debug + slug: -Dev-Debug - name: Dev - preset: dev_debug + preset: development slug: -Dev dynarec: - name: ODR From bb0b8f254de968e9b0de8918467dea741f83a7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:19:39 +0200 Subject: [PATCH 0731/1190] ... --- .github/workflows/cmake_windows_msys2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 98aae1883..ca48599a0 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -41,7 +41,7 @@ jobs: matrix: build: - name: Dev Debug - preset: debug + preset: dev_debug slug: -Dev-Debug - name: Dev preset: development From 245619674d160e092bd0d54ed50a5edb06294094 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 15 Apr 2025 22:05:11 +0200 Subject: [PATCH 0732/1190] PAS16/Plus change of the day (April 15th, 2025) Actually make the DMA transfer speed normal in when in 16-bit stereo mode with System Configuration 1 bit 1 (Master Clock) cleared. Fixes audio being too quick with said configuration. --- src/sound/snd_pas16.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index dd95eac4c..cfefc8df5 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -1756,7 +1756,7 @@ static uint16_t pas16_readdmaw_stereo(pas16_t *pas16) { uint16_t ret; - uint16_t ticks = (pas16->sys_conf_1 & 0x02) ? (1 + (pas16->dma < 5)) : 2; + uint16_t ticks = (pas16->sys_conf_1 & 0x02) ? (1 + (pas16->dma < 5)) : 1; ret = pas16_dma_readw(pas16, ticks); From 2c3fc6ec1ad25ea206c3f96822487645f4f3844b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 16 Apr 2025 22:09:27 +0200 Subject: [PATCH 0733/1190] Bump version to 5.0. --- CMakeLists.txt | 2 +- debian/changelog | 4 ++-- src/unix/assets/86Box.spec | 4 ++-- src/unix/assets/net.86box.86Box.metainfo.xml | 2 +- vcpkg.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a94321038..007c1ffd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 4.3 + VERSION 5.0 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) diff --git a/debian/changelog b/debian/changelog index 5665ff968..079fba5dd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (4.3) UNRELEASED; urgency=medium +86box (5.0) UNRELEASED; urgency=medium * Bump release. - -- Jasmine Iwanek Wed, 13 Nov 2024 06:31:46 +0100 + -- Jasmine Iwanek Wed, 16 Apr 2025 22:08:04 +0200 diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index 86f380d22..bb9b85b12 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -15,7 +15,7 @@ %global romver 4.1 Name: 86Box -Version: 4.3 +Version: 5.0 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -121,5 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Sat Aug 31 Jasmine Iwanek 4.3-1 +* Sat Aug 31 Jasmine Iwanek 5.0-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index 6618f21d2..4c6a795a7 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -11,7 +11,7 @@ net.86box.86Box.desktop - + diff --git a/vcpkg.json b/vcpkg.json index 87859869b..20b783add 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "4.3", + "version-string": "5.0", "homepage": "https://86box.net/", "documentation": "https://86box.readthedocs.io/", "license": "GPL-2.0-or-later", From 90265546e6bb75ac5e4dac25925458e5198e6cd4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 17 Apr 2025 00:18:38 +0200 Subject: [PATCH 0734/1190] CD-ROM: Do not stop playing on a READ command that immediately terminates with an "illegal mode for this track" error, fixes track skipping in the Windows 95 CD Player. --- src/cdrom/cdrom.c | 89 +++++++++++++++++++++++++++------------ src/include/86box/cdrom.h | 2 + src/scsi/scsi_cdrom.c | 17 ++++++++ 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index b30d93812..644a8e245 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2274,6 +2274,65 @@ cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, return ret; } +static uint32_t +cdrom_msf_to_lba(const int sector, const int ismsf, + int cdrom_sector_type, const uint8_t vendor_type) +{ + int pos = sector; + uint32_t lba; + + if ((cdrom_sector_type & 0x0f) >= 0x08) { + mult = cdrom_sector_type >> 4; + pos /= mult; + } + + if (ismsf) { + const int m = (pos >> 16) & 0xff; + const int s = (pos >> 8) & 0xff; + const int f = pos & 0xff; + + lba = MSFtoLBA(m, s, f) - 150; + } else { + switch (vendor_type) { + case 0x00: + lba = pos; + break; + case 0x40: { + const int m = bcd2bin((pos >> 24) & 0xff); + const int s = bcd2bin((pos >> 16) & 0xff); + const int f = bcd2bin((pos >> 8) & 0xff); + + lba = MSFtoLBA(m, s, f) - 150; + break; + } case 0x80: + lba = bcd2bin((pos >> 24) & 0xff); + break; + /* Never used values but the compiler complains. */ + default: + lba = 0; + } + } + + return lba; +} + +int +cdrom_is_track_audio(cdrom_t *dev, const int sector, + const int ismsf, int cdrom_sector_type, + const uint8_t vendor_type) +{ + int audio = 0; + uint32_t lba = cdrom_msf_to_lba(sector, ismsf, + cdrom_sector_type, vendor_type); + + if (dev->ops->get_track_type) + audio = dev->ops->get_track_type(dev->local, lba); + + audio &= CD_TRACK_AUDIO; + + return audio; +} + int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, int cdrom_sector_type, const int cdrom_sector_flags, @@ -2298,38 +2357,12 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int uint8_t *temp_b; uint8_t *b = temp_b = buffer; int audio = 0; - uint32_t lba; + uint32_t lba = cdrom_msf_to_lba(sector, ismsf, + cdrom_sector_type, vendor_type); int mode2 = 0; *len = 0; - if (ismsf) { - const int m = (pos >> 16) & 0xff; - const int s = (pos >> 8) & 0xff; - const int f = pos & 0xff; - - lba = MSFtoLBA(m, s, f) - 150; - } else { - switch (vendor_type) { - case 0x00: - lba = pos; - break; - case 0x40: { - const int m = bcd2bin((pos >> 24) & 0xff); - const int s = bcd2bin((pos >> 16) & 0xff); - const int f = bcd2bin((pos >> 8) & 0xff); - - lba = MSFtoLBA(m, s, f) - 150; - break; - } case 0x80: - lba = bcd2bin((pos >> 24) & 0xff); - break; - /* Never used values but the compiler complains. */ - default: - lba = 0; - } - } - if (dev->ops->get_track_type) audio = dev->ops->get_track_type(dev->local, lba); diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 30c6476fb..5ff4170a2 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -425,6 +425,8 @@ extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint #endif extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, const uint8_t track, const int type); +extern int cdrom_is_track_audio(cdrom_t *dev, const int sector, const int ismsf, + int cdrom_sector_type, const uint8_t vendor_type); extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf, int cdrom_sector_type, const int cdrom_sector_flags, int *len, const uint8_t vendor_type); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 246f185e8..95c8c3640 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -2610,6 +2610,11 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->sector_len = 256; dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + if (cdrom_is_track_audio(dev->drv, dev->sector_pos, msf, + dev->sector_type, 0x00)) { + scsi_cdrom_illegal_mode(dev); + ret = 0; + } scsi_cdrom_log(dev->log, "READ (6): Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; @@ -2617,6 +2622,12 @@ scsi_cdrom_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 (cdrom_is_track_audio(dev->drv, dev->sector_pos, msf, + dev->sector_type, dev->use_cdb_9 ? + (cdb[9] & 0xc0) : 0x00)) { + scsi_cdrom_illegal_mode(dev); + ret = 0; + } scsi_cdrom_log(dev->log, "READ (10): Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; @@ -2627,6 +2638,12 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + if (cdrom_is_track_audio(dev->drv, dev->sector_pos, msf, + dev->sector_type, dev->use_cdb_9 ? + (cdb[9] & 0xc0) : 0x00)) { + scsi_cdrom_illegal_mode(dev); + ret = 0; + } scsi_cdrom_log(dev->log, "READ (12): Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); break; From 18aea4e19f2abe96ce40d84b07da2464dfc3e151 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 17 Apr 2025 00:30:12 +0200 Subject: [PATCH 0735/1190] CD-ROM: Fix a newly introduced accidental division by zero. --- src/cdrom/cdrom.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 644a8e245..0f468bba0 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2338,8 +2338,9 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int int cdrom_sector_type, const int cdrom_sector_flags, int *len, const uint8_t vendor_type) { - int pos = sector; - int ret = 0; + int pos = sector; + int ret = 0; + const int old_type = cdrom_sector_type; if ((cdrom_sector_type & 0x0f) >= 0x08) { mult = cdrom_sector_type >> 4; @@ -2358,7 +2359,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int uint8_t *b = temp_b = buffer; int audio = 0; uint32_t lba = cdrom_msf_to_lba(sector, ismsf, - cdrom_sector_type, vendor_type); + old_type, vendor_type); int mode2 = 0; *len = 0; From 37ed6662dc2c45cf8099b3170768c1ff7a103c30 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 17 Apr 2025 01:10:04 +0200 Subject: [PATCH 0736/1190] Serial mouse: do not attempt to transmit a byte if none is queued, fixes #5475. --- src/device/mouse_serial.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 96d3a867c..b50a3c987 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -146,7 +146,11 @@ sermouse_transmit_byte(mouse_t *dev, int do_next) serial_write_fifo(dev->serial, dev->buf[dev->buf_pos]); if (do_next) { - dev->buf_pos = (dev->buf_pos + 1) % dev->buf_len; + /* If we have a buffer length of 0, pretend the state is STATE_SKIP_PACKET. */ + if (dev->buf_len == 0) + dev->buf_pos = 0; + else + dev->buf_pos = (dev->buf_pos + 1) % dev->buf_len; if (dev->buf_pos != 0) sermouse_set_period(dev, dev->transmit_period); @@ -374,6 +378,7 @@ sermouse_report(mouse_t *dev) break; default: + pclog("unknown dev->format = %02X\n", dev->format); break; } @@ -747,7 +752,7 @@ sermouse_timer(void *priv) if (!dev->prompt && !dev->continuous) sermouse_transmit_report(dev, (dev->state == STATE_TRANSMIT_REPORT)); else - dev->state = STATE_IDLE; + dev->state = STATE_IDLE; break; case STATE_TRANSMIT_REPORT: case STATE_TRANSMIT: From 6ab7f61c744611fa62284e2792698c8b51d1d499 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 17 Apr 2025 01:12:39 +0200 Subject: [PATCH 0737/1190] Serial mouse: Remove the excess logging line. --- src/device/mouse_serial.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index b50a3c987..8ed4865cd 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -378,7 +378,6 @@ sermouse_report(mouse_t *dev) break; default: - pclog("unknown dev->format = %02X\n", dev->format); break; } From 629d976f8ea85e08b6049bbd2f4a492ee4f00106 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 17 Apr 2025 13:31:28 +0600 Subject: [PATCH 0738/1190] Disable OpenGL 3.x logs --- src/qt/qt_openglrenderer.cpp | 48 +++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 2e8869c09..53d29f9a8 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -145,6 +145,24 @@ const char* fragment_shader_default_color_src = " outColor.a = 1.0;\n" "}\n"; +#ifdef ENABLE_OGL3_LOG +int ogl3_do_log = ENABLE_OGL3_LOG; + +static void +ogl3_log(const char *fmt, ...) +{ + va_list ap; + + if (ogl3_do_log) { + va_start(ap, fmt); + ogl3_log_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ogl3_log(fmt, ...) +#endif + static inline int next_pow2(unsigned int n) { @@ -232,8 +250,8 @@ OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const ch main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not compile shader:\n\n%1").arg(log).replace("\n", "
    ")); // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); - pclog("Could not compile shader: %s\n", log); - // pclog("Shader: %s\n", program); + ogl3_log("Could not compile shader: %s\n", log); + // ogl3_log("Shader: %s\n", program); free(log); return 0; @@ -348,7 +366,7 @@ OpenGLRenderer::create_texture(struct shader_texture *tex) tex->width = max_texture_size; if (tex->height > max_texture_size) tex->height = max_texture_size; - pclog("Create texture with size %dx%d\n", tex->width, tex->height); + ogl3_log("Create texture with size %dx%d\n", tex->width, tex->height); glw.glGenTextures(1, (GLuint *) &tex->id); glw.glBindTexture(GL_TEXTURE_2D, tex->id); glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex->wrap_mode); @@ -452,7 +470,7 @@ OpenGLRenderer::create_fbo(struct shader_fbo *fbo) glw.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->texture.id, 0); if (glw.glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - pclog("Could not create framebuffer!\n"); + ogl3_log("Could not create framebuffer!\n"); glw.glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -629,12 +647,12 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) struct shader_lut_texture *tex = &gshader->lut_textures[i]; strcpy(tex->name, texture->name); - pclog("Load texture %s...\n", file); + ogl3_log("Load texture %s...\n", file); if (!load_texture(file, &tex->texture)) { //QMessageBox::critical(main_window, tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load texture: %1").arg(file)); - pclog("Could not load texture %s!\n", file); + ogl3_log("Could not load texture %s!\n", file); failed = 1; break; } @@ -676,16 +694,16 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) if (!strlen(pass->alias)) sprintf(pass->alias, "Pass %u", (i + 1)); - pclog("Creating pass %u (%s)\n", (i + 1), pass->alias); - pclog("Loading shader %s...\n", shader->shader_fn); + ogl3_log("Creating pass %u (%s)\n", (i + 1), pass->alias); + ogl3_log("Loading shader %s...\n", shader->shader_fn); if (!shader->shader_program) { main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); - pclog("Could not load shader %s\n", shader->shader_fn); + ogl3_log("Could not load shader %s\n", shader->shader_fn); failed = 1; break; } else - pclog("Shader %s loaded\n", shader->shader_fn); + ogl3_log("Shader %s loaded\n", shader->shader_fn); failed = !compile_shader(GL_VERTEX_SHADER, "#define VERTEX\n#define PARAMETER_UNIFORM\n", shader->shader_program, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, "#define FRAGMENT\n#define PARAMETER_UNIFORM\n", @@ -856,15 +874,15 @@ OpenGLRenderer::initialize() glw.initializeOpenGLFunctions(); - pclog("OpenGL information: [%s] %s (%s)\n", glw.glGetString(GL_VENDOR), glw.glGetString(GL_RENDERER), glw.glGetString(GL_VERSION)); + ogl3_log("OpenGL information: [%s] %s (%s)\n", glw.glGetString(GL_VENDOR), glw.glGetString(GL_RENDERER), glw.glGetString(GL_VERSION)); glsl_version[0] = glsl_version[1] = -1; glw.glGetIntegerv(GL_MAJOR_VERSION, &glsl_version[0]); glw.glGetIntegerv(GL_MINOR_VERSION, &glsl_version[1]); if (glsl_version[0] < 3) { throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2").arg(glsl_version[0]).arg(glsl_version[1])); } - pclog("Using OpenGL %s\n", glw.glGetString(GL_VERSION)); - pclog("Using Shading Language %s\n", glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); + ogl3_log("Using OpenGL %s\n", glw.glGetString(GL_VERSION)); + ogl3_log("Using Shading Language %s\n", glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); glslVersion = reinterpret_cast(glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); glslVersion.truncate(4); @@ -876,7 +894,7 @@ OpenGLRenderer::initialize() glslVersion.append(" core"); glw.glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); - pclog("Max texture size: %dx%d\n", max_texture_size, max_texture_size); + ogl3_log("Max texture size: %dx%d\n", max_texture_size, max_texture_size); glw.glEnable(GL_TEXTURE_2D); @@ -1218,7 +1236,7 @@ OpenGLRenderer::render_pass(struct render_data *data) int i; GLuint texture_unit = 0; - // pclog("pass %d: %gx%g, %gx%g -> %gx%g, %gx%g, %gx%g\n", num_pass, pass->state.input_size[0], + // ogl3_log("pass %d: %gx%g, %gx%g -> %gx%g, %gx%g, %gx%g\n", num_pass, pass->state.input_size[0], // pass->state.input_size[1], pass->state.input_texture_size[0], pass->state.input_texture_size[1], // pass->state.output_size[0], pass->state.output_size[1], pass->state.output_texture_size[0], // pass->state.output_texture_size[1], output_size[0], output_size[1]); From 05f4906eb30c11745e30bf563883594084ad835c Mon Sep 17 00:00:00 2001 From: GH Cao Date: Fri, 18 Apr 2025 00:36:04 +0800 Subject: [PATCH 0739/1190] win_dynld: use LoadLibraryA specifically --- src/qt/win_dynld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/win_dynld.c b/src/qt/win_dynld.c index 88fb632bc..e4d9d5a13 100644 --- a/src/qt/win_dynld.c +++ b/src/qt/win_dynld.c @@ -51,7 +51,7 @@ dynld_module(const char *name, dllimp_t *table) void *func; /* See if we can load the desired module. */ - if ((h = LoadLibrary(name)) == NULL) { + if ((h = LoadLibraryA(name)) == NULL) { dynld_log("DynLd(\"%s\"): library not found! (%08X)\n", name, GetLastError()); return (NULL); } From 46978a808c7e0309ca4a88f0028669d49eb177a7 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 16 Apr 2025 19:56:48 +0500 Subject: [PATCH 0740/1190] Disable rich text for `ui_msgbox()`-generated dialogs No strings that gets passed to `ui_msgbox()` use HTML, and it causes newlines to be ignored unless replaced by
    `MainWindow::showMessage()` can still accept rich text, but it's now optional and disabled by default --- src/network/network.c | 2 +- src/qt/qt_mainwindow.cpp | 13 +++++++------ src/qt/qt_mainwindow.hpp | 6 +++--- src/qt/qt_openglrenderer.cpp | 10 +++++----- src/qt/qt_ui.cpp | 3 +-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/network/network.c b/src/network/network.c index 047642085..52b686c7e 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -501,7 +501,7 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin if(net_cards_conf[net_card_current].net_type != NET_TYPE_NONE) { // We're here because of a failure - swprintf(tempmsg, sizeof_w(tempmsg), L"%ls:

    %s

    %ls", plat_get_string(STRING_NET_ERROR), net_drv_error, plat_get_string(STRING_NET_ERROR_DESC)); + swprintf(tempmsg, sizeof_w(tempmsg), L"%ls:\n\n%s\n\n%ls", plat_get_string(STRING_NET_ERROR), net_drv_error, plat_get_string(STRING_NET_ERROR_DESC)); ui_msgbox(MBX_ERROR, tempmsg); net_cards_conf[net_card_current].net_type = NET_TYPE_NONE; } diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 886f84dcd..760ca7d9b 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1342,17 +1342,17 @@ MainWindow::refreshMediaMenu() } void -MainWindow::showMessage(int flags, const QString &header, const QString &message) +MainWindow::showMessage(int flags, const QString &header, const QString &message, bool richText) { if (QThread::currentThread() == this->thread()) { if (!cpu_thread_running) { - showMessageForNonQtThread(flags, header, message, nullptr); + showMessageForNonQtThread(flags, header, message, richText, nullptr); } else - showMessage_(flags, header, message); + showMessage_(flags, header, message, richText); } else { std::atomic_bool done = false; - emit showMessageForNonQtThread(flags, header, message, &done); + emit showMessageForNonQtThread(flags, header, message, richText, &done); while (!done) { QThread::msleep(1); } @@ -1360,7 +1360,7 @@ MainWindow::showMessage(int flags, const QString &header, const QString &message } void -MainWindow::showMessage_(int flags, const QString &header, const QString &message, std::atomic_bool *done) +MainWindow::showMessage_(int flags, const QString &header, const QString &message, bool richText, std::atomic_bool *done) { if (done) { *done = false; @@ -1372,7 +1372,8 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag } else if (!(flags & (MBX_ERROR | MBX_WARNING))) { box.setIcon(QMessageBox::Warning); } - box.setTextFormat(Qt::TextFormat::RichText); + if (richText) + box.setTextFormat(Qt::TextFormat::RichText); box.exec(); if (done) { *done = true; diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 4b3f9ecae..739d179ff 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -26,7 +26,7 @@ public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void showMessage(int flags, const QString &header, const QString &message); + void showMessage(int flags, const QString &header, const QString &message, bool richText); void getTitle(wchar_t *title); void blitToWidget(int x, int y, int w, int h, int monitor_index); QSize getRenderWidgetSize(); @@ -55,7 +55,7 @@ signals: void setFullscreen(bool state); void setMouseCapture(bool state); - void showMessageForNonQtThread(int flags, const QString &header, const QString &message, std::atomic_bool* done); + void showMessageForNonQtThread(int flags, const QString &header, const QString &message, bool richText, std::atomic_bool* done); void getTitleForNonQtThread(wchar_t *title); public slots: void showSettings(); @@ -123,7 +123,7 @@ private slots: void on_actionRenderer_options_triggered(); void refreshMediaMenu(); - void showMessage_(int flags, const QString &header, const QString &message, std::atomic_bool* done = nullptr); + void showMessage_(int flags, const QString &header, const QString &message, bool richText, std::atomic_bool* done = nullptr); void getTitle_(wchar_t *title); void on_actionMCA_devices_triggered(); diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 53d29f9a8..45bae6ea7 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -200,7 +200,7 @@ OpenGLRenderer::create_program(struct shader_program *program) glw.glGetProgramiv(program->id, GL_INFO_LOG_LENGTH, &maxLength); char *log = (char *) malloc(maxLength); glw.glGetProgramInfoLog(program->id, maxLength, &length, log); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Program not linked:\n\n%1").arg(log).replace("\n", "
    ")); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Program not linked:\n\n%1").arg(log), false); // wx_simple_messagebox("GLSL Error", "Program not linked:\n%s", log); free(log); return 0; @@ -247,7 +247,7 @@ OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const ch glw.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); char *log = (char *) malloc(length); glw.glGetShaderInfoLog(shader, length, &length, log); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not compile shader:\n\n%1").arg(log).replace("\n", "
    ")); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not compile shader:\n\n%1").arg(log), false); // wx_simple_messagebox("GLSL Error", "Could not compile shader:\n%s", log); ogl3_log("Could not compile shader: %s\n", log); @@ -651,7 +651,7 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) if (!load_texture(file, &tex->texture)) { //QMessageBox::critical(main_window, tr("GLSL Error"), tr("Could not load texture: %s").arg(file)); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load texture: %1").arg(file)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load texture: %1").arg(file), false); ogl3_log("Could not load texture %s!\n", file); failed = 1; break; @@ -697,7 +697,7 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) ogl3_log("Creating pass %u (%s)\n", (i + 1), pass->alias); ogl3_log("Loading shader %s...\n", shader->shader_fn); if (!shader->shader_program) { - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn)); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("GLSL Error"), tr("Could not load shader: %1").arg(shader->shader_fn), false); // wx_simple_messagebox("GLSL Error", "Could not load shader: %s", shader->shader_fn); ogl3_log("Could not load shader %s\n", shader->shader_fn); failed = 1; @@ -1115,7 +1115,7 @@ OpenGLRenderer::initialize() for (auto &flag : buf_usage) flag.test_and_set(); - main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("Error initializing OpenGL"), e.what() + tr("\nFalling back to software rendering.")); + main_window->showMessage(MBX_ERROR | MBX_FATAL, tr("Error initializing OpenGL"), e.what() + tr("\nFalling back to software rendering."), false); context->doneCurrent(); isFinalized = true; diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index b9253663b..57f8001dc 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -142,11 +142,10 @@ ui_msgbox_header(int flags, void *header, void *message) // any error in early init if (main_window == nullptr) { QMessageBox msgBox(QMessageBox::Icon::Critical, hdr, msg); - msgBox.setTextFormat(Qt::TextFormat::RichText); msgBox.exec(); } else { // else scope it to main_window - main_window->showMessage(flags, hdr, msg); + main_window->showMessage(flags, hdr, msg, false); } return 0; } From d5cc259d65c65069fb438ffd1e33116ebe2af610 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 16 Apr 2025 20:47:13 +0500 Subject: [PATCH 0741/1190] Dev branch: Enable Mitsumi CD-ROM in the UI --- src/cdrom/cdrom.c | 6 ++++++ src/qt/CMakeLists.txt | 4 ++++ src/qt/qt_harddrive_common.cpp | 6 +++--- src/qt/qt_settingsstoragecontrollers.cpp | 9 +++++++++ src/qt/qt_settingsstoragecontrollers.ui | 9 --------- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 0f468bba0..44bf2811c 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -29,6 +29,9 @@ #include <86box/cdrom.h> #include <86box/cdrom_image.h> #include <86box/cdrom_interface.h> +#ifdef USE_CDROM_MITSUMI +#include <86box/cdrom_mitsumi.h> +#endif #include <86box/log.h> #include <86box/plat.h> #include <86box/plat_cdrom_ioctl.h> @@ -117,6 +120,9 @@ static const struct { } controllers[] = { // clang-format off { &cdrom_interface_none_device }, +#ifdef USE_CDROM_MITSUMI + { &mitsumi_cdrom_device }, +#endif { NULL } // clang-format on }; diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index e6e45fc25..f02e3708a 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -207,6 +207,10 @@ if(WACOM) target_compile_definitions(ui PRIVATE USE_WACOM) endif() +if(CDROM_MITSUMI) + target_compile_definitions(ui PRIVATE USE_CDROM_MITSUMI) +endif() + if(WIN32) enable_language(RC) target_sources(86Box PUBLIC 86Box-qt.rc) diff --git a/src/qt/qt_harddrive_common.cpp b/src/qt/qt_harddrive_common.cpp index e0b0233f1..52ae10a98 100644 --- a/src/qt/qt_harddrive_common.cpp +++ b/src/qt/qt_harddrive_common.cpp @@ -51,7 +51,7 @@ void Harddrives::populateRemovableBuses(QAbstractItemModel *model) { model->removeRows(0, model->rowCount()); -#if 0 +#ifdef USE_CDROM_MITSUMI model->insertRows(0, 4); #else model->insertRows(0, 3); @@ -59,14 +59,14 @@ Harddrives::populateRemovableBuses(QAbstractItemModel *model) model->setData(model->index(0, 0), QObject::tr("Disabled")); model->setData(model->index(1, 0), QObject::tr("ATAPI")); model->setData(model->index(2, 0), QObject::tr("SCSI")); -#if 0 +#ifdef USE_CDROM_MITSUMI model->setData(model->index(3, 0), QObject::tr("Mitsumi")); #endif model->setData(model->index(0, 0), HDD_BUS_DISABLED, Qt::UserRole); model->setData(model->index(1, 0), HDD_BUS_ATAPI, Qt::UserRole); model->setData(model->index(2, 0), HDD_BUS_SCSI, Qt::UserRole); -#if 0 +#ifdef USE_CDROM_MITSUMI model->setData(model->index(3, 0), CDROM_BUS_MITSUMI, Qt::UserRole); #endif } diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 9bd1bda6f..6fa5906b5 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -142,6 +142,15 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->comboBoxFD->setCurrentIndex(selectedRow); /*CD interface controller config*/ +#ifdef USE_CDROM_MITSUMI + ui->label_7->setVisible(true); + ui->comboBoxCDInterface->setVisible(true); + ui->pushButtonCDInterface->setVisible(true); +#else + ui->label_7->setVisible(false); + ui->comboBoxCDInterface->setVisible(false); + ui->pushButtonCDInterface->setVisible(false); +#endif c = 0; model = ui->comboBoxCDInterface->model(); removeRows = model->rowCount(); diff --git a/src/qt/qt_settingsstoragecontrollers.ui b/src/qt/qt_settingsstoragecontrollers.ui index 16d6e2494..a167e5bc1 100644 --- a/src/qt/qt_settingsstoragecontrollers.ui +++ b/src/qt/qt_settingsstoragecontrollers.ui @@ -51,9 +51,6 @@
    - - false - CD-ROM Controller: @@ -61,9 +58,6 @@ - - false - 30 @@ -71,9 +65,6 @@ - - false - Configure From a4a26f8b56c1f39ef0356032bd2c6657ae3872c9 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 16 Apr 2025 22:04:14 +0500 Subject: [PATCH 0742/1190] qt: Fix HDD model still being speed in the HDD list --- src/qt/qt_settingsharddisks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index ded50ac34..32b677888 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -116,7 +116,7 @@ SettingsHarddisks::SettingsHarddisks(QWidget *parent) model->setHeaderData(ColumnHeads, Qt::Horizontal, tr("H")); model->setHeaderData(ColumnSectors, Qt::Horizontal, tr("S")); model->setHeaderData(ColumnSize, Qt::Horizontal, tr("MiB")); - model->setHeaderData(ColumnSpeed, Qt::Horizontal, tr("Speed")); + model->setHeaderData(ColumnSpeed, Qt::Horizontal, tr("Model")); ui->tableView->setModel(model); for (int i = 0; i < HDD_NUM; i++) { From 4160fd6a5a00e649e57d2639ef97fbff757ef8c6 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 16 Apr 2025 22:23:52 +0500 Subject: [PATCH 0743/1190] qt: Add colons to dropdown labels on the network settings page For consistency purposes --- src/qt/qt_settingsnetwork.ui | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index 741b60648..8fb048f71 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -58,7 +58,7 @@
    - Adapter + Adapter:
    @@ -84,7 +84,7 @@ - Mode + Mode:
    @@ -124,14 +124,14 @@ - Interface + Interface:
    - VDE Socket + VDE Socket: @@ -197,7 +197,7 @@ - Interface + Interface:
    @@ -217,7 +217,7 @@ - Mode + Mode:
    @@ -237,7 +237,7 @@ - VDE Socket + VDE Socket: @@ -257,7 +257,7 @@ - Adapter + Adapter:
    @@ -326,7 +326,7 @@ - VDE Socket + VDE Socket: @@ -362,7 +362,7 @@ - Interface + Interface:
    @@ -382,7 +382,7 @@ - Mode + Mode:
    @@ -408,7 +408,7 @@ - Adapter + Adapter:
    @@ -461,7 +461,7 @@ - Mode + Mode:
    @@ -481,7 +481,7 @@ - VDE Socket + VDE Socket: @@ -494,7 +494,7 @@ - Adapter + Adapter:
    @@ -514,7 +514,7 @@ - Interface + Interface:
    From de35961bb4a14911f64d862448754a245d310d1d Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 17 Apr 2025 17:20:08 +0500 Subject: [PATCH 0744/1190] qt: Use Yu Gothic UI as the Japanese font on Windows 10 and later --- src/qt/qt_progsettings.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 0fce0d705..aa9bbe97b 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -26,6 +26,10 @@ #include #include #include +#ifdef Q_OS_WINDOWS +# include +# include +#endif extern "C" { #include <86box/86box.h> @@ -115,7 +119,11 @@ ProgSettings::getFontName(uint32_t lcid) case 0x0404: /* zh-TW */ return "Microsoft JhengHei"; case 0x0411: /* ja-JP */ - return "Meiryo UI"; + /* Check for Windows 10 or later to choose the appropriate system font */ + if (QVersionNumber::fromString(QSysInfo::kernelVersion()).majorVersion() >= 10) + return "Yu Gothic UI"; + else + return "Meiryo UI"; case 0x0412: /* ko-KR */ return "Malgun Gothic"; case 0x0804: /* zh-CN */ From e1007d2377f572639ac9d847cfca371d2fffac20 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 17 Apr 2025 21:52:32 +0500 Subject: [PATCH 0745/1190] Get rid of Windows LCIDs as numeric language IDs --- src/86box.c | 3 +- src/config.c | 6 +-- src/include/86box/86box.h | 8 ++- src/include/86box/plat.h | 4 +- src/qt/qt_platform.cpp | 53 +++--------------- src/qt/qt_progsettings.cpp | 108 ++++++++++++++++++++++++++----------- src/qt/qt_progsettings.hpp | 16 +++--- src/unix/unix.c | 10 ++-- 8 files changed, 106 insertions(+), 102 deletions(-) diff --git a/src/86box.c b/src/86box.c index ad1cfc519..168e8a8dc 100644 --- a/src/86box.c +++ b/src/86box.c @@ -160,6 +160,7 @@ int window_remember; int vid_resize; /* (C) allow resizing */ int invert_display = 0; /* (C) invert the display */ int suppress_overscan = 0; /* (C) suppress overscans */ +int lang_id = 0; /* (C) language id */ int scale = 0; /* (C) screen scale factor */ int dpi_scale = 0; /* (C) DPI scaling of the emulated screen */ @@ -584,7 +585,7 @@ pc_init(int argc, char *argv[]) uint32_t *uid; uint32_t *shwnd; #endif - uint32_t lang_init = 0; + int lang_init = 0; /* Grab the executable's full path. */ plat_get_exe_name(exe_path, sizeof(exe_path) - 1); diff --git a/src/config.c b/src/config.c index 6f023cf67..b3de77d71 100644 --- a/src/config.c +++ b/src/config.c @@ -186,7 +186,7 @@ load_general(void) if (p != NULL) lang_id = plat_language_code(p); else - lang_id = 0xffff; + lang_id = plat_language_code(DEFAULT_LANGUAGE); mouse_sensitivity = ini_section_get_double(cat, "mouse_sensitivity", 1.0); if (mouse_sensitivity < 0.1) @@ -1842,7 +1842,7 @@ config_load(void) cassette_pcm = 0; cassette_ui_writeprot = 0; - lang_id = DEFAULT_LANGUAGE; + lang_id = plat_language_code(DEFAULT_LANGUAGE); config_log("Config file not present or invalid!\n"); } else { @@ -2029,7 +2029,7 @@ save_general(void) else ini_section_delete_var(cat, "mouse_sensitivity"); - if (lang_id == DEFAULT_LANGUAGE) + if (lang_id == plat_language_code(DEFAULT_LANGUAGE)) ini_section_delete_var(cat, "language"); else { plat_language_code_r(lang_id, buffer, 511); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index ddca937f1..c85311688 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -44,8 +44,8 @@ /* Max UUID Length */ #define MAX_UUID_LEN 64 -/* Default language 0xFFFF = from system, 0x409 = en-US */ -#define DEFAULT_LANGUAGE 0xffff +/* Default language code */ +#define DEFAULT_LANGUAGE "system" #define POSTCARDS_NUM 4 #define POSTCARD_MASK (POSTCARDS_NUM - 1) @@ -84,8 +84,6 @@ extern "C" { #endif /* Global variables. */ -extern uint32_t lang_sys; /* (-) system language code */ - extern int dump_on_exit; /* (O) dump regs on exit*/ extern int start_in_fullscreen; /* (O) start in fullscreen */ #ifdef _WIN32 @@ -117,7 +115,7 @@ extern int window_remember; 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 int lang_id; /* (C) language id */ 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/include/86box/plat.h b/src/include/86box/plat.h index 7ed6e80d4..bbc673dcf 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -160,8 +160,8 @@ extern int plat_vidapi(const char *name); extern char *plat_vidapi_name(int api); extern void plat_resize(int x, int y, int monitor_index); extern void plat_resize_request(int x, int y, int monitor_index); -extern uint32_t plat_language_code(char *langcode); -extern void plat_language_code_r(uint32_t lcid, char *outbuf, int len); +extern int plat_language_code(char *langcode); +extern void plat_language_code_r(int id, 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); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index e8a02fc3b..0f792feda 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -140,7 +140,6 @@ int update_icons = 1; int kbd_req_capture = 0; int hide_status_bar = 0; int hide_tool_bar = 0; -uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US int stricmp(const char *s1, const char *s2) @@ -461,58 +460,18 @@ plat_power_off(void) QTimer::singleShot(0, (const QWidget *) main_window, &QMainWindow::close); } -extern "C++" { -QMap> ProgSettings::lcid_langcode = { - { 0x0403, { "ca-ES", "Catalan (Spain)" } }, - { 0x0804, { "zh-CN", "Chinese (Simplified)" } }, - { 0x0404, { "zh-TW", "Chinese (Traditional)" } }, - { 0x041A, { "hr-HR", "Croatian (Croatia)" } }, - { 0x0405, { "cs-CZ", "Czech (Czech Republic)" } }, - { 0x0407, { "de-DE", "German (Germany)" } }, - { 0x0809, { "en-GB", "English (United Kingdom)" }}, - { 0x0409, { "en-US", "English (United States)" } }, - { 0x040B, { "fi-FI", "Finnish (Finland)" } }, - { 0x040C, { "fr-FR", "French (France)" } }, - { 0x040E, { "hu-HU", "Hungarian (Hungary)" } }, - { 0x0410, { "it-IT", "Italian (Italy)" } }, - { 0x0411, { "ja-JP", "Japanese (Japan)" } }, - { 0x0412, { "ko-KR", "Korean (Korea)" } }, - { 0x0413, { "nl-NL", "Dutch (Netherlands)" } }, - { 0x0415, { "pl-PL", "Polish (Poland)" } }, - { 0x0416, { "pt-BR", "Portuguese (Brazil)" } }, - { 0x0816, { "pt-PT", "Portuguese (Portugal)" } }, - { 0x0419, { "ru-RU", "Russian (Russia)" } }, - { 0x041B, { "sk-SK", "Slovak (Slovakia)" } }, - { 0x0424, { "sl-SI", "Slovenian (Slovenia)" } }, - { 0x0C0A, { "es-ES", "Spanish (Spain, Modern Sort)" } }, - { 0x041F, { "tr-TR", "Turkish (Turkey)" } }, - { 0x0422, { "uk-UA", "Ukrainian (Ukraine)" } }, - { 0x042A, { "vi-VN", "Vietnamese (Vietnam)" } }, - { 0xFFFF, { "system", "(System Default)" } }, -}; -} - -/* Sets up the program language before initialization. */ -uint32_t +/* Converts the language code string to a numeric language ID */ +int plat_language_code(char *langcode) { - for (auto &curKey : ProgSettings::lcid_langcode.keys()) { - if (ProgSettings::lcid_langcode[curKey].first == langcode) { - return curKey; - } - } - return 0xFFFF; + return ProgSettings::languageCodeToId(QString(langcode)); } -/* Converts back the language code to LCID */ +/* Converts the numeric language ID to a language code string */ void -plat_language_code_r(uint32_t lcid, char *outbuf, int len) +plat_language_code_r(int id, char *outbuf, int len) { - if (!ProgSettings::lcid_langcode.contains(lcid)) { - qstrncpy(outbuf, "system", len); - return; - } - qstrncpy(outbuf, ProgSettings::lcid_langcode[lcid].first.toUtf8().constData(), len); + qstrncpy(outbuf, ProgSettings::languageIdToCode(id).toUtf8().constData(), len); return; } diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index aa9bbe97b..3903c9d9f 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -45,18 +45,45 @@ extern MainWindow *main_window; ProgSettings::CustomTranslator *ProgSettings::translator = nullptr; QTranslator *ProgSettings::qtTranslator = nullptr; +QVector> ProgSettings::languages = { + { "system", "(System Default)" }, + { "ca-ES", "Catalan (Spain)" }, + { "zh-CN", "Chinese (Simplified)" }, + { "zh-TW", "Chinese (Traditional)" }, + { "hr-HR", "Croatian (Croatia)" }, + { "cs-CZ", "Czech (Czech Republic)" }, + { "de-DE", "German (Germany)" }, + { "en-GB", "English (United Kingdom)" }, + { "en-US", "English (United States)" }, + { "fi-FI", "Finnish (Finland)" }, + { "fr-FR", "French (France)" }, + { "hu-HU", "Hungarian (Hungary)" }, + { "it-IT", "Italian (Italy)" }, + { "ja-JP", "Japanese (Japan)" }, + { "ko-KR", "Korean (Korea)" }, + { "nl-NL", "Dutch (Netherlands)" }, + { "pl-PL", "Polish (Poland)" }, + { "pt-BR", "Portuguese (Brazil)" }, + { "pt-PT", "Portuguese (Portugal)" }, + { "ru-RU", "Russian (Russia)" }, + { "sk-SK", "Slovak (Slovakia)" }, + { "sl-SI", "Slovenian (Slovenia)" }, + { "es-ES", "Spanish (Spain)" }, + { "tr-TR", "Turkish (Turkey)" }, + { "uk-UA", "Ukrainian (Ukraine)" }, + { "vi-VN", "Vietnamese (Vietnam)" }, +}; + ProgSettings::ProgSettings(QWidget *parent) : QDialog(parent) , ui(new Ui::ProgSettings) { ui->setupUi(this); - ui->comboBoxLanguage->setItemData(0, 0xFFFF); - for (auto i = lcid_langcode.begin(); i != lcid_langcode.end(); i++) { - if (i.key() == 0xFFFF) - continue; - ui->comboBoxLanguage->addItem(lcid_langcode[i.key()].second, i.key()); - if (i.key() == lang_id) { - ui->comboBoxLanguage->setCurrentIndex(ui->comboBoxLanguage->findData(i.key())); + ui->comboBoxLanguage->setItemData(0, 0); + for (int i = 1; i < languages.length(); i++) { + ui->comboBoxLanguage->addItem(languages[i].second, i); + if (i == lang_id) { + ui->comboBoxLanguage->setCurrentIndex(ui->comboBoxLanguage->findData(i)); } } ui->comboBoxLanguage->model()->sort(Qt::AscendingOrder); @@ -78,7 +105,7 @@ ProgSettings::ProgSettings(QWidget *parent) void ProgSettings::accept() { - lang_id = ui->comboBoxLanguage->currentData().toUInt(); + lang_id = ui->comboBoxLanguage->currentData().toInt(); open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; confirm_exit = ui->checkBoxConfirmExit->isChecked() ? 1 : 0; confirm_save = ui->checkBoxConfirmSave->isChecked() ? 1 : 0; @@ -113,27 +140,46 @@ ProgSettings::~ProgSettings() /* Return the standard font name on Windows, which is overridden per-language to prevent CJK fonts with embedded bitmaps being chosen as a fallback. */ QString -ProgSettings::getFontName(uint32_t lcid) +ProgSettings::getFontName(int langId) { - switch (lcid) { - case 0x0404: /* zh-TW */ - return "Microsoft JhengHei"; - case 0x0411: /* ja-JP */ - /* Check for Windows 10 or later to choose the appropriate system font */ - if (QVersionNumber::fromString(QSysInfo::kernelVersion()).majorVersion() >= 10) - return "Yu Gothic UI"; - else - return "Meiryo UI"; - case 0x0412: /* ko-KR */ - return "Malgun Gothic"; - case 0x0804: /* zh-CN */ - return "Microsoft YaHei"; - default: - return "Segoe UI"; - } + QString langCode = languageIdToCode(lang_id); + if (langCode == "ja-JP") { + /* Check for Windows 10 or later to choose the appropriate system font */ + if (QVersionNumber::fromString(QSysInfo::kernelVersion()).majorVersion() >= 10) + return "Yu Gothic UI"; + else + return "Meiryo UI"; + } else if (langCode == "ko-KR") + return "Malgun Gothic"; + else if (langCode == "zh-CN") + return "Microsoft YaHei"; + else if (langCode == "zh-TW") + return "Microsoft JhengHei"; + else + return "Segoe UI"; } #endif +int +ProgSettings::languageCodeToId(QString langCode) +{ + for (int i = 0; i < languages.length(); i++) { + if (languages[i].first == langCode) { + return i; + } + } + return 0; +} + +QString +ProgSettings::languageIdToCode(int id) +{ + if ((id == 0) || (id >= languages.length())) { + return "system"; + } + return languages[id].first; +} + void ProgSettings::loadTranslators(QObject *parent) { @@ -148,7 +194,7 @@ ProgSettings::loadTranslators(QObject *parent) qtTranslator = new QTranslator(parent); translator = new CustomTranslator(parent); QString localetofilename = ""; - if (lang_id == 0xFFFF || lcid_langcode.contains(lang_id) == false) { + if (lang_id == 0 || lang_id >= languages.length()) { for (int i = 0; i < QLocale::system().uiLanguages().size(); i++) { localetofilename = QLocale::system().uiLanguages()[i]; if (translator->load(QLatin1String("86box_") + localetofilename, QLatin1String(":/"))) { @@ -166,12 +212,12 @@ ProgSettings::loadTranslators(QObject *parent) } } } else { - translator->load(QLatin1String("86box_") + lcid_langcode[lang_id].first, QLatin1String(":/")); + translator->load(QLatin1String("86box_") + languages[lang_id].first, QLatin1String(":/")); QCoreApplication::installTranslator(translator); - if (!qtTranslator->load(QLatin1String("qtbase_") + QString(lcid_langcode[lang_id].first).replace('-', '_'), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - if (!qtTranslator->load(QLatin1String("qtbase_") + QString(lcid_langcode[lang_id].first).left(QString(lcid_langcode[lang_id].first).indexOf('-')), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - if(!qtTranslator->load(QLatin1String("qt_") + QString(lcid_langcode[lang_id].first).replace('-', '_'), QApplication::applicationDirPath() + "/./translations/")) - qtTranslator->load(QLatin1String("qt_") + QString(lcid_langcode[lang_id].first).replace('-', '_'), QLatin1String(":/")); + if (!qtTranslator->load(QLatin1String("qtbase_") + QString(languages[lang_id].first).replace('-', '_'), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + if (!qtTranslator->load(QLatin1String("qtbase_") + QString(languages[lang_id].first).left(QString(languages[lang_id].first).indexOf('-')), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + if(!qtTranslator->load(QLatin1String("qt_") + QString(languages[lang_id].first).replace('-', '_'), QApplication::applicationDirPath() + "/./translations/")) + qtTranslator->load(QLatin1String("qt_") + QString(languages[lang_id].first).replace('-', '_'), QLatin1String(":/")); QCoreApplication::installTranslator(qtTranslator); } diff --git a/src/qt/qt_progsettings.hpp b/src/qt/qt_progsettings.hpp index 1c7295f56..31600e7f1 100644 --- a/src/qt/qt_progsettings.hpp +++ b/src/qt/qt_progsettings.hpp @@ -15,10 +15,12 @@ public: explicit ProgSettings(QWidget *parent = nullptr); ~ProgSettings(); #ifdef Q_OS_WINDOWS - static QString getFontName(uint32_t lcid); + static QString getFontName(int langId); #endif - static void loadTranslators(QObject *parent = nullptr); - static void reloadStrings(); + static int languageCodeToId(QString langCode); + static QString languageIdToCode(int id); + static void loadTranslators(QObject *parent = nullptr); + static void reloadStrings(); class CustomTranslator : public QTranslator { public: CustomTranslator(QObject *parent = nullptr) @@ -31,10 +33,10 @@ public: return QTranslator::translate("", sourceText, disambiguation, n); } }; - static CustomTranslator *translator; - static QTranslator *qtTranslator; - static QMap> lcid_langcode; - static QMap translatedstrings; + static CustomTranslator *translator; + static QTranslator *qtTranslator; + static QVector> languages; + static QMap translatedstrings; protected slots: void accept() override; diff --git a/src/unix/unix.c b/src/unix/unix.c index c41aee2a4..395e6f540 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -71,8 +71,6 @@ SDL_mutex *blitmtx; SDL_threadID eventthread; 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 static const uint16_t sdl_to_xt[0x200] = { [SDL_SCANCODE_ESCAPE] = 0x01, @@ -1378,8 +1376,8 @@ plat_vidapi_name(UNUSED(int i)) return "default"; } -/* Sets up the program language before initialization. */ -uint32_t +/* Converts the language code string to a numeric language ID */ +int plat_language_code(UNUSED(char *langcode)) { /* or maybe not */ @@ -1419,9 +1417,9 @@ plat_set_thread_name(void *thread, const char *name) #endif } -/* Converts back the language code to LCID */ +/* Converts the numeric language ID to a language code string */ void -plat_language_code_r(UNUSED(uint32_t lcid), UNUSED(char *outbuf), UNUSED(int len)) +plat_language_code_r(UNUSED(int id), UNUSED(char *outbuf), UNUSED(int len)) { /* or maybe not */ return; From b6483a20cf023b71ff0781eae403085dfff1033f Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 16 Apr 2025 21:54:39 +0500 Subject: [PATCH 0746/1190] languages: French translation updates by jvernet Co-Authored-by: jvernet --- src/qt/languages/fr-FR.po | 138 +++++++++++++++++++------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index ebb181a30..0701a188e 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -40,7 +40,7 @@ msgid "Hide &toolbar" msgstr "Masquer la &barre d'outils" msgid "&Resizeable window" -msgstr "Fenètre &Retaillable" +msgstr "Fenêtre &Redimensionnable" msgid "R&emember size && position" msgstr "S&auvegarder taille && position" @@ -61,7 +61,7 @@ msgid "&VNC" msgstr "&VNC" msgid "Specify dimensions..." -msgstr "Specifier dimensions..." +msgstr "Spécifier dimensions..." msgid "F&orce 4:3 display ratio" msgstr "F&orcer 4:3" @@ -100,7 +100,7 @@ msgid "&8x" msgstr "&8x" msgid "Filter method" -msgstr "Methode Filtre" +msgstr "Méthode Filtre" msgid "&Nearest" msgstr "&Plus proche" @@ -157,7 +157,7 @@ msgid "&White monitor" msgstr "Moniteur &Blanc" msgid "Grayscale &conversion type" -msgstr "Grayscale &conversion type" +msgstr "Mode &Conversion tons de gris" msgid "BT&601 (NTSC/PAL)" msgstr "BT&601 (NTSC/PAL)" @@ -169,7 +169,7 @@ msgid "&Average" msgstr "&Moyenne" msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" -msgstr "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgstr "Overscan CGA/PCjr/Tandy/E&GA/(S)VGA" msgid "Change contrast for &monochrome display" msgstr "Modifier contraste affichage &monochrome" @@ -205,7 +205,7 @@ msgid "Begin trace" msgstr "Démarrer traces" msgid "End trace" -msgstr "Finir traces" +msgstr "Arrêter traces" msgid "&Help" msgstr "&Aide" @@ -244,7 +244,7 @@ msgid "&Image..." msgstr "&Image..." msgid "E&xport to 86F..." -msgstr "E&xport vers 86F..." +msgstr "E&xporter vers 86F..." msgid "&Mute" msgstr "&Couper" @@ -301,7 +301,7 @@ msgid "Settings" msgstr "Réglages" msgid "Specify Main Window Dimensions" -msgstr "Spécifier le détournement de la fenêtre principale" +msgstr "Spécifier les dimensions de la fenêtre principale" msgid "OK" msgstr "OK" @@ -349,7 +349,7 @@ msgid "Configure" msgstr "Configurer" msgid "CPU type:" -msgstr "Type du processeur:" +msgstr "Type de processeur:" msgid "Speed:" msgstr "Vitesse:" @@ -403,7 +403,7 @@ msgid "Mouse:" msgstr "Souris:" msgid "Joystick:" -msgstr "Manette de commande:" +msgstr "Manette:" msgid "Joystick 1..." msgstr "Manette 1..." @@ -607,7 +607,7 @@ msgid "ISA RTC:" msgstr "Horloge temps réel ISA:" msgid "ISA Memory Expansion" -msgstr "Expansion de la mémoire ISA" +msgstr "Extension de mémoire ISA" msgid "Card 1:" msgstr "Carte 1:" @@ -670,7 +670,7 @@ msgid "Off" msgstr "Désactivé" msgid "All images" -msgstr "Tous les images" +msgstr "Toutes les images" msgid "Basic sector images" msgstr "Images basiques du secteur" @@ -862,16 +862,16 @@ msgid "Hardware not available" msgstr "Matériel non disponible" msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." -msgstr "Assurez-vous que %1 est installé et que vou utilisez une connexion réseau compatible avec %1." +msgstr "Assurez-vous que %1 est installé et que vous utilisez une connexion réseau compatible avec %1." msgid "Invalid configuration" msgstr "Configuration non valide" msgid "%1 is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -msgstr "%1 est nécessair pour la conversion automatique des fichiers PostScript dans PDF.\n\nTous les documents envoyés à l'imprimante générique PostScript seront sauvés comme des fichiers PostScript (.ps)." +msgstr "%1 est nécessaire pour la conversion automatique des fichiers PostScript en PDF.\n\nTous les documents envoyés à l'imprimante générique PostScript seront sauvés en tant que fichiers PostScript (.ps)." msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." -msgstr "%1 est nécessair pour la conversion automatique des fichiers PCL dans PDF.\n\nTous les documents envoyés à l'imprimante générique PCL seront sauvés comme des fichiers Printer Command Language (.pcl)." +msgstr "%1 est nécessaire pour la conversion automatique des fichiers PCL en PDF.\n\nTous les documents envoyés à l'imprimante générique PCL seront sauvés en tant quefichiers Printer Command Language (.pcl)." msgid "Entering fullscreen mode" msgstr "Entrer en mode plein écran" @@ -904,7 +904,7 @@ msgid "You are loading an unsupported configuration" msgstr "Vous chargez une configuration non prise en charge" 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 "La filtrage du type du processeur sur la base de la machine sélectionné est désactivé pur cette machine émulée.\n\nCela permet de sélectionner une processeur que est sinon incompatible avec la machine sélectionné. Cependant, il pourrait y avoir des incompatibilités avec le BIOS de la machine ou autres logiciels.\n\nL'activatione de cette configuration non est officiellement prise en charge et tout rapport de bogue peut être fermé comme étant invalide." +msgstr "Le filtrage du type du processeur sur la base de la machine sélectionnée est désactivé pur cette machine émulée.\n\nCela permet de sélectionner un processeur qui est sinon incompatible avec la machine sélectionné. Cependant, il pourrait y avoir des incompatibilités avec le BIOS de la machine ou autres logiciels.\n\nL'activation de cette configuration non officiellement prise en charge implique que tout rapport de bogue peut être fermé comme étant invalide." msgid "Continue" msgstr "Continuer" @@ -928,7 +928,7 @@ msgid "Pause execution" msgstr "Pause de l'exécution" msgid "Press Ctrl+Alt+Del" -msgstr "Appuyer sur Ctrl+Alt+Suppr." +msgstr "Appuyer sur Ctrl+Alt+Suppr" msgid "Press Ctrl+Alt+Esc" msgstr "Appuyer sur Ctrl+Alt+Esc" @@ -958,13 +958,13 @@ msgid "Add Existing Hard Disk" msgstr "Ajouter un disque dur existant" msgid "HDI disk images cannot be larger than 4 GB." -msgstr "Les images de disque HDI ne peuvent pas avoir une taille supériure à Go." +msgstr "Les images de disque HDI ne peuvent pas avoir une taille supérieure à 4 Go." msgid "Disk images cannot be larger than 127 GB." -msgstr "Les images de disque ne peuvent pas avoir un taille supérieure à 127 Go." +msgstr "Les images de disque ne peuvent pas avoir une taille supérieure à 127 Go." msgid "Hard disk images" -msgstr "Images de dique dur" +msgstr "Images de disque dur" msgid "Unable to read file" msgstr "Impossible de lire le fichier" @@ -973,10 +973,10 @@ msgid "Unable to write file" msgstr "Impossible d'écrire le fichier" msgid "HDI or HDX images with a sector size other than 512 are not supported." -msgstr "Les images HDI ou HDX avec une taille de secteur différente de 512 non sont pas prises en charge." +msgstr "Les images HDI ou HDX avec une taille de secteur différente de 512 ne sont pas prises en charge." msgid "Disk image file already exists" -msgstr "Le fichier de l'image disque existe déjà." +msgstr "Le fichier de l'image disque existe déjà" msgid "Please specify a valid file name." msgstr "Veuillez spécifier un nom de fichier valide." @@ -1048,10 +1048,10 @@ msgid "Differencing VHD (.vhd)" msgstr "VHD à différenciation (.vhd)" msgid "Large blocks (2 MB)" -msgstr "Blocs grands (2 Mo)" +msgstr "Grands Blocs (2 Mo)" msgid "Small blocks (512 KB)" -msgstr "Blocs petits (512 Ko)" +msgstr "Petits Blocs (512 Ko)" msgid "VHD files" msgstr "Fichiers VHD" @@ -1060,10 +1060,10 @@ msgid "Select the parent VHD" msgstr "Sélectionnez le VHD parent" msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" -msgstr "Il est possible que l'image parente a été modifié après la création de l'image à différenciation.\n\nIl est même possible que les fichiers de l'mage ont été déplacés ou copiés ou il existe un bogue dans le programme que a créé ce disque.\n\nVoulez-vous réparer l'horodatage?" +msgstr "Il est possible que l'image parente ai été modifiée après la création de l'image à différenciation.\n\nIl est même possible que les fichiers de l’image ont été déplacés ou copiés ou il existe un bogue dans le programme qui a créé ce disque.\n\nVoulez-vous réparer l'horodatage?" msgid "Parent and child disk timestamps do not match" -msgstr "Les horodatages des disques parent et enfant ne correspondent pas" +msgstr "Les horodatages des disques parents et enfants ne correspondent pas" msgid "Could not fix VHD timestamp." msgstr "Impossible de réparer l'horodatage du VHD." @@ -1174,7 +1174,7 @@ msgid "Failed to initialize network driver" msgstr "Échec de l'initialisation du pilote réseau" msgid "The network configuration will be switched to the null driver" -msgstr "La configuration du réseau passera au pilote nul" +msgstr "La configuration du réseau passera au pilote NULL" msgid "Mouse sensitivity:" msgstr "Sensibilité de la souris:" @@ -1195,7 +1195,7 @@ msgid "Fast" msgstr "Rapide" msgid "&Auto-pause on focus loss" -msgstr "&Pause automatique à perte de mise au point" +msgstr "&Pause automatique à perte de focus" msgid "WinBox is no longer supported" msgstr "WinBox n'est plus pris en charge" @@ -1225,13 +1225,13 @@ msgid "List of MCA devices:" msgstr "Liste des dispositifs MCA :" msgid "Tablet tool" -msgstr "Nástroj pro tablety" +msgstr "Outil Tablette" msgid "Qt (OpenGL &ES)" msgstr "Qt (OpenGL &ES)" msgid "About Qt" -msgstr "O programu Qt" +msgstr "A propos de Qt" msgid "MCA devices..." msgstr "Dispositifs MCA..." @@ -1270,7 +1270,7 @@ msgid "Unknown Bus" msgstr "Bus inconnu" msgid "Null Driver" -msgstr "Pilote nul" +msgstr "Pilote NULL" msgid "NIC %1 (%2) %3" msgstr "NIC %1 (%2) %3" @@ -1282,7 +1282,7 @@ msgid "Use target framerate:" msgstr "Utiliser le taux de rafraîchissement cible:" msgid " fps" -msgstr " mages par seconde" +msgstr " Images par seconde" msgid "VSync" msgstr "VSync" @@ -1330,7 +1330,7 @@ msgid "I Copied It" msgstr "Je l'ai copié" msgid "86Box Monitor #" -msgstr "Moniteur 86Box " +msgstr "Moniteur 86Box" msgid "No MCA devices." msgstr "Pas de dispositifs MCA." @@ -1621,7 +1621,7 @@ msgid "Enable Game port" msgstr "Activer le port de jeu" msgid "Surround module" -msgstr "Module d'ambiance" +msgstr "Module Surround" msgid "CODEC" msgstr "CODEC" @@ -1846,7 +1846,7 @@ msgid "2 MB" msgstr "2 Mo" msgid "8 MB" -msgstr " 8 Mo" +msgstr "8 Mo" msgid "28 MB" msgstr "28 Mo" @@ -2002,10 +2002,10 @@ msgid "Stereo LPT DAC" msgstr "Convertisseur numérique stéréo LPT" msgid "Generic Text Printer" -msgstr "Imprimante de texte générique" +msgstr "Imprimante Texte générique" msgid "Generic ESC/P Dot-Matrix Printer" -msgstr "Imprimant générique ESC/P à matrice à points" +msgstr "Imprimante matricielle générique ESC/P" msgid "Generic PostScript Printer" msgstr "Imprimante PostScript générique" @@ -2062,100 +2062,100 @@ msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] Disque RAM (vitesse maximale)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Generic] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Generic] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Generic] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Generic] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" -msgstr "Clon IBM 8514/A (ISA)" +msgstr "Clone IBM 8514/A (ISA)" msgid "Vendor" msgstr "Fabricant" msgid "Generic PC/XT Memory Expansion" -msgstr "Expansion de la mémoire générique PC/XT" +msgstr "Extension de mémoire générique PC/XT" msgid "Generic PC/AT Memory Expansion" -msgstr "Expansion de la mémoire générique PC/AT" +msgstr "Extension de mémoire générique PC/AT" msgid "Unable to find Dot-Matrix fonts" -msgstr "Impossible de trouver les polices à matrice à points" +msgstr "Impossible de trouver les polices matricielles" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." -msgstr "Les polices TrueType dans le répertoire \"roms/printer/fonts\" sont nécessaires à l'émulation de l'imprimante générique ESC/P à matrice à points." +msgstr "Les polices TrueType dans le répertoire \"roms/printer/fonts\" sont nécessaires à l'émulation de l'imprimante générique ESC/P matricielle." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Désactiver les touches multimédia" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Demander confirmation avant de sauvegarder les réglages" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Demander confirmation avant Hard Reset" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Demander confirmation avant de quitter" msgid "Display hotkey message when entering full-screen mode" -msgstr "" +msgstr "Afficher Raccourcis Clavier avant de passer en plein écran" msgid "Options" -msgstr "" +msgstr "Options" msgid "Model:" -msgstr "" +msgstr "Modèle:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Impossible d’initialiser le moteur de rendu Vulkan." msgid "GLSL Error" -msgstr "" +msgstr "Erreur GLSL" msgid "Could not load shader: %1" -msgstr "" +msgstr "Impossible de charger le shaker %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL version 3.0 ou supérieur requis. Version installée: %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "Impossible de charger la texture %1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "Impossible de compiler le shader:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "Programme non linké:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "Gestionnaire de shader" msgid "Shader Configuration" -msgstr "" +msgstr "Configuration Shader" msgid "Add" -msgstr "" +msgstr "Ajouter" msgid "Move up" -msgstr "" +msgstr "Monter" msgid "Move down" -msgstr "" +msgstr "Descendre" msgid "Could not load file %1" -msgstr "" +msgstr "Impossible de charger le fichier %1" From 0d1f3a61cd271fc091d32570c525d6504590e4bb Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 16 Apr 2025 22:03:06 +0500 Subject: [PATCH 0747/1190] languages: Fix HDD model still being speed in the HDD list --- src/qt/languages/86box.pot | 3 +++ src/qt/languages/ca-ES.po | 3 +++ src/qt/languages/cs-CZ.po | 3 +++ src/qt/languages/de-DE.po | 3 +++ src/qt/languages/es-ES.po | 3 +++ src/qt/languages/fi-FI.po | 3 +++ src/qt/languages/fr-FR.po | 3 +++ src/qt/languages/hr-HR.po | 3 +++ src/qt/languages/hu-HU.po | 3 +++ src/qt/languages/it-IT.po | 3 +++ src/qt/languages/ja-JP.po | 3 +++ src/qt/languages/ko-KR.po | 3 +++ src/qt/languages/nl-NL.po | 3 +++ src/qt/languages/pl-PL.po | 3 +++ src/qt/languages/pt-BR.po | 3 +++ src/qt/languages/pt-PT.po | 3 +++ src/qt/languages/ru-RU.po | 3 +++ src/qt/languages/sk-SK.po | 3 +++ src/qt/languages/sl-SI.po | 3 +++ src/qt/languages/tr-TR.po | 3 +++ src/qt/languages/uk-UA.po | 3 +++ src/qt/languages/vi-VN.po | 3 +++ src/qt/languages/zh-CN.po | 3 +++ src/qt/languages/zh-TW.po | 3 +++ 24 files changed, 72 insertions(+) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 1d151a9d9..74481e068 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2124,6 +2124,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 9dec41c32..94b17adb3 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 2098fe018..e6a172e66 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 2088e4141..eead942eb 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -2121,6 +2121,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index bc11a4d4c..269d2f75e 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -2117,6 +2117,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 34e9aeead..6f4efd607 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -2121,6 +2121,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 0701a188e..d24f21c8d 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -2118,6 +2118,9 @@ msgstr "Afficher Raccourcis Clavier avant de passer en plein écran" msgid "Options" msgstr "Options" +msgid "Model" +msgstr "Modèle" + msgid "Model:" msgstr "Modèle:" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index c1f6480c2..346346687 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 09f914860..113591409 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index c9694c3be..028d86f40 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 1c139aaec..e66c8b2c1 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 941bd740a..61f65ad98 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index fd2b66245..5e0670385 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index ab50711f6..1a4ddda37 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index db07a69ae..cfc7fa42b 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index f67ddbdf8..564932890 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index fb1908f60..3c0eb619a 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2124,6 +2124,9 @@ msgstr "Показывать сообщение о горячих клавиша msgid "Options" msgstr "Параметры" +msgid "Model" +msgstr "Модель" + msgid "Model:" msgstr "Модель:" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 5080c49b5..1121aefb6 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -2119,6 +2119,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index c34fb6f7e..e3e8dba95 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index b7a59b620..2abe174ee 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 3145f5e34..7514e2fff 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -2124,6 +2124,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 932150f7b..d05396430 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 18f5a8fb8..450f148cf 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 9dbf51c70..c53753d28 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2118,6 +2118,9 @@ msgstr "" msgid "Options" msgstr "" +msgid "Model" +msgstr "" + msgid "Model:" msgstr "" From ab9e1eae5f3f3dc9a9c6a4f687e1a9d007f79c57 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 17 Apr 2025 00:18:15 +0500 Subject: [PATCH 0748/1190] languages: Remove more unused strings --- src/qt/languages/86box.pot | 9 --------- src/qt/languages/ca-ES.po | 9 --------- src/qt/languages/cs-CZ.po | 9 --------- src/qt/languages/de-DE.po | 9 --------- src/qt/languages/es-ES.po | 9 --------- src/qt/languages/fi-FI.po | 9 --------- src/qt/languages/fr-FR.po | 9 --------- src/qt/languages/hr-HR.po | 9 --------- src/qt/languages/hu-HU.po | 9 --------- src/qt/languages/it-IT.po | 9 --------- src/qt/languages/ja-JP.po | 9 --------- src/qt/languages/ko-KR.po | 9 --------- src/qt/languages/nl-NL.po | 9 --------- src/qt/languages/pl-PL.po | 9 --------- src/qt/languages/pt-BR.po | 9 --------- src/qt/languages/pt-PT.po | 9 --------- src/qt/languages/ru-RU.po | 9 --------- src/qt/languages/sk-SK.po | 9 --------- src/qt/languages/sl-SI.po | 9 --------- src/qt/languages/tr-TR.po | 9 --------- src/qt/languages/uk-UA.po | 9 --------- src/qt/languages/vi-VN.po | 9 --------- src/qt/languages/zh-CN.po | 9 --------- src/qt/languages/zh-TW.po | 9 --------- 24 files changed, 216 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 74481e068..81b639b7d 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -450,15 +450,6 @@ msgstr "" msgid "YMFM (faster)" msgstr "" -msgid "Network type:" -msgstr "" - -msgid "PCap device:" -msgstr "" - -msgid "Network adapter:" -msgstr "" - msgid "COM1 Device:" msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 94b17adb3..63b9b7a9b 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -450,15 +450,6 @@ msgstr "Nuked (més acurat)" msgid "YMFM (faster)" msgstr "YMFM (més ràpid)" -msgid "Network type:" -msgstr "Tipus de xarxa:" - -msgid "PCap device:" -msgstr "Dispositiu PCap:" - -msgid "Network adapter:" -msgstr "Adaptador de xarxa:" - msgid "COM1 Device:" msgstr "Dispositiu COM1:" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index e6a172e66..fd9769479 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -450,15 +450,6 @@ msgstr "Nuked (přesnější)" msgid "YMFM (faster)" msgstr "YMFM (rychlejší)" -msgid "Network type:" -msgstr "Druh sítě:" - -msgid "PCap device:" -msgstr "PCap zařízení:" - -msgid "Network adapter:" -msgstr "Síťový adaptér:" - msgid "COM1 Device:" msgstr "Zařízení na COM1:" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index eead942eb..cc734cb8b 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -450,15 +450,6 @@ msgstr "Nuked (genauer)" msgid "YMFM (faster)" msgstr "YMFM (schneller)" -msgid "Network type:" -msgstr "Netzwerktyp:" - -msgid "PCap device:" -msgstr "PCap-Gerät:" - -msgid "Network adapter:" -msgstr "Netzwerkadapter:" - msgid "COM1 Device:" msgstr "COM1-Gerät:" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 269d2f75e..cf349cd6d 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -450,15 +450,6 @@ msgstr "Nuked (más preciso)" msgid "YMFM (faster)" msgstr "YMFM (más rápido)" -msgid "Network type:" -msgstr "Tipo de red:" - -msgid "PCap device:" -msgstr "Dispositivo PCap:" - -msgid "Network adapter:" -msgstr "Adaptador de red:" - msgid "COM1 Device:" msgstr "Dispositivo COM1:" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 6f4efd607..3835165c0 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -450,15 +450,6 @@ msgstr "Nuked (tarkempi)" msgid "YMFM (faster)" msgstr "YMFM (nopeampi)" -msgid "Network type:" -msgstr "Verkon tyyppi:" - -msgid "PCap device:" -msgstr "PCap-laite:" - -msgid "Network adapter:" -msgstr "Verkkokortti:" - msgid "COM1 Device:" msgstr "COM1-laite:" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index d24f21c8d..8c53a7264 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -450,15 +450,6 @@ msgstr "Nuked (plus précis)" msgid "YMFM (faster)" msgstr "YMFM (plus rapide)" -msgid "Network type:" -msgstr "Type de réseau:" - -msgid "PCap device:" -msgstr "Dispositif PCap:" - -msgid "Network adapter:" -msgstr "Adaptateur de réseau:" - msgid "COM1 Device:" msgstr "Dispositif COM1:" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 346346687..f55ad7f53 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -450,15 +450,6 @@ msgstr "Nuked (precizniji)" msgid "YMFM (faster)" msgstr "YMFM (brži)" -msgid "Network type:" -msgstr "Tip mreže:" - -msgid "PCap device:" -msgstr "Uređaj PCap:" - -msgid "Network adapter:" -msgstr "Mrežna kartica:" - msgid "COM1 Device:" msgstr "Uređaj COM1:" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 113591409..009b6345e 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -450,15 +450,6 @@ msgstr "Nuked (pontosabb)" msgid "YMFM (faster)" msgstr "YMFM (gyorsabb)" -msgid "Network type:" -msgstr "Hálózati típusa:" - -msgid "PCap device:" -msgstr "PCap eszköz:" - -msgid "Network adapter:" -msgstr "Hálózati kártya:" - msgid "COM1 Device:" msgstr "COM1 eszköz:" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 028d86f40..75614e309 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -450,15 +450,6 @@ msgstr "Nuked (più accurato)" msgid "YMFM (faster)" msgstr "YMFM (più veloce)" -msgid "Network type:" -msgstr "Tipo di rete:" - -msgid "PCap device:" -msgstr "Dispositivo PCap:" - -msgid "Network adapter:" -msgstr "Scheda di rete:" - msgid "COM1 Device:" msgstr "Dispositivo COM1:" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index e66c8b2c1..7cf3e660e 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -450,15 +450,6 @@ msgstr "Nuked(高精度化)" msgid "YMFM (faster)" msgstr "YMFM(より速く)" -msgid "Network type:" -msgstr "ネットワーク タイプ:" - -msgid "PCap device:" -msgstr "PCapデバイス:" - -msgid "Network adapter:" -msgstr "ネットワークアダプター:" - msgid "COM1 Device:" msgstr "COM1デバイス:" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 61f65ad98..266a4c581 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -450,15 +450,6 @@ msgstr "Nuked (더 정확한)" msgid "YMFM (faster)" msgstr "YMFM (더 빠르게)" -msgid "Network type:" -msgstr "네트워크 종류:" - -msgid "PCap device:" -msgstr "PCap 장치:" - -msgid "Network adapter:" -msgstr "네트워크 어댑터:" - msgid "COM1 Device:" msgstr "COM1 장치:" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 5e0670385..bb2613d4e 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -450,15 +450,6 @@ msgstr "Nuked (nauwkeuriger)" msgid "YMFM (faster)" msgstr "YMFM (sneller)" -msgid "Network type:" -msgstr "Type netwerk:" - -msgid "PCap device:" -msgstr "PCap-apparaat:" - -msgid "Network adapter:" -msgstr "Netwerkadapter:" - msgid "COM1 Device:" msgstr "COM1-apparaat:" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 1a4ddda37..13904e627 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -450,15 +450,6 @@ msgstr "Nuked (dokładniejszy)" msgid "YMFM (faster)" msgstr "YMFM (szybszy)" -msgid "Network type:" -msgstr "Rodzaj sieci:" - -msgid "PCap device:" -msgstr "Urządzenie PCap:" - -msgid "Network adapter:" -msgstr "Karta sieciowa:" - msgid "COM1 Device:" msgstr "Urządzenie COM1:" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index cfc7fa42b..9466d25df 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -450,15 +450,6 @@ msgstr "Nuked (mais preciso)" msgid "YMFM (faster)" msgstr "YMFM (mais rápido)" -msgid "Network type:" -msgstr "Tipo de rede:" - -msgid "PCap device:" -msgstr "Dispositivo PCap:" - -msgid "Network adapter:" -msgstr "Adaptador de rede:" - msgid "COM1 Device:" msgstr "Dispositivo COM1:" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 564932890..8d212b67f 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -450,15 +450,6 @@ msgstr "Nuked (mais exacto)" msgid "YMFM (faster)" msgstr "YMFM (mais rápido)" -msgid "Network type:" -msgstr "Tipo de rede:" - -msgid "PCap device:" -msgstr "Dispositivo PCap:" - -msgid "Network adapter:" -msgstr "Placa de rede:" - msgid "COM1 Device:" msgstr "Dispositivo COM1:" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 3c0eb619a..9795638d0 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -450,15 +450,6 @@ msgstr "Nuked (более точный)" msgid "YMFM (faster)" msgstr "YMFM (быстрее)" -msgid "Network type:" -msgstr "Тип сети:" - -msgid "PCap device:" -msgstr "Устройство PCap:" - -msgid "Network adapter:" -msgstr "Сетевая карта:" - msgid "COM1 Device:" msgstr "Устройство COM1:" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 1121aefb6..c7855d823 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -450,15 +450,6 @@ msgstr "Nuked (presnejší)" msgid "YMFM (faster)" msgstr "YMFM (rýchlejší)" -msgid "Network type:" -msgstr "Druh siete:" - -msgid "PCap device:" -msgstr "PCap zariadenia:" - -msgid "Network adapter:" -msgstr "Sieťový adaptér:" - msgid "COM1 Device:" msgstr "Zariadenie na COM1:" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index e3e8dba95..3e5b35c6a 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -450,15 +450,6 @@ msgstr "Nuked (točnejši)" msgid "YMFM (faster)" msgstr "YMFM (hitrejši)" -msgid "Network type:" -msgstr "Vrsta omrežja:" - -msgid "PCap device:" -msgstr "Naprava PCap:" - -msgid "Network adapter:" -msgstr "Omrežna kartica:" - msgid "COM1 Device:" msgstr "Naprava COM1:" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 2abe174ee..879277f20 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -450,15 +450,6 @@ msgstr "Nuked (daha doğru)" msgid "YMFM (faster)" msgstr "YMFM (daha hızlı)" -msgid "Network type:" -msgstr "Ağ türü:" - -msgid "PCap device:" -msgstr "PCap cihazı:" - -msgid "Network adapter:" -msgstr "Ağ cihazı:" - msgid "COM1 Device:" msgstr "COM1 cihazı:" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 7514e2fff..0cb04da38 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -450,15 +450,6 @@ msgstr "Nuked (більш точний)" msgid "YMFM (faster)" msgstr "YMFM (швидший)" -msgid "Network type:" -msgstr "Тип мережі:" - -msgid "PCap device:" -msgstr "Пристрій PCap:" - -msgid "Network adapter:" -msgstr "Мережевий адаптер:" - msgid "COM1 Device:" msgstr "Пристрій COM1:" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index d05396430..8776ad40d 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -450,15 +450,6 @@ msgstr "Nuked (chính xác hơn)" msgid "YMFM (faster)" msgstr "YMFM (nhanh hơn)" -msgid "Network type:" -msgstr "Kiểu loại mạng:" - -msgid "PCap device:" -msgstr "Thiết bị PCap:" - -msgid "Network adapter:" -msgstr "Bộ thích ứng (adapter) mạng:" - msgid "COM1 Device:" msgstr "Thiết bị COM1:" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 450f148cf..787925f3b 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -450,15 +450,6 @@ msgstr "Nuked (更准确)" msgid "YMFM (faster)" msgstr "YMFM (更快)" -msgid "Network type:" -msgstr "网络类型:" - -msgid "PCap device:" -msgstr "PCap 设备:" - -msgid "Network adapter:" -msgstr "网络适配器:" - msgid "COM1 Device:" msgstr "COM1 设备:" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index c53753d28..6bf3ddd28 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -450,15 +450,6 @@ msgstr "Nuked (更準確)" msgid "YMFM (faster)" msgstr "YMFM (更快)" -msgid "Network type:" -msgstr "網路類型:" - -msgid "PCap device:" -msgstr "PCap 裝置:" - -msgid "Network adapter:" -msgstr "網路配接器:" - msgid "COM1 Device:" msgstr "COM1 裝置:" From ff0889c1a74a3e259ab2c04016713d0054966f03 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 17 Apr 2025 00:34:01 +0500 Subject: [PATCH 0749/1190] languages: Add colons to dropdown labels on the network settings page --- src/qt/languages/86box.pot | 8 ++++---- src/qt/languages/ca-ES.po | 16 ++++++++-------- src/qt/languages/cs-CZ.po | 16 ++++++++-------- src/qt/languages/de-DE.po | 16 ++++++++-------- src/qt/languages/es-ES.po | 16 ++++++++-------- src/qt/languages/fi-FI.po | 16 ++++++++-------- src/qt/languages/fr-FR.po | 16 ++++++++-------- src/qt/languages/hr-HR.po | 16 ++++++++-------- src/qt/languages/hu-HU.po | 16 ++++++++-------- src/qt/languages/it-IT.po | 16 ++++++++-------- src/qt/languages/ja-JP.po | 16 ++++++++-------- src/qt/languages/ko-KR.po | 16 ++++++++-------- src/qt/languages/nl-NL.po | 16 ++++++++-------- src/qt/languages/pl-PL.po | 16 ++++++++-------- src/qt/languages/pt-BR.po | 16 ++++++++-------- src/qt/languages/pt-PT.po | 16 ++++++++-------- src/qt/languages/ru-RU.po | 16 ++++++++-------- src/qt/languages/sk-SK.po | 16 ++++++++-------- src/qt/languages/sl-SI.po | 16 ++++++++-------- src/qt/languages/tr-TR.po | 16 ++++++++-------- src/qt/languages/uk-UA.po | 16 ++++++++-------- src/qt/languages/vi-VN.po | 16 ++++++++-------- src/qt/languages/zh-CN.po | 16 ++++++++-------- src/qt/languages/zh-TW.po | 16 ++++++++-------- 24 files changed, 188 insertions(+), 188 deletions(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 81b639b7d..71dc7572a 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -1341,16 +1341,16 @@ msgstr "" msgid "Network Card #4" msgstr "" -msgid "Mode" +msgid "Mode:" msgstr "" -msgid "Interface" +msgid "Interface:" msgstr "" -msgid "Adapter" +msgid "Adapter:" msgstr "" -msgid "VDE Socket" +msgid "VDE Socket:" msgstr "" msgid "86Box Unit Tester" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 63b9b7a9b..e3bb805a0 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -1341,17 +1341,17 @@ msgstr "Targeta de xarxa 3" msgid "Network Card #4" msgstr "Targeta de xarxa 4" -msgid "Mode" -msgstr "Mode" +msgid "Mode:" +msgstr "Mode:" -msgid "Interface" -msgstr "Interfície" +msgid "Interface:" +msgstr "Interfície:" -msgid "Adapter" -msgstr "Adaptador" +msgid "Adapter:" +msgstr "Adaptador:" -msgid "VDE Socket" -msgstr "Socket de VDE" +msgid "VDE Socket:" +msgstr "Socket de VDE:" msgid "86Box Unit Tester" msgstr "Test de la unitat de 86 Box" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index fd9769479..84c2cb94f 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -1341,17 +1341,17 @@ msgstr "Síťová karta 3" msgid "Network Card #4" msgstr "Síťová karta 4" -msgid "Mode" -msgstr "Režim" +msgid "Mode:" +msgstr "Režim:" -msgid "Interface" -msgstr "Rozhraní" +msgid "Interface:" +msgstr "Rozhraní:" -msgid "Adapter" -msgstr "Adaptér" +msgid "Adapter:" +msgstr "Adaptér:" -msgid "VDE Socket" -msgstr "Zásuvka VDE" +msgid "VDE Socket:" +msgstr "Zásuvka VDE:" msgid "86Box Unit Tester" msgstr "86Box Unit Tester" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index cc734cb8b..588a2b5cd 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1344,17 +1344,17 @@ msgstr "Netzwerkkarte 3" msgid "Network Card #4" msgstr "Netzwerkkarte 4" -msgid "Mode" -msgstr "Modus" +msgid "Mode:" +msgstr "Modus:" -msgid "Interface" -msgstr "Schnittstelle" +msgid "Interface:" +msgstr "Schnittstelle:" -msgid "Adapter" -msgstr "Adapter" +msgid "Adapter:" +msgstr "Adapter:" -msgid "VDE Socket" -msgstr "VDE Port" +msgid "VDE Socket:" +msgstr "VDE Port:" msgid "86Box Unit Tester" msgstr "86Box-Gerätetester" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index cf349cd6d..ac22a4d5c 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -1340,17 +1340,17 @@ msgstr "Tarjeta de red 3" msgid "Network Card #4" msgstr "Tarjeta de red 4" -msgid "Mode" -msgstr "Modalidad" +msgid "Mode:" +msgstr "Modalidad:" -msgid "Interface" -msgstr "Interfaz" +msgid "Interface:" +msgstr "Interfaz:" -msgid "Adapter" -msgstr "Adaptador" +msgid "Adapter:" +msgstr "Adaptador:" -msgid "VDE Socket" -msgstr "Toma VDE" +msgid "VDE Socket:" +msgstr "Toma VDE:" msgid "86Box Unit Tester" msgstr "Comprobador de unidad 86Box" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 3835165c0..8b8ca8374 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -1344,17 +1344,17 @@ msgstr "Verkkokortti 3" msgid "Network Card #4" msgstr "Verkkokortti 4" -msgid "Mode" -msgstr "Tila" +msgid "Mode:" +msgstr "Tila:" -msgid "Interface" -msgstr "Liitäntä" +msgid "Interface:" +msgstr "Liitäntä:" -msgid "Adapter" -msgstr "Sovitin" +msgid "Adapter:" +msgstr "Sovitin:" -msgid "VDE Socket" -msgstr "VDE-pistorasia" +msgid "VDE Socket:" +msgstr "VDE-pistorasia:" msgid "86Box Unit Tester" msgstr "86Box Unit Tester" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 8c53a7264..cc2d8c310 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -1341,17 +1341,17 @@ msgstr "Carte réseau 3" msgid "Network Card #4" msgstr "Carte réseau 4" -msgid "Mode" -msgstr "Mode" +msgid "Mode:" +msgstr "Mode:" -msgid "Interface" -msgstr "Interface" +msgid "Interface:" +msgstr "Interface:" -msgid "Adapter" -msgstr "Adaptateur" +msgid "Adapter:" +msgstr "Adaptateur:" -msgid "VDE Socket" -msgstr "Prise VDE" +msgid "VDE Socket:" +msgstr "Prise VDE:" msgid "86Box Unit Tester" msgstr "Testeur d'unité de 86Box" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index f55ad7f53..d074401a2 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -1341,17 +1341,17 @@ msgstr "Mrežna kartica 3" msgid "Network Card #4" msgstr "Mrežna kartica 4" -msgid "Mode" -msgstr "Način" +msgid "Mode:" +msgstr "Način:" -msgid "Interface" -msgstr "Sučelje" +msgid "Interface:" +msgstr "Sučelje:" -msgid "Adapter" -msgstr "Adapter" +msgid "Adapter:" +msgstr "Adapter:" -msgid "VDE Socket" -msgstr "VDE utičnica" +msgid "VDE Socket:" +msgstr "VDE utičnica:" msgid "86Box Unit Tester" msgstr "Jedinični ispitivač 86Box-a" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 009b6345e..841ed5e81 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -1341,17 +1341,17 @@ msgstr "Hálózati kártya 3" msgid "Network Card #4" msgstr "Hálózati kártya 4" -msgid "Mode" -msgstr "Mód" +msgid "Mode:" +msgstr "Mód:" -msgid "Interface" -msgstr "Interfész" +msgid "Interface:" +msgstr "Interfész:" -msgid "Adapter" -msgstr "Adapter" +msgid "Adapter:" +msgstr "Adapter:" -msgid "VDE Socket" -msgstr "VDE aljzat" +msgid "VDE Socket:" +msgstr "VDE aljzat:" msgid "86Box Unit Tester" msgstr "86Box Unit Tester" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 75614e309..8de67d28b 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -1341,17 +1341,17 @@ msgstr "Scheda di rete n. 3" msgid "Network Card #4" msgstr "Scheda di rete n. 4" -msgid "Mode" -msgstr "Modalità" +msgid "Mode:" +msgstr "Modalità:" -msgid "Interface" -msgstr "Interfaccia" +msgid "Interface:" +msgstr "Interfaccia:" -msgid "Adapter" -msgstr "Adattatore" +msgid "Adapter:" +msgstr "Adattatore:" -msgid "VDE Socket" -msgstr "Presa VDE" +msgid "VDE Socket:" +msgstr "Presa VDE:" msgid "86Box Unit Tester" msgstr "Tester di unità 86Box" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 7cf3e660e..6add03617 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -1341,17 +1341,17 @@ msgstr "ネットワークカード 3" msgid "Network Card #4" msgstr "ネットワークカード 4" -msgid "Mode" -msgstr "モード" +msgid "Mode:" +msgstr "モード:" -msgid "Interface" -msgstr "インターフェース" +msgid "Interface:" +msgstr "インターフェース:" -msgid "Adapter" -msgstr "アダプター" +msgid "Adapter:" +msgstr "アダプター:" -msgid "VDE Socket" -msgstr "VDEソケット" +msgid "VDE Socket:" +msgstr "VDEソケット:" msgid "86Box Unit Tester" msgstr "86Boxユニットテスター" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 266a4c581..f32a23ec4 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -1341,17 +1341,17 @@ msgstr "네트워크 카드 3" msgid "Network Card #4" msgstr "네트워크 카드 4" -msgid "Mode" -msgstr "모드" +msgid "Mode:" +msgstr "모드:" -msgid "Interface" -msgstr "인터페이스" +msgid "Interface:" +msgstr "인터페이스:" -msgid "Adapter" -msgstr "어댑터" +msgid "Adapter:" +msgstr "어댑터:" -msgid "VDE Socket" -msgstr "VDE 소켓" +msgid "VDE Socket:" +msgstr "VDE 소켓:" msgid "86Box Unit Tester" msgstr "86Box 유닛 테스터" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index bb2613d4e..f1b4eed91 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -1341,17 +1341,17 @@ msgstr "Netwerkkaart #3" msgid "Network Card #4" msgstr "Netwerkkaart #4" -msgid "Mode" -msgstr "Modus" +msgid "Mode:" +msgstr "Modus:" -msgid "Interface" -msgstr "Interface" +msgid "Interface:" +msgstr "Interface:" -msgid "Adapter" -msgstr "Adapter" +msgid "Adapter:" +msgstr "Adapter:" -msgid "VDE Socket" -msgstr "VDE-socket" +msgid "VDE Socket:" +msgstr "VDE-socket:" msgid "86Box Unit Tester" msgstr "86Box apparaattester" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 13904e627..1ad5dcf88 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -1341,17 +1341,17 @@ msgstr "Karta sieciowa 3" msgid "Network Card #4" msgstr "Karta sieciowa 4" -msgid "Mode" -msgstr "Tryb" +msgid "Mode:" +msgstr "Tryb:" -msgid "Interface" -msgstr "Interfejs" +msgid "Interface:" +msgstr "Interfejs:" -msgid "Adapter" -msgstr "Adapter" +msgid "Adapter:" +msgstr "Adapter:" -msgid "VDE Socket" -msgstr "Gniazdo VDE" +msgid "VDE Socket:" +msgstr "Gniazdo VDE:" msgid "86Box Unit Tester" msgstr "Tester urządzeń 86Box" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 9466d25df..3eead12fe 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -1341,17 +1341,17 @@ msgstr "Placa de rede 3" msgid "Network Card #4" msgstr "Placa de rede 4" -msgid "Mode" -msgstr "Modo" +msgid "Mode:" +msgstr "Modo:" -msgid "Interface" -msgstr "Interface" +msgid "Interface:" +msgstr "Interface:" -msgid "Adapter" -msgstr "Adaptador" +msgid "Adapter:" +msgstr "Adaptador:" -msgid "VDE Socket" -msgstr "Soquete VDE" +msgid "VDE Socket:" +msgstr "Soquete VDE:" msgid "86Box Unit Tester" msgstr "Testador de unidade 86Box" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 8d212b67f..1ffcf0c3b 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -1341,17 +1341,17 @@ msgstr "Placa de rede 3" msgid "Network Card #4" msgstr "Placa de rede 4" -msgid "Mode" -msgstr "Modo" +msgid "Mode:" +msgstr "Modo:" -msgid "Interface" -msgstr "Interface" +msgid "Interface:" +msgstr "Interface:" -msgid "Adapter" -msgstr "Adaptador" +msgid "Adapter:" +msgstr "Adaptador:" -msgid "VDE Socket" -msgstr "Tomada VDE" +msgid "VDE Socket:" +msgstr "Tomada VDE:" msgid "86Box Unit Tester" msgstr "Testador de unidades 86Box" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 9795638d0..f1c250a51 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1341,17 +1341,17 @@ msgstr "Сетевая карта 3" msgid "Network Card #4" msgstr "Сетевая карта 4" -msgid "Mode" -msgstr "Режим" +msgid "Mode:" +msgstr "Режим:" -msgid "Interface" -msgstr "Интерфейс" +msgid "Interface:" +msgstr "Интерфейс:" -msgid "Adapter" -msgstr "Адаптер" +msgid "Adapter:" +msgstr "Адаптер:" -msgid "VDE Socket" -msgstr "VDE сокет" +msgid "VDE Socket:" +msgstr "VDE сокет:" msgid "86Box Unit Tester" msgstr "Модульный Тестер 86Box" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index c7855d823..9ce9abc2f 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -1342,17 +1342,17 @@ msgstr "Sieťová karta 3" msgid "Network Card #4" msgstr "Sieťová karta 4" -msgid "Mode" -msgstr "Režim" +msgid "Mode:" +msgstr "Režim:" -msgid "Interface" -msgstr "Rozhranie" +msgid "Interface:" +msgstr "Rozhranie:" -msgid "Adapter" -msgstr "Adaptér" +msgid "Adapter:" +msgstr "Adaptér:" -msgid "VDE Socket" -msgstr "Zásuvka VDE" +msgid "VDE Socket:" +msgstr "Zásuvka VDE:" msgid "86Box Unit Tester" msgstr "86Box Unit Tester" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 3e5b35c6a..af5fd1fc1 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -1341,17 +1341,17 @@ msgstr "Omrežna kartica 3" msgid "Network Card #4" msgstr "Omrežna kartica 4" -msgid "Mode" -msgstr "Način" +msgid "Mode:" +msgstr "Način:" -msgid "Interface" -msgstr "Vmesnik" +msgid "Interface:" +msgstr "Vmesnik:" -msgid "Adapter" -msgstr "Adapter" +msgid "Adapter:" +msgstr "Adapter:" -msgid "VDE Socket" -msgstr "Vtičnica VDE" +msgid "VDE Socket:" +msgstr "Vtičnica VDE:" msgid "86Box Unit Tester" msgstr "Tester enote 86Box" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 879277f20..d3c1871e9 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -1341,17 +1341,17 @@ msgstr "Ağ kartı 3" msgid "Network Card #4" msgstr "Ağ kartı 4" -msgid "Mode" -msgstr "Mod" +msgid "Mode:" +msgstr "Mod:" -msgid "Interface" -msgstr "Arayüz" +msgid "Interface:" +msgstr "Arayüz:" -msgid "Adapter" -msgstr "Adaptör" +msgid "Adapter:" +msgstr "Adaptör:" -msgid "VDE Socket" -msgstr "VDE soketi" +msgid "VDE Socket:" +msgstr "VDE soketi:" msgid "86Box Unit Tester" msgstr "86Box birim test cihazı" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 0cb04da38..d4b4c7847 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -1341,17 +1341,17 @@ msgstr "Мережева карта 3" msgid "Network Card #4" msgstr "Мережева карта 4" -msgid "Mode" -msgstr "Режим" +msgid "Mode:" +msgstr "Режим:" -msgid "Interface" -msgstr "Інтерфейс" +msgid "Interface:" +msgstr "Інтерфейс:" -msgid "Adapter" -msgstr "Адаптер" +msgid "Adapter:" +msgstr "Адаптер:" -msgid "VDE Socket" -msgstr "VDE сокет" +msgid "VDE Socket:" +msgstr "VDE сокет:" msgid "86Box Unit Tester" msgstr "Тестер блоків 86Box" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 8776ad40d..9dcbf01ca 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -1341,17 +1341,17 @@ msgstr "Thẻ mạng 3" msgid "Network Card #4" msgstr "Thẻ mạng 4" -msgid "Mode" -msgstr "Chế độ" +msgid "Mode:" +msgstr "Chế độ:" -msgid "Interface" -msgstr "Giao diện" +msgid "Interface:" +msgstr "Giao diện:" -msgid "Adapter" -msgstr "Bộ chuyển đổi" +msgid "Adapter:" +msgstr "Bộ chuyển đổi:" -msgid "VDE Socket" -msgstr "Ổ cắm VDE" +msgid "VDE Socket:" +msgstr "Ổ cắm VDE:" msgid "86Box Unit Tester" msgstr "Trình kiểm tra đơn vị 86box" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 787925f3b..041b7bb6b 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1341,17 +1341,17 @@ msgstr "网卡 3" msgid "Network Card #4" msgstr "网卡 4" -msgid "Mode" -msgstr "模式" +msgid "Mode:" +msgstr "模式:" -msgid "Interface" -msgstr "界面" +msgid "Interface:" +msgstr "界面:" -msgid "Adapter" -msgstr "适配器" +msgid "Adapter:" +msgstr "适配器:" -msgid "VDE Socket" -msgstr "VDE 套接字" +msgid "VDE Socket:" +msgstr "VDE 套接字:" msgid "86Box Unit Tester" msgstr "86Box 装置测试仪" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 6bf3ddd28..c3e3fb4d5 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -1341,17 +1341,17 @@ msgstr "網路卡 3" msgid "Network Card #4" msgstr "網路卡 4" -msgid "Mode" -msgstr "模式" +msgid "Mode:" +msgstr "模式:" -msgid "Interface" -msgstr "介面" +msgid "Interface:" +msgstr "介面:" -msgid "Adapter" -msgstr "配接器" +msgid "Adapter:" +msgstr "配接器:" -msgid "VDE Socket" -msgstr "VDE 插座" +msgid "VDE Socket:" +msgstr "VDE 插座:" msgid "86Box Unit Tester" msgstr "86Box 單元測試器" From 0559d803a7cb7c3d86513c93e7055b559483ea34 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 17 Apr 2025 11:03:41 +0500 Subject: [PATCH 0750/1190] languages: update the Russian translation Co-Authored-by: usergithub64 <58270614+usergithub64@users.noreply.github.com> --- src/qt/languages/ru-RU.po | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index f1c250a51..42ad1716c 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -55,7 +55,7 @@ msgid "Qt (&OpenGL)" msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" -msgstr "Open&GL (3.0)" +msgstr "Open&GL (3.0 Core)" msgid "&VNC" msgstr "&VNC" @@ -214,7 +214,7 @@ msgid "&Documentation..." msgstr "&Документация..." msgid "&About 86Box..." -msgstr "&О программе 86Box..." +msgstr "&О 86Box..." msgid "&New image..." msgstr "&Новый образ..." @@ -253,7 +253,7 @@ msgid "E&mpty" msgstr "П&устой" msgid "Reload previous image" -msgstr "Загрузить предыдущий образ" +msgstr "Перезагрузить предыдущий образ" msgid "&Folder..." msgstr "&Папка..." @@ -430,10 +430,10 @@ msgid "Sound card #4:" msgstr "Звуковая карта 4:" msgid "MIDI Out Device:" -msgstr "MIDI Out устройство:" +msgstr "Устройство вывода MIDI:" msgid "MIDI In Device:" -msgstr "MIDI In устройство:" +msgstr "Устройство ввода MIDI:" msgid "Standalone MPU-401" msgstr "Отдельный MPU-401" @@ -1435,7 +1435,7 @@ msgid "BIOS Revision" msgstr "Версия BIOS" msgid "Translate 26 -> 17" -msgstr "Перевести 26 -> 17" +msgstr "Переводить 26 -> 17" msgid "Language" msgstr "Язык" @@ -1531,7 +1531,7 @@ msgid "Reversed stereo" msgstr "Реверс стерео" msgid "Nice ramp" -msgstr "Nice ramp" +msgstr "Улучшение рампы" msgid "Hz" msgstr "Гц" @@ -1582,7 +1582,7 @@ msgid "RAM Address" msgstr "Адрес оперативной памяти" msgid "RAM size" -msgstr "Объем оперативной памяти" +msgstr "Размер оперативной памяти" msgid "Initial RAM size" msgstr "Начальный размер оперативной памяти" @@ -1615,10 +1615,10 @@ msgid "Surround module" msgstr "Модуль объемного звучания" msgid "CODEC" -msgstr "КОДЕК" +msgstr "Кодек" msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)" -msgstr "Поднимать прерывание CODEC при настройке CODEC (необходимо некоторым драйверам)." +msgstr "Поднимать прерывание кодека при настройке кодека (необходимо некоторым драйверам)." msgid "SB Address" msgstr "Адрес SB" @@ -1645,7 +1645,7 @@ msgid "Enable CMS" msgstr "Включить CMS" msgid "Mixer" -msgstr "Смеситель" +msgstr "Микшер" msgid "High DMA" msgstr "Высокий DMA" @@ -1654,7 +1654,7 @@ msgid "Control PC speaker" msgstr "Управление динамиком ПК" msgid "Memory size" -msgstr "Объем памяти" +msgstr "Размер памяти" msgid "EMU8000 Address" msgstr "Адрес EMU8000" @@ -1669,7 +1669,7 @@ msgid "GUS type" msgstr "Тип GUS" msgid "Enable 0x04 \"Exit 86Box\" command" -msgstr "Включить команду 0x04 \"Выход 86Box\"." +msgstr "Включить команду 0x04 \"Выход из 86Box\"" msgid "Display type" msgstr "Тип дисплея" @@ -1711,13 +1711,13 @@ msgid "Bilinear filtering" msgstr "Билинейная фильтрация" msgid "Dithering" -msgstr "Dithering" +msgstr "Дизеринг" msgid "Enable NMI for CGA emulation" msgstr "Включение NMI для эмуляции CGA" msgid "Voodoo type" -msgstr "Тип Вуду" +msgstr "Тип Voodoo" msgid "Framebuffer memory size" msgstr "Размер памяти фреймбуфера" @@ -1726,10 +1726,10 @@ msgid "Texture memory size" msgstr "Размер памяти текстур" msgid "Dither subtraction" -msgstr "Вычитание с вычитанием" +msgstr "Вычитание дизеринга" msgid "Screen Filter" -msgstr "Фильтр экрана" +msgstr "Экранный фильтр" msgid "Render threads" msgstr "Потоки рендеринга" @@ -1912,7 +1912,7 @@ msgid "Monochrome (5151/MDA) (white)" msgstr "Монохромный (5151/MDA) (белый)" msgid "Monochrome (5151/MDA) (green)" -msgstr "Монохромный (5151/MDA) (зеленый)" +msgstr "Монохромный (5151/MDA) (зелёный)" msgid "Monochrome (5151/MDA) (amber)" msgstr "Монохромный (5151/MDA) (янтарный)" @@ -1930,7 +1930,7 @@ msgid "Enhanced Color - Enhanced Mode (5154/ECD)" msgstr "Улучшенный цветной - улучшенный режим (5154/ECD)" msgid "Green" -msgstr "Зеленый" +msgstr "Зелёный" msgid "Amber" msgstr "Янтарный" @@ -1954,13 +1954,13 @@ msgid "Bochs latest" msgstr "Bochs последний" msgid "Mono Non-Interlaced" -msgstr "Монохромный без чересстрочной развертки" +msgstr "Монохромный без чересстрочной развёртки" msgid "Color Interlaced" -msgstr "Цветной с чересстрочной разверткой" +msgstr "Цветной с чересстрочной развёрткой" msgid "Color Non-Interlaced" -msgstr "Цветной без чересстрочной развертки" +msgstr "Цветной без чересстрочной развёртки" msgid "3Dfx Voodoo Graphics" msgstr "Ускоритель 3Dfx Voodoo" @@ -2011,10 +2011,10 @@ msgid "Protection Dongle for Savage Quest" msgstr "Защитный донгл для Savage Quest" msgid "Serial Passthrough Device" -msgstr "Устройство прохода через последовательный порт" +msgstr "Устройство проброса через последовательный порт" msgid "Passthrough Mode" -msgstr "Проходной режим" +msgstr "Режим проброса" msgid "Host Serial Device" msgstr "Последовательное устройство хоста" @@ -2101,16 +2101,16 @@ msgid "Inhibit multimedia keys" msgstr "Перехватывать мультимедиа-клавиши" msgid "Ask for confirmation before saving settings" -msgstr "Спрашивать подтверждения перед сохранением настроек" +msgstr "Запрашивать подтверждение перед сохранением настроек" msgid "Ask for confirmation before hard resetting" -msgstr "Спрашивать подтверждения перед холодной перезагрузкой" +msgstr "Запрашивать подтверждение перед холодной перезагрузкой" msgid "Ask for confirmation before quitting" -msgstr "Спрашивать подтвержждения перед выходом" +msgstr "Запрашивать подтверждение перед выходом" msgid "Display hotkey message when entering full-screen mode" -msgstr "Показывать сообщение о горячих клавишах при включении полноэкранного режима" +msgstr "Показывать сообщение о горячей клавише при входе в полноэкранный режим" msgid "Options" msgstr "Параметры" From ed4820b798482a5de53ac82971404a00fd8cf197 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 17 Apr 2025 11:08:04 +0500 Subject: [PATCH 0751/1190] languages: Add string for the 5-button 2-wheel mouse --- src/qt/languages/86box.pot | 3 +++ src/qt/languages/ca-ES.po | 3 +++ src/qt/languages/cs-CZ.po | 3 +++ src/qt/languages/de-DE.po | 3 +++ src/qt/languages/es-ES.po | 3 +++ src/qt/languages/fi-FI.po | 3 +++ src/qt/languages/fr-FR.po | 3 +++ src/qt/languages/hr-HR.po | 3 +++ src/qt/languages/hu-HU.po | 3 +++ src/qt/languages/it-IT.po | 3 +++ src/qt/languages/ja-JP.po | 3 +++ src/qt/languages/ko-KR.po | 3 +++ src/qt/languages/nl-NL.po | 3 +++ src/qt/languages/pl-PL.po | 5 ++++- src/qt/languages/pt-BR.po | 3 +++ src/qt/languages/pt-PT.po | 3 +++ src/qt/languages/ru-RU.po | 3 +++ src/qt/languages/sk-SK.po | 3 +++ src/qt/languages/sl-SI.po | 3 +++ src/qt/languages/tr-TR.po | 3 +++ src/qt/languages/uk-UA.po | 3 +++ src/qt/languages/vi-VN.po | 3 +++ src/qt/languages/zh-CN.po | 3 +++ src/qt/languages/zh-TW.po | 3 +++ 24 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 71dc7572a..6e6dd3fc3 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -1809,6 +1809,9 @@ msgstr "" msgid "Five + Wheel" msgstr "" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index e3bb805a0..847cc0138 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -1809,6 +1809,9 @@ msgstr "Roda" msgid "Five + Wheel" msgstr "Cinc + roda" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 sèrie / SMT3(R)V" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 84c2cb94f..ea492f0b6 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -1809,6 +1809,9 @@ msgstr "Kolečko" msgid "Five + Wheel" msgstr "Pět + kolečko" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 sériová / SMT3(R)V" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 588a2b5cd..95d1b0249 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1812,6 +1812,9 @@ msgstr "Rad" msgid "Five + Wheel" msgstr "Fünf + Rad" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Seriell / SMT3(R)V" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index ac22a4d5c..57474ae53 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -1808,6 +1808,9 @@ msgstr "Rueda" msgid "Five + Wheel" msgstr "Cinco + rueda" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 serie / SMT3(R)V" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 8b8ca8374..187a423f6 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -1812,6 +1812,9 @@ msgstr "Pyörä" msgid "Five + Wheel" msgstr "Viisi + pyörä" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 sarja / SMT3(R)V" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index cc2d8c310..8456baf2f 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -1809,6 +1809,9 @@ msgstr "Molette" msgid "Five + Wheel" msgstr "Cinq + molette" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 série / SMT3(R)V" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index d074401a2..0fd342f88 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -1809,6 +1809,9 @@ msgstr "Kotač" msgid "Five + Wheel" msgstr "Pet + kotač" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 serijski / SMT3(R)V" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 841ed5e81..cbb753890 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -1809,6 +1809,9 @@ msgstr "Kerék" msgid "Five + Wheel" msgstr "Öt + kerék" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 soros / SMT3(R)V" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index 8de67d28b..c505b9eaa 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -1809,6 +1809,9 @@ msgstr "Ruota" msgid "Five + Wheel" msgstr "Cinque + ruota" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 seriale / SMT3(R)V" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 6add03617..cff667239 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -1809,6 +1809,9 @@ msgstr "ホイール" msgid "Five + Wheel" msgstr "五つ+ホイール" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 シリアル / SMT3(R)V" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index f32a23ec4..55f47be27 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -1809,6 +1809,9 @@ msgstr "휠" msgid "Five + Wheel" msgstr "5개 + 휠" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 직렬/SMT3(R)V" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index f1b4eed91..e854ea3f3 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -1809,6 +1809,9 @@ msgstr "Wiel" msgid "Five + Wheel" msgstr "Vijf + Wiel" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serieel / SMT3(R)V" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 1ad5dcf88..3fc731e5f 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -1807,7 +1807,10 @@ msgid "Wheel" msgstr "Koło" msgid "Five + Wheel" -msgstr "Five + Wheel" +msgstr "" + +msgid "Five + 2 Wheels" +msgstr "" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 szeregowa / SMT3(R)V" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 3eead12fe..02abe2321 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -1809,6 +1809,9 @@ msgstr "Roda" msgid "Five + Wheel" msgstr "Cinco + roda" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serial / SMT3(R)V" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 1ffcf0c3b..42550a266 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -1809,6 +1809,9 @@ msgstr "Roda" msgid "Five + Wheel" msgstr "Cinco + Roda" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 série / SMT3(R)V" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 42ad1716c..dde5387a7 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1809,6 +1809,9 @@ msgstr "Колесо" msgid "Five + Wheel" msgstr "Пять + колесо" +msgid "Five + 2 Wheels" +msgstr "Пять + 2 колеса" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 последовательная / SMT3(R)V" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 9ce9abc2f..6039adedc 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -1810,6 +1810,9 @@ msgstr "Koleso" msgid "Five + Wheel" msgstr "Päť + koleso" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 sériová / SMT3(R)V" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index af5fd1fc1..b6641f8a1 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -1809,6 +1809,9 @@ msgstr "Kolesa" msgid "Five + Wheel" msgstr "Pet + kolo" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 serijska / SMT3(R)V" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index d3c1871e9..e9a42a896 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -1809,6 +1809,9 @@ msgstr "Tekerlek" msgid "Five + Wheel" msgstr "Beş + tekerlek" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 seri / SMT3(R)V" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index d4b4c7847..bceb7bea5 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -1809,6 +1809,9 @@ msgstr "Колесо" msgid "Five + Wheel" msgstr "П'ять + колесо" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 послідовна / SMT3(R)V" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 9dcbf01ca..e14386bf8 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -1809,6 +1809,9 @@ msgstr "Con lăn" msgid "Five + Wheel" msgstr "Năm + con lăn" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serial / SMT3(R)V" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 041b7bb6b..9f6cc0328 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1809,6 +1809,9 @@ msgstr "滚轮" msgid "Five + Wheel" msgstr "五键+滚轮" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 串行 / SMT3(R)V" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index c3e3fb4d5..aefa89d5f 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -1809,6 +1809,9 @@ msgstr "滾輪" msgid "Five + Wheel" msgstr "五鍵 + 滾輪" +msgid "Five + 2 Wheels" +msgstr "" + msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 序列 / SMT3(R)V" From 48903bb48ecd8ea842e6395efec18158571717be Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 18 Apr 2025 03:32:16 +0500 Subject: [PATCH 0752/1190] qt: Add Swedish translation Contributed by toshineon on Discord --- src/qt/languages/sv-SE.po | 2164 +++++++++++++++++++++++++++++++++ src/qt/qt_progsettings.cpp | 1 + src/qt/qt_translations.qrc.in | 1 + 3 files changed, 2166 insertions(+) create mode 100644 src/qt/languages/sv-SE.po diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po new file mode 100644 index 000000000..a47997225 --- /dev/null +++ b/src/qt/languages/sv-SE.po @@ -0,0 +1,2164 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: sv_SE\n" +"X-Source-Language: en_US\n" + +msgid "&Action" +msgstr "" + +msgid "&Keyboard requires capture" +msgstr "Tangentbord behöver uppfångas" + +msgid "&Right CTRL is left ALT" +msgstr "&Höger CTRL är vänster ALT" + +msgid "&Hard Reset..." +msgstr "&Hård omstart..." + +msgid "&Ctrl+Alt+Del" +msgstr "&Ctrl+Alt+Del" + +msgid "Ctrl+Alt+&Esc" +msgstr "Ctrl+Alt+&Esc" + +msgid "&Pause" +msgstr "&Pausa" + +msgid "E&xit..." +msgstr "A&vsluta..." + +msgid "&View" +msgstr "&Visa" + +msgid "&Hide status bar" +msgstr "&Dölj statusfältet" + +msgid "Hide &toolbar" +msgstr "Dölj &verktygsfältet" + +msgid "&Resizeable window" +msgstr "&Ändringsbar fönsterstorlek" + +msgid "R&emember size && position" +msgstr "K&om ihåg storlek && position" + +msgid "Re&nderer" +msgstr "Re&nderare" + +msgid "&Qt (Software)" +msgstr "&Qt (Mjukvara)" + +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" + +msgid "Open&GL (3.0 Core)" +msgstr "Open&GL (3.0 Core)" + +msgid "&VNC" +msgstr "&VNC" + +msgid "Specify dimensions..." +msgstr "Ange mått..." + +msgid "F&orce 4:3 display ratio" +msgstr "T&vinga 4:3 bildförhållande" + +msgid "&Window scale factor" +msgstr "&Skalningsfaktor för fönster" + +msgid "&0.5x" +msgstr "&0.5x" + +msgid "&1x" +msgstr "&1x" + +msgid "1.&5x" +msgstr "1.&5x" + +msgid "&2x" +msgstr "&2x" + +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + +msgid "Filter method" +msgstr "Filtermetod" + +msgid "&Nearest" +msgstr "&Närmsta" + +msgid "&Linear" +msgstr "&Linjär" + +msgid "Hi&DPI scaling" +msgstr "Hög&DPI-skalning" + +msgid "&Fullscreen" +msgstr "&Helskärm" + +msgid "Fullscreen &stretch mode" +msgstr "Sträckningsläge för &helskärm" + +msgid "&Full screen stretch" +msgstr "&Sträck till helskärm" + +msgid "&4:3" +msgstr "&4:3" + +msgid "&Square pixels (Keep ratio)" +msgstr "&Fyrkantiga pixlar (Behåll bildförhållande)" + +msgid "&Integer scale" +msgstr "&Skala till heltal" + +msgid "4:&3 Integer scale" +msgstr "Skala till heltal i 4:&3" + +msgid "E&GA/(S)VGA settings" +msgstr "E&GA/(S)VGA-inställningar" + +msgid "&Inverted VGA monitor" +msgstr "&Inverterad VGA-skärm" + +msgid "VGA screen &type" +msgstr "Skärmtyp för &VGA" + +msgid "RGB &Color" +msgstr "RGB &färg" + +msgid "&RGB Grayscale" +msgstr "&RGB gråskala" + +msgid "&Amber monitor" +msgstr "&Bärnstensfärgad skärm" + +msgid "&Green monitor" +msgstr "&Grön skärm" + +msgid "&White monitor" +msgstr "&Vit skärm" + +msgid "Grayscale &conversion type" +msgstr "Konverteringstyp till &gråskala" + +msgid "BT&601 (NTSC/PAL)" +msgstr "BT&601 (NTSC/PAL)" + +msgid "BT&709 (HDTV)" +msgstr "BT&709 (HDTV)" + +msgid "&Average" +msgstr "&Genomsnittlig" + +msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgstr "CGA/PCjr/Tandy/E&GA/(S)VGA överskanning" + +msgid "Change contrast for &monochrome display" +msgstr "Ändra kontrast för &svartvita skärmar" + +msgid "&Media" +msgstr "&Media" + +msgid "&Tools" +msgstr "&Verktyg" + +msgid "&Settings..." +msgstr "&Inställningar..." + +msgid "&Update status bar icons" +msgstr "&Uppdatera statusfältets ikoner" + +msgid "Take s&creenshot" +msgstr "Tag s&kärmbild" + +msgid "S&ound" +msgstr "L&jud" + +msgid "&Preferences..." +msgstr "&Preferenser..." + +msgid "Enable &Discord integration" +msgstr "Aktivera &integration med Discord" + +msgid "Sound &gain..." +msgstr "Ljud&förstärkning..." + +msgid "Begin trace" +msgstr "Börja spårning" + +msgid "End trace" +msgstr "Avsluta spårning" + +msgid "&Help" +msgstr "&Hjälp" + +msgid "&Documentation..." +msgstr "&Dokumentation..." + +msgid "&About 86Box..." +msgstr "&Om 86Box..." + +msgid "&New image..." +msgstr "&Ny avbildning..." + +msgid "&Existing image..." +msgstr "&Befintlig avbildning..." + +msgid "Existing image (&Write-protected)..." +msgstr "Befintlig avbildning (&skrivskyddad)..." + +msgid "&Record" +msgstr "&Spela in" + +msgid "&Play" +msgstr "&Spela upp" + +msgid "&Rewind to the beginning" +msgstr "&Spola tillbaka till början" + +msgid "&Fast forward to the end" +msgstr "&Spola fram till slutet" + +msgid "E&ject" +msgstr "M&ata ut" + +msgid "&Image..." +msgstr "&Avbildning..." + +msgid "E&xport to 86F..." +msgstr "E&xportera till 86F..." + +msgid "&Mute" +msgstr "&Tysta" + +msgid "E&mpty" +msgstr "T&om" + +msgid "Reload previous image" +msgstr "Ladda om föregående avbildning" + +msgid "&Folder..." +msgstr "&Mapp..." + +msgid "Target &framerate" +msgstr "Mål för &bildhastighet" + +msgid "&Sync with video" +msgstr "&Synkronisera med bild" + +msgid "&25 fps" +msgstr "&25 fps" + +msgid "&30 fps" +msgstr "&30 fps" + +msgid "&50 fps" +msgstr "&50 fps" + +msgid "&60 fps" +msgstr "&60 fps" + +msgid "&75 fps" +msgstr "&75 fps" + +msgid "&VSync" +msgstr "&VSync" + +msgid "&Select shader..." +msgstr "&Välj shader..." + +msgid "&Remove shader" +msgstr "&Ta bort shader" + +msgid "Preferences" +msgstr "Preferenser" + +msgid "Sound Gain" +msgstr "Ljudförstärkning" + +msgid "New Image" +msgstr "Ny avbildning" + +msgid "Settings" +msgstr "Inställningar" + +msgid "Specify Main Window Dimensions" +msgstr "Ange mått för huvudfönster" + +msgid "OK" +msgstr "Okej" + +msgid "Cancel" +msgstr "Avbryt" + +msgid "&Default" +msgstr "&Standard" + +msgid "Language:" +msgstr "Språk:" + +msgid "Gain" +msgstr "Förstärkning" + +msgid "File name:" +msgstr "Filnamn:" + +msgid "Disk size:" +msgstr "Storlek på disk:" + +msgid "RPM mode:" +msgstr "Varvtalsläge:" + +msgid "Progress:" +msgstr "Framsteg:" + +msgid "Width:" +msgstr "Bredd:" + +msgid "Height:" +msgstr "Höjd:" + +msgid "Lock to this size" +msgstr "Lås till denna storlek" + +msgid "Machine type:" +msgstr "Maskintyp:" + +msgid "Machine:" +msgstr "Maskin:" + +msgid "Configure" +msgstr "Konfigurera" + +msgid "CPU type:" +msgstr "Processortyp:" + +msgid "Speed:" +msgstr "Hastighet:" + +msgid "Frequency:" +msgstr "Frekvens:" + +msgid "FPU:" +msgstr "Flyttalsprocessor:" + +msgid "Wait states:" +msgstr "Väntcykler:" + +msgid "MB" +msgstr "MB" + +msgid "Memory:" +msgstr "Minne:" + +msgid "Time synchronization" +msgstr "Synkronisera tid" + +msgid "Disabled" +msgstr "Inaktiverad" + +msgid "Enabled (local time)" +msgstr "Aktiverad (lokal tid)" + +msgid "Enabled (UTC)" +msgstr "Aktiverad (UTC)" + +msgid "Dynamic Recompiler" +msgstr "Dynamisk omkompilering" + +msgid "Video:" +msgstr "Bildskärmskort:" + +msgid "Video #2:" +msgstr "Bildskärmskort #2:" + +msgid "Voodoo 1 or 2 Graphics" +msgstr "Voodoo 1 eller 2-grafik" + +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A-grafik" + +msgid "XGA Graphics" +msgstr "XGA-grafik" + +msgid "Mouse:" +msgstr "Mus:" + +msgid "Joystick:" +msgstr "Styrspak:" + +msgid "Joystick 1..." +msgstr "Styrspak 1..." + +msgid "Joystick 2..." +msgstr "Styrspak 2..." + +msgid "Joystick 3..." +msgstr "Styrspak 3..." + +msgid "Joystick 4..." +msgstr "Styrspak 4..." + +msgid "Sound card #1:" +msgstr "Ljudkort #1:" + +msgid "Sound card #2:" +msgstr "Ljudkort #2:" + +msgid "Sound card #3:" +msgstr "Ljudkort #3:" + +msgid "Sound card #4:" +msgstr "Ljudkort #4:" + +msgid "MIDI Out Device:" +msgstr "Enhet för MIDI-utdata:" + +msgid "MIDI In Device:" +msgstr "Enhet för MIDI-indata:" + +msgid "Standalone MPU-401" +msgstr "Fristående MPU-401" + +msgid "Use FLOAT32 sound" +msgstr "Använd FLOAT32-ljud" + +msgid "FM synth driver" +msgstr "Drivrutin för FM-synt" + +msgid "Nuked (more accurate)" +msgstr "Nuked (mer exakt)" + +msgid "YMFM (faster)" +msgstr "YMFM (snabbare)" + +msgid "COM1 Device:" +msgstr "COM1-enhet:" + +msgid "COM2 Device:" +msgstr "COM2-enhet:" + +msgid "COM3 Device:" +msgstr "COM3-enhet:" + +msgid "COM4 Device:" +msgstr "COM4-enhet:" + +msgid "LPT1 Device:" +msgstr "LPT1-enhet:" + +msgid "LPT2 Device:" +msgstr "LPT2-enhet:" + +msgid "LPT3 Device:" +msgstr "LPT3-enhet:" + +msgid "LPT4 Device:" +msgstr "LPT4-enhet:" + +msgid "Serial port 1" +msgstr "Serieport 1" + +msgid "Serial port 2" +msgstr "Serieport 2" + +msgid "Serial port 3" +msgstr "Serieport 3" + +msgid "Serial port 4" +msgstr "Serieport 4" + +msgid "Parallel port 1" +msgstr "Parallellport 1" + +msgid "Parallel port 2" +msgstr "Parallellport 2" + +msgid "Parallel port 3" +msgstr "Parallellport 3" + +msgid "Parallel port 4" +msgstr "Parallellport 4" + +msgid "HD Controller:" +msgstr "Styrenhet för hårddisk:" + +msgid "FD Controller:" +msgstr "Styrenhet för diskett:" + +msgid "Tertiary IDE Controller" +msgstr "Tertiär IDE-kontroller" + +msgid "Quaternary IDE Controller" +msgstr "Kvartär IDE-kontroller" + +msgid "SCSI" +msgstr "SCSI" + +msgid "Controller 1:" +msgstr "Styrenhet 1:" + +msgid "Controller 2:" +msgstr "Styrenhet 2:" + +msgid "Controller 3:" +msgstr "Styrenhet 3:" + +msgid "Controller 4:" +msgstr "Styrenhet 4:" + +msgid "Cassette" +msgstr "Kassettband" + +msgid "Hard disks:" +msgstr "Hårddiskar:" + +msgid "&New..." +msgstr "&Ny..." + +msgid "&Existing..." +msgstr "&Befintlig..." + +msgid "&Remove" +msgstr "&Ta bort" + +msgid "Bus:" +msgstr "Buss:" + +msgid "Channel:" +msgstr "Kanal:" + +msgid "ID:" +msgstr "ID:" + +msgid "&Specify..." +msgstr "&Specificera..." + +msgid "Sectors:" +msgstr "Sektorer:" + +msgid "Heads:" +msgstr "Läshuvuden:" + +msgid "Cylinders:" +msgstr "Cylindrar:" + +msgid "Size (MB):" +msgstr "Storlek (MB):" + +msgid "Type:" +msgstr "Typ:" + +msgid "Image Format:" +msgstr "Avbildningsformat:" + +msgid "Block Size:" +msgstr "Blockstorlek:" + +msgid "Floppy drives:" +msgstr "Diskettenhet:" + +msgid "Turbo timings" +msgstr "Turbo timings" + +msgid "Check BPB" +msgstr "Kontrollera BPB" + +msgid "CD-ROM drives:" +msgstr "CD-ROM-enheter:" + +msgid "MO drives:" +msgstr "MO-enheter:" + +msgid "ZIP drives:" +msgstr "Zip-enheter:" + +msgid "ZIP 250" +msgstr "ZIP 250" + +msgid "ISA RTC:" +msgstr "ISA realtidsklocka:" + +msgid "ISA Memory Expansion" +msgstr "ISA minnesexpansion" + +msgid "Card 1:" +msgstr "Kort 1:" + +msgid "Card 2:" +msgstr "Kort 2:" + +msgid "Card 3:" +msgstr "Kort 3:" + +msgid "Card 4:" +msgstr "Kort 4:" + +msgid "ISABugger device" +msgstr "ISABugger-enhet" + +msgid "POST card" +msgstr "POST-kort" + +msgid "86Box" +msgstr "86Box" + +msgid "Error" +msgstr "Fel" + +msgid "Fatal error" +msgstr "Allvarligt fel" + +msgid " - PAUSED" +msgstr " - PAUSAD" + +msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgstr "Tryck på Ctrl+Alt+PgDn för att återvända till fönsterläge." + +msgid "Speed" +msgstr "Hastighet" + +msgid "ZIP %1 %2 (%3): %4" +msgstr "ZIP %1 %2 (%3): %4" + +msgid "ZIP images" +msgstr "Zip-avbildningar" + +msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgstr "86Box kunde inte hitta några användbara ROM-avbildningar.\n\nVänligen ladda ner en ROM-uppsättning och extrahera den till mappen \"roms\"." + +msgid "(empty)" +msgstr "(tom)" + +msgid "All files" +msgstr "Alla filer" + +msgid "Turbo" +msgstr "Turbo" + +msgid "On" +msgstr "På" + +msgid "Off" +msgstr "Av" + +msgid "All images" +msgstr "Alla avbildningar" + +msgid "Basic sector images" +msgstr "Grundläggande sektoravbildningar" + +msgid "Surface images" +msgstr "Ytavbildningar" + +msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." +msgstr "Maskinen \"%hs\" är inte tillgänglig på grund av saknade ROM-avbildningar i mappen roms/machines. Byter till en tillgänglig maskin." + +msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgstr "Bildskärmskortet \"%hs\" är inte tillgängligt på grund av saknade ROM-avbildningar i mappen roms/video. Byter till ett tillgängligt bildskärmskort." + +msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." +msgstr "Bildskärmskort #2 \"%hs\" är inte tillgängligt på grund av saknade ROM-avbildningar i mappen roms/video. Avaktiverar det andra bildskärmskortet." + +msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." +msgstr "Enheten \"%hs\" är inte tillgänglig på grund av saknade ROM-avbildningar. Ignorerar enheten." + +msgid "Machine" +msgstr "Maskin" + +msgid "Display" +msgstr "Bildskärm" + +msgid "Input devices" +msgstr "Inmatningsenheter" + +msgid "Sound" +msgstr "Ljud" + +msgid "Network" +msgstr "Nätverk" + +msgid "Ports (COM & LPT)" +msgstr "Portar (COM & LPT)" + +msgid "Storage controllers" +msgstr "Styrenheter för lagring" + +msgid "Hard disks" +msgstr "Hårddiskar" + +msgid "Floppy & CD-ROM drives" +msgstr "Diskett- och CD-ROM-enheter" + +msgid "Other removable devices" +msgstr "Andra flyttbara enheter" + +msgid "Other peripherals" +msgstr "Andra tillbehör" + +msgid "Click to capture mouse" +msgstr "Klicka för att fånga upp musen" + +msgid "Press %1 to release mouse" +msgstr "Tryck på %1 för att släppa musen" + +msgid "Press %1 or middle button to release mouse" +msgstr "Tryck på %1 eller mellersta musknappen för att släppa musen" + +msgid "Bus" +msgstr "Buss" + +msgid "File" +msgstr "Fil" + +msgid "C" +msgstr "C" + +msgid "H" +msgstr "H" + +msgid "S" +msgstr "S" + +msgid "KB" +msgstr "KB" + +msgid "Default" +msgstr "Standard" + +msgid "%1 Wait state(s)" +msgstr "" + +msgid "Type" +msgstr "Typ" + +msgid "No PCap devices found" +msgstr "Inga PCap-enheter hittade" + +msgid "Invalid PCap device" +msgstr "Ogiltig PCap-enhet" + +msgid "2-axis, 2-button joystick(s)" +msgstr "Styrspak med 2 axlar och 2 knappar" + +msgid "2-axis, 4-button joystick" +msgstr "Styrspak med 2 axlar och 4 knappar" + +msgid "2-axis, 6-button joystick" +msgstr "Styrspak med 2 axlar och 6 knappar" + +msgid "2-axis, 8-button joystick" +msgstr "Styrspak med 2 axlar och 8 knappar" + +msgid "3-axis, 2-button joystick" +msgstr "Styrspak med 3 axlar och 2 knappar" + +msgid "3-axis, 4-button joystick" +msgstr "Styrspak med 3 axlar och 4 knappar" + +msgid "4-axis, 4-button joystick" +msgstr "Styrspak med 4 axlar och 4 knappar" + +msgid "CH Flightstick Pro" +msgstr "CH Flightstick Pro" + +msgid "Microsoft SideWinder Pad" +msgstr "Microsoft SideWinder Pad" + +msgid "Thrustmaster Flight Control System" +msgstr "Thrustmaster Flight Control System" + +msgid "None" +msgstr "Ingen" + +msgid "%1 MB (CHS: %2, %3, %4)" +msgstr "%1 MB (CHS: %2, %3, %4)" + +msgid "Floppy %1 (%2): %3" +msgstr "Diskett %1 (%2): %3" + +msgid "Advanced sector images" +msgstr "Avancerade sektoravbildningar" + +msgid "Flux images" +msgstr "Flux-avbildningar" + +msgid "Are you sure you want to hard reset the emulated machine?" +msgstr "Är du säker på att du vill göra en hård omstart av den emulerade maskinen?" + +msgid "Are you sure you want to exit 86Box?" +msgstr "Är du säker på att du vill avsluta 86Box?" + +msgid "Unable to initialize Ghostscript" +msgstr "Ej möjligt att initialisera Ghostscript" + +msgid "Unable to initialize GhostPCL" +msgstr "Ej möjligt att initialisera GhostPCL" + +msgid "MO %1 (%2): %3" +msgstr "MO %1 (%2): %3" + +msgid "MO images" +msgstr "MO-avbildningar" + +msgid "Welcome to 86Box!" +msgstr "Välkommen till 86Box!" + +msgid "Internal device" +msgstr "Intern enhet" + +msgid "Exit" +msgstr "Avsluta" + +msgid "No ROMs found" +msgstr "Inga ROM-avbildningar hittades" + +msgid "Do you want to save the settings?" +msgstr "Vill du spara inställningarna?" + +msgid "This will hard reset the emulated machine." +msgstr "Detta kommer att göra en hård omstart av den emulerade maskinen." + +msgid "Save" +msgstr "Spara" + +msgid "About 86Box" +msgstr "Om 86Box" + +msgid "86Box v" +msgstr "86Box v" + +msgid "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." +msgstr "En emulator av gamla datorer\n\nUpphovsmän: 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, med flera.\n\nMed tidigare grundbidrag från Sarah Walker, leilei, JohnElliott, greatpsycho, med flera.\n\nSläppt under GNU General Public License upplaga 2 eller senare. Se LICENSE för mer information." + +msgid "Hardware not available" +msgstr "Hårdvara ej tillgänglig" + +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Säkerställ att %1 är installerad och att du använder en %1-kompatibel nätverksanslutning." + +msgid "Invalid configuration" +msgstr "Ogiltig konfiguration" + +msgid "%1 is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." +msgstr "%1 krävs för automatisk omvandling av PostScript-filer till PDF.\n\nAlla dokument som skickats till den allmänna PostScript-skrivaren kommer att sparas som PostScript-filer (.ps)." + +msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." +msgstr "%1 krävs för automatisk omvandling av PCL-filer till PDF.\n\nAlla dokument som skickas till den allmänna PCL-skrivaren kommer att sparas som Printer Command Language-filer (.pcl)." + +msgid "Entering fullscreen mode" +msgstr "Startar helskärmsläge" + +msgid "Don't show this message again" +msgstr "Visa inte detta meddelande igen" + +msgid "Don't exit" +msgstr "Avsluta inte" + +msgid "Reset" +msgstr "Starta om" + +msgid "Don't reset" +msgstr "Starta inte om" + +msgid "CD-ROM images" +msgstr "CD-ROM-avbildningar" + +msgid "%1 Device Configuration" +msgstr "%1 Enhetskonfiguration" + +msgid "Monitor in sleep mode" +msgstr "Skärm i viloläge" + +msgid "GLSL shaders" +msgstr "GLSL shaders" + +msgid "You are loading an unsupported configuration" +msgstr "Du laddar en konfiguration som inte stöds" + +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 "Filtrering av processortyp grundat på den valda maskinen är avaktiverat för denna emulerade maskin.\n\nDetta gör det möjligt att välja en processor som annars är oförenlig med den valda maskinen. Detta kan dock leda till oförenligheter med maskinens BIOS eller annan mjukvara\n\nAtt aktivera denna inställning stöds inte officiellt, och alla felrapporter som lämnas in kan komma att stängas som ogiltiga." + +msgid "Continue" +msgstr "Fortsätt" + +msgid "Cassette: %1" +msgstr "Kassettband: %1" + +msgid "Cassette images" +msgstr "Kassettbandsavbildningar" + +msgid "Cartridge %1: %2" +msgstr "Kassett %1: %2" + +msgid "Cartridge images" +msgstr "Kassettavbildningar" + +msgid "Resume execution" +msgstr "Fortsätt exekvering" + +msgid "Pause execution" +msgstr "Pausa exekvering" + +msgid "Press Ctrl+Alt+Del" +msgstr "Tryck på Ctrl+Alt+Del" + +msgid "Press Ctrl+Alt+Esc" +msgstr "Tryck på Ctrl+Alt+Esc" + +msgid "Hard reset" +msgstr "Hård omstart" + +msgid "ACPI shutdown" +msgstr "ACPI-avstängning" + +msgid "Hard disk (%1)" +msgstr "Hårddisk (%1)" + +msgid "MFM/RLL or ESDI CD-ROM drives never existed" +msgstr "MFM/RLL eller ESDI CD-ROM-enheter fanns aldrig" + +msgid "Custom..." +msgstr "Egen..." + +msgid "Custom (large)..." +msgstr "Egen (stor)..." + +msgid "Add New Hard Disk" +msgstr "Lägg till ny hårddisk" + +msgid "Add Existing Hard Disk" +msgstr "Lägg till befintlig hårddisk" + +msgid "HDI disk images cannot be larger than 4 GB." +msgstr "Avbildningar i HDI-format kan inte vara större än 4 GB." + +msgid "Disk images cannot be larger than 127 GB." +msgstr "Avbildningar kan inte vara större än 127 GB." + +msgid "Hard disk images" +msgstr "Hårddiskavbilningar" + +msgid "Unable to read file" +msgstr "Kan inte läsa fil" + +msgid "Unable to write file" +msgstr "Kan inte skriva till fil" + +msgid "HDI or HDX images with a sector size other than 512 are not supported." +msgstr "HDI- eller HDX-avbildningar med en sektorstorlek annat än 512 stöds inte." + +msgid "Disk image file already exists" +msgstr "Avbildningsfil finns redan" + +msgid "Please specify a valid file name." +msgstr "Vänligen ange ett giltigt filnamn." + +msgid "Disk image created" +msgstr "Avbildning skapad" + +msgid "Make sure the file exists and is readable." +msgstr "Säkerställ att filen finns och är läsbar." + +msgid "Make sure the file is being saved to a writable directory." +msgstr "Säkerställ att filen sparas till en skrivbar mapp." + +msgid "Disk image too large" +msgstr "Avbildning för stor" + +msgid "Remember to partition and format the newly-created drive." +msgstr "Kom ihåg att partitionera och formatera den skapade enheten." + +msgid "The selected file will be overwritten. Are you sure you want to use it?" +msgstr "Den valda filen kommer att skrivas över. Är du säker på att du vill använda den?" + +msgid "Unsupported disk image" +msgstr "Avbildning stöds inte" + +msgid "Overwrite" +msgstr "Skriv över" + +msgid "Don't overwrite" +msgstr "Skriv inte över" + +msgid "Raw image" +msgstr "Rå avbildning" + +msgid "HDI image" +msgstr "HDI-avbildning" + +msgid "HDX image" +msgstr "HDX-avbildning" + +msgid "Fixed-size VHD" +msgstr "VHD med fastställd storlek" + +msgid "Dynamic-size VHD" +msgstr "VHD med dynamisk storlek" + +msgid "Differencing VHD" +msgstr "Differencing-avbildning av VHD" + +msgid "(N/A)" +msgstr "(ej)" + +msgid "Raw image (.img)" +msgstr "Rå avbildning (.img)" + +msgid "HDI image (.hdi)" +msgstr "HDI-avbildning (.hdi)" + +msgid "HDX image (.hdx)" +msgstr "HDX-avbildning (.hdx)" + +msgid "Fixed-size VHD (.vhd)" +msgstr "VHD med fastställd storlek (.vhd)" + +msgid "Dynamic-size VHD (.vhd)" +msgstr "VHD med dynamisk storlek (.vhd)" + +msgid "Differencing VHD (.vhd)" +msgstr "Differencing-avbildning av VHD (.vhd)" + +msgid "Large blocks (2 MB)" +msgstr "Stora block (2 MB)" + +msgid "Small blocks (512 KB)" +msgstr "Små block (512 KB)" + +msgid "VHD files" +msgstr "VHD-filer" + +msgid "Select the parent VHD" +msgstr "Välj moders-VHDn" + +msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" +msgstr "Detta kan betyda att modersavbildningen har ändrats efter att skillnadsavbildningen skapades.\n\nDet kan också hända om avbildningarna har flyttats eller kopierats, eller av en bugg i programmet som skapade denna disk.\n\nVill du laga tidsstämplarna?" + +msgid "Parent and child disk timestamps do not match" +msgstr "Tidsstämpeln på moders- och dotterdisken stämmer inte överens" + +msgid "Could not fix VHD timestamp." +msgstr "Kunde inte laga tidsstämpeln på VHDn." + +msgid "MFM/RLL" +msgstr "MFM/RLL" + +msgid "XTA" +msgstr "XTA" + +msgid "ESDI" +msgstr "ESDI" + +msgid "IDE" +msgstr "IDE" + +msgid "ATAPI" +msgstr "ATAPI" + +msgid "CD-ROM %1 (%2): %3" +msgstr "CD-ROM %1 (%2): %3" + +msgid "160 KB" +msgstr "160 KB" + +msgid "180 KB" +msgstr "180 KB" + +msgid "320 KB" +msgstr "320 KB" + +msgid "360 KB" +msgstr "360 KB" + +msgid "640 KB" +msgstr "640 KB" + +msgid "720 KB" +msgstr "720 KB" + +msgid "1.2 MB" +msgstr "1.2 MB" + +msgid "1.25 MB" +msgstr "1.25 MB" + +msgid "1.44 MB" +msgstr "1.44 MB" + +msgid "DMF (cluster 1024)" +msgstr "DMF (kluster 1024)" + +msgid "DMF (cluster 2048)" +msgstr "DMF (kluster 2048)" + +msgid "2.88 MB" +msgstr "2.88 MB" + +msgid "ZIP 100" +msgstr "ZIP 100" + +msgid "3.5\" 128 MB (ISO 10090)" +msgstr "3.5\" 128 MB (ISO 10090)" + +msgid "3.5\" 230 MB (ISO 13963)" +msgstr "3.5\" 230 MB (ISO 13963)" + +msgid "3.5\" 540 MB (ISO 15498)" +msgstr "3.5\" 540 MB (ISO 15498)" + +msgid "3.5\" 640 MB (ISO 15498)" +msgstr "3.5\" 640 MB (ISO 15498)" + +msgid "3.5\" 1.3 GB (GigaMO)" +msgstr "3.5\" 1.3 GB (GigaMO)" + +msgid "3.5\" 2.3 GB (GigaMO 2)" +msgstr "3.5\" 2.3 GB (GigaMO 2)" + +msgid "5.25\" 600 MB" +msgstr "5.25\" 600 MB" + +msgid "5.25\" 650 MB" +msgstr "5.25\" 650 MB" + +msgid "5.25\" 1 GB" +msgstr "5.25\" 1 GB" + +msgid "5.25\" 1.3 GB" +msgstr "5.25\" 1.3 GB" + +msgid "Perfect RPM" +msgstr "Perfekt varv/min" + +msgid "1% below perfect RPM" +msgstr "1% under perfekt varv/min" + +msgid "1.5% below perfect RPM" +msgstr "1.5% under perfekt varv/min" + +msgid "2% below perfect RPM" +msgstr "2& under perfekt varm/min" + +msgid "(System Default)" +msgstr "(Systemstandard)" + +msgid "Failed to initialize network driver" +msgstr "Kunde inte initialisera drivrutiner för nätverk" + +msgid "The network configuration will be switched to the null driver" +msgstr "Nätverkskonfigurationen kommer att bytas till den tomma drivrutinen" + +msgid "Mouse sensitivity:" +msgstr "Muskänslighet:" + +msgid "Select media images from program working directory" +msgstr "Välj medieavbildningar från programmets arbetsmapp" + +msgid "PIT mode:" +msgstr "PIT-läge:" + +msgid "Auto" +msgstr "Automatisk" + +msgid "Slow" +msgstr "Långsam" + +msgid "Fast" +msgstr "Snabb" + +msgid "&Auto-pause on focus loss" +msgstr "&Pausa automatiskt när fokus tappas" + +msgid "WinBox is no longer supported" +msgstr "WinBox stöds inte längre" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Utvecklingen av hanteraren WinBox stoppades under 2022 på grund av avsaknad av underhållare. När vi nu riktar våra ansträngningar till att göra 86Box ännu bättre så har vi fattat beslutet att inte längre stödja WinBox som en hanterare.\n\nInga framtida uppdateringar kommer att tillhandahållas genom WinBox, och du kan stöta på felaktiga beteenden om du skulle fortsätta att använda det med nyare versioner av 86Box. Alla felrapporter som har att göra med WinBox kommer att stängas som ogiltiga.\n\nGå till 86Box.net för en lista med andra hanterare som du kan använda." + +msgid "Generate" +msgstr "Generera" + +msgid "Joystick configuration" +msgstr "Konfiguration av styrspak" + +msgid "Device" +msgstr "Enhet" + +msgid "%1 (X axis)" +msgstr "%1 (X-axeln)" + +msgid "%1 (Y axis)" +msgstr "%1 (Y-axeln)" + +msgid "MCA devices" +msgstr "MCA-enheter" + +msgid "List of MCA devices:" +msgstr "Lista på MCA-enheter:" + +msgid "Tablet tool" +msgstr "Plattverktyg" + +msgid "Qt (OpenGL &ES)" +msgstr "Qt (OpenGL &ES)" + +msgid "About Qt" +msgstr "Om Qt" + +msgid "MCA devices..." +msgstr "MCA-enheter..." + +msgid "Show non-primary monitors" +msgstr "Visa icke-primära skärmar" + +msgid "Open screenshots folder..." +msgstr "Öppna skärmbildsmappen..." + +msgid "Apply fullscreen stretch mode when maximized" +msgstr "Tillämpa sträckläge för helskärm när den är maximerad" + +msgid "Cursor/Puck" +msgstr "Pekare/puck" + +msgid "Pen" +msgstr "Penna" + +msgid "Host CD/DVD Drive (%1:)" +msgstr "Värdenhet för CD/DVD (%1:)" + +msgid "&Connected" +msgstr "&Ansluten" + +msgid "Clear image history" +msgstr "Rensa historik för avbildningar" + +msgid "Create..." +msgstr "Skapa..." + +msgid "Host CD/DVD Drive (%1)" +msgstr "Värdenhet för CD/DVD (%1)" + +msgid "Unknown Bus" +msgstr "Okänd buss" + +msgid "Null Driver" +msgstr "Tom drivrutin" + +msgid "NIC %1 (%2) %3" +msgstr "NIC %1 (%2) %3" + +msgid "Render behavior" +msgstr "Renderingsbeteende" + +msgid "Use target framerate:" +msgstr "Använd målbildhatighet:" + +msgid " fps" +msgstr " Bildhastighet" + +msgid "VSync" +msgstr "VSync" + +msgid "Synchronize with video" +msgstr "Synkronisera med bild" + +msgid "Shaders" +msgstr "" + +msgid "Remove" +msgstr "Ta bort" + +msgid "Browse..." +msgstr "Bläddra..." + +msgid "Couldn't create OpenGL context." +msgstr "Kunde inte skapa OpenGL-sammanhang." + +msgid "Couldn't switch to OpenGL context." +msgstr "Kunde inte växla till OpenGL-sammanhang." + +msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" +msgstr "OpenGL version 3.0 eller högre krävs. Nuvarande version är %1.%2" + +msgid "Error initializing OpenGL" +msgstr "Fel vid initialisering av OpenGL" + +msgid "\nFalling back to software rendering." +msgstr "\nFaller tillbaka på mjukvarurendering." + +msgid "<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>" +msgstr "<html><head/><body><p>Vid val av medieavbildningar (CD-ROM, diskett, osv.) så kommer fönstret att börja i samma mapp som 86Box konfigurationsfil. Denna inställning kommer troligtvis endast göra en skillnad på macOS.</p></body></html>" + +msgid "This machine might have been moved or copied." +msgstr "Denna maskin kan ha flyttats eller kopierats." + +msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure." +msgstr "För att säkerställa korrekt funktionalitet av nätverk så behöver 86Box veta om denna maskin har flyttats eller kopierats.\n\nVälj \"Jag kopierade den\" om du är osäker." + +msgid "I Moved It" +msgstr "Jag flyttade den" + +msgid "I Copied It" +msgstr "Jag kopierade den" + +msgid "86Box Monitor #" +msgstr "86Box skärm #" + +msgid "No MCA devices." +msgstr "Inga MCA-enheter." + +msgid "MiB" +msgstr "MiB" + +msgid "Network Card #1" +msgstr "Nätverkskort #1" + +msgid "Network Card #2" +msgstr "Nätverkskort #2" + +msgid "Network Card #3" +msgstr "Nätverkskort #3" + +msgid "Network Card #4" +msgstr "Nätverkskort #4" + +msgid "Mode:" +msgstr "Läge:" + +msgid "Interface:" +msgstr "Gränssnitt:" + +msgid "Adapter:" +msgstr "Adapter:" + +msgid "VDE Socket:" +msgstr "VDE-sockel:" + +msgid "86Box Unit Tester" +msgstr "86Box enhetsprövare" + +msgid "Novell NetWare 2.x Key Card" +msgstr "Novell NetWare 2.x nyckelkort" + +msgid "Serial port passthrough 1" +msgstr "Serieport passthrough 1" + +msgid "Serial port passthrough 2" +msgstr "Serieport passthrough 2" + +msgid "Serial port passthrough 3" +msgstr "Serieport passthrough 3" + +msgid "Serial port passthrough 4" +msgstr "Serieport passthrough 4" + +msgid "Renderer options..." +msgstr "Renderingsalternativ..." + +msgid "Logitech/Microsoft Bus Mouse" +msgstr "Logitech/Microsoft-buss-mus" + +msgid "Microsoft Bus Mouse (InPort)" +msgstr "Microsoft-buss-mus (InPort)" + +msgid "Mouse Systems Serial Mouse" +msgstr "Mouse Systems seriemus" + +msgid "Microsoft Serial Mouse" +msgstr "Microsoft seriemus" + +msgid "Logitech Serial Mouse" +msgstr "Logitech seriemus" + +msgid "PS/2 Mouse" +msgstr "PS/2-mus" + +msgid "3M MicroTouch (Serial)" +msgstr "3M MicroTouch (serie)" + +msgid "[COM] Standard Hayes-compliant Modem" +msgstr "[COM] Standard Hayes-kompatibelt modem" + +msgid "Roland MT-32 Emulation" +msgstr "Roland MT-32 emulering" + +msgid "Roland MT-32 (New) Emulation" +msgstr "Roland MT-32 (ny) emulering" + +msgid "Roland CM-32L Emulation" +msgstr "Roland CM-32L emulering" + +msgid "Roland CM-32LN Emulation" +msgstr "Roland CM-32LN emulering" + +msgid "OPL4-ML Daughterboard" +msgstr "OPL4-ML dotterkort" + +msgid "System MIDI" +msgstr "System-MIDI" + +msgid "MIDI Input Device" +msgstr "Indataenhet för MIDI" + +msgid "BIOS Address" +msgstr "BIOS-adress" + +msgid "Enable BIOS extension ROM Writes" +msgstr "Aktivera ROM-skrivningar för utökat BIOS" + +msgid "Address" +msgstr "Adress" + +msgid "IRQ" +msgstr "IRQ" + +msgid "BIOS Revision" +msgstr "BIOS revision" + +msgid "Translate 26 -> 17" +msgstr "Översätt 26 -> 17" + +msgid "Language" +msgstr "Språk" + +msgid "Enable backlight" +msgstr "Aktivera bakgrundsbelysning" + +msgid "Invert colors" +msgstr "Invertera färger" + +msgid "BIOS size" +msgstr "Storlek på BIOS" + +msgid "Map C0000-C7FFF as UMB" +msgstr "Kartlägg C0000-C7FFF som UMB" + +msgid "Map C8000-CFFFF as UMB" +msgstr "Kartlägg C8000-CFFFF som UMB" + +msgid "Map D0000-D7FFF as UMB" +msgstr "Kartlägg D0000-D7FFF som UMB" + +msgid "Map D8000-DFFFF as UMB" +msgstr "Kartlägg D8000-DFFFF som UMB" + +msgid "Map E0000-E7FFF as UMB" +msgstr "Kartlägg E0000-E7FFF som UMB" + +msgid "Map E8000-EFFFF as UMB" +msgstr "Kartlägg E8000-EFFFF som UMB" + +msgid "JS9 Jumper (JIM)" +msgstr "JS9-bygel (JIM)" + +msgid "MIDI Output Device" +msgstr "Utdataenhet för MIDI" + +msgid "MIDI Real time" +msgstr "Realtid för MIDI" + +msgid "MIDI Thru" +msgstr "MIDI genom" + +msgid "MIDI Clockout" +msgstr "MIDI utklockning" + +msgid "SoundFont" +msgstr "Ljudsnitt" + +msgid "Output Gain" +msgstr "Förstärkning av utmatning" + +msgid "Chorus" +msgstr "Chorus" + +msgid "Chorus Voices" +msgstr "Chorus voices" + +msgid "Chorus Level" +msgstr "Chorus nivå" + +msgid "Chorus Speed" +msgstr "Chorus hastighet" + +msgid "Chorus Depth" +msgstr "Chorus djup" + +msgid "Chorus Waveform" +msgstr "Chorus vågform" + +msgid "Reverb" +msgstr "Reverb" + +msgid "Reverb Room Size" +msgstr "Reverb rumsstorlek" + +msgid "Reverb Damping" +msgstr "Reverb dämpning" + +msgid "Reverb Width" +msgstr "Reverb bredd" + +msgid "Reverb Level" +msgstr "Reverb nivå" + +msgid "Interpolation Method" +msgstr "Interpoleringsmetod" + +msgid "Reverb Output Gain" +msgstr "Reverb utmatningsförstärkning" + +msgid "Reversed stereo" +msgstr "Omvänd stereo" + +msgid "Nice ramp" +msgstr "Nice ramp" + +msgid "Hz" +msgstr "Hz" + +msgid "Buttons" +msgstr "Knappar" + +msgid "Serial Port" +msgstr "Serieport" + +msgid "RTS toggle" +msgstr "RTS-brytare" + +msgid "Revision" +msgstr "Revision" + +msgid "Controller" +msgstr "Styrenhet" + +msgid "Show Crosshair" +msgstr "Visa hårkors" + +msgid "DMA" +msgstr "DMA" + +msgid "MAC Address" +msgstr "MAC-adress" + +msgid "MAC Address OUI" +msgstr "MAC-adress OUI" + +msgid "Enable BIOS" +msgstr "Aktivera BIOS" + +msgid "Baud Rate" +msgstr "Baudhastighet" + +msgid "TCP/IP listening port" +msgstr "TCP/IP lyssningsport" + +msgid "Phonebook File" +msgstr "Telefonsboksfil" + +msgid "Telnet emulation" +msgstr "Telnet-emulering" + +msgid "RAM Address" +msgstr "RAM-adress" + +msgid "RAM size" +msgstr "RAM-storlek" + +msgid "Initial RAM size" +msgstr "Ursprunglig RAM-storlek" + +msgid "Serial Number" +msgstr "Serienummer" + +msgid "Host ID" +msgstr "Värd-ID" + +msgid "FDC Address" +msgstr "Adress till diskettstyrenhet" + +msgid "MPU-401 Address" +msgstr "Adress till MPU-401" + +msgid "MPU-401 IRQ" +msgstr "MPU-401 IRQ" + +msgid "Receive MIDI input" +msgstr "Ta emot MIDI-indata" + +msgid "Low DMA" +msgstr "Låg DMA" + +msgid "Enable Game port" +msgstr "Aktivera spelport" + +msgid "Surround module" +msgstr "Sorround-modul" + +msgid "CODEC" +msgstr "CODEC" + +msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)" +msgstr "Öka avbrottsnummer för CODEC vid CODEC-installation (krävs av vissa drivrutiner)" + +msgid "SB Address" +msgstr "Adress för SB" + +msgid "WSS IRQ" +msgstr "WSS IRQ" + +msgid "WSS DMA" +msgstr "WSS DMA" + +msgid "Enable OPL" +msgstr "Aktivera OPL" + +msgid "Receive MIDI input (MPU-401)" +msgstr "Ta emot MIDI-indata (MPU-401)" + +msgid "SB low DMA" +msgstr "Låg DMA för SB" + +msgid "6CH variant (6-channel)" +msgstr "6CH-variant (6-kanals)" + +msgid "Enable CMS" +msgstr "Aktivera CMS" + +msgid "Mixer" +msgstr "Mixer" + +msgid "High DMA" +msgstr "Hög DMA" + +msgid "Control PC speaker" +msgstr "Styr PC-speaker" + +msgid "Memory size" +msgstr "Minnesstorlek" + +msgid "EMU8000 Address" +msgstr "Adress till EMU8000" + +msgid "IDE Controller" +msgstr "IDE-styrenhet" + +msgid "Codec" +msgstr "Kodek" + +msgid "GUS type" +msgstr "GUS-typ" + +msgid "Enable 0x04 \"Exit 86Box\" command" +msgstr "Aktivera kommandot 0x04 \"Avsluta 86Box\"" + +msgid "Display type" +msgstr "Skärmtyp" + +msgid "Composite type" +msgstr "Komposittyp" + +msgid "RGB type" +msgstr "RGB-typ" + +msgid "Line doubling type" +msgstr "Linjefördubblingstyp" + +msgid "Snow emulation" +msgstr "Snöemulering" + +msgid "Monitor type" +msgstr "Bildskärmstyp" + +msgid "Character set" +msgstr "Teckenuppsättning" + +msgid "XGA type" +msgstr "XGA-typ" + +msgid "Instance" +msgstr "Instans" + +msgid "MMIO Address" +msgstr "Adress för MMIO" + +msgid "RAMDAC type" +msgstr "RAMDAC-typ" + +msgid "Blend" +msgstr "Blanda" + +msgid "Bilinear filtering" +msgstr "Bilinjär filtrering" + +msgid "Dithering" +msgstr "Dithering" + +msgid "Enable NMI for CGA emulation" +msgstr "Aktivera NMI till CGA-emulering" + +msgid "Voodoo type" +msgstr "Voodoo-typ" + +msgid "Framebuffer memory size" +msgstr "Minnesstorlek för videobuffert" + +msgid "Texture memory size" +msgstr "Minnesstorlek för texturer" + +msgid "Dither subtraction" +msgstr "Dither subtraktion" + +msgid "Screen Filter" +msgstr "Skärmfilter" + +msgid "Render threads" +msgstr "Renderingstrådar" + +msgid "SLI" +msgstr "SLI" + +msgid "Start Address" +msgstr "Startadress" + +msgid "Contiguous Size" +msgstr "Angränsande storlek" + +msgid "I/O Width" +msgstr "I/O-bredd" + +msgid "Transfer Speed" +msgstr "Överföringshastighet" + +msgid "EMS mode" +msgstr "EMS-läge" + +msgid "Address for > 2 MB" +msgstr "Adress till > 2 MB" + +msgid "Frame Address" +msgstr "Bildadress" + +msgid "USA" +msgstr "Förenta staterna" + +msgid "Danish" +msgstr "Danska" + +msgid "Always at selected speed" +msgstr "Alltid vid den valda hastigheten" + +msgid "BIOS setting + Hotkeys (off during POST)" +msgstr "BIOS-inställningar + Snabbtangenter (av under POST)" + +msgid "64 kB starting from F0000" +msgstr "64 kB som börjar från F0000" + +msgid "128 kB starting from E0000 (address MSB inverted, last 64KB first)" +msgstr "128 kB som börjar från E0000 (adress MSB inverterad, de sista 64KB först)" + +msgid "Sine" +msgstr "Sinus" + +msgid "Triangle" +msgstr "Triangel" + +msgid "Linear" +msgstr "Linjär" + +msgid "4th Order" +msgstr "Fjärde ordningen" + +msgid "7th Order" +msgstr "Sjunde ordningen" + +msgid "Non-timed (original)" +msgstr "Ej tajmad (ursprunglig)" + +msgid "45 Hz (JMP2 not populated)" +msgstr "45 Hz (JMP2 ej byglad)" + +msgid "Two" +msgstr "Två" + +msgid "Three" +msgstr "Tre" + +msgid "Wheel" +msgstr "Hjul" + +msgid "Five + Wheel" +msgstr "Fem med hjul" + +msgid "Five + 2 Wheels" +msgstr "" + +msgid "A3 - SMT2 Serial / SMT3(R)V" +msgstr "A3 - SMT2 serie / SMT3(R)V" + +msgid "Q1 - SMT3(R) Serial" +msgstr "Q1 - SMT3(R) serie" + +msgid "8 KB" +msgstr "8 KB" + +msgid "32 KB" +msgstr "32 KB" + +msgid "16 KB" +msgstr "16 KB" + +msgid "64 KB" +msgstr "64 KB" + +msgid "Disable BIOS" +msgstr "Avaktivera BIOS" + +msgid "512 KB" +msgstr "512 KB" + +msgid "2 MB" +msgstr "2 MB" + +msgid "8 MB" +msgstr "8 MB" + +msgid "28 MB" +msgstr "28 MB" + +msgid "1 MB" +msgstr "1 MB" + +msgid "4 MB" +msgstr "4 MB" + +msgid "12 MB" +msgstr "12 MB" + +msgid "16 MB" +msgstr "16 MB" + +msgid "20 MB" +msgstr "20 MB" + +msgid "24 MB" +msgstr "24 MB" + +msgid "SigmaTel STAC9721T (stereo)" +msgstr "SigmaTel STAC9721T (stereo)" + +msgid "Classic" +msgstr "Klassisk" + +msgid "256 KB" +msgstr "256 KB" + +msgid "Composite" +msgstr "Komposit" + +msgid "Old" +msgstr "Gammal" + +msgid "New" +msgstr "Ny" + +msgid "Color (generic)" +msgstr "Färg (allmän)" + +msgid "Green Monochrome" +msgstr "Grön monokrom" + +msgid "Amber Monochrome" +msgstr "Bärnstensfärgad monokrom" + +msgid "Gray Monochrome" +msgstr "Grå monokrom" + +msgid "Color (no brown)" +msgstr "Färg (utan brun)" + +msgid "Color (IBM 5153)" +msgstr "Färg (IBM 5153)" + +msgid "Simple doubling" +msgstr "Enkel fördubbling" + +msgid "sRGB interpolation" +msgstr "sRGB-interpolering" + +msgid "Linear interpolation" +msgstr "Linjär interpolering" + +msgid "128 KB" +msgstr "128 KB" + +msgid "Monochrome (5151/MDA) (white)" +msgstr "Monokrom (5151/MDA) (vit)" + +msgid "Monochrome (5151/MDA) (green)" +msgstr "Monokrom (5151/MDA) (grön)" + +msgid "Monochrome (5151/MDA) (amber)" +msgstr "Monokrom (5151/MDA) (bärnstensfärgad)" + +msgid "Color 40x25 (5153/CGA)" +msgstr "Färg 40x25 (5153/CGA)" + +msgid "Color 80x25 (5153/CGA)" +msgstr "Färg 80x25 (5153/CGA)" + +msgid "Enhanced Color - Normal Mode (5154/ECD)" +msgstr "Utökad färg - normalt läge (5154/ECD)" + +msgid "Enhanced Color - Enhanced Mode (5154/ECD)" +msgstr "Utökad färg - utökat läge (5154/ECD)" + +msgid "Green" +msgstr "Grön" + +msgid "Amber" +msgstr "Bärnstensfärgad" + +msgid "Gray" +msgstr "Grå" + +msgid "Color" +msgstr "Färg" + +msgid "U.S. English" +msgstr "Amerikansk engelska" + +msgid "Scandinavian" +msgstr "Skandinaviska" + +msgid "Other languages" +msgstr "Andra språk" + +msgid "Bochs latest" +msgstr "Bochs senaste" + +msgid "Mono Non-Interlaced" +msgstr "Ej sammanflätad monokrom" + +msgid "Color Interlaced" +msgstr "Sammanflätad färg" + +msgid "Color Non-Interlaced" +msgstr "Ej sammanflätad färg" + +msgid "3Dfx Voodoo Graphics" +msgstr "3Dfx Voodoo-grafik" + +msgid "Obsidian SB50 + Amethyst (2 TMUs)" +msgstr "Obsidian SB50 + Amethyst (2 TMUs)" + +msgid "8-bit" +msgstr "8-bitar" + +msgid "16-bit" +msgstr "16-bitar" + +msgid "Standard (150ns)" +msgstr "Standard (150ns)" + +msgid "High-Speed (120ns)" +msgstr "Höghastighet (120ns)" + +msgid "Enabled" +msgstr "Aktiverad" + +msgid "Standard" +msgstr "Standard" + +msgid "High-Speed" +msgstr "Höghastighet" + +msgid "Stereo LPT DAC" +msgstr "Stereo LPT DAC" + +msgid "Generic Text Printer" +msgstr "Allmän textskrivare" + +msgid "Generic ESC/P Dot-Matrix Printer" +msgstr "Allmän ESC/P punktmatrisskrivare" + +msgid "Generic PostScript Printer" +msgstr "Allmän PostScript-skrivare" + +msgid "Generic PCL5e Printer" +msgstr "Allmän PCL5e-skrivare" + +msgid "Parallel Line Internet Protocol" +msgstr "Parallel Line Internet Protocol" + +msgid "Protection Dongle for Savage Quest" +msgstr "Skyddsdongel till Savage Quest" + +msgid "Serial Passthrough Device" +msgstr "Seriepassthrough-enhet" + +msgid "Passthrough Mode" +msgstr "Passthrough-läge" + +msgid "Host Serial Device" +msgstr "Värd-serieenhet" + +msgid "Name of pipe" +msgstr "Namn på pipe" + +msgid "Data bits" +msgstr "Databitar" + +msgid "Stop bits" +msgstr "Stopbitar" + +msgid "Baud Rate of Passthrough" +msgstr "Passthroughns Baudhastighet" + +msgid "Named Pipe (Server)" +msgstr "Namngiven pipe (server)" + +msgid "Host Serial Passthrough" +msgstr "Värd-seriepassthrough" + +msgid "E&ject %1" +msgstr "M&ata ut %1" + +msgid "&Unmute" +msgstr "&Avtysta" + +msgid "Softfloat FPU" +msgstr "Softfloat flyttalsprocessor" + +msgid "High performance impact" +msgstr "Hög påverkan på prestanda" + +msgid "[Generic] RAM Disk (max. speed)" +msgstr "[Allmän] RAM-disk (max hastighet)" + +msgid "[Generic] 1989 (3500 RPM)" +msgstr "[Allmän] 1989 (3500 varv/min)" + +msgid "[Generic] 1992 (3600 RPM)" +msgstr "[Allmän] 1992 (3600 varv/min)" + +msgid "[Generic] 1994 (4500 RPM)" +msgstr "[Allmän] 1994 (4500 varv/min)" + +msgid "[Generic] 1996 (5400 RPM)" +msgstr "[Allmän] 1996 (5400 varv/min)" + +msgid "[Generic] 1997 (5400 RPM)" +msgstr "[Allmän] 1997 (5400 varv/min)" + +msgid "[Generic] 1998 (5400 RPM)" +msgstr "[Allmän] 1998 (5400 varv/min)" + +msgid "[Generic] 2000 (7200 RPM)" +msgstr "[Allmän] 2000 (7200 varv/min)" + +msgid "IBM 8514/A clone (ISA)" +msgstr "IBM 8514/A-klon (ISA)" + +msgid "Vendor" +msgstr "Leverantör" + +msgid "30 Hz (JMP2 = 1)" +msgstr "30 Hz (JMP2 = 1)" + +msgid "60 Hz (JMP2 = 2)" +msgstr "60 Hz (JMP2 = 2)" + +msgid "Generic PC/XT Memory Expansion" +msgstr "Allmän minnesexpansion för PC/XT" + +msgid "Generic PC/AT Memory Expansion" +msgstr "Allmän minnesexpansion PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Kunde inte hitta typsnitt för punktmatris" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType-typsnitt i mappen \"roms/printer/fonts\" krävs för emulering av den allmänna ESC/P punktmatrisskrivaren." + +msgid "Inhibit multimedia keys" +msgstr "Hindra multimediatangenter" + +msgid "Ask for confirmation before saving settings" +msgstr "Bekräfta innan inställningarna sparas" + +msgid "Ask for confirmation before hard resetting" +msgstr "Bekräfta innan hård omstart" + +msgid "Ask for confirmation before quitting" +msgstr "Bekräfta innan avslut" + +msgid "Display hotkey message when entering full-screen mode" +msgstr "Visa meddelande om snabbtangenter när helskärmsläget startas" + +msgid "Options" +msgstr "Alternativ" + +msgid "Model" +msgstr "Modell" + +msgid "Model:" +msgstr "Modell:" + +msgid "Failed to initialize Vulkan renderer." +msgstr "Kunde inte initialisera Vulkan-renderaren" + +msgid "GLSL Error" +msgstr "GLSL-fel" + +msgid "Could not load shader: %1" +msgstr "Kunde inte ladda shader: %1" + +msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" +msgstr "OpenGL version 3.0 eller högre krävs. Nuvarande GLSL-version är %1.%2" + +msgid "Could not load texture: %1" +msgstr "Kunde inte ladda textur: %1" + +msgid "Could not compile shader:\n\n%1" +msgstr "Kunde inte kompilera shader:\n\n%1" + +msgid "Program not linked:\n\n%1" +msgstr "Program inte länkat:\n\n%1" + +msgid "Shader Manager" +msgstr "Shader-hanterare" + +msgid "Shader Configuration" +msgstr "Shader-inställningar" + +msgid "Add" +msgstr "Lägg till" + +msgid "Move up" +msgstr "Flytta upp" + +msgid "Move down" +msgstr "Flytta ner" + +msgid "Could not load file %1" +msgstr "Kunde inte ladda fil %1" diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 3903c9d9f..4894b99c0 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -68,6 +68,7 @@ QVector> ProgSettings::languages = { { "ru-RU", "Russian (Russia)" }, { "sk-SK", "Slovak (Slovakia)" }, { "sl-SI", "Slovenian (Slovenia)" }, + { "sv-SE", "Swedish (Sweden)" }, { "es-ES", "Spanish (Spain)" }, { "tr-TR", "Turkish (Turkey)" }, { "uk-UA", "Ukrainian (Ukraine)" }, diff --git a/src/qt/qt_translations.qrc.in b/src/qt/qt_translations.qrc.in index 655323563..c050747c0 100644 --- a/src/qt/qt_translations.qrc.in +++ b/src/qt/qt_translations.qrc.in @@ -20,6 +20,7 @@ 86box_ru-RU.qm 86box_sk-SK.qm 86box_sl-SI.qm + 86box_sv-SE.qm 86box_tr-TR.qm 86box_uk-UA.qm 86box_vi-VN.qm From 38389579c4b89fa9817c56f27490443f17dc1043 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 18 Apr 2025 10:23:23 +0200 Subject: [PATCH 0753/1190] Add Acer P3 (SiS 496). --- src/machine/m_at_386dx_486.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 4e659dd77..ef30a5aa4 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1182,6 +1182,39 @@ machine_at_ms4144_init(const machine_t *model) return ret; } +int +machine_at_acerp3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acerp3/Acer Mate 600 P3 BIOS U13 V2.0R02-J3 ACR8DE00-S00-950911-R02-J3.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + machine_at_sis_85c496_common_init(model); + device_add(&sis_85c496_device); + pci_register_slot(0x09, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x0A, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&fdc37c665_ide_device); + device_add(&keyboard_ps2_acer_pci_device); + device_add(&ide_cmd640_pci_legacy_only_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5434_onboard_pci_device); + + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_486sp3c_init(const machine_t *model) { From 658a00b4c7e3bfea85f095705275c73151220633 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 18 Apr 2025 10:25:16 +0200 Subject: [PATCH 0754/1190] Add Acer P3 machine table entry. --- src/machine/machine_table.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 42ac79417..39d9cc9ff 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8357,6 +8357,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[SiS 496] Acer P3", + .internal_name = "acerp3", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_acerp3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), + .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_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 2048, + .max = 131072, + .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 + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[SiS 496] ASUS PVI-486SP3C", From 40eaeb6ed5897ce9314f5e23ea4be24c422763a4 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 18 Apr 2025 10:26:16 +0200 Subject: [PATCH 0755/1190] Add Acer P3 machine definition. --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 5a552d6eb..4469b55c2 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -571,6 +571,7 @@ extern int machine_at_r418_init(const machine_t *); extern int machine_at_ls486e_init(const machine_t *); extern int machine_at_4dps_init(const machine_t *); extern int machine_at_ms4144_init(const machine_t *); +extern int machine_at_acerp3_init(const machine_t *); extern int machine_at_4saw2_init(const machine_t *); extern int machine_at_m4li_init(const machine_t *); extern int machine_at_alfredo_init(const machine_t *); From af908dadc65ff09f4abf0bbe4ec603ba6cc78ba1 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Fri, 18 Apr 2025 22:32:37 +0700 Subject: [PATCH 0756/1190] Fixed internal_name for Phoenix PS/2 PCI KBC --- src/device/kbc_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index f8fd33e62..447c07780 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2807,7 +2807,7 @@ const device_t keyboard_ps2_acer_pci_device = { const device_t keyboard_ps2_phoenix_pci_device = { .name = "PS/2 Keyboard (Phoenix)", - .internal_name = "keyboard_ps2_acer_pci", + .internal_name = "keyboard_ps2_phoenix_pci", .flags = DEVICE_KBC | DEVICE_PCI, .local = KBC_TYPE_PS2_1 | KBC_VEN_PHOENIX, .init = kbc_at_init, From 13ac57da95999fa58b5cf2a899abd86e76446816 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 19 Apr 2025 13:48:22 +0500 Subject: [PATCH 0757/1190] workflows: Don't rebuild libsndfile on macOS --- .github/workflows/cmake_macos.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml index 5a0454385..2ae417e13 100644 --- a/.github/workflows/cmake_macos.yml +++ b/.github/workflows/cmake_macos.yml @@ -56,22 +56,13 @@ jobs: - name: SDL GUI qt: off static: on - src-packages: >- - libsndfile - name: Qt GUI qt: on slug: -Qt packages: >- qt@5 - src-packages: >- - libsndfile steps: - - name: Install source dependencies - run: >- - brew reinstall -s - ${{ matrix.ui.src-packages }} - - name: Install dependencies run: >- brew install @@ -158,22 +149,13 @@ jobs: - name: SDL GUI qt: off static: on - src-packages: >- - libsndfile - name: Qt GUI qt: on slug: -Qt packages: >- qt@5 - src-packages: >- - libsndfile steps: - - name: Install source dependencies - run: >- - brew reinstall -s - ${{ matrix.ui.src-packages }} - - name: Install dependencies run: >- brew install From bfb3ff8460395219d752f2893cf550e8824258b9 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 19 Apr 2025 18:53:20 -0300 Subject: [PATCH 0758/1190] 7sbb: Fix AGP bridge IRQ links --- src/machine/m_at_socket370.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index b2e311166..3f8db4e8c 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -561,11 +561,11 @@ machine_at_7sbb_init(const machine_t *model) 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); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); 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 +} From 7f5d1b86c76c7afb401ec865617366670556a793 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 19 Apr 2025 19:44:47 -0700 Subject: [PATCH 0759/1190] Added keybind customization system --- CMakeLists.txt | 2 +- src/86box.c | 24 ++++-- src/config.c | 84 +++++++++++++++++++ src/device/keyboard.c | 21 ----- src/include/86box/86box.h | 18 ++-- src/qt/CMakeLists.txt | 5 ++ src/qt/qt.c | 2 +- src/qt/qt_mainwindow.cpp | 70 ++++++++++++++-- src/qt/qt_mainwindow.hpp | 6 +- src/qt/qt_settingsinput.cpp | 159 +++++++++++++++++++++++++++++++++++- src/qt/qt_settingsinput.hpp | 11 +++ src/qt/qt_settingsinput.ui | 118 ++++++++++++++++---------- 12 files changed, 429 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 007c1ffd8..a6ffa89e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,7 @@ if(WIN32) # Default value for the `WIN32` target property, which specifies whether # to build the application for the Windows GUI or console subsystem - option(CMAKE_WIN32_EXECUTABLE "Build a Windows GUI executable" ON) + option(CMAKE_WIN32_EXECUTABLE "Build a Windows GUI executable" OFF) else() # Prefer dynamic builds everywhere else set(PREFER_STATIC OFF) diff --git a/src/86box.c b/src/86box.c index 168e8a8dc..d8c05c8bb 100644 --- a/src/86box.c +++ b/src/86box.c @@ -222,6 +222,9 @@ int other_ide_present = 0; /* IDE control int other_scsi_present = 0; /* SCSI controllers from non-SCSI cards are present */ +// Accelerator key array +struct accelKey acc_keys[NUM_ACCELS]; + /* Statistics. */ extern int mmuflush; extern int readlnum; @@ -654,7 +657,6 @@ usage: #ifdef USE_INSTRUMENT printf("-J or --instrument name - set 'name' to be the profiling instrument\n"); #endif - printf("-K or --keycodes codes - set 'codes' to be the uncapture combination\n"); printf("-L or --logfile path - set 'path' to be the logfile\n"); printf("-M or --missing - dump missing machines and video cards\n"); printf("-N or --noconfirm - do not ask for confirmation on quit\n"); @@ -745,13 +747,6 @@ usage: do_nothing = 1; } else if (!strcasecmp(argv[c], "--nohook") || !strcasecmp(argv[c], "-W")) { hook_enabled = 0; - } else if (!strcasecmp(argv[c], "--keycodes") || !strcasecmp(argv[c], "-K")) { - if ((c + 1) == argc) - goto usage; - - sscanf(argv[++c], "%03hX,%03hX,%03hX,%03hX,%03hX,%03hX", - &key_prefix_1_1, &key_prefix_1_2, &key_prefix_2_1, &key_prefix_2_2, - &key_uncapture_1, &key_uncapture_2); } else if (!strcasecmp(argv[c], "--clearboth") || !strcasecmp(argv[c], "-X")) { if ((c + 1) == argc) goto usage; @@ -1789,3 +1784,16 @@ do_pause(int p) } atomic_store(&pause_ack, 0); } + +// Helper to find an accelerator key and return it's index in acc_keys +int FindAccelerator(const char *name) { + for(int x=0;x= QT_VERSION_CHECK(6, 0, 0) - auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_PageDown), this); + windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_PageDown), this); #else - auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_PageDown), this); + windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_PageDown), this); #endif windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); connect(windowedShortcut, &QShortcut::activated, this, [this] () { @@ -761,6 +762,8 @@ MainWindow::MainWindow(QWidget *parent) }); } #endif + + updateShortcuts(); } void @@ -826,6 +829,56 @@ MainWindow::closeEvent(QCloseEvent *event) event->accept(); } + +void MainWindow::updateShortcuts() +{ + // Update menu shortcuts from accelerator table + // Note that the "Release mouse" shortcut is hardcoded elsewhere + // This section only applies to shortcuts anchored to UI elements + + ui->actionTake_screenshot->setShortcut(QKeySequence()); + ui->actionCtrl_Alt_Del->setShortcut(QKeySequence()); + ui->actionCtrl_Alt_Esc->setShortcut(QKeySequence()); + ui->actionFullscreen->setShortcut(QKeySequence()); + ui->actionHard_Reset->setShortcut(QKeySequence()); + + int accID; + QKeySequence seq; + + accID = FindAccelerator("screenshot"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionTake_screenshot->setShortcut(seq); + + accID = FindAccelerator("send_ctrl_alt_del"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionCtrl_Alt_Del->setShortcut(seq); + + accID = FindAccelerator("send_ctrl_alt_esc"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionCtrl_Alt_Esc->setShortcut(seq); + + accID = FindAccelerator("fullscreen"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + //printf("shortcut: %s\n", qPrintable(ui->actionFullscreen->shortcut().toString())); + ui->actionFullscreen->setShortcut(seq); + + accID = FindAccelerator("hard_reset"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionHard_Reset->setShortcut(seq); + + // To rebind leave_fullscreen we have to disconnect the existing signal, + // build a new shortcut, then connect it. + accID = FindAccelerator("leave_fullscreen"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + disconnect(windowedShortcut,0,0,0); + windowedShortcut = new QShortcut(seq, this); + windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); + connect(windowedShortcut, &QShortcut::activated, this, [this] () { + if (video_fullscreen) + ui->actionFullscreen->trigger(); + }); +} + void MainWindow::resizeEvent(QResizeEvent *event) { @@ -1026,6 +1079,8 @@ MainWindow::on_actionSettings_triggered() case QDialog::Accepted: settings.save(); config_changed = 2; + printf("about to try\n"); + updateShortcuts(); pc_reset_hard(); break; case QDialog::Rejected: @@ -1394,9 +1449,14 @@ MainWindow::keyPressEvent(QKeyEvent *event) #endif } - if (keyboard_ismsexit()) - plat_mouse_capture(0); - + // Check if mouse release combo has been entered + int accID = FindAccelerator("release_mouse"); + QKeySequence seq = QKeySequence::fromString(acc_keys[accID].seq); + if (seq[0] == (event->key() | event->modifiers())) + plat_mouse_capture(0); + + // TODO: Other accelerators should probably be here? + event->accept(); } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 739d179ff..99b0021c2 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,8 @@ public: QSize getRenderWidgetSize(); void setSendKeyboardInput(bool enabled); void reloadAllRenderers(); - + QShortcut *windowedShortcut; + std::array, 8> renderers; signals: void paint(const QImage &image); @@ -159,6 +161,7 @@ private: std::unique_ptr status; std::shared_ptr mm; + void updateShortcuts(); void processKeyboardInput(bool down, uint32_t keycode); #ifdef Q_OS_MACOS uint32_t last_modifiers = 0; @@ -184,7 +187,6 @@ private: friend class RendererStack; // For UI variable access by non-primary renderer windows. friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. - bool isShowMessage = false; }; diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index d7c61e8d2..924594083 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -16,8 +16,11 @@ */ #include "qt_settingsinput.hpp" #include "ui_qt_settingsinput.h" +#include "qt_mainwindow.hpp" #include +#include +#include extern "C" { #include <86box/86box.h> @@ -25,11 +28,18 @@ extern "C" { #include <86box/machine.h> #include <86box/mouse.h> #include <86box/gameport.h> +#include <86box/ui.h> } #include "qt_models_common.hpp" #include "qt_deviceconfig.hpp" #include "qt_joystickconfiguration.hpp" +#include "qt_keybind.hpp" + +extern MainWindow *main_window; + +// Temporary working copy of key list +accelKey acc_keys_t[NUM_ACCELS]; SettingsInput::SettingsInput(QWidget *parent) : QWidget(parent) @@ -37,9 +47,55 @@ SettingsInput::SettingsInput(QWidget *parent) { ui->setupUi(this); + QStandardItemModel *model; + QStringList horizontalHeader; + QStringList verticalHeader; + + horizontalHeader.append("Action"); + horizontalHeader.append("Keybind"); + + QTableWidget *keyTable = ui->tableKeys; + keyTable->setRowCount(10); + keyTable->setColumnCount(3); + keyTable->setColumnHidden(2, true); + keyTable->setColumnWidth(0, 200); + keyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + QStringList headers; + headers << "Action" << "Bound key"; + keyTable->setHorizontalHeaderLabels(headers); + keyTable->verticalHeader()->setVisible(false); + keyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + keyTable->setSelectionBehavior(QAbstractItemView::SelectRows); + keyTable->setSelectionMode(QAbstractItemView::SingleSelection); + keyTable->setShowGrid(true); + keyTable->setStyleSheet("QTableWidget::item:hover { }"); + keyTable->setFocusPolicy(Qt::NoFocus); + keyTable->setSelectionMode(QAbstractItemView::NoSelection); + + // Make a working copy of acc_keys so we can check for dupes later without getting + // confused + printf("Instantiating list\n"); + for(int x=0;xtableKeys, &QTableWidget::cellDoubleClicked, + this, &SettingsInput::on_tableKeys_doubleClicked); + + connect(ui->pushButtonBind, &QPushButton::clicked, + this, &SettingsInput::on_pushButtonBind_Clicked); + + connect(ui->pushButtonClearBind, &QPushButton::clicked, + this, &SettingsInput::on_pushButtonClearBind_Clicked); + onCurrentMachineChanged(machine); } + SettingsInput::~SettingsInput() { delete ui; @@ -50,8 +106,15 @@ SettingsInput::save() { mouse_type = ui->comboBoxMouse->currentData().toInt(); joystick_type = ui->comboBoxJoystick->currentData().toInt(); + + // Copy accelerators from working set to global set + for(int x=0;xcomboBoxJoystick->setCurrentIndex(selectedRow); } +void +SettingsInput::refreshInputList() +{ + + for (int x=0;xtableKeys->setItem(x, 0, new QTableWidgetItem(acc_keys_t[x].desc)); + ui->tableKeys->setItem(x, 1, new QTableWidgetItem(acc_keys_t[x].seq)); + ui->tableKeys->setItem(x, 2, new QTableWidgetItem(acc_keys_t[x].name)); + } +} + +void +SettingsInput::on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn) +{ + // Enable/disable bind/clear buttons if user clicked valid row + QTableWidgetItem *cell = ui->tableKeys->item(currentRow,1); + if (!cell) + { + ui->pushButtonBind->setEnabled(false); + ui->pushButtonClearBind->setEnabled(false); + } + else + { + ui->pushButtonBind->setEnabled(true); + ui->pushButtonClearBind->setEnabled(true); + } +} + +void +SettingsInput::on_tableKeys_doubleClicked(int row, int col) +{ + // Edit bind + QTableWidgetItem *cell = ui->tableKeys->item(row,1); + if (!cell) return; + + QKeySequence keyseq = KeyBinder::BindKey(cell->text()); + if (keyseq != false) { + // If no change was made, don't change anything. + if (keyseq.toString(QKeySequence::NativeText) == cell->text()) return; + + // Otherwise, check for conflicts. + // Check against the *working* copy - NOT the one in use by the app, + // so we don't test against shortcuts the user already changed. + for(int x=0;xshowMessage(MBX_ANSI & MBX_INFO, "Bind conflict", "This key combo is already in use", false); + return; + } + } + // If we made it here, there were no conflicts. + // Go ahead and apply the bind. + + // Find the correct accelerator key entry + int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(row,2)->text())); + if (!accKeyID) return; // this should never happen + + // Make the change + cell->setText(keyseq.toString(QKeySequence::NativeText)); + strcpy(acc_keys_t[accKeyID].seq, qPrintable(keyseq.toString(QKeySequence::NativeText))); + + refreshInputList(); + } +} + +void +SettingsInput::on_pushButtonBind_Clicked() +{ + // Edit bind + QTableWidgetItem *cell = ui->tableKeys->currentItem(); + if (!cell) return; + + on_tableKeys_doubleClicked(cell->row(), cell->column()); +} + +void +SettingsInput::on_pushButtonClearBind_Clicked() +{ + // Wipe bind + QTableWidgetItem *cell = ui->tableKeys->currentItem(); + if (!cell) return; + + cell->setText(""); + // Find the correct accelerator key entry + int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(cell->row(),2)->text())); + if (!accKeyID) return; // this should never happen + + // Make the change + cell->setText(""); + strcpy(acc_keys_t[accKeyID].seq, ""); +} + void SettingsInput::on_comboBoxMouse_currentIndexChanged(int index) { diff --git a/src/qt/qt_settingsinput.hpp b/src/qt/qt_settingsinput.hpp index 0b8b665aa..ec7dc393b 100644 --- a/src/qt/qt_settingsinput.hpp +++ b/src/qt/qt_settingsinput.hpp @@ -2,6 +2,12 @@ #define QT_SETTINGSINPUT_HPP #include +#include +#include +#include +#include +#include +#include namespace Ui { class SettingsInput; @@ -27,10 +33,15 @@ private slots: void on_pushButtonJoystick2_clicked(); void on_pushButtonJoystick3_clicked(); void on_pushButtonJoystick4_clicked(); + void on_tableKeys_doubleClicked(int row, int col); + void on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); + void on_pushButtonBind_Clicked(); + void on_pushButtonClearBind_Clicked(); private: Ui::SettingsInput *ui; int machineId = 0; + void refreshInputList(); }; #endif // QT_SETTINGSINPUT_HPP diff --git a/src/qt/qt_settingsinput.ui b/src/qt/qt_settingsinput.ui index 839461119..b7074eeaa 100644 --- a/src/qt/qt_settingsinput.ui +++ b/src/qt/qt_settingsinput.ui @@ -23,17 +23,16 @@ 0 - - - - Joystick 2... + + + + + 0 + 0 + - - - - - - Joystick: + + 30 @@ -44,13 +43,6 @@ - - - - Mouse: - - - @@ -58,21 +50,15 @@ - - - - Qt::Vertical + + + + false - - QSizePolicy::Expanding + + Bind - - - 20 - 40 - - - + @@ -81,6 +67,44 @@ + + + + 30 + + + + + + + Mouse: + + + + + + + false + + + Clear binding + + + + + + + Joystick: + + + + + + + Joystick 2... + + + @@ -94,23 +118,29 @@ - - - - 30 - - - - 0 - 0 - + + + + Key Bindings: - - - - 30 + + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + false + + + false + + + true + + + QAbstractItemView::SelectionBehavior::SelectRows From f199fa5ce4b4b58ba0b857921b8f492ba3f10faa Mon Sep 17 00:00:00 2001 From: = Date: Sat, 19 Apr 2025 19:50:45 -0700 Subject: [PATCH 0760/1190] Added new UI files --- src/qt/qt_keybind.cpp | 95 ++++++++++++++++++++++++++++++++++ src/qt/qt_keybind.hpp | 32 ++++++++++++ src/qt/qt_keybind.ui | 85 ++++++++++++++++++++++++++++++ src/qt/qt_singlekeyseqedit.cpp | 20 +++++++ src/qt/qt_singlekeyseqedit.hpp | 16 ++++++ 5 files changed, 248 insertions(+) create mode 100644 src/qt/qt_keybind.cpp create mode 100644 src/qt/qt_keybind.hpp create mode 100644 src/qt/qt_keybind.ui create mode 100644 src/qt/qt_singlekeyseqedit.cpp create mode 100644 src/qt/qt_singlekeyseqedit.hpp diff --git a/src/qt/qt_keybind.cpp b/src/qt/qt_keybind.cpp new file mode 100644 index 000000000..dcfe424d9 --- /dev/null +++ b/src/qt/qt_keybind.cpp @@ -0,0 +1,95 @@ +/* + * 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. + * + * Device configuration UI code. + * + * + * + * Authors: Joakim L. Gilje + * Cacodemon345 + * + * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 + */ +#include "qt_keybind.hpp" +#include "ui_qt_keybind.h" +#include "qt_settings.hpp" +#include "qt_singlekeyseqedit.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include <86box/86box.h> +#include <86box/ini.h> +#include <86box/config.h> +#include <86box/device.h> +#include <86box/midi_rtmidi.h> +#include <86box/mem.h> +#include <86box/random.h> +#include <86box/rom.h> +} + +#include "qt_filefield.hpp" +#include "qt_models_common.hpp" +#ifdef Q_OS_LINUX +# include +# include +#endif +#ifdef Q_OS_WINDOWS +#include +#endif + +KeyBinder::KeyBinder(QWidget *parent) + : QDialog(parent) + , ui(new Ui::KeyBinder) +{ + ui->setupUi(this); + singleKeySequenceEdit *seq = new singleKeySequenceEdit(); + ui->formLayout->addRow(seq); + seq->setObjectName("keySequence"); +} + +KeyBinder::~KeyBinder() +{ + delete ui; +} + + +bool KeyBinder::eventFilter(QObject *obj, QEvent *event) +{ + return QObject::eventFilter(obj, event); +} + +QKeySequence +KeyBinder::BindKey(QString CurValue) +{ + KeyBinder kb; + kb.setWindowTitle("Bind Key"); + kb.setFixedSize(kb.minimumSizeHint()); + kb.findChild()->setKeySequence(QKeySequence::fromString(CurValue)); + + if (kb.exec() == QDialog::Accepted) { + QKeySequenceEdit *seq = kb.findChild(); + return (seq->keySequence()); + } else { + return (false); + } +} \ No newline at end of file diff --git a/src/qt/qt_keybind.hpp b/src/qt/qt_keybind.hpp new file mode 100644 index 000000000..afb750794 --- /dev/null +++ b/src/qt/qt_keybind.hpp @@ -0,0 +1,32 @@ +#ifndef QT_KeyBinder_HPP +#define QT_KeyBinder_HPP + +#include + +#include "qt_settings.hpp" + +extern "C" { +struct _device_; +} + +namespace Ui { +class KeyBinder; +} + +class Settings; + +class KeyBinder : public QDialog { + Q_OBJECT + +public: + explicit KeyBinder(QWidget *parent = nullptr); + ~KeyBinder() override; + + static QKeySequence BindKey(QString CurValue); + +private: + Ui::KeyBinder *ui; + bool eventFilter(QObject *obj, QEvent *event); +}; + +#endif // QT_KeyBinder_HPP diff --git a/src/qt/qt_keybind.ui b/src/qt/qt_keybind.ui new file mode 100644 index 000000000..835e12020 --- /dev/null +++ b/src/qt/qt_keybind.ui @@ -0,0 +1,85 @@ + + + KeyBinder + + + + 0 + 0 + 400 + 103 + + + + Dialog + + + + + + + + Enter key combo: + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + Qt::Orientation::Horizontal + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + + + buttonBox + accepted() + KeyBinder + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + KeyBinder + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qt_singlekeyseqedit.cpp b/src/qt/qt_singlekeyseqedit.cpp new file mode 100644 index 000000000..f17d2164f --- /dev/null +++ b/src/qt/qt_singlekeyseqedit.cpp @@ -0,0 +1,20 @@ +#include "qt_singlekeyseqedit.hpp" + +/* + This subclass of QKeySequenceEdit restricts the input to only a single + shortcut instead of an unlimited number with a fixed timeout. +*/ + +singleKeySequenceEdit::singleKeySequenceEdit(QWidget *parent) : QKeySequenceEdit(parent) {} + +void singleKeySequenceEdit::keyPressEvent(QKeyEvent *event) +{ + QKeySequenceEdit::keyPressEvent(event); + if (this->keySequence().count() > 0) { + QKeySequenceEdit::setKeySequence(this->keySequence()); + + // This could have unintended consequences since it will happen + // every single time the user presses a key. + emit editingFinished(); + } +} \ No newline at end of file diff --git a/src/qt/qt_singlekeyseqedit.hpp b/src/qt/qt_singlekeyseqedit.hpp new file mode 100644 index 000000000..43ebe70b2 --- /dev/null +++ b/src/qt/qt_singlekeyseqedit.hpp @@ -0,0 +1,16 @@ +#ifndef SINGLEKEYSEQUENCEEDIT_H +#define SINGLEKEYSEQUENCEEDIT_H + +#include +#include + +class singleKeySequenceEdit : public QKeySequenceEdit +{ + Q_OBJECT +public: + singleKeySequenceEdit(QWidget *parent = nullptr); + + void keyPressEvent(QKeyEvent *) override; +}; + +#endif // SINGLEKEYSEQUENCEEDIT_H From 34620f3246c6b31713fd0ced517dd68c2ef8b900 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 19 Apr 2025 20:04:00 -0700 Subject: [PATCH 0761/1190] Auto-set focus on keybind dialog --- src/config.c | 2 -- src/qt/qt_keybind.cpp | 6 ++++++ src/qt/qt_keybind.hpp | 1 + src/qt/qt_mainwindow.cpp | 1 - src/qt/qt_settingsinput.cpp | 1 - 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/config.c b/src/config.c index d537711d9..2bea312a9 100644 --- a/src/config.c +++ b/src/config.c @@ -2558,10 +2558,8 @@ save_keybinds(void) for(int x=0;xformLayout->addRow(seq); seq->setObjectName("keySequence"); + this->setTabOrder(seq, ui->buttonBox); } KeyBinder::~KeyBinder() @@ -72,6 +73,11 @@ KeyBinder::~KeyBinder() delete ui; } +void +KeyBinder::showEvent( QShowEvent* event ) { + QWidget::showEvent( event ); + this->findChild()->setFocus(); +} bool KeyBinder::eventFilter(QObject *obj, QEvent *event) { diff --git a/src/qt/qt_keybind.hpp b/src/qt/qt_keybind.hpp index afb750794..e8e7b6e5e 100644 --- a/src/qt/qt_keybind.hpp +++ b/src/qt/qt_keybind.hpp @@ -27,6 +27,7 @@ public: private: Ui::KeyBinder *ui; bool eventFilter(QObject *obj, QEvent *event); + void showEvent( QShowEvent* event ); }; #endif // QT_KeyBinder_HPP diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index ed9bf92a7..9fa38bfb1 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1079,7 +1079,6 @@ MainWindow::on_actionSettings_triggered() case QDialog::Accepted: settings.save(); config_changed = 2; - printf("about to try\n"); updateShortcuts(); pc_reset_hard(); break; diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 924594083..aa232df67 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -74,7 +74,6 @@ SettingsInput::SettingsInput(QWidget *parent) // Make a working copy of acc_keys so we can check for dupes later without getting // confused - printf("Instantiating list\n"); for(int x=0;x Date: Sat, 19 Apr 2025 20:11:17 -0700 Subject: [PATCH 0762/1190] Fixed bug in keybind UI --- src/qt/qt_mainwindow.cpp | 1 - src/qt/qt_settingsinput.cpp | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 9fa38bfb1..dc97c6294 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -859,7 +859,6 @@ void MainWindow::updateShortcuts() accID = FindAccelerator("fullscreen"); seq = QKeySequence::fromString(acc_keys[accID].seq); - //printf("shortcut: %s\n", qPrintable(ui->actionFullscreen->shortcut().toString())); ui->actionFullscreen->setShortcut(seq); accID = FindAccelerator("hard_reset"); diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index aa232df67..3be460a4a 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -68,9 +68,6 @@ SettingsInput::SettingsInput(QWidget *parent) keyTable->setSelectionBehavior(QAbstractItemView::SelectRows); keyTable->setSelectionMode(QAbstractItemView::SingleSelection); keyTable->setShowGrid(true); - keyTable->setStyleSheet("QTableWidget::item:hover { }"); - keyTable->setFocusPolicy(Qt::NoFocus); - keyTable->setSelectionMode(QAbstractItemView::NoSelection); // Make a working copy of acc_keys so we can check for dupes later without getting // confused @@ -224,7 +221,7 @@ SettingsInput::on_tableKeys_doubleClicked(int row, int col) // Find the correct accelerator key entry int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(row,2)->text())); - if (!accKeyID) return; // this should never happen + if (accKeyID < 0) return; // this should never happen // Make the change cell->setText(keyseq.toString(QKeySequence::NativeText)); @@ -254,7 +251,7 @@ SettingsInput::on_pushButtonClearBind_Clicked() cell->setText(""); // Find the correct accelerator key entry int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(cell->row(),2)->text())); - if (!accKeyID) return; // this should never happen + if (accKeyID < 0) return; // this should never happen // Make the change cell->setText(""); From 4c20994d5962c654e13285b524e40468a0cae68b Mon Sep 17 00:00:00 2001 From: = Date: Sat, 19 Apr 2025 23:50:03 -0700 Subject: [PATCH 0763/1190] Removed broken refs to fix -nix build --- src/config.c | 3 +-- src/include/86box/keyboard.h | 1 - src/unix/unix.c | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/config.c b/src/config.c index 2bea312a9..dcabcd922 100644 --- a/src/config.c +++ b/src/config.c @@ -1807,7 +1807,7 @@ load_keybinds(void) { p = ini_section_get_string(cat, acc_keys[x].name, "none"); // If there's no binding in the file, leave it alone. - if (p != "none") + if (strcmp(p, "none") != 0) { // It would be ideal to validate whether the user entered a // valid combo at this point, but the Qt method for testing that is @@ -2553,7 +2553,6 @@ static void save_keybinds(void) { ini_section_t cat = ini_find_or_create_section(config, "Keybinds"); - char temp[512]; for(int x=0;x Date: Sun, 20 Apr 2025 14:04:23 +0200 Subject: [PATCH 0764/1190] BusLogic SCSI controllers: Add a proper device reset functions, fixes POST error on Intel AMI BIOS'es after exiting AUTO-SCSI using the Esc key. --- src/scsi/scsi_buslogic.c | 57 +++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 9fe34380b..352232e34 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -256,6 +256,8 @@ buslogic_log(const char *fmt, ...) # define buslogic_log(fmt, ...) #endif +static x54x_t reset_state = { 0 }; + static char * BuslogicGetNVRFileName(buslogic_data_t *bl) { @@ -1084,7 +1086,7 @@ buslogic_interrupt_type(void *priv) } static void -buslogic_reset(void *priv) +buslogic_ven_reset(void *priv) { x54x_t *dev = (x54x_t *) priv; buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; @@ -1525,6 +1527,39 @@ BuslogicDeviceReset(void *priv) BuslogicInitializeAutoSCSIRam(dev); } +static void +buslogic_reset(void *priv) +{ + x54x_t *dev = (x54x_t *) priv; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + + x54x_io_remove(dev, dev->Base, 4); + + if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { + x54x_mem_init(dev, 0xfffd0000); + x54x_mem_disable(dev); + } + + timer_disable(&dev->timer); + timer_disable(&dev->ResetCB); + + reset_state.mmio_mapping = dev->mmio_mapping; + + reset_state.bios.mapping = dev->bios.mapping; + reset_state.uppersck.mapping = dev->uppersck.mapping; + + reset_state.timer = dev->timer; + reset_state.ResetCB = dev->ResetCB; + + memcpy(dev, &reset_state, sizeof(x54x_t)); + + dev->timer.period = 10.0; + timer_set_delay_u64(&dev->timer, (uint64_t) (dev->timer.period * ((double) TIMER_USEC))); + + if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) + x54x_io_set(dev, dev->Base, 4); +} + static void * buslogic_init(const device_t *info) { @@ -1586,7 +1621,7 @@ buslogic_init(const device_t *info) dev->interrupt_type = buslogic_interrupt_type; dev->is_aggressive_mode = buslogic_is_aggressive_mode; dev->get_ven_data = buslogic_setup_data; - dev->ven_reset = buslogic_reset; + dev->ven_reset = buslogic_ven_reset; strcpy(dev->vendor, "BusLogic"); @@ -1774,6 +1809,8 @@ buslogic_init(const device_t *info) BuslogicInitializeAutoSCSIRam(dev); } + memcpy(&reset_state, dev, sizeof(x54x_t)); + return dev; } @@ -1876,7 +1913,7 @@ const device_t buslogic_542b_device = { .local = CHIP_BUSLOGIC_ISA_542B_1991_12_14, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1890,7 +1927,7 @@ const device_t buslogic_545s_device = { .local = CHIP_BUSLOGIC_ISA_545S_1992_10_05, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1904,7 +1941,7 @@ const device_t buslogic_542bh_device = { .local = CHIP_BUSLOGIC_ISA_542BH_1993_05_23, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1918,7 +1955,7 @@ const device_t buslogic_545c_device = { .local = CHIP_BUSLOGIC_ISA_545C_1994_12_01, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1932,7 +1969,7 @@ const device_t buslogic_640a_device = { .local = CHIP_BUSLOGIC_MCA_640A_1993_05_23, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1946,7 +1983,7 @@ const device_t buslogic_445s_device = { .local = CHIP_BUSLOGIC_VLB_445S_1993_11_16, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1960,7 +1997,7 @@ const device_t buslogic_445c_device = { .local = CHIP_BUSLOGIC_VLB_445C_1994_12_01, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -1974,7 +2011,7 @@ const device_t buslogic_958d_pci_device = { .local = CHIP_BUSLOGIC_PCI_958D_1995_12_30, .init = buslogic_init, .close = x54x_close, - .reset = NULL, + .reset = buslogic_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, From aefcdc9e01ebdd7bac314f0a2c3fabdff6b2df8e Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 13:43:14 -0700 Subject: [PATCH 0765/1190] Merged fullscreen combos. Fixed bug when config file can't be loaded. --- src/86box.c | 30 +++++++++++++++++++++++++ src/config.c | 30 ------------------------- src/include/86box/86box.h | 3 ++- src/qt/qt_mainwindow.cpp | 46 +++++++++++++++++---------------------- 4 files changed, 52 insertions(+), 57 deletions(-) diff --git a/src/86box.c b/src/86box.c index d8c05c8bb..d650b8432 100644 --- a/src/86box.c +++ b/src/86box.c @@ -225,6 +225,28 @@ int other_scsi_present = 0; /* SCSI contro // Accelerator key array struct accelKey acc_keys[NUM_ACCELS]; +// Default accelerator key values +struct accelKey def_acc_keys[NUM_ACCELS] = { + { .name="send_ctrl_alt_del", .desc="Send Control+Alt+Del", + .seq="Ctrl+F12" }, + + { .name="send_ctrl_alt_esc", .desc="Send Control+Alt+Escape", + .seq="Ctrl+F10" }, + + { .name="fullscreen", .desc="Toggle fullscreen", + .seq="Ctrl+Alt+PgUp" }, + + { .name="screenshot", .desc="Screenshot", + .seq="Ctrl+F11" }, + + { .name="release_mouse", .desc="Release mouse pointer", + .seq="Ctrl+End" }, + + { .name="hard_reset", .desc="Hard reset", + .seq="Ctrl+Alt+F12" } +}; + + /* Statistics. */ extern int mmuflush; extern int readlnum; @@ -998,6 +1020,14 @@ usage: gdbstub_init(); + // Initialize the keyboard accelerator list with default values + for(int x=0;x= QT_VERSION_CHECK(6, 0, 0) - windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_PageDown), this); -#else - windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_PageDown), this); -#endif - windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); - connect(windowedShortcut, &QShortcut::activated, this, [this] () { - if (video_fullscreen) - ui->actionFullscreen->trigger(); - }); - connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot); connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection); connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot); @@ -836,10 +825,11 @@ void MainWindow::updateShortcuts() // Note that the "Release mouse" shortcut is hardcoded elsewhere // This section only applies to shortcuts anchored to UI elements + // First we need to wipe all existing accelerators, otherwise Qt will + // run into conflicts with old ones. ui->actionTake_screenshot->setShortcut(QKeySequence()); ui->actionCtrl_Alt_Del->setShortcut(QKeySequence()); ui->actionCtrl_Alt_Esc->setShortcut(QKeySequence()); - ui->actionFullscreen->setShortcut(QKeySequence()); ui->actionHard_Reset->setShortcut(QKeySequence()); int accID; @@ -857,25 +847,13 @@ void MainWindow::updateShortcuts() seq = QKeySequence::fromString(acc_keys[accID].seq); ui->actionCtrl_Alt_Esc->setShortcut(seq); - accID = FindAccelerator("fullscreen"); - seq = QKeySequence::fromString(acc_keys[accID].seq); - ui->actionFullscreen->setShortcut(seq); - accID = FindAccelerator("hard_reset"); seq = QKeySequence::fromString(acc_keys[accID].seq); ui->actionHard_Reset->setShortcut(seq); - // To rebind leave_fullscreen we have to disconnect the existing signal, - // build a new shortcut, then connect it. - accID = FindAccelerator("leave_fullscreen"); + accID = FindAccelerator("fullscreen"); seq = QKeySequence::fromString(acc_keys[accID].seq); - disconnect(windowedShortcut,0,0,0); - windowedShortcut = new QShortcut(seq, this); - windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); - connect(windowedShortcut, &QShortcut::activated, this, [this] () { - if (video_fullscreen) - ui->actionFullscreen->trigger(); - }); + ui->actionFullscreen->setShortcut(seq); } void @@ -1361,6 +1339,20 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) if (event->type() == QEvent::KeyPress) { event->accept(); this->keyPressEvent((QKeyEvent *) event); + + // Detect fullscreen shortcut when menubar is hidden + int accID = FindAccelerator("fullscreen"); + QKeySequence seq = QKeySequence::fromString(acc_keys[accID].seq); + + if (event->type() == QEvent::KeyPress) + { + QKeyEvent *ke = (QKeyEvent *) event; + if ((QKeySequence)(ke->key() | ke->modifiers()) == seq && video_fullscreen != 0) + { + ui->actionFullscreen->trigger(); + } + } + return true; } if (event->type() == QEvent::KeyRelease) { @@ -1380,6 +1372,8 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) plat_pause(curdopause); } } + + return QMainWindow::eventFilter(receiver, event); } From 24a4ed445e3b1805c4f230bdd3b394b85fba0a1d Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 13:59:52 -0700 Subject: [PATCH 0766/1190] All shortcuts now work in fullscreen --- src/qt/qt_mainwindow.cpp | 45 +++++++++++++++++++++++++++++++++------- src/qt/qt_mainwindow.hpp | 2 ++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e57c7b96f..2b3eda4af 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1325,6 +1325,19 @@ MainWindow::getTitle(wchar_t *title) } } + +// Helper to find an accelerator key and return it's sequence +// TODO: Is there a more central place to put this? +QKeySequence +MainWindow::FindAcceleratorSeq(const char *name) +{ + int accID = FindAccelerator(name); + if(accID == -1) + return false; + + return(QKeySequence::fromString(acc_keys[accID].seq)); +} + bool MainWindow::eventFilter(QObject *receiver, QEvent *event) { @@ -1337,22 +1350,40 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) } } if (event->type() == QEvent::KeyPress) { - event->accept(); this->keyPressEvent((QKeyEvent *) event); - // Detect fullscreen shortcut when menubar is hidden - int accID = FindAccelerator("fullscreen"); - QKeySequence seq = QKeySequence::fromString(acc_keys[accID].seq); + // Detect shortcuts when menubar is hidden + // TODO: Could this be simplified by proxying the event and manually + // shoving it into the menubar? + QKeySequence accKey; - if (event->type() == QEvent::KeyPress) + if (event->type() == QEvent::KeyPress && video_fullscreen != 0) { QKeyEvent *ke = (QKeyEvent *) event; - if ((QKeySequence)(ke->key() | ke->modifiers()) == seq && video_fullscreen != 0) + + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("screenshot")) { - ui->actionFullscreen->trigger(); + ui->actionTake_screenshot->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_del")) + { + ui->actionCtrl_Alt_Del->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_esc")) + { + ui->actionCtrl_Alt_Esc->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("hard_reset")) + { + ui->actionHard_Reset->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("fullscreen")) + { + ui->actionFullscreen->trigger(); } } + event->accept(); return true; } if (event->type() == QEvent::KeyRelease) { diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 99b0021c2..5811ac36a 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -34,6 +34,8 @@ public: void setSendKeyboardInput(bool enabled); void reloadAllRenderers(); QShortcut *windowedShortcut; + QKeySequence FindAcceleratorSeq(const char *name); + std::array, 8> renderers; signals: From ba19b8af895fab71442dbeaf1932c0a48c2abb26 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 20 Apr 2025 23:19:17 +0200 Subject: [PATCH 0767/1190] x86_64 new recompile: fix registers clean-up on block exit. --- src/codegen_new/codegen_backend_x86-64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen_new/codegen_backend_x86-64.c b/src/codegen_new/codegen_backend_x86-64.c index 6242ea40b..20d02a8db 100644 --- a/src/codegen_new/codegen_backend_x86-64.c +++ b/src/codegen_new/codegen_backend_x86-64.c @@ -329,7 +329,7 @@ codegen_backend_init(void) host_x86_POP(block, REG_RSI); #endif host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RBX); host_x86_RET(block); block_write_data = NULL; @@ -392,7 +392,7 @@ codegen_backend_epilogue(codeblock_t *block) host_x86_POP(block, REG_RSI); #endif host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RBX); host_x86_RET(block); } #endif From 9febdd1510346744e0edc114054a92353117acb2 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 14:28:10 -0700 Subject: [PATCH 0768/1190] Added pause shortcut. --- src/86box.c | 5 +- src/include/86box/86box.h | 2 +- src/qt/qt_mainwindow.cpp | 105 ++++++++++++++++++++++---------------- 3 files changed, 66 insertions(+), 46 deletions(-) diff --git a/src/86box.c b/src/86box.c index d650b8432..e3d1e785c 100644 --- a/src/86box.c +++ b/src/86box.c @@ -243,7 +243,10 @@ struct accelKey def_acc_keys[NUM_ACCELS] = { .seq="Ctrl+End" }, { .name="hard_reset", .desc="Hard reset", - .seq="Ctrl+Alt+F12" } + .seq="Ctrl+Alt+F12" }, + + { .name="pause", .desc="Toggle pause", + .seq="Ctrl+Alt+F1" } }; diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 4dcd521e0..51f1dbcbc 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -242,7 +242,7 @@ struct accelKey { char desc[64]; char seq[64]; }; -#define NUM_ACCELS 6 +#define NUM_ACCELS 7 extern struct accelKey acc_keys[NUM_ACCELS]; extern struct accelKey def_acc_keys[NUM_ACCELS]; extern int FindAccelerator(const char *name); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 2b3eda4af..ad1c0e2a0 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -821,9 +821,13 @@ MainWindow::closeEvent(QCloseEvent *event) void MainWindow::updateShortcuts() { - // Update menu shortcuts from accelerator table - // Note that the "Release mouse" shortcut is hardcoded elsewhere - // This section only applies to shortcuts anchored to UI elements + /* + Update menu shortcuts from accelerator table + Note that the "Release mouse" shortcut is hardcoded elsewhere + This section only applies to shortcuts anchored to UI elements + + MainWindow::eventFilter + */ // First we need to wipe all existing accelerators, otherwise Qt will // run into conflicts with old ones. @@ -831,6 +835,7 @@ void MainWindow::updateShortcuts() ui->actionCtrl_Alt_Del->setShortcut(QKeySequence()); ui->actionCtrl_Alt_Esc->setShortcut(QKeySequence()); ui->actionHard_Reset->setShortcut(QKeySequence()); + ui->actionPause->setShortcut(QKeySequence()); int accID; QKeySequence seq; @@ -854,6 +859,10 @@ void MainWindow::updateShortcuts() accID = FindAccelerator("fullscreen"); seq = QKeySequence::fromString(acc_keys[accID].seq); ui->actionFullscreen->setShortcut(seq); + + accID = FindAccelerator("pause"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionPause->setShortcut(seq); } void @@ -1341,6 +1350,54 @@ MainWindow::FindAcceleratorSeq(const char *name) bool MainWindow::eventFilter(QObject *receiver, QEvent *event) { + // Detect shortcuts when menubar is hidden + // TODO: Could this be simplified by proxying the event and manually + // shoving it into the menubar? + + // Note: This section should ONLY contain shortcuts that are valid + // when the emulator + if (event->type() == QEvent::KeyPress) + { + this->keyPressEvent((QKeyEvent *) event); + + if (event->type() == QEvent::KeyPress && video_fullscreen != 0) + { + QKeyEvent *ke = (QKeyEvent *) event; + + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("release_mouse")) + { + qDebug() << ke; + plat_mouse_capture(0); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("screenshot")) + { + ui->actionTake_screenshot->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("fullscreen")) + { + ui->actionFullscreen->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("hard_reset")) + { + ui->actionHard_Reset->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_del")) + { + ui->actionCtrl_Alt_Del->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_esc")) + { + ui->actionCtrl_Alt_Esc->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("pause")) + { + ui->actionPause->trigger(); + } + return true; + } + } + + if (!dopause) { if (event->type() == QEvent::Shortcut) { auto shortcutEvent = (QShortcutEvent *) event; @@ -1350,40 +1407,8 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) } } if (event->type() == QEvent::KeyPress) { - this->keyPressEvent((QKeyEvent *) event); - - // Detect shortcuts when menubar is hidden - // TODO: Could this be simplified by proxying the event and manually - // shoving it into the menubar? - QKeySequence accKey; - - if (event->type() == QEvent::KeyPress && video_fullscreen != 0) - { - QKeyEvent *ke = (QKeyEvent *) event; - - if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("screenshot")) - { - ui->actionTake_screenshot->trigger(); - } - if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_del")) - { - ui->actionCtrl_Alt_Del->trigger(); - } - if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_esc")) - { - ui->actionCtrl_Alt_Esc->trigger(); - } - if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("hard_reset")) - { - ui->actionHard_Reset->trigger(); - } - if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("fullscreen")) - { - ui->actionFullscreen->trigger(); - } - } - event->accept(); + return true; } if (event->type() == QEvent::KeyRelease) { @@ -1471,14 +1496,6 @@ MainWindow::keyPressEvent(QKeyEvent *event) processKeyboardInput(true, event->nativeScanCode()); #endif } - - // Check if mouse release combo has been entered - int accID = FindAccelerator("release_mouse"); - QKeySequence seq = QKeySequence::fromString(acc_keys[accID].seq); - if (seq[0] == (event->key() | event->modifiers())) - plat_mouse_capture(0); - - // TODO: Other accelerators should probably be here? event->accept(); } From fd235bcf9630eff939ccab2604a046e3b5510785 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 14:31:46 -0700 Subject: [PATCH 0769/1190] Added pause shortcut. --- src/86box.c | 5 ++++- src/qt/qt_mainwindow.cpp | 15 ++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/86box.c b/src/86box.c index e3d1e785c..dae2d4ba5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -246,7 +246,10 @@ struct accelKey def_acc_keys[NUM_ACCELS] = { .seq="Ctrl+Alt+F12" }, { .name="pause", .desc="Toggle pause", - .seq="Ctrl+Alt+F1" } + .seq="Ctrl+Alt+F1" }, + + { .name="mute", .desc="Toggle mute", + .seq="Ctrl+Alt+M" } }; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index ad1c0e2a0..27124b9fd 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -836,6 +836,7 @@ void MainWindow::updateShortcuts() ui->actionCtrl_Alt_Esc->setShortcut(QKeySequence()); ui->actionHard_Reset->setShortcut(QKeySequence()); ui->actionPause->setShortcut(QKeySequence()); + ui->actionMute_Unmute->setShortcut(QKeySequence()); int accID; QKeySequence seq; @@ -863,6 +864,10 @@ void MainWindow::updateShortcuts() accID = FindAccelerator("pause"); seq = QKeySequence::fromString(acc_keys[accID].seq); ui->actionPause->setShortcut(seq); + + accID = FindAccelerator("mute"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionMute_Unmute->setShortcut(seq); } void @@ -1353,9 +1358,6 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) // Detect shortcuts when menubar is hidden // TODO: Could this be simplified by proxying the event and manually // shoving it into the menubar? - - // Note: This section should ONLY contain shortcuts that are valid - // when the emulator if (event->type() == QEvent::KeyPress) { this->keyPressEvent((QKeyEvent *) event); @@ -1393,6 +1395,11 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) { ui->actionPause->trigger(); } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("mute")) + { + ui->actionMute_Unmute->setShortcut(seq); + } + return true; } } @@ -1429,8 +1436,6 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) } } - - return QMainWindow::eventFilter(receiver, event); } From eaff1fcd703a08b846e0fc6e6efe08e670b5c6ae Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 14:33:19 -0700 Subject: [PATCH 0770/1190] Added mute shortcut. --- src/include/86box/86box.h | 2 +- src/qt/qt_mainwindow.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 51f1dbcbc..7f7723bba 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -242,7 +242,7 @@ struct accelKey { char desc[64]; char seq[64]; }; -#define NUM_ACCELS 7 +#define NUM_ACCELS 8 extern struct accelKey acc_keys[NUM_ACCELS]; extern struct accelKey def_acc_keys[NUM_ACCELS]; extern int FindAccelerator(const char *name); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 27124b9fd..568c84b36 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1397,7 +1397,7 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) } if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("mute")) { - ui->actionMute_Unmute->setShortcut(seq); + ui->actionMute_Unmute->trigger(); } return true; From 505874f22ee33691a54774487f273d775edc0336 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 15:23:38 -0700 Subject: [PATCH 0771/1190] Added translation to key shortcut table, modals, and release mouse status line. --- src/qt/languages/fr-FR.po | 8 ++++---- src/qt/qt_mainwindow.cpp | 26 +++++++++++++++++--------- src/qt/qt_platform.cpp | 10 ++++++++-- src/qt/qt_settingsinput.cpp | 9 +++++---- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 8456baf2f..5416f7662 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -717,11 +717,11 @@ msgstr "Autres périfériques" msgid "Click to capture mouse" msgstr "Cliquer pour capturer la souris" -msgid "Press %1 to release mouse" -msgstr "Appuyer sur %1 pour libérer la souris" +msgid "Press %s to release mouse" +msgstr "Appuyer sur %s pour libérer la souris" -msgid "Press %1 or middle button to release mouse" -msgstr "Appuyer sur %1 ou le bouton central pour libérer la souris" +msgid "Press %s or middle button to release mouse" +msgstr "Appuyer sur %s ou le bouton central pour libérer la souris" msgid "Bus" msgstr "Bus" diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 568c84b36..d79cc1b9e 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -823,10 +823,9 @@ void MainWindow::updateShortcuts() { /* Update menu shortcuts from accelerator table - Note that the "Release mouse" shortcut is hardcoded elsewhere - This section only applies to shortcuts anchored to UI elements - MainWindow::eventFilter + Note that these only work in windowed mode. If you add any new shortcuts, + you have to go duplicate them in MainWindow::eventFilter() */ // First we need to wipe all existing accelerators, otherwise Qt will @@ -1295,7 +1294,10 @@ MainWindow::on_actionFullscreen_triggered() if (video_fullscreen_first) { bool wasCaptured = mouse_capture == 1; - QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), tr("Press Ctrl+Alt+PgDn to return to windowed mode."), QMessageBox::Ok, this); + char strFullscreen[100]; + sprintf(strFullscreen, qPrintable(tr("To return to windowed mode, press %s")), acc_keys[FindAccelerator("fullscreen")].seq); + + QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), QString(strFullscreen), QMessageBox::Ok, this); QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!video_fullscreen_first); @@ -1362,15 +1364,21 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) { this->keyPressEvent((QKeyEvent *) event); + // We check for mouse release even if we aren't fullscreen, + // because it's not a menu accelerator. + if (event->type() == QEvent::KeyPress) + { + QKeyEvent *ke = (QKeyEvent *) event; + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("release_mouse")) + { + plat_mouse_capture(0); + } + } + if (event->type() == QEvent::KeyPress && video_fullscreen != 0) { QKeyEvent *ke = (QKeyEvent *) event; - if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("release_mouse")) - { - qDebug() << ke; - plat_mouse_capture(0); - } if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("screenshot")) { ui->actionTake_screenshot->trigger(); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 0f792feda..26682528d 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -595,8 +595,14 @@ ProgSettings::reloadStrings() { translatedstrings.clear(); translatedstrings[STRING_MOUSE_CAPTURE] = QCoreApplication::translate("", "Click to capture mouse").toStdWString(); - translatedstrings[STRING_MOUSE_RELEASE] = QCoreApplication::translate("", "Press %1 to release mouse").arg(QCoreApplication::translate("", MOUSE_CAPTURE_KEYSEQ)).toStdWString(); - translatedstrings[STRING_MOUSE_RELEASE_MMB] = QCoreApplication::translate("", "Press %1 or middle button to release mouse").arg(QCoreApplication::translate("", MOUSE_CAPTURE_KEYSEQ)).toStdWString(); + + char mouseCaptureKeyseq[100]; + sprintf(mouseCaptureKeyseq, qPrintable(QCoreApplication::translate("", "Press %s to release mouse")), acc_keys[FindAccelerator("release_mouse")].seq); + translatedstrings[STRING_MOUSE_RELEASE] = QString(mouseCaptureKeyseq).toStdWString(); + + sprintf(mouseCaptureKeyseq, qPrintable(QCoreApplication::translate("", "Press %s or middle button to release mouse")), acc_keys[FindAccelerator("release_mouse")].seq); + translatedstrings[STRING_MOUSE_RELEASE_MMB] = QString(mouseCaptureKeyseq).toStdWString(); + translatedstrings[STRING_INVALID_CONFIG] = QCoreApplication::translate("", "Invalid configuration").toStdWString(); translatedstrings[STRING_NO_ST506_ESDI_CDROM] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").toStdWString(); translatedstrings[STRING_PCAP_ERROR_NO_DEVICES] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 3be460a4a..20cb40ecd 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -51,8 +51,8 @@ SettingsInput::SettingsInput(QWidget *parent) QStringList horizontalHeader; QStringList verticalHeader; - horizontalHeader.append("Action"); - horizontalHeader.append("Keybind"); + horizontalHeader.append(tr("Action")); + horizontalHeader.append(tr("Keybind")); QTableWidget *keyTable = ui->tableKeys; keyTable->setRowCount(10); @@ -61,7 +61,7 @@ SettingsInput::SettingsInput(QWidget *parent) keyTable->setColumnWidth(0, 200); keyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); QStringList headers; - headers << "Action" << "Bound key"; + //headers << "Action" << "Bound key"; keyTable->setHorizontalHeaderLabels(headers); keyTable->verticalHeader()->setVisible(false); keyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -109,6 +109,7 @@ SettingsInput::save() strcpy(acc_keys[x].desc, acc_keys_t[x].desc); strcpy(acc_keys[x].seq, acc_keys_t[x].seq); } + // ProgSettings::reloadStrings(); } void @@ -169,7 +170,7 @@ SettingsInput::refreshInputList() { for (int x=0;xtableKeys->setItem(x, 0, new QTableWidgetItem(acc_keys_t[x].desc)); + ui->tableKeys->setItem(x, 0, new QTableWidgetItem(tr(acc_keys_t[x].desc))); ui->tableKeys->setItem(x, 1, new QTableWidgetItem(acc_keys_t[x].seq)); ui->tableKeys->setItem(x, 2, new QTableWidgetItem(acc_keys_t[x].name)); } From d6b280dd29eb066fcf48c3b1df1d813dd290736e Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 15:29:15 -0700 Subject: [PATCH 0772/1190] Status line now updates --- src/qt/qt_settingsinput.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 20cb40ecd..f87296451 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -17,6 +17,7 @@ #include "qt_settingsinput.hpp" #include "ui_qt_settingsinput.h" #include "qt_mainwindow.hpp" +#include "qt_progsettings.hpp" #include #include @@ -109,7 +110,7 @@ SettingsInput::save() strcpy(acc_keys[x].desc, acc_keys_t[x].desc); strcpy(acc_keys[x].seq, acc_keys_t[x].seq); } - // ProgSettings::reloadStrings(); + ProgSettings::reloadStrings(); } void From 30ea1eb08752cf6332b1c48a924aa7daeb80dc7e Mon Sep 17 00:00:00 2001 From: = Date: Sun, 20 Apr 2025 15:36:49 -0700 Subject: [PATCH 0773/1190] Updated translations --- src/qt/languages/ca-ES.po | 12 ++++++------ src/qt/languages/cs-CZ.po | 12 ++++++------ src/qt/languages/de-DE.po | 12 ++++++------ src/qt/languages/es-ES.po | 12 ++++++------ src/qt/languages/fi-FI.po | 12 ++++++------ src/qt/languages/fr-FR.po | 4 ++-- src/qt/languages/hr-HR.po | 12 ++++++------ src/qt/languages/hu-HU.po | 12 ++++++------ src/qt/languages/it-IT.po | 12 ++++++------ src/qt/languages/ja-JP.po | 12 ++++++------ src/qt/languages/ko-KR.po | 12 ++++++------ src/qt/languages/nl-NL.po | 12 ++++++------ src/qt/languages/pl-PL.po | 12 ++++++------ src/qt/languages/pt-BR.po | 12 ++++++------ src/qt/languages/pt-PT.po | 12 ++++++------ src/qt/languages/ru-RU.po | 12 ++++++------ src/qt/languages/sk-SK.po | 12 ++++++------ src/qt/languages/sl-SI.po | 12 ++++++------ src/qt/languages/sv-SE.po | 12 ++++++------ src/qt/languages/tr-TR.po | 12 ++++++------ src/qt/languages/uk-UA.po | 12 ++++++------ src/qt/languages/vi-VN.po | 12 ++++++------ src/qt/languages/zh-CN.po | 8 ++++---- src/qt/languages/zh-TW.po | 8 ++++---- src/qt/qt_mainwindow.cpp | 2 +- 25 files changed, 137 insertions(+), 137 deletions(-) diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 847cc0138..4851106cd 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -630,8 +630,8 @@ msgstr "Error fatal" msgid " - PAUSED" msgstr " - EN PAUSA" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Premeu Ctrl+Alt+PgDn per tornar al mode de finestra." +msgid "Press %s to return to windowed mode." +msgstr "Premeu %s per tornar al mode de finestra." msgid "Speed" msgstr "Velocitat" @@ -717,11 +717,11 @@ msgstr "Altres perifèrics" msgid "Click to capture mouse" msgstr "Feu clic per capturar el ratolí" -msgid "Press %1 to release mouse" -msgstr "Premeu %1 per alliberar el ratolí" +msgid "Press %s to release mouse" +msgstr "Premeu %s per alliberar el ratolí" -msgid "Press %1 or middle button to release mouse" -msgstr "Premeu %1 o el botó central per alliberar el ratolí" +msgid "Press %s or middle button to release mouse" +msgstr "Premeu %s o el botó central per alliberar el ratolí" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index ea492f0b6..352fafc31 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -630,8 +630,8 @@ msgstr "Kritická chyba" msgid " - PAUSED" msgstr " - POZASTAVENO" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Stiskněte Ctrl+Alt+PgDn pro návrat z režimu celé obrazovky." +msgid "Press %s to return to windowed mode." +msgstr "Stiskněte %s pro návrat z režimu celé obrazovky." msgid "Speed" msgstr "Rychlost" @@ -717,11 +717,11 @@ msgstr "Jiné příslušenství" msgid "Click to capture mouse" msgstr "Klikněte pro zabraní myši" -msgid "Press %1 to release mouse" -msgstr "Stiskněte %1 pro uvolnění myši" +msgid "Press %s to release mouse" +msgstr "Stiskněte %s pro uvolnění myši" -msgid "Press %1 or middle button to release mouse" -msgstr "Stiskněte %1 nebo prostřední tlačítko pro uvolnění myši" +msgid "Press %s or middle button to release mouse" +msgstr "Stiskněte %s nebo prostřední tlačítko pro uvolnění myši" msgid "Bus" msgstr "Sběrnice" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 95d1b0249..ce7d52d55 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -630,8 +630,8 @@ msgstr "Fataler Fehler" msgid " - PAUSED" msgstr " - PAUSIERT" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Strg+Alt+Bild ab, zur Rückkehr in den Fenstermodus." +msgid "Press %s to return to windowed mode." +msgstr "%s ab, zur Rückkehr in den Fenstermodus." msgid "Speed" msgstr "Geschwindigkeit" @@ -717,11 +717,11 @@ msgstr "Andere Peripheriegeräte" msgid "Click to capture mouse" msgstr "Klicken zum Einfangen des Mauszeigers" -msgid "Press %1 to release mouse" -msgstr "Drücke %1 zur Mausfreigabe" +msgid "Press %s to release mouse" +msgstr "Drücke %s zur Mausfreigabe" -msgid "Press %1 or middle button to release mouse" -msgstr "Drücke %1 oder die mittlere Maustaste zur Mausfreigabe" +msgid "Press %s or middle button to release mouse" +msgstr "Drücke %s oder die mittlere Maustaste zur Mausfreigabe" msgid "Ctrl+End" msgstr "Strg+Ende" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 57474ae53..177d08d18 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -630,8 +630,8 @@ msgstr "Error fatal" msgid " - PAUSED" msgstr " - EN PAUSA" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Pulsa Ctrl+Alt+PgDn para volver a modo ventana." +msgid "Press %s to return to windowed mode." +msgstr "Pulsa %s para volver a modo ventana." msgid "Speed" msgstr "Velocidad" @@ -717,11 +717,11 @@ msgstr "Otros periféricos" msgid "Click to capture mouse" msgstr "Haga click para capturar el ratón" -msgid "Press %1 to release mouse" -msgstr "Pulse %1 para liberar el ratón" +msgid "Press %s to release mouse" +msgstr "Pulse %s para liberar el ratón" -msgid "Press %1 or middle button to release mouse" -msgstr "Pulse %1 o el botón central para liberar el ratón" +msgid "Press %s or middle button to release mouse" +msgstr "Pulse %s o el botón central para liberar el ratón" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 187a423f6..a77b3f6ef 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -630,8 +630,8 @@ msgstr "Vakava virhe" msgid " - PAUSED" msgstr " - TAUKO" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Paina Ctrl+Alt+PgDn palataksesi ikkunoituun tilaan." +msgid "Press %s to return to windowed mode." +msgstr "Paina %s palataksesi ikkunoituun tilaan." msgid "Speed" msgstr "Nopeus" @@ -717,11 +717,11 @@ msgstr "Muut oheislaitteet" msgid "Click to capture mouse" msgstr "Kaappaa hiiri klikkaamalla" -msgid "Press %1 to release mouse" -msgstr "Paina %1 vapauttaaksesi hiiren" +msgid "Press %s to release mouse" +msgstr "Paina %s vapauttaaksesi hiiren" -msgid "Press %1 or middle button to release mouse" -msgstr "Paina %1 tai keskipainiketta vapauttaaksesi hiiren" +msgid "Press %s or middle button to release mouse" +msgstr "Paina %s tai keskipainiketta vapauttaaksesi hiiren" msgid "Bus" msgstr "Väylä" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 5416f7662..fe3dc4bb4 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -630,8 +630,8 @@ msgstr "Erreur fatale" msgid " - PAUSED" msgstr " - EN PAUSE" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Appuyez sur Ctrl+Alt+PgDn pour revenir au mode fenêtré." +msgid "Press %s to return to windowed mode." +msgstr "Appuyez sur %s pour revenir au mode fenêtré." msgid "Speed" msgstr "Vitesse" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 0fd342f88..1eecaa2d0 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -630,8 +630,8 @@ msgstr "Fatalna greška" msgid " - PAUSED" msgstr " - ZASTAO" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Pritisnite Ctrl+Alt+PgDn za povratak u prozorski način rada." +msgid "Press %s to return to windowed mode." +msgstr "Pritisnite %s za povratak u prozorski način rada." msgid "Speed" msgstr "Brzina" @@ -717,11 +717,11 @@ msgstr "Ostali periferni uređaji" msgid "Click to capture mouse" msgstr "Kliknite da uhvatite miš" -msgid "Press %1 to release mouse" -msgstr "Pritisnite %1 za otpustanje miša" +msgid "Press %s to release mouse" +msgstr "Pritisnite %s za otpustanje miša" -msgid "Press %1 or middle button to release mouse" -msgstr "Pritisnite %1 ili srednji gumb miša za otpuštanje miša" +msgid "Press %s or middle button to release mouse" +msgstr "Pritisnite %s ili srednji gumb miša za otpuštanje miša" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index cbb753890..43a1fd9ba 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -630,8 +630,8 @@ msgstr "Végzetes hiba" msgid " - PAUSED" msgstr " - SZÜNETELT" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Használja a Ctrl+Alt+PgDn gombokat az ablakhoz való visszatéréshez." +msgid "Press %s to return to windowed mode." +msgstr "Használja a %s gombokat az ablakhoz való visszatéréshez." msgid "Speed" msgstr "Sebesség" @@ -717,11 +717,11 @@ msgstr "Egyéb perifériák" msgid "Click to capture mouse" msgstr "Kattintson az egér elfogásához" -msgid "Press %1 to release mouse" -msgstr "Nyomja meg az %1-t az egér elengédéséhez" +msgid "Press %s to release mouse" +msgstr "Nyomja meg az %s-t az egér elengédéséhez" -msgid "Press %1 or middle button to release mouse" -msgstr "Nyomja meg az %1-t vagy a középső gombot az egér elengédéséhez" +msgid "Press %s or middle button to release mouse" +msgstr "Nyomja meg az %s-t vagy a középső gombot az egér elengédéséhez" msgid "Bus" msgstr "Busz" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index c505b9eaa..b8ded74de 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -630,8 +630,8 @@ msgstr "Errore fatale" msgid " - PAUSED" msgstr " - IN PAUSA" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Usa Ctrl+Alt+PgDn per tornare alla modalità finestra." +msgid "Press %s to return to windowed mode." +msgstr "Usa %s per tornare alla modalità finestra." msgid "Speed" msgstr "Velocità" @@ -717,11 +717,11 @@ msgstr "Altre periferiche" msgid "Click to capture mouse" msgstr "Fare clic per catturare mouse" -msgid "Press %1 to release mouse" -msgstr "Premi %1 per rilasciare il mouse" +msgid "Press %s to release mouse" +msgstr "Premi %s per rilasciare il mouse" -msgid "Press %1 or middle button to release mouse" -msgstr "Premi %1 o pulsante centrale per rilasciare il mouse" +msgid "Press %s or middle button to release mouse" +msgstr "Premi %s o pulsante centrale per rilasciare il mouse" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index cff667239..dc000b175 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -630,8 +630,8 @@ msgstr "致命的なエラー" msgid " - PAUSED" msgstr " - 一時停止" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Ctrl+Alt+PgDnでウィンドウ モードに戻ります。" +msgid "Press %s to return to windowed mode." +msgstr "%sでウィンドウ モードに戻ります。" msgid "Speed" msgstr "速度" @@ -717,11 +717,11 @@ msgstr "他の周辺デバイス" msgid "Click to capture mouse" msgstr "左クリックでマウスをキャプチャします" -msgid "Press %1 to release mouse" -msgstr "%1キーでマウスを解放します" +msgid "Press %s to release mouse" +msgstr "%sキーでマウスを解放します" -msgid "Press %1 or middle button to release mouse" -msgstr "%1キーまたは中クリックでマウスを解放します" +msgid "Press %s or middle button to release mouse" +msgstr "%sキーまたは中クリックでマウスを解放します" msgid "Bus" msgstr "バス" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 55f47be27..3ef901789 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -630,8 +630,8 @@ msgstr "치명적인 오류" msgid " - PAUSED" msgstr " - 일시 중지됨" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Ctrl+Alt+PgDn 키를 누르면 창 모드로 전환합니다." +msgid "Press %s to return to windowed mode." +msgstr "%s 키를 누르면 창 모드로 전환합니다." msgid "Speed" msgstr "속도" @@ -717,11 +717,11 @@ msgstr "기타 주변기기" msgid "Click to capture mouse" msgstr "이 창을 클릭하면 마우스를 사용합니다" -msgid "Press %1 to release mouse" -msgstr "%1키를 누르면 마우스를 해제합니다" +msgid "Press %s to release mouse" +msgstr "%s키를 누르면 마우스를 해제합니다" -msgid "Press %1 or middle button to release mouse" -msgstr "%1키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" +msgid "Press %s or middle button to release mouse" +msgstr "%s키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" msgid "Bus" msgstr "버스" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index e854ea3f3..8ee391957 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -630,8 +630,8 @@ msgstr "Fatale fout" msgid " - PAUSED" msgstr " - GEPAUZEERD" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Druk op Ctrl+Alt+PgDn om terug te gaan naar de venstermodus." +msgid "Press %s to return to windowed mode." +msgstr "Druk op %s om terug te gaan naar de venstermodus." msgid "Speed" msgstr "Snelheid" @@ -717,11 +717,11 @@ msgstr "Andere randapparatuur" msgid "Click to capture mouse" msgstr "Klik om muis vast te leggen" -msgid "Press %1 to release mouse" -msgstr "Druk op %1 om de muis los te laten" +msgid "Press %s to release mouse" +msgstr "Druk op %s om de muis los te laten" -msgid "Press %1 or middle button to release mouse" -msgstr "Druk op %1 of middelste knop om de muis los te laten" +msgid "Press %s or middle button to release mouse" +msgstr "Druk op %s of middelste knop om de muis los te laten" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 3fc731e5f..d5b5ec3ea 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -630,8 +630,8 @@ msgstr "Fatalny błąd" msgid " - PAUSED" msgstr " - PAUSED" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Naciśnij klawisze Ctrl+Alt+PgDn aby wrócić to trybu okna." +msgid "Press %s to return to windowed mode." +msgstr "Naciśnij klawisze %s aby wrócić to trybu okna." msgid "Speed" msgstr "Szybkość" @@ -717,11 +717,11 @@ msgstr "Inne urządzenia peryferyjne" msgid "Click to capture mouse" msgstr "Kliknij w celu przechwycenia myszy" -msgid "Press %1 to release mouse" -msgstr "Naciśnij klawisze %1 w celu uwolnienia myszy" +msgid "Press %s to release mouse" +msgstr "Naciśnij klawisze %s w celu uwolnienia myszy" -msgid "Press %1 or middle button to release mouse" -msgstr "Naciśnij klawisze %1 lub środkowy przycisk w celu uwolnienia myszy" +msgid "Press %s or middle button to release mouse" +msgstr "Naciśnij klawisze %s lub środkowy przycisk w celu uwolnienia myszy" msgid "Bus" msgstr "Magistrala" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 02abe2321..8961f11b8 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -630,8 +630,8 @@ msgstr "Erro fatal" msgid " - PAUSED" msgstr " - PAUSADO" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Use Ctrl+Alt+PgDn para retornar ao modo janela" +msgid "Press %s to return to windowed mode." +msgstr "Use %s para retornar ao modo janela" msgid "Speed" msgstr "Velocidade" @@ -717,11 +717,11 @@ msgstr "Outros periféricos" msgid "Click to capture mouse" msgstr "Clique para capturar o mouse" -msgid "Press %1 to release mouse" -msgstr "Aperte %1 para liberar o mouse" +msgid "Press %s to release mouse" +msgstr "Aperte %s para liberar o mouse" -msgid "Press %1 or middle button to release mouse" -msgstr "Aperte %1 ou botão do meio para liberar o mouse" +msgid "Press %s or middle button to release mouse" +msgstr "Aperte %s ou botão do meio para liberar o mouse" msgid "Bus" msgstr "Barramento" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 42550a266..ba1c6976c 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -630,8 +630,8 @@ msgstr "Erro fatal" msgid " - PAUSED" msgstr " - EM PAUSA" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Pressione Ctrl+Alt+PgDn para voltar ao modo de janela." +msgid "Press %s to return to windowed mode." +msgstr "Pressione %s para voltar ao modo de janela." msgid "Speed" msgstr "Velocidade" @@ -717,11 +717,11 @@ msgstr "Outros dispositivos" msgid "Click to capture mouse" msgstr "Clique para capturar o rato" -msgid "Press %1 to release mouse" -msgstr "Pressione %1 para soltar o rato" +msgid "Press %s to release mouse" +msgstr "Pressione %s para soltar o rato" -msgid "Press %1 or middle button to release mouse" -msgstr "Pressione %1 ou tecla média para soltar o rato" +msgid "Press %s or middle button to release mouse" +msgstr "Pressione %s ou tecla média para soltar o rato" msgid "Bus" msgstr "Barramento" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index dde5387a7..baf1035ea 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -630,8 +630,8 @@ msgstr "Неустранимая ошибка" msgid " - PAUSED" msgstr " - ПАУЗА" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Нажмите Ctrl+Alt+PgDn для возврата в оконный режим." +msgid "Press %s to return to windowed mode." +msgstr "Нажмите %s для возврата в оконный режим." msgid "Speed" msgstr "Скорость" @@ -717,11 +717,11 @@ msgstr "Другая периферия" msgid "Click to capture mouse" msgstr "Щёлкните мышью для захвата курсора" -msgid "Press %1 to release mouse" -msgstr "Нажмите %1, чтобы освободить курсор" +msgid "Press %s to release mouse" +msgstr "Нажмите %s, чтобы освободить курсор" -msgid "Press %1 or middle button to release mouse" -msgstr "Нажмите %1 или среднюю кнопку мыши, чтобы освободить курсор" +msgid "Press %s or middle button to release mouse" +msgstr "Нажмите %s или среднюю кнопку мыши, чтобы освободить курсор" msgid "Bus" msgstr "Шина" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 6039adedc..f11f335d4 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -630,8 +630,8 @@ msgstr "Kritická chyba" msgid " - PAUSED" msgstr " - POZASTAVENÝ" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Stlačte Ctrl+Alt+PgDn pre návrat z režimu celej obrazovky." +msgid "Press %s to return to windowed mode." +msgstr "Stlačte %s pre návrat z režimu celej obrazovky." msgid "Speed" msgstr "Rýchlosť" @@ -717,11 +717,11 @@ msgstr "Iné príslušenstvo" msgid "Click to capture mouse" msgstr "Kliknite pre zabráni myši" -msgid "Press %1 to release mouse" -msgstr "Stlačte %1 pre uvoľnenie myši" +msgid "Press %s to release mouse" +msgstr "Stlačte %s pre uvoľnenie myši" -msgid "Press %1 or middle button to release mouse" -msgstr "Stlačte %1 alebo prostredné tlačidlo na uvoľnenie myši" +msgid "Press %s or middle button to release mouse" +msgstr "Stlačte %s alebo prostredné tlačidlo na uvoľnenie myši" msgid "Bus" msgstr "Zbernica" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index b6641f8a1..7c2b36650 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -630,8 +630,8 @@ msgstr "Kritična napaka" msgid " - PAUSED" msgstr " - ZAUSTAVLJEN" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Pritisnite Ctrl+Alt+PgDn za povratek iz celozaslonskega načina." +msgid "Press %s to return to windowed mode." +msgstr "Pritisnite %s za povratek iz celozaslonskega načina." msgid "Speed" msgstr "Hitrost" @@ -717,11 +717,11 @@ msgstr "Druga periferija" msgid "Click to capture mouse" msgstr "Kliknite za zajem miške" -msgid "Press %1 to release mouse" -msgstr "Pritisnite %1 za izpust miške" +msgid "Press %s to release mouse" +msgstr "Pritisnite %s za izpust miške" -msgid "Press %1 or middle button to release mouse" -msgstr "Pritisnite %1 ali srednji gumb za izpust miške" +msgid "Press %s or middle button to release mouse" +msgstr "Pritisnite %s ali srednji gumb za izpust miške" msgid "Bus" msgstr "Vodilo" diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index a47997225..61152c663 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -630,8 +630,8 @@ msgstr "Allvarligt fel" msgid " - PAUSED" msgstr " - PAUSAD" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Tryck på Ctrl+Alt+PgDn för att återvända till fönsterläge." +msgid "Press %s to return to windowed mode." +msgstr "Tryck på %s för att återvända till fönsterläge." msgid "Speed" msgstr "Hastighet" @@ -717,11 +717,11 @@ msgstr "Andra tillbehör" msgid "Click to capture mouse" msgstr "Klicka för att fånga upp musen" -msgid "Press %1 to release mouse" -msgstr "Tryck på %1 för att släppa musen" +msgid "Press %s to release mouse" +msgstr "Tryck på %s för att släppa musen" -msgid "Press %1 or middle button to release mouse" -msgstr "Tryck på %1 eller mellersta musknappen för att släppa musen" +msgid "Press %s or middle button to release mouse" +msgstr "Tryck på %s eller mellersta musknappen för att släppa musen" msgid "Bus" msgstr "Buss" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index e9a42a896..de111c59b 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -630,8 +630,8 @@ msgstr "Kritik hata" msgid " - PAUSED" msgstr " - DURAKLATILDI" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Pencere moduna geri dönmek için Ctrl+Alt+PgDn tuşlarına basın." +msgid "Press %s to return to windowed mode." +msgstr "Pencere moduna geri dönmek için %s tuşlarına basın." msgid "Speed" msgstr "Hız" @@ -717,11 +717,11 @@ msgstr "Diğer cihazlar" msgid "Click to capture mouse" msgstr "Farenin yakalanması için tıklayın" -msgid "Press %1 to release mouse" -msgstr "Farenin bırakılması için %1 tuşlarına basın" +msgid "Press %s to release mouse" +msgstr "Farenin bırakılması için %s tuşlarına basın" -msgid "Press %1 or middle button to release mouse" -msgstr "Farenin bırakılması için %1 tuşlarına veya tekerlek tuşuna basın" +msgid "Press %s or middle button to release mouse" +msgstr "Farenin bırakılması için %s tuşlarına veya tekerlek tuşuna basın" msgid "Bus" msgstr "Veri yolu" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index bceb7bea5..db9b73491 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -630,8 +630,8 @@ msgstr "Непереробна помилка" msgid " - PAUSED" msgstr " - ПРИЗУПИНЕННЯ" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Натисніть Ctrl+Alt+PgDn для повернення у віконний режим." +msgid "Press %s to return to windowed mode." +msgstr "Натисніть %s для повернення у віконний режим." msgid "Speed" msgstr "Швидкість" @@ -717,11 +717,11 @@ msgstr "Інша периферія" msgid "Click to capture mouse" msgstr "Клацніть мишею для захвату курсора" -msgid "Press %1 to release mouse" -msgstr "Натисніть %1, щоб звільнити курсор" +msgid "Press %s to release mouse" +msgstr "Натисніть %s, щоб звільнити курсор" -msgid "Press %1 or middle button to release mouse" -msgstr "Натисніть %1 або середню кнопку миші, щоб звільнити курсор" +msgid "Press %s or middle button to release mouse" +msgstr "Натисніть %s або середню кнопку миші, щоб звільнити курсор" msgid "Bus" msgstr "Шина" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index e14386bf8..e21466a18 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -630,8 +630,8 @@ msgstr "Lỗi nghiêm trọng" msgid " - PAUSED" msgstr " - TẠM DỪNG" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Bấm Ctrl+Alt+PgDn để quay lại chế độ cửa sổ." +msgid "Press %s to return to windowed mode." +msgstr "Bấm %s để quay lại chế độ cửa sổ." msgid "Speed" msgstr "Vận tốc" @@ -717,11 +717,11 @@ msgstr "Thiết bị ngoại vi khác" msgid "Click to capture mouse" msgstr "Nhấp vào khung hình để 'nhốt' chuột vào" -msgid "Press %1 to release mouse" -msgstr "Nhấn %1 để thả chuột" +msgid "Press %s to release mouse" +msgstr "Nhấn %s để thả chuột" -msgid "Press %1 or middle button to release mouse" -msgstr "Nhấn %1 hoặc nhấp chuột giữa để thả chuột" +msgid "Press %s or middle button to release mouse" +msgstr "Nhấn %s hoặc nhấp chuột giữa để thả chuột" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 9f6cc0328..c29e40dfb 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -717,11 +717,11 @@ msgstr "其他外围设备" msgid "Click to capture mouse" msgstr "单击窗口捕捉鼠标" -msgid "Press %1 to release mouse" -msgstr "按下 %1 释放鼠标" +msgid "Press %s to release mouse" +msgstr "按下 %s 释放鼠标" -msgid "Press %1 or middle button to release mouse" -msgstr "按下 %1 或鼠标中键释放鼠标" +msgid "Press %s or middle button to release mouse" +msgstr "按下 %s 或鼠标中键释放鼠标" msgid "Bus" msgstr "总线" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index aefa89d5f..7de6f8cd3 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -717,11 +717,11 @@ msgstr "其他周邊裝置" msgid "Click to capture mouse" msgstr "點擊視窗捕捉滑鼠" -msgid "Press %1 to release mouse" -msgstr "按下 %1 釋放滑鼠" +msgid "Press %s to release mouse" +msgstr "按下 %s 釋放滑鼠" -msgid "Press %1 or middle button to release mouse" -msgstr "按下 %1 或滑鼠中鍵釋放滑鼠" +msgid "Press %s or middle button to release mouse" +msgstr "按下 %s 或滑鼠中鍵釋放滑鼠" msgid "Bus" msgstr "匯流排" diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index d79cc1b9e..1fb9b3fb5 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1295,7 +1295,7 @@ MainWindow::on_actionFullscreen_triggered() bool wasCaptured = mouse_capture == 1; char strFullscreen[100]; - sprintf(strFullscreen, qPrintable(tr("To return to windowed mode, press %s")), acc_keys[FindAccelerator("fullscreen")].seq); + sprintf(strFullscreen, qPrintable(tr("Press %s to return to windowed mode.")), acc_keys[FindAccelerator("fullscreen")].seq); QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), QString(strFullscreen), QMessageBox::Ok, this); QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); From a0f90f7c98830bd826d74e7e5c4d926c1683dfa6 Mon Sep 17 00:00:00 2001 From: snake-4 <18491360+snake-4@users.noreply.github.com> Date: Mon, 21 Apr 2025 03:29:00 +0200 Subject: [PATCH 0774/1190] Fixed stack overflow in CharPointer::operator= --- src/qt/qt_platform.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 26682528d..be40452fd 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -87,13 +87,13 @@ public: CharPointer &operator=(const QByteArray &ba) { if (s > 0) { + // If the size is known, copy up to s - 1 bytes + // and null-terminate the string. strncpy(b, ba.data(), s - 1); - b[s] = 0; - } else { - // if we haven't been told the length of b, just assume enough - // because we didn't get it from emulator code + b[s - 1] = 0; + } else if (ba.size() > 0) { + // If the size is unknown, copy the whole QByteArray strcpy(b, ba.data()); - b[ba.size()] = 0; } return *this; } From 46546f203289ed0a7f2e59f202c28786ed667133 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 21 Apr 2025 14:46:21 +0600 Subject: [PATCH 0775/1190] Keybind UI fixes 1. Don't clear the description text cell if selected; clear the actual keybind text instead. 2. Header texts are now correct. 3. Make the keybind dialog model and usable with dark mode --- src/qt/qt_keybind.cpp | 13 +++++++------ src/qt/qt_keybind.hpp | 2 +- src/qt/qt_settingsinput.cpp | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/qt/qt_keybind.cpp b/src/qt/qt_keybind.cpp index e8cbbf5b6..8b0f52eab 100644 --- a/src/qt/qt_keybind.cpp +++ b/src/qt/qt_keybind.cpp @@ -6,15 +6,15 @@ * * This file is part of the 86Box distribution. * - * Device configuration UI code. + * Keybind dialog * * * - * Authors: Joakim L. Gilje + * Authors: Cathode Ray Dude * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2022 Cacodemon345 + * Copyright 2025 Cathode Ray Dude + * Copyright 2025 Cacodemon345 */ #include "qt_keybind.hpp" #include "ui_qt_keybind.h" @@ -85,12 +85,13 @@ bool KeyBinder::eventFilter(QObject *obj, QEvent *event) } QKeySequence -KeyBinder::BindKey(QString CurValue) +KeyBinder::BindKey(QWidget* widget, QString CurValue) { - KeyBinder kb; + KeyBinder kb(widget); kb.setWindowTitle("Bind Key"); kb.setFixedSize(kb.minimumSizeHint()); kb.findChild()->setKeySequence(QKeySequence::fromString(CurValue)); + kb.setEnabled(true); if (kb.exec() == QDialog::Accepted) { QKeySequenceEdit *seq = kb.findChild(); diff --git a/src/qt/qt_keybind.hpp b/src/qt/qt_keybind.hpp index e8e7b6e5e..393ee0f5c 100644 --- a/src/qt/qt_keybind.hpp +++ b/src/qt/qt_keybind.hpp @@ -22,7 +22,7 @@ public: explicit KeyBinder(QWidget *parent = nullptr); ~KeyBinder() override; - static QKeySequence BindKey(QString CurValue); + static QKeySequence BindKey(QWidget* widget, QString CurValue); private: Ui::KeyBinder *ui; diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index f87296451..bf5035110 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -63,7 +63,7 @@ SettingsInput::SettingsInput(QWidget *parent) keyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); QStringList headers; //headers << "Action" << "Bound key"; - keyTable->setHorizontalHeaderLabels(headers); + keyTable->setHorizontalHeaderLabels(horizontalHeader); keyTable->verticalHeader()->setVisible(false); keyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); keyTable->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -201,7 +201,7 @@ SettingsInput::on_tableKeys_doubleClicked(int row, int col) QTableWidgetItem *cell = ui->tableKeys->item(row,1); if (!cell) return; - QKeySequence keyseq = KeyBinder::BindKey(cell->text()); + QKeySequence keyseq = KeyBinder::BindKey(this, cell->text()); if (keyseq != false) { // If no change was made, don't change anything. if (keyseq.toString(QKeySequence::NativeText) == cell->text()) return; @@ -247,7 +247,7 @@ void SettingsInput::on_pushButtonClearBind_Clicked() { // Wipe bind - QTableWidgetItem *cell = ui->tableKeys->currentItem(); + QTableWidgetItem *cell = ui->tableKeys->item(ui->tableKeys->currentRow(), 1); if (!cell) return; cell->setText(""); From 0e634a3b7fa9eec1aa61c29d70fff6051d221fad Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 21 Apr 2025 16:13:11 +0600 Subject: [PATCH 0776/1190] HDD tooltips now list paths of disk images, CHS and their sizes --- src/qt/qt_machinestatus.cpp | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index d86dae7b9..c8f089749 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -640,6 +640,14 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_MFM].setActive(false); d->hdds[HDD_BUS_MFM].refresh(); d->hdds[HDD_BUS_MFM].label->setToolTip(tr("Hard disk (%1)").arg("MFM/RLL")); + auto tooltip = d->hdds[HDD_BUS_MFM].label->toolTip(); + tooltip.append("\n"); + for (int i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus_type == HDD_BUS_MFM && hdd[i].fn[0] != 0) { + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + } + } + d->hdds[HDD_BUS_MFM].label->setToolTip(tooltip); sbar->addWidget(d->hdds[HDD_BUS_MFM].label.get()); } if ((has_esdi || (hdc_name.left(4) == QStringLiteral("esdi"))) && (c_esdi > 0)) { @@ -647,6 +655,14 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_ESDI].setActive(false); d->hdds[HDD_BUS_ESDI].refresh(); d->hdds[HDD_BUS_ESDI].label->setToolTip(tr("Hard disk (%1)").arg("ESDI")); + auto tooltip = d->hdds[HDD_BUS_ESDI].label->toolTip(); + tooltip.append("\n"); + for (int i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus_type == HDD_BUS_ESDI && hdd[i].fn[0] != 0) { + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + } + } + d->hdds[HDD_BUS_ESDI].label->setToolTip(tooltip); sbar->addWidget(d->hdds[HDD_BUS_ESDI].label.get()); } if ((has_xta || (hdc_name.left(3) == QStringLiteral("xta"))) && (c_xta > 0)) { @@ -654,6 +670,14 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_XTA].setActive(false); d->hdds[HDD_BUS_XTA].refresh(); d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%1)").arg("XTA")); + auto tooltip = d->hdds[HDD_BUS_XTA].label->toolTip(); + tooltip.append("\n"); + for (int i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus_type == HDD_BUS_XTA && hdd[i].fn[0] != 0) { + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + } + } + d->hdds[HDD_BUS_XTA].label->setToolTip(tooltip); sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get()); } if (hasIDE() || (hdc_name.left(5) == QStringLiteral("xtide")) || @@ -664,6 +688,14 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_IDE].setActive(false); d->hdds[HDD_BUS_IDE].refresh(); d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%1)").arg("IDE")); + auto tooltip = d->hdds[HDD_BUS_IDE].label->toolTip(); + tooltip.append("\n"); + for (int i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus_type == HDD_BUS_IDE && hdd[i].fn[0] != 0) { + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + } + } + d->hdds[HDD_BUS_IDE].label->setToolTip(tooltip); sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); } if (c_atapi > 0) { @@ -671,6 +703,14 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_ATAPI].setActive(false); d->hdds[HDD_BUS_ATAPI].refresh(); d->hdds[HDD_BUS_ATAPI].label->setToolTip(tr("Hard disk (%1)").arg("ATAPI")); + auto tooltip = d->hdds[HDD_BUS_ATAPI].label->toolTip(); + tooltip.append("\n"); + for (int i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus_type == HDD_BUS_ATAPI && hdd[i].fn[0] != 0) { + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + } + } + d->hdds[HDD_BUS_ATAPI].label->setToolTip(tooltip); sbar->addWidget(d->hdds[HDD_BUS_ATAPI].label.get()); } } @@ -682,6 +722,14 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_SCSI].setActive(false); d->hdds[HDD_BUS_SCSI].refresh(); d->hdds[HDD_BUS_SCSI].label->setToolTip(tr("Hard disk (%1)").arg("SCSI")); + auto tooltip = d->hdds[HDD_BUS_SCSI].label->toolTip(); + tooltip.append("\n"); + for (int i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus_type == HDD_BUS_SCSI && hdd[i].fn[0] != 0) { + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 4), QString::asprintf("%02d", hdd[i].channel & 15), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + } + } + d->hdds[HDD_BUS_SCSI].label->setToolTip(tooltip); sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get()); } From c7db5122b76ca68cf99e22dcea76715c0847863d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 21 Apr 2025 17:25:12 +0600 Subject: [PATCH 0777/1190] Make `MB` in HDD tooltips translated --- src/qt/qt_machinestatus.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index c8f089749..f93734887 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -644,7 +644,7 @@ MachineStatus::refresh(QStatusBar *sbar) tooltip.append("\n"); for (int i = 0; i < HDD_NUM; i++) { if (hdd[i].bus_type == HDD_BUS_MFM && hdd[i].fn[0] != 0) { - tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 %8)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull), tr("MB"))); } } d->hdds[HDD_BUS_MFM].label->setToolTip(tooltip); @@ -659,7 +659,7 @@ MachineStatus::refresh(QStatusBar *sbar) tooltip.append("\n"); for (int i = 0; i < HDD_NUM; i++) { if (hdd[i].bus_type == HDD_BUS_ESDI && hdd[i].fn[0] != 0) { - tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 %8)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull), tr("MB"))); } } d->hdds[HDD_BUS_ESDI].label->setToolTip(tooltip); @@ -674,7 +674,7 @@ MachineStatus::refresh(QStatusBar *sbar) tooltip.append("\n"); for (int i = 0; i < HDD_NUM; i++) { if (hdd[i].bus_type == HDD_BUS_XTA && hdd[i].fn[0] != 0) { - tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 %8)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull), tr("MB"))); } } d->hdds[HDD_BUS_XTA].label->setToolTip(tooltip); @@ -692,7 +692,7 @@ MachineStatus::refresh(QStatusBar *sbar) tooltip.append("\n"); for (int i = 0; i < HDD_NUM; i++) { if (hdd[i].bus_type == HDD_BUS_IDE && hdd[i].fn[0] != 0) { - tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 %8)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull), tr("MB"))); } } d->hdds[HDD_BUS_IDE].label->setToolTip(tooltip); @@ -707,7 +707,7 @@ MachineStatus::refresh(QStatusBar *sbar) tooltip.append("\n"); for (int i = 0; i < HDD_NUM; i++) { if (hdd[i].bus_type == HDD_BUS_ATAPI && hdd[i].fn[0] != 0) { - tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 %8)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 1), QString::number(hdd[i].channel & 1), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull), tr("MB"))); } } d->hdds[HDD_BUS_ATAPI].label->setToolTip(tooltip); @@ -726,7 +726,7 @@ MachineStatus::refresh(QStatusBar *sbar) tooltip.append("\n"); for (int i = 0; i < HDD_NUM; i++) { if (hdd[i].bus_type == HDD_BUS_SCSI && hdd[i].fn[0] != 0) { - tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 MB)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 4), QString::asprintf("%02d", hdd[i].channel & 15), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull))); + tooltip.append(QString("\n%5:%6: %1 (C:H:S = %2:%3:%4, %7 %8)").arg(QString::fromUtf8(hdd[i].fn), QString::number(hdd[i].tracks), QString::number(hdd[i].hpc), QString::number(hdd[i].spt), QString::number(hdd[i].channel >> 4), QString::asprintf("%02d", hdd[i].channel & 15), QString::number((((qulonglong)hdd[i].hpc * (qulonglong)hdd[i].spt * (qulonglong)hdd[i].tracks) * 512ull) / 1048576ull), tr("MB"))); } } d->hdds[HDD_BUS_SCSI].label->setToolTip(tooltip); From 11a55708fb66e8fa1a65117741cbbab2eb4abfe8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 21 Apr 2025 13:41:58 +0200 Subject: [PATCH 0778/1190] Made it compile as GUI again on Windows and made the help message a message box. --- CMakeLists.txt | 2 +- src/86box.c | 52 ++++++++++++++++++++++++++---------------------- src/qt/qt_ui.cpp | 9 ++++++++- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6ffa89e5..007c1ffd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,7 @@ if(WIN32) # Default value for the `WIN32` target property, which specifies whether # to build the application for the Windows GUI or console subsystem - option(CMAKE_WIN32_EXECUTABLE "Build a Windows GUI executable" OFF) + option(CMAKE_WIN32_EXECUTABLE "Build a Windows GUI executable" ON) else() # Prefer dynamic builds everywhere else set(PREFER_STATIC OFF) diff --git a/src/86box.c b/src/86box.c index dae2d4ba5..cde98f5d8 100644 --- a/src/86box.c +++ b/src/86box.c @@ -666,40 +666,44 @@ usage: } } - printf("\nUsage: 86box [options] [cfg-file]\n\n"); - printf("Valid options are:\n\n"); - printf("-? or --help - show this information\n"); - printf("-C or --config path - set 'path' to be config file\n"); + ui_msgbox(MBX_INFO, L"\nUsage: 86box [options] [cfg-file]\n\n" + "Valid options are:\n\n" + "-? or --help\t\t\t- show this information\n" + "-C or --config path\t\t- set 'path' to be config file\n" #ifdef _WIN32 - printf("-D or --debug - force debug output logging\n"); + "-D or --debug\t\t\t- force debug output logging\n" #endif #if 0 - printf("-E or --nographic - forces the old behavior\n"); + "-E or --nographic\t\t- forces the old behavior\n" #endif - printf("-F or --fullscreen - start in fullscreen mode\n"); - printf("-G or --lang langid - start with specified language (e.g. en-US, or system)\n"); + "-F or --fullscreen\t\t- start in fullscreen mode\n" + "-G or --lang langid\t\t- start with specified language\n" + "\t\t\t\t (e.g. en-US, or system)\n" #ifdef _WIN32 - printf("-H or --hwnd id,hwnd - sends back the main dialog's hwnd\n"); + "-H or --hwnd id,hwnd\t\t- sends back the main dialog's hwnd\n" #endif - printf("-I or --image d:path - load 'path' as floppy image on drive d\n"); + "-I or --image d:path\t\t- load 'path' as floppy image on drive d\n" #ifdef USE_INSTRUMENT - printf("-J or --instrument name - set 'name' to be the profiling instrument\n"); + "-J or --instrument name\t- set 'name' to be the profiling instrument\n" #endif - printf("-L or --logfile path - set 'path' to be the logfile\n"); - printf("-M or --missing - dump missing machines and video cards\n"); - printf("-N or --noconfirm - do not ask for confirmation on quit\n"); - printf("-P or --vmpath path - set 'path' to be root for vm\n"); - printf("-R or --rompath path - set 'path' to be ROM path\n"); + "-L or --logfile pat\t\t- set 'path' to be the logfile\n" + "-M or --missing\t\t- dump missing machines and video cards\n" + "-N or --noconfirm\t\t- do not ask for confirmation on quit\n" + "-P or --vmpath path\t\t- set 'path' to be root for vm\n" + "-R or --rompath path\t\t- set 'path' to be ROM path\n" #ifndef USE_SDL_UI - printf("-S or --settings - show only the settings dialog\n"); + "-S or --settings\t\t\t- show only the settings dialog\n" #endif - printf("-T or --testmode - test mode: execute the test mode entry point on init/hard reset\n"); - printf("-V or --vmname name - overrides the name of the running VM\n"); - printf("-W or --nohook - disables keyboard hook (compatibility-only outside Windows)\n"); - printf("-X or --clear what - clears the 'what' (cmos/flash/both)\n"); - printf("-Y or --donothing - do not show any UI or run the emulation\n"); - printf("-Z or --lastvmpath - the last parameter is VM path rather than config\n"); - printf("\nA config file can be specified. If none is, the default file will be used.\n"); + "-T or --testmode\t\t- test mode: execute the test mode entry\n" + "\t\t\t\t point on init/hard reset\n" + "-V or --vmname name\t\t- overrides the name of the running VM\n" + "-W or --nohook\t\t- disables keyboard hook\n" + "\t\t\t\t (compatibility-only outside Windows)\n" + "-X or --clear what\t\t- clears the 'what' (cmos/flash/both)\n" + "-Y or --donothing\t\t- do not show any UI or run the emulation\n" + "-Z or --lastvmpath\t\t- the last parameter is VM path rather\n" + "\t\t\t\t than config\n" + "\nA config file can be specified. If none is, the default file will be used.\n"); return 0; } else if (!strcasecmp(argv[c], "--lastvmpath") || !strcasecmp(argv[c], "-Z")) { lvmp = 1; diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 57f8001dc..b4e8a5486 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -141,7 +141,14 @@ ui_msgbox_header(int flags, void *header, void *message) // any error in early init if (main_window == nullptr) { - QMessageBox msgBox(QMessageBox::Icon::Critical, hdr, msg); + auto msgicon = QMessageBox::Icon::Critical; + if (flags & MBX_INFO) + msgicon = QMessageBox::Icon::Information; + else if (flags & MBX_QUESTION) + msgicon = QMessageBox::Icon::Question; + else if (flags & MBX_WARNING) + msgicon = QMessageBox::Icon::Warning; + QMessageBox msgBox(msgicon, hdr, msg); msgBox.exec(); } else { // else scope it to main_window From ac25b87e48ce723f3d7896089634fe2e0b603148 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 21 Apr 2025 13:42:28 +0200 Subject: [PATCH 0779/1190] Fix a warning in QT. --- src/qt/qt_settingsinput.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index bf5035110..79225cb91 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -48,7 +48,6 @@ SettingsInput::SettingsInput(QWidget *parent) { ui->setupUi(this); - QStandardItemModel *model; QStringList horizontalHeader; QStringList verticalHeader; From 5d33bc0dc23be9bfa95567b5121c0a02ff3a7c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 21 Apr 2025 14:20:57 +0200 Subject: [PATCH 0780/1190] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c01a852b5..ee0e1e7f1 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ Performance may vary depending on both host and guest configuration. Most emulat It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines. +* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux) * [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only) * [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia) -* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux) * [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python) * [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested) * [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only) From 369167dd9be5aa9fe4f54c9d5f1a2a8fa1728e9f Mon Sep 17 00:00:00 2001 From: richardg867 Date: Mon, 21 Apr 2025 21:05:54 -0300 Subject: [PATCH 0781/1190] Update Jenkinsfile Jenkins: Fix the branch build manifest change (note: new Windows build node starts here) --- .ci/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index 04b0bc350..530349ced 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -20,7 +20,7 @@ def repository = ['https://github.com/86Box/86Box.git', scm.userRemoteConfigs[0] def commitBrowser = ['https://github.com/86Box/86Box/commit/%s', null] def branch = ['master', scm.branches[0].name] def buildType = ['beta', 'alpha'] -def tarballFlags = ['', '-s'] +def tarballFlags = ['', '-t'] def buildBranch = env.JOB_BASE_NAME.contains('-') ? 1 : 0 def osArchs = [ From 8790395a055578f29c2d1cac65178ecfa39301e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 22 Apr 2025 09:13:38 +0200 Subject: [PATCH 0782/1190] Fix the FXSAVE/FXRSTOR instructions. --- src/codegen/codegen_x86-64.c | 13 +++++++++ src/codegen/codegen_x86.c | 13 +++++++++ src/codegen_new/codegen.c | 12 +++++++++ src/codegen_new/codegen_reg.c | 1 + src/codegen_new/codegen_reg.h | 3 ++- src/cpu/386_common.c | 2 ++ src/cpu/cpu.h | 2 ++ src/cpu/x86_ops_fpu.h | 16 +++++++++++ src/cpu/x86_ops_fpu_2386.h | 16 +++++++++++ src/cpu/x86_ops_i686.h | 50 ++++++++++++++++++++++++----------- 10 files changed, 111 insertions(+), 17 deletions(-) diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index 00db630a3..adb97169d 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -819,6 +819,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int pc_off = 0; int test_modrm = 1; int c; + uint16_t op87 = 0x0000; op_ea_seg = &cpu_state.seg_ds; op_ssegs = 0; @@ -872,6 +873,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xd8: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8; opcode_shift = 3; @@ -882,6 +884,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xd9: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9; opcode_mask = 0xff; @@ -891,6 +894,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xda: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da; opcode_mask = 0xff; @@ -900,6 +904,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdb: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db; opcode_mask = 0xff; @@ -909,6 +914,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdc: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc; opcode_shift = 3; @@ -919,6 +925,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdd: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd; opcode_mask = 0xff; @@ -928,6 +935,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xde: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de; opcode_mask = 0xff; @@ -937,6 +945,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdf: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df; opcode_mask = 0xff; @@ -1000,6 +1009,10 @@ generate_call: recomp_op_table = recomp_opcodes; } + if (op87 != 0x0000) { + STORE_IMM_ADDR_W((uintptr_t) &x87_op, op87); + } + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); if (new_pc) { diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index 935e2bab6..cb635d4f1 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1858,6 +1858,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int pc_off = 0; int test_modrm = 1; int c; + uint16_t op87 = 0x0000; op_ea_seg = &cpu_state.seg_ds; op_ssegs = 0; @@ -1912,6 +1913,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xd8: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8; opcode_shift = 3; @@ -1922,6 +1924,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xd9: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9; opcode_mask = 0xff; @@ -1931,6 +1934,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xda: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da; opcode_mask = 0xff; @@ -1940,6 +1944,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdb: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db; opcode_mask = 0xff; @@ -1949,6 +1954,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdc: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc; opcode_shift = 3; @@ -1959,6 +1965,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdd: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd; opcode_mask = 0xff; @@ -1968,6 +1975,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xde: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de; opcode_mask = 0xff; @@ -1977,6 +1985,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdf: + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df; opcode_mask = 0xff; @@ -2041,6 +2050,10 @@ generate_call: recomp_op_table = recomp_opcodes; } + if (op87 != 0x0000) { + STORE_IMM_ADDR_W((uintptr_t) &x87_op, op87); + } + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); if (new_pc) { diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 82f6cd037..44dd408ab 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -396,6 +396,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int test_modrm = 1; int pc_off = 0; uint32_t next_pc = 0; + uint16_t op87 = 0x0000; #ifdef DEBUG_EXTRA uint8_t last_prefix = 0; #endif @@ -451,6 +452,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xd8; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8; opcode_shift = 3; @@ -464,6 +466,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xd9; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9; opcode_mask = 0xff; @@ -476,6 +479,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xda; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da; opcode_mask = 0xff; @@ -488,6 +492,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdb; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db; opcode_mask = 0xff; @@ -500,6 +505,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdc; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc; opcode_shift = 3; @@ -513,6 +519,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdd; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd; opcode_mask = 0xff; @@ -525,6 +532,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xde; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de; opcode_mask = 0xff; @@ -537,6 +545,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdf; #endif + op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff); op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df; opcode_mask = 0xff; @@ -657,6 +666,9 @@ generate_call: } } codegen_mark_code_present(block, cs + old_pc, (op_pc - old_pc) - pc_off); + if (op87 != 0x0000) { + uop_MOV_IMM(ir, IREG_x87_op, op87); + } /* It is apparently a prefixed instruction. */ #if 0 if ((recomp_op_table == recomp_opcodes) && (opcode == 0x48)) diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index de67fde5a..ba60ab038 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -170,6 +170,7 @@ struct [IREG_SS_limit_high] = { REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, [IREG_eaa16] = { REG_WORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, + [IREG_x87_op] = { REG_WORD, &x87_op, REG_INTEGER, REG_PERMANENT}, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will diff --git a/src/codegen_new/codegen_reg.h b/src/codegen_new/codegen_reg.h index fd3cf279a..2185fde45 100644 --- a/src/codegen_new/codegen_reg.h +++ b/src/codegen_new/codegen_reg.h @@ -133,8 +133,9 @@ enum { IREG_SS_limit_high = 87, IREG_eaa16 = 88, + IREG_x87_op = 89, - IREG_COUNT = 89, + IREG_COUNT = 90, IREG_INVALID = 255, diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 2853e3c9a..ecd83966c 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -113,6 +113,8 @@ uint8_t is_smint = 0; uint16_t io_port = 0x0000; uint32_t io_val = 0x00000000; +uint16_t x87_op = 0x0000; + 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*/ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 0e49704fd..63b831d84 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -784,6 +784,8 @@ typedef struct { uint32_t smhr; } cyrix_t; +extern uint16_t x87_op; + extern uint32_t addr64; extern uint32_t addr64_2; extern uint32_t addr64a[8]; diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index 3434c4a73..afc79dd42 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -4,88 +4,104 @@ static int opESCAPE_d8_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_d8_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_d9_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_d9_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_da_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_da_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_db_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_db_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_dc_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_dc_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_dd_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_dd_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_de_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_de_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_df_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_df_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat); } diff --git a/src/cpu/x86_ops_fpu_2386.h b/src/cpu/x86_ops_fpu_2386.h index c2252af12..7488a3d85 100644 --- a/src/cpu/x86_ops_fpu_2386.h +++ b/src/cpu/x86_ops_fpu_2386.h @@ -4,88 +4,104 @@ static int opESCAPE_d8_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_d8_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_d9_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_d9_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_d9_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_d9_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_da_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_da_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_da_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_da_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_db_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_db_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_db_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_db_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_dc_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_dc_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); } static int opESCAPE_dd_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_dd_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_dd_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_dd_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_de_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_de_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_de_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_de_a32[fetchdat & 0xff](fetchdat); } static int opESCAPE_df_a16(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_df_a16[fetchdat & 0xff](fetchdat); } static int opESCAPE_df_a32(uint32_t fetchdat) { + x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff); return x86_2386_opcodes_df_a32[fetchdat & 0xff](fetchdat); } diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index a67571875..0809fac74 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -46,8 +46,6 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) if (CPUID < 0x650) return ILLEGAL(fetchdat); - FP_ENTER(); - if (bits == 32) { fetch_ea_32(fetchdat); } else { @@ -82,12 +80,18 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ fpu_state.foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF; - fpu_state.fip = readmeml(easeg, cpu_state.eaaddr + 8); + if (bits == 32) + fpu_state.fip = readmeml(easeg, cpu_state.eaaddr + 8); + else + fpu_state.fip = readmemw(easeg, cpu_state.eaaddr + 8); fpu_state.fcs = readmemw(easeg, cpu_state.eaaddr + 12); tag_byte = readmemb(easeg, cpu_state.eaaddr + 4); - fpu_state.fdp = readmeml(easeg, cpu_state.eaaddr + 16); + if (bits == 32) + fpu_state.fdp = readmeml(easeg, cpu_state.eaaddr + 16); + else + fpu_state.fdp = readmemw(easeg, cpu_state.eaaddr + 16); fpu_state.fds = readmemw(easeg, cpu_state.eaaddr + 20); /* load i387 register file */ @@ -110,7 +114,6 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward); } - // CLOCK_CYCLES((cr0 & 1) ? 34 : 44); CLOCK_CYCLES(1); } else { /* FXSAVE */ @@ -132,7 +135,10 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) * x87 CS FPU IP Selector * + 16 bit, in 16/32 bit mode only */ - writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip); + if (bits == 32) + writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip); + else + writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip & 0xffff); writememl(easeg, cpu_state.eaaddr + 12, fpu_state.fcs); /* @@ -145,7 +151,10 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) * x87 DS FPU Instruction Operand (Data) Pointer Selector * + 16 bit, in 16/32 bit mode only */ - writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp); + if (bits == 32) + writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp); + else + writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp & 0xffff); writememl(easeg, cpu_state.eaaddr + 20, fpu_state.fds); /* store i387 register file */ @@ -256,8 +265,6 @@ fx_save_stor_common(uint32_t fetchdat, int bits) return cpu_state.abrt; } - FP_ENTER(); - old_eaaddr = cpu_state.eaaddr; if (fxinst == 1) { @@ -269,13 +276,19 @@ fx_save_stor_common(uint32_t fetchdat, int bits) cpu_state.TOP = (fpus >> 11) & 7; cpu_state.npxs &= fpus & ~0x3800; - x87_pc_off = readmeml(easeg, cpu_state.eaaddr + 8); + if (bits == 32) + x87_pc_off = readmeml(easeg, cpu_state.eaaddr + 8); + else + x87_pc_off = readmemw(easeg, cpu_state.eaaddr + 8); x87_pc_seg = readmemw(easeg, cpu_state.eaaddr + 12); ftwb = readmemb(easeg, cpu_state.eaaddr + 4); + x87_op = readmemw(easeg, cpu_state.eaaddr + 6) & 0x07ff; - x87_op_off = readmeml(easeg, cpu_state.eaaddr + 16); - x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16; + if (bits == 32) + x87_op_off = readmeml(easeg, cpu_state.eaaddr + 16); + else + x87_op_off = readmemw(easeg, cpu_state.eaaddr +16); x87_op_seg = readmemw(easeg, cpu_state.eaaddr + 20); for (i = 0; i <= 7; i++) { @@ -320,7 +333,6 @@ fx_save_stor_common(uint32_t fetchdat, int bits) } } - // CLOCK_CYCLES((cr0 & 1) ? 34 : 44); CLOCK_CYCLES(1); } else { /* FXSAVE */ @@ -345,11 +357,17 @@ fx_save_stor_common(uint32_t fetchdat, int bits) writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs); writememb(easeg, cpu_state.eaaddr + 4, ftwb); - writememw(easeg, cpu_state.eaaddr + 6, (x87_op_off >> 16) << 12); - writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 6, x87_op); + if (bits == 32) + writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off); + else + writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off & 0xffff); writememw(easeg, cpu_state.eaaddr + 12, x87_pc_seg); - writememl(easeg, cpu_state.eaaddr + 16, x87_op_off); + if (bits == 32) + writememl(easeg, cpu_state.eaaddr + 16, x87_op_off); + else + writememl(easeg, cpu_state.eaaddr + 16, x87_op_off & 0xffff); writememw(easeg, cpu_state.eaaddr + 20, x87_op_seg); if (cpu_state.ismmx) { From b15f25ffa46ed7c2bc189fcf34fef2dd546dd6a4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 22 Apr 2025 09:46:58 +0200 Subject: [PATCH 0783/1190] Fixed old recompiler compiling in a kludgy way because it appears there's no STORE_IMM_ADDR_W. --- src/codegen/codegen_x86-64.c | 4 ++-- src/codegen/codegen_x86.c | 4 ++-- src/cpu/386_common.c | 2 +- src/cpu/cpu.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index adb97169d..c424cf8c5 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -819,7 +819,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int pc_off = 0; int test_modrm = 1; int c; - uint16_t op87 = 0x0000; + uint32_t op87 = 0x00000000; op_ea_seg = &cpu_state.seg_ds; op_ssegs = 0; @@ -1010,7 +1010,7 @@ generate_call: } if (op87 != 0x0000) { - STORE_IMM_ADDR_W((uintptr_t) &x87_op, op87); + STORE_IMM_ADDR_L((uintptr_t) &x87_op, op87); } if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index cb635d4f1..bf34c2de8 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1858,7 +1858,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int pc_off = 0; int test_modrm = 1; int c; - uint16_t op87 = 0x0000; + uint32_t op87 = 0x00000000; op_ea_seg = &cpu_state.seg_ds; op_ssegs = 0; @@ -2051,7 +2051,7 @@ generate_call: } if (op87 != 0x0000) { - STORE_IMM_ADDR_W((uintptr_t) &x87_op, op87); + STORE_IMM_ADDR_L((uintptr_t) &x87_op, op87); } if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index ecd83966c..c6a759d36 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -113,7 +113,7 @@ uint8_t is_smint = 0; uint16_t io_port = 0x0000; uint32_t io_val = 0x00000000; -uint16_t x87_op = 0x0000; +uint32_t x87_op = 0x00000000; int opcode_has_modrm[256] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 63b831d84..b76e2d622 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -784,7 +784,7 @@ typedef struct { uint32_t smhr; } cyrix_t; -extern uint16_t x87_op; +extern uint32_t x87_op; extern uint32_t addr64; extern uint32_t addr64_2; From e703ac760b6c0cf0cac3bfa0b196688178c5a099 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 22 Apr 2025 17:37:00 +0600 Subject: [PATCH 0784/1190] Write indicators (except for floppy drives) --- src/disk/hdc_esdi_at.c | 24 ++++-- src/disk/hdc_esdi_mca.c | 9 ++ src/disk/hdc_ide.c | 12 +-- src/disk/hdc_st506_at.c | 9 +- src/disk/hdc_st506_xt.c | 18 ++-- src/disk/hdc_xta.c | 10 +-- src/disk/mo.c | 6 +- src/disk/zip.c | 6 +- src/include/86box/machine_status.h | 2 + src/include/86box/ui.h | 1 + src/machine/m_ps1_hdc.c | 13 +-- src/network/network.c | 4 +- src/qt/icons/write_active.ico | Bin 0 -> 6950 bytes src/qt/qt_iconindicators.cpp | 8 +- src/qt/qt_iconindicators.hpp | 2 + src/qt/qt_machinestatus.cpp | 131 ++++++++++++++++++++++++----- src/qt/qt_ui.cpp | 37 ++++++++ src/qt_resources.qrc | 1 + src/scsi/scsi_disk.c | 5 +- src/sound/CMakeLists.txt | 2 +- 20 files changed, 232 insertions(+), 68 deletions(-) create mode 100644 src/qt/icons/write_active.ico diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index ab24aa6fa..64d292250 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -395,7 +395,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) fatal("Write with ECC\n"); esdi->status = STAT_READY | STAT_DRQ | STAT_DSC; esdi->pos = 0; - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 1); break; case CMD_VERIFY: @@ -412,7 +412,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case CMD_FORMAT: esdi->status = STAT_DRQ; esdi->pos = 0; - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 1); break; case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ @@ -593,6 +593,7 @@ esdi_callback(void *priv) esdi->reset = 0; ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); return; } @@ -650,7 +651,7 @@ read_error: esdi->status = STAT_READY | STAT_ERR | STAT_DSC; esdi->error = ERR_ABRT; irq_raise(esdi); - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; } else { if (get_sector(esdi, &addr)) { @@ -658,7 +659,7 @@ read_error: write_error: esdi->status = STAT_READY | STAT_DSC | STAT_ERR; irq_raise(esdi); - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; } @@ -672,10 +673,10 @@ write_error: esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; esdi->pos = 0; next_sector(esdi); - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 1); } else { esdi->status = STAT_READY | STAT_DSC; - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } } break; @@ -718,7 +719,7 @@ verify_error: break; case CMD_FORMAT: - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); if (!drive->present) { esdi->status = STAT_READY | STAT_ERR | STAT_DSC; esdi->error = ERR_ABRT; @@ -752,10 +753,12 @@ format_error: esdi->status = STAT_READY | STAT_DSC; irq_raise(esdi); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); if (!drive->present) { esdi->status = STAT_READY | STAT_ERR | STAT_DSC; esdi->error = ERR_ABRT; @@ -778,10 +781,12 @@ format_error: esdi->error = ERR_ABRT; irq_raise(esdi); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; case 0xe0: ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); if (!drive->present) { esdi->status = STAT_READY | STAT_ERR | STAT_DSC; esdi->error = ERR_ABRT; @@ -825,6 +830,7 @@ format_error: } irq_raise(esdi); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; case CMD_READ_PARAMETERS: @@ -869,6 +875,7 @@ format_error: irq_raise(esdi); } ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; default: @@ -880,6 +887,7 @@ format_error: esdi->error = ERR_ABRT; irq_raise(esdi); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; } } @@ -954,6 +962,7 @@ wd1007vse1_init(UNUSED(const device_t *info)) timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); return esdi; } @@ -973,6 +982,7 @@ wd1007vse1_close(void *priv) free(esdi); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } static int diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 8f1def137..e59ae981d 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -288,6 +288,7 @@ cmd_unsupported(esdi_t *dev) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } static void @@ -309,6 +310,7 @@ device_not_present(esdi_t *dev) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } static void @@ -330,6 +332,7 @@ rba_out_of_range(esdi_t *dev) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } static void @@ -351,6 +354,7 @@ defective_block(esdi_t *dev) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } static void @@ -368,6 +372,7 @@ complete_command_status(esdi_t *dev) dev->status_data[5] = (dev->rba - 1) >> 8; dev->status_data[6] = 0; /*Number of blocks requiring error recovery*/ ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); } #define ESDI_ADAPTER_ONLY() \ @@ -696,6 +701,7 @@ esdi_callback(void *priv) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; case CMD_GET_DEV_CONFIG: @@ -744,6 +750,7 @@ esdi_callback(void *priv) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; case CMD_GET_POS_INFO: @@ -764,6 +771,7 @@ esdi_callback(void *priv) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; case 0x10: @@ -817,6 +825,7 @@ esdi_callback(void *priv) dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0); break; default: diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 04e580e72..fe48bba6d 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1827,7 +1827,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->blockcount = 0; /* Turn on the activity indicator *here* so that it gets turned on less times. */ - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1); fallthrough; case WIN_WRITE: @@ -2479,10 +2479,10 @@ ide_callback(void *priv) ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide->tf->pos = 0; ide_next_sector(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } else { ide->tf->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } if (ret < 0) err = UNC_ERR; @@ -2524,7 +2524,7 @@ ide_callback(void *priv) err = UNC_ERR; ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } else { /* Bus master DMA error, abort the command. */ ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); @@ -2562,7 +2562,7 @@ ide_callback(void *priv) ide_next_sector(ide); } else { ide->tf->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0); + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } if (ret < 0) err = UNC_ERR; @@ -2596,7 +2596,7 @@ ide_callback(void *priv) err = UNC_ERR; ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1); + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } break; diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index 07c57b2ca..ed7b29d1f 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -557,6 +557,7 @@ do_callback(void *priv) mfm->reset = 0; ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); return; } @@ -627,9 +628,9 @@ write_error: mfm->status |= STAT_DRQ; mfm->pos = 0; next_sector(mfm); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1); } else - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); break; case CMD_VERIFY: @@ -657,7 +658,7 @@ write_error: mfm->status = STAT_READY | STAT_DSC; irq_raise(mfm); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1); break; case CMD_DIAGNOSE: @@ -772,6 +773,7 @@ mfm_init(UNUSED(const device_t *info)) timer_add(&mfm->callback_timer, do_callback, mfm, 0); ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); return mfm; } @@ -790,6 +792,7 @@ mfm_close(void *priv) free(mfm); ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); } const device_t st506_at_wd1003_device = { diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 536fd76c0..b3a07fa5a 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -580,14 +580,14 @@ st506_callback(void *priv) (void) get_chs(dev, drive); st506_xt_log("ST506: FORMAT_DRIVE(%i) interleave=%i\n", dev->drive_sel, dev->command[4]); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1); timer_advance_u64(&dev->timer, ST506_TIME); dev->state = STATE_SEND_DATA; break; case STATE_SEND_DATA: /* wrong, but works */ if (!get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); st506_error(dev, dev->error); st506_complete(dev); return; @@ -604,7 +604,7 @@ st506_callback(void *priv) break; case STATE_SENT_DATA: - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); st506_complete(dev); break; @@ -663,14 +663,14 @@ st506_callback(void *priv) st506_xt_log("ST506: FORMAT_%sTRACK(%i, %i/%i)\n", (dev->command[0] == CMD_FORMAT_BAD_TRACK) ? "BAD_" : "", dev->drive_sel, dev->cylinder, dev->head); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1); timer_advance_u64(&dev->timer, ST506_TIME); dev->state = STATE_SEND_DATA; break; case STATE_SEND_DATA: /* wrong, but works */ if (!get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); st506_error(dev, dev->error); st506_complete(dev); return; @@ -686,7 +686,7 @@ st506_callback(void *priv) break; case STATE_SENT_DATA: - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); st506_complete(dev); break; @@ -828,7 +828,7 @@ read_error_sent: return; } - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1); /* Set up the data transfer. */ dev->buff_pos = 0; @@ -865,7 +865,7 @@ read_error_sent: case STATE_RECEIVED_DATA: if (!get_sector(dev, drive, &addr)) { write_error: - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); st506_error(dev, dev->error); st506_complete(dev); return; @@ -879,7 +879,7 @@ write_error: } if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0); st506_complete(dev); break; } diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index b01d80c61..85581af2d 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -385,7 +385,7 @@ do_format(hdc_t *dev, drive_t *drive, dcb_t *dcb) dev->sector = 0; /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 1); do_fmt: /* @@ -426,7 +426,7 @@ do_fmt: } /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); } /* Execute the DCB we just received. */ @@ -631,7 +631,7 @@ read_error: case STATE_RECV: /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 1); do_recv: /* Ready to transfer the data in. */ dev->state = STATE_RDATA; @@ -680,7 +680,7 @@ do_recv: if (get_sector(dev, drive, &addr)) { write_error: /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); dev->comp |= COMP_ERR; set_intr(dev); @@ -697,7 +697,7 @@ write_error: dev->buf_idx = 0; if (--dev->count == 0) { /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); set_intr(dev); return; diff --git a/src/disk/mo.c b/src/disk/mo.c index a20333404..1a2db0443 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -628,6 +628,7 @@ mo_cmd_error(mo_t *dev) dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); + ui_sb_update_icon_write(SB_MO | dev->id, 0); mo_log(dev->log, "[%02X] ERROR: %02X/%02X/%02X\n", dev->current_cdb[0], mo_sense_key, mo_asc, mo_ascq); } @@ -644,6 +645,7 @@ mo_unit_attention(mo_t *dev) dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); + ui_sb_update_icon_write(SB_MO | dev->id, 0); mo_log(dev->log, "UNIT ATTENTION\n"); } @@ -1462,7 +1464,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size, dev->packet_len, 1); - ui_sb_update_icon(SB_MO | dev->id, + ui_sb_update_icon_write(SB_MO | dev->id, dev->packet_status != PHASE_COMPLETE); } else { mo_set_phase(dev, SCSI_PHASE_STATUS); @@ -1501,7 +1503,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) dev->drv->sector_size, alloc_length, 1); - ui_sb_update_icon(SB_MO | dev->id, + ui_sb_update_icon_write(SB_MO | dev->id, dev->packet_status != PHASE_COMPLETE); } else { mo_set_phase(dev, SCSI_PHASE_STATUS); diff --git a/src/disk/zip.c b/src/disk/zip.c index 7a407c5fe..55cf901a4 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -709,6 +709,7 @@ zip_cmd_error(zip_t *dev) dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); ui_sb_update_icon(SB_ZIP | dev->id, 0); + ui_sb_update_icon_write(SB_ZIP | dev->id, 0); zip_log(dev->log, "[%02X] ERROR: %02X/%02X/%02X\n", dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); } @@ -725,6 +726,7 @@ zip_unit_attention(zip_t *dev) dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); ui_sb_update_icon(SB_ZIP | dev->id, 0); + ui_sb_update_icon_write(SB_ZIP | dev->id, 0); zip_log(dev->log, "UNIT ATTENTION\n", dev->id); } @@ -1485,7 +1487,7 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb) zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - ui_sb_update_icon(SB_ZIP | dev->id, + ui_sb_update_icon_write(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); } else { zip_set_phase(dev, SCSI_PHASE_STATUS); @@ -1526,7 +1528,7 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb) zip_data_command_finish(dev, 512, 512, alloc_length, 1); - ui_sb_update_icon(SB_ZIP | dev->id, + ui_sb_update_icon_write(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); } else { zip_set_phase(dev, SCSI_PHASE_STATUS); diff --git a/src/include/86box/machine_status.h b/src/include/86box/machine_status.h index e7c57881b..e6e9e6acd 100644 --- a/src/include/86box/machine_status.h +++ b/src/include/86box/machine_status.h @@ -4,10 +4,12 @@ typedef struct dev_status_empty_active_t { atomic_bool_t empty; atomic_bool_t active; + atomic_bool_t write_active; } dev_status_empty_active_t; typedef struct dev_status_active_t { atomic_bool_t active; + atomic_bool_t write_active; } dev_status_active_t; typedef struct dev_status_empty_t { diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index c12eb73a0..783400ebc 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -65,6 +65,7 @@ extern void ui_sb_update_panes(void); extern void ui_sb_update_text(void); extern void ui_sb_update_tip(int meaning); extern void ui_sb_update_icon(int tag, int active); +extern void ui_sb_update_icon_write(int tag, int write); extern void ui_sb_update_icon_state(int tag, int state); extern void ui_sb_set_text_w(wchar_t *wstr); extern void ui_sb_set_text(char *str); diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index 18792ded7..ea71c918b 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -653,7 +653,7 @@ do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb) case STATE_FINIT: do_fmt: /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 1); /* Seek to cylinder. */ if (do_seek(dev, drive, start_cyl)) { @@ -691,7 +691,7 @@ do_fmt: } /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); /* This saves us a LOT of code. */ dev->state = STATE_FINIT; @@ -705,6 +705,7 @@ do_fmt: if (intr) { /* De-activate the status icon. */ ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); do_finish(dev); } @@ -970,7 +971,7 @@ do_send: case STATE_RECV: /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 1); do_recv: /* Ready to transfer the data in. */ dev->state = STATE_RDATA; @@ -1000,7 +1001,7 @@ do_recv: ps1_hdc_log("HDC: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); dev->intstat |= ISR_EQUIP_CHECK; dev->ssb.need_reset = 1; @@ -1025,7 +1026,7 @@ do_recv: /* Get address of sector to write. */ if (get_sector(dev, drive, &addr)) { /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); do_finish(dev); return; @@ -1038,7 +1039,7 @@ do_recv: dev->buf_idx = 0; if (--dev->count == 0) { /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0); if (!(dev->ctrl & ACR_DMA_EN)) dev->status &= ~ASR_DATA_REQ; diff --git a/src/network/network.c b/src/network/network.c index 52b686c7e..239178a5d 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -432,7 +432,8 @@ network_rx_queue(void *priv) bool activity = rx_bytes || tx_bytes; bool led_on = card->led_timer & 0x80000000; if ((activity && !led_on) || (card->led_timer & 0x7fffffff) >= 150000) { - ui_sb_update_icon(SB_NETWORK | card->card_num, activity); + ui_sb_update_icon(SB_NETWORK | card->card_num, !!(rx_bytes)); + ui_sb_update_icon_write(SB_NETWORK | card->card_num, !!(tx_bytes)); card->led_timer = 0 | (activity << 31); } @@ -577,6 +578,7 @@ void network_reset(void) { ui_sb_update_icon(SB_NETWORK, 0); + ui_sb_update_icon_write(SB_NETWORK, 0); #ifdef ENABLE_NETWORK_LOG network_dump_mutex = thread_create_mutex(); diff --git a/src/qt/icons/write_active.ico b/src/qt/icons/write_active.ico new file mode 100644 index 0000000000000000000000000000000000000000..d1ebdb22498d6dbdfeae87c7d21969948c5cc868 GIT binary patch literal 6950 zcmeI$zfTlF6u|L!czRdyBSAtz^g<=rm`p`yC=3lHJ=MgL{{U)3hy~5-F|nY&n$qHx zmzYoyLnj5Xx=8W-zFqEa!9zu(hOo2w?2ox+=IxtfXZJ)J(vUEugIs^AQ0~3`}O~gdw!Jt&{CUSS`8-sE+{u{2hdhPZ8m<+U-Gj1W~n%jtZtb>;r z%wtTCqf*afqg>Q`bq4ATjLksh_Fn8>KdCZ*#r$?z{2DW(+`F%W-{85SLlz1iYVECMJ`F>4R`L2C=Oh@(mc9E2NRcGLSXW(*L z8z!NA&KOO9w?B^gv-0<42gCON`%e7C_ygP;c|W{a+-Kvb&e#s_vv0@VXQPp_t7x!j zlZvCGBk}&ZeEj@XdcIwR^6B{-Szdlu+>@KlrnKAb;H0$mZsz83romQ z7#ws!&$(EXwZRbyNXSqa9Fdd+g~1U?O2|+c9Fe$$428iF$xO&l7#uW2ED?nki?Mb@ z(i1Wi21g7;LWaWNh`~w7FgO|vRzilt;D`ZC$WRy@1WzoHjfldE#aYKdCuArLju`xe z428iFUx97o|CQn;m%5wUz>sn>0_B$rNQB-$(PoAF3 LuW&zSIDhUNEg`@d literal 0 HcmV?d00001 diff --git a/src/qt/qt_iconindicators.cpp b/src/qt/qt_iconindicators.cpp index dc8e3ceb2..d5d22c78d 100644 --- a/src/qt/qt_iconindicators.cpp +++ b/src/qt/qt_iconindicators.cpp @@ -8,6 +8,8 @@ getIndicatorIcon(IconIndicator indicator) switch (indicator) { case Active: return QIcon(":/settings/qt/icons/active.ico"); + case WriteActive: + return QIcon(":/settings/qt/icons/write_active.ico"); case Disabled: return QIcon(":/settings/qt/icons/disabled.ico"); default: @@ -24,9 +26,13 @@ getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, return iconPixmap; auto painter = QPainter(&iconPixmap); - auto indicatorPixmap = getIndicatorIcon(indicator).pixmap(size); + auto indicatorPixmap = getIndicatorIcon(indicator == ReadWriteActive ? Active : indicator).pixmap(size); painter.drawPixmap(0, 0, indicatorPixmap); + if (indicator == ReadWriteActive) { + auto writeIndicatorPixmap = getIndicatorIcon(WriteActive).pixmap(size); + painter.drawPixmap(0, 0, writeIndicatorPixmap); + } painter.end(); return iconPixmap; diff --git a/src/qt/qt_iconindicators.hpp b/src/qt/qt_iconindicators.hpp index 553520063..861e41d94 100644 --- a/src/qt/qt_iconindicators.hpp +++ b/src/qt/qt_iconindicators.hpp @@ -7,6 +7,8 @@ enum IconIndicator { None, Active, + WriteActive, + ReadWriteActive, Disabled, }; diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index f93734887..db32569f3 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -68,6 +68,8 @@ namespace { struct PixmapSetActive { QPixmap normal; QPixmap active; + QPixmap write_active; + QPixmap read_write_active; void load(const QIcon &icon); }; struct PixmapSetDisabled { @@ -85,6 +87,10 @@ struct PixmapSetEmptyActive { QPixmap active; QPixmap empty; QPixmap empty_active; + QPixmap write_active; + QPixmap read_write_active; + QPixmap empty_write_active; + QPixmap empty_read_write_active; void load(const QIcon &icon); }; struct Pixmaps { @@ -105,6 +111,7 @@ struct StateActive { std::unique_ptr label; PixmapSetActive *pixmaps = nullptr; bool active = false; + bool write_active = false; void setActive(bool b) { @@ -115,11 +122,23 @@ struct StateActive { refresh(); } + void setWriteActive(bool b) + { + if (!label || b == write_active) + return; + + write_active = b; + refresh(); + } + void refresh() { if (!label) return; - label->setPixmap(active ? pixmaps->active : pixmaps->normal); + if (active && write_active) + label->setPixmap(pixmaps->read_write_active); + else + label->setPixmap(write_active ? pixmaps->write_active : (active ? pixmaps->active : pixmaps->normal)); } }; struct StateEmpty { @@ -145,9 +164,10 @@ struct StateEmpty { }; struct StateEmptyActive { std::unique_ptr label; - PixmapSetEmptyActive *pixmaps = nullptr; - bool empty = false; - bool active = false; + PixmapSetEmptyActive *pixmaps = nullptr; + bool empty = false; + bool active = false; + bool write_active = false; void setActive(bool b) { @@ -157,6 +177,14 @@ struct StateEmptyActive { active = b; refresh(); } + void setWriteActive(bool b) + { + if (!label || b == write_active) + return; + + write_active = b; + refresh(); + } void setEmpty(bool b) { if (!label || b == empty) @@ -170,9 +198,15 @@ struct StateEmptyActive { if (!label) return; if (empty) { - label->setPixmap(active ? pixmaps->empty_active : pixmaps->empty); + if (active && write_active) + label->setPixmap(pixmaps->empty_read_write_active); + else + label->setPixmap(write_active ? pixmaps->empty_write_active : (active ? pixmaps->empty_active : pixmaps->empty)); } else { - label->setPixmap(active ? pixmaps->active : pixmaps->normal); + if (active && write_active) + label->setPixmap(pixmaps->read_write_active); + else + label->setPixmap(write_active ? pixmaps->write_active : (active ? pixmaps->active : pixmaps->normal)); } } }; @@ -191,6 +225,9 @@ PixmapSetActive::load(const QIcon &icon) { normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); + + write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, WriteActive); + read_write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, ReadWriteActive); } void @@ -203,10 +240,14 @@ PixmapSetDisabled::load(const QIcon &icon) 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); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); + write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, WriteActive); + read_write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, ReadWriteActive); + empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None); + empty_active = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Active); + empty_write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, WriteActive); + empty_read_write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, ReadWriteActive); } } @@ -217,10 +258,13 @@ struct MachineStatus::States { { 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_disabled.normal = QIcon(":/settings/qt/icons/floppy_disabled.ico").pixmap(pixmap_size); + pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.read_write_active = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.empty_write_active = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.empty_read_write_active = pixmaps.floppy_disabled.normal; 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")); @@ -435,49 +479,79 @@ MachineStatus::refreshIcons() if (!update_icons) return; - for (size_t i = 0; i < FDD_NUM; ++i) + for (size_t i = 0; i < FDD_NUM; ++i) { d->fdd[i].setActive(machine_status.fdd[i].active); + d->fdd[i].setWriteActive(machine_status.fdd[i].write_active); + } for (size_t i = 0; i < CDROM_NUM; ++i) { d->cdrom[i].setActive(machine_status.cdrom[i].active); - if (machine_status.cdrom[i].active) + d->cdrom[i].setWriteActive(machine_status.cdrom[i].write_active); + if (machine_status.cdrom[i].active) { ui_sb_update_icon(SB_CDROM | i, 0); + } + if (machine_status.cdrom[i].write_active) { + ui_sb_update_icon_write(SB_CDROM | i, 0); + } } for (size_t i = 0; i < ZIP_NUM; i++) { d->zip[i].setActive(machine_status.zip[i].active); + d->zip[i].setWriteActive(machine_status.zip[i].write_active); if (machine_status.zip[i].active) ui_sb_update_icon(SB_ZIP | i, 0); + if (machine_status.zip[i].write_active) + ui_sb_update_icon_write(SB_ZIP | i, 0); } for (size_t i = 0; i < MO_NUM; i++) { d->mo[i].setActive(machine_status.mo[i].active); + d->mo[i].setWriteActive(machine_status.mo[i].write_active); if (machine_status.mo[i].active) ui_sb_update_icon(SB_MO | i, 0); + if (machine_status.mo[i].write_active) + ui_sb_update_icon_write(SB_MO | i, 0); } for (size_t i = 0; i < HDD_BUS_USB; i++) { d->hdds[i].setActive(machine_status.hdd[i].active); + d->hdds[i].setWriteActive(machine_status.hdd[i].write_active); if (machine_status.hdd[i].active) ui_sb_update_icon(SB_HDD | i, 0); + if (machine_status.hdd[i].write_active) + ui_sb_update_icon_write(SB_HDD | i, 0); } - for (size_t i = 0; i < NET_CARD_MAX; i++) + for (size_t i = 0; i < NET_CARD_MAX; i++) { d->net[i].setActive(machine_status.net[i].active); + d->net[i].setWriteActive(machine_status.net[i].write_active); + } } void MachineStatus::clearActivity() { - for (auto &fdd : d->fdd) + for (auto &fdd : d->fdd) { fdd.setActive(false); - for (auto &cdrom : d->cdrom) + fdd.setWriteActive(false); + } + for (auto &cdrom : d->cdrom) { cdrom.setActive(false); - for (auto &zip : d->zip) + cdrom.setWriteActive(false); + } + for (auto &zip : d->zip) { zip.setActive(false); - for (auto &mo : d->mo) + zip.setWriteActive(false); + } + for (auto &mo : d->mo) { mo.setActive(false); - for (auto &hdd : d->hdds) + mo.setWriteActive(false); + } + for (auto &hdd : d->hdds) { hdd.setActive(false); - for (auto &net : d->net) + hdd.setWriteActive(false); + } + for (auto &net : d->net) { net.setActive(false); + net.setWriteActive(false); + } } void @@ -562,6 +636,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->fdd[i].label = std::make_unique(); d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty()); d->fdd[i].setActive(false); + d->fdd[i].setWriteActive(false); d->fdd[i].refresh(); connect((ClickableLabel *) d->fdd[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->floppyMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->floppyMenus[i]->sizeHint().height())); @@ -578,6 +653,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->cdrom[i].label = std::make_unique(); d->cdrom[i].setEmpty(QString(cdrom[i].image_path).isEmpty()); d->cdrom[i].setActive(false); + d->cdrom[i].setWriteActive(false); d->cdrom[i].refresh(); connect((ClickableLabel *) d->cdrom[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->cdromMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cdromMenus[i]->sizeHint().height())); @@ -594,6 +670,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->zip[i].label = std::make_unique(); d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty()); d->zip[i].setActive(false); + d->zip[i].setWriteActive(false); d->zip[i].refresh(); connect((ClickableLabel *) d->zip[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->zipMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->zipMenus[i]->sizeHint().height())); @@ -610,6 +687,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->mo[i].label = std::make_unique(); d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty()); d->mo[i].setActive(false); + d->mo[i].setWriteActive(false); d->mo[i].refresh(); connect((ClickableLabel *) d->mo[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->moMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->moMenus[i]->sizeHint().height())); @@ -626,6 +704,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->net[i].label = std::make_unique(); d->net[i].setEmpty(!network_is_connected(i)); d->net[i].setActive(false); + d->net[i].setWriteActive(false); d->net[i].refresh(); d->net[i].label->setToolTip(MediaMenu::ptr->netMenus[i]->title()); connect((ClickableLabel *) d->net[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { @@ -638,6 +717,7 @@ MachineStatus::refresh(QStatusBar *sbar) if ((has_mfm || (hdc_name.left(5) == QStringLiteral("st506"))) && (c_mfm > 0)) { d->hdds[HDD_BUS_MFM].label = std::make_unique(); d->hdds[HDD_BUS_MFM].setActive(false); + d->hdds[HDD_BUS_MFM].setWriteActive(false); d->hdds[HDD_BUS_MFM].refresh(); d->hdds[HDD_BUS_MFM].label->setToolTip(tr("Hard disk (%1)").arg("MFM/RLL")); auto tooltip = d->hdds[HDD_BUS_MFM].label->toolTip(); @@ -653,6 +733,7 @@ MachineStatus::refresh(QStatusBar *sbar) if ((has_esdi || (hdc_name.left(4) == QStringLiteral("esdi"))) && (c_esdi > 0)) { d->hdds[HDD_BUS_ESDI].label = std::make_unique(); d->hdds[HDD_BUS_ESDI].setActive(false); + d->hdds[HDD_BUS_ESDI].setWriteActive(false); d->hdds[HDD_BUS_ESDI].refresh(); d->hdds[HDD_BUS_ESDI].label->setToolTip(tr("Hard disk (%1)").arg("ESDI")); auto tooltip = d->hdds[HDD_BUS_ESDI].label->toolTip(); @@ -668,6 +749,7 @@ MachineStatus::refresh(QStatusBar *sbar) if ((has_xta || (hdc_name.left(3) == QStringLiteral("xta"))) && (c_xta > 0)) { d->hdds[HDD_BUS_XTA].label = std::make_unique(); d->hdds[HDD_BUS_XTA].setActive(false); + d->hdds[HDD_BUS_XTA].setWriteActive(false); d->hdds[HDD_BUS_XTA].refresh(); d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%1)").arg("XTA")); auto tooltip = d->hdds[HDD_BUS_XTA].label->toolTip(); @@ -686,6 +768,7 @@ MachineStatus::refresh(QStatusBar *sbar) if (c_ide > 0) { d->hdds[HDD_BUS_IDE].label = std::make_unique(); d->hdds[HDD_BUS_IDE].setActive(false); + d->hdds[HDD_BUS_IDE].setWriteActive(false); d->hdds[HDD_BUS_IDE].refresh(); d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%1)").arg("IDE")); auto tooltip = d->hdds[HDD_BUS_IDE].label->toolTip(); @@ -701,6 +784,7 @@ MachineStatus::refresh(QStatusBar *sbar) if (c_atapi > 0) { d->hdds[HDD_BUS_ATAPI].label = std::make_unique(); d->hdds[HDD_BUS_ATAPI].setActive(false); + d->hdds[HDD_BUS_ATAPI].setWriteActive(false); d->hdds[HDD_BUS_ATAPI].refresh(); d->hdds[HDD_BUS_ATAPI].label->setToolTip(tr("Hard disk (%1)").arg("ATAPI")); auto tooltip = d->hdds[HDD_BUS_ATAPI].label->toolTip(); @@ -720,6 +804,7 @@ MachineStatus::refresh(QStatusBar *sbar) (c_scsi > 0)) { d->hdds[HDD_BUS_SCSI].label = std::make_unique(); d->hdds[HDD_BUS_SCSI].setActive(false); + d->hdds[HDD_BUS_SCSI].setWriteActive(false); d->hdds[HDD_BUS_SCSI].refresh(); d->hdds[HDD_BUS_SCSI].label->setToolTip(tr("Hard disk (%1)").arg("SCSI")); auto tooltip = d->hdds[HDD_BUS_SCSI].label->toolTip(); diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index b4e8a5486..5a6bda852 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -314,4 +314,41 @@ ui_sb_update_icon(int tag, int active) break; } } + +void +ui_sb_update_icon_write(int tag, int write) +{ + const auto temp = static_cast(tag); + const int category = static_cast(temp & 0xfffffff0); + const int item = tag & 0xf; + + switch (category) { + default: + case SB_CASSETTE: + case SB_CARTRIDGE: + break; + case SB_FLOPPY: + machine_status.fdd[item].write_active = write > 0 ? true : false; + break; + case SB_CDROM: + machine_status.cdrom[item].write_active = write > 0 ? true : false; + break; + case SB_ZIP: + machine_status.zip[item].write_active = write > 0 ? true : false; + break; + case SB_MO: + machine_status.mo[item].write_active = write > 0 ? true : false; + break; + case SB_HDD: + machine_status.hdd[item].write_active = write > 0 ? true : false; + break; + case SB_NETWORK: + machine_status.net[item].write_active = write > 0 ? true : false; + break; + case SB_SOUND: + case SB_TEXT: + break; + } +} + } diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index dc8db2c06..bc553ac61 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -28,6 +28,7 @@ qt/icons/zip.ico qt/icons/zip_disabled.ico qt/icons/active.ico + qt/icons/write_active.ico qt/icons/disabled.ico qt/icons/86Box-gray.ico qt/icons/86Box-green.ico diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 0a035a23d..8c09a30a1 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -614,6 +614,7 @@ scsi_disk_cmd_error(scsi_disk_t *dev) dev->callback = 50.0 * SCSI_TIME; scsi_disk_set_callback(dev); ui_sb_update_icon(SB_HDD | dev->drv->bus_type, 0); + ui_sb_update_icon_write(SB_HDD | dev->drv->bus_type, 0); scsi_disk_log(dev->log, "ERROR: %02X/%02X/%02X\n", scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); } @@ -1208,7 +1209,7 @@ scsi_disk_command(scsi_common_t *sc, const uint8_t *cdb) scsi_disk_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - ui_sb_update_icon(SB_HDD | dev->drv->bus_type, dev->packet_status != PHASE_COMPLETE); + ui_sb_update_icon_write(SB_HDD | dev->drv->bus_type, dev->packet_status != PHASE_COMPLETE); } else { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); scsi_disk_log(dev->log, "All done - callback set\n"); @@ -1243,7 +1244,7 @@ scsi_disk_command(scsi_common_t *sc, const uint8_t *cdb) scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1); - ui_sb_update_icon(SB_HDD | dev->drv->bus_type, + ui_sb_update_icon_write(SB_HDD | dev->drv->bus_type, dev->packet_status != PHASE_COMPLETE); } else { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index d575717a0..0bbeb2af5 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -146,7 +146,7 @@ if(FLUIDSYNTH) pkg_check_modules(FLUIDSYNTH REQUIRED IMPORTED_TARGET fluidsynth) target_link_libraries(86Box PkgConfig::FLUIDSYNTH) if(STATIC_BUILD) - target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp) + target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp -lgomp) if(WIN32) add_compile_definitions(FLUIDSYNTH_NOT_A_DLL) From 7901842c429a650278de5e0039cee30c01e9465b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 22 Apr 2025 22:08:52 +0600 Subject: [PATCH 0785/1190] Write indicator for floppy drives Write indicator is also properly contrasted on 5.25 floppy drives --- src/floppy/fdc.c | 27 +++++++++++++++++++++------ src/qt/icons/write_active.ico | Bin 6950 -> 6950 bytes src/sound/CMakeLists.txt | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 1f49b192a..c32b1f442 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -615,7 +615,10 @@ fdc_io_command_phase1(fdc_t *fdc, int out) } } - ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + if (fdc->processed_cmd == 0x05 || fdc->processed_cmd == 0x09) + ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + else + ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); fdc->stat = out ? 0x10 : 0x50; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { fdc->stat |= 0x20; @@ -671,8 +674,10 @@ fdc_soft_reset(fdc_t *fdc) fdc->perp &= 0xfc; - for (int i = 0; i < FDD_NUM; i++) - ui_sb_update_icon(SB_FLOPPY | i, 0); + for (int i = 0; i < FDD_NUM; i++) { + ui_sb_update_icon(SB_FLOPPY | i, 0); + ui_sb_update_icon_write(SB_FLOPPY | i, 0); + } fdc_ctrl_reset(fdc); } @@ -706,6 +711,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); fdc->interrupt = -1; ui_sb_update_icon(SB_FLOPPY | 0, 0); + ui_sb_update_icon_write(SB_FLOPPY | 0, 0); fdc_ctrl_reset(fdc); } if (!fdd_get_flags(0)) @@ -1502,6 +1508,7 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) fdc->res[10] = fdc->params[4]; fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n", fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]); ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); + ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); fdc->paramstogo = 7; dma_set_drq(fdc->dma_ch, 0); } @@ -1545,8 +1552,10 @@ fdc_callback(void *priv) case -5: /*Reset in power down mode */ fdc->perp &= 0xfc; - for (uint8_t i = 0; i < FDD_NUM; i++) + for (uint8_t i = 0; i < FDD_NUM; i++) { ui_sb_update_icon(SB_FLOPPY | i, 0); + ui_sb_update_icon_write(SB_FLOPPY | i, 0); + } fdc_ctrl_reset(fdc); @@ -1694,7 +1703,10 @@ fdc_callback(void *priv) fdc->sector++; else if (fdc->params[5] == 0) fdc->sector++; - ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + if (fdc->interrupt == 0x05 || fdc->interrupt == 0x09) + ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + else + ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); switch (fdc->interrupt) { case 5: case 9: @@ -1885,6 +1897,7 @@ fdc_error(fdc_t *fdc, int st5, int st6) break; } ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); + ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); fdc->paramstogo = 7; } @@ -2333,8 +2346,10 @@ fdc_reset(void *priv) current_drive = 0; - for (uint8_t i = 0; i < FDD_NUM; i++) + for (uint8_t i = 0; i < FDD_NUM; i++) { ui_sb_update_icon(SB_FLOPPY | i, 0); + ui_sb_update_icon_write(SB_FLOPPY | i, 0); + } fdc->power_down = 0; } diff --git a/src/qt/icons/write_active.ico b/src/qt/icons/write_active.ico index d1ebdb22498d6dbdfeae87c7d21969948c5cc868..9cbf6e74b659ca410b87ec4501534d187c76f82f 100644 GIT binary patch literal 6950 zcmeI%zfTlF6u|L!7nE!Gl^~%YdZ7|*Os1kE6o!V9o@!#re*m>1#DeDam{?F>O=$Nb&r>Iqq)x6-AkJ-JMcW-cK_Y`T!h|JCkr6pgUi@am6-R>QK zZi$SKicC)Sj^95M=}d@BPxp>nT>tWg$ZHOxiMMFbPL$qvbyTByX$dO z>grXUfjR?EHv`Q|sb-|p z=+9$JkHb>WW5Zn3dvylt4BVQ5%I&@EUcaa^f5rTEWp0RT>+}6-zij_Pe)`jL+1_mb z+5lc3zxw#8XJCs5kw3>X$%9Hfr^G9H8-wSR%lB)ldhgohxcB@seBUl->s6hBIs;E2 z16O9zc+lvTL3Oj-BbpC5j`_3l`D^VD8vai^<>$rz&y2Thc|GL)@NRLRjh{MW+rQ6# zyyHF_eMJ}1U}=-1!^1=I?zw#Z{zHy@tDOJ#=7TIQek#9#k``&TTJa&7nwpZCnHiaz zo0IwZd0ALkkd%@vEiK8)%8IP5t;zcOx@>H0NX}U{H#cQ_ds}vPc4TjFPgGU*_xI)C z;6OT^PU+jsLp_p&%4-L=qA*6o$wbwPney6$VEHlc6v;BDjPMg~1U4CuArLj`$J@ z8480VzF0zr!r-6-dd_80)&@r;AR$9xa70oP6b45mDIr5)a75w~G86_!Br_pHVQ|n8 zu|yPF7Gv#*q$gx342~Fxgbanj5rdPEVQ@4Utb`1O!4U(PkfAU*2%cCX8xe(-#aYKd zCuArLju`xe428iFe-H^73WFp5ND?v>4pziM9TWx!Cx|6RC9)Aw@b8X=i;0DLC=3o7 zAQtMOFgR$GSg41>;GiR7p&kl@gU;!KdMFGN6XQ3^*q{tgo$`MvrHuXSy3t;#_Ir9+ VDs{uC9`~NSI+x$!e$H_I+D{z$j}HI< literal 6950 zcmeI$zfTlF6u|L!czRdyBSAtz^g<=rm`p`yC=3lHJ=MgL{{U)3hy~5-F|nY&n$qHx zmzYoyLnj5Xx=8W-zFqEa!9zu(hOo2w?2ox+=IxtfXZJ)J(vUEugIs^AQ0~3`}O~gdw!Jt&{CUSS`8-sE+{u{2hdhPZ8m<+U-Gj1W~n%jtZtb>;r z%wtTCqf*afqg>Q`bq4ATjLksh_Fn8>KdCZ*#r$?z{2DW(+`F%W-{85SLlz1iYVECMJ`F>4R`L2C=Oh@(mc9E2NRcGLSXW(*L z8z!NA&KOO9w?B^gv-0<42gCON`%e7C_ygP;c|W{a+-Kvb&e#s_vv0@VXQPp_t7x!j zlZvCGBk}&ZeEj@XdcIwR^6B{-Szdlu+>@KlrnKAb;H0$mZsz83romQ z7#ws!&$(EXwZRbyNXSqa9Fdd+g~1U?O2|+c9Fe$$428iF$xO&l7#uW2ED?nki?Mb@ z(i1Wi21g7;LWaWNh`~w7FgO|vRzilt;D`ZC$WRy@1WzoHjfldE#aYKdCuArLju`xe z428iFUx97o|CQn;m%5wUz>sn>0_B$rNQB-$(PoAF3 LuW&zSIDhUNEg`@d diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 0bbeb2af5..d575717a0 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -146,7 +146,7 @@ if(FLUIDSYNTH) pkg_check_modules(FLUIDSYNTH REQUIRED IMPORTED_TARGET fluidsynth) target_link_libraries(86Box PkgConfig::FLUIDSYNTH) if(STATIC_BUILD) - target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp -lgomp) + target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp) if(WIN32) add_compile_definitions(FLUIDSYNTH_NOT_A_DLL) From c23f33b65e9cf64239c2bd3ddb3032e371ba01fd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 22 Apr 2025 22:12:15 +0600 Subject: [PATCH 0786/1190] Fix SDL compiles --- src/unix/unix.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/unix/unix.c b/src/unix/unix.c index 8e44cc26a..2e92a90d3 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -471,6 +471,12 @@ ui_sb_update_icon(UNUSED(int tag), UNUSED(int active)) /* No-op. */ } +void +ui_sb_update_icon_write(UNUSED(int tag), UNUSED(int active)) +{ + /* No-op. */ +} + void plat_delay_ms(uint32_t count) { From e1cdf1b288aeffd759112e7bdd21a8c7206b9a27 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 22 Apr 2025 22:31:58 +0600 Subject: [PATCH 0787/1190] 20x20 icon made consistent with other sizes --- src/qt/icons/write_active.ico | Bin 6950 -> 6950 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/qt/icons/write_active.ico b/src/qt/icons/write_active.ico index 9cbf6e74b659ca410b87ec4501534d187c76f82f..babf8c86c0f94585cf9e00cd60d17c682fcf7c34 100644 GIT binary patch delta 155 xcmZ2xw#;lpo@6~QI|Bsp^1%Up#MnWAnVp??a)6}VWNE40lNF?RCts5a005JK4IBUf delta 171 ycmZ2xw#;lpo@D(Kb_NLG<%0wIh_Qo!I6FJC#ZRDsce0?=(a8!@ypyj<1poj5RvMH5 From 592e5c6a79e6f700e7e9de6036450d28c2955871 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 22 Apr 2025 21:10:06 +0200 Subject: [PATCH 0788/1190] Cirrus Logic: Implement proper VLB addressing, closes #5337. --- src/video/vid_cl54xx.c | 95 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 21d9b21d8..b60f9bdca 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -260,6 +260,8 @@ typedef struct gd54xx_t { uint8_t pos_regs[8]; + uint32_t vlb_lfb_base; + uint32_t lfb_base; uint32_t vgablt_base; @@ -1750,7 +1752,8 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) } else mem_mapping_disable(&gd54xx->mmio_mapping); } else { - if ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) || (!gd54xx->pci && !gd54xx->vlb)) { + if ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) || + (!gd54xx->pci && !gd54xx->vlb)) { if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) { base = (svga->seqregs[0x07] & 0xf0) << 16; size = 1 * 1024 * 1024; @@ -1770,7 +1773,10 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) else size = 4 * 1024 * 1024; } else { /*VLB/ISA/MCA*/ - base = 128 * 1024 * 1024; + if (gd54xx->vlb_lfb_base != 0x00000000) + base = gd54xx->vlb_lfb_base; + else + base = 128 * 1024 * 1024; if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) size = 16 * 1024 * 1024; else @@ -4224,6 +4230,12 @@ gd54xx_init(const device_t *info) gd54xx->id = id; + if (gd54xx->vlb && ((gd54xx->id == CIRRUS_ID_CLGD5430) || + (gd54xx->id == CIRRUS_ID_CLGD5434) || + (gd54xx->id == CIRRUS_ID_CLGD5434_4) || + (gd54xx->id == CIRRUS_ID_CLGD5440))) + gd54xx->vlb_lfb_base = device_get_config_int("lfb_base") << 20; + switch (id) { case CIRRUS_ID_CLGD5401: romfn = BIOS_GD5401_PATH; @@ -4777,6 +4789,41 @@ static const device_config_t gd5429_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t gd5430_vlb_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "lfb_base", + .description = "Linear framebuffer base", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "32 MB", .value = 32 }, + { .description = "64 MB", .value = 64 }, + { .description = "2048 MB", .value = 2048 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t gd5440_onboard_config[] = { { .name = "memory", @@ -4816,6 +4863,42 @@ static const device_config_t gd5434_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t gd5434_vlb_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 4, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "4 MB", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "lfb_base", + .description = "Linear framebuffer base", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "32 MB", .value = 32 }, + { .description = "64 MB", .value = 64 }, + { .description = "2048 MB", .value = 2048 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t gd5434_onboard_config[] = { { .name = "memory", @@ -5150,7 +5233,7 @@ const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device = { .available = gd5430_diamond_a8_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5429_config + .config = gd5430_vlb_config }; const device_t gd5430_vlb_device = { @@ -5164,7 +5247,7 @@ const device_t gd5430_vlb_device = { .available = gd5430_orchid_vlb_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5429_config + .config = gd5430_vlb_config }; const device_t gd5430_onboard_vlb_device = { @@ -5178,7 +5261,7 @@ const device_t gd5430_onboard_vlb_device = { .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5429_config + .config = gd5430_vlb_config }; const device_t gd5430_pci_device = { @@ -5263,7 +5346,7 @@ const device_t gd5434_vlb_device = { .available = gd5430_orchid_vlb_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5434_config + .config = gd5434_vlb_config }; const device_t gd5434_pci_device = { From 14ef3b75ac810a9b65500ac61b6c108576c01033 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 22 Apr 2025 21:15:05 +0200 Subject: [PATCH 0789/1190] Vast fixes to the Mach8/32/8514/A compatible side (April 22nd 2025) 1. As tiring as it seems, XOR properly the passthrough bits for mode changes. Fixes everything tested as of now (Mach8/32). 2. Implemented separate destination and source GE pitch and offsets. Fixes Windows 3.1 mach8/32 drivers using devicebitmap enabled (or dmp=1). 3. Properly fixed high and true color patterns so that the aforementioned patterns are drawn correctly in various stuff. 4. Implemented in the best possible way the CRT offset (currently in on conjunction with the GE offset). 5. On ScanToX with bpp set to 24 and dpconfig 0x6211, optmize the SRC/CUR X-Y coordinates at the end of the blit. 6. For mode changes, don't call the mode change recalctimings function if we aren't in the appropriate bits of the respective ports. 7. Separate 8514/A compatible and Extended foreground/background selection implemented, fixes Windows 3.x ATI Ultra drivers from 1992 without hacks. 8. Clear the busy flags when needed without stalling the entire guests (but not the emulator itself) (Mach8/32). 9. The MMIO regs should be enabled only when the VGA aperture has reached a graphics mode (0xA000). This fixes NT 3.x mach drivers in true color mode and making Win3.1 drivers working without a hitch at the same time. 10. Actually implement the hardware 4bpp cursor properly on Mach32. 11. Cosmetic cleanups. --- src/include/86box/vid_8514a.h | 17 +- src/include/86box/vid_ati_mach8.h | 14 +- src/include/86box/vid_svga.h | 4 +- src/video/vid_8514a.c | 236 ++--- src/video/vid_ati_mach8.c | 1344 +++++++++++++++-------------- src/video/vid_svga.c | 6 +- 6 files changed, 803 insertions(+), 818 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 7694a028a..696b640bc 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -90,6 +90,7 @@ typedef struct ibm8514_t { uint16_t subsys_cntl; uint16_t setup_md; uint16_t advfunc_cntl; + uint16_t advfunc_cntl_old; uint16_t cur_y; uint16_t cur_x; int16_t destx; @@ -107,8 +108,10 @@ typedef struct ibm8514_t { uint16_t wrt_mask; uint16_t rd_mask; uint16_t color_cmp; - uint16_t bkgd_mix; - uint16_t frgd_mix; + uint8_t bkgd_mix; + uint8_t frgd_mix; + uint8_t bkgd_sel; + uint8_t frgd_sel; uint16_t multifunc_cntl; uint16_t multifunc[16]; uint16_t clip_right; @@ -159,6 +162,14 @@ typedef struct ibm8514_t { int ydir; int linedraw; uint32_t ge_offset; + uint32_t src_ge_offset; + uint32_t dst_ge_offset; + uint16_t src_pitch; + uint16_t dst_pitch; + int64_t cur_x_24bpp; + int64_t cur_y_24bpp; + int64_t dest_x_24bpp; + int64_t dest_y_24bpp; } accel; uint16_t test; @@ -240,6 +251,8 @@ typedef struct ibm8514_t { uint32_t vram_amount; int vram_512k_8514; int vendor_mode; + int _8514on; + int _8514crt; PALETTE _8514pal; latch8514_t latch; diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index 8ed1dbc74..d5e80d0c8 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -77,8 +77,9 @@ typedef struct mach_t { uint8_t overscan_g_col_24; uint8_t overscan_r_col_24; uint16_t fifo_test_data[17]; - int port_len; - int crt_resolution; + uint8_t old_on1; + uint8_t old_on2; + int crt_resolution; struct { uint8_t line_idx; @@ -99,12 +100,13 @@ 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; uint16_t crt_pitch; uint16_t ge_pitch; + uint16_t src_pitch; + uint16_t dst_pitch; uint16_t dest_cmp_fn; uint16_t dp_config; uint16_t ext_ge_config; @@ -158,14 +160,18 @@ typedef struct mach_t { int src_stepx; uint8_t mono_pattern_normal[16]; uint8_t color_pattern[32]; + uint16_t color_pattern_hicol[8]; int mono_pattern[8][8]; - uint32_t ge_offset; + uint32_t src_ge_offset; + uint32_t dst_ge_offset; uint32_t crt_offset; uint32_t patt_len_reg; int poly_fill; uint16_t dst_clr_cmp_mask; int clip_overrun; int color_pattern_idx; + int64_t src_x_scan; + int64_t src_y_scan; } accel; atomic_int force_busy; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 068774eac..932aa718a 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -171,11 +171,11 @@ typedef struct svga_t { latch_t latch; pc_timer_t timer; - pc_timer_t timer8514; + pc_timer_t timer_8514; pc_timer_t timer_xga; double clock; - double clock8514; + double clock_8514; double clock_xga; double multiplier; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 8925f01da..533ec8fa9 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -124,7 +124,7 @@ CLAMP(int16_t in, int16_t min, int16_t max) #define MIX(mixmode, dest_dat, src_dat) \ { \ - switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ + switch ((mixmode) ? dev->accel.frgd_mix : dev->accel.bkgd_mix) { \ case 0x00: \ dest_dat = ~dest_dat; \ break; \ @@ -268,8 +268,8 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in uint32_t monoxfer = 0xffffffff; int pixcnt = 0; int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; - int frgd_mix = (dev->accel.frgd_mix >> 5) & 3; - int bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; + int frgd_mix = dev->accel.frgd_sel; + int bkgd_mix = dev->accel.bkgd_sel; int cmd = dev->accel.cmd >> 13; if (!dev->accel.cmd_back) { @@ -351,13 +351,12 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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); + WRITE8(port - 1, dev->htotal, val); ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); svga_recalctimings(svga); break; @@ -379,10 +378,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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 { @@ -392,12 +387,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x12e9: /*In preparation to switch from VGA to 8514/A mode*/ if (len == 1) { - WRITE8(port, dev->v_total_reg, val); + WRITE8(port, dev->v_total_reg, val >> 8); 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); } @@ -408,7 +399,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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); @@ -419,9 +409,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x16e9: /*In preparation to switch from VGA to 8514/A mode*/ if (len == 1) { - WRITE8(port, dev->v_disp, val); + WRITE8(port, dev->v_disp, val >> 8); 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); @@ -433,10 +422,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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); @@ -447,7 +432,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x1ae9: /*In preparation to switch from VGA to 8514/A mode*/ if (len == 1) { - WRITE8(port, dev->v_sync_start, val); + WRITE8(port, dev->v_sync_start, val >> 8); dev->v_sync_start &= 0x1fff; dev->v_syncstart = dev->v_sync_start + 1; if (dev->interlace) @@ -639,11 +624,15 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0xb6e8: - dev->accel.bkgd_mix = val & 0xff; + dev->accel.bkgd_mix = val & 0x1f; + dev->accel.bkgd_sel = (val >> 5) & 3; + ibm8514_log("Background Mix reg=%02x.\n", val); break; case 0xbae8: - dev->accel.frgd_mix = val & 0xff; + dev->accel.frgd_mix = val & 0x1f; + dev->accel.frgd_sel = (val >> 5) & 3; + ibm8514_log("Foreground Mix reg=%02x.\n", val); break; case 0xbee8: @@ -667,7 +656,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if ((dev->accel.multifunc_cntl >> 12) == 4) dev->accel.clip_right = dev->accel.multifunc[4] & 0x7ff; - } break; @@ -821,8 +809,22 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) if (dev->fifo_idx > 0) dev->fifo_idx--; - if (dev->force_busy) + if (dev->force_busy) { temp |= 0x0200; /*Hardware busy*/ + switch (dev->accel.cmd >> 13) { + case 2: + case 3: + case 4: + case 6: + if (dev->accel.sy < 0) + dev->force_busy = 0; + break; + default: + if (!dev->accel.sy) + dev->force_busy = 0; + break; + } + } if (dev->data_available) { temp |= 0x0100; /*Read Data available*/ @@ -1066,8 +1068,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat rd_mask_polygon &= 0xff; } - frgd_mix = (dev->accel.frgd_mix >> 5) & 3; - bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; + frgd_mix = dev->accel.frgd_sel; + bkgd_mix = dev->accel.bkgd_sel; if (cpu_input) { if ((dev->accel.cmd & 0x02) || (pixcntl == 2)) { @@ -1821,12 +1823,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); if (cmd == 4) dev->accel.cmd |= 0x02; @@ -2030,12 +2027,7 @@ skip_vector_rect_write: break; } - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; dev->accel.x_count = 0; @@ -2194,12 +2186,7 @@ skip_nibble_rect_write: else dev->accel.cy--; - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; dev->accel.x_count = 0; @@ -2285,12 +2272,7 @@ skip_nibble_rect_write: else dev->accel.cy--; - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; @@ -2367,12 +2349,7 @@ skip_nibble_rect_write: else dev->accel.cy--; - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; @@ -2482,12 +2459,7 @@ skip_nibble_rect_write: else dev->accel.cy--; - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; @@ -2512,8 +2484,6 @@ skip_nibble_rect_write: switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; - if (!bkgd_mix && (dev->accel.cmd & 0x40) && ((dev->accel.frgd_mix & 0x1f) == 7) && ((dev->accel.bkgd_mix & 0x1f) == 3) && !dev->bpp && (bkgd_color == 0x00)) /*For some reason, the September 1992 Mach8/32 drivers for Win3.x don't set the background colors properly.*/ - src_dat = frgd_color; break; case 1: src_dat = frgd_color; @@ -2570,12 +2540,7 @@ skip_nibble_rect_write: else dev->accel.cy--; - if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else if (dev->bpp) - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; if (dev->accel.sy < 0) { @@ -2870,16 +2835,8 @@ skip_nibble_rect_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; - 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); - } 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); - } 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.src = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch); dev->accel.fill_state = 0; if (ibm8514_cpu_src(svga)) { @@ -3051,16 +3008,8 @@ skip_nibble_bitblt_write: 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); - } 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); - } 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.src = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch); dev->accel.sy--; dev->accel.x_count = 0; @@ -3156,16 +3105,8 @@ skip_nibble_bitblt_write: 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); - } 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); - } 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.src = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch); dev->accel.sy--; @@ -3252,16 +3193,9 @@ skip_nibble_bitblt_write: 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); - } 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); - } 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.src = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch); + dev->accel.sy--; if (dev->accel.sy < 0) { @@ -3282,29 +3216,14 @@ skip_nibble_bitblt_write: cx = (int64_t) dev->accel.cx; dx = (int64_t) dev->accel.dx; + dev->accel.src = dev->accel.src_ge_offset + (dev->accel.cy * dev->accel.src_pitch); + dev->accel.dest = dev->accel.dst_ge_offset + (dev->accel.dy * dev->accel.dst_pitch); + 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))) { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = 0; - break; - case 3: - READ(dev->accel.src + cx, src_dat); - break; - - default: - break; - } - READ(dev->accel.src + cx, src_dat); READ(dev->accel.dest + dx, dest_dat); old_dest_dat = dest_dat; @@ -3411,16 +3330,9 @@ skip_nibble_bitblt_write: 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); - } 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); - } 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.src = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); + dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch); + dev->accel.sy--; if (dev->accel.sy < 0) { @@ -3804,7 +3716,7 @@ ibm8514_poll(void *priv) if ((svga->cgastat & 8) && ((dev->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) svga->cgastat &= ~8; svga->vslines++; - if (dev->displine > 1500) + if (dev->displine > 2000) dev->displine = 0; } else { timer_advance_u64(&svga->timer, dev->dispontime); @@ -3871,9 +3783,9 @@ ibm8514_poll(void *priv) svga->vslines = 0; if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = dev->ma_latch + (dev->rowoffset << 1); + dev->ma = dev->maback = (dev->rowoffset << 1); else - dev->ma = dev->maback = dev->ma_latch; + dev->ma = dev->maback = 0; dev->ma = (dev->ma << 2); dev->maback = (dev->maback << 2); @@ -3904,26 +3816,43 @@ ibm8514_recalctimings(svga_t *svga) ati8514_recalctimings(svga); } else { if (dev->on) { + dev->hdisp = (dev->hdisped + 1) << 3; dev->h_total = dev->htotal + 1; + + if (dev->h_total == 1) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/ + dev->h_total = 0x9e; + + dev->vdisp = (dev->v_disp + 1) >> 1; + if ((dev->vdisp == 478) || (dev->vdisp == 766)) + 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; + dev->rowcount = !!(dev->disp_cntl & 0x08); - if (dev->accel.advfunc_cntl & 0x01) { + if ((dev->hdisp != 640) && (dev->hdisp != 1024)) { if (dev->accel.advfunc_cntl & 0x04) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; + dev->hdisp = 1024; + dev->vdisp = 768; } else { - dev->h_disp = 640; - dev->dispend = 480; + dev->hdisp = 640; + dev->vdisp = 480; } - } else { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; } + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + if (dev->accel.advfunc_cntl & 0x04) - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; else - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; if ((dev->dispend == 478) || (dev->dispend == 766)) dev->dispend += 2; @@ -4026,6 +3955,7 @@ ibm8514_init(const device_t *info) dev->map8 = dev->pallook; dev->local = 0; dev->accel_bpp = 8; + dev->on = 0; dev->type = info->flags; dev->bpp = 0; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 9f92ebde1..3bcde5b0c 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -15,6 +15,7 @@ * * Copyright 2022-2024 TheCollector1995. */ +#include #include #include #include @@ -142,10 +143,10 @@ mach_log(const char *fmt, ...) } \ } else if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { \ if (dev->bpp) \ - temp = vram_w[((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ + temp = vram_w[(mach->accel.dst_ge_offset + ((dev->accel.cy) * (mach->accel.dst_pitch)) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ else { \ - temp = dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & dev->vram_mask]; \ - temp |= (dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + temp = dev->vram[(mach->accel.dst_ge_offset + ((dev->accel.cy) * (mach->accel.dst_pitch)) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[(mach->accel.dst_ge_offset + ((dev->accel.cy) * (mach->accel.dst_pitch)) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } \ } @@ -160,7 +161,7 @@ mach_log(const char *fmt, ...) #define MIX(mixmode, dest_dat, src_dat) \ { \ - switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ + switch ((mixmode) ? dev->accel.frgd_mix : dev->accel.bkgd_mix) { \ case 0x00: \ dest_dat = ~dest_dat; \ break; \ @@ -334,7 +335,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } - mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i, dpconfig = %04x, cur_x = %d, cur_y = %d.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config, dev->accel.cur_x, dev->accel.cur_y); + mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i, dpconfig = %04x, cur_x = %d, cur_y = %d, cl = %d, cr = %d, ct = %d, cb = %d, accel_bpp = %d, pitch = %d, hicolbpp = %d, pattlen = %d.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config, dev->accel.cur_x, dev->accel.cur_y, clip_l, clip_r, clip_t, clip_b, dev->accel_bpp, dev->pitch, dev->bpp, mach->accel.patt_len); switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ @@ -368,6 +369,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { + mach_log("Extended Bresenham Write pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -375,6 +377,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { + mach_log("Extended Bresenham Read pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -423,11 +426,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 3: - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, mix); mix = (mix & rd_mask) == rd_mask; break; @@ -439,6 +438,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 |= INT_GE_BSY; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = bkgd_color; @@ -453,19 +453,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); - } else { - READ((mach->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, src_dat); if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: @@ -473,22 +470,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); if (poly_src) mach->accel.poly_fill = !mach->accel.poly_fill; } if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } + READ(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); switch (compare_mode) { case 1: @@ -528,18 +517,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config & 0x10) { if (mach->accel.linedraw_opt & 0x04) { if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } } else { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } } } @@ -570,10 +551,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx > mach->accel.patt_len) mach->accel.color_pattern_idx = 0; @@ -658,11 +636,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 3: - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, mix); mix = (mix & rd_mask) == rd_mask; break; @@ -689,20 +663,17 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, src_dat); if (mono_src == 3) { src_dat = (src_dat & rd_mask) == rd_mask; } } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: @@ -710,22 +681,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); if (poly_src) mach->accel.poly_fill = !mach->accel.poly_fill; } if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } + READ(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); switch (compare_mode) { case 1: @@ -765,18 +728,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config & 0x10) { if (mach->accel.linedraw_opt & 0x04) { if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } } else { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } } } @@ -807,10 +762,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx > mach->accel.patt_len) mach->accel.color_pattern_idx = 0; @@ -869,7 +821,6 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dest_x_start >= 0x600) mach->accel.dx_start |= ~0x5ff; - mach_log("DXStart=%d, CURX=%d.\n", mach->accel.dx_start, dev->accel.dx); mach->accel.dx_end = mach->accel.dest_x_end; if (mach->accel.dest_x_end >= 0x600) mach->accel.dx_end |= ~0x5ff; @@ -916,10 +867,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } dev->accel.sy = 0; - if (dev->bpp) - dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); - else - dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); mach->accel.src_stepx = 0; /*Source Width*/ @@ -961,15 +909,12 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.dp_config, mach->accel.src_width & 1); } mach->accel.sx = 0; - if (mach->accel.patt_data_idx < 16) + if (mach->accel.patt_data_idx < 0x10) mach->accel.color_pattern_idx = mach->accel.patt_idx; else mach->accel.color_pattern_idx = 0; - if (dev->bpp) - dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); if (mono_src == 1) { if (mach->accel.mono_pattern_enable || mach->accel.block_write_mono_pattern_enable) { @@ -982,7 +927,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mono_dat1 |= (mach->accel.mono_pattern_normal[6] << 16); mono_dat1 |= (mach->accel.mono_pattern_normal[7] << 24); - mach_log("MonoData0=%x, MonoData1=%x.\n", mono_dat0, mono_dat1); + mach_log("MonoData0=%x, MonoData1=%x, enable mono pattern=%x, dpconfig=%04x.\n", mono_dat0, mono_dat1, mach->accel.mono_pattern_enable, mach->accel.dp_config); for (uint8_t y = 0; y < 8; y++) { for (uint8_t x = 0; x < 8; x++) { uint32_t temp = (y & 4) ? mono_dat1 : mono_dat0; @@ -994,6 +939,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { + mach_log("Non-Conforming BitBLT Write pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -1001,6 +947,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { + mach_log("Non-Conforming BitBLT Read pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -1140,9 +1087,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: @@ -1151,7 +1099,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && !mach->accel.mono_pattern_enable) { if (dev->accel.sy & 1) { - READ(dev->accel.dest + dev->accel.dx - dev->pitch, dest_dat); + READ(dev->accel.dest + dev->accel.dx - mach->accel.dst_pitch, dest_dat); } else { READ(dev->accel.dest + dev->accel.dx, dest_dat); } @@ -1197,7 +1145,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config & 0x10) { if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && !mach->accel.mono_pattern_enable) { if (dev->accel.sy & 1) { - WRITE(dev->accel.dest + dev->accel.dx - dev->pitch, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx - mach->accel.dst_pitch, dest_dat); } else { WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } @@ -1213,11 +1161,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (mach->accel.dp_config == 0x2071 || (mach->accel.dp_config == 0x2011)) - mach_log("FontBlit: SX=%d, C(%d,%d), SRCWidth=%d, frgdmix=%d, bkgdmix=%d, rdmask=%04x, D(%d,%d), geoffset=%x, addr=%08x,.\n", + if (mach->accel.dp_config == 0x2071) + mach_log("FontBlit: SX=%d, C(%d,%d), SRCWidth=%d, frgdmix=%d, bkgdmix=%d, rdmask=%04x, D(%d,%d), geoffset=%x, addr=%08x, 8bppdata=%02x, 16bppdata=%04x, vgabase=%06x.\n", mach->accel.sx, dev->accel.cx, dev->accel.cy, mach->accel.src_width, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, rd_mask, dev->accel.dx, dev->accel.dy, dev->accel.ge_offset, - (dev->accel.src + dev->accel.cx) & dev->vram_mask); + (dev->accel.src + dev->accel.cx) & dev->vram_mask, dev->vram[(dev->accel.src + dev->accel.cx) & dev->vram_mask], vram_w[(dev->accel.src + dev->accel.cx) & (dev->vram_mask >> 1)], svga->mapping.base); if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) { dev->accel.cx += mach->accel.src_stepx; @@ -1230,17 +1178,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.cx -= mach->accel.src_width; dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); - if (dev->bpp) - dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - else - dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); } } - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if ((mono_src == 1) && !mach->accel.mono_pattern_enable && !mach->accel.block_write_mono_pattern_enable && (frgd_sel == 5) && (dev->accel_bpp == 24)) { if (mach->accel.color_pattern_idx > 2) @@ -1263,14 +1205,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sy++; mach->accel.poly_fill = 0; - if (mach->accel.dp_config & 0x02) - dev->accel.dest = (dev->accel.dy * dev->pitch); - else { - if (dev->bpp) - dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); - else - dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); - } + dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); if (dev->accel.sy >= mach->accel.height) { if (cpu_input) { @@ -1321,7 +1256,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { - mach_log("Write PIXTRANS.\n"); + mach_log("Direct Linedraw Write pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -1329,7 +1264,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { - mach_log("Read PIXTRANS.\n"); + mach_log("Direct Linedraw Read pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -1384,20 +1319,17 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 src_dat = 0; break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: break; } - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); switch (compare_mode) { case 1: @@ -1434,11 +1366,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } else mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); @@ -1459,10 +1387,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx > mach->accel.patt_len) mach->accel.color_pattern_idx = 0; @@ -1508,11 +1433,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); - } + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); if (poly_src) mach->accel.poly_fill ^= 1; } @@ -1535,24 +1456,17 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: break; } - if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } else { - READ(((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); switch (compare_mode) { case 1: @@ -1594,26 +1508,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { if (mach->accel.linedraw_opt & 0x04) { if (dev->accel.sx < mach->accel.width) { - if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } else { - WRITE(((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } else { - if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } else { - WRITE(((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } } else @@ -1635,10 +1533,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx > mach->accel.patt_len) mach->accel.color_pattern_idx = 0; @@ -1690,20 +1585,18 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: break; } - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + switch (compare_mode) { case 1: compare = 1; @@ -1740,11 +1633,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } else mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); @@ -1765,10 +1654,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx > mach->accel.patt_len) mach->accel.color_pattern_idx = 0; @@ -1831,24 +1717,17 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: break; } - if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } else { - READ(((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); switch (compare_mode) { case 1: @@ -1888,26 +1767,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { if (mach->accel.linedraw_opt & 0x04) { if (dev->accel.sx < mach->accel.width) { - if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } else { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } else { - if (mach->accel.linedraw_opt & 0x02) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } else { - WRITE(((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } } else @@ -1929,10 +1792,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx > mach->accel.patt_len) mach->accel.color_pattern_idx = 0; @@ -2010,11 +1870,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sy = 0; } - if (dev->bpp) - dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); - else - dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch)); - + dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); mach->accel.src_stepx = 0; /*Source Width*/ @@ -2047,33 +1903,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } mach->accel.sx = 0; - if (dev->bpp) - dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); - else - dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); + dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); - if ((dev->accel_bpp >= 24) && (frgd_sel == 5)) { - if (mach->accel.patt_len == 0x17) - mach->accel.color_pattern_idx = 0; - - dev->accel.x1 = dev->accel.dx + mach->accel.width; - if (dev->accel.x1 == dev->pitch) - dev->accel.x2 = mach->accel.width & 1; - else if ((dev->accel.x1 == mach->accel.width) && (dev->accel.dy & 1) && !dev->accel.y1 && dev->accel.x2) { - if (mach->accel.patt_len == 0x17) - mach->accel.color_pattern_idx = 3; - - dev->accel.x3 = 1; - } else - dev->accel.x3 = 0; - } - dev->accel.y1 = 0; - - mach_log("ScanToX: Parameters=%04x: xbit=%d, ybit=%d, widthbit=%d, DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, srcwidth=%d, height=%d, frmix=%02x.\n", - mach->accel.dp_config, dev->accel.dx & 1, dev->accel.dy & 1, mach->accel.width & 1, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.src_width, dev->accel.sy, dev->accel.frgd_mix & 0x1f); + mach_log("ScanToX: Parameters=%04x: xbit=%d, ybit=%d, widthbit=%d, DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, srcwidth=%d, height=%d, frmix=%02x, colpatidx=%d, srcpitch=%d, dstpitch=%d, scantox=%d.\n", + mach->accel.dp_config, dev->accel.dx & 1, dev->accel.dy & 1, mach->accel.width & 1, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.src_width, dev->accel.sy, dev->accel.frgd_mix & 0x1f, mach->accel.color_pattern_idx, mach->accel.src_pitch, mach->accel.dst_pitch, mach->accel.scan_to_x); if (!dev->accel.cmd_back) { if (mach_pixel_write(mach)) { + mach_log("Scan To X Write pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -2081,6 +1918,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->data_available2 = 0; return; } else if (mach_pixel_read(mach)) { + mach_log("Scan To X Read pixtrans.\n"); dev->force_busy = 1; dev->force_busy2 = 1; mach->force_busy = 1; @@ -2091,6 +1929,110 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } + if ((dev->accel_bpp == 24) && (mach->accel.dp_config == 0x6211)) { + int64_t cx; + int64_t cy; + + cx = mach->accel.src_x_scan; + cy = mach->accel.src_y_scan; + + if (mach->accel.src_stepx == -1) { + if (cx > 0) + cx--; + } + + dev->accel.src = mach->accel.src_ge_offset + (cy * mach->accel.src_pitch); + + while (1) { + mix = 1; + + if ((dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= INT_GE_BSY; + READ(dev->accel.src + cx, src_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; + + default: + break; + } + + if (!compare) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + + cx += mach->accel.src_stepx; + mach->accel.sx++; + if (mach->accel.sx >= mach->accel.src_width) { + mach->accel.sx = 0; + cx = mach->accel.src_x_scan; + if (mach->accel.src_stepx == -1) { + if (cx > 0) + cx--; + } + + cy += (mach->accel.src_y_dir ? 1 : -1); + dev->accel.src = mach->accel.src_ge_offset + (cy * mach->accel.src_pitch); + } + + dev->accel.dx += mach->accel.stepx; + dev->accel.sx++; + if (dev->accel.sx >= mach->accel.width) { + dev->accel.sx = 0; + dev->accel.dy += mach->accel.stepy; + dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); + + if (mach->accel.line_idx == 2) { + 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->fifo_idx = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + dev->accel.cmd_back = 1; + dev->accel.cur_x = dev->accel.dx; + dev->accel.cur_y = dev->accel.dy; + mach->accel.src_x_scan = cx; + mach->accel.src_y_scan = cy; + return; + } + } + return; + } + if (mono_src == 1) { count = mach->accel.width; mix_dat = mach->accel.mono_pattern_normal[0]; @@ -2128,7 +2070,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 3: - READ(dev->accel.src + (dev->accel.cx), mix); + READ(dev->accel.src + dev->accel.cx, mix); mix = (mix & rd_mask) == rd_mask; break; @@ -2161,9 +2103,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 5: - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; if (dev->bpp) - src_dat |= (mach->accel.color_pattern[mach->accel.color_pattern_idx + 1] << 8); + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: @@ -2209,7 +2152,6 @@ 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); } } @@ -2228,40 +2170,21 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.cx -= mach->accel.src_width; dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); - if (dev->bpp) - dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); - else - dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); + dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); } - mach_log("ColorIdx=%d, data=%02x, DestX=%d, DestY=%d.\n", mach->accel.color_pattern_idx, mach->accel.color_pattern[mach->accel.color_pattern_idx], dev->accel.dx, dev->accel.dy & 1); - if (dev->bpp) - mach->accel.color_pattern_idx += 2; - else - mach->accel.color_pattern_idx++; + mach->accel.color_pattern_idx++; - if ((dev->accel_bpp >= 24) && (frgd_sel == 5) && (mach->accel.patt_len == 0x17)) { - if (dev->accel.x3) { - if (mach->accel.color_pattern_idx == 9) - mach->accel.color_pattern_idx = 3; - } else { - if (mach->accel.color_pattern_idx == 6) - mach->accel.color_pattern_idx = 0; - } - } else { - if (mach->accel.color_pattern_idx > mach->accel.patt_len) - mach->accel.color_pattern_idx = 0; - } + if (mach->accel.color_pattern_idx > mach->accel.patt_len) + mach->accel.color_pattern_idx = 0; dev->accel.dx += mach->accel.stepx; dev->accel.sx++; if (dev->accel.sx >= mach->accel.width) { dev->accel.sx = 0; dev->accel.dy += mach->accel.stepy; - if (dev->bpp) - dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); - else - dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); + if (mach->accel.line_idx == 2) { mach->accel.line_array[0] = dev->accel.dx; mach->accel.line_array[4] = dev->accel.dx; @@ -2348,13 +2271,12 @@ mach_out(uint16_t addr, uint8_t val, void *priv) if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; - if (((dev->disp_cntl & 0x60) == 0x20) && ATI_MACH32) { - if ((addr >= 0x3c6) && (addr <= 0x3c9)) { - mach_log("VGA DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", - addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); - } else if ((addr >= 0x2ea) && (addr <= 0x2ed)) - mach_log("8514/A DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", - addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); + if ((addr >= 0x3c6) && (addr <= 0x3c9)) { + mach_log("VGA DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", + addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); + } else if ((addr >= 0x2ea) && (addr <= 0x2ed)) { + mach_log("8514/A DAC write regs=%03x, on=%d, display control=%02x, on1=%x, clocksel=%02x.\n", + addr, dev->on, dev->disp_cntl & 0x60, dev->accel.advfunc_cntl & 0x01, mach->accel.clock_sel & 0x01); } switch (addr) { @@ -2364,7 +2286,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x1cf: old = mach->regs[mach->index]; mach->regs[mach->index] = val; - mach_log("ATI VGA write reg=%02x, val=%02x.\n", mach->index, val); + mach_log("ATI VGA write reg=%02x, val=%02x, old=%02x.\n", mach->index, val, old); switch (mach->index) { case 0xa3: if ((old ^ val) & 0x10) { @@ -2388,8 +2310,25 @@ mach_out(uint16_t addr, uint8_t val, void *priv) break; case 0xb0: if ((old ^ val) & 0x60) { - mach_log("ATI B0 bits 5-6: old=%02x, val=%02x.\n", old & 0x60, val & 0x60); - svga_recalctimings(svga); + if (dev->_8514crt) { + if (!(mach->accel.clock_sel & 0x01)) { + if ((val & 0x20) && !(old & 0x20)) { + dev->on = 1; + dev->vendor_mode = !!(ATI_MACH32); + mach_set_resolution(mach, svga); + mach32_updatemapping(mach, svga); + } else if (!(val & 0x20) && (old & 0x20)) { + dev->on = 0; + dev->vendor_mode = 0; + mach_set_resolution(mach, svga); + mach32_updatemapping(mach, svga); + } + } + } else + svga_recalctimings(svga); + + mach_log("ATI B0 bits 5-6: old=%02x, val=%02x, on=%d, bpp=%d, hires=%x, vgahires=%02x, base=%05x.\n", + old & 0x60, val & 0x60, dev->on, dev->accel_bpp, dev->accel.advfunc_cntl & 0x04, svga->gdcreg[5] & 0x60, svga->mapping.base); } break; case 0xae: @@ -2464,23 +2403,12 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); - mach_log("8514/A RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); - if (ATI_MACH32) { - if (mach->regs[0xb0] & 0x20) { /*ATI extended 8514/A mode.*/ - mach_log("Extended 8514/A mode.\n"); - dev->vendor_mode = 1; - dev->on |= 0x01; - mach_set_resolution(mach, svga); - mach32_updatemapping(mach, svga); - } - if (dev->on) - svga_out(addr, val, svga); - else { - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); - else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } + mach_log("8514/A Extended mode=%02x.\n", mach->regs[0xb0] & 0x20); + if (ATI_MACH32 && !dev->on) { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); } else svga_out(addr, val, svga); return; @@ -2491,23 +2419,12 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x3C9: rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); - mach_log("VGA RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); - if (ATI_MACH32) { - if (svga->attrregs[0x10] & 0x40) { - mach_log("VGA mode.\n"); - dev->vendor_mode = 0; - dev->on &= ~0x01; - mach_set_resolution(mach, svga); - mach32_updatemapping(mach, svga); - } - if (dev->on) - svga_out(addr, val, svga); - else { - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); - else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } + mach_log("VGA Extended mode=%02x.\n", mach->regs[0xb0] & 0x20); + if (ATI_MACH32 && !dev->on) { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); } else svga_out(addr, val, svga); return; @@ -2622,15 +2539,11 @@ mach_in(uint16_t addr, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); - if (ATI_MACH32) { - if (dev->on) - temp = svga_in(addr, svga); - else { - if (mach->pci_bus && !mach->ramdac_type) - temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); - else - temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } + if (ATI_MACH32 && !dev->on) { + if (mach->pci_bus && !mach->ramdac_type) + temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); + else + temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); } else temp = svga_in(addr, svga); break; @@ -2770,13 +2683,15 @@ static void mach_set_resolution(mach_t *mach, svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int ret = 0; - dev->hdisp = (dev->hdisped + 1) << 3; dev->h_total = dev->htotal + 1; if (dev->h_total == 1) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/ dev->h_total = 0x9e; + dev->hdisp = (dev->hdisped + 1) << 3; + dev->vdisp = (dev->v_disp + 1) >> 1; if ((dev->vdisp == 478) || (dev->vdisp == 598) || (dev->vdisp == 766) || (dev->vdisp == 1022)) dev->vdisp += 2; @@ -2789,70 +2704,53 @@ mach_set_resolution(mach_t *mach, svga_t *svga) if (dev->interlace) dev->v_syncstart >>= 1; - mach_log("Shadow set ATI=%x, shadow set 8514/A=%x, resolution h=%d, v=%d, vtotal=%d, vsyncstart=%d.\n", mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp, dev->v_total, dev->v_syncstart); - switch (mach->shadow_set & 0x03) { - case 0x00: /*Primary CRT Register set*/ - if (dev->on) { - if (mach->crt_resolution == 0x01) { - if (ATI_8514A_ULTRA) { + if ((mach->accel.clock_sel & 0x01) && !(mach->old_on2 & 0x01) && + !(dev->accel.advfunc_cntl & 0x01)) + ret = 2; + else if ((dev->accel.advfunc_cntl & 0x01) && !(mach->old_on1 & 0x01) && + !(mach->accel.clock_sel & 0x01)) + ret = 1; + else if ((!(dev->accel.advfunc_cntl & 0x01) && (mach->old_on1 & 0x01)) || + (!(mach->accel.clock_sel & 0x01) && (mach->old_on2 & 0x01))) + ret = 0; + + if (ret) { + if (ret == 2) + svga_recalctimings(svga); + else { + switch (mach->shadow_set & 0x03) { + case 0x00: + if (mach->crt_resolution) + svga_recalctimings(svga); + else { if (dev->accel.advfunc_cntl & 0x04) { if (dev->hdisp == 640) { dev->hdisp = 1024; dev->vdisp = 768; - svga_recalctimings(svga); } } else { if (dev->hdisp == 1024) { dev->hdisp = 640; dev->vdisp = 480; - svga_recalctimings(svga); } } - } else svga_recalctimings(svga); - } else if (mach->crt_resolution == 0x02) { - if (dev->accel.advfunc_cntl & 0x04) { - if (dev->hdisp == 640) { - dev->hdisp = 1024; - dev->vdisp = 768; - svga_recalctimings(svga); - } - } else { - if (dev->hdisp == 1024) { - dev->hdisp = 640; - dev->vdisp = 480; - svga_recalctimings(svga); - } } - } else - svga_recalctimings(svga); + break; + case 0x01: + mach->crt_resolution = 0x01; + break; + case 0x02: + mach->crt_resolution = 0x02; + break; + default: + break; } - break; - case 0x01: /*Shadow 640x480 CRT register set*/ - if (dev->on) { - if (!(dev->accel.advfunc_cntl & 0x04)) { - if (dev->hdisp == 1024) { - dev->hdisp = 640; - dev->vdisp = 480; - } - } - svga_recalctimings(svga); - } - break; - case 0x02: /*Shadow 1024x768 CRT register set*/ - if (dev->on) { - if (dev->accel.advfunc_cntl & 0x04) { - if (dev->hdisp == 640) { - dev->hdisp = 1024; - dev->vdisp = 768; - } - } - svga_recalctimings(svga); - } - break; - default: - break; - } + } + } else + svga_recalctimings(svga); + + mach_log("Shadow set ATI=%x, shadow set 8514/A and on1=%x, on2=%x, resolution h=%d, v=%d, vtotal=%d, vsyncstart=%d, crtres=%d, ret=%d, actual passthrough=%x.\n", mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x05, mach->accel.clock_sel & 0x01, dev->hdisp, dev->vdisp, dev->v_total, dev->v_syncstart, mach->crt_resolution, ret, dev->on); } void @@ -2864,42 +2762,52 @@ ati8514_recalctimings(svga_t *svga) mach_log("ON=%d, vgahdisp=%d.\n", dev->on, svga->hdisp); if (dev->on) { mach_log("8514/A ON.\n"); - dev->pitch = dev->ext_pitch; + dev->pitch = ((mach->accel.ge_pitch & 0xff) << 3); + dev->interlace = !!(dev->disp_cntl & 0x10); dev->rowoffset = dev->ext_crt_pitch; 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; + dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; + mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2; + dev->accel.ge_offset -= mach->accel.crt_offset; 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); + mach->accel.src_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.dst_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.src_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; + mach->accel.dst_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; + mach->accel.src_ge_offset -= mach->accel.crt_offset; + mach->accel.dst_ge_offset -= mach->accel.crt_offset; + dev->h_disp = dev->hdisp; dev->dispend = dev->vdisp; + if (dev->dispend == 600) + dev->h_disp = 800; + else if (dev->h_disp == 640) + dev->dispend = 480; if (dev->accel.advfunc_cntl & 0x04) - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; else - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; if (dev->interlace) dev->dispend >>= 1; - mach->crt_resolution = 0x00; 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); if (dev->vram_512k_8514) { - if (dev->h_disp == 640) { - dev->ext_pitch = 640; - dev->pitch = dev->ext_pitch; - } else { - dev->ext_pitch = 1024; - dev->pitch = dev->ext_pitch; - } + if (dev->h_disp == 640) + dev->pitch = 640; + else + dev->pitch = 1024; } dev->accel_bpp = 8; svga->render8514 = ibm8514_render_8bpp; - } + } else + mach->crt_resolution = 0; } static void @@ -2956,13 +2864,29 @@ mach_recalctimings(svga_t *svga) mach_log("ON=%d, override=%d, gelo=%04x, gehi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, svga->hdisp); if (dev->on) { dev->ma_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ - dev->pitch = dev->ext_pitch; + dev->interlace = !!(dev->disp_cntl & 0x10); + dev->pitch = ((mach->accel.ge_pitch & 0xff) << 3); dev->rowoffset = dev->ext_crt_pitch; 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; - mach_log("8514/A ON, extpitch=%d, geoffset=%x, 8514malatch=%x, vgamalatch=%x.\n", dev->ext_pitch, mach->accel.ge_offset, dev->ma_latch, svga->ma_latch); + mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)); + if (dev->bpp) { + dev->accel.ge_offset <<= 1; + mach->accel.crt_offset <<= 1; + } else { + dev->accel.ge_offset <<= 2; + mach->accel.crt_offset <<= 2; + } + + if (ATI_MACH32 && !dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + dev->accel.ge_offset <<= 1; + mach->accel.crt_offset <<= 1; + } + + dev->accel.ge_offset -= mach->accel.crt_offset; + + mach_log("RowCount=%x, rowoffset=%x, pitch=%d, geoffset=%x, crtoffset=%x.\n", dev->rowcount, dev->rowoffset, dev->pitch, dev->accel.ge_offset, mach->accel.crt_offset); 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); @@ -2972,59 +2896,94 @@ mach_recalctimings(svga_t *svga) if (dev->dispend == 959) { /*FIXME: vertical resolution mess on EEPROM tests on Mach8*/ dev->dispend >>= 1; dev->dispend++; - } + } else if (dev->dispend == 600) + dev->h_disp = 800; + else if (dev->h_disp == 640) + dev->dispend = 480; - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); if (mach->accel.clock_sel & 0x40) - svga->clock8514 *= 2; + svga->clock_8514 *= 2; if (dev->interlace) dev->dispend >>= 1; - mach->crt_resolution = 0x00; if (ATI_MACH32) { + switch ((mach->shadow_set >> 8) & 0x03) { + case 0x00: + mach->accel.src_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.dst_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.src_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + mach->accel.dst_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + if (dev->bpp) { + mach->accel.src_ge_offset <<= 1; + mach->accel.dst_ge_offset <<= 1; + } else { + mach->accel.src_ge_offset <<= 2; + mach->accel.dst_ge_offset <<= 2; + } + if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { + mach->accel.src_ge_offset <<= 1; + mach->accel.dst_ge_offset <<= 1; + } + mach->accel.src_ge_offset -= mach->accel.crt_offset; + mach->accel.dst_ge_offset -= mach->accel.crt_offset; + dev->accel.src_pitch = mach->accel.src_pitch; + dev->accel.dst_pitch = mach->accel.dst_pitch; + dev->accel.src_ge_offset = mach->accel.src_ge_offset; + dev->accel.dst_ge_offset = mach->accel.dst_ge_offset; + break; + case 0x01: + mach->accel.dst_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.dst_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + if (dev->bpp) + mach->accel.dst_ge_offset <<= 1; + else + mach->accel.dst_ge_offset <<= 2; + + if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) + mach->accel.dst_ge_offset <<= 1; + + mach->accel.dst_ge_offset -= mach->accel.crt_offset; + dev->accel.dst_pitch = mach->accel.dst_pitch; + dev->accel.dst_ge_offset = mach->accel.dst_ge_offset; + break; + case 0x02: + mach->accel.src_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.src_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + if (dev->bpp) + mach->accel.src_ge_offset <<= 1; + else + mach->accel.src_ge_offset <<= 2; + + if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) + mach->accel.src_ge_offset <<= 1; + + mach->accel.src_ge_offset -= mach->accel.crt_offset; + dev->accel.src_pitch = mach->accel.src_pitch; + dev->accel.src_ge_offset = mach->accel.src_ge_offset; + break; + default: + break; + } 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) { - dev->accel_bpp = 16; - 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; - - 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; - svga->overscan_color = dev->pallook[mach->overscan_col_8]; - } else { - if (dev->vram_512k_8514) { - if (dev->h_disp == 640) { - dev->ext_pitch = 640; - dev->pitch = dev->ext_pitch; - } else { - dev->ext_pitch = 1024; - dev->pitch = dev->ext_pitch; - } - } - dev->accel_bpp = 8; - svga->overscan_color = dev->pallook[mach->overscan_col_8]; - } - - mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n", + 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); + dev->accel_bpp, mach->shadow_set & 0x03, svga->hdisp); switch (dev->accel_bpp) { case 8: + if ((mach->accel.ext_ge_config & 0x30) == 0x00) { + if (dev->vram_512k_8514) { + if (dev->h_disp == 640) + dev->pitch = 640; + else + dev->pitch = 1024; + } + } svga->render8514 = ibm8514_render_8bpp; break; case 15: @@ -3047,22 +3006,34 @@ mach_recalctimings(svga_t *svga) } } } else { + mach->accel.src_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.dst_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.src_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + mach->accel.dst_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + if (dev->bpp) { + mach->accel.src_ge_offset <<= 1; + mach->accel.dst_ge_offset <<= 1; + } else { + mach->accel.src_ge_offset <<= 2; + mach->accel.dst_ge_offset <<= 2; + } + mach->accel.src_ge_offset -= mach->accel.crt_offset; + mach->accel.dst_ge_offset -= mach->accel.crt_offset; + 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); + mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 0x03, dev->interlace, svga->hdisp); if (dev->vram_512k_8514) { - if (dev->h_disp == 640) { - dev->ext_pitch = 640; - dev->pitch = dev->ext_pitch; - } else { - dev->ext_pitch = 1024; - dev->pitch = dev->ext_pitch; - } + if (dev->h_disp == 640) + dev->pitch = 640; + else + dev->pitch = 1024; } dev->accel_bpp = 8; svga->render8514 = ibm8514_render_8bpp; } } else { + mach->crt_resolution = 0; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { mach_log("GDCREG5=%02x, ATTR10=%02x, ATI B0 bit 5=%02x, ON=%d.\n", svga->gdcreg[5] & 0x60, svga->attrregs[0x10] & 0x40, mach->regs[0xb0] & 0x20, dev->on); @@ -3129,9 +3100,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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); } + svga_recalctimings(svga); break; case 0xae8: @@ -3139,8 +3109,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (!(mach->shadow_cntl & 0x04)) { WRITE8(port, dev->hsync_start, val); } - mach_set_resolution(mach, svga); } + svga_recalctimings(svga); break; case 0xee8: @@ -3148,14 +3118,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (!(mach->shadow_cntl & 0x04)) { WRITE8(port, dev->hsync_width, val); } - mach_set_resolution(mach, 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.*/ - mach_set_resolution(mach, svga); + svga_recalctimings(svga); break; case 0x6e8: @@ -3166,52 +3130,45 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->htotal = (val >> 8) & 0xff; if (!(mach->shadow_cntl & 0x08)) { - if (dev->htotal || (mach->accel.clock_sel & 0x01)) { + if ((dev->htotal || (mach->accel.clock_sel & 0x01)) && (val & 0xff)) { WRITE8(port, dev->hdisped, val); } } - - if (dev->htotal || (mach->accel.clock_sel & 0x01)) - 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); + if ((dev->htotal || (mach->accel.clock_sel & 0x01)) && (val & 0xff)) { + 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); - } - 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); + svga_recalctimings(svga); 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)) + if (!(mach->shadow_cntl & 0x04)) { dev->htotal = val; - - mach_set_resolution(mach, svga); + } } } + svga_recalctimings(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)) { + if (!(mach->shadow_cntl & 0x10) && val) { 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.*/ @@ -3219,39 +3176,32 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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); + svga_recalctimings(svga); 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); + WRITE8(port, dev->v_total_reg, val >> 8); 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); } + svga_recalctimings(svga); break; case 0x16e8: 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 & 0x20)) { + if (!(mach->shadow_cntl & 0x20) && val) { dev->v_disp = val; dev->v_disp &= 0x1fff; } - 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 & 0x20)) { - 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); @@ -3261,9 +3211,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u WRITE8(port, dev->v_disp, val); dev->v_disp &= 0x1fff; } - mach_set_resolution(mach, svga); } } + svga_recalctimings(svga); break; case 0x16e9: if (len == 1) { @@ -3272,21 +3222,20 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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); } + svga_recalctimings(svga); break; case 0x1ae8: 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)) { + if (!(mach->shadow_cntl & 0x10) && val) { 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); @@ -3296,9 +3245,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u WRITE8(port, dev->v_sync_start, val); dev->v_sync_start &= 0x1fff; } - mach_set_resolution(mach, svga); } } + svga_recalctimings(svga); break; case 0x1ae9: if (len == 1) { @@ -3307,18 +3256,22 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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); } + svga_recalctimings(svga); + break; + + case 0x1ee8: + case 0x1ee9: + svga_recalctimings(svga); break; case 0x22e8: - if ((mach->shadow_cntl & 0x03) == 0x00) { + 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); @@ -3346,17 +3299,25 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x4ae8: - dev->accel.advfunc_cntl = val; - dev->on = val & 0x01; + case 0x4ae9: + mach->old_on1 = dev->accel.advfunc_cntl & 0x01; + WRITE8(port, dev->accel.advfunc_cntl, val); + if (len == 2) { + WRITE8(port + 1, dev->accel.advfunc_cntl, val >> 8); + } + 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, extmode=%02x.\n", - CS, cpu_state.pc, port, val & 0x01, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp, mach->regs[0xb0] & 0x20); + if (dev->_8514crt) { + if (mach->regs[0xb0] & 0x20) { + dev->on = 1; + dev->vendor_mode = !!(ATI_MACH32); + } + } + + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, valxor=%x, shadow crt=%x, hdisp=%d, vdisp=%d, extmode=%02x, accelbpp=%d, crt=%d, crtres=%d.\n", + CS, cpu_state.pc, port, val & 0x01, dev->on, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp, mach->regs[0xb0] & 0x20, dev->accel_bpp, dev->_8514crt, mach->crt_resolution); if (ATI_MACH32) { - if ((mach->regs[0xb0] & 0x20) || (dev->accel_bpp >= 15)) { /*Account for the extended ATI 8514/A mode here too*/ - dev->on |= 0x01; - dev->vendor_mode = 1; - } mach_set_resolution(mach, svga); mach32_updatemapping(mach, svga); } else { @@ -3367,23 +3328,30 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x82e8: + ibm8514_accel_out_fifo(svga, port, val, len); + mach_log("DSTY=%04x, len=%d.\n", val & 0x07ff, len); + break; + case 0x86e8: ibm8514_accel_out_fifo(svga, port, val, len); + mach_log("DSTX=%04x, len=%d.\n", val & 0x07ff, len); break; case 0x8ae8: ibm8514_accel_out_fifo(svga, port, val, len); + mach_log("SRCY=%04x, len=%d.\n", val & 0x07ff, len); if (len == 2) { - mach_log("SRCY=%d.\n", val & 0x07ff); mach->accel.src_y = val & 0x07ff; + mach->accel.src_y_scan = ((int64_t)(val & 0x07ff)); } break; case 0x8ee8: ibm8514_accel_out_fifo(svga, port, val, len); + mach_log("SRCX=%04x, len=%d.\n", val & 0x07ff, len); if (len == 2) { - mach_log("SRCX=%d.\n", val & 0x07ff); mach->accel.src_x = val & 0x07ff; + mach->accel.src_x_scan = ((int64_t)(val & 0x07ff)); } break; @@ -3409,7 +3377,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xa2e8: case 0xe2e8: if (port == 0xe2e8) { - mach_log("%04X: Background Color=%04x.\n", port, val); + mach_log("%04X: Background Color=%04x, pix=%d, len=%d.\n", port, val, dev->accel.cmd_back, len); if (len == 2) { if (!dev->accel.cmd_back) { if (mach->accel.cmd_type >= 0) { @@ -3430,7 +3398,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("%04X: CMDBack BKGDCOLOR, sy=%d, height=%d, cmdtype=%d, val=%04x.\n", port, dev->accel.sy, mach->accel.height, mach->accel.cmd_type, val); } } else { - if (dev->accel.cmd & 0x100) { + if (!dev->accel.cmd_back) { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; @@ -3450,7 +3418,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xa6e8: case 0xe6e8: if (port == 0xe6e8) { - mach_log("%04X: Foreground Color=%04x.\n", port, val); + mach_log("%04X: Foreground Color=%04x, pix=%d, len=%d.\n", port, val, dev->accel.cmd_back, len); if (len == 2) { if (!dev->accel.cmd_back) { if (mach->accel.cmd_type >= 0) { @@ -3533,6 +3501,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xaae8: + if (len == 2) + mach->accel.dst_clr_cmp_mask = val; + fallthrough; case 0xaee8: case 0xb2e8: case 0xb6e8: @@ -3580,65 +3551,63 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xaee: case 0xaef: - if (len == 2) - mach->cursor_offset_lo_reg = val; - else { - WRITE8(port, mach->cursor_offset_lo_reg, val); + WRITE8(port, mach->cursor_offset_lo_reg, val); + if (len == 2) { + WRITE8(port + 1, mach->cursor_offset_lo_reg, val >> 8); } mach->cursor_offset_lo = mach->cursor_offset_lo_reg; dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); + if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) + dev->hwcursor.addr <<= 1; break; case 0xeee: case 0xeef: - if (len == 2) - mach->cursor_offset_hi_reg = val; - else { - WRITE8(port, mach->cursor_offset_hi_reg, val); + WRITE8(port, mach->cursor_offset_hi_reg, val); + if (len == 2) { + WRITE8(port + 1, mach->cursor_offset_hi_reg, val >> 8); } 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); - mach_log("HWCursorEnabled=%x.\n", dev->hwcursor.ena); + if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) + dev->hwcursor.addr <<= 1; break; case 0x12ee: case 0x12ef: - if (len == 2) - mach->cursor_x = val; - else { - WRITE8(port, mach->cursor_x, val); + WRITE8(port, mach->cursor_x, val); + if (len == 2) { + WRITE8(port + 1, mach->cursor_x, val >> 8); } dev->hwcursor.x = mach->cursor_x & 0x7ff; break; case 0x16ee: case 0x16ef: - if (len == 2) - mach->cursor_y = val; - else { - WRITE8(port, mach->cursor_y, val); + WRITE8(port, mach->cursor_y, val); + if (len == 2) { + WRITE8(port + 1, mach->cursor_y, val >> 8); } dev->hwcursor.y = mach->cursor_y & 0xfff; break; case 0x1aee: case 0x1aef: - if (len == 2) - mach->cursor_col_b = val; - else { - WRITE8(port, mach->cursor_col_b, val); + WRITE8(port, mach->cursor_col_b, val); + if (len == 2) { + WRITE8(port + 1, mach->cursor_col_b, val >> 8); } mach->cursor_col_0 = mach->cursor_col_b & 0xff; mach->cursor_col_1 = (mach->cursor_col_b >> 8) & 0xff; + mach_log("ATI 8514/A: (0x%04x) Cursor Color B, val=0x%02x, len=%d, extended 8514/A mode bpp=%d.\n", port, val, len, dev->accel_bpp); break; case 0x1eee: case 0x1eef: - if (len == 2) - mach->cursor_vh_offset = val; - else { - WRITE8(port, mach->cursor_vh_offset, val); + WRITE8(port, mach->cursor_vh_offset, val); + if (len == 2) { + WRITE8(port + 1, mach->cursor_vh_offset, val >> 8); } dev->hwcursor.xoff = mach->cursor_vh_offset & 0x3f; dev->hwcursor.yoff = (mach->cursor_vh_offset >> 8) & 0x3f; @@ -3654,45 +3623,52 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x26ee: case 0x26ef: - if (len == 2) - mach->accel.crt_pitch = val; - else { - WRITE8(port, mach->accel.crt_pitch, val); + WRITE8(port, mach->accel.crt_pitch, val); + if (len == 2) { + WRITE8(port + 1, mach->accel.crt_pitch, val >> 8); } + dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; + if (dev->accel_bpp > 8) { - if (dev->accel_bpp == 24) + if (dev->accel_bpp == 24) { dev->ext_crt_pitch *= 3; - else if (dev->accel_bpp == 32) + } else if (dev->accel_bpp == 32) dev->ext_crt_pitch <<= 2; else dev->ext_crt_pitch <<= 1; } - if (ATI_MACH32) { - dev->on |= 0x01; - dev->vendor_mode = 1; - } - svga_recalctimings(svga); + + if (len == 2) { + dev->_8514crt = 0; + if (!(dev->accel.advfunc_cntl & 0x01)) { + dev->on = 1; + dev->vendor_mode = !!ATI_MACH32; + } + } else + dev->_8514crt = 1; + + mach_set_resolution(mach, svga); if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); - 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); + mach_log("ATI 8514/A: (0x%04x) CRT Pitch, val=0x%02x, crtpitch=%x, len=%d, extended 8514/A mode bpp=%d.\n", port, val, dev->ext_crt_pitch, len, dev->accel_bpp); break; case 0x2aee: case 0x2aef: - if (len == 2) { + if (len == 2) mach->accel.crt_offset_lo = val; - } else { + else { WRITE8(port, mach->accel.crt_offset_lo, val); } - svga_recalctimings(svga); + mach_log("ATI 8514/A: (0x%04x) CRT Offset Low val=0x%02x, len=%d.\n", port, val, len); break; case 0x2eee: case 0x2eef: mach->accel.crt_offset_hi = val & 0x0f; - svga_recalctimings(svga); + mach_log("ATI 8514/A: (0x%04x) CRT Offset High val=0x%02x, len=%d.\n", port, val, len); break; case 0x32ee: @@ -3727,6 +3703,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } 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; + mach_log("ATI 8514/A: (0x%04x) Cursor Color 0 RG, val=0x%02x, len=%d, extended 8514/A mode bpp=%d.\n", port, val, len, dev->accel_bpp); break; case 0x3eee: @@ -3738,6 +3715,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } 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; + mach_log("ATI 8514/A: (0x%04x) Cursor Color 1 RG, val=0x%02x, len=%d, extended 8514/A mode bpp=%d.\n", port, val, len, dev->accel_bpp); break; case 0x42ee: @@ -3763,18 +3741,20 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x4aee: case 0x4aef: - if (len == 2) - mach->accel.clock_sel = val; - else { - WRITE8(port, mach->accel.clock_sel, val); + mach->old_on2 = mach->accel.clock_sel & 0x01; + WRITE8(port, mach->accel.clock_sel, val); + if (len == 2) { + WRITE8(port + 1, mach->accel.clock_sel, val >> 8); } 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", - port, mach->accel.clock_sel & 0x01, val, dev->hdisp, dev->vdisp); + + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, val=%04x, xor=%d, hdisp=%d, vdisp=%d, accelbpp=%d.\n", + CS, cpu_state.pc, port, mach->accel.clock_sel & 0x01, val, dev->on, dev->hdisp, dev->vdisp, dev->accel_bpp); mach_log("Vendor ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); - svga_recalctimings(svga); + + mach_set_resolution(mach, svga); if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); break; @@ -3801,29 +3781,17 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x5aee: case 0x5aef: - if (len == 2) - mach->shadow_set = val; - else { - WRITE8(port, mach->shadow_set, val); + WRITE8(port, mach->shadow_set, val); + if (len == 2) { + WRITE8(port + 1, mach->shadow_set, val >> 8); } - mach_log("ATI 8514/A: (0x%04x) val=0x%02x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=0x%02x, len=%d.\n", port, val, len); if ((mach->shadow_set & 0x03) == 0x00) mach_log("Primary CRT register set.\n"); - else if ((mach->shadow_set & 0x03) == 0x01) { - mach->crt_resolution = 0x01; + else if ((mach->shadow_set & 0x03) == 0x01) mach_log("CRT Shadow Set 1: 640x480.\n"); - } else if ((mach->shadow_set & 0x03) == 0x02) { - mach->crt_resolution = 0x02; + else if ((mach->shadow_set & 0x03) == 0x02) mach_log("CRT Shadow Set 2: 1024x768.\n"); - } - - if (ATI_MACH32) { - mach_log("Load both SRC/DST GE Offset/Pitch=%03x, offset=%08x.\n", mach->shadow_set & 0x300, dev->accel.ge_offset); - if ((mach->shadow_set & 0x300) == 0x000) { - mach->accel.ge_offset_lo = 0x0000; - mach->accel.ge_offset_hi = 0x0000; - } - } break; case 0x5eee: @@ -3857,8 +3825,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { WRITE8(port, mach->accel.ge_offset_lo, val); } + mach_log("ATI 8514/A: (0x%04x) GE Offset Low val=0x%02x, geoffset=%04x, len=%d.\n", port, val, dev->accel.ge_offset, len); 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: @@ -3868,8 +3836,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { WRITE8(port, mach->accel.ge_offset_hi, val); } + mach_log("ATI 8514/A: (0x%04x) GE Offset High val=0x%02x, geoffset=%04x, len=%d.\n", port, val, dev->accel.ge_offset, len); 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: @@ -3879,18 +3847,17 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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); + mach_log("ATI 8514/A: (0x%04x) GE Pitch val=0x%02x.\n", port, val); svga_recalctimings(svga); break; case 0x7aee: case 0x7aef: - if (len == 2) - mach->accel.ext_ge_config = val; - else { - WRITE8(port, mach->accel.ext_ge_config, val); + WRITE8(port, mach->accel.ext_ge_config, val); + if (len == 2) { + WRITE8(port + 1, mach->accel.ext_ge_config, val >> 8); } + if (ATI_MACH32) { if (mach->accel.crt_pitch & 0xff) dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; @@ -3899,25 +3866,40 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x00: case 0x10: dev->bpp = 0; + dev->accel_bpp = 8; break; case 0x20: dev->bpp = 1; dev->ext_crt_pitch <<= 1; + switch (mach->accel.ext_ge_config & 0xc0) { + case 0x00: + dev->accel_bpp = 15; + break; + case 0x40: + dev->accel_bpp = 16; + break; + default: /*TODO: 655RGB and 664RGB*/ + break; + } break; case 0x30: dev->bpp = 0; - if (mach->accel.ext_ge_config & 0x200) + if (mach->accel.ext_ge_config & 0x200) { dev->ext_crt_pitch <<= 2; - else + dev->accel_bpp = 32; + } else { dev->ext_crt_pitch *= 3; + dev->accel_bpp = 24; + } break; default: break; } svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); - mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); - svga_recalctimings(svga); + mach_log("ATI 8514/A: (0x%04x) Extended Configuration=%04x, val=%04x.\n", port, mach->accel.ext_ge_config, val); + mach_set_resolution(mach, svga); + mach32_updatemapping(mach, svga); } else ati_eeprom_write(&mach->eeprom, !!(mach->accel.ext_ge_config & 0x04), !!(mach->accel.ext_ge_config & 0x02), !!(mach->accel.ext_ge_config & 0x01)); break; @@ -3936,30 +3918,33 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach->accel.patt_data_idx_reg = val & 0x1f; mach->accel.patt_data_idx = mach->accel.patt_data_idx_reg; + mach_log("Write Port 82ee: Pattern Data Index=%d, idx for color=%d.\n", val & 0x1f, mach->accel.color_pattern_idx); + 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) { - frgd_sel = (mach->accel.dp_config >> 13) & 7; - 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); - if ((dev->accel_bpp >= 24) && (frgd_sel == 5) && (mach->accel.patt_len == 0x17)) - dev->accel.y1 = 1; + if (dev->bpp) { + mach->accel.color_pattern_hicol[mach->accel.patt_data_idx] = val; + mach_log("Write Port 8eee: Color Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx, val); + mach->accel.patt_data_idx++; + } else { + 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); + mach->accel.patt_data_idx += 2; + } } 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; } - mach->accel.patt_data_idx += 2; } break; @@ -4026,7 +4011,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } dev->data_available = 0; dev->data_available2 = 0; - mach_log("BitBLT=%04x.\n", mach->accel.dp_config); + mach_log("BitBLT=%04x, pattidx=%d.\n", mach->accel.dp_config, mach->accel.patt_idx); mach_log(".\n"); mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ @@ -4048,11 +4033,13 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xb6ee: - dev->accel.bkgd_mix = val & 0xff; + dev->accel.bkgd_mix = val & 0x1f; + dev->accel.bkgd_sel = (mach->accel.dp_config >> 7) & 3; break; case 0xbaee: - dev->accel.frgd_mix = val & 0xff; + dev->accel.frgd_mix = val & 0x1f; + dev->accel.frgd_sel = (mach->accel.dp_config >> 13) & 3; break; case 0xbeee: @@ -4088,6 +4075,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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 len=%d.\n", val); mach_log(".\n"); frgd_sel = (mach->accel.dp_config >> 13) & 7; @@ -4104,7 +4092,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xceee: - mach_log("Data Path Configuration (%04x) write val=%04x.\n", port, val); + mach_log("Data Path Configuration (%04x) write val=%04x, len=%d.\n", port, val, len); if (len == 2) { dev->data_available = 0; dev->data_available2 = 0; @@ -4124,6 +4112,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xd6ee: mach->accel.patt_idx = val & 0x1f; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + + if ((frgd_sel == 5) && (dev->accel_bpp >= 24) && (mach->accel.patt_len == 0x17)) + mach->accel.color_pattern_idx = 0; + mach_log("Write Port d6ee: Pattern Index=%d.\n", val & 0x1f); break; @@ -4169,12 +4162,13 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xeeee: + mach_log("EEEE val=%04x, len=%d.\n", val, len); if (len == 2) mach->accel.dest_cmp_fn = val; break; case 0xf2ee: - mach_log("F2EE.\n"); + mach_log("F2EE val=%04x, len=%d.\n", val, len); if (len == 2) mach->accel.dst_clr_cmp_mask = val; break; @@ -4259,8 +4253,39 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in if (dev->fifo_idx > 0) dev->fifo_idx--; - if (dev->force_busy) + if (dev->force_busy) { temp |= 0x0200; /*Hardware busy*/ + if (mach->accel.cmd_type >= 0) { + switch (mach->accel.cmd_type) { + case 2: + if (dev->accel.sy >= mach->accel.height) + dev->force_busy = 0; + break; + case 5: + if (dev->accel.sx >= mach->accel.width) + dev->force_busy = 0; + break; + default: + if (dev->accel.sy < 0) + dev->force_busy = 0; + break; + } + } else { + switch (dev->accel.cmd >> 13) { + case 2: + case 3: + case 4: + case 6: + if (dev->accel.sy < 0) + dev->force_busy = 0; + break; + default: + if (!dev->accel.sy) + dev->force_busy = 0; + break; + } + } + } if (dev->data_available) { temp |= 0x0100; /*Read Data available*/ @@ -4837,6 +4862,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x56ee: case 0x56ef: READ8(port, mach->accel.scratch1); + mach_log("ScratchPad1=%x.\n", mach->accel.scratch1); break; case 0x5eee: @@ -4855,6 +4881,8 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) if (mach->force_busy) temp |= 0x20; + mach->force_busy = 0; + if (ati_eeprom_read(&mach->eeprom)) temp |= 0x40; @@ -5425,6 +5453,7 @@ mach32_svga_write(uint32_t addr, uint8_t val, void *priv) xga_write_test(addr, val, svga); addr = svga_decode_addr(svga, addr, 1); + if (addr == 0xffffffff) { mach_log("WriteCommon Over.\n"); return; @@ -5465,7 +5494,7 @@ mach32_svga_write(uint32_t addr, uint8_t val, void *priv) count = 4; - switch (svga->writemode) { + 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)) { @@ -5696,17 +5725,17 @@ mach32_read_common(uint32_t addr, int linear, mach_t *mach, svga_t *svga) addr &= dev->vram_mask; if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { - switch (addr & 0x06) { + switch ((addr & 0x06) >> 1) { case 0x00: - case 0x06: + case 0x03: ret = dev->vram[addr] & 0x0f; ret |= (dev->vram[addr + 1] << 4); break; - case 0x02: + case 0x01: ret = dev->vram[addr + 2] & 0x0f; ret |= (dev->vram[addr + 3] << 4); break; - case 0x04: + case 0x02: ret = dev->vram[addr - 2] & 0x0f; ret |= (dev->vram[addr - 1] << 4); break; @@ -5800,24 +5829,24 @@ mach32_read(uint32_t addr, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t ret = 0x00; + uint8_t ret; (void) xga_read_test(addr, svga); addr = (addr & svga->banked_mask) + svga->read_bank; if ((ATI_MACH32 && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; - switch (addr & 0x06) { + switch ((addr & 0x06) >> 1) { case 0x00: - case 0x06: + case 0x03: ret = mach32_read_common(addr, 0, mach, svga) & 0x0f; ret |= (mach32_read_common(addr + 1, 0, mach, svga) << 4); break; - case 0x02: + case 0x01: ret = mach32_read_common(addr + 2, 0, mach, svga) & 0x0f; ret |= (mach32_read_common(addr + 3, 0, mach, svga) << 4); break; - case 0x04: + case 0x02: ret = mach32_read_common(addr - 2, 0, mach, svga) & 0x0f; ret |= (mach32_read_common(addr - 1, 0, mach, svga) << 4); break; @@ -5958,7 +5987,8 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) 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)))) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20))) && + (svga->mapping.base == 0xa0000)) { if (addr & 0x100) { mach_log("Port WORDB Write=%04x.\n", actual_port_ext); mach_accel_outb(actual_port_ext, val, mach); @@ -5967,8 +5997,8 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) 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); + mach_log("Linear WORDB Write=%08x, val=%02x, ON=%x, dpconfig=%04x, apsize=%08x, addr=%08x.\n", + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20, addr); if (dev->on) mach32_write_common(addr, val, 1, mach, svga); @@ -5988,17 +6018,19 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) 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)))) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20))) && + (svga->mapping.base == 0xa0000)) { if (addr & 0x100) { 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, localcntl=%02x, pcicntl=%02x, actual addr=%08x.\n", actual_port, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80, addr); + mach_log("Port WORDW Write=%04x, localcntl=%02x, pcicntl=%02x, actual addr=%08x, val=%04x.\n", actual_port, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80, addr, val); mach_accel_outw(actual_port, val, mach); } } else { - 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); + mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x, addr=%08x.\n", + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20, addr); + if (dev->on) mach32_writew_linear(addr, val, mach); else @@ -6016,11 +6048,9 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) 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); - 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)))) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20))) && + (svga->mapping.base == 0xa0000)) { if (addr & 0x100) { 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); @@ -6029,6 +6059,9 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_accel_outl(actual_port, val, mach); } } else { + mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x, addr=%08x.\n", + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20, addr); + if (dev->on) mach32_writel_linear(addr, val, mach); else @@ -6048,7 +6081,8 @@ mach32_ap_readb(uint32_t addr, void *priv) 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)))) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20))) && + (svga->mapping.base == 0xa0000)) { if (addr & 0x100) temp = mach_accel_inb(actual_port_ext, mach); else @@ -6077,7 +6111,8 @@ mach32_ap_readw(uint32_t addr, void *priv) 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)))) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20))) && + (svga->mapping.base == 0xa0000)) { if (addr & 0x100) { temp = mach_accel_inw(actual_port_ext, mach); mach_log("Port WORDW Read=%04x.\n", actual_port_ext); @@ -6109,7 +6144,8 @@ mach32_ap_readl(uint32_t addr, void *priv) 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)))) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20))) && + (svga->mapping.base == 0xa0000)) { if (addr & 0x100) { temp = mach_accel_inl(actual_port_ext, mach); mach_log("Port WORDL Read=%04x.\n", actual_port_ext); @@ -6149,32 +6185,18 @@ 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); svga->banked_mask = 0x7fff; - if (ATI_MACH32 && !(dev->accel.advfunc_cntl & 0x01) && !(mach->accel.clock_sel & 0x01)) { - if ((svga->gdcreg[6] & 0x01) || (svga->attrregs[0x10] & 0x01)) { - if (svga->attrregs[0x10] & 0x40) { - dev->vendor_mode = 0; - dev->on &= ~0x01; - mach_log("No 8514/A mode on b8000.\n"); - mach_set_resolution(mach, svga); - } - } - } - mem_mapping_set_addr(&mach->banked_mapping, 0xb8000, 0x08000); break; default: @@ -6205,16 +6227,16 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) if (ATI_MACH32) { if (dev->on && dev->vendor_mode) { mach_log("Mach32 banked mapping.\n"); - mem_mapping_disable(&svga->mapping); - mem_mapping_enable(&mach->banked_mapping); + 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); } else { mach_log("IBM compatible banked mapping.\n"); - mem_mapping_enable(&svga->mapping); - mem_mapping_disable(&mach->banked_mapping); + mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, mach32_svga_write, mach32_svga_writew, mach32_svga_writel); + mem_mapping_set_p(&svga->mapping, svga); } } else { - mem_mapping_enable(&svga->mapping); - mem_mapping_disable(&mach->banked_mapping); + 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); } } @@ -6231,8 +6253,11 @@ mach32_hwcursor_draw(svga_t *svga, int displine) uint32_t *p; int x_pos; int y_pos; + int shift = 0; offset = dev->hwcursor_latch.x - dev->hwcursor_latch.xoff; + if (!dev->vram_512k_8514 && ((mach->accel.ext_ge_config & 0x30) == 0x00)) + shift = 1; mach_log("BPP=%d, displine=%d.\n", dev->accel_bpp, displine); switch (dev->accel_bpp) { @@ -6254,16 +6279,26 @@ mach32_hwcursor_draw(svga_t *svga, int displine) case 32: color0 = ((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0); color1 = ((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1); + mach_log("24/32BPP: Color0=%08x, Color1=%08x.\n", color0, color1); break; } if (dev->interlace && dev->hwcursor_oddeven) - dev->hwcursor_latch.addr += 16; + dev->hwcursor_latch.addr += (16 >> shift); - for (int x = 0; x < 64; x += 8) { - dat = dev->vram[dev->hwcursor_latch.addr & dev->vram_mask] | (dev->vram[(dev->hwcursor_latch.addr + 1) & dev->vram_mask] << 8); - - for (int xx = 0; xx < 8; xx++) { + for (int x = 0; x < 64; x += (8 >> shift)) { + if (shift) { + dat = dev->vram[(dev->hwcursor_latch.addr) & dev->vram_mask] & 0x0f; + dat |= (dev->vram[(dev->hwcursor_latch.addr + 1) & dev->vram_mask] << 4); + dat |= (dev->vram[(dev->hwcursor_latch.addr + 2) & dev->vram_mask] << 8); + dat |= (dev->vram[(dev->hwcursor_latch.addr + 3) & dev->vram_mask] << 12); + mach_log("4bpp Data=%04x.\n", dat); + } else { + dat = dev->vram[dev->hwcursor_latch.addr & dev->vram_mask]; + dat |= (dev->vram[(dev->hwcursor_latch.addr + 1) & dev->vram_mask] << 8); + mach_log("8bppplus Data=%04x.\n", dat); + } + for (int xx = 0; xx < (8 >> shift); xx++) { comb = (dat >> (xx << 1)) & 0x03; y_pos = displine; @@ -6293,7 +6328,7 @@ mach32_hwcursor_draw(svga_t *svga, int displine) } if (dev->interlace && !dev->hwcursor_oddeven) - dev->hwcursor_latch.addr += 16; + dev->hwcursor_latch.addr += (16 >> shift); } static void @@ -6923,20 +6958,20 @@ ati8514_accel_out_fifo(void *priv, uint16_t port, uint16_t val, int 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); + if (mach->pci_bus) { + 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; @@ -6951,6 +6986,10 @@ mach_reset(void *priv) ibm8514_t *dev = (ibm8514_t *) svga->dev8514; if (reset_state != NULL) { + dev->on = 0; + dev->vendor_mode = 0; + dev->_8514on = 0; + dev->_8514crt = 0; mach_disable_handlers(mach); mach->force_busy = 0; dev->force_busy = 0; @@ -7068,9 +7107,7 @@ 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); @@ -7096,7 +7133,7 @@ mach8_init(const device_t *info) svga->getclock = ics2494_getclock; dev->on = 0; - dev->ext_pitch = 1024; + dev->pitch = 1024; dev->ext_crt_pitch = 0x80; dev->accel_bpp = 8; svga->force_old_addr = 1; @@ -7158,7 +7195,7 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) /*Init as 1024x768 87hz interlaced first, per 8514/A.*/ dev->on = 0; - dev->ext_pitch = 1024; + dev->pitch = 1024; dev->ext_crt_pitch = 0x80; dev->accel_bpp = 8; dev->rowoffset = 0x80; @@ -7170,7 +7207,6 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) dev->disp_cntl = 0x33; mach->accel.clock_sel = 0x1c; mach->shadow_set = 0x02; - mach->crt_resolution = 0x02; dev->accel.cmd_back = 1; io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index d0189e0f7..67469ed22 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -776,9 +776,9 @@ svga_recalctimings(svga_t *svga) } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) { /*40 column*/ + if (svga->seqregs[1] & 8) /*40 column*/ svga->render = svga_render_text_40; - } else + else svga->render = svga_render_text_80; if (xga_active && (svga->xga != NULL)) { @@ -981,7 +981,7 @@ svga_recalctimings(svga_t *svga) crtcconst = svga->clock * svga->char_width; if (ibm8514_active && (svga->dev8514 != NULL)) { if (dev->on) - crtcconst8514 = svga->clock8514; + crtcconst8514 = svga->clock_8514; } if (xga_active && (svga->xga != NULL)) { if (xga->on) From b7319cf60b6297803f3405c877b3a7b3474fe40f Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 22 Apr 2025 21:24:31 +0200 Subject: [PATCH 0790/1190] Fix warnings and build. --- src/video/vid_ati_mach8.c | 2 +- src/video/vid_chips_69000.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 3bcde5b0c..5cbd48623 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -5829,7 +5829,7 @@ mach32_read(uint32_t addr, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t ret; + uint8_t ret = 0x00; (void) xga_read_test(addr, svga); addr = (addr & svga->banked_mask) + svga->read_bank; diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index d06ab0484..c9830f0ed 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -2793,7 +2793,8 @@ chips_69000_disable_handlers(chips_69000_t *chips) reset_state->decrement_timer = chips->decrement_timer; reset_state->svga.timer = chips->svga.timer; - reset_state->svga.timer8514 = chips->svga.timer8514; + reset_state->svga.timer_8514 = chips->svga.timer_8514; + reset_state->svga.timer_xga = chips->svga.timer_xga; } static void From cdb01de6d4604b57fbb493877d9b6e75db3887d1 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 22 Apr 2025 21:33:21 +0200 Subject: [PATCH 0791/1190] Apply it to the virge too. --- src/video/vid_s3_virge.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index cc0985c02..1b61c02d5 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -5109,7 +5109,8 @@ s3_virge_disable_handlers(virge_t *dev) reset_state->bios_rom.mapping = dev->bios_rom.mapping; reset_state->svga.timer = dev->svga.timer; - reset_state->svga.timer8514 = dev->svga.timer8514; + reset_state->svga.timer_8514 = dev->svga.timer_8514; + reset_state->svga.timer_xga = dev->svga.timer_xga; reset_state->irq_timer = dev->irq_timer; } From 571b0595debfb26093c1e6c3b27cbbdc94b4789b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 22 Apr 2025 21:44:56 +0200 Subject: [PATCH 0792/1190] sigh, apply it to the Bochs VBE virtual card too. --- src/video/vid_bochs_vbe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index 6dc015fb0..36185214c 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -344,7 +344,7 @@ bochs_vbe_recalctimings(svga_t* svga) svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); - svga->fullchange = 3; + svga->fullchange = 3; } if (svga->bpp == 4) @@ -708,7 +708,7 @@ bochs_vbe_disable_handlers(bochs_vbe_t *dev) reset_state->bios_rom.mapping = dev->bios_rom.mapping; reset_state->svga.timer = dev->svga.timer; - reset_state->svga.timer8514 = dev->svga.timer8514; + reset_state->svga.timer_8514 = dev->svga.timer_8514; } static void From 406588293ce2bea83bd83b746eb734ed32640946 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 22 Apr 2025 22:38:16 +0200 Subject: [PATCH 0793/1190] Load key bind defaults before loading the config, fixes saved key binds across emulator closures and reopenings. --- src/86box.c | 15 +++++++-------- src/config.c | 54 ++++++++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/86box.c b/src/86box.c index cde98f5d8..57abb12a6 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1000,6 +1000,13 @@ usage: zip_global_init(); mo_global_init(); + /* Initialize the keyboard accelerator list with default values */ + for (int x = 0; x < NUM_ACCELS; x++) { + strcpy(acc_keys[x].name, def_acc_keys[x].name); + strcpy(acc_keys[x].desc, def_acc_keys[x].desc); + strcpy(acc_keys[x].seq, def_acc_keys[x].seq); + } + /* Load the configuration file. */ config_load(); @@ -1030,14 +1037,6 @@ usage: gdbstub_init(); - // Initialize the keyboard accelerator list with default values - for(int x=0;x Date: Wed, 23 Apr 2025 12:49:29 +0500 Subject: [PATCH 0794/1190] Fix cleared key bindings not being reloaded --- src/config.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index 0de69de70..98923d9cf 100644 --- a/src/config.c +++ b/src/config.c @@ -1774,9 +1774,12 @@ load_keybinds(void) /* Now load values from config */ for (int x = 0; x < NUM_ACCELS; x++) { - p = ini_section_get_string(cat, acc_keys[x].name, "none"); + p = ini_section_get_string(cat, acc_keys[x].name, "default"); + /* Check if the binding was marked as cleared */ + if (strcmp(p, "none") == 0) + acc_keys[x].seq[0] = '\0'; /* If there's no binding in the file, leave it alone. */ - if (strcmp(p, "none") != 0) { + else if (strcmp(p, "default") != 0) { /* It would be ideal to validate whether the user entered a valid combo at this point, but the Qt method for testing that is @@ -2527,6 +2530,9 @@ save_keybinds(void) /* Has accelerator been changed from default? */ if (strcmp(def_acc_keys[x].seq, acc_keys[x].seq) == 0) ini_section_delete_var(cat, acc_keys[x].name); + /* Check for a cleared binding to avoid saving it as an empty string */ + else if (acc_keys[x].seq[0] == '\0') + ini_section_set_string(cat, acc_keys[x].name, "none"); else ini_section_set_string(cat, acc_keys[x].name, acc_keys[x].seq); } From 41a3e132ef75d86ae9566191cb82a033949ae19d Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 23 Apr 2025 12:56:20 +0500 Subject: [PATCH 0795/1190] Fix `QMetaObject::connectSlotsByName` warnings --- src/qt/qt_settingsinput.cpp | 17 ++++------------- src/qt/qt_settingsinput.hpp | 6 +++--- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 79225cb91..695dc43e9 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -79,15 +79,6 @@ SettingsInput::SettingsInput(QWidget *parent) refreshInputList(); - connect(ui->tableKeys, &QTableWidget::cellDoubleClicked, - this, &SettingsInput::on_tableKeys_doubleClicked); - - connect(ui->pushButtonBind, &QPushButton::clicked, - this, &SettingsInput::on_pushButtonBind_Clicked); - - connect(ui->pushButtonClearBind, &QPushButton::clicked, - this, &SettingsInput::on_pushButtonClearBind_Clicked); - onCurrentMachineChanged(machine); } @@ -194,7 +185,7 @@ SettingsInput::on_tableKeys_currentCellChanged(int currentRow, int currentColumn } void -SettingsInput::on_tableKeys_doubleClicked(int row, int col) +SettingsInput::on_tableKeys_cellDoubleClicked(int row, int col) { // Edit bind QTableWidgetItem *cell = ui->tableKeys->item(row,1); @@ -233,17 +224,17 @@ SettingsInput::on_tableKeys_doubleClicked(int row, int col) } void -SettingsInput::on_pushButtonBind_Clicked() +SettingsInput::on_pushButtonBind_clicked() { // Edit bind QTableWidgetItem *cell = ui->tableKeys->currentItem(); if (!cell) return; - on_tableKeys_doubleClicked(cell->row(), cell->column()); + on_tableKeys_cellDoubleClicked(cell->row(), cell->column()); } void -SettingsInput::on_pushButtonClearBind_Clicked() +SettingsInput::on_pushButtonClearBind_clicked() { // Wipe bind QTableWidgetItem *cell = ui->tableKeys->item(ui->tableKeys->currentRow(), 1); diff --git a/src/qt/qt_settingsinput.hpp b/src/qt/qt_settingsinput.hpp index ec7dc393b..742421f64 100644 --- a/src/qt/qt_settingsinput.hpp +++ b/src/qt/qt_settingsinput.hpp @@ -33,10 +33,10 @@ private slots: void on_pushButtonJoystick2_clicked(); void on_pushButtonJoystick3_clicked(); void on_pushButtonJoystick4_clicked(); - void on_tableKeys_doubleClicked(int row, int col); + void on_tableKeys_cellDoubleClicked(int row, int col); void on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); - void on_pushButtonBind_Clicked(); - void on_pushButtonClearBind_Clicked(); + void on_pushButtonBind_clicked(); + void on_pushButtonClearBind_clicked(); private: Ui::SettingsInput *ui; From b074c28d3d4929957319778073561869dc99d8ed Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 23 Apr 2025 16:07:41 +0600 Subject: [PATCH 0796/1190] DMA-based IDE writes are now reported properly --- src/disk/hdc_ide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index fe48bba6d..e1e12afcd 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -2514,6 +2514,7 @@ ide_callback(void *priv) return; } else if (ret & 1) { /* DMA successful */ + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1); ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); @@ -2524,7 +2525,6 @@ ide_callback(void *priv) err = UNC_ERR; ide_irq_raise(ide); - ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } else { /* Bus master DMA error, abort the command. */ ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); From 531e6545be8ff3714536c8557e32948048fac637 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 23 Apr 2025 16:22:53 +0600 Subject: [PATCH 0797/1190] IDE: Report single sector writes properly for 28-bit Write commands --- src/disk/hdc_ide.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index e1e12afcd..d725b2ace 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -2472,6 +2472,7 @@ ide_callback(void *priv) else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { + ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1); ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); ide_irq_raise(ide); ide->tf->secount--; @@ -2479,10 +2480,8 @@ ide_callback(void *priv) ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide->tf->pos = 0; ide_next_sector(ide); - ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1); } else { ide->tf->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 0); } if (ret < 0) err = UNC_ERR; From 17eeea1fd516274a2d952d6526edd67f0b8046b9 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Thu, 24 Apr 2025 13:24:43 +0300 Subject: [PATCH 0798/1190] Update the Russian translation Update the Russian translation --- src/qt/languages/ru-RU.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index baf1035ea..ebc71bb1b 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1618,7 +1618,7 @@ msgid "CODEC" msgstr "Кодек" msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)" -msgstr "Поднимать прерывание кодека при настройке кодека (необходимо некоторым драйверам)." +msgstr "Поднимать прерывание кодека при настройке кодека (необходимо некоторым драйверам)" msgid "SB Address" msgstr "Адрес SB" @@ -1885,7 +1885,7 @@ msgid "Color (generic)" msgstr "Цветной (стандартный)" msgid "Green Monochrome" -msgstr "Зеленый монохромный" +msgstr "Зелёный монохромный" msgid "Amber Monochrome" msgstr "Янтарный монохромный" From 191503e5292ff2e48083ac238a0932b2dcd0b684 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Thu, 24 Apr 2025 13:30:11 +0300 Subject: [PATCH 0799/1190] Update the Russian translation Update the Russian translation --- src/qt/languages/ru-RU.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index ebc71bb1b..b1c6cf22b 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2059,22 +2059,22 @@ msgid "[Generic] 1989 (3500 RPM)" msgstr "[Стандартный] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "[Стандартный] 1989 (3500 RPM)" +msgstr "[Стандартный] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "[Стандартный] 1989 (3500 RPM)" +msgstr "[Стандартный] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "[Стандартный] 1989 (3500 RPM)" +msgstr "[Стандартный] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "[Стандартный] 1989 (3500 RPM)" +msgstr "[Стандартный] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "[Стандартный] 1989 (3500 RPM)" +msgstr "[Стандартный] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "[Стандартный] 1989 (3500 RPM)" +msgstr "[Стандартный] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "Клон IBM 8514/A (ISA)" From 1c12b8c68fcaf7ba4c61c871b2b218fe8f91dc9e Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:31:20 +0300 Subject: [PATCH 0800/1190] Fixes for broken translation Fixes for broken translation --- src/qt/qt_keybind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_keybind.cpp b/src/qt/qt_keybind.cpp index 8b0f52eab..c7ed894b3 100644 --- a/src/qt/qt_keybind.cpp +++ b/src/qt/qt_keybind.cpp @@ -88,7 +88,7 @@ QKeySequence KeyBinder::BindKey(QWidget* widget, QString CurValue) { KeyBinder kb(widget); - kb.setWindowTitle("Bind Key"); + kb.setWindowTitle(tr("Bind Key")); kb.setFixedSize(kb.minimumSizeHint()); kb.findChild()->setKeySequence(QKeySequence::fromString(CurValue)); kb.setEnabled(true); From d3f32a52f4bbee0e13780ea6b7a00b1147019c03 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:32:21 +0300 Subject: [PATCH 0801/1190] Update the Russian translation Update the Russian translation --- src/qt/languages/ru-RU.po | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index b1c6cf22b..e88f4f0fc 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2162,3 +2162,45 @@ msgstr "Вниз" msgid "Could not load file %1" msgstr "Не удалось загрузить файл %1" + +msgid "Key Bindings:" +msgstr "Привязки клавиш:" + +msgid "Action" +msgstr "Действие" + +msgid "Keybind" +msgstr "Привязка клавиш" + +msgid "Clear binding" +msgstr "Очистить привязку" + +msgid "Bind" +msgstr "Привязка" + +msgid "Bind Key" +msgstr "Привязать клавишу" + +msgid "Enter key combo:" +msgstr "Введите комбинацию клавиш:" + +msgid "Send Control+Alt+Del" +msgstr "Отправить Control+Alt+Del" + +msgid "Send Control+Alt+Escape" +msgstr "Отправить Control+Alt+Escape" + +msgid "Toggle fullscreen" +msgstr "Переключить на полноэкранный режим" + +msgid "Screenshot" +msgstr "Скриншот" + +msgid "Release mouse pointer" +msgstr "Отпустить указатель мыши" + +msgid "Toggle pause" +msgstr "Переключить паузу" + +msgid "Toggle mute" +msgstr "Переключить беззвучный режим" \ No newline at end of file From 57d5bb76282175db1876c49de5d1cfe0e558ba53 Mon Sep 17 00:00:00 2001 From: sharkbyte16 <87238812+sharkbyte16@users.noreply.github.com> Date: Sat, 26 Apr 2025 12:08:37 +0200 Subject: [PATCH 0802/1190] Update nl-NL.po --- src/qt/languages/nl-NL.po | 86 +++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 8ee391957..49a32506b 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -112,7 +112,7 @@ msgid "Hi&DPI scaling" msgstr "Hi&DPI-schaling" msgid "&Fullscreen" -msgstr "&Fullscreen" +msgstr "&Volledig scherm" msgid "Fullscreen &stretch mode" msgstr "Volledig scherm &uitrekmodus" @@ -670,16 +670,16 @@ msgid "Surface images" msgstr "Oppervlakte-images" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "Machine \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/machines. Overschakelen naar een beschikbare machine." +msgstr "Machine \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/machines. Er wordt overgeschakeld naar een beschikbare machine." msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Videokaart \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Overschakel over naar een beschikbare videokaart." +msgstr "Videokaart \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Er wordt overgeschakeld naar een beschikbare videokaart." msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." -msgstr "Videokaart #2 \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. Uitschakel de tweede videokaart." +msgstr "Videokaart #2 \"%hs\" is niet beschikbaar door ontbrekende ROMs in de map roms/video. De tweede videokaart wordt uitgeschakeld." msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." -msgstr "Het apparaat \"%hs\" is niet beschikbaar door ontbrekende ROMs. Negeer het apparaat." +msgstr "Het apparaat \"%hs\" is niet beschikbaar door ontbrekende ROMs. Het apparaat wordt genegeerd." msgid "Machine" msgstr "Machine" @@ -1018,7 +1018,7 @@ msgid "Differencing VHD" msgstr "Verschil-VHD" msgid "(N/A)" -msgstr "(N/A)" +msgstr "(N/B)" msgid "Raw image (.img)" msgstr "Ruw image (.img)" @@ -1054,7 +1054,7 @@ msgid "This could mean that the parent image was modified after the differencing msgstr "Dit kan betekenen dat de bovenliggende image is gewijzigd nadat de verschil-image is gemaakt.\n\nDit kan ook gebeuren als de imagebestanden zijn verplaatst of gekopieerd, of door een fout in het programma waarmee deze schijf is gemaakt.\n\nWil je de tijdstempels herstellen?" msgid "Parent and child disk timestamps do not match" -msgstr "Bovenliggende en onderliggende schijf tijdstempels komen niet overeen" +msgstr "Bovenliggende en onderliggende schijftijdstempels komen niet overeen" msgid "Could not fix VHD timestamp." msgstr "Kan VHD tijdstempel niet herstellen." @@ -1234,7 +1234,7 @@ msgid "Open screenshots folder..." msgstr "Map met schermafbeeldingen openen..." msgid "Apply fullscreen stretch mode when maximized" -msgstr "Pas fullscreen stretchmodus toe wanneer gemaximaliseerd" +msgstr "Schakel de volledig scherm-uitrekmodus in bij maximaliseren" msgid "Cursor/Puck" msgstr "Cursor/Puck" @@ -1291,7 +1291,7 @@ msgid "Browse..." msgstr "Bladeren..." msgid "Couldn't create OpenGL context." -msgstr "Kan OpenGL context niet maken." +msgstr "Kan OpenGL context niet aanmaken." msgid "Couldn't switch to OpenGL context." msgstr "Kan niet overschakelen naar OpenGL context." @@ -1444,7 +1444,7 @@ msgid "Enable backlight" msgstr "Backlight inschakelen" msgid "Invert colors" -msgstr "Kleuren omkeren" +msgstr "Kleuren inverteren" msgid "BIOS size" msgstr "BIOS-grootte" @@ -1810,7 +1810,7 @@ msgid "Five + Wheel" msgstr "Vijf + Wiel" msgid "Five + 2 Wheels" -msgstr "" +msgstr "Vijf + 2 Wielen" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serieel / SMT3(R)V" @@ -1957,13 +1957,13 @@ msgid "Bochs latest" msgstr "Bochs nieuwste" msgid "Mono Non-Interlaced" -msgstr "Mono Non-Interlaced" +msgstr "Mono niet geïnterlaced" msgid "Color Interlaced" msgstr "Kleur interlaced" msgid "Color Non-Interlaced" -msgstr "Kleur non-interlaced" +msgstr "Kleur niet geïnterlaced" msgid "3Dfx Voodoo Graphics" msgstr "3Dfx Voodoo Graphics" @@ -2053,34 +2053,34 @@ msgid "High performance impact" msgstr "Hoge prestatie-impact" msgid "[Generic] RAM Disk (max. speed)" -msgstr "[Generic] RAM-schijf (max. snelheid)" +msgstr "[Generiek] RAM-schijf (max. snelheid)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Generiek] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Generiek] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Generiek] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Generiek] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Generiek] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Generiek] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Generiek] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A-kloon (ISA)" msgid "Vendor" -msgstr "Verkoper" +msgstr "Leverancier" msgid "Generic PC/XT Memory Expansion" msgstr "Generieke PC/XT geheugenuitbreiding" @@ -2095,64 +2095,64 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "TrueType lettertypen in de map \"roms/printer/fonts\" zijn nodig voor de emulatie van de generieke ESC/P dot-matrix-printer." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Multimedia-toetsen blokkeren" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Vraag om bevestiging voor het opslaan van instellingen" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Vraag om bevestiging voor een harde reset" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Vraag om bevestiging voor afsluiten" msgid "Display hotkey message when entering full-screen mode" -msgstr "" +msgstr "Toon een sneltoetsmelding bij het openen van de volledigschermmodus" msgid "Options" -msgstr "" +msgstr "Opties" msgid "Model" -msgstr "" +msgstr "Model" msgid "Model:" -msgstr "" +msgstr "Model:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Initialisatie van de Vulkan-renderer is mislukt." msgid "GLSL Error" -msgstr "" +msgstr "GLSL-fout" msgid "Could not load shader: %1" -msgstr "" +msgstr "Kon de shader niet laden: %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL versie 3.0 of hoger is vereist. Huidige GLSL-versie is %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "Kon de textuur niet laden: %1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "Kon de shader niet compileren:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "Programma niet gelinkt:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "Shaderbeheer" msgid "Shader Configuration" -msgstr "" +msgstr "Shaderconfiguratie" msgid "Add" -msgstr "" +msgstr "Toevoegen" msgid "Move up" -msgstr "" +msgstr "Omhoog verplaatsen" msgid "Move down" -msgstr "" +msgstr "Omlaag verplaatsen" msgid "Could not load file %1" -msgstr "" +msgstr "Kon bestand %1 niet laden" From 34e017bbf4c1af21c2cc86705140d6cc3680f9b9 Mon Sep 17 00:00:00 2001 From: sharkbyte16 <87238812+sharkbyte16@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:03:37 +0200 Subject: [PATCH 0803/1190] Add cmake linux clang and intel Add cmake files for x86_64 linux clang and intel compilers. --- cmake/intel-linux-x86_64.cmake | 20 ++++++++++++++++++++ cmake/llvm-linux-x86_64.cmake | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 cmake/intel-linux-x86_64.cmake create mode 100644 cmake/llvm-linux-x86_64.cmake diff --git a/cmake/intel-linux-x86_64.cmake b/cmake/intel-linux-x86_64.cmake new file mode 100644 index 000000000..a0c3e5d0b --- /dev/null +++ b/cmake/intel-linux-x86_64.cmake @@ -0,0 +1,20 @@ +# +# 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 toolchain file defining GCC compiler flags +# for 64-bit x86 targets. +# +# Authors: David Hrdlička, +# +# Copyright 2021 David Hrdlička. +# + +include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-x86_64.cmake) + +set(CMAKE_C_COMPILER icx) +set(CMAKE_CXX_COMPILER icpx) diff --git a/cmake/llvm-linux-x86_64.cmake b/cmake/llvm-linux-x86_64.cmake new file mode 100644 index 000000000..ccdd7b18e --- /dev/null +++ b/cmake/llvm-linux-x86_64.cmake @@ -0,0 +1,23 @@ +# +# 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 toolchain file defining Clang compiler flags +# for 64-bit x86 targets. +# +# Authors: David Hrdlička, +# dob205 +# +# Copyright 2021 David Hrdlička. +# Copyright 2022 dob205. +# + +include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-x86_64.cmake) + +# Use the GCC-compatible Clang executables in order to use our flags +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) From e076c1051d9cd43936dc170857b24cb99a574a75 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 26 Apr 2025 23:17:32 +0600 Subject: [PATCH 0804/1190] Fix x87_op being outside of structure, fixing crashes in ARM64 NDR --- src/codegen_new/codegen.h | 1 + src/codegen_new/codegen_block.c | 1 + src/codegen_new/codegen_reg.c | 14 ++++++++++++++ src/cpu/386_common.c | 2 -- src/cpu/cpu.h | 4 +++- src/cpu/x86.c | 1 + 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/codegen_new/codegen.h b/src/codegen_new/codegen.h index eecfa249b..0ff6a90d6 100644 --- a/src/codegen_new/codegen.h +++ b/src/codegen_new/codegen.h @@ -306,6 +306,7 @@ struct ir_data_t; x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset); extern void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); extern void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +extern void codegen_check_regs(void); extern int codegen_purge_purgable_list(void); /*Delete a random code block to free memory. This is obviously quite expensive, and diff --git a/src/codegen_new/codegen_block.c b/src/codegen_new/codegen_block.c index a8ea0e06e..ff82384be 100644 --- a/src/codegen_new/codegen_block.c +++ b/src/codegen_new/codegen_block.c @@ -217,6 +217,7 @@ block_free_list_get(void) void codegen_init(void) { + codegen_check_regs(); codegen_allocator_init(); codegen_backend_init(); diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index ba60ab038..75cf25ded 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -226,6 +226,20 @@ reg_is_native_size(ir_reg_t ir_reg) return 0; } +void +codegen_check_regs(void) +{ + int i = 0; + for (i = 0; i < IREG_COUNT; i++) { + if (ireg_data[i].is_volatile == REG_VOLATILE) + continue; + + if (ireg_data[i].p && ((uintptr_t)ireg_data[i].p - (uintptr_t)&cpu_state) >= sizeof(cpu_state)) { + fatal("Register number %d outside cpu_state!\n", i); + } + } +} + void codegen_reg_reset(void) { diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index c6a759d36..2853e3c9a 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -113,8 +113,6 @@ uint8_t is_smint = 0; uint16_t io_port = 0x0000; uint32_t io_val = 0x00000000; -uint32_t x87_op = 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*/ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index b76e2d622..b6f5f593c 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -416,6 +416,8 @@ typedef struct { uint16_t eflags; uint32_t _smbase; + + uint32_t x87_op; } cpu_state_t; #define in_smm cpu_state._in_smm @@ -784,7 +786,7 @@ typedef struct { uint32_t smhr; } cyrix_t; -extern uint32_t x87_op; +#define x87_op cpu_state.x87_op extern uint32_t addr64; extern uint32_t addr64_2; diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 97ae19f3a..a8ab9d866 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -272,6 +272,7 @@ reset_common(int hard) msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw = 0; new_ne = 0; + x87_op = 0; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; ccr4 = 0x85; From 2424e848a7c7ab03671f5b65c599674b830ad6b4 Mon Sep 17 00:00:00 2001 From: Nelson Kerber Hennemann Filho <87081197+nelsonhef@users.noreply.github.com> Date: Sat, 26 Apr 2025 15:27:14 -0300 Subject: [PATCH 0805/1190] Update pt-BR.po Some fixes and added missing translations --- src/qt/languages/pt-BR.po | 86 +++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 8961f11b8..a3e98b625 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -631,7 +631,7 @@ msgid " - PAUSED" msgstr " - PAUSADO" msgid "Press %s to return to windowed mode." -msgstr "Use %s para retornar ao modo janela" +msgstr "Use %s para retornar ao modo janela." msgid "Speed" msgstr "Velocidade" @@ -847,7 +847,7 @@ msgid "86Box v" msgstr "86Box versão" msgid "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." -msgstr "Um emulador de computadores antigos\n\nAutores: 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, e outros.\n\nCom contribuições anteriores de Sarah Walker, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva\n\nLançado sob a Licença Pública Geral GNU, versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." +msgstr "Um emulador de computadores antigos\n\nAutores: 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, e outros.\n\nCom contribuições anteriores de Sarah Walker, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva, Nelson K. Hennemann Filho\n\nLançado sob a Licença Pública Geral GNU, versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." msgid "Hardware not available" msgstr "Hardware não disponível" @@ -967,13 +967,13 @@ msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Imagens HDI ou HDX com um tamanho de setor que não seja 512 não são suportadas." msgid "Disk image file already exists" -msgstr "Esta imagem existe" +msgstr "A imagem de disco já existe" msgid "Please specify a valid file name." msgstr "Digite um nome de arquivo válido." msgid "Disk image created" -msgstr "A imagem foi criada com sucesso" +msgstr "A imagem de disco foi criada" msgid "Make sure the file exists and is readable." msgstr "Certifique-se de que o arquivo existe e é legível." @@ -982,7 +982,7 @@ msgid "Make sure the file is being saved to a writable directory." msgstr "Certifique-se de que o arquivo está sendo salvo em um diretório gravável." msgid "Disk image too large" -msgstr "A imagem do disco é muito grande" +msgstr "A imagem de disco é muito grande" msgid "Remember to partition and format the newly-created drive." msgstr "Lembre-se de particionar e formatar a unidade recém-criada." @@ -1312,16 +1312,16 @@ msgid "This machine might have been moved or copied." msgstr "Essa máquina pode ter sido movida ou copiada." msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure." -msgstr "Para garantir a funcionalidade adequada da rede, o 86Box precisa saber se essa máquina foi movida ou copiada.\n\nSelecione \"A copiei\" se não tiver certeza." +msgstr "Para garantir a funcionalidade adequada da rede, o 86Box precisa saber se essa máquina foi movida ou copiada.\n\nSelecione \"Copiei\" se não tiver certeza." msgid "I Moved It" -msgstr "O movi" +msgstr "Movi" msgid "I Copied It" -msgstr "A copiei" +msgstr "Copiei" msgid "86Box Monitor #" -msgstr "Monitor 86Box " +msgstr "Monitor 86Box #" msgid "No MCA devices." msgstr "Nenhum dispositivo MCA." @@ -1483,7 +1483,7 @@ msgid "MIDI Clockout" msgstr "Saída do relógio MIDI" msgid "SoundFont" -msgstr "Fonte de som" +msgstr "SoundFont" msgid "Output Gain" msgstr "Ganho de saída" @@ -1789,7 +1789,7 @@ msgid "4th Order" msgstr "De 4ª ordem" msgid "7th Order" -msgstr "De 7º order" +msgstr "De 7ª order" msgid "Non-timed (original)" msgstr "Sem cronômetro (original)" @@ -1807,10 +1807,10 @@ msgid "Wheel" msgstr "Roda" msgid "Five + Wheel" -msgstr "Cinco + roda" +msgstr "Cinco + Roda" msgid "Five + 2 Wheels" -msgstr "" +msgstr "Cinco + 2 Rodas" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 Serial / SMT3(R)V" @@ -2035,7 +2035,7 @@ msgid "Baud Rate of Passthrough" msgstr "Taxa de transmissão de passagem" msgid "Named Pipe (Server)" -msgstr "Tubo nomeado (servidor)" +msgstr "Pipe nomeado (servidor)" msgid "Host Serial Passthrough" msgstr "Passagem da porta serial do host" @@ -2053,28 +2053,28 @@ msgid "High performance impact" msgstr "Alto impacto no desempenho" msgid "[Generic] RAM Disk (max. speed)" -msgstr "[Generic] Disco RAM (velocidade máxima)" +msgstr "[Genérico] Disco RAM (velocidade máxima)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Genérico] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Genérico] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Genérico] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Genérico] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Genérico] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Genérico] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Genérico] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "Clone IBM 8514/A (ISA)" @@ -2095,64 +2095,64 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Inibir teclas multimídia" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Perguntar antes de salvar configurações" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Perguntar antes de reinicialização completa" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Perguntar antes de sair" msgid "Display hotkey message when entering full-screen mode" -msgstr "" +msgstr "Mostrar mensagem de atalho quando entrar em tela cheia" msgid "Options" -msgstr "" +msgstr "Opções" msgid "Model" -msgstr "" +msgstr "Modelo" msgid "Model:" -msgstr "" +msgstr "Modelo:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Falha ao inicializar o renderizador Vulkan." msgid "GLSL Error" -msgstr "" +msgstr "Erro GLSL" msgid "Could not load shader: %1" -msgstr "" +msgstr "Impossível carregar o shader: %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL versão 3.0 ou superior é exigido. Versão atual GLSL é %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "Impossível carregar a textura: %1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "Impossível compilar o shader:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "Programa não linkado:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "Gerenciador de Shader" msgid "Shader Configuration" -msgstr "" +msgstr "Configuração de Shader" msgid "Add" -msgstr "" +msgstr "Adicionar" msgid "Move up" -msgstr "" +msgstr "Mover para cima" msgid "Move down" -msgstr "" +msgstr "Mover para baixo" msgid "Could not load file %1" -msgstr "" +msgstr "Impossível carregar arquivo %1" From 388fcb3046b19eef209620b6920a8635e835d433 Mon Sep 17 00:00:00 2001 From: Nelson Kerber Hennemann Filho <87081197+nelsonhef@users.noreply.github.com> Date: Sat, 26 Apr 2025 15:36:47 -0300 Subject: [PATCH 0806/1190] Update 2 pt-BR.po Added strings and translations for the new key bindings settings --- src/qt/languages/pt-BR.po | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index a3e98b625..4f06e0d85 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2156,3 +2156,45 @@ msgstr "Mover para baixo" msgid "Could not load file %1" msgstr "Impossível carregar arquivo %1" + +msgid "Key Bindings:" +msgstr "Atalhos:" + +msgid "Action" +msgstr "Ação" + +msgid "Keybind" +msgstr "Atalho" + +msgid "Clear binding" +msgstr "Limpar atalho" + +msgid "Bind" +msgstr "Vincular" + +msgid "Bind Key" +msgstr "Vincular tecla" + +msgid "Enter key combo:" +msgstr "Pressione combinação de teclas:" + +msgid "Send Control+Alt+Del" +msgstr "Enviar Control+Alt+Del" + +msgid "Send Control+Alt+Escape" +msgstr "Enviar Control+Alt+Escape" + +msgid "Toggle fullscreen" +msgstr "Alternar tela cheia" + +msgid "Screenshot" +msgstr "Captura de tela" + +msgid "Release mouse pointer" +msgstr "Liberar ponteiro do mouse" + +msgid "Toggle pause" +msgstr "Alternar pausa" + +msgid "Toggle mute" +msgstr "Alternar mudo" From 98e3cdf1cf24f18ccc293806082146aa5b71b2e8 Mon Sep 17 00:00:00 2001 From: Nelson Kerber Hennemann Filho <87081197+nelsonhef@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:18:31 -0300 Subject: [PATCH 0807/1190] Update 3 pt-BR.po Fix minor typo --- src/qt/languages/pt-BR.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 4f06e0d85..e33630ccf 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -1789,7 +1789,7 @@ msgid "4th Order" msgstr "De 4ª ordem" msgid "7th Order" -msgstr "De 7ª order" +msgstr "De 7ª ordem" msgid "Non-timed (original)" msgstr "Sem cronômetro (original)" From f563b73768b8705d1adb21db98f635276fe24b7e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 27 Apr 2025 17:52:53 +0200 Subject: [PATCH 0808/1190] Warn on deprecated usage. --- src/86box.c | 98 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/src/86box.c b/src/86box.c index 57abb12a6..66d9afa00 100644 --- a/src/86box.c +++ b/src/86box.c @@ -586,6 +586,55 @@ delete_nvr_file(uint8_t flash) extern void device_find_all_descs(void); +static void +pc_show_usage(char *s) +{ + char p[4096] = { 0 }; + + sprintf(p, + "\n%sUsage: 86box [options] [cfg-file]\n\n" + "Valid options are:\n\n" + "-? or --help\t\t\t- show this information\n" + "-C or --config path\t\t- set 'path' to be config file\n" +#ifdef _WIN32 + "-D or --debug\t\t\t- force debug output logging\n" +#endif +#if 0 + "-E or --nographic\t\t- forces the old behavior\n" +#endif + "-F or --fullscreen\t\t- start in fullscreen mode\n" + "-G or --lang langid\t\t- start with specified language\n" + "\t\t\t\t (e.g. en-US, or system)\n" +#ifdef _WIN32 + "-H or --hwnd id,hwnd\t\t- sends back the main dialog's hwnd\n" +#endif + "-I or --image d:path\t\t- load 'path' as floppy image on drive d\n" +#ifdef USE_INSTRUMENT + "-J or --instrument name\t- set 'name' to be the profiling instrument\n" +#endif + "-L or --logfile pat\t\t- set 'path' to be the logfile\n" + "-M or --missing\t\t- dump missing machines and video cards\n" + "-N or --noconfirm\t\t- do not ask for confirmation on quit\n" + "-P or --vmpath path\t\t- set 'path' to be root for vm\n" + "-R or --rompath path\t\t- set 'path' to be ROM path\n" +#ifndef USE_SDL_UI + "-S or --settings\t\t\t- show only the settings dialog\n" +#endif + "-T or --testmode\t\t- test mode: execute the test mode entry\n" + "\t\t\t\t point on init/hard reset\n" + "-V or --vmname name\t\t- overrides the name of the running VM\n" + "-W or --nohook\t\t- disables keyboard hook\n" + "\t\t\t\t (compatibility-only outside Windows)\n" + "-X or --clear what\t\t- clears the 'what' (cmos/flash/both)\n" + "-Y or --donothing\t\t- do not show any UI or run the emulation\n" + "-Z or --lastvmpath\t\t- the last parameter is VM path rather\n" + "\t\t\t\t than config\n" + "\nA config file can be specified. If none is, the default file will be used.\n", + (s == NULL) ? "" : s); + + ui_msgbox(MBX_ANSI | ((s == NULL) ? MBX_INFO : MBX_WARNING), p); +} + /* * Perform initial startup of the PC. * @@ -609,6 +658,7 @@ pc_init(int argc, char *argv[]) time_t now; int c; int lvmp = 0; + int deprecated = 1; #ifdef ENABLE_NG int ng = 0; #endif @@ -666,44 +716,7 @@ usage: } } - ui_msgbox(MBX_INFO, L"\nUsage: 86box [options] [cfg-file]\n\n" - "Valid options are:\n\n" - "-? or --help\t\t\t- show this information\n" - "-C or --config path\t\t- set 'path' to be config file\n" -#ifdef _WIN32 - "-D or --debug\t\t\t- force debug output logging\n" -#endif -#if 0 - "-E or --nographic\t\t- forces the old behavior\n" -#endif - "-F or --fullscreen\t\t- start in fullscreen mode\n" - "-G or --lang langid\t\t- start with specified language\n" - "\t\t\t\t (e.g. en-US, or system)\n" -#ifdef _WIN32 - "-H or --hwnd id,hwnd\t\t- sends back the main dialog's hwnd\n" -#endif - "-I or --image d:path\t\t- load 'path' as floppy image on drive d\n" -#ifdef USE_INSTRUMENT - "-J or --instrument name\t- set 'name' to be the profiling instrument\n" -#endif - "-L or --logfile pat\t\t- set 'path' to be the logfile\n" - "-M or --missing\t\t- dump missing machines and video cards\n" - "-N or --noconfirm\t\t- do not ask for confirmation on quit\n" - "-P or --vmpath path\t\t- set 'path' to be root for vm\n" - "-R or --rompath path\t\t- set 'path' to be ROM path\n" -#ifndef USE_SDL_UI - "-S or --settings\t\t\t- show only the settings dialog\n" -#endif - "-T or --testmode\t\t- test mode: execute the test mode entry\n" - "\t\t\t\t point on init/hard reset\n" - "-V or --vmname name\t\t- overrides the name of the running VM\n" - "-W or --nohook\t\t- disables keyboard hook\n" - "\t\t\t\t (compatibility-only outside Windows)\n" - "-X or --clear what\t\t- clears the 'what' (cmos/flash/both)\n" - "-Y or --donothing\t\t- do not show any UI or run the emulation\n" - "-Z or --lastvmpath\t\t- the last parameter is VM path rather\n" - "\t\t\t\t than config\n" - "\nA config file can be specified. If none is, the default file will be used.\n"); + pc_show_usage(NULL); return 0; } else if (!strcasecmp(argv[c], "--lastvmpath") || !strcasecmp(argv[c], "-Z")) { lvmp = 1; @@ -730,6 +743,7 @@ usage: goto usage; ppath = argv[++c]; + deprecated = 0; } else if (!strcasecmp(argv[c], "--rompath") || !strcasecmp(argv[c], "-R")) { if ((c + 1) == argc) goto usage; @@ -741,6 +755,7 @@ usage: goto usage; cfg = argv[++c]; + deprecated = 0; } else if (!strcasecmp(argv[c], "--image") || !strcasecmp(argv[c], "-I")) { if ((c + 1) == argc) goto usage; @@ -839,11 +854,18 @@ usage: ppath = argv[c++]; else cfg = argv[c++]; + + deprecated = 0; } if (c != argc) goto usage; + if (deprecated) + pc_show_usage("Running 86Box without a specified VM path and/or configuration\n" + "file has been deprected. Please specify one or use a manager\n" + "(Avalonia 86 is recommended).\n\n"); + path_slash(usr_path); path_slash(rom_path); From 5b4db319bf53e0984568c168fc56e090597846d1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 27 Apr 2025 18:50:45 +0200 Subject: [PATCH 0809/1190] Opcode D6 is now an alias of opcode D7 (XLAT) on NEC Vx0, closes #5516. --- src/cpu/808x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index e98b7de3d..be0d5e6cc 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -3438,10 +3438,13 @@ execx86(int cycs) set_pzs(8); break; case 0xD6: /*SALC*/ - wait(1, 0); - AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; - wait(1, 0); - break; + if (!is_nec) { + wait(1, 0); + AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; + wait(1, 0); + break; + } + fallthrough; case 0xD7: /*XLATB*/ cpu_state.eaaddr = (BX + AL) & 0xffff; access(4, 8); From 9b93e71b23f9e0f539387ce22c72e0d5ab3c68ce Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 27 Apr 2025 18:57:21 +0200 Subject: [PATCH 0810/1190] #included the missing plat_fallthrough.h. --- src/cpu/808x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index be0d5e6cc..dda688ee1 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -38,6 +38,7 @@ #include <86box/ppi.h> #include <86box/timer.h> #include <86box/gdbstub.h> +#include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> /* Is the CPU 8088 or 8086. */ From d0f682ea08ceed2726fe3ee3eb6a604c50795470 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 28 Apr 2025 04:37:58 +0200 Subject: [PATCH 0811/1190] Print help to console on non-Windows OS'es unless it's the deprecaption warning. --- src/86box.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/86box.c b/src/86box.c index 66d9afa00..d96a571c0 100644 --- a/src/86box.c +++ b/src/86box.c @@ -632,7 +632,14 @@ pc_show_usage(char *s) "\nA config file can be specified. If none is, the default file will be used.\n", (s == NULL) ? "" : s); +#ifdef _WIN32 ui_msgbox(MBX_ANSI | ((s == NULL) ? MBX_INFO : MBX_WARNING), p); +#else + if (s == NULL) + pclog(p); + else + ui_msgbox(MBX_ANSI | MBX_WARNING, p); +#endif } /* From 94a68a869834ec92a16b66fb7ee38c31a4cb7be5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 28 Apr 2025 14:26:49 +0600 Subject: [PATCH 0812/1190] Add Mouse Systems Bus Mouse --- src/device/mouse.c | 27 ++++++----- src/device/mouse_serial.c | 97 +++++++++++++++++++++++++++++++++++--- src/device/serial.c | 31 ++++++++---- src/include/86box/mouse.h | 2 + src/include/86box/serial.h | 2 +- 5 files changed, 130 insertions(+), 29 deletions(-) diff --git a/src/device/mouse.c b/src/device/mouse.c index f7d8c9861..0bf87934d 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -83,23 +83,24 @@ static const device_t mouse_internal_device = { static mouse_t mouse_devices[] = { // clang-format off - { &mouse_none_device }, - { &mouse_internal_device }, - { &mouse_logibus_device }, - { &mouse_msinport_device }, + { &mouse_none_device }, + { &mouse_internal_device }, + { &mouse_logibus_device }, + { &mouse_msinport_device }, #ifdef USE_GENIBUS - { &mouse_genibus_device }, + { &mouse_genibus_device }, #endif - { &mouse_mssystems_device }, - { &mouse_msserial_device }, - { &mouse_ltserial_device }, - { &mouse_ps2_device }, + { &mouse_mssystems_device }, + { &mouse_mssystems_bus_device }, + { &mouse_msserial_device }, + { &mouse_ltserial_device }, + { &mouse_ps2_device }, #ifdef USE_WACOM - { &mouse_wacom_device }, - { &mouse_wacom_artpad_device }, + { &mouse_wacom_device }, + { &mouse_wacom_artpad_device }, #endif - { &mouse_mtouch_device }, - { NULL } + { &mouse_mtouch_device }, + { NULL } // clang-format on }; diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 8ed4865cd..24d7ae853 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -833,10 +833,6 @@ sermouse_close(void *priv) { mouse_t *dev = (mouse_t *) priv; - /* Detach serial port from the mouse. */ - if (dev && dev->serial && dev->serial->sd) - memset(dev->serial->sd, 0, sizeof(serial_device_t)); - free(dev); } @@ -849,6 +845,11 @@ sermouse_init(const device_t *info) void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data); void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period); + if (info->local == MOUSE_TYPE_MSYSTEMSB) { + uintptr_t irqbase = ((device_get_config_int("irq") << 16) | (device_get_config_hex16("addr") << 20)) | ns16450_device.local; + device_add_params(&ns16450_device, (void*)irqbase); + } + dev = (mouse_t *) calloc(1, sizeof(mouse_t)); dev->name = info->name; dev->but = device_get_config_int("buttons"); @@ -862,7 +863,7 @@ sermouse_init(const device_t *info) if (dev->but > 2) dev->flags |= FLAG_3BTN; - if (info->local == MOUSE_TYPE_MSYSTEMS) { + if (info->local == MOUSE_TYPE_MSYSTEMS || info->local == MOUSE_TYPE_MSYSTEMSB) { dev->format = 0; dev->type = info->local; dev->id_len = 1; @@ -893,7 +894,7 @@ sermouse_init(const device_t *info) } } - dev->port = device_get_config_int("port"); + dev->port = (info->local == MOUSE_TYPE_MSYSTEMSB) ? SERIAL_MAX : device_get_config_int("port"); /* Attach a serial port to the mouse. */ rcr_callback = dev->rts_toggle ? sermouse_callback : NULL; @@ -968,6 +969,76 @@ static const device_config_t msssermouse_config[] = { // clang-format on }; +static const device_config_t mssbusmouse_config[] = { + // clang-format off + { + .name = "addr", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x238, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x338", .value = 0x338 }, + { .description = "0x238", .value = 0x238 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 5, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 15", .value = 15 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "rts_toggle", + .description = "RTS toggle", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on + }; + static const device_config_t mssermouse_config[] = { // clang-format off { @@ -1087,6 +1158,20 @@ const device_t mouse_mssystems_device = { .config = msssermouse_config }; +const device_t mouse_mssystems_bus_device = { + .name = "Mouse Systems Bus Mouse", + .internal_name = "mssystems_bus", + .flags = DEVICE_ISA, + .local = MOUSE_TYPE_MSYSTEMSB, + .init = sermouse_init, + .close = sermouse_close, + .reset = NULL, + .available = NULL, + .speed_changed = sermouse_speed_changed, + .force_redraw = NULL, + .config = mssbusmouse_config +}; + const device_t mouse_msserial_device = { .name = "Microsoft Serial Mouse", .internal_name = "msserial", diff --git a/src/device/serial.c b/src/device/serial.c index deb97225a..c00cfad10 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -38,7 +38,7 @@ #include <86box/serial.h> #include <86box/mouse.h> -serial_port_t com_ports[SERIAL_MAX]; +serial_port_t com_ports[SERIAL_MAX + 1]; enum { SERIAL_INT_LSR = 1, @@ -53,7 +53,7 @@ enum { void serial_update_ints(serial_t *dev); static int next_inst = 0; -static serial_device_t serial_devices[SERIAL_MAX]; +static serial_device_t serial_devices[SERIAL_MAX + 1]; static void serial_xmit_d_empty_evt(void *priv); @@ -884,10 +884,10 @@ serial_close(void *priv) { serial_t *dev = (serial_t *) priv; - next_inst--; - - if (com_ports[dev->inst].enabled) + if (dev->sd) { + memset(dev->sd, 0, sizeof(serial_device_t)); fifo_close(dev->rcvr_fifo); + } free(dev); } @@ -897,7 +897,7 @@ serial_reset(void *priv) { serial_t *dev = (serial_t *) priv; - if (com_ports[dev->inst].enabled) { + if (dev->sd) { timer_disable(&dev->transmit_timer); timer_disable(&dev->timeout_timer); timer_disable(&dev->receive_timer); @@ -930,16 +930,28 @@ static void * serial_init(const device_t *info) { serial_t *dev = (serial_t *) calloc(1, sizeof(serial_t)); + int orig_inst = next_inst; + + if (info->local & 0xFFF00000) { + next_inst = SERIAL_MAX; + } dev->inst = next_inst; - if (com_ports[next_inst].enabled) { + if (com_ports[next_inst].enabled || (info->local & 0xFFF00000)) { serial_log("Adding serial port %i...\n", next_inst); dev->type = info->local; memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t)); dev->sd = &(serial_devices[next_inst]); dev->sd->serial = dev; - if (next_inst == 6) + + if (info->local & 0xFFF00000) { + dev->base_address = info->local >> 20; + dev->irq = (info->local >> 16) & 0xF; + io_sethandler(dev->base_address, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, dev); + next_inst = orig_inst; + } + else if (next_inst == 6) serial_setup(dev, COM7_ADDR, COM7_IRQ); else if (next_inst == 5) serial_setup(dev, COM6_ADDR, COM6_IRQ); @@ -984,7 +996,8 @@ serial_init(const device_t *info) serial_reset_port(dev); } - next_inst++; + if (!(info->local & 0xFFF00000)) + next_inst++; return dev; } diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index 333849846..8dd3bad2d 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -41,6 +41,7 @@ #define MOUSE_TYPE_PS2 11 /* PS/2 series Bus Mouse */ #define MOUSE_TYPE_WACOM 12 /* WACOM tablet */ #define MOUSE_TYPE_WACOMARTP 13 /* WACOM tablet (ArtPad) */ +#define MOUSE_TYPE_MSYSTEMSB 14 /* Mouse Systems bus mouse */ #define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */ @@ -68,6 +69,7 @@ extern const device_t mouse_msinport_device; extern const device_t mouse_genibus_device; # endif extern const device_t mouse_mssystems_device; +extern const device_t mouse_mssystems_bus_device; extern const device_t mouse_msserial_device; extern const device_t mouse_ltserial_device; extern const device_t mouse_ps2_device; diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index 31c77ce5a..c6259d7bc 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -116,7 +116,7 @@ typedef struct serial_port_s { uint8_t enabled; } serial_port_t; -extern serial_port_t com_ports[SERIAL_MAX]; +extern serial_port_t com_ports[SERIAL_MAX + 1]; extern serial_t *serial_attach_ex(int port, void (*rcr_callback)(struct serial_s *serial, void *priv), From 6fc6a16be6c8a408a3ae2f1d4729f60b20e18da8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 28 Apr 2025 11:18:57 +0200 Subject: [PATCH 0813/1190] Fixed a few minor things with how the Mouse Systems Bus Mouse as added. --- src/86box.c | 2 +- src/config.c | 6 +++--- src/device/mouse_serial.c | 11 ++++++++--- src/device/serial.c | 18 ++++++++---------- src/device/serial_passthrough.c | 2 +- src/include/86box/86box.h | 2 +- src/include/86box/serial.h | 2 +- src/include/86box/serial_passthrough.h | 2 +- src/qt/qt_settingsports.cpp | 4 ++-- 9 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/86box.c b/src/86box.c index d96a571c0..cd573d98f 100644 --- a/src/86box.c +++ b/src/86box.c @@ -174,7 +174,7 @@ int force_43 = 0; /* (C) video * int video_filter_method = 1; /* (C) video */ int video_vsync = 0; /* (C) video */ int video_framerate = -1; /* (C) video */ -bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of +bool serial_passthrough_enabled[SERIAL_MAX - 1] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of pass-through for serial ports */ int bugger_enabled = 0; /* (C) enable ISAbugger */ int novell_keycard_enabled = 0; /* (C) enable Novell NetWare 2.x key card emulation. */ diff --git a/src/config.c b/src/config.c index 98923d9cf..52a80763a 100644 --- a/src/config.c +++ b/src/config.c @@ -746,7 +746,7 @@ load_ports(void) char temp[512]; memset(temp, 0, sizeof(temp)); - for (int c = 0; c < SERIAL_MAX; c++) { + for (int c = 0; c < (SERIAL_MAX - 1); c++) { sprintf(temp, "serial%d_enabled", c + 1); com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1); @@ -1839,7 +1839,7 @@ config_load(void) com_ports[0].enabled = 1; com_ports[1].enabled = 1; - for (i = 2; i < SERIAL_MAX; i++) + for (i = 2; i < (SERIAL_MAX - 1); i++) com_ports[i].enabled = 0; lpt_ports[0].enabled = 1; @@ -2459,7 +2459,7 @@ save_ports(void) ini_section_t cat = ini_find_or_create_section(config, "Ports (COM & LPT)"); char temp[512]; - for (int c = 0; c < SERIAL_MAX; c++) { + for (int c = 0; c < (SERIAL_MAX - 1); c++) { sprintf(temp, "serial%d_enabled", c + 1); if (((c < 2) && com_ports[c].enabled) || ((c >= 2) && !com_ports[c].enabled)) ini_section_delete_var(cat, temp); diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 24d7ae853..7505cf3a3 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -843,10 +843,13 @@ sermouse_init(const device_t *info) mouse_t *dev; void (*rcr_callback)(struct serial_s *serial, void *priv); void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data); - void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period); + void (*transmit_period_callback)(struct serial_s *serial, void *priv, + double transmit_period); if (info->local == MOUSE_TYPE_MSYSTEMSB) { - uintptr_t irqbase = ((device_get_config_int("irq") << 16) | (device_get_config_hex16("addr") << 20)) | ns16450_device.local; + uintptr_t irqbase = ((device_get_config_int("irq") << 16) | + (device_get_config_hex16("addr") << 20)) | + ns16450_device.local; device_add_params(&ns16450_device, (void*)irqbase); } @@ -894,7 +897,7 @@ sermouse_init(const device_t *info) } } - dev->port = (info->local == MOUSE_TYPE_MSYSTEMSB) ? SERIAL_MAX : device_get_config_int("port"); + dev->port = (info->local == MOUSE_TYPE_MSYSTEMSB) ? (SERIAL_MAX - 1) : device_get_config_int("port"); /* Attach a serial port to the mouse. */ rcr_callback = dev->rts_toggle ? sermouse_callback : NULL; @@ -982,6 +985,8 @@ static const device_config_t mssbusmouse_config[] = { .selection = { { .description = "0x338", .value = 0x338 }, { .description = "0x238", .value = 0x238 }, + { .description = "0x3f8", .value = 0x3f8 }, + { .description = "0x2f8", .value = 0x2f8 }, { .description = "" } }, .bios = { { 0 } } diff --git a/src/device/serial.c b/src/device/serial.c index c00cfad10..71be924c1 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -38,7 +38,7 @@ #include <86box/serial.h> #include <86box/mouse.h> -serial_port_t com_ports[SERIAL_MAX + 1]; +serial_port_t com_ports[SERIAL_MAX]; enum { SERIAL_INT_LSR = 1, @@ -53,7 +53,7 @@ enum { void serial_update_ints(serial_t *dev); static int next_inst = 0; -static serial_device_t serial_devices[SERIAL_MAX + 1]; +static serial_device_t serial_devices[SERIAL_MAX]; static void serial_xmit_d_empty_evt(void *priv); @@ -932,9 +932,8 @@ serial_init(const device_t *info) serial_t *dev = (serial_t *) calloc(1, sizeof(serial_t)); int orig_inst = next_inst; - if (info->local & 0xFFF00000) { - next_inst = SERIAL_MAX; - } + if (info->local & 0xFFF00000) + next_inst = SERIAL_MAX - 1; dev->inst = next_inst; @@ -945,13 +944,12 @@ serial_init(const device_t *info) dev->sd = &(serial_devices[next_inst]); dev->sd->serial = dev; - if (info->local & 0xFFF00000) { + if (info->local & 0xfff00000) { dev->base_address = info->local >> 20; dev->irq = (info->local >> 16) & 0xF; io_sethandler(dev->base_address, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, dev); next_inst = orig_inst; - } - else if (next_inst == 6) + } else if (next_inst == 6) serial_setup(dev, COM7_ADDR, COM7_IRQ); else if (next_inst == 5) serial_setup(dev, COM6_ADDR, COM6_IRQ); @@ -996,7 +994,7 @@ serial_init(const device_t *info) serial_reset_port(dev); } - if (!(info->local & 0xFFF00000)) + if (!(info->local & 0xfff00000)) next_inst++; return dev; @@ -1011,7 +1009,7 @@ serial_set_next_inst(int ni) void serial_standalone_init(void) { - while (next_inst < SERIAL_MAX) + while (next_inst < (SERIAL_MAX - 1)) device_add_inst(&ns8250_device, next_inst + 1); }; diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index 3ad969006..25db29096 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -54,7 +54,7 @@ serial_passthrough_log(const char *fmt, ...) void serial_passthrough_init(void) { - for (uint8_t c = 0; c < SERIAL_MAX; c++) { + for (uint8_t c = 0; c < (SERIAL_MAX - 1); c++) { if (serial_passthrough_enabled[c]) { /* Instance n for COM n */ device_add_inst(&serial_passthrough_device, c + 1); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 7f7723bba..e19665535 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -27,7 +27,7 @@ /* Configuration values. */ #define GFXCARD_MAX 2 -#define SERIAL_MAX 7 +#define SERIAL_MAX 8 #define PARALLEL_MAX 4 #define SCREEN_RES_X 640 #define SCREEN_RES_Y 480 diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index c6259d7bc..31c77ce5a 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -116,7 +116,7 @@ typedef struct serial_port_s { uint8_t enabled; } serial_port_t; -extern serial_port_t com_ports[SERIAL_MAX + 1]; +extern serial_port_t com_ports[SERIAL_MAX]; extern serial_t *serial_attach_ex(int port, void (*rcr_callback)(struct serial_s *serial, void *priv), diff --git a/src/include/86box/serial_passthrough.h b/src/include/86box/serial_passthrough.h index 7ca6479d6..c5454194a 100644 --- a/src/include/86box/serial_passthrough.h +++ b/src/include/86box/serial_passthrough.h @@ -55,7 +55,7 @@ typedef struct serial_passthrough_s { void *backend_priv; /* Private platform backend data */ } serial_passthrough_t; -extern bool serial_passthrough_enabled[SERIAL_MAX]; +extern bool serial_passthrough_enabled[SERIAL_MAX - 1]; extern const device_t serial_passthrough_device; extern void serial_passthrough_init(void); diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index f68106dc9..2b57a683c 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -58,7 +58,7 @@ SettingsPorts::save() lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; } - for (int i = 0; i < SERIAL_MAX; i++) { + for (int i = 0; i < (SERIAL_MAX - 1); i++) { auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); if (checkBox != NULL) @@ -118,7 +118,7 @@ SettingsPorts::onCurrentMachineChanged(int machineId) cbox[i]->setEnabled(lpt_ports[i].enabled > 0); } - for (int i = 0; i < SERIAL_MAX; i++) { + for (int i = 0; i < (SERIAL_MAX - 1); i++) { auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); auto *buttonPass = findChild(QString("pushButtonSerialPassThru%1").arg(i + 1)); From aa940316ffe6446fcadfd923b85af9a1929f20ed Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 28 Apr 2025 18:00:49 +0500 Subject: [PATCH 0814/1190] qt: For device config dialogs, default to the settings dialog as the parent Fixes (somehow) controls being non-interactable when no parent dialog is passed and 86Box is running in settings-only mode --- src/qt/qt_deviceconfig.hpp | 2 +- src/qt/qt_settingsdisplay.cpp | 16 ++++++++-------- src/qt/qt_settingsinput.cpp | 2 +- src/qt/qt_settingsmachine.cpp | 2 +- src/qt/qt_settingsnetwork.cpp | 8 ++++---- src/qt/qt_settingsotherperipherals.cpp | 10 +++++----- src/qt/qt_settingsports.cpp | 14 +++++++------- src/qt/qt_settingssound.cpp | 18 ++++++++---------- src/qt/qt_settingsstoragecontrollers.cpp | 18 +++++++++--------- 9 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/qt/qt_deviceconfig.hpp b/src/qt/qt_deviceconfig.hpp index a16c152a6..a5214111f 100644 --- a/src/qt/qt_deviceconfig.hpp +++ b/src/qt/qt_deviceconfig.hpp @@ -23,7 +23,7 @@ public: ~DeviceConfig() override; static void ConfigureDevice(const _device_ *device, int instance = 0, - Settings *settings = nullptr); + Settings *settings = qobject_cast(Settings::settings)); static QString DeviceName(const _device_ *device, const char *internalName, int bus); private: diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index b7a930711..fbe6ab5cc 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -122,22 +122,22 @@ SettingsDisplay::on_pushButtonConfigure_clicked() auto *device = video_card_getdevice(videoCard); if (videoCard == VID_INTERNAL) device = machine_get_vid_device(machineId); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device); } void SettingsDisplay::on_pushButtonConfigureVoodoo_clicked() { - DeviceConfig::ConfigureDevice(&voodoo_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&voodoo_device); } void SettingsDisplay::on_pushButtonConfigure8514_clicked() { if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { - DeviceConfig::ConfigureDevice(&ibm8514_mca_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&ibm8514_mca_device); } else { - DeviceConfig::ConfigureDevice(&gen8514_isa_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&gen8514_isa_device); } } @@ -145,16 +145,16 @@ void SettingsDisplay::on_pushButtonConfigureXga_clicked() { if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { - DeviceConfig::ConfigureDevice(&xga_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&xga_device); } else { - DeviceConfig::ConfigureDevice(&xga_isa_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&xga_isa_device); } } void SettingsDisplay::on_pushButtonConfigureDa2_clicked() { - DeviceConfig::ConfigureDevice(&ps55da2_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&ps55da2_device); } void @@ -298,5 +298,5 @@ void SettingsDisplay::on_pushButtonConfigureSecondary_clicked() { auto *device = video_card_getdevice(ui->comboBoxVideoSecondary->currentData().toInt()); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device); } diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 695dc43e9..f3729ab3f 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -274,7 +274,7 @@ void SettingsInput::on_pushButtonConfigureMouse_clicked() { int mouseId = ui->comboBoxMouse->currentData().toInt(); - DeviceConfig::ConfigureDevice(mouse_get_device(mouseId), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(mouse_get_device(mouseId)); } static int diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 939cd9eb2..8548ca8cc 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -347,7 +347,7 @@ SettingsMachine::on_pushButtonConfigure_clicked() // deviceconfig_inst_open int machineId = ui->comboBoxMachine->currentData().toInt(); const auto *device = machine_get_device(machineId); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device); } void SettingsMachine::on_checkBoxFPUSoftfloat_stateChanged(int state) { diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 9a53411d5..1ea48ee6b 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -240,7 +240,7 @@ SettingsNetwork::on_pushButtonConf1_clicked() auto *device = network_card_getdevice(netCard); if (netCard == NET_INTERNAL) device = machine_get_net_device(machineId); - DeviceConfig::ConfigureDevice(device, 1, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 1); } void @@ -248,7 +248,7 @@ SettingsNetwork::on_pushButtonConf2_clicked() { int netCard = ui->comboBoxNIC2->currentData().toInt(); auto *device = network_card_getdevice(netCard); - DeviceConfig::ConfigureDevice(device, 2, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 2); } void @@ -256,7 +256,7 @@ SettingsNetwork::on_pushButtonConf3_clicked() { int netCard = ui->comboBoxNIC3->currentData().toInt(); auto *device = network_card_getdevice(netCard); - DeviceConfig::ConfigureDevice(device, 3, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 3); } void @@ -264,5 +264,5 @@ SettingsNetwork::on_pushButtonConf4_clicked() { int netCard = ui->comboBoxNIC4->currentData().toInt(); auto *device = network_card_getdevice(netCard); - DeviceConfig::ConfigureDevice(device, 4, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 4); } diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index b780dc1a6..e1920bf47 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -159,7 +159,7 @@ SettingsOtherPeripherals::on_comboBoxRTC_currentIndexChanged(int index) void SettingsOtherPeripherals::on_pushButtonConfigureRTC_clicked() { - DeviceConfig::ConfigureDevice(isartc_get_device(ui->comboBoxRTC->currentData().toInt()), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(isartc_get_device(ui->comboBoxRTC->currentData().toInt())); } void @@ -174,7 +174,7 @@ SettingsOtherPeripherals::on_comboBoxCard1_currentIndexChanged(int index) void SettingsOtherPeripherals::on_pushButtonConfigureCard1_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard1->currentData().toInt()), 1, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard1->currentData().toInt()), 1); } void @@ -189,7 +189,7 @@ SettingsOtherPeripherals::on_comboBoxCard2_currentIndexChanged(int index) void SettingsOtherPeripherals::on_pushButtonConfigureCard2_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard2->currentData().toInt()), 2, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard2->currentData().toInt()), 2); } void @@ -204,7 +204,7 @@ SettingsOtherPeripherals::on_comboBoxCard3_currentIndexChanged(int index) void SettingsOtherPeripherals::on_pushButtonConfigureCard3_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard3->currentData().toInt()), 3, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard3->currentData().toInt()), 3); } void @@ -219,7 +219,7 @@ SettingsOtherPeripherals::on_comboBoxCard4_currentIndexChanged(int index) void SettingsOtherPeripherals::on_pushButtonConfigureCard4_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()), 4, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()), 4); } void diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 2b57a683c..7e8f2aeda 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -254,43 +254,43 @@ SettingsPorts::on_checkBoxSerialPassThru7_stateChanged(int state) void SettingsPorts::on_pushButtonSerialPassThru1_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1); } void SettingsPorts::on_pushButtonSerialPassThru2_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2); } void SettingsPorts::on_pushButtonSerialPassThru3_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3); } void SettingsPorts::on_pushButtonSerialPassThru4_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4); } #if 0 void SettingsPorts::on_pushButtonSerialPassThru5_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5); } void SettingsPorts::on_pushButtonSerialPassThru6_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6); } void SettingsPorts::on_pushButtonSerialPassThru7_clicked() { - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7); } #endif diff --git a/src/qt/qt_settingssound.cpp b/src/qt/qt_settingssound.cpp index 3e1240888..e49e1ae27 100644 --- a/src/qt/qt_settingssound.cpp +++ b/src/qt/qt_settingssound.cpp @@ -232,7 +232,7 @@ SettingsSound::on_pushButtonConfigureSoundCard1_clicked() if (sndCard == SOUND_INTERNAL) device = machine_get_snd_device(machineId); - DeviceConfig::ConfigureDevice(device, 1, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 1); } void @@ -252,7 +252,7 @@ SettingsSound::on_pushButtonConfigureSoundCard2_clicked() { int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); const device_t *device = sound_card_getdevice(sndCard); - DeviceConfig::ConfigureDevice(device, 2, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 2); } void @@ -273,7 +273,7 @@ SettingsSound::on_pushButtonConfigureSoundCard3_clicked() int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); const device_t *device = sound_card_getdevice(sndCard); - DeviceConfig::ConfigureDevice(device, 3, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 3); } void @@ -294,7 +294,7 @@ SettingsSound::on_pushButtonConfigureSoundCard4_clicked() int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); const device_t *device = sound_card_getdevice(sndCard); - DeviceConfig::ConfigureDevice(device, 4, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 4); } void @@ -312,8 +312,7 @@ SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) void SettingsSound::on_pushButtonConfigureMidiOut_clicked() { - DeviceConfig::ConfigureDevice(midi_out_device_getdevice(ui->comboBoxMidiOut->currentData().toInt()), 0, - qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(midi_out_device_getdevice(ui->comboBoxMidiOut->currentData().toInt())); } void @@ -331,8 +330,7 @@ SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) void SettingsSound::on_pushButtonConfigureMidiIn_clicked() { - DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt()), 0, - qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt())); } void @@ -345,7 +343,7 @@ void SettingsSound::on_pushButtonConfigureMPU401_clicked() { if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) - DeviceConfig::ConfigureDevice(&mpu401_mca_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&mpu401_mca_device); else - DeviceConfig::ConfigureDevice(&mpu401_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&mpu401_device); } diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 6fa5906b5..48fa04892 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -281,31 +281,31 @@ SettingsStorageControllers::on_checkBoxQuaternaryIDE_stateChanged(int arg1) void SettingsStorageControllers::on_pushButtonHD_clicked() { - DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt()), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt())); } void SettingsStorageControllers::on_pushButtonFD_clicked() { - DeviceConfig::ConfigureDevice(fdc_card_getdevice(ui->comboBoxFD->currentData().toInt()), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(fdc_card_getdevice(ui->comboBoxFD->currentData().toInt())); } void SettingsStorageControllers::on_pushButtonCDInterface_clicked() { - DeviceConfig::ConfigureDevice(cdrom_interface_get_device(ui->comboBoxCDInterface->currentData().toInt()), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(cdrom_interface_get_device(ui->comboBoxCDInterface->currentData().toInt())); } void SettingsStorageControllers::on_pushButtonTertiaryIDE_clicked() { - DeviceConfig::ConfigureDevice(&ide_ter_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&ide_ter_device); } void SettingsStorageControllers::on_pushButtonQuaternaryIDE_clicked() { - DeviceConfig::ConfigureDevice(&ide_qua_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&ide_qua_device); } void @@ -347,25 +347,25 @@ SettingsStorageControllers::on_comboBoxSCSI4_currentIndexChanged(int index) void SettingsStorageControllers::on_pushButtonSCSI1_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI1->currentData().toInt()), 1, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI1->currentData().toInt()), 1); } void SettingsStorageControllers::on_pushButtonSCSI2_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI2->currentData().toInt()), 2, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI2->currentData().toInt()), 2); } void SettingsStorageControllers::on_pushButtonSCSI3_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI3->currentData().toInt()), 3, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI3->currentData().toInt()), 3); } void SettingsStorageControllers::on_pushButtonSCSI4_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4); } void From d566a0620285ed3d625fe01b6d1a85f14b3cf43d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 28 Apr 2025 19:28:58 +0200 Subject: [PATCH 0815/1190] Fix pitch regression of the ATI Mach8/32 side (April 28th, 2025) This patch fixes the pitch that was originally 0 when specifying the 8514/A compatible side in the Mach8/32 cards, which should be 1024 for 8514/A compatible stuff. --- src/video/vid_ati_mach8.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 5cbd48623..d2fde4f93 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2761,9 +2761,9 @@ ati8514_recalctimings(svga_t *svga) mach_log("ON=%d, vgahdisp=%d.\n", dev->on, svga->hdisp); if (dev->on) { - mach_log("8514/A ON.\n"); - dev->pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach_log("8514/A ON, pitch=%d.\n", dev->ext_pitch); dev->interlace = !!(dev->disp_cntl & 0x10); + dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; dev->rowcount = !!(dev->disp_cntl & 0x08); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; @@ -2865,7 +2865,7 @@ mach_recalctimings(svga_t *svga) if (dev->on) { dev->ma_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ dev->interlace = !!(dev->disp_cntl & 0x10); - dev->pitch = ((mach->accel.ge_pitch & 0xff) << 3); + dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; dev->rowcount = !!(dev->disp_cntl & 0x08); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); @@ -3321,6 +3321,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_set_resolution(mach, svga); mach32_updatemapping(mach, svga); } else { + dev->ext_pitch = 1024; dev->ext_crt_pitch = 128; mach_set_resolution(mach, svga); } @@ -3515,8 +3516,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { if ((dev->accel.multifunc_cntl >> 12) == 5) { - if (!ATI_MACH32) + if (!ATI_MACH32) { + dev->ext_pitch = 1024; dev->ext_crt_pitch = 128; + svga_recalctimings(svga); + } } } break; @@ -3847,6 +3851,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { WRITE8(port, mach->accel.ge_pitch, val); } + dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); mach_log("ATI 8514/A: (0x%04x) GE Pitch val=0x%02x.\n", port, val); svga_recalctimings(svga); break; From ad4ec20374d08ddb3b8e8919d2fc775ab3e0c22e Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 29 Apr 2025 00:33:51 +0200 Subject: [PATCH 0816/1190] Modify the CL-GD 54xx (S)VGA read and write handlers in order to use the pointer to the svga struct instead of the gd54xx struct, fixes #5521. --- src/include/86box/vid_svga.h | 2 + src/video/vid_cl54xx.c | 78 ++++++++++++++++++------------------ 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 932aa718a..6de73f9f9 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -315,6 +315,8 @@ typedef struct svga_t { card should not attempt to display anything. */ void (*render_override)(void *priv); void * priv_parent; + + void * local; } svga_t; extern void ibm8514_set_poll(svga_t *svga); diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index b60f9bdca..4988b3797 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -2263,8 +2263,8 @@ gd54xx_mem_sys_src_write(gd54xx_t *gd54xx, uint8_t val, uint8_t ap) static void gd54xx_write(uint32_t addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = (svga_t *) priv; + gd54xx_t *gd54xx = (gd54xx_t *) svga->local; if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { @@ -2282,16 +2282,16 @@ gd54xx_write(uint32_t addr, uint8_t val, void *priv) static void gd54xx_writew(uint32_t addr, uint16_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = (svga_t *) priv; + gd54xx_t *gd54xx = (gd54xx_t *) svga->local; if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) val = (val >> 8) | (val << 8); - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); + gd54xx_write(addr, val, svga); + gd54xx_write(addr + 1, val >> 8, svga); return; } @@ -2312,18 +2312,18 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) static void gd54xx_writel(uint32_t addr, uint32_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = (svga_t *) priv; + gd54xx_t *gd54xx = (gd54xx_t *) svga->local; if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); - gd54xx_write(addr + 2, val >> 16, gd54xx); - gd54xx_write(addr + 3, val >> 24, gd54xx); + gd54xx_write(addr, val, svga); + gd54xx_write(addr + 1, val >> 8, svga); + gd54xx_write(addr + 2, val >> 16, svga); + gd54xx_write(addr + 3, val >> 24, svga); return; } @@ -2881,8 +2881,8 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv) static uint8_t gd54xx_read(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = (svga_t *) priv; + gd54xx_t *gd54xx = (gd54xx_t *) svga->local; if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) @@ -2898,14 +2898,14 @@ gd54xx_read(uint32_t addr, void *priv) static uint16_t gd54xx_readw(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = (svga_t *) priv; + gd54xx_t *gd54xx = (gd54xx_t *) svga->local; uint16_t ret; if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd54xx_read(addr, priv); - ret |= gd54xx_read(addr + 1, priv) << 8; + ret = gd54xx_read(addr, svga); + ret |= gd54xx_read(addr + 1, svga) << 8; return ret; } @@ -2920,16 +2920,16 @@ gd54xx_readw(uint32_t addr, void *priv) static uint32_t gd54xx_readl(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = (svga_t *) priv; + gd54xx_t *gd54xx = (gd54xx_t *) svga->local; uint32_t ret; if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd54xx_read(addr, priv); - ret |= gd54xx_read(addr + 1, priv) << 8; - ret |= gd54xx_read(addr + 2, priv) << 16; - ret |= gd54xx_read(addr + 3, priv) << 24; + ret = gd54xx_read(addr, svga); + ret |= gd54xx_read(addr + 1, svga) << 8; + ret |= gd54xx_read(addr + 2, svga) << 16; + ret |= gd54xx_read(addr + 3, svga) << 24; return ret; } @@ -3120,7 +3120,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *priv) break; } } else if (gd54xx->mmio_vram_overlap) - gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr, val, svga); } static void @@ -3153,8 +3153,8 @@ gd543x_mmio_writew(uint32_t addr, uint16_t val, void *priv) gd543x_mmio_write(addr, val & 0xff, gd54xx); gd543x_mmio_write(addr + 1, val >> 8, gd54xx); } else { - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); + gd54xx_write(addr, val, svga); + gd54xx_write(addr + 1, val >> 8, svga); } } } @@ -3178,10 +3178,10 @@ gd543x_mmio_writel(uint32_t addr, uint32_t val, void *priv) gd543x_mmio_write(addr + 2, val >> 16, gd54xx); gd543x_mmio_write(addr + 3, val >> 24, gd54xx); } else { - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); - gd54xx_write(addr + 2, val >> 16, gd54xx); - gd54xx_write(addr + 3, val >> 24, gd54xx); + gd54xx_write(addr, val, svga); + gd54xx_write(addr + 1, val >> 8, svga); + gd54xx_write(addr + 2, val >> 16, svga); + gd54xx_write(addr + 3, val >> 24, svga); } } } @@ -3320,7 +3320,7 @@ gd543x_mmio_read(uint32_t addr, void *priv) break; } } else if (gd54xx->mmio_vram_overlap) - ret = gd54xx_read(addr, gd54xx); + ret = gd54xx_read(addr, svga); else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) ret = gd54xx_mem_sys_dest_read(gd54xx, 0); @@ -3338,7 +3338,7 @@ gd543x_mmio_readw(uint32_t addr, void *priv) if (gd543x_do_mmio(svga, addr)) ret = gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr + 1, gd54xx) << 8); else if (gd54xx->mmio_vram_overlap) - ret = gd54xx_read(addr, gd54xx) | (gd54xx_read(addr + 1, gd54xx) << 8); + ret = gd54xx_read(addr, svga) | (gd54xx_read(addr + 1, svga) << 8); else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { ret = gd543x_mmio_read(addr, priv); @@ -3361,7 +3361,7 @@ gd543x_mmio_readl(uint32_t addr, void *priv) (gd543x_mmio_read(addr + 2, gd54xx) << 16) | (gd543x_mmio_read(addr + 3, gd54xx) << 24); else if (gd54xx->mmio_vram_overlap) - ret = gd54xx_read(addr, gd54xx) | (gd54xx_read(addr + 1, gd54xx) << 8) | + ret = gd54xx_read(addr, svga) | (gd54xx_read(addr + 1, svga) << 8) | (gd54xx_read(addr + 2, gd54xx) << 16) | (gd54xx_read(addr + 3, gd54xx) << 24); else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { @@ -4141,6 +4141,8 @@ gd54xx_reset(void *priv) gd54xx_t *gd54xx = (gd54xx_t *) priv; svga_t *svga = &gd54xx->svga; + pclog("gd54xx_reset()\n"); + memset(svga->crtc, 0x00, sizeof(svga->crtc)); memset(svga->seqregs, 0x00, sizeof(svga->seqregs)); memset(svga->gdcreg, 0x00, sizeof(svga->gdcreg)); @@ -4159,7 +4161,6 @@ gd54xx_reset(void *priv) memset(gd54xx->pci_regs, 0x00, 256); - mem_mapping_set_p(&svga->mapping, gd54xx); mem_mapping_disable(&gd54xx->mmio_mapping); mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_disable(&gd54xx->aperture2_mapping); @@ -4210,7 +4211,7 @@ gd54xx_reset(void *priv) static void * gd54xx_init(const device_t *info) { - gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t)); + gd54xx_t *gd54xx = calloc(1, sizeof(gd54xx_t)); svga_t *svga = &gd54xx->svga; int id = info->local & 0xff; int vram; @@ -4218,8 +4219,6 @@ gd54xx_init(const device_t *info) const char *romfn1 = NULL; const char *romfn2 = NULL; - memset(gd54xx, 0, sizeof(gd54xx_t)); - gd54xx->pci = !!(info->flags & DEVICE_PCI); gd54xx->vlb = !!(info->flags & DEVICE_VLB); gd54xx->mca = !!(info->flags & DEVICE_MCA); @@ -4475,7 +4474,6 @@ gd54xx_init(const device_t *info) if ((id <= CIRRUS_ID_CLGD5429) || (!gd54xx->pci && !gd54xx->vlb)) mem_mapping_set_base_ignore(&gd54xx->linear_mapping, 0xff000000); - mem_mapping_set_p(&svga->mapping, gd54xx); mem_mapping_disable(&gd54xx->mmio_mapping); mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_disable(&gd54xx->aperture2_mapping); @@ -4538,6 +4536,8 @@ gd54xx_init(const device_t *info) gd54xx->overlay.colorkeycompare = 0xff; + svga->local = gd54xx; + return gd54xx; } From 0da871f54e45f8b7ac349c3f304d22732cc95a5a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 29 Apr 2025 00:39:26 +0200 Subject: [PATCH 0817/1190] Vast overhaul to the 15bpp/16bpp accelerated mode of the 911/924. 1. See above, as best as possible, but manuals would be helpful. 2. Reverted the ramdac of the 924 to the sierra one because of a bug that triggers 24bpp mode when it shouldn't. --- src/video/vid_s3.c | 563 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 445 insertions(+), 118 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index ef21b18df..8fa392891 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -245,6 +245,8 @@ typedef struct s3_t { uint32_t pat_bg_color, pat_fg_color; uint32_t bkgd_color; uint32_t frgd_color; + uint16_t bkgd_color_back; + uint16_t frgd_color_back; uint32_t wrt_mask; uint32_t rd_mask; uint32_t color_cmp; @@ -253,7 +255,8 @@ typedef struct s3_t { uint16_t multifunc_cntl; uint16_t multifunc[16]; uint8_t pix_trans[4]; - uint16_t pix_trans_val; + uint8_t pix_trans_val[2048][2048]; + int pix_trans_inc; int ssv_state; int16_t cx, cy; @@ -281,7 +284,10 @@ typedef struct s3_t { uint8_t bkgd_color_actual[2]; uint8_t wrt_mask_actual[2]; int color_16bit_check; + int color_16bit_check_pixtrans; int16_t minus; + int rd_mask_16bit_check; + int start; /*For non-threaded FIFO*/ int setup_fifo_slot; @@ -611,18 +617,34 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); + s3->accel_start(8, 1, val | (val << 16), 0, s3); } else { - if ((s3->bpp == 0) && s3->color_16bit) + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) + val = (val >> 8) | (val << 8); + } else { + if (s3->accel.cur_x & 0x400) + s3->accel.color_16bit_check_pixtrans = 1; + else + s3->accel.color_16bit_check_pixtrans = 0; + } s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - else + } else s3->accel_start(1, 1, 0xffffffff, val | (val << 16), s3); } } else { if ((s3->bpp == 0) && s3->color_16bit) { - if (s3->accel.cur_x & 0x400) - val = (val >> 8) | (val << 8); - + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) + val = (val >> 8) | (val << 8); + } else { + if (s3->accel.cur_x & 0x400) + s3->accel.color_16bit_check_pixtrans = 1; + else + s3->accel.color_16bit_check_pixtrans = 0; + } s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } else s3->accel_start(1, 1, 0xffffffff, val | (val << 16), s3); @@ -638,11 +660,19 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) } else s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } else { - if ((s3->bpp == 0) && s3->color_16bit) { - if (s3->accel.cur_x & 0x400) + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cmd == 0x53f1) { + if (s3->accel.cur_x & 0x400) + val = (val >> 8) | (val << 8); + + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + val = (val >> 8) | (val << 8); - } - s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } else + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } else + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } break; case 0x400: @@ -1037,7 +1067,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa549: case 0xa6e9: - s3_log("[%04X:%08X] OUT PORTB=%04x (Foreground Color), val=%02x.\n", CS, cpu_state.pc, port, val); if (s3->bpp == 3) { if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { if (s3->accel.multifunc[0xe] & 0x10) @@ -1450,6 +1479,8 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xbee9: s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + if ((s3->accel.multifunc_cntl >> 12) == 5) + s3_log("S3 multifunc_cntl = %d, val = %03x.\n", s3->accel.multifunc_cntl >> 12, s3->accel.multifunc_cntl & 0xfff); break; case 0xd148: @@ -1589,13 +1620,36 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } else { if ((s3->bpp == 0) && s3->color_16bit) { - s3->accel.pix_trans[1] = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx - s3->accel.minus)) & s3->vram_mask]; - if (s3->accel.cur_x & 0x400) { - s3_log("Last Pixel Written=%02x (1024).\n", s3->accel.pix_trans[1]); - s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + if (s3->accel.rd_mask_16bit_check) { + s3->accel.pix_trans[1] = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx - s3->accel.minus)) & s3->vram_mask]; + if (s3->accel.cmd & 0x1000) { + if (s3->accel.cur_x & 0x400) { + s3_log("Last Pixel Written=%02x (1024) reverse.\n", s3->accel.pix_trans[1]); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } else { + s3_log("Last Pixel Written=%02x (0) reverse, cx=%d.\n", s3->accel.pix_trans[1], s3->accel.cx, s3->accel.cur_x); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + } + } else { + if (s3->accel.cur_x & 0x400) { + s3_log("Last Pixel Written=%02x (1024) normal, cx=%d, curx=%d.\n", s3->accel.pix_trans[1], s3->accel.cx, s3->accel.cur_x); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + } else { + s3_log("Last Pixel Written=%02x (0) normal, cx=%d, curx=%d.\n", s3->accel.pix_trans[1], s3->accel.cx, s3->accel.cur_x); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } } else { - s3_log("Last Pixel Written=%02x (0).\n", s3->accel.pix_trans[1]); - s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3->accel.pix_trans_val[s3->accel.cy][s3->accel.cx] = val; + + if (s3->accel.cur_x & 0x400) { + s3->accel.color_16bit_check_pixtrans = 0; + s3_log("%04X:%08X: Last Pixel Written=%04x (1024) normal, cx=%d, cy=%d.\n", CS, cpu_state.pc, s3->accel.pix_trans_val[s3->accel.cy][s3->accel.cx - s3->accel.minus] | (s3->accel.pix_trans_val[s3->accel.cy][s3->accel.cx] << 8), s3->accel.cx, s3->accel.cy); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans_val[s3->accel.cy][s3->accel.cx - s3->accel.minus] | (s3->accel.pix_trans_val[s3->accel.cy][s3->accel.cx] << 8), s3); + } else { + s3->accel.color_16bit_check_pixtrans = 1; + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } } } else s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); @@ -2164,7 +2218,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) const s3_t *s3 = (s3_t *) svga->priv; int shift = 1; int width = 16; - uint16_t dat[2] = { 0, 0 }; + uint16_t dat[4] = { 0, 0, 0, 0 }; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg; @@ -2176,30 +2230,53 @@ s3_hwcursor_draw(svga_t *svga, int displine) case 15: fg = video_15to32[s3->hwc_fg_col & 0xffff]; bg = video_15to32[s3->hwc_bg_col & 0xffff]; - if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805)) { + if (!s3->color_16bit) { + if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805)) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } } + } else { + shift = 2; + width = 8; + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; } + } else if (s3->chip <= S3_86C924) { + shift = 2; + width = 8; + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; } break; case 16: fg = video_16to32[s3->hwc_fg_col & 0xffff]; bg = video_16to32[s3->hwc_bg_col & 0xffff]; - if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805)) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; - } - } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - if (!(svga->crtc[0x45] & 0x04)) { - offset <<= 1; + if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805)) { + if (!s3->color_16bit) { + if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805)) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (!(svga->crtc[0x45] & 0x04)) + offset <<= 1; } + } else { + shift = 2; + width = 8; + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; } + } else if (s3->chip <= S3_86C924) { + shift = 2; + width = 8; + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; } break; @@ -2236,40 +2313,62 @@ s3_hwcursor_draw(svga_t *svga, int displine) for (uint8_t x = 0; x < 64; x += 16) { remapped_addr = dword_remap(svga, real_addr); + if (((svga->bpp == 15) || (svga->bpp == 16)) && s3->color_16bit) { + dat[0] = svga->vram[remapped_addr & s3->vram_mask]; + dat[1] = svga->vram[(remapped_addr + 1) & s3->vram_mask]; + dat[2] = svga->vram[(remapped_addr + 2) & s3->vram_mask]; + dat[3] = svga->vram[(remapped_addr + 3) & s3->vram_mask]; - dat[0] = (svga->vram[remapped_addr & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 1) & s3->vram_mask]; - dat[1] = (svga->vram[(remapped_addr + 2) & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 3) & s3->vram_mask]; - - if (svga->crtc[0x55] & 0x10) { - /*X11*/ - for (xx = 0; xx < 16; xx++) { - if (offset >= 0) { - if (dat[0] & 0x8000) - buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; - } - - offset++; - dat[0] <<= shift; - dat[1] <<= shift; - } - } else { /*Windows*/ - for (xx = 0; xx < width; xx++) { + for (xx = 0; xx < 8; xx++) { if (offset >= 0) { - if (!(dat[0] & 0x8000)) - buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; - else if (dat[1] & 0x8000) + if (!(dat[(xx & 4) ? 2 : 0] & 0x80)) + buffer32->line[displine][offset + svga->x_add] = (dat[(xx & 4) ? 3 : 1] & 0x80) ? fg : bg; + else if (dat[(xx & 4) ? 3 : 1] & 0x80) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } offset++; - dat[0] <<= shift; - dat[1] <<= shift; + s3_log("Up: Data0=%04x, Data1=%04x, Data2=%04x, Data3=%04x, xx=%d addr=%06x.\n", dat[0], dat[1], dat[2], dat[3], xx, remapped_addr); + dat[(xx & 4) ? 2 : 0] <<= 2; + dat[(xx & 4) ? 3 : 1] <<= 2; + } + } else { + dat[0] = (svga->vram[remapped_addr & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 1) & s3->vram_mask]; + dat[1] = (svga->vram[(remapped_addr + 2) & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 3) & s3->vram_mask]; + + if (svga->crtc[0x55] & 0x10) { + /*X11*/ + for (xx = 0; xx < 16; xx++) { + if (offset >= 0) { + if (dat[0] & 0x8000) + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; + } + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; + } + } else { + /*Windows*/ + for (xx = 0; xx < width; xx++) { + if (offset >= 0) { + if (!(dat[0] & 0x8000)) + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; + else if (dat[1] & 0x8000) + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + } + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; + } } } svga->hwcursor_latch.addr += 4; real_addr = s3_hwcursor_convert_addr(svga); } + if (svga->interlace && !svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; } @@ -2812,10 +2911,10 @@ s3_out(uint16_t addr, uint8_t val, void *priv) else if (s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968)) { rs3 = !!(svga->crtc[0x55] & 0x02); tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C924)) && + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805))) att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if (s3->chip == S3_86C911) { + else if (s3->chip <= S3_86C924) { sc1148x_ramdac_out(addr, rs2, val, svga->ramdac, svga); } else if (s3->card_type == S3_NUMBER9_9FX_531) att498_ramdac_out(addr, rs2, val, svga->ramdac, svga); @@ -2916,7 +3015,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) break; case 0x45: - if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968)) break; svga->hwcursor.ena = val & 1; break; @@ -2928,7 +3027,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x4d: case 0x4e: case 0x4f: - if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968)) break; svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) @@ -2937,14 +3036,14 @@ s3_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) + if ((s3->chip >= S3_TRIO32) && (svga->bpp == 32)) svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) { - if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && svga->bpp == 16) + else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && ((svga->bpp == 15) || (svga->bpp == 16))) { + if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && (svga->bpp == 16)) svga->hwcursor.x >>= 2; else svga->hwcursor.x >>= 1; - } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) + } else if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805) && (svga->bpp == 24)) svga->hwcursor.x /= 3; else if ((s3->chip <= S3_86C805) && s3->color_16bit) svga->hwcursor.x >>= 1; @@ -3137,10 +3236,10 @@ s3_in(uint16_t addr, void *priv) else if (s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968)) { rs3 = !!(svga->crtc[0x55] & 0x02); return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C924)) && + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805))) return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); - else if (s3->chip == S3_86C911) + else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->card_type == S3_NUMBER9_9FX_531) return att498_ramdac_in(addr, rs2, svga->ramdac, svga); @@ -3449,7 +3548,8 @@ s3_recalctimings(svga_t *svga) if (s3->chip <= S3_86C805) { s3->color_16bit = !!(svga->crtc[0x43] & 0x08); - if (svga->bpp == 24) + s3_log("Color 16bit=%x, bpp=%d, 256color=%x.\n", s3->color_16bit, svga->bpp, (svga->attrregs[0x10] & 0x40)); + if ((svga->bpp == 24) || (svga->bpp == 8)) s3->color_16bit = 0; if (s3->color_16bit) @@ -5678,11 +5778,15 @@ s3_accel_in_w(uint16_t port, void *priv) if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { if (s3->accel.cmd & 0x1000) temp = (temp >> 8) | (temp << 8); + s3->accel_start(8, 1, temp | (temp << 16), 0, s3); } else { - if ((s3->bpp == 0) && s3->color_16bit) + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.cur_x & 0x400) + temp = ((temp >> 8) | (temp << 8)) & 0xffff; + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - else + } else s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); } } else { @@ -5715,6 +5819,7 @@ s3_accel_in_w(uint16_t port, void *priv) } else { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); + temp = s3->accel.short_stroke; } @@ -6472,7 +6577,6 @@ polygon_setup(s3_t *s3) #define MIX \ { \ - old_dest_dat = dest_dat; \ MIX_READ \ dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); \ } @@ -7695,6 +7799,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi uint32_t srcbase; uint32_t dstbase; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + if (((s3->chip >= S3_TRIO64) || (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) && (s3->accel.cmd & (1 << 11))) cmd |= 0x08; @@ -7720,32 +7827,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->accel.cmd & 0x100) && (s3_cpu_src(s3) || (s3_cpu_dest(s3))) && (!cpu_input || (s3_enable_fifo(s3) == 0))) s3->force_busy = 1; - if ((s3->bpp == 0) && s3->color_16bit && !s3->accel.b2e8_pix) { - if (cmd <= 2) { - if (s3->accel.cur_x & 0x400) { - if (s3->accel.cmd != 0x41b3) - wrt_mask = (wrt_mask << 8) & 0xff00; - else - wrt_mask &= 0xff; - - frgd_color = (frgd_color << 8) & 0xff00; - bkgd_color = (bkgd_color << 8) & 0xff00; - } else { - if (clip_r >= 0x400) { - wrt_mask &= 0xff; - frgd_color &= 0xff; - bkgd_color &= 0xff; - } - } - } else if (cmd == 6) { - if (s3->accel.destx_distp & 0x400) { - wrt_mask = (wrt_mask << 8) & 0xff00; - frgd_color = (frgd_color << 8) & 0xff00; - bkgd_color = (bkgd_color << 8) & 0xff00; - } - } - } - if (!cpu_input) s3->accel.dat_count = 0; @@ -7794,13 +7875,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ - s3_log("CMD=%d, full=%04x, s3bpp=%x, multifuncE=%03x, sourcedisplay=%x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%04x, mix=%04x, count=%d, rd_mask=%04x, wrt_mask=%04x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%04x, bkgdcolor=%04x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, svgabpp=%d.\n", cmd, s3->accel.cmd, s3->bpp, s3->accel.multifunc[0x0e], vram_mask, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffff, mix_dat & 0xffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, svga->bpp); + s3_log("CMD=%d, full=%04x, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%04x, mix=%04x, count=%d, rd_mask=%04x, wrt_mask=%04x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%04x, bkgdcolor=%04x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x.\n", cmd, s3->accel.cmd, s3->bpp, clip_r, clip_b, vram_mask, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffff, mix_dat & 0xffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -7846,6 +7924,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + old_dest_dat = dest_dat; MIX if (s3->accel.ssv_draw) { @@ -7911,10 +7990,16 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi case 1: /*Draw line*/ if (!cpu_input) { s3->accel.minus = 0; + s3->accel.color_16bit_check_pixtrans = 0; s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; s3->accel.sy = s3->accel.maj_axis_pcnt; - if ((s3->bpp == 0) && s3->color_16bit && (s3->accel.cur_x & 0x400)) + if ((s3->bpp == 0) && s3->color_16bit) + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + else + s3->accel.rd_mask_16bit_check = 0; + + if ((s3->bpp == 0) && s3->color_16bit && (s3->accel.cur_x & 0x400) && s3->accel.rd_mask_16bit_check) s3->accel.minus = 0x400; if (s3_cpu_src(s3)) @@ -7922,6 +8007,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } if (s3->accel.cmd & 0x08) { /*Radial*/ + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + rd_mask &= 0x00ff; + } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400)) + break; + } + while (count-- && s3->accel.sy >= 0) { if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -7960,6 +8061,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, dest_dat); + old_dest_dat = dest_dat; MIX WRITE((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, dest_dat); @@ -7973,8 +8075,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else cpu_dat >>= 16; - if (!s3->accel.sy) + if (!s3->accel.sy) { + if ((s3->bpp == 0) && s3->color_16bit) { + if (!(s3->accel.cur_x & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } break; + } switch (s3->accel.cmd & 0xe0) { case 0x00: @@ -8016,9 +8125,40 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cur_x = s3->accel.cx & 0xfff; s3->accel.cur_y = s3->accel.cy & 0xfff; } else { /*Bresenham*/ - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Stupid undocumented 0xB2E8 on 911/924*/ + if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Pattern on pixtrans (911/924)*/ count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + rd_mask &= 0x00ff; + } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400)) + break; + } + } else { + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + rd_mask &= 0x00ff; + } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400)) + break; + } } while (count-- && s3->accel.sy >= 0) { @@ -8064,6 +8204,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, dest_dat); + old_dest_dat = dest_dat; MIX WRITE((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, dest_dat); @@ -8086,8 +8227,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else cpu_dat >>= 16; - if (!s3->accel.sy) + if (!s3->accel.sy) { + if ((s3->bpp == 0) && s3->color_16bit) { + if (!(s3->accel.cur_x & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } break; + } if (s3->accel.cmd & 0x40) { if (s3->accel.cmd & 0x80) @@ -8131,21 +8279,43 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi case 2: /*Rectangle fill*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { + s3->accel.start = 0; s3->accel.minus = 0; + s3->accel.color_16bit_check_pixtrans = 0; s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if ((s3->bpp == 0) && s3->color_16bit && (s3->accel.cur_x & 0x400)) - s3->accel.minus = 0x400; - - if (s3->accel.cur_x & 0x400) - s3_log("Rectangle Fill + 1024 FULLCMD=%04x: frgdcolor=%04x, s(%d,%d), c(%d,%d).\n", s3->accel.cmd, frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy); - else - s3_log("Rectangle Fill + 0 FULLCMD=%04x: frgdcolor=%04x, s(%d,%d), c(%d,%d).\n", s3->accel.cmd, frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy); s3->accel.dest = dstbase + s3->accel.cy * s3->width; + if ((s3->bpp == 0) && s3->color_16bit) { + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + if (s3->accel.rd_mask_16bit_check) { + s3->accel.start = 1; + if (s3->accel.cur_x & 0x400) { + s3->accel.minus = 0x400; + if ((s3->accel.cmd == 0x41b3) && (frgd_mix == 0)) + s3->accel.minus = 0; + } + } else { + if (s3->accel.cmd & 0x100) { + if (!(s3->accel.cmd & 0x200)) { + if (s3->accel.cur_x & 0x400) + s3->accel.minus = 0x400; + else + s3->accel.minus = 0; + } + } + } + } else + s3->accel.rd_mask_16bit_check = 0; + + if (s3->accel.cur_x & 0x400) + s3_log("Rectangle Fill + 1024 FULLCMD=%04x: frgdcolor=%04x, s=%d,%d, c=%d,%d, frmix=%x, bkmix=%x, pixcntl=%02x, m2=%d, m4=%d.\n", s3->accel.cmd, s3->accel.frgd_color_actual[1] << 8, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, frgd_mix, bkgd_mix, s3->accel.multifunc[0xa] & 0xc0, s3->accel.multifunc[2], s3->accel.multifunc[4]); + else + s3_log("Rectangle Fill + 0 FULLCMD=%04x: frgdcolor=%04x, s=%d,%d, c=%d,%d, frmix=%x, bkmix=%x, pixcntl=%02x, m2=%d, m4=%d.\n", s3->accel.cmd, s3->accel.frgd_color_actual[0], s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, frgd_mix, bkgd_mix, s3->accel.multifunc[0xa] & 0xc0, s3->accel.multifunc[2], s3->accel.multifunc[4]); + if (s3_cpu_src(s3)) { s3->data_available = 0; return; /*Wait for data from CPU*/ @@ -8155,9 +8325,93 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Stupid undocumented 0xB2E8 on 911/924*/ + + if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Pattern on pixtrans (911/924)*/ count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) { + if (s3->accel.start) { + s3->accel.minus = 0x400; + s3->accel.start = 0; + } + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + if (s3->accel.start) { + s3->accel.minus = 0; + s3->accel.start = 0; + } + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + rd_mask &= 0x00ff; + } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400)) + break; + } else { + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.cmd == 0x41b3) { + if (frgd_mix != 0) { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + rd_mask &= 0x00ff; + } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400)) + break; + } + } else { + if (s3->accel.rd_mask_16bit_check) { + rd_mask &= 0x00ff; + if (s3->accel.cmd == 0x53b3) { + if (clip_l & 0x400) { + if (s3->accel.start) { + s3->accel.minus = 0x400; + s3->accel.start = 0; + } + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + if (s3->accel.start) { + s3->accel.minus = 0; + s3->accel.start = 0; + } + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + } else { + if (s3->accel.cur_x & 0x400) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + } + } else { + if ((s3_cpu_src(s3)) && !(s3->accel.cmd & 0x200)) { + s3_log("FIXME: S3 911/924 15/16bpp documentation needed.\n"); + } else { + if (!cpu_input && (s3->accel.cur_x & 0x400)) + break; + else if (cpu_input && (s3->accel.cmd == 0x53b3) && (s3->accel.cur_x & 0x400)) + break; + } + } + } + } } while (count-- && (s3->accel.sy >= 0)) { @@ -8177,7 +8431,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi mix_dat = mix_dat ? mix_mask : 0; } - if (s3_cpu_dest(s3) || ((s3_cpu_src(s3)) && s3->color_16bit && (s3->bpp == 0) && (s3->accel.cmd == 0x41b3))) { + if (s3_cpu_dest(s3)) { READ(s3->accel.dest + s3->accel.cx - s3->accel.minus, src_dat); if (vram_mask) src_dat = ((src_dat & rd_mask) == rd_mask); @@ -8221,17 +8475,18 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (s3_cpu_dest(s3)) { if (vram_mask) { + old_dest_dat = dest_dat; MIX } } else { + old_dest_dat = dest_dat; MIX } if (s3->accel.cmd & 0x10) { - if (s3->accel.cmd == 0x41b3) - s3_log("Full=%04x: Destination=%04x, OldDest=%04x, c=%d,%d.\n", s3->accel.cmd, dest_dat, old_dest_dat, s3->accel.cx, s3->accel.cy); - - WRITE(s3->accel.dest + s3->accel.cx - s3->accel.minus, dest_dat); + if (!s3->accel.color_16bit_check_pixtrans) { + WRITE(s3->accel.dest + s3->accel.cx - s3->accel.minus, dest_dat); + } } } } @@ -8274,9 +8529,25 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy &= 0xfff; s3->accel.dest = dstbase + s3->accel.cy * s3->width; + s3->accel.sy--; if (cpu_input) { + if (s3->accel.sy < 0) { + if ((s3->bpp == 0) && s3->color_16bit) { + if ((s3->accel.cmd == 0x53b3) && !s3->accel.b2e8_pix) { + if (!(clip_l & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } else { + if (!(s3->accel.cur_x & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } + } + } if (s3->accel.b2e8_pix) { s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -8284,6 +8555,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi return; } if (s3->accel.sy < 0) { + if ((s3->bpp == 0) && s3->color_16bit) { + if (!(s3->accel.cur_x & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; return; @@ -8352,6 +8629,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + old_dest_dat = dest_dat; MIX if (s3->accel.cmd & 0x10) { @@ -8396,10 +8674,17 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.dx = s3->accel.destx_distp & 0xfff; s3->accel.dy = s3->accel.desty_axstp & 0xfff; + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); - if ((s3->bpp == 0) && s3->color_16bit && (clip_r > 0x3ff) && (s3->accel.destx_distp & 0x400)) + if ((s3->bpp == 0) && s3->color_16bit && (s3->accel.destx_distp & 0x400) && s3->accel.rd_mask_16bit_check) s3->accel.minus = 0x400; + if (s3->accel.destx_distp & 0x400) { + s3_log("BitBLT + 1024 FULLCMD=%04x: frgdcolor=%04x, s=%d,%d, d=%d,%d, frmix=%x, bkmix=%x, pixcntl=%02x.\n", s3->accel.cmd, frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.dx, s3->accel.dy, frgd_mix, bkgd_mix, s3->accel.multifunc[0xa] & 0xc0); + } else { + s3_log("BitBLT + 0 FULLCMD=%04x: frgdcolor=%04x, s=%d,%d, d=%d,%d, frmix=%x, bkmix=%x, pixcntl=%02x.\n", s3->accel.cmd, frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.dx, s3->accel.dy, frgd_mix, bkgd_mix, s3->accel.multifunc[0xa] & 0xc0); + } + s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; @@ -8411,6 +8696,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->bpp == 0) && s3->color_16bit) { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.destx_distp & 0x400) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + } + rd_mask &= 0x00ff; + } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.destx_distp & 0x400)) + break; + } + if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { while (1) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { @@ -8441,6 +8742,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.sy--; if (s3->accel.sy < 0) { + if ((s3->bpp == 0) && s3->color_16bit) { + if (!(s3->accel.destx_distp & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } s3->accel.destx_distp = s3->accel.dx; s3->accel.desty_axstp = s3->accel.dy; return; @@ -8493,6 +8800,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ(s3->accel.dest + s3->accel.dx - s3->accel.minus, dest_dat); + old_dest_dat = dest_dat; MIX if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) { @@ -8540,10 +8848,25 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.sy--; - if (cpu_input) + if (cpu_input) { + if (s3->accel.sy < 0) { + if ((s3->bpp == 0) && s3->color_16bit) { + if (!(s3->accel.destx_distp & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } + } return; + } if (s3->accel.sy < 0) { + if ((s3->bpp == 0) && s3->color_16bit) { + if (!(s3->accel.destx_distp & 0x400)) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + } s3->accel.destx_distp = s3->accel.dx; s3->accel.desty_axstp = s3->accel.dy; return; @@ -8623,6 +8946,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); + old_dest_dat = dest_dat; MIX if (s3->accel.cmd & 0x10) { @@ -8728,6 +9052,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + old_dest_dat = dest_dat; MIX if (s3->accel.cmd & 0x10) { @@ -8777,6 +9102,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + old_dest_dat = dest_dat; MIX if (s3->accel.cmd & 0x10) { @@ -8878,6 +9204,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + old_dest_dat = dest_dat; MIX if (s3->accel.cmd & 0x10) { @@ -9838,7 +10165,7 @@ s3_init(const device_t *info) s3->id_ext_pci = 0; s3->packed_mmio = 0; - svga->ramdac = device_add(&att490_ramdac_device); + svga->ramdac = device_add(&sc11483_ramdac_device); svga->clock_gen = device_add(&ics2494an_305_device); svga->getclock = ics2494_getclock; break; From d623425efdf1b418623a444278aad60ec024d201 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 29 Apr 2025 00:57:03 +0200 Subject: [PATCH 0818/1190] Some more changes to the Mach8/32/8514/A side (April 29th, 2025) 1. Do not stall the guest when the passthrough mode is on, fixes hang ups in Windows 3.1 using the 2.3 drivers. 2. In the pitch register, make sure the passthrough goes on when needed only on the ATI Mach32, not 8, fixes mode on/off in text mode when needed. 3. Cosmetic changes and logs. --- src/video/vid_8514a.c | 2 +- src/video/vid_ati_mach8.c | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 533ec8fa9..ba4641259 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -961,7 +961,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) temp |= INT_GE_BSY; } - if (!dev->fifo_idx) { + if (!dev->fifo_idx && !dev->on) { dev->force_busy = 0; dev->force_busy2 = 0; dev->data_available = 0; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index d2fde4f93..07fa0a93c 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -866,6 +866,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.stepy = 1; } + if (mach->accel.dp_config == 0x4011) + mach->accel.height++; + dev->accel.sy = 0; dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); @@ -1172,7 +1175,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.sx++; if (mach->accel.sx >= mach->accel.src_width) { mach->accel.sx = 0; - if (mach->accel.src_stepx < 0) + if (mach->accel.src_stepx == -1) dev->accel.cx += mach->accel.src_width; else dev->accel.cx -= mach->accel.src_width; @@ -1196,7 +1199,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sx++; if ((dev->accel.sx >= mach->accel.width) || (dev->accel.dx >= 0x600)) { dev->accel.sx = 0; - if (mach->accel.stepx < 0) + if (mach->accel.stepx == -1) dev->accel.dx += mach->accel.width; else dev->accel.dx -= mach->accel.width; @@ -3457,7 +3460,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xe2e9: case 0xe6e9: - mach_log("Write PORT=%04x, 8514/A=%x, val=%04x, len=%d.\n", port, dev->accel.cmd_back, val, len); + mach_log("Write PORT=%04x, 8514/A=%x, val0=%02x, sy=%d, len=%d, dx=%d, dy=%d.\n", port, dev->accel.cmd_back, val, dev->accel.sy, len, dev->accel.dx, dev->accel.dy); if (len == 1) { if (!dev->accel.cmd_back) { if (mach->accel.cmd_type >= 0) { @@ -3645,9 +3648,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (len == 2) { dev->_8514crt = 0; - if (!(dev->accel.advfunc_cntl & 0x01)) { + if (!(dev->accel.advfunc_cntl & 0x01) && ATI_MACH32) { dev->on = 1; - dev->vendor_mode = !!ATI_MACH32; + dev->vendor_mode = 1; } } else dev->_8514crt = 1; @@ -3656,7 +3659,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (ATI_GRAPHICS_ULTRA || ATI_MACH32) mach32_updatemapping(mach, svga); - mach_log("ATI 8514/A: (0x%04x) CRT Pitch, val=0x%02x, crtpitch=%x, len=%d, extended 8514/A mode bpp=%d.\n", port, val, dev->ext_crt_pitch, len, dev->accel_bpp); + mach_log("ATI 8514/A: (0x%04x) CRT Pitch, val=0x%02x, crtpitch=%x, len=%d, extended 8514/A mode bpp=%d, enable_on=%d.\n", port, val, dev->ext_crt_pitch, len, dev->accel_bpp, dev->on); break; case 0x2aee: @@ -4747,21 +4750,23 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) } } - if (!dev->fifo_idx) { + if (!dev->fifo_idx && !dev->on) { dev->force_busy = 0; dev->force_busy2 = 0; mach->force_busy = 0; dev->data_available = 0; dev->data_available2 = 0; temp |= INT_FIFO_EMP; + mach_log("Fifo Empty.\n"); } 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); else temp |= 0x20; + + mach_log("0x%04x read: Subsystem Status=%02x, monitoralias=%02x.\n", port, temp, mach->accel.ext_ge_config & 0x07); } - mach_log("0x%04x read: Subsystem Status=%02x, monitoralias=%02x.\n", port, temp, mach->accel.ext_ge_config & 0x07); break; /*ATI Mach8/32 specific registers*/ From 1282ecfd56fc21095de975e34a59e716d12533d2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 30 Apr 2025 01:37:25 +0200 Subject: [PATCH 0819/1190] BT-958D PCI: Preserve PCI slot across device resets, fixes IRQ's. --- src/scsi/scsi_buslogic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 352232e34..0e8954aff 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1551,6 +1551,8 @@ buslogic_reset(void *priv) reset_state.timer = dev->timer; reset_state.ResetCB = dev->ResetCB; + reset_state.pci_slot = dev->pci_slot; + memcpy(dev, &reset_state, sizeof(x54x_t)); dev->timer.period = 10.0; From 9f03881dd84d173280583e289ffa7a9b9258f538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 30 Apr 2025 18:04:25 +0200 Subject: [PATCH 0820/1190] Trigem 486G: Fix memory limits. --- 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 39d9cc9ff..c269c7b0f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7328,9 +7328,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_VLB, .flags = MACHINE_IDE | MACHINE_APM, /* Has internal video: Western Digital WD90C33-ZZ */ .ram = { - .min = 1024, - .max = 65536, - .step = 1024 + .min = 4096, + .max = 40960, + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, From a6599a60b2f246c6e39f6969fabc481cbe6ee6c8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 30 Apr 2025 18:46:39 +0200 Subject: [PATCH 0821/1190] TriGem 486G: Initialize NVR with 0x00's instead of 0xFF's, fixes the cache error on empty NVR. --- src/machine/m_at_386dx_486.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index ef30a5aa4..264111a96 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2283,7 +2283,10 @@ machine_at_tg486gp_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); + + device_add(&ide_isa_device); device_add(&ali1429g_device); From 77f7be608ec596c0c584cccf43eb59f669faf96b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 30 Apr 2025 19:15:12 +0200 Subject: [PATCH 0822/1190] Turns out I committed the NVR fix to the wrong TriGem 486 machine. --- src/machine/m_at_386dx_486.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 264111a96..5b746e3ef 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2283,10 +2283,7 @@ machine_at_tg486gp_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); - - device_add(&ide_isa_device); + machine_at_common_ide_init(model); device_add(&ali1429g_device); @@ -2319,7 +2316,8 @@ machine_at_tg486g_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); device_add(&sis_85c471_device); device_add(&ide_isa_device); device_add(&fdc37c651_ide_device); From 26c0e4af811f1a41cc73bca04e8424156d8d8b38 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 30 Apr 2025 14:51:49 -0400 Subject: [PATCH 0823/1190] Fix second standard joystick --- src/game/joystick_standard.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 122d2c65f..5f200cb98 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -62,13 +62,18 @@ joystick_standard_read(UNUSED(void *priv)) { uint8_t ret = 0xf0; - for (int js = 0; js < 2; js++) { - if (JOYSTICK_PRESENT(0, js)) { - if (joystick_state[0][js].button[0]) - ret &= ~0x10; - if (joystick_state[0][js].button[1]) - ret &= ~0x20; - } + if (JOYSTICK_PRESENT(0, 0)) { + if (joystick_state[0][0].button[0]) + ret &= ~0x10; + if (joystick_state[0][0].button[1]) + ret &= ~0x20; + } + + if (JOYSTICK_PRESENT(0, 1)) { + if (joystick_state[0][1].button[0]) + ret &= ~0x40; + if (joystick_state[0][1].button[1]) + ret &= ~0x80; } return ret; From 49bbd6e8cdcd451c099a86d18f9a28868c22c097 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 30 Apr 2025 22:20:33 +0200 Subject: [PATCH 0824/1190] Removed the usage deprecation warning. --- src/86box.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/86box.c b/src/86box.c index cd573d98f..1d7a73060 100644 --- a/src/86box.c +++ b/src/86box.c @@ -665,7 +665,9 @@ pc_init(int argc, char *argv[]) time_t now; int c; int lvmp = 0; +#ifdef DEPRECATE_USAGE int deprecated = 1; +#endif #ifdef ENABLE_NG int ng = 0; #endif @@ -750,7 +752,9 @@ usage: goto usage; ppath = argv[++c]; +#ifdef DEPRECATE_USAGE deprecated = 0; +#endif } else if (!strcasecmp(argv[c], "--rompath") || !strcasecmp(argv[c], "-R")) { if ((c + 1) == argc) goto usage; @@ -762,7 +766,9 @@ usage: goto usage; cfg = argv[++c]; +#ifdef DEPRECATE_USAGE deprecated = 0; +#endif } else if (!strcasecmp(argv[c], "--image") || !strcasecmp(argv[c], "-I")) { if ((c + 1) == argc) goto usage; @@ -862,16 +868,20 @@ usage: else cfg = argv[c++]; +#ifdef DEPRECATE_USAGE deprecated = 0; +#endif } if (c != argc) goto usage; +#ifdef DEPRECATE_USAGE if (deprecated) pc_show_usage("Running 86Box without a specified VM path and/or configuration\n" "file has been deprected. Please specify one or use a manager\n" "(Avalonia 86 is recommended).\n\n"); +#endif path_slash(usr_path); path_slash(rom_path); From 8c736c7b9a66f5ec26db51a154f08af9edb19ba5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 30 Apr 2025 23:15:58 +0200 Subject: [PATCH 0825/1190] Stall fix for the mach8/32 (April 30th, 2025) See above. --- src/video/vid_ati_mach8.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 07fa0a93c..ce6ee12d5 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -4264,10 +4264,13 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in if (dev->force_busy) { temp |= 0x0200; /*Hardware busy*/ if (mach->accel.cmd_type >= 0) { + mono_src = (mach->accel.dp_config >> 5) & 3; switch (mach->accel.cmd_type) { case 2: if (dev->accel.sy >= mach->accel.height) dev->force_busy = 0; + else if (mono_src == 2) + dev->force_busy = 0; break; case 5: if (dev->accel.sx >= mach->accel.width) From 27425dbd492e935e094eb120139bc0d70cc03ebc Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 1 May 2025 15:39:43 +0200 Subject: [PATCH 0826/1190] SiS 85c471: Implement DRAM banks/rows. --- src/chipset/sis_85c4xx.c | 442 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 418 insertions(+), 24 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 537675a85..003b66697 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -36,24 +36,340 @@ #include <86box/machine.h> #include <86box/chipset.h> +typedef struct ram_bank_t { + uint32_t virt_base; + uint32_t virt_size; + uint32_t phys_base; + uint32_t phys_size; + + mem_mapping_t mapping; +} ram_bank_t; + typedef struct sis_85c4xx_t { - uint8_t cur_reg; - uint8_t tries; - uint8_t reg_base; - uint8_t reg_last; - uint8_t reg_00; - uint8_t is_471; - uint8_t force_flush; - uint8_t shadowed; - uint8_t smram_enabled; - uint8_t pad; - uint8_t regs[39]; - uint8_t scratch[2]; - uint32_t mem_state[8]; - smram_t *smram; - port_92_t *port_92; + uint8_t cur_reg; + uint8_t tries; + uint8_t reg_base; + uint8_t reg_last; + uint8_t reg_00; + uint8_t is_471; + uint8_t ram_banks_val; + uint8_t force_flush; + uint8_t shadowed; + uint8_t smram_enabled; + uint8_t pad; + uint8_t regs[39]; + uint8_t scratch[2]; + uint32_t mem_state[8]; + ram_bank_t ram_banks[8]; + smram_t * smram; + port_92_t * port_92; } sis_85c4xx_t; +static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, + 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b, + 0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }; +static uint8_t ram_tg486g[64] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, + 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, + 0x15, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, + 0x17, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; + +static uint32_t banks_471[64][4] = { { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x00 */ + { 0x00100000, 0x00100000, 0x00000000, 0x00000000 }, + { 0x00100000, 0x00100000, 0x00200000, 0x00000000 }, + { 0x00100000, 0x00100000, 0x00400000, 0x00000000 }, + { 0x00100000, 0x00100000, 0x00200000, 0x00400000 }, + { 0x00100000, 0x00100000, 0x00400000, 0x00400000 }, + { 0x00100000, 0x00100000, 0x01000000, 0x00000000 }, + { 0x00200000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00200000, 0x00200000, 0x00000000, 0x00000000 }, /* 0x08 */ + { 0x00200000, 0x00400000, 0x00000000, 0x00000000 }, + { 0x00200000, 0x00200000, 0x00400000, 0x00000000 }, + { 0x00200000, 0x00200000, 0x00400000, 0x00400000 }, + { 0x00200000, 0x01000000, 0x00000000, 0x00000000 }, + { 0x00200000, 0x00200000, 0x01000000, 0x00000000 }, + { 0x00200000, 0x00200000, 0x00400000, 0x01000000 }, + { 0x00200000, 0x00200000, 0x01000000, 0x01000000 }, + { 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x10 */ + { 0x00400000, 0x00400000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x00400000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x00400000, 0x00400000 }, + { 0x00400000, 0x01000000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x01000000, 0x00000000 }, + { 0x00400000, 0x01000000, 0x01000000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x01000000, 0x01000000 }, + { 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x18 */ + { 0x00800000, 0x00800000, 0x00000000, 0x00000000 }, + { 0x00800000, 0x00800000, 0x00800000, 0x00000000 }, + { 0x00800000, 0x00800000, 0x00800000, 0x00800000 }, + { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x01000000, 0x01000000, 0x00000000, 0x00000000 }, + { 0x01000000, 0x01000000, 0x01000000, 0x00000000 }, + { 0x01000000, 0x01000000, 0x01000000, 0x01000000 }, + { 0x00100000, 0x00400000, 0x00000000, 0x00000000 }, /* 0x20 */ + { 0x00100000, 0x01000000, 0x00000000, 0x00000000 }, + { 0x00100000, 0x04000000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x00800000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x04000000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x04000000, 0x00000000 }, + { 0x01000000, 0x04000000, 0x00000000, 0x00000000 }, + { 0x01000000, 0x01000000, 0x04000000, 0x00000000 }, + { 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x28 */ + { 0x04000000, 0x04000000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x02000000, 0x00000000, 0x00000000 }, + { 0x00400000, 0x02000000, 0x02000000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x02000000, 0x00000000 }, + { 0x00400000, 0x00400000, 0x02000000, 0x02000000 }, + { 0x01000000, 0x02000000, 0x00000000, 0x00000000 }, + { 0x01000000, 0x02000000, 0x02000000, 0x00000000 }, + { 0x01000000, 0x01000000, 0x02000000, 0x00000000 }, /* 0x30 */ + { 0x01000000, 0x01000000, 0x02000000, 0x02000000 }, + { 0x02000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x02000000, 0x02000000, 0x00000000, 0x00000000 }, + { 0x02000000, 0x02000000, 0x02000000, 0x00000000 }, + { 0x02000000, 0x02000000, 0x02000000, 0x02000000 }, + { 0x00400000, 0x00800000, 0x00800000, 0x00000000 }, + { 0x00400000, 0x00800000, 0x00800000, 0x00800000 }, + { 0x00400000, 0x00400000, 0x00800000, 0x00000000 }, /* 0x38 */ + { 0x00400000, 0x00400000, 0x00800000, 0x00800000 }, + { 0x00800000, 0x01000000, 0x00000000, 0x00000000 }, + { 0x00800000, 0x00800000, 0x00800000, 0x01000000 }, + { 0x00800000, 0x00800000, 0x01000000, 0x00000000 }, + { 0x00800000, 0x00800000, 0x01000000, 0x01000000 }, + { 0x00800000, 0x00800000, 0x02000000, 0x00000000 }, + { 0x00800000, 0x00800000, 0x02000000, 0x02000000 } }; + +static uint32_t +sis_85c471_get_row(ram_bank_t *dev, uint32_t addr) +{ + uint32_t ret = 0x00000000; + + switch (dev->virt_size) { + case 0x04000000: + ret = (addr >> 14) & 0x00000fff; + break; + case 0x01000000: + ret = (addr >> 13) & 0x000007ff; + break; + case 0x00400000: + ret = (addr >> 12) & 0x000003ff; + break; + case 0x00100000: + ret = (addr >> 11) & 0x000001ff; + break; + } + + return ret; +} + +static uint32_t +sis_85c471_get_col(ram_bank_t *dev, uint32_t addr) +{ + uint32_t ret = 0x00000000; + + switch (dev->virt_size) { + case 0x04000000: + ret = (addr >> 2) & 0x00000fff; + break; + case 0x01000000: + ret = (addr >> 2) & 0x000007ff; + break; + case 0x00400000: + ret = (addr >> 2) & 0x000003ff; + break; + case 0x00100000: + ret = (addr >> 2) & 0x000001ff; + break; + } + + return ret; +} + +static uint32_t +sis_85c471_set_row(ram_bank_t *dev, uint32_t addr) +{ + uint32_t ret = 0x00000000; + + switch (dev->phys_size) { + case 0x04000000: + ret = (addr & 0x00000fff) << 14; + break; + case 0x01000000: + ret = (addr & 0x000007ff) << 13; + break; + case 0x00400000: + ret = (addr & 0x000003ff) << 12; + break; + case 0x00100000: + ret = (addr & 0x000002ff) << 11; + break; + } + + return ret; +} + +static uint32_t +sis_85c471_set_col(ram_bank_t *dev, uint32_t addr) +{ + uint32_t ret = 0x00000000; + + switch (dev->phys_size) { + case 0x04000000: + ret = (addr & 0x00000fff) << 2; + break; + case 0x01000000: + ret = (addr & 0x000007ff) << 2; + break; + case 0x00400000: + ret = (addr & 0x000003ff) << 2; + break; + case 0x00100000: + ret = (addr & 0x000002ff) << 2; + break; + } + + return ret; +} + +static uint8_t +sis_85c471_read_ram(uint32_t addr, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint32_t rel = addr - dev->virt_base; + uint8_t ret = 0xff; + + if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; + } + + addr = (rel + dev->phys_base); + + if ((addr < (mem_size << 10)) && (rel < dev->phys_size)) + ret = ram[addr]; + + return ret; +} + +static uint16_t +sis_85c471_read_ramw(uint32_t addr, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint32_t rel = addr - dev->virt_base; + uint16_t ret = 0xffff; + + if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; + } + + addr = (rel + dev->phys_base); + + if ((addr < (mem_size << 10)) && (rel < dev->phys_size)) + ret = *(uint16_t *) &(ram[addr]); + + return ret; +} + +static uint32_t +sis_85c471_read_raml(uint32_t addr, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint32_t rel = addr - dev->virt_base; + uint32_t ret = 0xffffffff; + + if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; + } + + addr = (rel + dev->phys_base); + + if ((addr < (mem_size << 10)) && (rel < dev->phys_size)) + ret = *(uint32_t *) &(ram[addr]); + + return ret; +} + +static void +sis_85c471_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint32_t rel = addr - dev->virt_base; + + if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; + } + + addr = (rel + dev->phys_base); + + if ((addr < (mem_size << 10)) && (rel < dev->phys_size)) + ram[addr] = val; +} + +static void +sis_85c471_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint32_t rel = addr - dev->virt_base; + + if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; + } + + addr = (rel + dev->phys_base); + + if ((addr < (mem_size << 10)) && (rel < dev->phys_size)) + *(uint16_t *) &(ram[addr]) = val; +} + +static void +sis_85c471_write_raml(uint32_t addr, uint32_t val, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint32_t rel = addr - dev->virt_base; + + if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; + } + + addr = (rel + dev->phys_base); + + if ((addr < (mem_size << 10)) && (rel < dev->phys_size)) + *(uint32_t *) &(ram[addr]) = val; +} + static void sis_85c4xx_recalcremap(sis_85c4xx_t *dev) { @@ -158,6 +474,60 @@ sis_85c4xx_sw_smi_handler(sis_85c4xx_t *dev) NULL, NULL, NULL, sis_85c4xx_sw_smi_out, NULL, NULL, dev); } +static void +sis_85c471_banks_split(uint32_t *b_ex, uint32_t *banks) +{ + for (uint8_t i = 0; i < 4; i++) { + if ((banks[i] == 0x00200000) || (banks[i] == 0x00800000) || + (banks[i] == 0x02000000)) + b_ex[i << 1] = b_ex[(i << 1) + 1] = banks[i] >> 1; + else { + b_ex[i << 1] = banks[i]; + b_ex[(i << 1) + 1] = 0x00000000; + } + } +} + +static void +sis_85c471_banks_recalc(sis_85c4xx_t *dev) +{ + for (uint8_t i = 0; i < 8; i++) + mem_mapping_disable(&dev->ram_banks[i].mapping); + + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_high_mapping); + mem_set_mem_state_both(1 << 20, 127 << 20, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + if ((dev->regs[0x09] & 0x3f) == dev->ram_banks_val) { + if (mem_size > 1024) { + mem_mapping_enable(&ram_low_mapping); + mem_mapping_enable(&ram_high_mapping); + mem_set_mem_state_both(1 << 20, (mem_size << 10) - (1 << 20), + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + } else { + uint8_t banks_val = dev->regs[0x09] & 0x3f; + uint32_t *banks = banks_471[banks_val]; + uint32_t b_ex[8] = { 0x00000000 }; + uint32_t size = 0x00000000; + + sis_85c471_banks_split(b_ex, banks); + + for (uint8_t i = 0; i < 8; i++) if (b_ex[i] != 0x00000000) { + dev->ram_banks[i].virt_base = size; + dev->ram_banks[i].virt_size = b_ex[i]; + + mem_mapping_set_addr(&dev->ram_banks[i].mapping, size, b_ex[i]); + + size += b_ex[i]; + } + + mem_set_mem_state_both(1 << 20, 127 << 20, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + + flushmmucache_nopc(); +} + static void sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) { @@ -192,6 +562,11 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) sis_85c4xx_recalcmapping(dev); break; + case 0x09: + if (dev->is_471) + sis_85c471_banks_recalc(dev); + break; + case 0x0b: sis_85c4xx_sw_smi_handler(dev); if (valxor & 0x02) @@ -297,14 +672,6 @@ sis_85c4xx_reset(void *priv) { sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; int mem_size_mb = mem_size >> 10; - static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b, - 0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }; memset(dev->regs, 0x00, sizeof(dev->regs)); @@ -318,8 +685,25 @@ sis_85c4xx_reset(void *priv) dev->regs[0x09] |= 0x22; else dev->regs[0x09] |= 0x24; - } else + } else if (!strcmp(machine_get_internal_name(), "tg486g")) + dev->regs[0x09] |= ram_tg486g[mem_size_mb]; + else dev->regs[0x09] |= ram_471[mem_size_mb]; + dev->ram_banks_val = dev->regs[0x09] & 0x3f; + dev->regs[0x09] = 0x00; + + uint32_t *banks = banks_471[dev->ram_banks_val]; + uint32_t b_ex[8] = { 0x00000000 }; + uint32_t size = 0x00000000; + + sis_85c471_banks_split(b_ex, banks); + + for (uint8_t i = 0; i < 8; i++) { + dev->ram_banks[i].phys_base = size; + dev->ram_banks[i].phys_size = b_ex[i]; + + size += b_ex[i]; + } dev->regs[0x11] = 0x09; dev->regs[0x12] = 0xff; @@ -332,6 +716,8 @@ sis_85c4xx_reset(void *priv) port_92_remove(dev->port_92); soft_reset_mask = 0; + + sis_85c471_banks_recalc(dev); } else { /* Bits 6 and 7 must be clear on the SiS 40x. */ if (dev->reg_base == 0x60) @@ -380,6 +766,14 @@ sis_85c4xx_init(const device_t *info) dev->smram = smram_add(); dev->port_92 = device_add(&port_92_device); + + for (uint8_t i = 0; i < 8; i++) { + mem_mapping_add(&dev->ram_banks[i].mapping, 0x00000000, 0x00000000, + sis_85c471_read_ram, sis_85c471_read_ramw, sis_85c471_read_raml, + sis_85c471_write_ram, sis_85c471_write_ramw, sis_85c471_write_raml, + NULL, MEM_MAPPING_INTERNAL, &(dev->ram_banks[i])); + mem_mapping_disable(&dev->ram_banks[i].mapping); + } } else dev->reg_last = dev->reg_base + 0x11; From a2abb497e2d75d67cc9d4482a785e7910aabcc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Thu, 1 May 2025 21:02:59 +0200 Subject: [PATCH 0827/1190] Fix header guard warning --- src/qt/qt_iconindicators.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_iconindicators.hpp b/src/qt/qt_iconindicators.hpp index 861e41d94..12f82f259 100644 --- a/src/qt/qt_iconindicators.hpp +++ b/src/qt/qt_iconindicators.hpp @@ -1,5 +1,5 @@ #ifndef QT_ICONINDICATORS_HPP -# define QT_INDICATORS_HPP +# define QT_ICONINDICATORS_HPP #include #include @@ -14,4 +14,4 @@ enum IconIndicator { QPixmap getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator); -#endif \ No newline at end of file +#endif From a72142f2b5395e04e40cbf0ecb0dd3ed73174d39 Mon Sep 17 00:00:00 2001 From: GreaseMonkey Date: Fri, 2 May 2025 10:51:34 +1200 Subject: [PATCH 0828/1190] Fix EGA/VGA/SVGA odd-even handling of write mask Matches my AMD Stoney + S3 Trio64V2, and also Intel's 2023 GPU docs (which *still* tend to be more accurate than IBM's), and makes more sense than what we've (I've?) been doing. --- src/video/vid_ega.c | 4 +--- src/video/vid_svga.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 8333e522e..b828239c0 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1180,9 +1180,7 @@ ega_write(uint32_t addr, uint8_t val, void *priv) cycles -= video_timing_write_b; if (ega->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; + writemask2 &= 0x5 << (addr & 1); } addr = ega_remap_cpu_addr(addr, ega); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 67469ed22..86a57c00e 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1689,9 +1689,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) addr &= ~3; addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; + writemask2 &= 0x5 << (addr & 1); addr &= ~1; addr <<= 2; } else From 5e85f4533a18026311f5249b1cab826034a590a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 2 May 2025 02:06:02 +0200 Subject: [PATCH 0829/1190] Update RAM limits for SiS 471 machines --- src/machine/machine_table.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c269c7b0f..77132b6b5 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7089,7 +7089,7 @@ const machine_t machines[] = { .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 65536, + .max = 131072, .step = 1024 }, .nvrmask = 127, @@ -7129,7 +7129,7 @@ const machine_t machines[] = { .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 65536, + .max = 131072, .step = 1024 }, .nvrmask = 127, @@ -7209,7 +7209,7 @@ const machine_t machines[] = { .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 65536, + .max = 131072, .step = 1024 }, .nvrmask = 127, @@ -7249,7 +7249,7 @@ const machine_t machines[] = { .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 65536, + .max = 131072, .step = 1024 }, .nvrmask = 127, @@ -7368,9 +7368,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2, .flags = MACHINE_IDE_DUAL | MACHINE_SUPER_IO | MACHINE_APM | MACHINE_VIDEO, .ram = { - .min = 1024, - .max = 65536, - .step = 1024 + .min = 4096, + .max = 69632, + .step = 4096 }, .nvrmask = 127, .kbc_device = NULL, From 7885c28ea2ad5597d8c52c73b750d59a0bce2ad4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 May 2025 02:17:09 +0200 Subject: [PATCH 0830/1190] SiS 471: Fix RAM bank values (and some other minor things), fixes #5534. --- src/chipset/sis_85c4xx.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 003b66697..51f7fd4e6 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -33,6 +33,7 @@ #include <86box/mem.h> #include <86box/smram.h> #include <86box/pic.h> +#include <86box/keyboard.h> #include <86box/machine.h> #include <86box/chipset.h> @@ -79,8 +80,8 @@ static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }; + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d }; static uint8_t ram_tg486g[64] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, @@ -544,12 +545,23 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) case 0x23: if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) { valxor = val ^ dev->regs[rel_reg]; - if (rel_reg == 0x00) + + if (!dev->is_471 && (rel_reg == 0x00)) dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0); else dev->regs[rel_reg] = val; switch (rel_reg) { + case 0x00: + if (val & 0x01) { + kbc_at_set_fast_reset(0); + cpu_cpurst_on_sr = 1; + } else { + kbc_at_set_fast_reset(1); + cpu_cpurst_on_sr = 0; + } + break; + case 0x01: cpu_cache_ext_enabled = ((val & 0x84) == 0x84); cpu_update_waitstates(); @@ -560,6 +572,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) case 0x08: if (valxor) sis_85c4xx_recalcmapping(dev); + if (rel_reg == 0x08) + flushmmucache(); break; case 0x09: @@ -681,10 +695,16 @@ sis_85c4xx_reset(void *priv) if (dev->is_471) { dev->regs[0x09] = 0x40; if (mem_size_mb >= 64) { - if ((mem_size_mb >= 65) && (mem_size_mb < 68)) - dev->regs[0x09] |= 0x22; + if ((mem_size_mb >= 64) && (mem_size_mb < 68)) + dev->regs[0x09] |= 0x33; + if ((mem_size_mb >= 68) && (mem_size_mb < 72)) + dev->regs[0x09] |= 0x2b; + if ((mem_size_mb >= 72) && (mem_size_mb < 80)) + dev->regs[0x09] |= 0x2d; + if ((mem_size_mb >= 80) && (mem_size_mb < 96)) + dev->regs[0x09] |= 0x2f; else - dev->regs[0x09] |= 0x24; + dev->regs[0x09] |= 0x29; } else if (!strcmp(machine_get_internal_name(), "tg486g")) dev->regs[0x09] |= ram_tg486g[mem_size_mb]; else @@ -718,6 +738,9 @@ sis_85c4xx_reset(void *priv) soft_reset_mask = 0; sis_85c471_banks_recalc(dev); + + kbc_at_set_fast_reset(1); + cpu_cpurst_on_sr = 0; } else { /* Bits 6 and 7 must be clear on the SiS 40x. */ if (dev->reg_base == 0x60) From 384af874f5dee71ce0cd300d9186561d2d2227d8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 3 May 2025 17:02:30 +0600 Subject: [PATCH 0831/1190] Bochs VBE: Update for 0.9c ROM --- src/video/vid_bochs_vbe.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index 36185214c..a87890c75 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -811,22 +811,22 @@ bochs_vbe_init(const device_t *info) dev->vram_size = device_get_config_int("memory") * (1 << 20); rom_init(&dev->bios_rom, "roms/video/bochs/VGABIOS-lgpl-latest.bin", - 0xc0000, 0x10000, 0xffff, 0x0000, + 0xc0000, 0x8000, 0x7fff, 0x0000, MEM_MAPPING_EXTERNAL); if (dev->id5_val == VBE_DISPI_ID4) { /* Patch the BIOS to match the PCI ID. */ dev->bios_rom.rom[0x010c] = 0xee; - dev->bios_rom.rom[0x8dff] -= (0xee - 0x34); + dev->bios_rom.rom[0x7fff] -= (0xee - 0x34); dev->bios_rom.rom[0x010d] = 0x80; - dev->bios_rom.rom[0x8dff] -= (0x80 - 0x12); + dev->bios_rom.rom[0x7fff] -= (0x80 - 0x12); dev->bios_rom.rom[0x010e] = 0xef; - dev->bios_rom.rom[0x8dff] -= (0xef - 0x11); + dev->bios_rom.rom[0x7fff] -= (0xef - 0x11); dev->bios_rom.rom[0x010f] = 0xbe; - dev->bios_rom.rom[0x8dff] -= (0xbe - 0x11); + dev->bios_rom.rom[0x7fff] -= (0xbe - 0x11); } video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_bochs); From e09a5007c5d7cde3d27fcba0dfb8ee8a96f9770c Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 3 May 2025 21:10:55 +0200 Subject: [PATCH 0832/1190] Fix Acer P3 Machine table entry... ... to make the onboard video's RAM configurable. --- 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 77132b6b5..9c83f4b22 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8392,7 +8392,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &gd5434_onboard_pci_device, .snd_device = NULL, .net_device = NULL }, From c9d07c657c0cd8b33f5c93e989eda8db321fc1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jernej=20Simon=C4=8Di=C4=8D?= <1800143+jernejs@users.noreply.github.com> Date: Sat, 3 May 2025 21:58:14 +0200 Subject: [PATCH 0833/1190] Update sl-SI.po --- src/qt/languages/sl-SI.po | 196 +++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 7c2b36650..dcb3dbf50 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -37,7 +37,7 @@ msgid "&Hide status bar" msgstr "&Skrij statusno vrstico" msgid "Hide &toolbar" -msgstr "Hide &toolbar" +msgstr "Skrij &orodno vrstico" msgid "&Resizeable window" msgstr "S&premenljiva velikost okna" @@ -55,7 +55,7 @@ msgid "Qt (&OpenGL)" msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" -msgstr "Open&GL (Jedro 3.0)" +msgstr "Open&GL (jedro 3.0)" msgid "&VNC" msgstr "&VNC" @@ -64,10 +64,10 @@ msgid "Specify dimensions..." msgstr "&Določi velikost..." msgid "F&orce 4:3 display ratio" -msgstr "&Vsili 4:3 razmerje zaslona" +msgstr "&Vsili razmerje zaslona 4:3" msgid "&Window scale factor" -msgstr "&Faktor velikosti okna" +msgstr "&Faktor povečave okna" msgid "&0.5x" msgstr "&0.5x" @@ -100,7 +100,7 @@ msgid "&8x" msgstr "&8x" msgid "Filter method" -msgstr "&Metoda filtriranja" +msgstr "&Vrsta filtriranja" msgid "&Nearest" msgstr "&Najbližja" @@ -241,7 +241,7 @@ msgid "E&ject" msgstr "I&zvrzi" msgid "&Image..." -msgstr "Slika..." +msgstr "S&lika..." msgid "E&xport to 86F..." msgstr "&Izvozi v 86F..." @@ -355,7 +355,7 @@ msgid "Speed:" msgstr "Hitrost:" msgid "Frequency:" -msgstr "Pogostost:" +msgstr "Takt:" msgid "FPU:" msgstr "Procesor plavajoče vejice:" @@ -367,7 +367,7 @@ msgid "MB" msgstr "MB" msgid "Memory:" -msgstr "Spomin:" +msgstr "Pomnilnik:" msgid "Time synchronization" msgstr "Sinhronizacija časa" @@ -445,7 +445,7 @@ msgid "FM synth driver" msgstr "Gonilnik sintetizacije FM" msgid "Nuked (more accurate)" -msgstr "Nuked (točnejši)" +msgstr "Nuked (natančnejši)" msgid "YMFM (faster)" msgstr "YMFM (hitrejši)" @@ -487,22 +487,22 @@ msgid "Serial port 4" msgstr "Serijska vrata 4" msgid "Parallel port 1" -msgstr "Paralelna vrata 1" +msgstr "Vzporedna vrata 1" msgid "Parallel port 2" -msgstr "Paralelna vrata 2" +msgstr "Vzporedna vrata 2" msgid "Parallel port 3" -msgstr "Paralelna vrata 3" +msgstr "Vzporedna vrata 3" msgid "Parallel port 4" -msgstr "Paralelna vrata 4" +msgstr "Vzporedna vrata 4" msgid "HD Controller:" msgstr "Krmilnik trdega diska:" msgid "FD Controller:" -msgstr "Krmilnik disketnika:" +msgstr "Disketni krmilnik:" msgid "Tertiary IDE Controller" msgstr "Terciarni krmilnik IDE" @@ -550,7 +550,7 @@ msgid "ID:" msgstr "ID:" msgid "&Specify..." -msgstr "Določi..." +msgstr "&Določi..." msgid "Sectors:" msgstr "Sektorji:" @@ -595,7 +595,7 @@ msgid "ZIP 250" msgstr "ZIP 250" msgid "ISA RTC:" -msgstr "Ura v realnem času ISA:" +msgstr "Ura realnega časa ISA:" msgid "ISA Memory Expansion" msgstr "Razširitev pomnilnika ISA" @@ -643,7 +643,7 @@ msgid "ZIP images" msgstr "ZIP slike" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box ni našel nobenih uporabnih ROM slik.\n\nProsim prenesite set ROM-ov in ga razširite v mapo \"roms\"." +msgstr "86Box ni našel nobenih uporabnih ROM slik.\n\nProsim prenesite komplet ROM-ov in ga razširite v mapo \"roms\"." msgid "(empty)" msgstr "(prazno)" @@ -751,7 +751,7 @@ msgid "Type" msgstr "Vrsta" msgid "No PCap devices found" -msgstr "Nobena naprava PCap ni bila najdena" +msgstr "Najdena ni bila nobena naprava PCap" msgid "Invalid PCap device" msgstr "Neveljavna naprava PCap" @@ -874,16 +874,16 @@ msgid "Don't exit" msgstr "Prekliči izhod" msgid "Reset" -msgstr "Resetiraj" +msgstr "Znova zaženi" msgid "Don't reset" -msgstr "Ne resetiraj" +msgstr "Ne zaženi znova" msgid "CD-ROM images" msgstr "Slike CD-ROM" msgid "%1 Device Configuration" -msgstr "Konfiguracija naprave %1" +msgstr "Nastavitev naprave %1" msgid "Monitor in sleep mode" msgstr "Zaslon v načinu spanja" @@ -946,7 +946,7 @@ msgid "Add New Hard Disk" msgstr "Dodaj nov trdi disk" msgid "Add Existing Hard Disk" -msgstr "Dodaj obstoječ trdi disk" +msgstr "Dodaj obstoječi trdi disk" msgid "HDI disk images cannot be larger than 4 GB." msgstr "Slike diska HDI ne morejo biti večje od 4 GB." @@ -1048,13 +1048,13 @@ msgid "VHD files" msgstr "Datoteke VHD" msgid "Select the parent VHD" -msgstr "Izberite starševsko sliko VHD" +msgstr "Izberite nadrejeno sliko VHD" msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" -msgstr "To lahko pomeni, da je bila starševska slika spremenjena potem, ko je že bila ustvarjena diferencialna slika.\n\nDo tega lahko pride tudi kadar so datoteke slik diska premaknjene ali kopirane, ali pa gre za hrošča v programu, ki je ustvaril ta disk.\n\nŽelite popraviti časovni žig?" +msgstr "To lahko pomeni, da je bila nadrejena slika spremenjena po ustvaritvi diferencialne slike.\n\nDo tega lahko pride tudi kadar so datoteke slik diska premaknjene ali kopirane, ali pa gre za hrošča v programu, ki je ustvaril ta disk.\n\nŽelite popraviti časovni žig?" msgid "Parent and child disk timestamps do not match" -msgstr "Časovna žiga starševske slike diska in slike diska otroka se ne ujemata" +msgstr "Časovna žiga nadrejene in podrejene slike diska se ne ujemata" msgid "Could not fix VHD timestamp." msgstr "Ne morem popraviti časovnega žiga slike VHD." @@ -1105,10 +1105,10 @@ msgid "1.44 MB" msgstr "1.44 MB" msgid "DMF (cluster 1024)" -msgstr "DMF (grozd 1024)" +msgstr "DMF (gruča 1024)" msgid "DMF (cluster 2048)" -msgstr "DMF (grozd 2048)" +msgstr "DMF (gruča 2048)" msgid "2.88 MB" msgstr "2.88 MB" @@ -1162,7 +1162,7 @@ msgid "(System Default)" msgstr "(Sistemsko privzeto)" msgid "Failed to initialize network driver" -msgstr "Ni uspelo inicializirati omrežnega gonilnika" +msgstr "Inicializacija omrežnega gonilnika ni uspela" msgid "The network configuration will be switched to the null driver" msgstr "Omrežne nastavitve bodo preklopljene na ničelni gonilnik" @@ -1234,7 +1234,7 @@ msgid "Open screenshots folder..." msgstr "Odprite mapo s posnetki zaslona..." msgid "Apply fullscreen stretch mode when maximized" -msgstr "Uporabi način celozaslonskega raztezanja v povečanem stanju" +msgstr "Uporabi način celozaslonskega raztezanja v maksimiranem stanju" msgid "Cursor/Puck" msgstr "Kazalec/ključ" @@ -1243,19 +1243,19 @@ msgid "Pen" msgstr "Pisalo" msgid "Host CD/DVD Drive (%1:)" -msgstr "Pogon CD/DVD gostitelja (%1:)" +msgstr "Gostiteljski pogon CD/DVD (%1:)" msgid "&Connected" msgstr "&Povezan" msgid "Clear image history" -msgstr "Jasna zgodovina slik" +msgstr "Počisti zgodovino slik" msgid "Create..." msgstr "Ustvari..." msgid "Host CD/DVD Drive (%1)" -msgstr "Pogon CD/DVD gostitelja (%1)" +msgstr "Gostiteljski pogon CD/DVD (%1)" msgid "Unknown Bus" msgstr "Neznano vodilo" @@ -1288,7 +1288,7 @@ msgid "Remove" msgstr "Odstrani" msgid "Browse..." -msgstr "Brskaj..." +msgstr "Prerskaj..." msgid "Couldn't create OpenGL context." msgstr "Ni bilo mogoče ustvariti konteksta OpenGL." @@ -1297,13 +1297,13 @@ msgid "Couldn't switch to OpenGL context." msgstr "Ni bilo mogoče preklopiti na kontekst OpenGL." msgid "OpenGL version 3.0 or greater is required. Current version is %1.%2" -msgstr "Zahteva se različica OpenGL 3.0 ali novejša. Trenutna različica je %1.%2" +msgstr "Potrebna je OpenGL različica 3.0 ali novejša. Trenutna različica je %1.%2" msgid "Error initializing OpenGL" msgstr "Napaka pri inicializaciji OpenGL" msgid "\nFalling back to software rendering." -msgstr "\nVrnitev k programskemu upodabljanju." +msgstr "\nVrnitev na programsko upodabljanje." msgid "<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>" msgstr "<html><head/><body><p>Pri izbiri medijskih slik (CD-ROM, disketa itd.) se bo odprto pogovorno okno začelo v istem imeniku kot konfiguracijska datoteka 86Box. Ta nastavitev bo verjetno imela pomen le v operacijskem sistemu MacOS.</p></body></html>" @@ -1312,7 +1312,7 @@ msgid "This machine might have been moved or copied." msgstr "Ta naprava je bila morda premeščena ali kopirana." msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure." -msgstr "Da bi zagotovili pravilno delovanje omrežja, mora 86Box vedeti, ali je bil ta stroj prestavljen ali kopiran.\n\nČe niste prepričani, izberite \"Kopiral sem jo\"." +msgstr "Da bi zagotovili pravilno delovanje omrežja, mora 86Box vedeti, ali je bil ta virtualna naprava prestavljena ali kopirana.\n\nČe niste prepričani, izberite \"Kopiral sem jo\"." msgid "I Moved It" msgstr "Premaknil sem jo" @@ -1348,7 +1348,7 @@ msgid "Interface:" msgstr "Vmesnik:" msgid "Adapter:" -msgstr "Adapter:" +msgstr "Mrežna kartica:" msgid "VDE Socket:" msgstr "Vtičnica VDE:" @@ -1396,7 +1396,7 @@ msgid "3M MicroTouch (Serial)" msgstr "3M MicroTouch (serijska)" msgid "[COM] Standard Hayes-compliant Modem" -msgstr "[COM] Standardni modem v skladu s standardom Hayes" +msgstr "[COM] Standardni modem v skladen s Hayes" msgid "Roland MT-32 Emulation" msgstr "Emulacija Roland MT-32" @@ -1411,10 +1411,10 @@ msgid "Roland CM-32LN Emulation" msgstr "Emulacija Roland CM-32LN" msgid "OPL4-ML Daughterboard" -msgstr "Hčerinska plošča OPL4-ML" +msgstr "Dodatna kartica OPL4-ML" msgid "System MIDI" -msgstr "Sistem MIDI" +msgstr "Sistemski MIDI" msgid "MIDI Input Device" msgstr "Vhodna naprava MIDI" @@ -1423,7 +1423,7 @@ msgid "BIOS Address" msgstr "Naslov BIOS-a" msgid "Enable BIOS extension ROM Writes" -msgstr "Omogočanje razširitve BIOS-a ROM piše" +msgstr "Omogoči zapisovanje razširitev BIOS ROM-a" msgid "Address" msgstr "Naslov" @@ -1435,7 +1435,7 @@ msgid "BIOS Revision" msgstr "Revizija BIOS-a" msgid "Translate 26 -> 17" -msgstr "Prevesti 26 -> 17" +msgstr "Prevedi 26 -> 17" msgid "Language" msgstr "Jezik" @@ -1450,25 +1450,25 @@ msgid "BIOS size" msgstr "Velikost BIOS-a" msgid "Map C0000-C7FFF as UMB" -msgstr "Zemljevid C0000-C7FFF kot UMB" +msgstr "Preslikaj C0000-C7FFF kot UMB" msgid "Map C8000-CFFFF as UMB" -msgstr "Zemljevid C8000-CFFFF kot UMB" +msgstr "Preslikaj C8000-CFFFF kot UMB" msgid "Map D0000-D7FFF as UMB" -msgstr "Zemljevid D0000-D7FFF kot UMB" +msgstr "Preslikaj D0000-D7FFF kot UMB" msgid "Map D8000-DFFFF as UMB" -msgstr "Zemljevid D8000-DFFFF kot UMB" +msgstr "Preslikaj D8000-DFFFF kot UMB" msgid "Map E0000-E7FFF as UMB" -msgstr "Zemljevid E0000-E7FFF kot UMB" +msgstr "Preslikaj E0000-E7FFF kot UMB" msgid "Map E8000-EFFFF as UMB" -msgstr "Zemljevid E8000-EFFFF kot UMB" +msgstr "Preslikaj E8000-EFFFF kot UMB" msgid "JS9 Jumper (JIM)" -msgstr "JS9 Jumper (JIM)" +msgstr "JS9 mostiček (JIM)" msgid "MIDI Output Device" msgstr "Izhodna naprava MIDI" @@ -1582,10 +1582,10 @@ msgid "RAM Address" msgstr "Naslov RAM" msgid "RAM size" -msgstr "Velikost pomnilnika RAM" +msgstr "Velikost pomnilnika" msgid "Initial RAM size" -msgstr "Začetna velikost pomnilnika RAM" +msgstr "Začetna velikost pomnilnika" msgid "Serial Number" msgstr "Serijska številka" @@ -1597,7 +1597,7 @@ msgid "FDC Address" msgstr "Naslov FDC" msgid "MPU-401 Address" -msgstr "MPU-401 Naslov" +msgstr "Naslov MPU-401" msgid "MPU-401 IRQ" msgstr "MPU-401 IRQ" @@ -1633,7 +1633,7 @@ msgid "Enable OPL" msgstr "Omogoči OPL" msgid "Receive MIDI input (MPU-401)" -msgstr "Sprejemaj vhod MIDI (MPU-401)" +msgstr "Vhod MIDI za sprejem (MPU-401)" msgid "SB low DMA" msgstr "Nizki DMA SB" @@ -1666,7 +1666,7 @@ msgid "Codec" msgstr "Kodek" msgid "GUS type" -msgstr "Tip GUS" +msgstr "Vrsta GUS" msgid "Enable 0x04 \"Exit 86Box\" command" msgstr "Omogoči ukaz 0x04 \"Zapusti 86Box\"" @@ -1681,7 +1681,7 @@ msgid "RGB type" msgstr "Vrsta RGB zaslona" msgid "Line doubling type" -msgstr "Vrsta podvojitve črt" +msgstr "Vrsta podvojevanja črt" msgid "Snow emulation" msgstr "Emulacija snega" @@ -1693,16 +1693,16 @@ msgid "Character set" msgstr "Nabor znakov" msgid "XGA type" -msgstr "Tip kartice XGA" +msgstr "Vrsta kartice XGA" msgid "Instance" -msgstr "Primer" +msgstr "Primerek" msgid "MMIO Address" msgstr "Naslov MMIO" msgid "RAMDAC type" -msgstr "Vrsta čipa RAMDAC" +msgstr "Vrsta RAMDAC" msgid "Blend" msgstr "Mešanica" @@ -1714,13 +1714,13 @@ msgid "Dithering" msgstr "Barvno stresanje" msgid "Enable NMI for CGA emulation" -msgstr "Omogočite NMI za emulacijo CGA" +msgstr "Omogoči NMI za emulacijo CGA" msgid "Voodoo type" -msgstr "Tip kartice Voodoo" +msgstr "Vrsta kartice Voodoo" msgid "Framebuffer memory size" -msgstr "Velikost pomnilnika predpomnilnika okvirja" +msgstr "Velikost videopomnilnika" msgid "Texture memory size" msgstr "Velikost pomnilnika tekstur" @@ -1732,7 +1732,7 @@ msgid "Screen Filter" msgstr "Filter zaslona" msgid "Render threads" -msgstr "Nitke za upodabljanje" +msgstr "Niti za upodabljanje" msgid "SLI" msgstr "SLI" @@ -1795,7 +1795,7 @@ msgid "Non-timed (original)" msgstr "Brez časovnika (izvirnik)" msgid "45 Hz (JMP2 not populated)" -msgstr "45 Hz (brez mostička na JMP2)" +msgstr "45 Hz (brez mostička JMP2)" msgid "Two" msgstr "Dva" @@ -1804,13 +1804,13 @@ msgid "Three" msgstr "Tri" msgid "Wheel" -msgstr "Kolesa" +msgstr "Kolesce" msgid "Five + Wheel" -msgstr "Pet + kolo" +msgstr "Pet + kolesce" msgid "Five + 2 Wheels" -msgstr "" +msgstr "Pet + 2 kolesci" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 serijska / SMT3(R)V" @@ -1885,13 +1885,13 @@ msgid "Color (generic)" msgstr "Barvni (generični)" msgid "Green Monochrome" -msgstr "Zeleni enobvarni" +msgstr "Zeleni monokromatski" msgid "Amber Monochrome" -msgstr "Jantarni enobarvni" +msgstr "Jantarni monokromatski" msgid "Gray Monochrome" -msgstr "Sivi enobarvni" +msgstr "Sivi monokromatski" msgid "Color (no brown)" msgstr "Barvni (brez rjave)" @@ -1912,13 +1912,13 @@ msgid "128 KB" msgstr "128 KB" msgid "Monochrome (5151/MDA) (white)" -msgstr "Enobarvni (5151/MDA) (beli)" +msgstr "Monokromatski (5151/MDA) (beli)" msgid "Monochrome (5151/MDA) (green)" -msgstr "Enobarvni (5151/MDA) (zeleni)" +msgstr "Monokromatski (5151/MDA) (zeleni)" msgid "Monochrome (5151/MDA) (amber)" -msgstr "Enobarvni (5151/MDA) (jantarni)" +msgstr "Monokromatski (5151/MDA) (jantarni)" msgid "Color 40x25 (5153/CGA)" msgstr "Barvni 40x25 (5153/CGA)" @@ -1930,7 +1930,7 @@ msgid "Enhanced Color - Normal Mode (5154/ECD)" msgstr "Izboljšani barvni - običajni način (5154/ECD)" msgid "Enhanced Color - Enhanced Mode (5154/ECD)" -msgstr "Izboljšani barvni - Izboljšani način (5154/ECD)" +msgstr "Izboljšani barvni - izboljšani način (5154/ECD)" msgid "Green" msgstr "Zeleni" @@ -2008,7 +2008,7 @@ msgid "Generic PCL5e Printer" msgstr "Generični tiskalnik PCL5e" msgid "Parallel Line Internet Protocol" -msgstr "Internetni protokol za paralelno linijo" +msgstr "Internetni protokol za vzporedno linijo" msgid "Protection Dongle for Savage Quest" msgstr "Zaščitni ključek za Savage Quest" @@ -2029,7 +2029,7 @@ msgid "Data bits" msgstr "Podatkovni biti" msgid "Stop bits" -msgstr "Stop biti" +msgstr "Zaključni biti" msgid "Baud Rate of Passthrough" msgstr "Baudna hitrost prepusta" @@ -2038,7 +2038,7 @@ msgid "Named Pipe (Server)" msgstr "Poimenovana cev (Strežnik)" msgid "Host Serial Passthrough" -msgstr "Prepustno serijskih vrat gostitelja" +msgstr "Prepust serijskih vrat gostitelja" msgid "E&ject %1" msgstr "I&zvrzi %1" @@ -2053,7 +2053,7 @@ msgid "High performance impact" msgstr "Visok učinek na hitrost delovanja" msgid "[Generic] RAM Disk (max. speed)" -msgstr "[Generic] Pogon RAM (največja hitrost)" +msgstr "[Generic] Pomnilniški disk (največja hitrost)" msgid "[Generic] 1989 (3500 RPM)" msgstr "" @@ -2089,28 +2089,28 @@ msgid "Generic PC/AT Memory Expansion" msgstr "Generična razširitev pomnilnika PC/AT" msgid "Unable to find Dot-Matrix fonts" -msgstr "Matričnih pisav ni bilo mogoče najti" +msgstr "Ni bilo mogoče najti matričnih pisav" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." -msgstr "Matrične pisave v imeniku \"roms/printer/fonts\" so potrebne za emulacijo generičnega matričnega tiskalnika ESC/P." +msgstr "Za emulacijo generičnega ESC/P matričnega tiskalnika so potrebne TrueType pisave v imeniku \"roms/printer/fonts\"." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Blokiraj multimedijske tipke" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Vprašaj za potrditev pred shranjevanjem nastavitev" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Vprašaj za potrditev pred ponovnim zagonom" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Vprašaj za potrditev pred izhodom" msgid "Display hotkey message when entering full-screen mode" -msgstr "" +msgstr "Prikaži obvestilo o bližnjični tipki pri prehodu v celozaslonski način" msgid "Options" -msgstr "" +msgstr "Možnosti" msgid "Model" msgstr "" @@ -2119,40 +2119,40 @@ msgid "Model:" msgstr "" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Inicializacija upodobljevalnika Vulkan ni uspela." msgid "GLSL Error" -msgstr "" +msgstr "Napaka GLSL" msgid "Could not load shader: %1" -msgstr "" +msgstr "Ni bilo mogoče naložiti senčilnika: %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "Potrebna je OpenGL različica 3.0 ali novejša. Trenutna različica GLSL je %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "Ni bilo mogoče naložiti teksture: %1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "Ni bilo mogoče prevesti senčilnika:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "Program ni povezan:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "Upravljalnik senčilnikov" msgid "Shader Configuration" -msgstr "" +msgstr "Nastavitve senčilnikov" msgid "Add" -msgstr "" +msgstr "Dodaj" msgid "Move up" -msgstr "" +msgstr "Premakni gor" msgid "Move down" -msgstr "" +msgstr "Premakni dol" msgid "Could not load file %1" -msgstr "" +msgstr "Ni bilo mogoče naložiti datoteke %1" From b1d409471c37bac854a551cbeedfae45c04e2d9d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 4 May 2025 02:01:34 +0200 Subject: [PATCH 0834/1190] Fixes to the S3 911/924 of the night (May 4th, 2025) 1. Actually mostly workarounds to make it render normally without a hitch (I hope) using the Diamond Stealth VRAM 911-based 15bpp driver. 2. Updated logs. --- src/video/vid_s3.c | 240 +++++++++++++++++++++++++++++---------------- 1 file changed, 156 insertions(+), 84 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8fa392891..d6b91903a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -234,6 +234,8 @@ typedef struct s3_t { uint8_t advfunc_cntl; uint16_t cur_y, cur_y2; uint16_t cur_x, cur_x2; + uint16_t cur_x_overflow; + uint16_t destx_overflow; uint16_t x2, ropmix; uint16_t pat_x, pat_y; int16_t desty_axstp, desty_axstp2; @@ -288,6 +290,7 @@ typedef struct s3_t { int16_t minus; int rd_mask_16bit_check; int start; + int mix_dat_upper; /*For non-threaded FIFO*/ int setup_fifo_slot; @@ -657,22 +660,29 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) val = (val >> 8) | (val << 8); s3->accel_start(16, 1, val | (val << 16), 0, s3); - } else - s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } else { - if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.cmd == 0x53f1) { + } else { + if ((s3->accel.cmd == 0x53f1) || (s3->accel.cmd == 0x53b1)) { if (s3->accel.cur_x & 0x400) val = (val >> 8) | (val << 8); s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); val = (val >> 8) | (val << 8); - s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } else - s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } else + } s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } + } else { + if (s3->accel.rd_mask_16bit_check) { + if ((s3->accel.cmd == 0x53f1) || (s3->accel.cmd == 0x53b1)) { + if (s3->accel.cur_x & 0x400) + val = (val >> 8) | (val << 8); + + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + + val = (val >> 8) | (val << 8); + } + } + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } break; case 0x400: @@ -808,12 +818,14 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x8548: case 0x86e8: s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; + s3->accel.cur_x_overflow = (s3->accel.cur_x_overflow & 0xff00) | val; s3->accel.poly_cx = s3->accel.cur_x << 20; s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x8549: case 0x86e9: s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x0f) << 8); + s3->accel.cur_x_overflow = (s3->accel.cur_x_overflow & 0xff) | (val << 8); s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; s3->accel.poly_x = s3->accel.poly_cx >> 20; s3_log("[%04X:%08X] OUT PORTB=%04x, val=%04x.\n", CS, cpu_state.pc, port - 1, s3->accel.cur_x); @@ -859,11 +871,13 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x8d48: case 0x8ee8: s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; + s3->accel.destx_overflow = (s3->accel.destx_overflow & 0xff00) | val; s3->accel.point_1_updated = 1; break; case 0x8d49: case 0x8ee9: s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); + s3->accel.destx_overflow = (s3->accel.destx_overflow & 0xff) | (val << 8); if (val & 0x20) s3->accel.destx_distp |= ~0x3fff; s3->accel.point_1_updated = 1; @@ -5763,6 +5777,8 @@ s3_accel_in_w(uint16_t port, void *priv) s3_t *s3 = (s3_t *) priv; svga_t *svga = &s3->svga; uint16_t temp = 0x0000; + uint16_t temp1 = 0x0000; + uint16_t temp2 = 0x0000; const uint16_t *vram_w = (uint16_t *) svga->vram; if (!s3->enable_8514) @@ -5774,7 +5790,7 @@ s3_accel_in_w(uint16_t port, void *priv) switch (s3->accel.cmd & 0x600) { case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 0x02)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { if (s3->accel.cmd & 0x1000) temp = (temp >> 8) | (temp << 8); @@ -5800,15 +5816,31 @@ s3_accel_in_w(uint16_t port, void *priv) } break; case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 0x02)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { if (s3->accel.cmd & 0x1000) temp = (temp >> 8) | (temp << 8); + s3->accel_start(16, 1, temp | (temp << 16), 0, s3); } else s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else { - s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cmd == 0x53b0) { + temp1 = vram_w[dword_remap_w(svga, s3->accel.dest + s3->accel.cx - s3->accel.minus) & (s3->vram_mask >> 1)]; + temp2 = vram_w[dword_remap_w(svga, s3->accel.dest + s3->accel.cx - s3->accel.minus + 1) & (s3->vram_mask >> 1)]; + if (s3->accel.cur_x & 0x400) { + temp = temp1 >> 8; + temp |= (temp2 >> 8) << 8; + } else { + temp = temp1 & 0xff; + temp |= ((temp2 & 0xff) << 8); + } + s3->accel_start(4, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } break; @@ -7878,7 +7910,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ - s3_log("CMD=%d, full=%04x, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%04x, mix=%04x, count=%d, rd_mask=%04x, wrt_mask=%04x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%04x, bkgdcolor=%04x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x.\n", cmd, s3->accel.cmd, s3->bpp, clip_r, clip_b, vram_mask, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffff, mix_dat & 0xffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix); + s3_log("CMD=%d, full=%04x, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%02x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%04x, mix=%04x, count=%d, rd_mask=%04x, wrt_mask=%04x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%04x, bkgdcolor=%04x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x.\n", cmd, s3->accel.cmd, s3->bpp, clip_r, clip_b, s3->accel.multifunc[0x0a] & 0xc4, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffff, mix_dat & 0xffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -8279,8 +8311,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi case 2: /*Rectangle fill*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { - s3->accel.start = 0; s3->accel.minus = 0; + s3->accel.mix_dat_upper = 0; s3->accel.color_16bit_check_pixtrans = 0; s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; @@ -8292,11 +8324,37 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->bpp == 0) && s3->color_16bit) { s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); if (s3->accel.rd_mask_16bit_check) { - s3->accel.start = 1; - if (s3->accel.cur_x & 0x400) { - s3->accel.minus = 0x400; - if ((s3->accel.cmd == 0x41b3) && (frgd_mix == 0)) - s3->accel.minus = 0; + if (s3->accel.cmd == 0x41b3) { + if (frgd_mix == 0) { + if (!(s3->accel.cur_x & 0x400)) + s3->accel.color_16bit_check = 0; + } else { + if ((s3->accel.cur_x_overflow & 0xc00) == 0xc00) + s3->accel.start = 1; + else { + if (s3->accel.start) { + s3->accel.start = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.start = 0; + if (s3->accel.cur_x_overflow & 0x400) + s3->accel.minus = 0x400; + } + } + } + } else { + if ((s3->accel.cur_x_overflow & 0xc00) == 0xc00) + s3->accel.start = 1; + else { + if (s3->accel.start) { + s3->accel.start = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.start = 0; + if (s3->accel.cur_x_overflow & 0x400) + s3->accel.minus = 0x400; + } + } } } else { if (s3->accel.cmd & 0x100) { @@ -8330,19 +8388,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.cur_x & 0x400) { - if (s3->accel.start) { - s3->accel.minus = 0x400; - s3->accel.start = 0; - } + if (s3->accel.minus) { wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); frgd_color = (s3->accel.frgd_color_actual[1] << 8); bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); } else { - if (s3->accel.start) { - s3->accel.minus = 0; - s3->accel.start = 0; - } wrt_mask = s3->accel.wrt_mask_actual[0]; frgd_color = s3->accel.frgd_color_actual[0]; bkgd_color = s3->accel.bkgd_color_actual[0]; @@ -8355,7 +8405,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (s3->accel.cmd == 0x41b3) { if (frgd_mix != 0) { if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.cur_x & 0x400) { + if (s3->accel.minus) { wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); frgd_color = (s3->accel.frgd_color_actual[1] << 8); bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); @@ -8367,39 +8417,33 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi rd_mask &= 0x00ff; } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400)) break; + } else { + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); + } else { + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; + s3->accel.mix_dat_upper = !!(mix_dat & 0xff00); + } + rd_mask &= 0x00ff; + } } } else { if (s3->accel.rd_mask_16bit_check) { - rd_mask &= 0x00ff; - if (s3->accel.cmd == 0x53b3) { - if (clip_l & 0x400) { - if (s3->accel.start) { - s3->accel.minus = 0x400; - s3->accel.start = 0; - } - wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); - frgd_color = (s3->accel.frgd_color_actual[1] << 8); - bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); - } else { - if (s3->accel.start) { - s3->accel.minus = 0; - s3->accel.start = 0; - } - wrt_mask = s3->accel.wrt_mask_actual[0]; - frgd_color = s3->accel.frgd_color_actual[0]; - bkgd_color = s3->accel.bkgd_color_actual[0]; - } + if (s3->accel.minus) { + wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); + frgd_color = (s3->accel.frgd_color_actual[1] << 8); + bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); } else { - if (s3->accel.cur_x & 0x400) { - wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); - frgd_color = (s3->accel.frgd_color_actual[1] << 8); - bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); - } else { - wrt_mask = s3->accel.wrt_mask_actual[0]; - frgd_color = s3->accel.frgd_color_actual[0]; - bkgd_color = s3->accel.bkgd_color_actual[0]; - } + wrt_mask = s3->accel.wrt_mask_actual[0]; + frgd_color = s3->accel.frgd_color_actual[0]; + bkgd_color = s3->accel.bkgd_color_actual[0]; } + rd_mask &= 0x00ff; } else { if ((s3_cpu_src(s3)) && !(s3->accel.cmd & 0x200)) { s3_log("FIXME: S3 911/924 15/16bpp documentation needed.\n"); @@ -8414,6 +8458,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } + if (s3->accel.mix_dat_upper) + s3_log("CMDFULL=%04x, FRGDMIX=%x, BKGDCOLR=%04x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, OVERFLOW=%d.\n", s3->accel.cmd, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_color, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, (s3->accel.cur_x_overflow & 0xc00) == 0xc00); + while (count-- && (s3->accel.sy >= 0)) { if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) { mix_dat >>= 16; @@ -8535,15 +8582,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (cpu_input) { if (s3->accel.sy < 0) { if ((s3->bpp == 0) && s3->color_16bit) { - if ((s3->accel.cmd == 0x53b3) && !s3->accel.b2e8_pix) { - if (!(clip_l & 0x400)) - s3->accel.color_16bit_check = 1; - else + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) s3->accel.color_16bit_check = 0; - } else { - if (!(s3->accel.cur_x & 0x400)) - s3->accel.color_16bit_check = 1; else + s3->accel.color_16bit_check = 1; + + if ((s3->accel.cmd == 0x41b3) && (frgd_mix == 0)) s3->accel.color_16bit_check = 0; } } @@ -8556,10 +8601,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } if (s3->accel.sy < 0) { if ((s3->bpp == 0) && s3->color_16bit) { - if (!(s3->accel.cur_x & 0x400)) - s3->accel.color_16bit_check = 1; - else - s3->accel.color_16bit_check = 0; + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) + s3->accel.color_16bit_check = 0; + else + s3->accel.color_16bit_check = 1; + } } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -8674,10 +8721,24 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.dx = s3->accel.destx_distp & 0xfff; s3->accel.dy = s3->accel.desty_axstp & 0xfff; - s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); - if ((s3->bpp == 0) && s3->color_16bit && (s3->accel.destx_distp & 0x400) && s3->accel.rd_mask_16bit_check) - s3->accel.minus = 0x400; + if ((s3->bpp == 0) && s3->color_16bit) { + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + if (s3->accel.rd_mask_16bit_check) { + if (!(s3->accel.cmd & 0x40) && !(clip_r & 0x400)) + s3->accel.start = 1; + else { + if (s3->accel.start) { + s3->accel.start = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.start = 0; + if (s3->accel.destx_distp & 0x400) + s3->accel.minus = 0x400; + } + } + } + } if (s3->accel.destx_distp & 0x400) { s3_log("BitBLT + 1024 FULLCMD=%04x: frgdcolor=%04x, s=%d,%d, d=%d,%d, frmix=%x, bkmix=%x, pixcntl=%02x.\n", s3->accel.cmd, frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.dx, s3->accel.dy, frgd_mix, bkgd_mix, s3->accel.multifunc[0xa] & 0xc0); @@ -8698,7 +8759,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->bpp == 0) && s3->color_16bit) { if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.destx_distp & 0x400) { + if (s3->accel.minus) { wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); frgd_color = (s3->accel.frgd_color_actual[1] << 8); bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); @@ -8712,6 +8773,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } + if (!vram_mask && (frgd_mix == 3)) + s3_log("CMDFULL=%04x, FRGDMIX=%x, BKGDMIX=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00); + if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { while (1) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { @@ -8728,6 +8792,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.dx++; s3->accel.sx--; s3->accel.dx &= 0xfff; + if (s3->accel.sx < 0) { s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; @@ -8742,11 +8807,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.sy--; if (s3->accel.sy < 0) { - if ((s3->bpp == 0) && s3->color_16bit) { - if (!(s3->accel.destx_distp & 0x400)) - s3->accel.color_16bit_check = 1; - else + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) s3->accel.color_16bit_check = 0; + else + s3->accel.color_16bit_check = 1; } s3->accel.destx_distp = s3->accel.dx; s3->accel.desty_axstp = s3->accel.dy; @@ -8824,7 +8889,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cx--; s3->accel.dx--; } - s3->accel.dx &= 0xfff; + if (s3->accel.rd_mask_16bit_check) + s3->accel.dx &= 0x7ff; + else + s3->accel.dx &= 0xfff; + s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) { @@ -8850,21 +8919,24 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (cpu_input) { if (s3->accel.sy < 0) { - if ((s3->bpp == 0) && s3->color_16bit) { - if (!(s3->accel.destx_distp & 0x400)) - s3->accel.color_16bit_check = 1; - else + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) s3->accel.color_16bit_check = 0; + else + s3->accel.color_16bit_check = 1; } } return; } if (s3->accel.sy < 0) { - if ((s3->bpp == 0) && s3->color_16bit) { - if (!(s3->accel.destx_distp & 0x400)) - s3->accel.color_16bit_check = 1; + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) + s3->accel.color_16bit_check = 0; else + s3->accel.color_16bit_check = 1; + + if (s3->accel.mix_dat_upper && !vram_mask && (frgd_mix == 3)) s3->accel.color_16bit_check = 0; } s3->accel.destx_distp = s3->accel.dx; From 608ce2d15537751e594029b460c80c3d06cb0be3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 4 May 2025 02:04:41 +0200 Subject: [PATCH 0835/1190] Another stall fix for the mach8/32. See above, covering the foreground and background select bits as well. --- src/video/vid_ati_mach8.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index ce6ee12d5..3537cf337 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -4264,12 +4264,14 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in if (dev->force_busy) { temp |= 0x0200; /*Hardware busy*/ if (mach->accel.cmd_type >= 0) { + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; mono_src = (mach->accel.dp_config >> 5) & 3; switch (mach->accel.cmd_type) { case 2: if (dev->accel.sy >= mach->accel.height) dev->force_busy = 0; - else if (mono_src == 2) + else if ((mono_src == 2) || (frgd_sel == 2) || (bkgd_sel == 2)) dev->force_busy = 0; break; case 5: From 3bce5e13f1c234f9f0e573679fe8389320bead30 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 May 2025 02:19:48 +0200 Subject: [PATCH 0836/1190] SiS 5511 Host to PCI bridge: Fix DRB unit, fixes AOpen AP5S soft reset. --- src/chipset/sis_5511_h2p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c index b94e69f26..c8cb44a0a 100644 --- a/src/chipset/sis_5511_h2p.c +++ b/src/chipset/sis_5511_h2p.c @@ -259,7 +259,7 @@ sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv) case 0x7a: /* DRAM Bank Register 2-1 */ case 0x7c: /* DRAM Bank Register 3-0 */ case 0x7e: /* DRAM Bank Register 3-1 */ - spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82); + spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x02); break; case 0x71: /* DRAM Bank Register 0-0 */ From dca7ed737c4f82e43c536ea8b004d7b04fbff536 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 May 2025 23:58:41 +0200 Subject: [PATCH 0837/1190] SiS 85c471: Fix DRAM banks, fixes #5545. --- src/chipset/sis_85c4xx.c | 194 ++++++++++++++++++++++++--------------- 1 file changed, 122 insertions(+), 72 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 51f7fd4e6..1c1e0614b 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -33,6 +33,7 @@ #include <86box/mem.h> #include <86box/smram.h> #include <86box/pic.h> +#include <86box/plat_fallthrough.h> #include <86box/keyboard.h> #include <86box/machine.h> #include <86box/chipset.h> @@ -82,6 +83,14 @@ static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d }; +static uint8_t ram_asus[64] = { 0x00, 0x00, 0x01, 0x10, 0x10, 0x20, 0x03, 0x11, + 0x11, 0x05, 0x05, 0x12, 0x12, 0x13, 0x13, 0x13, + 0x13, 0x21, 0x06, 0x14, 0x14, 0x15, 0x15, 0x15, + 0x15, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, + 0x17, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; static uint8_t ram_tg486g[64] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, @@ -162,17 +171,32 @@ sis_85c471_get_row(ram_bank_t *dev, uint32_t addr) uint32_t ret = 0x00000000; switch (dev->virt_size) { - case 0x04000000: - ret = (addr >> 14) & 0x00000fff; - break; - case 0x01000000: - ret = (addr >> 13) & 0x000007ff; + case 0x00100000: + case 0x00200000: + ret |= (addr >> 13) & 0x00000001; + ret |= ((addr >> 12) & 0x00000001) << 1; + ret |= ((addr >> 14) & 0x0000003f) << 2; + ret |= ((addr >> 11) & 0x00000001) << 8; + ret |= ((addr >> 20) & 0x00000001) << 9; + ret |= ((addr >> 22) & 0x00000001) << 10; + ret |= ((addr >> 24) & 0x00000001) << 11; break; case 0x00400000: - ret = (addr >> 12) & 0x000003ff; + case 0x00800000: + ret |= (addr >> 13) & 0x00000001; + ret |= ((addr >> 12) & 0x00000001) << 1; + ret |= ((addr >> 14) & 0x000000ff) << 2; + ret |= ((addr >> 22) & 0x00000001) << 10; + ret |= ((addr >> 24) & 0x00000001) << 11; break; - case 0x00100000: - ret = (addr >> 11) & 0x000001ff; + case 0x01000000: + case 0x02000000: + case 0x04000000: + ret |= (addr >> 13) & 0x00000001; + ret |= ((addr >> 22) & 0x00000001) << 1; + ret |= ((addr >> 14) & 0x000000ff) << 2; + ret |= ((addr >> 23) & 0x00000001) << 10; + ret |= ((addr >> 24) & 0x00000001) << 11; break; } @@ -185,17 +209,31 @@ sis_85c471_get_col(ram_bank_t *dev, uint32_t addr) uint32_t ret = 0x00000000; switch (dev->virt_size) { - case 0x04000000: - ret = (addr >> 2) & 0x00000fff; - break; - case 0x01000000: - ret = (addr >> 2) & 0x000007ff; + case 0x00100000: + case 0x00200000: + ret |= (addr >> 3) & 0x00000001; + ret |= ((addr >> 2) & 0x00000001) << 1; + ret |= ((addr >> 4) & 0x0000003f) << 2; + ret |= ((addr >> 10) & 0x00000001) << 8; + ret |= ((addr >> 21) & 0x00000001) << 9; + ret |= ((addr >> 23) & 0x00000001) << 10; + ret |= ((addr >> 25) & 0x00000001) << 11; break; case 0x00400000: - ret = (addr >> 2) & 0x000003ff; + case 0x00800000: + ret |= (addr >> 3) & 0x00000001; + ret |= ((addr >> 2) & 0x00000001) << 1; + ret |= ((addr >> 4) & 0x000000ff) << 2; + ret |= ((addr >> 23) & 0x00000001) << 10; + ret |= ((addr >> 25) & 0x00000001) << 11; break; - case 0x00100000: - ret = (addr >> 2) & 0x000001ff; + case 0x01000000: + case 0x02000000: + case 0x04000000: + ret |= (addr >> 3) & 0x00000001; + ret |= ((addr >> 2) & 0x00000001) << 1; + ret |= ((addr >> 4) & 0x000001ff) << 2; + ret |= ((addr >> 25) & 0x00000001) << 11; break; } @@ -208,17 +246,26 @@ sis_85c471_set_row(ram_bank_t *dev, uint32_t addr) uint32_t ret = 0x00000000; switch (dev->phys_size) { - case 0x04000000: - ret = (addr & 0x00000fff) << 14; + case 0x00100000: + ret = (addr & 0x1ff) << 11; break; - case 0x01000000: - ret = (addr & 0x000007ff) << 13; + case 0x00200000: + ret = (addr & 0x3ff) << 11; break; case 0x00400000: - ret = (addr & 0x000003ff) << 12; + ret = (addr & 0x3ff) << 12; break; - case 0x00100000: - ret = (addr & 0x000002ff) << 11; + case 0x00800000: + ret = (addr & 0x7ff) << 12; + break; + case 0x01000000: + ret = (addr & 0x7ff) << 13; + break; + case 0x02000000: + ret = (addr & 0xfff) << 13; + break; + case 0x04000000: + ret = (addr & 0xfff) << 14; break; } @@ -231,23 +278,28 @@ sis_85c471_set_col(ram_bank_t *dev, uint32_t addr) uint32_t ret = 0x00000000; switch (dev->phys_size) { - case 0x04000000: - ret = (addr & 0x00000fff) << 2; - break; - case 0x01000000: - ret = (addr & 0x000007ff) << 2; + case 0x00100000: + case 0x00200000: + ret = (addr & 0x1ff) << 2; break; case 0x00400000: - ret = (addr & 0x000003ff) << 2; + case 0x00800000: + ret = (addr & 0x3ff) << 2; break; - case 0x00100000: - ret = (addr & 0x000002ff) << 2; + case 0x01000000: + case 0x02000000: + ret = (addr & 0x7ff) << 2; + break; + case 0x04000000: + ret = (addr & 0xfff) << 2; break; } return ret; } +uint8_t reg09 = 0x00; + static uint8_t sis_85c471_read_ram(uint32_t addr, void *priv) { @@ -255,12 +307,10 @@ sis_85c471_read_ram(uint32_t addr, void *priv) uint32_t rel = addr - dev->virt_base; uint8_t ret = 0xff; - if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { - uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); - uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); - uint32_t dw = rel & 0x00000003; - rel = row | col | dw; - } + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; addr = (rel + dev->phys_base); @@ -277,12 +327,10 @@ sis_85c471_read_ramw(uint32_t addr, void *priv) uint32_t rel = addr - dev->virt_base; uint16_t ret = 0xffff; - if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { - uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); - uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); - uint32_t dw = rel & 0x00000003; - rel = row | col | dw; - } + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; addr = (rel + dev->phys_base); @@ -299,12 +347,10 @@ sis_85c471_read_raml(uint32_t addr, void *priv) uint32_t rel = addr - dev->virt_base; uint32_t ret = 0xffffffff; - if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { - uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); - uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); - uint32_t dw = rel & 0x00000003; - rel = row | col | dw; - } + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; addr = (rel + dev->phys_base); @@ -320,12 +366,10 @@ sis_85c471_write_ram(uint32_t addr, uint8_t val, void *priv) ram_bank_t *dev = (ram_bank_t *) priv; uint32_t rel = addr - dev->virt_base; - if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { - uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); - uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); - uint32_t dw = rel & 0x00000003; - rel = row | col | dw; - } + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; addr = (rel + dev->phys_base); @@ -339,12 +383,10 @@ sis_85c471_write_ramw(uint32_t addr, uint16_t val, void *priv) ram_bank_t *dev = (ram_bank_t *) priv; uint32_t rel = addr - dev->virt_base; - if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { - uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); - uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); - uint32_t dw = rel & 0x00000003; - rel = row | col | dw; - } + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; addr = (rel + dev->phys_base); @@ -358,12 +400,10 @@ sis_85c471_write_raml(uint32_t addr, uint32_t val, void *priv) ram_bank_t *dev = (ram_bank_t *) priv; uint32_t rel = addr - dev->virt_base; - if ((dev->virt_size == 0x01000000) && (dev->phys_size == 0x00400000)) { - uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); - uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); - uint32_t dw = rel & 0x00000003; - rel = row | col | dw; - } + uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel)); + uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel)); + uint32_t dw = rel & 0x00000003; + rel = row | col | dw; addr = (rel + dev->phys_base); @@ -492,6 +532,8 @@ sis_85c471_banks_split(uint32_t *b_ex, uint32_t *banks) static void sis_85c471_banks_recalc(sis_85c4xx_t *dev) { + reg09 = dev->regs[0x09]; + for (uint8_t i = 0; i < 8; i++) mem_mapping_disable(&dev->ram_banks[i].mapping); @@ -694,17 +736,25 @@ sis_85c4xx_reset(void *priv) if (dev->is_471) { dev->regs[0x09] = 0x40; - if (mem_size_mb >= 64) { + + if (!strcmp(machine_get_internal_name(), "vli486sv2g")) { + if (mem_size_mb == 64) + dev->regs[0x09] |= 0x1f; + else + dev->regs[0x09] |= ram_asus[mem_size_mb]; + } else if (mem_size_mb >= 64) { if ((mem_size_mb >= 64) && (mem_size_mb < 68)) dev->regs[0x09] |= 0x33; - if ((mem_size_mb >= 68) && (mem_size_mb < 72)) + else if ((mem_size_mb >= 68) && (mem_size_mb < 72)) dev->regs[0x09] |= 0x2b; - if ((mem_size_mb >= 72) && (mem_size_mb < 80)) + else if ((mem_size_mb >= 72) && (mem_size_mb < 80)) dev->regs[0x09] |= 0x2d; - if ((mem_size_mb >= 80) && (mem_size_mb < 96)) + else if ((mem_size_mb >= 80) && (mem_size_mb < 96)) dev->regs[0x09] |= 0x2f; + else if ((mem_size_mb >= 96) && (mem_size_mb < 128)) + dev->regs[0x09] |= 0x34; else - dev->regs[0x09] |= 0x29; + dev->regs[0x09] |= 0x35; } else if (!strcmp(machine_get_internal_name(), "tg486g")) dev->regs[0x09] |= ram_tg486g[mem_size_mb]; else From 6a6be85852bcd1946bd6f8bd4038d5d6d68b393c Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 5 May 2025 02:02:02 +0200 Subject: [PATCH 0838/1190] Late night fixes for the Mach8 (May 5th, 2025) 1. The Mach8 doesn't have separate graphics pitches a la Mach32 (68800-6 and up), fixes the rendering in some drivers for Windows. 2. Special case for the add-on Mach8 for the mode switching (resolution only). --- src/video/vid_ati_mach8.c | 56 +++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 3537cf337..8423f096b 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2681,7 +2681,6 @@ ati_render_32bpp(svga_t *svga) When ATI mode is selected, allow complete auto-detection. But when 8514/A mode is selected, allow detection based on the shadow register sets. */ - static void mach_set_resolution(mach_t *mach, svga_t *svga) { @@ -2707,15 +2706,27 @@ mach_set_resolution(mach_t *mach, svga_t *svga) if (dev->interlace) dev->v_syncstart >>= 1; - if ((mach->accel.clock_sel & 0x01) && !(mach->old_on2 & 0x01) && - !(dev->accel.advfunc_cntl & 0x01)) - ret = 2; - else if ((dev->accel.advfunc_cntl & 0x01) && !(mach->old_on1 & 0x01) && - !(mach->accel.clock_sel & 0x01)) - ret = 1; - else if ((!(dev->accel.advfunc_cntl & 0x01) && (mach->old_on1 & 0x01)) || - (!(mach->accel.clock_sel & 0x01) && (mach->old_on2 & 0x01))) - ret = 0; + if (ATI_8514A_ULTRA) { + if ((mach->accel.clock_sel & 0x01) && + !(dev->accel.advfunc_cntl & 0x01)) + ret = 2; + else if ((dev->accel.advfunc_cntl & 0x01) && + !(mach->accel.clock_sel & 0x01)) + ret = 1; + else if ((!(dev->accel.advfunc_cntl & 0x01) && (mach->old_on1 & 0x01)) || + (!(mach->accel.clock_sel & 0x01) && (mach->old_on2 & 0x01))) + ret = 0; + } else { + if ((mach->accel.clock_sel & 0x01) && !(mach->old_on2 & 0x01) && + !(dev->accel.advfunc_cntl & 0x01)) + ret = 2; + else if ((dev->accel.advfunc_cntl & 0x01) && !(mach->old_on1 & 0x01) && + !(mach->accel.clock_sel & 0x01)) + ret = 1; + else if ((!(dev->accel.advfunc_cntl & 0x01) && (mach->old_on1 & 0x01)) || + (!(mach->accel.clock_sel & 0x01) && (mach->old_on2 & 0x01))) + ret = 0; + } if (ret) { if (ret == 2) @@ -2730,11 +2741,13 @@ mach_set_resolution(mach_t *mach, svga_t *svga) if (dev->hdisp == 640) { dev->hdisp = 1024; dev->vdisp = 768; + mach_log("1024x768.\n"); } } else { if (dev->hdisp == 1024) { dev->hdisp = 640; dev->vdisp = 480; + mach_log("640x480.\n"); } } svga_recalctimings(svga); @@ -2764,7 +2777,6 @@ ati8514_recalctimings(svga_t *svga) mach_log("ON=%d, vgahdisp=%d.\n", dev->on, svga->hdisp); if (dev->on) { - mach_log("8514/A ON, pitch=%d.\n", dev->ext_pitch); dev->interlace = !!(dev->disp_cntl & 0x10); dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; @@ -2773,16 +2785,19 @@ ati8514_recalctimings(svga_t *svga) mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2; dev->accel.ge_offset -= mach->accel.crt_offset; + 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); - mach->accel.src_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach->accel.dst_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.src_pitch = dev->pitch; + mach->accel.dst_pitch = dev->pitch; mach->accel.src_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; mach->accel.dst_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; mach->accel.src_ge_offset -= mach->accel.crt_offset; mach->accel.dst_ge_offset -= mach->accel.crt_offset; + mach_log("8514/A ON, pitch=%d, GE offset=%08x.\n", ((mach->accel.ge_pitch & 0xff) << 3), dev->accel.ge_offset); + dev->h_disp = dev->hdisp; dev->dispend = dev->vdisp; if (dev->dispend == 600) @@ -2809,6 +2824,7 @@ ati8514_recalctimings(svga_t *svga) } dev->accel_bpp = 8; svga->render8514 = ibm8514_render_8bpp; + } else mach->crt_resolution = 0; } @@ -3009,17 +3025,12 @@ mach_recalctimings(svga_t *svga) } } } else { - mach->accel.src_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach->accel.dst_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + mach->accel.src_pitch = dev->pitch; + mach->accel.dst_pitch = dev->pitch; mach->accel.src_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.dst_ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); - if (dev->bpp) { - mach->accel.src_ge_offset <<= 1; - mach->accel.dst_ge_offset <<= 1; - } else { - mach->accel.src_ge_offset <<= 2; - mach->accel.dst_ge_offset <<= 2; - } + mach->accel.src_ge_offset <<= 2; + mach->accel.dst_ge_offset <<= 2; mach->accel.src_ge_offset -= mach->accel.crt_offset; mach->accel.dst_ge_offset -= mach->accel.crt_offset; @@ -7221,7 +7232,6 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) dev->v_sync_start = 0x0600; dev->disp_cntl = 0x33; mach->accel.clock_sel = 0x1c; - mach->shadow_set = 0x02; dev->accel.cmd_back = 1; io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); From 018bbfae4333beaf0c71e6b05603aabb5ab242ed Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 5 May 2025 05:11:55 +0200 Subject: [PATCH 0839/1190] SM(S)C FDC37C93x Super I/O chip rewrite, add the Acer V62x, and un-dev-branch the V-Tech Laser XT machines. --- src/chipset/intel_piix.c | 61 -- src/device/kbc_at.c | 23 +- src/floppy/fdc.c | 19 +- src/include/86box/fdc.h | 5 + src/include/86box/keyboard.h | 1 + src/include/86box/machine.h | 9 +- src/include/86box/sio.h | 24 +- src/machine/CMakeLists.txt | 6 +- src/machine/m_at_slot1.c | 33 +- src/machine/m_at_socket7.c | 23 +- src/machine/m_at_socket7_3v.c | 8 +- src/machine/m_at_socket8.c | 4 +- src/machine/m_pcjr.c | 3 +- src/machine/m_xt_laserxt.c | 461 +++++++-- src/machine/m_xt_zenith.c | 3 +- src/machine/machine_table.c | 61 +- src/sio/sio_fdc37c93x.c | 1732 ++++++++++++++++++++++++--------- 17 files changed, 1810 insertions(+), 666 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 6969d3274..ed9fd9460 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -59,7 +59,6 @@ typedef struct piix_io_trap_t { } piix_io_trap_t; typedef struct _piix_ { - uint8_t cur_readout_reg; uint8_t rev; uint8_t type; uint8_t func_shift; @@ -67,7 +66,6 @@ typedef struct _piix_ { uint8_t pci_slot; uint8_t no_mirq0; uint8_t regs[4][256]; - uint8_t readout_regs[256]; uint16_t func0_id; uint16_t nvr_io_base; uint16_t acpi_io_base; @@ -1185,31 +1183,6 @@ piix_read(int func, int addr, void *priv) return ret; } -static void -board_write(uint16_t port, uint8_t val, void *priv) -{ - piix_t *dev = (piix_t *) priv; - - if (port == 0x00e0) - dev->cur_readout_reg = val; - else if (port == 0x00e1) - dev->readout_regs[dev->cur_readout_reg] = val; -} - -static uint8_t -board_read(uint16_t port, void *priv) -{ - const piix_t *dev = (piix_t *) priv; - uint8_t ret = 0x64; - - if (port == 0x00e0) - ret = dev->cur_readout_reg; - else if (port == 0x00e1) - ret = dev->readout_regs[dev->cur_readout_reg]; - - return ret; -} - static void piix_reset_hard(piix_t *dev) { @@ -1624,40 +1597,6 @@ piix_init(const device_t *info) if (dev->type < 3) pci_enable_mirq(1); - dev->readout_regs[0] = 0xff; - dev->readout_regs[1] = 0x40; - dev->readout_regs[2] = 0xff; - - /* Port E1 register 01 (TODO: Find how multipliers > 3.0 are defined): - - Bit 6: 1 = can boot, 0 = no; - Bit 7, 1 = multiplier (00 = 2.5, 01 = 2.0, 10 = 3.0, 11 = 1.5); - Bit 5, 4 = bus speed (00 = 50 MHz, 01 = 66 MHz, 10 = 60 MHz, 11 = ????): - Bit 7, 5, 4, 1: 0000 = 125 MHz, 0010 = 166 MHz, 0100 = 150 MHz, 0110 = ??? MHz; - 0001 = 100 MHz, 0011 = 133 MHz, 0101 = 120 MHz, 0111 = ??? MHz; - 1000 = 150 MHz, 1010 = 200 MHz, 1100 = 180 MHz, 1110 = ??? MHz; - 1001 = 75 MHz, 1011 = 100 MHz, 1101 = 90 MHz, 1111 = ??? MHz */ - - if (cpu_busspeed <= 40000000) - dev->readout_regs[1] |= 0x30; - else if ((cpu_busspeed > 40000000) && (cpu_busspeed <= 50000000)) - dev->readout_regs[1] |= 0x00; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - dev->readout_regs[1] |= 0x20; - else if (cpu_busspeed > 60000000) - dev->readout_regs[1] |= 0x10; - - if (cpu_dmulti <= 1.5) - dev->readout_regs[1] |= 0x82; - else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) - dev->readout_regs[1] |= 0x02; - else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) - dev->readout_regs[1] |= 0x00; - else if (cpu_dmulti > 2.5) - dev->readout_regs[1] |= 0x80; - - io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); - #if 0 device_add(&i8254_sec_device); #endif diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 447c07780..aaa746570 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -509,9 +509,6 @@ kbc_scan_kbd_at(atkbc_t *dev) } } -static void -write_p2(atkbc_t *dev, uint8_t val); - static void kbc_at_poll_at(atkbc_t *dev) { @@ -778,6 +775,7 @@ static void write_p2(atkbc_t *dev, uint8_t val) { uint8_t old = dev->p2; + kbc_at_log("ATkbc: write P2: %02X (old: %02X)\n", val, dev->p2); uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; @@ -851,6 +849,25 @@ write_p2(atkbc_t *dev, uint8_t val) } } +uint8_t +kbc_at_read_p(void *priv, uint8_t port, uint8_t mask) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t *p = (port == 2) ? &dev->p2 : &dev->p1; + uint8_t ret = *p & mask; + + return ret; +} + +void +kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t *p = (port == 2) ? &dev->p2 : &dev->p1; + + *p = (*p & mask) | val; +} + static void write_p2_fast_a20(atkbc_t *dev, uint8_t val) { diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index c32b1f442..de8508e69 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -81,6 +81,7 @@ int fdc_current[FDC_MAX] = { 0, 0 }; volatile int fdcinited = 0; +// #define ENABLE_FDC_LOG 1 #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; @@ -395,6 +396,20 @@ fdc_update_rwc(fdc_t *fdc, int drive, int rwc) fdc_rate(fdc, drive); } +uint8_t +fdc_get_media_id(fdc_t *fdc, int id) +{ + uint8_t ret = fdc->media_id & (1 << id); + + return ret; +} + +void +fdc_set_media_id(fdc_t *fdc, int id, int set) +{ + fdc->media_id = (fdc->media_id & ~(1 << id)) | (set << id); +} + int fdc_get_boot_drive(fdc_t *fdc) { @@ -1369,7 +1384,7 @@ fdc_read(uint16_t addr, void *priv) } else if (!fdc->enh_mode) ret = 0x20; else - ret = fdc->rwc[drive] << 4; + ret = (fdc->rwc[drive] << 4) | (fdc->media_id << 6); break; case 4: /*Status*/ ret = fdc->stat; @@ -2352,6 +2367,8 @@ fdc_reset(void *priv) } fdc->power_down = 0; + + fdc->media_id = 0; } static void diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 2d17380d0..36cfaeb7a 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -119,6 +119,8 @@ typedef struct fdc_t { uint8_t lock; uint8_t dsr; + uint8_t media_id; + uint8_t params[15]; uint8_t specify[2]; uint8_t res[11]; @@ -166,6 +168,9 @@ extern void fdc_3f1_enable(fdc_t *fdc, int enable); extern int fdc_get_bit_rate(fdc_t *fdc); extern int fdc_get_bitcell_period(fdc_t *fdc); +extern uint8_t fdc_get_media_id(fdc_t *fdc, int id); +extern void fdc_set_media_id(fdc_t *fdc, int id, int set); + /* A few functions to communicate between Super I/O chips and the FDC. */ extern void fdc_update_enh_mode(fdc_t *fdc, int enh_mode); extern int fdc_get_rwc(fdc_t *fdc, int drive); diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index e21fa60d9..583960e80 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -285,6 +285,7 @@ extern int keyboard_isfsexit(void); extern int keyboard_isfsexit_up(void); extern void keyboard_set_is_amstrad(int ams); extern void kbc_at_set_ps2(void *priv, uint8_t ps2); +extern uint8_t kbc_at_read_p(void *priv, uint8_t port, uint8_t mask); extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t val); extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 4469b55c2..d62947848 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -806,6 +806,7 @@ extern int machine_at_p65up5_cp6nd_init(const machine_t *); /* m_at_slot1.c */ extern int machine_at_m729_init(const machine_t *); +extern int machine_at_acerv62x_init(const machine_t *); extern int machine_at_p65up5_cpknd_init(const machine_t *); extern int machine_at_kn97_init(const machine_t *); @@ -969,10 +970,14 @@ extern int machine_xt_compaq_deskpro_init(const machine_t *); extern int machine_xt_compaq_portable_init(const machine_t *); /* m_xt_laserxt.c */ -#ifdef USE_LASERXT extern int machine_xt_laserxt_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t laserxt_device; +#endif extern int machine_xt_lxt3_init(const machine_t *); -#endif /* USE_LASERXT */ +#ifdef EMU_DEVICE_H +extern const device_t lxt3_device; +#endif /* m_xt_philips.c */ extern int machine_xt_p3105_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 7fcb376b9..bdff29f7f 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -48,14 +48,22 @@ extern const device_t fdc37c669_370_device; extern const device_t fdc37c67x_device; -extern const device_t fdc37c931apm_device; -extern const device_t fdc37c931apm_compaq_device; -extern const device_t fdc37c932fr_device; -extern const device_t fdc37c932qf_device; -extern const device_t fdc37c932_device; -extern const device_t fdc37c935_device; -extern const device_t fdc37c935_370_device; -extern const device_t fdc37c935_no_nvr_device; +#define FDC37C93X_NORMAL 0x0002 +#define FDC37C93X_FR 0x0003 +#define FDC37C93X_APM 0x0030 +#define FDC37C93X_CHIP_ID 0x00ff + +#define FDC37C931 0x0100 /* Compaq KBC firmware and configuration registers on GPIO ports. */ +#define FDC37C932 0x0200 /* AMI '5' Megakey KBC firmware. */ +#define FDC37C933 0x0300 /* IBM KBC firmware. */ +#define FDC37C935 0x0500 /* Phoenix Multikey/42 1.38 KBC firmware. */ +#define FDC37C937 0x0700 /* Phoenix Multikey/42i 4.16 KBC firmware. */ +#define FDC37C93X_KBC 0x0f00 + +#define FDC37C93X_NO_NVR 0x1000 +#define FDC37C93X_370 0x2000 + +extern const device_t fdc37c93x_device; extern const device_t fdc37m60x_device; extern const device_t fdc37m60x_370_device; diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index ff6a66801..4098f2553 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(mch OBJECT machine_table.c m_xt.c m_xt_compaq.c + m_xt_laserxt.c m_xt_philips.c m_xt_t1000.c m_xt_t1000_vid.c @@ -64,11 +65,6 @@ if(DESKPRO386) target_compile_definitions(mch PRIVATE USE_DESKPRO386) endif() -if(LASERXT) - target_sources(mch PRIVATE m_xt_laserxt.c) - target_compile_definitions(mch PRIVATE USE_LASERXT) -endif() - if(OLIVETTI) target_compile_definitions(mch PRIVATE USE_OLIVETTI) endif() diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index a3ff921e3..bd3a4833f 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -40,6 +40,35 @@ #include <86box/clock.h> #include <86box/snd_ac97.h> +int +machine_at_acerv62x_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acerv62x/v62xc0s1.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 5, 0, 0, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + device_add(&i440fx_device); + device_add(&piix3_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_APM)); + device_add(&sst_flash_29ee020_device); + + return ret; +} + int machine_at_p65up5_cpknd_init(const machine_t *model) { @@ -131,7 +160,7 @@ machine_at_spitfire_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -143,7 +172,7 @@ machine_at_spitfire_init(const machine_t *model) pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440lx_device); device_add(&piix4e_device); - device_add(&fdc37c935_no_nvr_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL | FDC37C93X_NO_NVR)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); device_add(&lm78_device); /* no reporting in BIOS */ diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 3fe883323..319856d41 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -69,7 +69,8 @@ machine_at_acerv35n_init(const machine_t *model) pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&i430hx_device); device_add(&piix3_device); - device_add(&fdc37c932fr_device); + /* The chip is not marked FR but the BIOS accesses register 06h of GPIO. */ + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_FR)); device_add(&sst_flash_29ee010_device); return ret; @@ -160,7 +161,7 @@ machine_at_m7shi_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); - device_add(&fdc37c935_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL)); device_add(&intel_flash_bxt_device); return ret; @@ -568,7 +569,7 @@ machine_at_presario2240_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c932qf_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C932 | FDC37C93X_NORMAL)); device_add(&sst_flash_29ee020_device); return ret; @@ -598,7 +599,7 @@ machine_at_presario4500_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c931apm_compaq_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C931 | FDC37C93X_APM)); device_add(&sst_flash_29ee020_device); return ret; @@ -631,7 +632,7 @@ machine_at_dellhannibalp_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c932fr_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C932 | FDC37C93X_FR)); device_add(&intel_flash_bxt_ami_device); return ret; @@ -659,7 +660,7 @@ machine_at_p55va_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c932fr_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C932 | FDC37C93X_FR)); device_add(&intel_flash_bxt_device); return ret; @@ -687,7 +688,7 @@ machine_at_brio80xx_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c935_370_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL | FDC37C93X_370)); device_add(&sst_flash_29ee020_device); return ret; @@ -756,7 +757,7 @@ machine_at_pb810_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c935_370_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL | FDC37C93X_370)); device_add(&intel_flash_bxt_device); return ret; @@ -851,7 +852,7 @@ machine_at_gw2kte_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c932fr_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C932 | FDC37C93X_FR)); device_add(&intel_flash_bxt_ami_device); return ret; @@ -1553,7 +1554,7 @@ machine_at_thunderbolt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1564,7 +1565,7 @@ machine_at_thunderbolt_init(const machine_t *model) pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 0, 1, 2); device_add(&i430tx_device); device_add(&piix4_device); - device_add(&fdc37c935_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL | FDC37C93X_NO_NVR)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 4b980f2b0..913c82518 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -455,7 +455,7 @@ machine_at_pb640_init(const machine_t *model) device_add(&piix_rev02_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5440_onboard_pci_device); + device_add(machine_get_vid_device(machine)); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&pc87306_device); @@ -546,7 +546,7 @@ machine_at_acerm3a_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); - device_add(&fdc37c935_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL)); device_add(&sst_flash_29ee010_device); @@ -700,7 +700,7 @@ machine_at_gw2kma_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&fdc37c932fr_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C932 | FDC37C93X_FR)); device_add(&intel_flash_bxt_ami_device); return ret; @@ -819,7 +819,7 @@ machine_at_vectra54_init(const machine_t *model) device_add(&i430fx_device); device_add(&piix_device); - device_add(&fdc37c932_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C932 | FDC37C93X_NORMAL)); device_add(&sst_flash_29ee010_device); return ret; diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 935a26fb2..479c4b9fc 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -188,7 +188,7 @@ machine_at_acerv60n_init(const machine_t *model) pci_register_slot(0x0C, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&fdc37c935_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL)); device_add(&sst_flash_29ee010_device); return ret; @@ -389,7 +389,7 @@ machine_at_m6mi_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&fdc37c935_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL)); device_add(&intel_flash_bxt_device); return ret; diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index ca9e72fca..d4d3b09cf 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -1566,7 +1566,8 @@ machine_pcjr_init(UNUSED(const machine_t *model)) device_add(&fdc_pcjr_device); device_add(&ns8250_pcjr_device); - serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ + /* So that serial_standalone_init() won't do anything. */ + serial_set_next_inst(SERIAL_MAX - 1); /* "All the inputs are 'read' with one 'IN' from address hex 201." - PCjr Technical Reference (Nov. 83), p.2-119 diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index c0405f99a..d298e726b 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -1,6 +1,7 @@ /*This is the chipset used in the LaserXT series model*/ #include #include +#include #include #include #include <86box/86box.h> @@ -21,125 +22,411 @@ #include <86box/keyboard.h> #include <86box/plat_unused.h> -static int laserxt_emspage[4]; -static int laserxt_emscontrol[4]; -static mem_mapping_t laserxt_ems_mapping[4]; -static int laserxt_ems_baseaddr_index = 0; -static int laserxt_is_lxt3 = 0; +#define EMS_TOTAL_MAX 0x00100000 -static uint32_t -get_laserxt_ems_addr(uint32_t addr) +typedef struct { - if (laserxt_emspage[(addr >> 14) & 3] & 0x80) { - addr = (!laserxt_is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((laserxt_emspage[(addr >> 14) & 3] & 0x0F) << 14) + ((laserxt_emspage[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3FFF); - } + uint8_t page; + uint8_t ctrl; - return addr; + uint32_t phys; + uint32_t virt; + + mem_mapping_t mapping; + + uint8_t *ram; + + void *parent; +} lxt_ems_t; + +typedef struct +{ + int ems_base_idx; + + lxt_ems_t ems[4]; + + uint16_t io_base; + uint32_t base; + + uint32_t mem_size; + + uint8_t *ram; + + void *parent; +} lxt_ems_board_t; + +typedef struct +{ + int is_lxt3; + + lxt_ems_board_t *ems_boards[2]; +} lxt_t; + +static void +ems_update_virt(lxt_ems_t *dev, uint8_t new_page) +{ + lxt_ems_board_t *board = (lxt_ems_board_t *) dev->parent; + lxt_t *lxt = (lxt_t *) board->parent; + + dev->page = new_page; + + if (new_page & 0x80) { + if (lxt->is_lxt3) { + /* Point invalid pages at 1 MB which is outside the maximum. */ + if ((new_page & 0x7f) >= 0x40) + dev->virt = EMS_TOTAL_MAX; + else + dev->virt = ((new_page & 0x7f) << 14); + } else + dev->virt = ((new_page & 0x0f) << 14) + ((new_page & 0x40) << 12); + + if (dev->virt >= board->mem_size) + dev->virt = EMS_TOTAL_MAX; + } else + dev->virt = EMS_TOTAL_MAX; + + dev->ram = board->ram + dev->virt; + + if ((new_page & 0x80) && (dev->virt != EMS_TOTAL_MAX)) { + mem_mapping_enable(&dev->mapping); + + mem_mapping_set_exec(&dev->mapping, dev->ram); + mem_mapping_set_p(&dev->mapping, dev->ram); + } else + mem_mapping_disable(&dev->mapping); + + flushmmucache(); } static void -laserxt_write(uint16_t port, uint8_t val, UNUSED(void *priv)) +lxt_ems_out(uint16_t port, uint8_t val, void *priv) { - uint32_t paddr; - uint32_t vaddr; - switch (port) { - case 0x0208: - case 0x4208: - case 0x8208: - case 0xC208: - laserxt_emspage[port >> 14] = val; - paddr = 0xC0000 + (port & 0xC000) + (((laserxt_ems_baseaddr_index + (4 - (port >> 14))) & 0x0C) << 14); - if (val & 0x80) { - mem_mapping_enable(&laserxt_ems_mapping[port >> 14]); - vaddr = get_laserxt_ems_addr(paddr); - mem_mapping_set_exec(&laserxt_ems_mapping[port >> 14], ram + vaddr); - } else { - mem_mapping_disable(&laserxt_ems_mapping[port >> 14]); - } - flushmmucache(); - break; - case 0x0209: - case 0x4209: - case 0x8209: - case 0xC209: - laserxt_emscontrol[port >> 14] = val; - laserxt_ems_baseaddr_index = 0; + lxt_ems_board_t *dev = (lxt_ems_board_t *) priv; + uint8_t reg = port >> 14; + uint32_t saddrs[8] = { 0xc4000, 0xc8000, 0xcc000, 0xd0000, + 0xd4000, 0xd8000, 0xdc000, 0xe0000 }; + uint32_t saddr; + + if (port & 0x0001) { + dev->ems[reg].ctrl = val; + + if (reg < 0x03) { + dev->ems_base_idx = (dev->ems_base_idx & ~(0x04 >> (2 - reg))) | + ((dev->ems[reg].ctrl & 0x80) >> (7 - reg)); + + saddr = saddrs[dev->ems_base_idx]; + for (uint8_t i = 0; i < 4; i++) { - laserxt_ems_baseaddr_index |= (laserxt_emscontrol[i] & 0x80) >> (7 - i); + uint32_t base = saddr + (i * 0x4000); + mem_mapping_set_addr(&dev->ems[i].mapping, base, 0x4000); + if (!(dev->ems[i].page & 0x80) || (dev->ems[i].virt == EMS_TOTAL_MAX)) + mem_mapping_disable(&dev->ems[i].mapping); } + } - mem_mapping_set_addr(&laserxt_ems_mapping[0], 0xC0000 + (((laserxt_ems_baseaddr_index + 4) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&laserxt_ems_mapping[1], 0xC4000 + (((laserxt_ems_baseaddr_index + 3) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&laserxt_ems_mapping[2], 0xC8000 + (((laserxt_ems_baseaddr_index + 2) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&laserxt_ems_mapping[3], 0xCC000 + (((laserxt_ems_baseaddr_index + 1) & 0x0C) << 14), 0x4000); - flushmmucache(); - break; - - default: - break; + flushmmucache(); + } else if (!(port & 0x0001)) { + dev->ems[reg].page = val; + ems_update_virt(&dev->ems[reg], val); } } static uint8_t -laserxt_read(uint16_t port, UNUSED(void *priv)) +lxt_ems_in(uint16_t port, void *priv) { - switch (port) { - case 0x0208: - case 0x4208: - case 0x8208: - case 0xC208: - return laserxt_emspage[port >> 14]; - case 0x0209: - case 0x4209: - case 0x8209: - case 0xC209: - return laserxt_emscontrol[port >> 14]; + lxt_ems_board_t *dev = (lxt_ems_board_t *) priv; + uint8_t reg = port >> 14; + uint8_t ret = 0xff; - default: - break; - } - return 0xff; + if (port & 0x0001) + ret = dev->ems[reg].ctrl; + else + ret = dev->ems[reg].page; + + return ret; } static void -mem_write_laserxtems(uint32_t addr, uint8_t val, UNUSED(void *priv)) +lxt_ems_write(uint32_t addr, uint8_t val, void *priv) { - addr = get_laserxt_ems_addr(addr); - if (addr < (mem_size << 10)) - ram[addr] = val; + uint8_t *mem = (uint8_t *) priv; + + mem[addr & 0x3fff] = val; } static uint8_t -mem_read_laserxtems(uint32_t addr, UNUSED(void *priv)) +lxt_ems_read(uint32_t addr, void *priv) { - uint8_t val = 0xFF; - addr = get_laserxt_ems_addr(addr); - if (addr < (mem_size << 10)) - val = ram[addr]; - return val; + uint8_t *mem = (uint8_t *) priv; + uint8_t ret = 0xff; + + ret = mem[addr & 0x3fff]; + + return ret; +} + +static lxt_ems_board_t * +lxt_ems_init(lxt_t *parent, int en, uint16_t io, uint32_t mem) +{ + lxt_ems_board_t *dev = (lxt_ems_board_t *) calloc(1, sizeof(lxt_ems_board_t)); + + if (en) { + dev->parent = parent; + + if (io != 0x0000) { + io_sethandler(io , 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev); + io_sethandler(io | 0x4000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev); + io_sethandler(io | 0x8000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev); + io_sethandler(io | 0xc000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev); + } + + dev->ram = (uint8_t *) calloc(mem, sizeof(uint8_t)); + dev->mem_size = mem; + + for (uint8_t i = 0; i < 4; i++) { + uint8_t *ptr = dev->ram + (i << 14); + + mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000, + lxt_ems_read, NULL, NULL, + lxt_ems_write, NULL, NULL, + ptr, 0, ptr); + mem_mapping_disable(&dev->ems[i].mapping); + + dev->ems[i].page = 0x7f; + dev->ems[i].ctrl = (i == 3) ? 0x00 : 0x80; + + dev->ems[i].parent = dev; + + ems_update_virt(&(dev->ems[i]), dev->ems[i].page); + } + } + + return dev; } static void -laserxt_init(int is_lxt3) +lxt_close(void *priv) { - if (mem_size > 640) { - io_sethandler(0x0208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - io_sethandler(0x4208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - io_sethandler(0x8208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - io_sethandler(0xc208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - mem_mapping_set_addr(&ram_low_mapping, 0, !is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)); + lxt_t *dev = (lxt_t *) priv; + int ems_boards = (1 - dev->is_lxt3) + 1; + + for (int i = 0; i < ems_boards; i++) + if (dev->ems_boards[i] != NULL) { + if (dev->ems_boards[i]->ram != NULL) + free(dev->ems_boards[i]->ram); + free(dev->ems_boards[i]); + } + + free(dev); +} + +static void * +lxt_init(const device_t *info) +{ + lxt_t * dev = (lxt_t *) calloc(1, sizeof(lxt_t)); + int ems_boards = (1 - info->local) + 1; + int ems_en[2] = { 0 }; + uint16_t ems_io[2] = { 0 }; + uint32_t ems_mem[2] = { 0 }; + char conf_str[512] = { 0 }; + + dev->is_lxt3 = info->local; + + for (int i = 0; i < ems_boards; i++) { + sprintf(conf_str, "ems_%i_enable", i + 1); + ems_en[i] = device_get_config_int(conf_str); + + sprintf(conf_str, "ems_%i_base", i + 1); + ems_io[i] = device_get_config_hex16(conf_str); + + sprintf(conf_str, "ems_%i_mem_size", i + 1); + ems_mem[i] = device_get_config_int(conf_str) << 10; + + dev->ems_boards[i] = lxt_ems_init(dev, ems_en[i], ems_io[i], ems_mem[i]); } - for (uint8_t i = 0; i < 4; i++) { - laserxt_emspage[i] = 0x7F; - laserxt_emscontrol[i] = (i == 3) ? 0x00 : 0x80; - mem_mapping_add(&laserxt_ems_mapping[i], 0xE0000 + (i << 14), 0x4000, mem_read_laserxtems, NULL, NULL, mem_write_laserxtems, NULL, NULL, ram + 0xA0000 + (i << 14), 0, NULL); - mem_mapping_disable(&laserxt_ems_mapping[i]); - } mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - laserxt_is_lxt3 = is_lxt3; + + return dev; } +static const device_config_t laserxt_config[] = { + { + .name = "ems_1_base", + .description = "EMS 1 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "0x208", .value = 0x208 }, + { .description = "0x218", .value = 0x218 }, + { .description = "0x258", .value = 0x258 }, + { .description = "0x268", .value = 0x268 }, + { .description = "0x2A8", .value = 0x2a8 }, + { .description = "0x2B8", .value = 0x2b8 }, + { .description = "0x2E8", .value = 0x2e8 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "ems_2_base", + .description = "EMS 2 Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "0x208", .value = 0x208 }, + { .description = "0x218", .value = 0x218 }, + { .description = "0x258", .value = 0x258 }, + { .description = "0x268", .value = 0x268 }, + { .description = "0x2A8", .value = 0x2a8 }, + { .description = "0x2B8", .value = 0x2b8 }, + { .description = "0x2E8", .value = 0x2e8 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "ems_1_mem_size", + .description = "EMS 1 Memory Size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 512, + .step = 32 + }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "ems_2_mem_size", + .description = "EMS 2 Memory Size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 512, + .step = 32 + }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "ems_1_enable", + .description = "Enable EMS 1", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "ems_2_enable", + .description = "Enable EMS 2", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +const device_t laserxt_device = { + .name = "VTech Laser Turbo XT", + .internal_name = "laserxt", + .flags = 0, + .local = 0, + .init = lxt_init, + .close = lxt_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = laserxt_config +}; + +static const device_config_t lxt3_config[] = { + { + .name = "ems_1_base", + .description = "EMS Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "0x208", .value = 0x208 }, + { .description = "0x218", .value = 0x218 }, + { .description = "0x258", .value = 0x258 }, + { .description = "0x268", .value = 0x268 }, + { .description = "0x2A8", .value = 0x2a8 }, + { .description = "0x2B8", .value = 0x2b8 }, + { .description = "0x2E8", .value = 0x2e8 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "ems_1_mem_size", + .description = "EMS Memory Size", + .type = CONFIG_SPINNER, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { + .min = 0, + .max = 1024, + .step = 32 + }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "ems_1_enable", + .description = "Enable EMS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +const device_t lxt3_device = { + .name = "VTech Laser Turbo XT", + .internal_name = "laserxt", + .flags = 0, + .local = 1, + .init = lxt_init, + .close = lxt_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = lxt3_config +}; + static void machine_xt_laserxt_common_init(const machine_t *model,int is_lxt3) { @@ -153,7 +440,7 @@ machine_xt_laserxt_common_init(const machine_t *model,int is_lxt3) nmi_init(); standalone_gameport_type = &gameport_device; - laserxt_init(is_lxt3); + device_add(is_lxt3 ? &lxt3_device : &laserxt_device); device_add(&keyboard_xt_lxt3_device); } diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 6c5d556f2..62c6496d1 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -146,7 +146,8 @@ machine_xt_z184_init(const machine_t *model) lpt2_remove(); lpt1_setup(LPT2_ADDR); device_add(&ns8250_device); - serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ + /* So that serial_standalone_init() won't do anything. */ + serial_set_next_inst(SERIAL_MAX - 1); device_add(&cga_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 9c83f4b22..44e93f721 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1709,7 +1709,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#ifdef USE_LASERXT { .name = "[8088] VTech Laser Turbo XT", .internal_name = "ltxt", @@ -1742,14 +1741,13 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &laserxt_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL }, -#endif /* USE_LASERXT */ /* Has a standard PS/2 KBC (so, use IBM PS/2 Type 1). */ { .name = "[8088] Xi8088", @@ -2612,8 +2610,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - -#ifdef USE_LASERXT { .name = "[8086] VTech Laser XT3", .internal_name = "lxt3", @@ -2637,23 +2633,22 @@ const machine_t machines[] = { .bus_flags = MACHINE_PC, .flags = MACHINE_FLAGS_NONE, .ram = { - .min = 256, + .min = 512, .max = 640, - .step = 256 + .step = 64 }, .nvrmask = 0, .kbc_device = &keyboard_xt_lxt3_device, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &lxt3_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL }, -#endif /* USE_LASERXT */ /* 286 AT machines */ /* Has IBM AT KBC firmware. */ @@ -8156,7 +8151,10 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* I'm going to assume this as an AMIKey-2 like the other two 486SP3's. */ + /* + This has an AMIKey (and an on-board NCR 53C810 PCI SCSI controller), thanks, eBay! + The keyboard port is AT. + */ { .name = "[i420TX] ASUS PCI/I-486SP3", .internal_name = "486sp3", @@ -10092,7 +10090,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE | MACHINE_SCSI | MACHINE_APM, + .flags = MACHINE_IDE /*| MACHINE_SCSI */ | MACHINE_APM, .ram = { .min = 2048, .max = 524288, @@ -14593,6 +14591,47 @@ const machine_t machines[] = { }, /* 440FX */ + /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix + MultiKey/42 (version 1.38) KBC firmware. */ + { + .name = "[i440FX] Acer V62X", + .internal_name = "acerv62x", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_acerv62x_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 83333333, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 511, + .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 + }, /* The base board has a Holtek HT6542B KBC with AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] ASUS P/I-P65UP5 (C-PKND)", diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 8d8f76cb6..ebc500c96 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -15,8 +15,9 @@ * * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/pci.h> +#include <86box/pic.h> #include <86box/lpt.h> #include <86box/serial.h> #include <86box/hdc.h> @@ -37,20 +39,28 @@ #include <86box/apm.h> #include <86box/access_bus.h> #include <86box/acpi.h> -#include <86box/sio.h> +#include <86box/plat.h> #include <86box/plat_unused.h> +#include <86box/video.h> +#include <86box/sio.h> +#include "cpu.h" typedef struct fdc37c93x_t { uint8_t chip_id; uint8_t is_apm; uint8_t is_compaq; uint8_t has_nvr; + uint8_t max_ld; uint8_t tries; uint8_t port_370; - uint8_t gpio_regs[2]; + uint8_t gpio_reg; + uint8_t gpio_regs[256]; + uint8_t gpio_pulldn[8]; uint8_t auxio_reg; uint8_t regs[48]; + uint8_t alt_regs[3][8]; uint8_t ld_regs[11][256]; + uint16_t kbc_type; uint16_t superio_base; uint16_t fdc_base; uint16_t lpt_base; @@ -73,6 +83,15 @@ typedef struct fdc37c93x_t { static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv); static uint8_t fdc37c93x_read(uint16_t port, void *priv); +static uint8_t gp_func_regs[8][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, /* GP00-GP07 */ + { 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7 }, /* GP10-GP17 */ + { 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef }, /* GP20-GP27 */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, /* GP30-GP37 */ + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }, /* GP40-GP47 */ + { 0xc8, 0xc9, 0xff, 0xcb, 0xcc, 0xff, 0xff, 0xff }, /* GP50-GP57 */ + { 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7 }, /* GP60-GP67 */ + { 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf } }; /* GP70-GP77 */ + static uint16_t make_port_superio(const fdc37c93x_t *dev) { @@ -122,14 +141,562 @@ fdc37c93x_auxio_write(UNUSED(uint16_t port), uint8_t val, void *priv) dev->auxio_reg = val; } +static __inline uint8_t +fdc37c93x_do_read_gp(fdc37c93x_t *dev, int reg, int bit) +{ + /* Update bit 2 on the Acer V35N according to the selected graphics card type. */ + if ((reg == 2) && (strstr(machine_get_internal_name(), "acer") != NULL)) + dev->gpio_pulldn[reg] = (dev->gpio_pulldn[reg] & 0xfb) | (video_is_mda() ? 0x00 : 0x04); + + return dev->gpio_regs[reg] & dev->gpio_pulldn[reg] & (1 << bit); +} + +static __inline uint8_t +fdc37c93x_do_read_alt(const fdc37c93x_t *dev, int alt, int reg, int bit) +{ + return dev->alt_regs[alt][reg] & (1 << bit); +} + +static uint8_t +fdc37c93x_read_gp(const fdc37c93x_t *dev, int reg, int bit) +{ + uint8_t gp_reg = gp_func_regs[reg][bit]; + uint8_t gp_func_reg = dev->ld_regs[0x08][gp_reg]; + uint8_t gp_func; + uint8_t ret = 1 << bit; + + if (gp_func_reg & 0x01) switch (reg) { + default: + /* Do nothing, this GP does not exist. */ + break; + case 1: + switch (bit) { + default: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x00) + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + else + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + gp_func = (gp_func_reg >> 3) & 0x03; + if (!(gp_func & 0x01)) { + if (gp_func & 0x02) + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + else + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + } + break; + case 3: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x01) + /* TODO: Write to power LED if it's ever implemented. */ + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + else + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 6: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 1 ... 3: + ret = fdc37c93x_do_read_alt(dev, gp_func - 1, reg, bit); + break; + } + break; + } + break; + case 2: + switch (bit) { + default: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x00) + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + else + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 0: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 2: + ret = kbc_at_read_p(dev->kbc, 2, 0x01) ? (1 << bit) : 0x00; + break; + } + break; + case 1: case 2: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 1: case 2: + ret = fdc37c93x_do_read_alt(dev, gp_func - 1, reg, bit); + break; + } + break; + case 5: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x00) + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + else + ret = kbc_at_read_p(dev->kbc, 2, 0x02) ? (1 << bit) : 0x00; + break; + case 6: case 7: + /* Do nothing, these bits do not exist. */ + break; + } + break; + case 4: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + } + break; + case 0: case 1: + switch (gp_func) { + case 0: + ret = fdc_get_media_id(dev->fdc, bit ^ 1) ? (1 << bit) : 0x00; + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + } + break; + case 6: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 2: + /* TODO: Write to power LED if it's ever implemented. */ + ret = fdc37c93x_do_read_alt(dev, 1, reg, bit); + break; + case 3: + ret = fdc37c93x_do_read_alt(dev, 2, reg, bit); + break; + } + break; + case 7: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 2: + ret = fdc37c93x_do_read_alt(dev, 1, reg, bit); + break; + } + break; + } + break; + case 5: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + break; + case 0: case 3: case 4: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + } + break; + case 1: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + } + break; + } + break; + case 6: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 2: + ret = kbc_at_read_p(dev->kbc, 1, 1 << bit); + break; + } + break; + case 0: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 2: + /* TODO: Write to power LED if it's ever implemented. */ + ret = fdc37c93x_do_read_alt(dev, 1, reg, bit); + break; + } + break; + case 1: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + case 2: + ret = fdc37c93x_do_read_alt(dev, 1, reg, bit); + break; + } + break; + } + break; + case 7: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + switch (gp_func) { + case 0: + ret = fdc37c93x_do_read_alt(dev, 0, reg, bit); + break; + case 1: + ret = fdc37c93x_do_read_gp((fdc37c93x_t *) dev, reg, bit); + break; + } + break; + } + break; + } + + if (gp_func_reg & 0x02) + ret ^= (1 << bit); + + return ret; +} + +static __inline void +fdc37c93x_do_write_gp(fdc37c93x_t *dev, int reg, int bit, int set) +{ + dev->gpio_regs[reg] = (dev->gpio_regs[reg] & ~(1 << bit)) | + (set << bit); +} + +static __inline void +fdc37c93x_do_write_alt(fdc37c93x_t *dev, int alt, int reg, int bit, int set) +{ + dev->alt_regs[alt][reg] = (dev->alt_regs[alt][reg] & ~(1 << bit)) | + (set << bit); +} + +static void +fdc37c93x_write_gp(fdc37c93x_t *dev, int reg, int bit, int set) +{ + uint8_t gp_func_reg = dev->ld_regs[0x08][gp_func_regs[reg][bit]]; + uint8_t gp_func; + + if (gp_func_reg & 0x02) + set = !set; + + if (!(gp_func_reg & 0x01)) switch (reg) { + default: + /* Do nothing, this GP does not exist. */ + break; + case 1: + switch (bit) { + default: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x00) + fdc37c93x_do_write_gp(dev, reg, bit, set); + else + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + gp_func = (gp_func_reg >> 3) & 0x03; + if (!(gp_func & 0x01)) { + if (gp_func & 0x02) { + set ? picint(1 << 13) : picintc(1 << 13); + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + } else + fdc37c93x_do_write_gp(dev, reg, bit, set); + } + break; + case 3: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x01) + /* TODO: Write to power LED if it's ever implemented. */ + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + else + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 6: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (gp_func) { + case 0: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 1 ... 3: + fdc37c93x_do_write_alt(dev, gp_func - 1, reg, bit, set); + break; + } + break; + } + break; + case 2: + switch (bit) { + default: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x00) + fdc37c93x_do_write_gp(dev, reg, bit, set); + else + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 0: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (gp_func) { + case 0: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 2: + kbc_at_write_p(dev->kbc, 2, 0xfe, set); + break; + } + break; + case 1: case 2: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (gp_func) { + case 0: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 1: case 2: + fdc37c93x_do_write_alt(dev, gp_func - 1, reg, bit, set); + break; + } + break; + case 5: + gp_func = (gp_func_reg >> 3) & 0x01; + if (gp_func == 0x00) + fdc37c93x_do_write_gp(dev, reg, bit, set); + else + kbc_at_write_p(dev->kbc, 2, 0xfd, set << 1); + break; + case 6: case 7: + /* Do nothing, these bits do not exist. */ + break; + } + break; + case 4: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + } + break; + case 0: case 1: + switch (gp_func) { + case 0: + fdc_set_media_id(dev->fdc, bit ^ 1, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + } + break; + case 6: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 2: + /* TODO: Write to power LED if it's ever implemented. */ + fdc37c93x_do_write_alt(dev, 1, reg, bit, set); + break; + case 3: + fdc37c93x_do_write_alt(dev, 2, reg, bit, set); + break; + } + break; + case 7: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 2: + fdc37c93x_do_write_alt(dev, 1, reg, bit, set); + if (!set) + smi_raise(); + break; + } + break; + } + break; + case 5: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + break; + case 0: case 3: case 4: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + } + break; + case 1: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + if (set) + plat_power_off(); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + } + break; + } + break; + case 6: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 2: + kbc_at_write_p(dev->kbc, 1, ~(1 << bit), set << bit); + break; + } + break; + case 0: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 2: + /* TODO: Write to power LED if it's ever implemented. */ + fdc37c93x_do_write_alt(dev, 1, reg, bit, set); + break; + } + break; + case 1: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + case 2: + fdc37c93x_do_write_alt(dev, 1, reg, bit, set); + break; + } + break; + } + break; + case 7: + gp_func = (gp_func_reg >> 3) & 0x03; + switch (bit) { + default: + switch (gp_func) { + case 0: + fdc37c93x_do_write_alt(dev, 0, reg, bit, set); + break; + case 1: + fdc37c93x_do_write_gp(dev, reg, bit, set); + break; + } + break; + } + break; + } +} + static uint8_t fdc37c93x_gpio_read(uint16_t port, void *priv) { const fdc37c93x_t *dev = (fdc37c93x_t *) priv; uint8_t ret = 0xff; - if (strcmp(machine_get_internal_name(), "vectra54")) - ret = dev->gpio_regs[port & 1]; + if (dev->locked) { + if (dev->is_compaq) + ret = fdc37c93x_read(port & 0x0001, priv); + } else if (port & 0x0001) switch (dev->gpio_reg) { + case 0x01: case 0x02: + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, dev->gpio_reg, i); + break; + case 0x03: + ret = dev->ld_regs[0x08][0xf4]; + break; + case 0x04 ... 0x07: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, dev->gpio_reg, i); + } + break; + case 0x08 ... 0x0f: + if (dev->chip_id >= FDC37C93X_FR) + ret = dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08]; + break; + } else + ret = dev->gpio_reg; return ret; } @@ -139,8 +706,52 @@ fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv) { fdc37c93x_t *dev = (fdc37c93x_t *) priv; - if (!(port & 1)) - dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); + if (dev->locked) { + if (dev->is_compaq) + fdc37c93x_write(port & 0x0001, val, priv); + } else if (port & 0x0001) switch (dev->gpio_reg) { + case 0x01: case 0x02: + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, dev->gpio_reg, i, val & (1 << i)); + break; + case 0x03: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[0x08][0xf4] = val & 0xef; + else + dev->ld_regs[0x08][0xf4] = val & 0x0f; + break; + case 0x04 ... 0x07: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, dev->gpio_reg, i, val & (1 << i)); + break; + case 0x08: case 0x0a: + case 0x0c: case 0x0e: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val; + break; + case 0x09: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val & 0xd3; + break; + case 0x0b: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val & 0x17; + break; + case 0x0d: + if (dev->chip_id == FDC37C93X_APM) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val; + else if (dev->chip_id == FDC37C93X_FR) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val & 0xbf; + break; + case 0x0f: + if (dev->chip_id == FDC37C93X_APM) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val & 0x7f; + else if (dev->chip_id == FDC37C93X_FR) + dev->ld_regs[0x08][0xb0 + dev->gpio_reg - 0x08] = val & 0x3f; + break; + } else + dev->gpio_reg = val; } static void @@ -226,7 +837,14 @@ fdc37c93x_serial_handler(fdc37c93x_t *dev, const int uart) serial_setup(dev->uart[uart], dev->uart_base[uart], dev->ld_regs[uart_no][0x70]); } - serial_irq(dev->uart[uart], dev->ld_regs[uart_no][0x70]); + /* + TODO: If UART 2's own IRQ pin is also enabled when shared, + it should also be asserted. + */ + if ((dev->chip_id >= FDC37C93X_FR) && (dev->ld_regs[4][0xf0] & 0x80)) + serial_irq(dev->uart[uart], dev->ld_regs[4][0x70]); + else + serial_irq(dev->uart[uart], dev->ld_regs[uart_no][0x70]); } static void @@ -304,7 +922,8 @@ fdc37c93x_auxio_handler(fdc37c93x_t *dev) static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) { - const uint8_t local_enable = !dev->locked && !!(dev->regs[0x03] & 0x80); + const uint8_t local_enable = !!(dev->regs[0x03] & 0x80) || + (dev->is_compaq && dev->locked); const uint16_t old_base = dev->gpio_base; dev->gpio_base = 0x0000; @@ -383,23 +1002,15 @@ static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv) { fdc37c93x_t *dev = (fdc37c93x_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; + uint8_t index = !(port & 1); uint8_t valxor; - /* Compaq Presario 4500: Unlock at FB, Register at EA, Data at EB, Lock at F9. */ - if (port == 0xea) - index = 1; - else if (port == 0xeb) - index = 0; - - if (port == 0xfb) { + if (port == 0x00fb) { fdc37c93x_state_change(dev, 1); dev->tries = 0; - return; - } else if (port == 0xf9) { + } else if (port == 0x00f9) fdc37c93x_state_change(dev, 0); - return; - } else if (index) { + else if (index) { if ((!dev->is_compaq) && (val == 0x55) && !dev->locked) { if (dev->tries) { fdc37c93x_state_change(dev, 1); @@ -407,338 +1018,480 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) } else dev->tries++; } else if (dev->locked) { - if ((!dev->is_compaq) && (val == 0xaa)) { + if ((!dev->is_compaq) && (val == 0xaa)) fdc37c93x_state_change(dev, 0); - return; - } - dev->cur_reg = val; + else + dev->cur_reg = val; } else if ((!dev->is_compaq) && dev->tries) dev->tries = 0; - return; - } else { - if (dev->locked) { - if (dev->cur_reg < 48) { - valxor = val ^ dev->regs[dev->cur_reg]; - if ((val == 0x20) || (val == 0x21)) - return; - dev->regs[dev->cur_reg] = val; - } else { - uint8_t keep = 0x00; + } else if (dev->locked) { + if (dev->cur_reg < 0x30) { + valxor = val ^ dev->regs[dev->cur_reg]; - valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; - if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) - return; - /* Block writes to some logical devices. */ - if (dev->regs[7] > 0x0a) - return; - else - switch (dev->regs[7]) { - // case 0x01: - // case 0x02: - // return; - case 0x06: - if (!dev->has_nvr) - return; - /* Bits 0 to 3 of logical device 6 (RTC) register F0h must stay set - once they are set. */ - else if (dev->cur_reg == 0xf0) - keep = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0x0f; - break; - case 0x09: - /* If we're on the FDC37C935, return as this is not a valid - logical device there. */ - if (!dev->is_apm && (dev->chip_id == 0x02)) - return; - break; - case 0x0a: - /* If we're not on the FDC37C931APM, return as this is not a - valid logical device there. */ - if (!dev->is_apm) - return; - break; - - default: - break; - } - dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; - } - } else - return; - } - - if (dev->cur_reg < 48) { - switch (dev->cur_reg) { - case 0x02: - if (val == 0x02) - fdc37c93x_state_change(dev, 0); - break; - case 0x03: - dev->regs[0x03] &= 0x83; - break; - case 0x22: - if (valxor & 0x01) - fdc37c93x_fdc_handler(dev); - if (valxor & 0x08) - fdc37c93x_lpt_handler(dev); - if (valxor & 0x10) - fdc37c93x_serial_handler(dev, 0); - if (valxor & 0x20) - fdc37c93x_serial_handler(dev, 1); - if ((valxor & 0x40) && (dev->chip_id != 0x02)) - fdc37c93x_access_bus_handler(dev); - break; - - case 0x27: - if (dev->chip_id != 0x02) - fdc37c93x_superio_handler(dev); - break; - - default: - break; - } - - return; - } - - switch (dev->regs[7]) { - case 0: - /* FDD */ switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x01; - if (valxor) - fdc37c93x_fdc_handler(dev); + case 0x02: + dev->regs[dev->cur_reg] = val; + if (val == 0x02) + fdc37c93x_state_change(dev, 0); break; - case 0xF0: + case 0x03: + dev->regs[dev->cur_reg] = val & 0x83; + break; + case 0x07: case 0x26: + case 0x2e ... 0x2f: + dev->regs[dev->cur_reg] = val; + break; + case 0x22: + if (dev->chip_id >= FDC37C93X_FR) + dev->regs[dev->cur_reg] = val & 0x7f; + else + dev->regs[dev->cur_reg] = val & 0x6f; + if (valxor & 0x01) - fdc_update_enh_mode(dev->fdc, val & 0x01); - if (valxor & 0x10) - fdc_set_swap(dev->fdc, (val & 0x10) >> 4); - break; - case 0xF1: - if (valxor & 0xC) - fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); - break; - case 0xF2: - if (valxor & 0xC0) - fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); - if (valxor & 0x30) - fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); - if (valxor & 0x0C) - fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); - if (valxor & 0x03) - fdc_update_rwc(dev->fdc, 0, (val & 0x03)); - break; - case 0xF4: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); - break; - case 0xF5: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); - break; - case 0xF6: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); - break; - case 0xF7: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); - break; - - default: - break; - } - break; - case 3: - /* Parallel port */ - switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x08; - if (valxor) + fdc37c93x_fdc_handler(dev); + if (valxor & 0x08) fdc37c93x_lpt_handler(dev); - break; - - default: - break; - } - break; - case 4: - /* Serial port 1 */ - switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x10; - if (valxor) + if (valxor & 0x10) fdc37c93x_serial_handler(dev, 0); - break; - - default: - break; - } - break; - case 5: - /* Serial port 2 */ - switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x20; - if (valxor) + if (valxor & 0x20) fdc37c93x_serial_handler(dev, 1); - break; - - default: - break; - } - break; - case 6: - /* RTC/NVR */ - if (!dev->has_nvr) - return; - switch (dev->cur_reg) { - case 0x30: - if (valxor) { - fdc37c93x_nvr_pri_handler(dev); - if (dev->chip_id != 0x02) - fdc37c93x_nvr_sec_handler(dev); - } - break; - case 0x62: - case 0x63: - if ((dev->chip_id != 0x02) && valxor) - fdc37c93x_nvr_sec_handler(dev); - break; - case 0xf0: - if (valxor) { - nvr_lock_set(0x80, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x01), dev->nvr); - nvr_lock_set(0xa0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x02), dev->nvr); - nvr_lock_set(0xc0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x04), dev->nvr); - nvr_lock_set(0xe0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x08), dev->nvr); - if ((dev->chip_id == 0x02) && (dev->ld_regs[6][dev->cur_reg] & 0x80)) - nvr_bank_set(0, 1, dev->nvr); - else if ((dev->chip_id != 0x02) && (dev->ld_regs[6][dev->cur_reg] & 0x80)) - switch ((dev->ld_regs[6][dev->cur_reg] >> 4) & 0x07) { - default: - case 0x00: - nvr_bank_set(0, 0xff, dev->nvr); - nvr_bank_set(1, 1, dev->nvr); - break; - case 0x01: - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 1, dev->nvr); - break; - case 0x02: - case 0x04: - nvr_bank_set(0, 0xff, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); - break; - case 0x03: - case 0x05: - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); - break; - case 0x06: - nvr_bank_set(0, 0xff, dev->nvr); - nvr_bank_set(1, 2, dev->nvr); - break; - case 0x07: - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 2, dev->nvr); - break; - } - else { - nvr_bank_set(0, 0, dev->nvr); - if (dev->chip_id != 0x02) - nvr_bank_set(1, 0xff, dev->nvr); - } - - fdc37c93x_nvr_pri_handler(dev); - if (dev->chip_id != 0x02) - fdc37c93x_nvr_sec_handler(dev); - } - break; - - default: - break; - } - break; - case 7: - /* Keyboard */ - switch (dev->cur_reg) { - case 0x30: - if (valxor) - fdc37c93x_kbc_handler(dev); - break; - - default: - break; - } - break; - case 8: - /* Auxiliary I/O */ - switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if (valxor) - fdc37c93x_auxio_handler(dev); - break; - - default: - break; - } - break; - case 9: - /* Access bus (FDC37C932FR and FDC37C931APM only) */ - switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x40; - if (valxor) + if ((dev->chip_id >= FDC37C93X_FR) && (valxor & 0x40)) fdc37c93x_access_bus_handler(dev); break; + case 0x23: + if (dev->chip_id >= FDC37C93X_FR) + dev->regs[dev->cur_reg] = val & 0x7f; + else + dev->regs[dev->cur_reg] = val & 0x6f; + break; + case 0x24: + if (dev->chip_id >= FDC37C93X_FR) + dev->regs[dev->cur_reg] = val & 0xcf; + else + dev->regs[dev->cur_reg] = val & 0xcc; + + if ((dev->chip_id >= FDC37C93X_FR) && (valxor & 0x01)) { + serial_set_clock_src(dev->uart[0], (val & 0x01) ? + 48000000.0 : 24000000.0); + serial_set_clock_src(dev->uart[1], (val & 0x01) ? + 48000000.0 : 24000000.0); + } + break; + case 0x27: + if (dev->chip_id >= FDC37C93X_FR) { + dev->regs[dev->cur_reg] = val; + + fdc37c93x_superio_handler(dev); + } + break; + case 0x28: + if (dev->chip_id >= FDC37C93X_FR) + dev->regs[dev->cur_reg] = val & 0x1f; + break; default: break; } - break; - case 10: - /* Access bus (FDC37C931APM only) */ - switch (dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x70: - if (valxor) - fdc37c93x_acpi_handler(dev); - break; + } else { + valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; - default: + if ((dev->regs[7] <= dev->max_ld) && ((dev->regs[7] != 0x08) || + (dev->cur_reg < 0xb0) || (dev->cur_reg > 0xdf) || + (dev->chip_id >= FDC37C93X_FR))) switch (dev->regs[7]) { + case 0x00: /* FDD */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x70: + case 0x74: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x01; + if (valxor) + fdc37c93x_fdc_handler(dev); + break; + case 0xf0: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x1f; + + if (valxor & 0x01) + fdc_update_enh_mode(dev->fdc, val & 0x01); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) >> 4); + break; + case 0xf1: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0xfc; + + if (valxor & 0x0c) + fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); + break; + case 0xf2: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if (valxor & 0xc0) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (valxor & 0x0c) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, (val & 0x03)); + break; + case 0xf4 ... 0xf7: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x5b; + + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, dev->cur_reg - 0xf4, + (val & 0x18) >> 3); + break; + } + break; + case 0x01: /* IDE1 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x62: case 0x63: + case 0x70: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x02; + break; + case 0xf0: case 0xf1: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x1f; + else if (dev->cur_reg == 0xf0) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + break; + } + break; + case 0x02: /* IDE2 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x62: case 0x63: + case 0x70: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x04; + break; + case 0xf0: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x01; + break; + } + break; + case 0x03: /* Parallel Port */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x70: + case 0x74: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x08; + if (valxor) + fdc37c93x_lpt_handler(dev); + break; + case 0xf0: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + break; + case 0xf1: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x03; + break; + } + break; + case 0x04: /* Serial port 1 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x70: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x10; + if (valxor) + fdc37c93x_serial_handler(dev, 0); + break; + /* TODO: Bit 0 = MIDI Mode, Bit 1 = High speed. */ + case 0xf0: + if (dev->chip_id >= FDC37C93X_FR) { + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x83; + } else + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x03; + + if (valxor & 0x83) { + fdc37c93x_serial_handler(dev, 0); + fdc37c93x_serial_handler(dev, 1); + } + break; + } + break; + case 0x05: /* Serial port 2 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x62: case 0x63: + case 0x70: + case 0x74: + if (((dev->cur_reg != 0x62) && (dev->cur_reg != 0x63)) || + (dev->chip_id == FDC37C93X_FR)) { + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x20; + if (valxor) + fdc37c93x_serial_handler(dev, 1); + } + break; + /* TODO: Bit 0 = MIDI Mode, Bit 1 = High speed. */ + case 0xf0: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x03; + + if (valxor & 0x03) { + fdc37c93x_serial_handler(dev, 0); + fdc37c93x_serial_handler(dev, 1); + } + break; + case 0xf1: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x7f; + break; + case 0xf2: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + break; + } + break; + case 0x06: /* RTC */ + switch (dev->cur_reg) { + case 0x30: + // case 0x60: case 0x61: + case 0x62: case 0x63: + case 0x70: + if (((dev->cur_reg != 0x62) && (dev->cur_reg != 0x63)) || + (dev->chip_id >= FDC37C93X_FR)) { + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if (valxor) { + fdc37c93x_nvr_pri_handler(dev); + + if (dev->chip_id >= FDC37C93X_FR) + fdc37c93x_nvr_sec_handler(dev); + } + } + break; + case 0xf0: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + else + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x8f; + + if (valxor) { + nvr_lock_set(0x80, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x01), dev->nvr); + nvr_lock_set(0xa0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x02), dev->nvr); + nvr_lock_set(0xc0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x04), dev->nvr); + nvr_lock_set(0xe0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x08), dev->nvr); + if (dev->ld_regs[6][dev->cur_reg] & 0x80) { + if (dev->chip_id == FDC37C93X_NORMAL) + nvr_bank_set(0, 1, dev->nvr); + else switch ((dev->ld_regs[6][dev->cur_reg] >> 4) & 0x07) { + case 0x00: + default: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 1, dev->nvr); + break; + case 0x01: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 1, dev->nvr); + break; + case 0x02: case 0x04: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + break; + case 0x03: case 0x05: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + break; + case 0x06: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 2, dev->nvr); + break; + case 0x07: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 2, dev->nvr); + break; + } + } else { + nvr_bank_set(0, 0, dev->nvr); + if (dev->chip_id >= FDC37C93X_FR) + nvr_bank_set(1, 0xff, dev->nvr); + } + + fdc37c93x_nvr_pri_handler(dev); + if (dev->chip_id >= FDC37C93X_FR) + fdc37c93x_nvr_sec_handler(dev); + } + break; + case 0xf1: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x1f; + break; + case 0xf2: case 0xf3: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + break; + case 0xf4: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x83; + break; + } + break; + case 0x07: /* Keyboard */ + switch (dev->cur_reg) { + case 0x30: + case 0x70: case 0x71: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if (valxor) + fdc37c93x_kbc_handler(dev); + break; + case 0xf0: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x87; + break; + } + break; + case 0x08: /* Aux. I/O */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x62: case 0x63: + case 0x70: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if (valxor) + fdc37c93x_auxio_handler(dev); + break; + case 0xb0: case 0xb2: + case 0xb4: case 0xb6: + case 0xe0: case 0xe1: + case 0xe9: case 0xf2: + case 0xf3: + case 0xc0 ... 0xc9: + case 0xcb ... 0xcc: + case 0xd0 ... 0xdf: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + break; + case 0xb1: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0xd3; + break; + case 0xb3: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x17; + break; + case 0xb5: + if (dev->chip_id == FDC37C93X_APM) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + else + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0xbf; + break; + case 0xb7: + if (dev->chip_id == FDC37C93X_APM) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x7f; + else + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x3f; + break; + case 0xb8: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x3f; + break; + case 0x18: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x18; + break; + case 0xe2 ... 0xe5: + case 0xe7: + case 0xeb ... 0xed: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x0f; + break; + case 0xe6: case 0xe8: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x1f; + break; + case 0xea: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x9f; + break; + case 0xef: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0xf8; + break; + case 0xf1: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x83; + else + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x03; + break; + case 0xf4: + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0xef; + else + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val & 0x0f; + break; + case 0xf6: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, 1, i, val & (1 << i)); + break; + case 0xf7: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, 2, i, val & (1 << i)); + break; + case 0xf8: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, 4, i, val & (1 << i)); + break; + case 0xf9: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, 5, i, val & (1 << i)); + break; + case 0xfa: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, 6, i, val & (1 << i)); + break; + case 0xfb: + if (dev->chip_id >= FDC37C93X_FR) + for (uint8_t i = 0; i < 8; i++) + fdc37c93x_write_gp(dev, 7, i, val & (1 << i)); + break; + } + break; + case 0x09: /* Access.Bus */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x70: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x40; + if (valxor) + fdc37c93x_access_bus_handler(dev); + break; + } + break; + case 0x0a: /* ACPI */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: case 0x61: + case 0x62: case 0x63: + case 0x70: + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val; + + if (valxor) + fdc37c93x_acpi_handler(dev); + break; + } break; } - break; - - default: - break; + } } } @@ -764,11 +1517,58 @@ fdc37c93x_read(uint16_t port, void *priv) ret = dev->chip_id; else ret = dev->regs[dev->cur_reg]; - } else { - if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); - } else + } else if (dev->regs[7] <= dev->max_ld) { + if ((dev->regs[7] == 0x00) && (dev->cur_reg == 0xf2)) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | + (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + else if ((dev->regs[7] != 0x06) || (dev->cur_reg != 0xf3)) ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; + else if ((dev->regs[7] == 0x08) && (dev->cur_reg >= 0xf6) && + (dev->cur_reg <= 0xfb) && + (dev->chip_id >= FDC37C93X_FR)) switch (dev->cur_reg) { + case 0xf6: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, 1, i); + } + break; + case 0xf7: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, 2, i); + } + break; + case 0xf8: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, 4, i); + } + break; + case 0xf9: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, 5, i); + } + break; + case 0xfa: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, 6, i); + } + break; + case 0xfb: + if (dev->chip_id >= FDC37C93X_FR) { + ret = 0x00; + for (uint8_t i = 0; i < 8; i++) + ret |= fdc37c93x_read_gp(dev, 7, i); + } + break; + } } } } @@ -786,10 +1586,12 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->regs[0x21] = 0x01; dev->regs[0x22] = 0x39; dev->regs[0x24] = 0x04; - dev->regs[0x26] = dev->port_370 ? 0x70 : 0xf0; + if (dev->chip_id >= FDC37C93X_FR) + dev->regs[0x26] = dev->port_370 ? 0x70 : 0xf0; dev->regs[0x27] = 0x03; - memset(dev->ld_regs, 0x00, sizeof(dev->ld_regs)); + for (uint8_t i = 0; i <= 0x0a; i++) + memset(dev->ld_regs[i], 0x00, 256); /* Logical device 0: FDD */ dev->ld_regs[0x00][0x30] = 0x00; @@ -807,7 +1609,8 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[0x01][0x62] = 0x03; dev->ld_regs[0x01][0x63] = 0xf6; dev->ld_regs[0x01][0x70] = 0x0e; - dev->ld_regs[0x01][0xf0] = 0x0c; + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[0x01][0xf0] = 0x0c; /* Logical device 2: IDE2 */ dev->ld_regs[0x02][0x30] = 0x00; @@ -840,7 +1643,8 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[0x05][0x70] = 0x03; dev->ld_regs[0x05][0x74] = 0x04; dev->ld_regs[0x05][0xf1] = 0x02; - dev->ld_regs[0x05][0xf2] = 0x03; + if (dev->chip_id >= FDC37C93X_FR) + dev->ld_regs[0x05][0xf2] = 0x03; serial_irq(dev->uart[1], dev->ld_regs[5][0x70]); /* Logical device 6: RTC */ @@ -858,16 +1662,34 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[0x08][0x30] = 0x00; dev->ld_regs[0x08][0x60] = 0x00; dev->ld_regs[0x08][0x61] = 0x00; + if (dev->chip_id >= FDC37C93X_FR) { + dev->ld_regs[0x08][0xb1] = 0x80; + dev->ld_regs[0x08][0xc0] = 0x01; + dev->ld_regs[0x08][0xc1] = 0x01; + dev->ld_regs[0x08][0xc5] = 0x01; + dev->ld_regs[0x08][0xc6] = 0x01; + dev->ld_regs[0x08][0xc7] = 0x01; + dev->ld_regs[0x08][0xc8] = 0x01; + dev->ld_regs[0x08][0xc9] = 0x80; + dev->ld_regs[0x08][0xcb] = 0x01; + dev->ld_regs[0x08][0xcc] = 0x01; + memset(&(dev->ld_regs[0x08][0xd0]), 0x01, 16); + } + memset(&(dev->ld_regs[0x08][0xe0]), 0x01, 14); /* Logical device 9: ACCESS.bus */ - dev->ld_regs[0x09][0x30] = 0x00; - dev->ld_regs[0x09][0x60] = 0x00; - dev->ld_regs[0x09][0x61] = 0x00; + if (dev->chip_id >= FDC37C93X_FR) { + dev->ld_regs[0x09][0x30] = 0x00; + dev->ld_regs[0x09][0x60] = 0x00; + dev->ld_regs[0x09][0x61] = 0x00; + } /* Logical device A: ACPI */ - dev->ld_regs[0x0a][0x30] = 0x00; - dev->ld_regs[0x0a][0x60] = 0x00; - dev->ld_regs[0x0a][0x61] = 0x00; + if (dev->chip_id == FDC37C93X_APM) { + dev->ld_regs[0x0a][0x30] = 0x00; + dev->ld_regs[0x0a][0x60] = 0x00; + dev->ld_regs[0x0a][0x61] = 0x00; + } fdc37c93x_gpio_handler(dev); fdc37c93x_lpt_handler(dev); @@ -899,6 +1721,62 @@ fdc37c93x_reset(fdc37c93x_t *dev) if (dev->chip_id != 0x02) fdc37c93x_superio_handler(dev); + if (dev->chip_id >= FDC37C93X_FR) { + serial_set_clock_src(dev->uart[0], 24000000.0); + serial_set_clock_src(dev->uart[1], 24000000.0); + } + + memset(dev->gpio_regs, 0xff, 256); + memset(dev->gpio_pulldn, 0xff, 8); + + /* Acer V62X requires bit 0 to be clear to not be stuck in "clear password" mode. */ + if (!strcmp(machine_get_internal_name(), "vectra54")) { + dev->gpio_pulldn[1] = 0x40; + + /* + HP Vectra VL/5 Series 4 GPIO + (TODO: Find how multipliers > 3.0 are defined): + + Bit 6: 1 = can boot, 0 = no; + Bit 7, 1 = multiplier (00 = 2.5, 01 = 2.0, + 10 = 3.0, 11 = 1.5); + Bit 5, 4 = bus speed (00 = 50 MHz, 01 = 66 MHz, + 10 = 60 MHz, 11 = ????): + Bit 7, 5, 4, 1: 0000 = 125 MHz, 0010 = 166 MHz, + 0100 = 150 MHz, 0110 = ??? MHz; + 0001 = 100 MHz, 0011 = 133 MHz, + 0101 = 120 MHz, 0111 = ??? MHz; + 1000 = 150 MHz, 1010 = 200 MHz, + 1100 = 180 MHz, 1110 = ??? MHz; + 1001 = 75 MHz, 1011 = 100 MHz, + 1101 = 90 MHz, 1111 = ??? MHz + */ + if (cpu_busspeed <= 40000000) + dev->gpio_pulldn[1] |= 0x30; + else if ((cpu_busspeed > 40000000) && (cpu_busspeed <= 50000000)) + dev->gpio_pulldn[1] |= 0x00; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + dev->gpio_pulldn[1] |= 0x20; + else if (cpu_busspeed > 60000000) + dev->gpio_pulldn[1] |= 0x10; + + if (cpu_dmulti <= 1.5) + dev->gpio_pulldn[1] |= 0x82; + else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) + dev->gpio_pulldn[1] |= 0x02; + else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) + dev->gpio_pulldn[1] |= 0x00; + else if (cpu_dmulti > 2.5) + dev->gpio_pulldn[1] |= 0x80; + } else if (!strcmp(machine_get_internal_name(), "acerv62x")) + dev->gpio_pulldn[1] = 0xfe; + else + dev->gpio_pulldn[1] = (dev->chip_id == 0x30) ? 0xff : 0xfd; + + if (strstr(machine_get_internal_name(), "acer") != NULL) + /* Bit 2 on the Acer V35N is the text/graphics toggle, bits 1 and 3 = ????. */ + dev->gpio_pulldn[2] = 0x10; + dev->locked = 0; } @@ -920,41 +1798,59 @@ fdc37c93x_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - dev->chip_id = info->local & 0xff; - dev->is_apm = (info->local >> 8) & 0x01; - dev->is_compaq = (info->local >> 8) & 0x02; - dev->has_nvr = !((info->local >> 8) & 0x04); - dev->port_370 = ((info->local >> 8) & 0x08); + dev->chip_id = info->local & FDC37C93X_CHIP_ID; + dev->kbc_type = info->local & FDC37C93X_KBC; - dev->gpio_regs[0] = 0xff; -#if 0 - dev->gpio_regs[1] = (info->local == 0x0030) ? 0xff : 0xfd; -#endif - dev->gpio_regs[1] = (dev->chip_id == 0x30) ? 0xff : 0xfd; + dev->is_apm = (dev->chip_id == FDC37C93X_APM); + dev->is_compaq = (dev->kbc_type == FDC37C931); + + dev->has_nvr = !(info->local & FDC37C93X_NO_NVR); + dev->port_370 = !!(info->local & FDC37C93X_370); if (dev->has_nvr) { - dev->nvr = device_add(&at_nvr_device); + dev->nvr = device_add(&amstrad_megapc_nvr_device); nvr_bank_set(0, 0, dev->nvr); nvr_bank_set(1, 0xff, dev->nvr); } - if (dev->is_apm || (dev->chip_id == 0x03)) - dev->access_bus = device_add(&access_bus_device); + dev->max_ld = 8; - if (dev->is_apm) + if (dev->chip_id >= FDC37C93X_FR) { + dev->access_bus = device_add(&access_bus_device); + dev->max_ld++; + } + + if (dev->chip_id == FDC37C93X_APM) { dev->acpi = device_add(&acpi_smc_device); + dev->max_ld++; + } if (dev->is_compaq) { - io_sethandler(0x0ea, 0x0002, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); io_sethandler(0x0f9, 0x0001, fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); io_sethandler(0x0fb, 0x0001, fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); } - dev->kbc = device_add(&keyboard_ps2_ami_pci_device); + switch (dev->kbc_type) { + case FDC37C931: + dev->kbc = device_add(&keyboard_ps2_compaq_device); + break; + case FDC37C932: + dev->kbc = device_add(&keyboard_ps2_intel_ami_pci_device); + break; + case FDC37C933: + default: + dev->kbc = device_add(&keyboard_ps2_pci_device); + break; + case FDC37C935: + dev->kbc = device_add(&keyboard_ps2_phoenix_device); + break; + case FDC37C937: + dev->kbc = device_add(&keyboard_ps2_phoenix_pci_device); + break; + } /* Set the defaults here so the ports can be removed by fdc37c93x_reset(). */ dev->fdc_base = 0x03f0; @@ -978,109 +1874,11 @@ fdc37c93x_init(const device_t *info) return dev; } -const device_t fdc37c931apm_device = { - .name = "SMC FDC37C931APM Super I/O", - .internal_name = "fdc37c931apm", +const device_t fdc37c93x_device = { + .name = "SMC FDC37C93x Super I/O", + .internal_name = "fdc37c93x", .flags = 0, - .local = 0x130, /* Share the same ID with the 932QF. */ - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c931apm_compaq_device = { - .name = "SMC FDC37C931APM Super I/O (Compaq Presario 4500)", - .internal_name = "fdc37c931apm_compaq", - .flags = 0, - .local = 0x330, /* Share the same ID with the 932QF. */ - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c932_device = { - .name = "SMC FDC37C932 Super I/O", - .internal_name = "fdc37c932", - .flags = 0, - .local = 0x02, - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c932fr_device = { - .name = "SMC FDC37C932FR Super I/O", - .internal_name = "fdc37c932fr", - .flags = 0, - .local = 0x03, - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c932qf_device = { - .name = "SMC FDC37C932QF Super I/O", - .internal_name = "fdc37c932qf", - .flags = 0, - .local = 0x30, - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c935_device = { - .name = "SMC FDC37C935 Super I/O", - .internal_name = "fdc37c935", - .flags = 0, - .local = 0x02, - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c935_370_device = { - .name = "SMC FDC37C935 Super I/O (Port 370h)", - .internal_name = "fdc37c935_370", - .flags = 0, - .local = 0x802, - .init = fdc37c93x_init, - .close = fdc37c93x_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t fdc37c935_no_nvr_device = { - .name = "SMC FDC37C935 Super I/O", - .internal_name = "fdc37c935", - .flags = 0, - .local = 0x402, + .local = 0, .init = fdc37c93x_init, .close = fdc37c93x_close, .reset = NULL, From 76ae3eff56269fbe8c41137caf0fb56979e9be3f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 5 May 2025 05:12:17 +0200 Subject: [PATCH 0840/1190] And the root CMakeLists.txt. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 007c1ffd8..5b78295fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,7 +180,6 @@ cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) From ebb52490c32fed37442a8fc167d5a5ad2936a9a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 5 May 2025 05:14:56 +0200 Subject: [PATCH 0841/1190] Properly un-dev-branch the Laser XT stuff in the keyboard files. --- src/device/keyboard_xt.c | 2 -- src/include/86box/keyboard.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 3c616a2ab..bafc80d88 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -1312,7 +1312,6 @@ const device_t keyboard_xt_t1x00_device = { .config = NULL }; -#ifdef USE_LASERXT const device_t keyboard_xt_lxt3_device = { .name = "VTech Laser Turbo XT Keyboard", .internal_name = "keyboard_xt_lxt", @@ -1326,7 +1325,6 @@ const device_t keyboard_xt_lxt3_device = { .force_redraw = NULL, .config = NULL }; -#endif /* USE_LASERXT */ const device_t keyboard_xt_olivetti_device = { .name = "Olivetti XT Keyboard", diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 583960e80..024b16169 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -224,9 +224,7 @@ extern const device_t keyboard_xt86_device; extern const device_t keyboard_xt_compaq_device; extern const device_t keyboard_xt_t1x00_device; extern const device_t keyboard_tandy_device; -# ifdef USE_LASERXT extern const device_t keyboard_xt_lxt3_device; -# endif /* USE_LASERXT */ extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_xt_hyundai_device; From 1e81473d34f254cab13019b62e948c6e9a950b53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 5 May 2025 05:59:20 +0200 Subject: [PATCH 0842/1190] Fix MMX_ENTER() exceptions. --- src/cpu/x86_ops_mmx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/x86_ops_mmx.h b/src/cpu/x86_ops_mmx.h index 338948af5..9a2d797a8 100644 --- a/src/cpu/x86_ops_mmx.h +++ b/src/cpu/x86_ops_mmx.h @@ -22,12 +22,12 @@ } #define MMX_ENTER() \ - if (!cpu_has_feature(CPU_FEATURE_MMX)) { \ + if (!cpu_has_feature(CPU_FEATURE_MMX) || (cr0 & 0x4)) { \ cpu_state.pc = cpu_state.oldpc; \ x86illegal(); \ return 1; \ } \ - if (cr0 & 0xc) { \ + if (cr0 & 0x8) { \ x86_int(7); \ return 1; \ } \ From c91796c388e481f759b3286f5d3d7e8f83c27251 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Mon, 5 May 2025 19:57:41 +0200 Subject: [PATCH 0843/1190] Add the Micro Firmware/Phoenix 4.05 BIOS for the PB450. --- src/machine/m_at_386dx_486.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 5b746e3ef..ed8f75a84 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -700,6 +700,8 @@ static const device_config_t pb450_config[] = { .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/OPTI802.bin", "" } }, { .name = "PNP 1.1A", .internal_name = "pnp11a", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/PNP11A.bin", "" } }, + { .name = "P4HS20 (Micro Firmware/Phoenix 4.05)", .internal_name = "p4hs20", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/p4hs20.bin", "" } }, { .files_no = 0 } }, }, From ab75f222fe04d44fc4f1cb552f78d216a028ec30 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 03:17:05 +0200 Subject: [PATCH 0844/1190] Acer V60N and V62X: Fix RAM limits. --- 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 44e93f721..bb912cf9a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14166,7 +14166,7 @@ const machine_t machines[] = { .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 786432, + .max = 532480, .step = 8192 }, .nvrmask = 511, @@ -14617,7 +14617,7 @@ const machine_t machines[] = { .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 786432, + .max = 540672, .step = 8192 }, .nvrmask = 511, From a0b80e04cd41bc28b27036bb13c96431b687fef9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 03:18:46 +0200 Subject: [PATCH 0845/1190] Remove the unused mmu_perm stuff. --- src/cpu/x86.c | 1 - src/cpu/x86_ops_mov_ctrl.h | 4 --- src/cpu/x86_ops_mov_ctrl_2386.h | 4 --- src/include/86box/mem.h | 1 - src/mem/mem.c | 59 ++++----------------------------- src/mem/mmu_2386.c | 2 -- 6 files changed, 6 insertions(+), 65 deletions(-) diff --git a/src/cpu/x86.c b/src/cpu/x86.c index a8ab9d866..1b0de661b 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -326,7 +326,6 @@ reset_common(int hard) resetreadlookup(); makemod1table(); cpu_set_edx(); - mmu_perm = 4; } x86seg_reset(); #ifdef USE_DYNAREC diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 253dc059e..3f5d6a4d7 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -201,8 +201,6 @@ opMOV_CRx_r_a16(uint32_t fetchdat) cr0 = cpu_state.regs[cpu_rm].l; if (cpu_16bitbus) cr0 |= 0x10; - if (!(cr0 & 0x80000000)) - mmu_perm = 4; if (hascache && !(cr0 & (1 << 30))) cpu_cache_int_enabled = 1; else @@ -267,8 +265,6 @@ opMOV_CRx_r_a32(uint32_t fetchdat) cr0 = cpu_state.regs[cpu_rm].l; if (cpu_16bitbus) cr0 |= 0x10; - if (!(cr0 & 0x80000000)) - mmu_perm = 4; if (hascache && !(cr0 & (1 << 30))) cpu_cache_int_enabled = 1; else diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h index 8827d29b2..0d13cc833 100644 --- a/src/cpu/x86_ops_mov_ctrl_2386.h +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -193,8 +193,6 @@ opMOV_CRx_r_a16(uint32_t fetchdat) cr0 = cpu_state.regs[cpu_rm].l; if (cpu_16bitbus) cr0 |= 0x10; - if (!(cr0 & 0x80000000)) - mmu_perm = 4; if (hascache && !(cr0 & (1 << 30))) cpu_cache_int_enabled = 1; else @@ -255,8 +253,6 @@ opMOV_CRx_r_a32(uint32_t fetchdat) cr0 = cpu_state.regs[cpu_rm].l; if (cpu_16bitbus) cr0 |= 0x10; - if (!(cr0 & 0x80000000)) - mmu_perm = 4; if (hascache && !(cr0 & (1 << 30))) cpu_cache_int_enabled = 1; else diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index f8d0f659a..62cb493a5 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -300,7 +300,6 @@ extern int writelnum; extern int memspeed[11]; -extern int mmu_perm; extern uint8_t high_page; /* if a high (> 4 gb) page was detected */ extern uint8_t *_mem_exec[MEM_MAPPINGS_NO]; diff --git a/src/mem/mem.c b/src/mem/mem.c index 8c2cfd6cc..07d897172 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -108,7 +108,6 @@ int mem_a20_alt = 0; int mem_a20_state = 0; int mmuflush = 0; -int mmu_perm = 4; #ifdef USE_NEW_DYNAREC uint64_t *byte_dirty_mask; @@ -125,10 +124,6 @@ mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; uint8_t *_mem_exec[MEM_MAPPINGS_NO]; -/* FIXME: re-do this with a 'mem_ops' struct. */ -static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */ -static uint8_t *readlookupp; -static uint8_t *writelookupp; static mem_mapping_t *base_mapping; static mem_mapping_t *last_mapping; static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO]; @@ -187,10 +182,8 @@ resetreadlookup(void) /* Initialize the tables for high (> 1024K) RAM. */ memset(readlookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); - memset(readlookupp, 0x04, (1 << 20) * sizeof(uint8_t)); memset(writelookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); - memset(writelookupp, 0x04, (1 << 20) * sizeof(uint8_t)); readlnext = 0; writelnext = 0; @@ -204,14 +197,11 @@ flushmmucache(void) for (uint16_t c = 0; c < 256; c++) { if (readlookup[c] != (int) 0xffffffff) { readlookup2[readlookup[c]] = LOOKUP_INV; - readlookupp[readlookup[c]] = 4; readlookup[c] = 0xffffffff; } 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; } } @@ -231,9 +221,7 @@ 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; } } @@ -259,14 +247,11 @@ flushmmucache_nopc(void) for (uint16_t c = 0; c < 256; c++) { if (readlookup[c] != (int) 0xffffffff) { readlookup2[readlookup[c]] = LOOKUP_INV; - readlookupp[readlookup[c]] = 4; readlookup[c] = 0xffffffff; } 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; } } @@ -348,7 +333,6 @@ mmutranslatereal_normal(uint32_t addr, int rw) return 0xffffffffffffffffULL; } - mmu_perm = temp & 4; rammap(addr2) |= (rw ? 0x60 : 0x20); uint64_t page = temp & ~0x3fffff; @@ -371,7 +355,6 @@ mmutranslatereal_normal(uint32_t addr, int rw) return 0xffffffffffffffffULL; } - mmu_perm = temp & 4; rammap(addr2) |= 0x20; rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw ? 0x60 : 0x20); @@ -435,7 +418,6 @@ mmutranslatereal_pae(uint32_t addr, int rw) return 0xffffffffffffffffULL; } - mmu_perm = temp & 4; rammap64(addr3) |= (rw ? 0x60 : 0x20); return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; @@ -456,7 +438,6 @@ mmutranslatereal_pae(uint32_t addr, int rw) return 0xffffffffffffffffULL; } - mmu_perm = temp & 4; rammap64(addr3) |= 0x20; rammap64(addr4) |= (rw ? 0x60 : 0x20); @@ -631,7 +612,6 @@ addreadlookup(uint32_t virt, uint32_t phys) else readlookup2[virt >> 12] = (uintptr_t) &ram[a]; #endif - readlookupp[virt >> 12] = mmu_perm; readlookup[readlnext++] = virt >> 12; readlnext &= (cachesize - 1); @@ -671,7 +651,6 @@ addwritelookup(uint32_t virt, uint32_t phys) # endif #endif page_lookup[virt >> 12] = &pages[phys >> 12]; - page_lookupp[virt >> 12] = mmu_perm; } else { #if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) writelookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; @@ -684,7 +663,6 @@ addwritelookup(uint32_t virt, uint32_t phys) writelookup2[virt >> 12] = (uintptr_t) &ram[a]; #endif } - writelookupp[virt >> 12] = mmu_perm; writelookup[writelnext++] = virt >> 12; writelnext &= (cachesize - 1); @@ -973,10 +951,8 @@ readmemwl(uint32_t addr) } return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) return *(uint16_t *) (readlookup2[addr >> 12] + addr); - } } if (cr0 >> 31) { @@ -1044,7 +1020,6 @@ writememwl(uint32_t addr, uint16_t val) writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); return; } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; return; } @@ -1052,7 +1027,6 @@ writememwl(uint32_t addr, uint16_t val) if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); - mmu_perm = page_lookupp[addr >> 12]; return; } @@ -1100,10 +1074,8 @@ readmemwl_no_mmut(uint32_t addr, uint32_t *a64) } return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) return *(uint16_t *) (readlookup2[addr >> 12] + addr); - } } if (cr0 >> 31) { @@ -1149,14 +1121,12 @@ writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) writemembl_no_mmut(addr + 1, a64[1], val >> 8); return; } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; return; } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { - mmu_perm = page_lookupp[addr >> 12]; page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); return; } @@ -1231,10 +1201,8 @@ readmemll(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(addr, addr64a) | (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) return *(uint32_t *) (readlookup2[addr >> 12] + addr); - } } if (cr0 >> 31) { @@ -1316,14 +1284,12 @@ writememll(uint32_t addr, uint32_t val) writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); return; } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; return; } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); return; } @@ -1378,10 +1344,8 @@ readmemll_no_mmut(uint32_t addr, uint32_t *a64) } return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) return *(uint32_t *) (readlookup2[addr >> 12] + addr); - } } if (cr0 >> 31) { @@ -1429,14 +1393,12 @@ writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); return; } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; return; } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); return; } @@ -1516,10 +1478,8 @@ readmemql(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 readmemll_no_mmut(addr, addr64a) | (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) return *(uint64_t *) (readlookup2[addr >> 12] + addr); - } } if (cr0 >> 31) { @@ -1611,14 +1571,12 @@ writememql(uint32_t addr, uint64_t val) writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); return; } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; *(uint64_t *) (writelookup2[addr >> 12] + addr) = val; return; } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); page_lookup[addr >> 12]->write_l(addr + 4, val >> 32, page_lookup[addr >> 12]); return; @@ -1702,8 +1660,7 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a; } - } else - mmu_perm = page_lookupp[addr >> 12]; + } addr++; } @@ -2914,7 +2871,6 @@ mem_reset(void) pages = (page_t *) malloc(m * sizeof(page_t)); memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); - memset(page_lookupp, 0x04, (1 << 20) * sizeof(uint8_t)); memset(pages, 0x00, pages_sz * sizeof(page_t)); @@ -3033,11 +2989,8 @@ mem_init(void) /* Allocate the lookup tables. */ page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *)); - page_lookupp = (uint8_t *) malloc((1 << 20) * sizeof(uint8_t)); readlookup2 = malloc((1 << 20) * sizeof(uintptr_t)); - readlookupp = malloc((1 << 20) * sizeof(uint8_t)); writelookup2 = malloc((1 << 20) * sizeof(uintptr_t)); - writelookupp = malloc((1 << 20) * sizeof(uint8_t)); } static void diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 1a2782237..ebf062d95 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -211,7 +211,6 @@ mmutranslatereal_2386(uint32_t addr, int rw) return 0xffffffffffffffffULL; } - mmu_perm = temp & 4; mem_writel_map(addr2, mem_readl_map(addr2) | (rw ? 0x60 : 0x20)); return (temp & ~0x3fffff) + (addr & 0x3fffff); @@ -231,7 +230,6 @@ mmutranslatereal_2386(uint32_t addr, int rw) return 0xffffffffffffffffULL; } - mmu_perm = temp & 4; mem_writel_map(addr2, mem_readl_map(addr2) | 0x20); mem_writel_map((temp2 & ~0xfff) + ((addr >> 10) & 0xffc), mem_readl_map((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) | (rw ? 0x60 : 0x20)); From c3debc5e27dd70e94c393d06420b8845ca9187dd Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 03:21:54 +0200 Subject: [PATCH 0846/1190] Implement the RZ-1000 PCI IDE controller needed by some Intel machines. --- src/disk/CMakeLists.txt | 1 + src/disk/hdc_ide_rz1000.c | 322 +++++++++++++++++++++++++++++++++++++ src/include/86box/hdc.h | 6 + src/machine/m_at_socket4.c | 3 +- src/machine/m_at_socket5.c | 2 +- 5 files changed, 332 insertions(+), 2 deletions(-) create mode 100644 src/disk/hdc_ide_rz1000.c diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index 3f6a4d018..bdbb9e74c 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -31,6 +31,7 @@ add_library(hdd OBJECT hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c + hdc_ide_rz1000.c hdc_ide_sff8038i.c hdc_ide_um8673f.c hdc_ide_w83769f.c diff --git a/src/disk/hdc_ide_rz1000.c b/src/disk/hdc_ide_rz1000.c new file mode 100644 index 000000000..d93e83859 --- /dev/null +++ b/src/disk/hdc_ide_rz1000.c @@ -0,0 +1,322 @@ +/* + * 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. + * + * Implementation of the PC Technology RZ-1000 controller. + * + * Authors: Miran Grca, + * + * Copyright 2025 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/cdrom.h> +#include <86box/scsi_device.h> +#include <86box/scsi_cdrom.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/zip.h> +#include <86box/mo.h> + +typedef struct rz1000_t { + uint8_t vlb_idx; + uint8_t id; + uint8_t in_cfg; + uint8_t channels; + uint8_t pci; + uint8_t irq_state; + uint8_t pci_slot; + uint8_t pad0; + uint8_t regs[256]; + uint32_t local; + int irq_mode[2]; + int irq_pin; + int irq_line; +} rz1000_t; + +static int next_id = 0; + +#define ENABLE_RZ1000_LOG 1 +#ifdef ENABLE_RZ1000_LOG +int rz1000_do_log = ENABLE_RZ1000_LOG; + +static void +rz1000_log(const char *fmt, ...) +{ + va_list ap; + + if (rz1000_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define rz1000_log(fmt, ...) +#endif + +static void +rz1000_ide_handlers(rz1000_t *dev) +{ + uint16_t main; + uint16_t side; + + if (dev->channels & 0x01) { + ide_pri_disable(); + + main = 0x1f0; + side = 0x3f6; + + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->regs[0x04] & 0x01) + ide_pri_enable(); + } + + if (dev->channels & 0x02) { + ide_sec_disable(); + + main = 0x170; + side = 0x376; + + ide_set_base(1, main); + ide_set_side(1, side); + + if (dev->regs[0x04] & 0x01) + ide_sec_enable(); + } +} + +static void +rz1000_pci_write(int func, int addr, uint8_t val, void *priv) +{ + rz1000_t *dev = (rz1000_t *) priv; + + rz1000_log("rz1000_pci_write(%i, %02X, %02X)\n", func, addr, val); + + if (func == 0x00) + switch (addr) { + case 0x04: + dev->regs[addr] = (val & 0x41); + rz1000_ide_handlers(dev); + break; + case 0x07: + dev->regs[addr] &= ~(val & 0x80); + break; + case 0x09: + if ((dev->regs[addr] & 0x0a) == 0x0a) { + dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05); + dev->irq_mode[0] = !!(val & 0x01); + dev->irq_mode[1] = !!(val & 0x04); + rz1000_ide_handlers(dev); + } + break; + case 0x10: + dev->regs[0x10] = (val & 0xf8) | 1; + rz1000_ide_handlers(dev); + break; + case 0x11: + dev->regs[0x11] = val; + rz1000_ide_handlers(dev); + break; + case 0x14: + dev->regs[0x14] = (val & 0xfc) | 1; + rz1000_ide_handlers(dev); + break; + case 0x15: + dev->regs[0x15] = val; + rz1000_ide_handlers(dev); + break; + case 0x18: + dev->regs[0x18] = (val & 0xf8) | 1; + rz1000_ide_handlers(dev); + break; + case 0x19: + dev->regs[0x19] = val; + rz1000_ide_handlers(dev); + break; + case 0x1c: + dev->regs[0x1c] = (val & 0xfc) | 1; + rz1000_ide_handlers(dev); + break; + case 0x1d: + dev->regs[0x1d] = val; + rz1000_ide_handlers(dev); + break; + case 0x40 ... 0x4f: + dev->regs[addr] = val; + break; + } +} + +static uint8_t +rz1000_pci_read(int func, int addr, void *priv) +{ + rz1000_t *dev = (rz1000_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = dev->regs[addr]; + + rz1000_log("rz1000_pci_read(%i, %02X, %02X)\n", func, addr, ret); + + return ret; +} + +static void +rz1000_reset(void *priv) +{ + rz1000_t *dev = (rz1000_t *) priv; + int i = 0; + int min_channel; + int max_channel; + + switch (dev->channels) { + default: + case 0x00: + min_channel = max_channel = 0; + break; + case 0x01: + min_channel = 0; + max_channel = 1; + break; + case 0x02: + min_channel = 2; + max_channel = 3; + break; + case 0x03: + min_channel = 0; + max_channel = 3; + break; + } + + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel >= min_channel) && + (cdrom[i].ide_channel <= max_channel) && cdrom[i].priv) + scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); + } + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) && + (zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv) + zip_reset((scsi_common_t *) zip_drives[i].priv); + } + for (i = 0; i < MO_NUM; i++) { + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) && + (mo_drives[i].ide_channel <= max_channel) && mo_drives[i].priv) + mo_reset((scsi_common_t *) mo_drives[i].priv); + } + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + rz1000_log("dev->local = %08X\n", dev->local); + + dev->regs[0x00] = 0x42; /* PC Technology */ + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x00; /* RZ-1000 */ + dev->regs[0x03] = 0x10; + dev->regs[0x04] = 0x01; + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x08] = 0x02; /* Revision 02 */ + dev->regs[0x09] = dev->local; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ + + dev->regs[0x3c] = 0x14; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ + + dev->irq_mode[0] = dev->irq_mode[1] = 0; + dev->irq_pin = PCI_INTA; + dev->irq_line = 14; + + rz1000_ide_handlers(dev); +} + +static void +rz1000_close(void *priv) +{ + rz1000_t *dev = (rz1000_t *) priv; + + free(dev); + + next_id = 0; +} + +static void * +rz1000_init(const device_t *info) +{ + rz1000_t *dev = (rz1000_t *) calloc(1, sizeof(rz1000_t)); + + dev->id = next_id | 0x60; + + dev->pci = !!(info->flags & DEVICE_PCI); + dev->local = info->local; + + dev->channels = ((info->local & 0x60000) >> 17) & 0x03; + + device_add(&ide_pci_2ch_device); + + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, rz1000_pci_read, rz1000_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, rz1000_pci_read, rz1000_pci_write, dev, &dev->pci_slot); + + if (dev->channels & 0x01) + ide_board_set_force_ata3(0, 1); + + if (dev->channels & 0x02) + ide_board_set_force_ata3(1, 1); + + next_id++; + + rz1000_reset(dev); + + return dev; +} + +const device_t ide_rz1000_pci_device = { + .name = "PC Technology RZ-1000 PCI", + .internal_name = "ide_rz1000_pci", + .flags = DEVICE_PCI, + .local = 0x6000a, + .init = rz1000_init, + .close = rz1000_close, + .reset = rz1000_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_rz1000_pci_single_channel_device = { + .name = "PC Technology RZ-1000 PCI", + .internal_name = "ide_rz1000_pci_single_channel", + .flags = DEVICE_PCI, + .local = 0x2000a, + .init = rz1000_init, + .close = rz1000_close, + .reset = rz1000_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 71f83e5e6..0a5985370 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -60,6 +60,8 @@ extern const device_t ide_pci_device; /* pci_ide */ extern const device_t ide_pci_sec_device; /* pci_ide sec */ extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ +extern const device_t ide_pci_ter_qua_2ch_device; /* pci_ide_ter_qua_2ch */ + extern const device_t ide_ali1489_device; /* ALi M1489 */ extern const device_t ide_ali5213_device; /* ALi M5213 */ @@ -76,10 +78,14 @@ extern const device_t ide_cmd640_pci_single_channel_sec_device; /* CMD PCI-640B extern const device_t ide_cmd646_device; /* CMD PCI-646 */ extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */ extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */ +extern const device_t ide_cmd646_ter_qua_device; /* CMD PCI-646 (Tertiary and quaternary channels) */ extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */ extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */ +extern const device_t ide_rz1000_pci_device; /* PC Technology RZ-1000 PCI */ +extern const device_t ide_rz1000_pci_single_channel_device; /* PC Technology RZ-1000 PCI (Only primary channel) */ + extern const device_t ide_um8673f_device; /* UMC UM8673F */ extern const device_t ide_um8886af_device; /* UMC UM8886AF */ diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index c747d8cc0..92f88fbe6 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -58,7 +58,8 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_phoenix_device); device_add(&sio_zb_device); - device_add(&fdc37c665_device); + device_add(&ide_rz1000_pci_single_channel_device); + device_add(&fdc37c665_ide_sec_device); device_add(&intel_flash_bxt_ami_device); } diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 02922b425..0d748b85e 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -169,8 +169,8 @@ machine_at_tek932_init(const machine_t *model) device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&i430nx_device); device_add(&sio_zb_device); - device_add(&fdc37c665_ide_device); device_add(&ide_vlb_device); + device_add(&fdc37c665_ide_pri_device); device_add(&intel_flash_bxt_ami_device); return ret; From fc3a6379b59e897cff7cde478ef79b5d83a552c7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 03:36:05 +0200 Subject: [PATCH 0847/1190] A small sanity check in the VISO code. --- src/cdrom/cdrom_image_viso.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index 4bf976794..cf132c560 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -782,9 +782,8 @@ viso_close(void *priv) if (viso->entry_map) free(viso->entry_map); - if (tf->log != NULL) { - - } + if (tf->log != NULL) + log_close(tf->log); free(viso); } @@ -1607,10 +1606,12 @@ end: return &viso->tf; } else { - image_viso_log(viso->tf.log, "Initialization failed\n"); - if (data) - free(data); - viso_close(&viso->tf); + if (viso != NULL) { + image_viso_log(viso->tf.log, "Initialization failed\n"); + if (data) + free(data); + viso_close(&viso->tf); + } return NULL; } } From c438073d689f8bce2071b9c2932f630be2cd9293 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 03:41:33 +0200 Subject: [PATCH 0848/1190] CD-ROM Image: Actually close image if ret = 0 also in case of a cue sheet, and also warn if ret = 0, closes #5552. --- src/cdrom/cdrom_image.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 519afaa4c..6bc284fd3 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -2016,6 +2016,10 @@ image_open(cdrom_t *dev, const char *path) img->has_audio = 0; else if (ret) img->has_audio = 1; + else { + image_close(img); + img = NULL; + } } else { ret = image_load_iso(img, path); @@ -2033,7 +2037,8 @@ image_open(cdrom_t *dev, const char *path) img->log = log_open(n); dev->ops = &image_ops; - } + } else + warning("Unable to load CD-ROM image: %s\n", path); } return img; From 813a19aad87988a79c5d623c81411c488e00ec7d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 03:44:50 +0200 Subject: [PATCH 0849/1190] Acer V60N and V62X: limit to 384 MB. --- 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 bb912cf9a..23409d6db 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14166,7 +14166,7 @@ const machine_t machines[] = { .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 532480, + .max = 393216, .step = 8192 }, .nvrmask = 511, @@ -14617,7 +14617,7 @@ const machine_t machines[] = { .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 540672, + .max = 393216, .step = 8192 }, .nvrmask = 511, From eb82f9bcca6f01a31b7ebfca04620e0bc37e9fc9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 04:51:59 +0200 Subject: [PATCH 0850/1190] Added the TriGem Delhi III (AMI VIA MVP3 machine). --- src/acpi.c | 8 ++++++++ src/include/86box/machine.h | 1 + src/machine/m_at_sockets7.c | 32 +++++++++++++++++++++++++++++ src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/src/acpi.c b/src/acpi.c index ccd51ebca..e9549adb0 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -2387,6 +2387,14 @@ acpi_reset(void *priv) dev->regs.gpi_val = 0xfff57fc1; if (!strcmp(machine_get_internal_name(), "ficva503a") || !strcmp(machine_get_internal_name(), "6via90ap")) dev->regs.gpi_val |= 0x00000004; + /* + TriGem Delhi-III second GPI word: + - Bit 7 = Save CMOS (must be set); + - Bit 6 = Password jumper (must be set); + - Bit 5 = Enable Setup (must be set). + */ + else if (!strcmp(machine_get_internal_name(), "delhi3")) + dev->regs.gpi_val |= 0x00008000; } if (acpi_power_on) { diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d62947848..fb979172c 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -782,6 +782,7 @@ extern int machine_at_ax59pro_init(const machine_t *); extern int machine_at_mvp3_init(const machine_t *); extern int machine_at_ficva503a_init(const machine_t *); extern int machine_at_5emapro_init(const machine_t *); +extern int machine_at_delhi3_init(const machine_t *); extern int machine_at_5sg100_init(const machine_t *); diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 0360b5650..b7ffc03b3 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -343,6 +343,38 @@ machine_at_5emapro_init(const machine_t *model) return ret; } +int +machine_at_delhi3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/delhi3/DELHI3.ROM", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + + device_add(&via_mvp3_device); + device_add(&via_vt82c596a_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 256); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)) + device_add(machine_get_snd_device(machine)); + + return ret; +} + int machine_at_5sg100_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 23409d6db..bf4c7fa1b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14013,6 +14013,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has the VIA VT82C596A southbridge with on-chip KBC identical to the VIA + VT82C42N. */ + { + .name = "[VIA MVP3] TriGem Delhi-III", + .internal_name = "delhi3", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_MVP3, + .init = machine_at_delhi3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 124242424, + .min_voltage = 2000, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_SOUND | MACHINE_USB, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .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 = &cs4235_device, + .net_device = NULL + }, /* SiS 5591 */ /* Has the SiS 5591 chipset with on-chip KBC. */ From 0d8779da649c42a8ee899f202764e7c784d277a8 Mon Sep 17 00:00:00 2001 From: borisvolk117 <141923951+borisvolk117@users.noreply.github.com> Date: Tue, 6 May 2025 13:52:29 +0800 Subject: [PATCH 0851/1190] Delhi III bus change and update internal device note for Delhi III and NEC Mate NXMA30D --- 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 bf4c7fa1b..ccffc4a03 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14035,7 +14035,7 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 5.5 }, - .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Has internal video: ATI 3D Rage IIc AGP (Rage 2) */ .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_SOUND | MACHINE_USB, .ram = { .min = 8192, @@ -14860,7 +14860,7 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Has internal video: SGS Thompson Riva 128 AGP and sound: OAK Audia 3D (OTI-610) */ .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, From 5b959937e3211923eddac3ae5c9e7492daf2d7b0 Mon Sep 17 00:00:00 2001 From: borisvolk117 <141923951+borisvolk117@users.noreply.github.com> Date: Tue, 6 May 2025 14:32:14 +0800 Subject: [PATCH 0852/1190] 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 ccffc4a03..e0a2cfc10 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14860,7 +14860,7 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Has internal video: SGS Thompson Riva 128 AGP and sound: OAK Audia 3D (OTI-610) */ + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Has internal video: SGS Thompson Riva 128 AGP, network: NEC PK-UG-X006 (Intel 82558B chip) sound: OAK Audia 3D (OTI-610) */ .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, From 17211e4564b92b97a1d9cca28e7c21a8b0876d1a Mon Sep 17 00:00:00 2001 From: borisvolk117 <141923951+borisvolk117@users.noreply.github.com> Date: Tue, 6 May 2025 14:32:48 +0800 Subject: [PATCH 0853/1190] 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 e0a2cfc10..032fd6483 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14860,7 +14860,7 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Has internal video: SGS Thompson Riva 128 AGP, network: NEC PK-UG-X006 (Intel 82558B chip) sound: OAK Audia 3D (OTI-610) */ + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Has internal video: SGS Thompson Riva 128 AGP, network: NEC PK-UG-X006 (Intel 82558B chip) and sound: OAK Audia 3D (OTI-610) */ .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, From c84266d41adcf90ea11d05987d4a52acaae987f8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 08:43:39 +0200 Subject: [PATCH 0854/1190] VTech Laser TX: Fix RAM step, fixes #5554. --- 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 bf4c7fa1b..a636ca3ba 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1734,7 +1734,7 @@ const machine_t machines[] = { .ram = { .min = 256, .max = 640, - .step = 256 + .step = 64 }, .nvrmask = 0, .kbc_device = &keyboard_xt_device, From 3d233fc4b44b9881df2b03f9289862a57707d3f3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 6 May 2025 13:06:44 +0600 Subject: [PATCH 0855/1190] Use icons for the indicators --- src/qt/icons/caps_lock_off.ico | Bin 0 -> 9622 bytes src/qt/icons/caps_lock_on.ico | Bin 0 -> 9622 bytes src/qt/icons/kana_lock_off.ico | Bin 0 -> 9622 bytes src/qt/icons/kana_lock_on.ico | Bin 0 -> 9622 bytes src/qt/icons/num_lock_off.ico | Bin 0 -> 9622 bytes src/qt/icons/num_lock_on.ico | Bin 0 -> 9622 bytes src/qt/icons/scroll_lock_off.ico | Bin 0 -> 9622 bytes src/qt/icons/scroll_lock_on.ico | Bin 0 -> 9622 bytes src/qt/qt_mainwindow.cpp | 37 ++++++++++++++++++++----------- src/qt/qt_mainwindow.hpp | 3 +++ src/qt_resources.qrc | 8 +++++++ 11 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 src/qt/icons/caps_lock_off.ico create mode 100644 src/qt/icons/caps_lock_on.ico create mode 100644 src/qt/icons/kana_lock_off.ico create mode 100644 src/qt/icons/kana_lock_on.ico create mode 100644 src/qt/icons/num_lock_off.ico create mode 100644 src/qt/icons/num_lock_on.ico create mode 100644 src/qt/icons/scroll_lock_off.ico create mode 100644 src/qt/icons/scroll_lock_on.ico diff --git a/src/qt/icons/caps_lock_off.ico b/src/qt/icons/caps_lock_off.ico new file mode 100644 index 0000000000000000000000000000000000000000..6895c735cf1d2d0cdc497f20bd810e9d2ef22892 GIT binary patch literal 9622 zcmds*J#O4U425R_BS4TME?l_sZkaMCSZ|eM*joiTg{?AWj*%*LPL(Tc_-XMBnwXJB z(#UoqfTlDve2?UCe!MAd(nY$wOs03~+eJ!WQc71>=kMR|Qu<|W*VpIo@9$Ik`XQy= z?)?4J?Ecu;PiAAUhH!2-l@4ZCcuv+nN7BvB&FS{`c9I+phZ6!P_FdOK*{iQcdwVeM z@9%rLySsaO_ie}H@q~bl&(WSf#?vl4Y1+o@8H*o0jQ658#+3N!dwhIkX!em`L-xcj z495F+@Q323f2qAN9v&W^Vvyg;?~wmX?D1U!4zY`yZ%K(?wozk8o9wBbT>UWjHL}zm z4)I%j{TgH)ZMWMhVJw1ex1m<&3AXGrw%zpm4f_?(58I;(&$BgQW9EK8+jp4HC4wJI z_Myn_@tCXqe%}jorrJ{tc*klbEVgBSh4PeeT4@3H(5Z}g=P-u;=1CrtT+*1N}IT#bJb4-7>4 zq+j!1izm$790+TQf35IT8`9vCJLOG0Xk;v2;pDWi=;Iw>&8r6C)c(Snm?PlH#};__ z03Ol`Pnh7DOg@+5`St9aN?XJH*hD(R;@q+;boy+fbL(h#>B7_J$og9ArstUIO&Why zcbaSUwa^})xvxFvjh@!`<=@@q|PCC%8{b4z;`+_EX*s^5<#jxqm`kE7iCHt##{wf^VuX+v7!=QxJ289&AU96tHZ<(;u}@WtV4DbA^| z-vYjBBx-yk_wrqFX`Esh%fH4C>4?o(;kUjwY0XKmagP$VG&w@ZrOsdVwbH^jj>Y$^ z;d|Gnxc3s@66w;WzlZG%b^`7R>^xQjstBzD#xp8Z?d4B5G z-}B^8OC95g{A>GA!;cTzvs!80CzVV2k&8d_Yrmc9i?^G@uX_X{{3Rb$e>L1|@R$6eJ;uJ2zr6yI5nnLVBlUVLEl!JZq9xkV|=Jr=vy0L zi25tsOZlx0YxRj?xs&``^9TB!NGpOovVuO_&u8S4Ex>@(Gs1CJcf&nm+dcGsbI23u zpkSYo?MC+->{lp1WRJRG;aXbT4yH8@oVYr*e}=; z7uuX-pS2No#kS#nE}o4&Y(k-JYw)a%G1gi<+E@xt?T~ZL`iVa64-wRNa?w)Dn>I)o z=SR<9lk*|_i=Go*z$Es<7MNle#21T)HJl^lw0J-TCZx_3>IKtEH^_m`ed-(cev<$L z1?QH0Lc5P5Jhx8rEq%wrxh>TWuE^Z1J=d7WZ1*_lh|RX-xhGjXs^pO14C@HF-in;Z zV|C0(J9=;50Z-~x{C3di-nN9pj@<*_o_|a6;fd87JR9Fx+wmp`f28Z@E4enXo*Bm+ zeCq=+rV6oh?bq?)cT`nXdTuwhSSW%s9D=e1-}+#2rsgI$KGui5@M9kkpExcUqqc+$ zQd{JrrIt5skTA}V9B&aFX+Qw_-fz8_tC|MmGP(kT$_v!zAd^S zoaYTKI3#Z%zF2&m0b7K2S$wd715$4k;sn$8Zjfu8dysFgLs0=H3ckaRBCjI+4r}no z<^NllJGW|wNXXptI}YvMwelAC}>}4s&mT^gb>_fo@x!a}E=1KlG z*su$`yPQ!;esEI^|LMz#b7guL#>dZbuNb0z)qirMHFe3^XvgzDrFTpI)HlN#e)yBZ zqMxZYYfJLSG05eH z{+9Twe)!D;Zuo}ZIsDy&-$4+T*!L3raSSZSRL((%b*ultv3YP0e%KKE8b8zDxGmv- zDh6}&PCH8R1JC+=E$7Isc5hh!7DutnTDS*4Y_Kt~xft8Z=aTV{V{i|C+OULM#}=G_ z#x$ob9seBeMgDg(sukgP@D43wpmQb{EtPPBoBXh0M}ZB(3-RT~{OX(KhZV2^QtvF} W39jF}!QR<9_t41S1h*7$g8MJPaVKN| literal 0 HcmV?d00001 diff --git a/src/qt/icons/kana_lock_off.ico b/src/qt/icons/kana_lock_off.ico new file mode 100644 index 0000000000000000000000000000000000000000..27c9b88c25d39dde2f48fe5fbf5283fec9dd1541 GIT binary patch literal 9622 zcmdUzziu2i5Qizi2w^{`yNPf7iYbA71T0-$es?yEh-cmzS554V-KHiBKWB(=k=(* zt@^ujhxObd#Ixlb%G?o;wYs~zJB#b?{?kT_VV^cS0>pc#NY?;Kq7sqZvakBl~5le&FD@E^~Mhi)ZE&5BX`U@h!y@-?*YpAMd<- z22Rfx>a<3{GsZpehygrgFFY~9tFrjJl)qo!eW%Jz#r$m-IaVybTlETEey`$p>#5$Q zJMCPf>f2lI`WsfpKp=UVIALq~kpK7Z%ngh%eIjUo2ihtBwL@NPwk?{MtrIlhyl z=Y|-LCkFbkTfXRL47r%YT>RuiV;r$Y4$dlDf-rN2q5O_Dk-=wja(pe8w2-dE($7ct-IV zM_m>8Vx6_4pE=|`vj1b9PON(DQHs7^^dDwZ>hlFY>d0TlYNU+C%3&GXJGx z7~v-d&#b+4{031+<7nmIWnk3%_%T6@j0=UL1~dUL5BhTAIJ#c<(#p*oq;K z%dxKI2WJjD`i*lhe%JK*`T5(et+f`t7+ixb`4htw|5S{7@PjcD!&Ho0@*m-!8iQ{u z{}jIOL$5}A@q-ih+1x(VzlPsEm33ZY{NOt-`|%-5>Tf+g&$9MK%>CNYzlNVVvCiTx z)x`6E5XNt{L$E+ zU687`ZCU+ZtJV7KICtaj-2J_SKDcjp&V6>yJv@Z>-*24zg|^4X@c#X+b6?*%cQ}Oi zpRoIbz8_$NM<9fDDE9=r9m@&WCDOT4xsyk&7uM=ji6>yd-ZhYgl|0ecVDDjh99U~C z!c5+?_DyGBSM^DSJihXJHC~SO8Gm9=q}m4z>&N%HdtYKt4Dp%|KKNkI3;3gd=J)V< zjz1m$dEoJ3DL*lULmRzYY;yBAh@WPIcIH3gp$g=F{MY6W?OO>EywzOUEA)nw{ zEX1Jr8Bsskt<;>B_V#qDZ_0!=EZk?X-PnG^{fgxW_NXfs&E=)Ka}}{I*@u`%sKVZr%;${4J3!he#07Ut#uNQm`P37vD($f9D+0FIPy7q=WHzy zYk)@#*<1g}mF}4({+)gD-5zTk$)0-&Ub_Dh&nJ8EVm!q>YQ-zYiLXWRQ{2pO@Rjsw9rkt5YuA8*s-K|T*DSy^7R(w&b4$G3Cz9janyU)t$)wZ+Fq(TJ`A1` z3fImt$Wn|o{j&VrhoTR7+NH|pQT`_SunW73Cm_z`T>Qx`8RHLgHukk^AL%zaesNQ0 zs?JF6El8S7kI**NZw)`ur?7|LbAGPnCx`BoIs7>vw&0(O!IY0%@K53M8|#>lTk((K zi=R3-Ph0Vi;a`(q|2vK5A@27oTCe}?__d!6bZ>lvZydAAn(?Q(CcIMpFY_~}83PmK z6!VU2tE#GV7&tz*+3(V^k3B~_t&3~spEy&!C4ZV1n%|Tw_xwNcb9~B+ml%I8zH@C` z#($10_kEVXg;fL5J$MH#A8gL>$4UiGa*Lln>?rgByxspFSLU~|rTh#6eW3WAMLZVx Um;b{}ymjuj#?J)T6mpXLFKF~OvH$=8 literal 0 HcmV?d00001 diff --git a/src/qt/icons/num_lock_off.ico b/src/qt/icons/num_lock_off.ico new file mode 100644 index 0000000000000000000000000000000000000000..5b14da1d4c3490e38cbda89bc89a53fc493b890f GIT binary patch literal 9622 zcmeI0J&qGW5QW>)3JDRg!3Ga*Ae0r_Jo8SgNT?@aRpP~SkHRfn#S|f zGZuo8O4U8n_3Bl1^^cv>D&3^p+Z1|}zTBkrDW!CGck2IqlhTiPcYlBCe|?+M=XWV> zHmCmgu=^EbKZH#*1L5>ORN97J;W@_pF_Io09*$2>PlIH;-5wEqV&62)*lp-JU>4lC4AfMcCCO7=iFZ3(ZXVk+w!esFB@q%@d!ij$JjfkKK8_YI2_LY``9x^ z0%wG041f6^Yfr9*=1+4i4F)`vcj;38WS48~cqe;mr>lP8+efC_<3s*qZrU}-I$E#S zy@as{w#|z99Vghb&%}1q?llX*K0da> zoaJM^ue!*`<#=GK7F~PY>b=&pV|L+b99p($#;WgQF5$_>HN1U4a9>mL91EXg@U&+U z^He=b8Jv#7`Km#Zy>(Q+o`a zu)**)eb&6zHgl)_g_y<&c;Z+C4-ViVweW-qUdZ5cDL=nnol|KYnD47d6Ih&EafMDF zLv(KK;x1iy+8o8V+PdmFrh1cxuj)>7t#387<1_bu&h_!9F|M6gj*kzm*IaA;`I`1I z+E4K%AARs;=UCX$_it(s#dloV+DGvLX8wIDJ~=Gy(fFEzPwt(6&V4FA_H*+8oAFim zHS(jnQ%zHg2tI1y=XK$jbJdUgs9pc$#cRJdKKYUlk0Z|`{Y&dtI3*1RbAa|S^pP6) zj;prtYu}s5m&+XYD95Kwju6(2&fk2@)V}b;$K-p~pYL6(+IOBaUXxbsJ!}&(Y(sPp zYxv```#Iaj=Ox>--qUm+DQRL=9jUfTW9NA9{;Aupd!BgJ(0L5G|G7Ez@ec>>S+%sz zTjfwZy5b+=Uwf?UF3z?53n%wM9EjeR#?_7=fBXHuz4!XrjDK-)y@dagZ+O)7uQ~6E z-(&W6P5khs2{A*v;ehY`C>p%B*jrE^%&;j6Q zkgt2SYpj3GzsJ3#e_|D&MS literal 0 HcmV?d00001 diff --git a/src/qt/icons/num_lock_on.ico b/src/qt/icons/num_lock_on.ico new file mode 100644 index 0000000000000000000000000000000000000000..0dd08d7ae4594ca8f076a41145181800c344c140 GIT binary patch literal 9622 zcmeHMv2xom4293R-u1d<$dIibJN6Hnso&8lm#+{tcI;<#>f9;P7xfp^_eddv6-t#v zQL?Wg4+f2|6Gz6=-57PHStBcaVG@k>zj|u5ioo+x=W>e_4dJFO{bkRmW2Qsg7<(ptHaKsqsVk8pIf2 z99iN!`(B@eZ$td?lR8N5AEfg-$)pkYram@Jd6-9(VPl>_y7Bpj`HJlaa@2-R&+<~< znF`;|$wQ1I?UWnJOFCyRr%o703XQSx+)@KRqboKPo$IS6=%Y-pkLsh&fga0;oO>zy zV)^nS>w)p_cC*MO3_FJMYq)d%5TFaNFl#fY79c;X}P(sURkltJ0 zP)qOFbZ^(<-BPeGOYb#}W92#SIn}Lv&3g|KdDayJ&go*6aa@6TcBXd9NBXG#Dkkyz z-OwG$nb)9y=nlOW`>);qS?mwz#YcQuzWz?DQM@!hZ9Otn9i+wA=Uu*G$igFTjL zD`}&~b5hF@HP>NPqE0r}VJFZ7Nb9hYKU`jJ)7aUHcb>q$YaK_PyRZFwhMw)Ioa@8l zyIAKrXwT+U9Vzpo_{>AC4H#wVYV#m|)!L8+U0!O;C_b^3mf(l|9F-hhzhaZm>{^#H z@A$YHkblDu9$0(-_x8Wm#e41l8-D!%p#C||b^iWK|C@Zf_4@VumY%nwC^+xVt?)ep48+SMQD%0GRaq34UoXAN9|v<}X|)dxOK@Znnl wOkyiOZOBNp0l3}wkB#yD+AKbuKpRLdGbxUD{Qe)zo3+TX#Lom<5;2MW7pM8O;{X5v literal 0 HcmV?d00001 diff --git a/src/qt/icons/scroll_lock_off.ico b/src/qt/icons/scroll_lock_off.ico new file mode 100644 index 0000000000000000000000000000000000000000..85cb09ec6a5f5c4f6ad460227182397270bef609 GIT binary patch literal 9622 zcmds*F>V_%5Jf4#2oR)*3m2{=l__%qNmY(vsS0umd&`tLMyk{~Rj#1STj3icg52dU zxpI&N#LI@8Jm-g>>A^ftw$Hz(HxT;Ei)z!v5ho@xc-z)@T8w5Q-Ooj;9_HTJ$wc=0` z$CPi<_}lVa6Rxz!XYF(6965ntr}vx|Haf=>VRE{>`A_{AKFBZoWJ|J3}`mzo-ga^{WSN%Xi6{_y{G9s&uM&A9x1nSW0&an{N(M}Jx@N))o~0l|I$8`@Z*DO zVk=EeM>KEpBNhJ?e%10ZKbPXie+2&Ax#fLp6+dyqtA}^`#(b#d*L*)eKa2WRm-tZ2 z&s@fLl2-@pWo#{K`G>gW$B+-T{KU`xVE+9Yz)5>-@6_^Z{n0T$eLmMy@3s73$_Kv| z%Doh)?`y#?yqI78L;8Q`zg7Kti~Q3WLas^to>!m7rShP5{e8}fJJ$FCcWNza`N19X zVTc>sT7K<)Uwafk+COEtVhW98RU{6pM) z6Tkl-nL8-!rvE=UJC_#ye=&CdUD6Lf2e*!2aVZbpiXT7l0e+L_zca+YJH%~r4uQMl K=YcnR;QkAzOeNm{ literal 0 HcmV?d00001 diff --git a/src/qt/icons/scroll_lock_on.ico b/src/qt/icons/scroll_lock_on.ico new file mode 100644 index 0000000000000000000000000000000000000000..33476406a5a559008e9628c0772333e9fd7b08e3 GIT binary patch literal 9622 zcmeHLJ967F5M7NtnaQMa;lf>1rpyiED(6U*$tg&dDRYcesZ)tOQLeze2k=Q04T3*F zR>oP(azz^Z-U3)IV4Cgh&hGCG_F&)c%s!jh!-K#7{l@GUo;^PL`|oefzP>X%9Q^%H z`29iO5AeZHAo%An_5{C-(gJ&loz05V~#(gDT~s%ui@Y7pCW!?tc{;zAO>x}J)6I+`9uE( zT0@yfeH}jIJ=MP}Fr5&CT283?$#0`&f;9WKt#-?lJ`~m&lp9xXSg$BQP@}FWn#;BJ z94h8^NgZMysnKt&E~(E_OH2eu^}^gZcG|)&XyOLYC0;#&$Nqs9#Uo~*jlIw8yA)4Y zJ`2M&mYBiuj>I=sFW1CJpVx$!V?BiF)^LzdOY?>6;np#*AGqgT1}@1LVTNolKGyE0 z(;9Z6KFjAmp6bF}EADkH1( zFDR;2sqA?uSeLc?n(|mS$37=)*_8VpGV-E{1Cw*kRpxpPJzn+=-i_>s>Knx;N2JB- zo&46~3)>|>E^hpRSk~YZTYH`G`7Fe-247e{ zne+WpeuyJi{=57eIUk*3NPJEbu52*>d9K)SZW^Am$l>M?7bksu?g3l0hCj8xzmS9+ z)N-Q=#|57M!g}7=9%rsyQY9vZ=dc6x3955g#SfRaD_YxY+4D?b?RAc$&D~Oe&(OO) z*K&LqJk<-|ouk*e7+d-U`B{g$81O4gQ_Q3Mbr(Yxb~~Lxg8bx`F5&mvS-Q4T>SSF<67rxHT z3?eq~>Ytil{}=q{f1UIHV)>_stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); + num_icon = QIcon(":/settings/qt/icons/num_lock_on.ico"); + num_icon_off = QIcon(":/settings/qt/icons/num_lock_off.ico"); + scroll_icon = QIcon(":/settings/qt/icons/scroll_lock_on.ico"); + scroll_icon_off = QIcon(":/settings/qt/icons/scroll_lock_off.ico"); + caps_icon = QIcon(":/settings/qt/icons/caps_lock_on.ico"); + caps_icon_off = QIcon(":/settings/qt/icons/caps_lock_off.ico"); + /* TODO: Add Kana indicator here after the keyboard type work is done. */ + num_label = new QLabel; - num_label->setText(" NUM "); + num_label->setPixmap(num_icon_off.pixmap(QSize(16, 16))); statusBar()->addPermanentWidget(num_label); caps_label = new QLabel; - caps_label->setText(" CAPS "); + caps_label->setPixmap(caps_icon_off.pixmap(QSize(16, 16))); statusBar()->addPermanentWidget(caps_label); scroll_label = new QLabel; - scroll_label->setText(" SCRL "); + scroll_label->setPixmap(scroll_icon_off.pixmap(QSize(16, 16))); statusBar()->addPermanentWidget(scroll_label); QTimer* ledKeyboardTimer = new QTimer(this); @@ -205,10 +213,13 @@ MainWindow::MainWindow(QWidget *parent) connect(ledKeyboardTimer, &QTimer::timeout, this, [this] () { uint8_t caps, num, scroll; keyboard_get_states(&caps, &num, &scroll); - - num_label->setStyleSheet(num ? "QLabel { background: green; }" : ""); - caps_label->setStyleSheet(caps ? "QLabel { background: green; }" : ""); - scroll_label->setStyleSheet(scroll ? "QLabel { background: green; }" : ""); + + if (num_label->isVisible()) + num_label->setPixmap(num ? this->num_icon.pixmap(QSize(16, 16)) : this->num_icon_off.pixmap(QSize(16, 16))); + if (caps_label->isVisible()) + caps_label->setPixmap(caps ? this->caps_icon.pixmap(QSize(16, 16)) : this->caps_icon_off.pixmap(QSize(16, 16))); + if (scroll_label->isVisible()) + scroll_label->setPixmap(scroll ? this->scroll_icon.pixmap(QSize(16, 16)) : this->scroll_icon_off.pixmap(QSize(16, 16))); }); ledKeyboardTimer->start(); @@ -239,9 +250,9 @@ MainWindow::MainWindow(QWidget *parent) connect(this, &MainWindow::hardResetCompleted, this, [this]() { ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); - num_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); - scroll_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); - caps_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); + num_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + scroll_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + caps_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); while (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); #ifdef USE_WACOM @@ -1485,9 +1496,9 @@ MainWindow::refreshMediaMenu() ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled); - num_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); - scroll_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); - caps_label->setVisible(machine_has_bus(machine, MACHINE_AT) > 0); + num_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + scroll_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + caps_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); } void diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 2ba29c128..421b9ce15 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -191,6 +192,8 @@ private: friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. QLabel *caps_label, *scroll_label, *num_label; + QIcon caps_icon, scroll_icon, num_icon; + QIcon caps_icon_off, scroll_icon_off, num_icon_off; bool isShowMessage = false; }; diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index bc553ac61..a5963c152 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -34,6 +34,14 @@ qt/icons/86Box-green.ico qt/icons/86Box-red.ico qt/icons/86Box-yellow.ico + qt/icons/caps_lock_off.ico + qt/icons/caps_lock_on.ico + qt/icons/kana_lock_off.ico + qt/icons/kana_lock_on.ico + qt/icons/num_lock_off.ico + qt/icons/num_lock_on.ico + qt/icons/scroll_lock_off.ico + qt/icons/scroll_lock_on.ico qt/icons/acpi_shutdown.ico From 8508a048256944da709d68f83edc75fadffcf5e2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:06:30 +0200 Subject: [PATCH 0856/1190] CL-GD 54xx: Remove an excess logging line. --- src/video/vid_cl54xx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 4988b3797..43c4e22b2 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4141,8 +4141,6 @@ gd54xx_reset(void *priv) gd54xx_t *gd54xx = (gd54xx_t *) priv; svga_t *svga = &gd54xx->svga; - pclog("gd54xx_reset()\n"); - memset(svga->crtc, 0x00, sizeof(svga->crtc)); memset(svga->seqregs, 0x00, sizeof(svga->seqregs)); memset(svga->gdcreg, 0x00, sizeof(svga->gdcreg)); From 0c97a1f7f6060aa547cd3070b2ec17fd615b8e91 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:08:16 +0200 Subject: [PATCH 0857/1190] Acer V60N and V62X: Tell the DRB filler the slot limits to avoid unsupported DRAM row combinations, fixes black screen on PCI graphics cards on some RAM sizes. --- src/machine/m_at_slot1.c | 1 + src/machine/m_at_socket8.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index bd3a4833f..b2f05d33e 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -65,6 +65,7 @@ machine_at_acerv62x_init(const machine_t *model) device_add(&piix3_device); device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_APM)); device_add(&sst_flash_29ee020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 128); return ret; } diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 479c4b9fc..f604c4f01 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -190,6 +190,7 @@ machine_at_acerv60n_init(const machine_t *model) device_add(&piix3_device); device_add_params(&fdc37c93x_device, (void *) (FDC37C935 | FDC37C93X_NORMAL)); device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 128); return ret; } From 3b149759ae2cec3df911622783ebca002f86b1e1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:14:56 +0200 Subject: [PATCH 0858/1190] LG IBM x61: Remove some left-over commented out lines. --- src/machine/m_at_socket8.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index f604c4f01..006e0f419 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -217,9 +217,7 @@ machine_at_lgibmx61_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); - // device_add(&keyboard_ps2_ami_pci_device); device_add(&keyboard_ps2_ami_device); - // device_add(&w83787f_device); device_add(&w83877f_president_device); device_add(&sst_flash_29ee010_device); From ef3f57b338e58e2443e2dedf4fc06e85f4937955 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:26:26 +0200 Subject: [PATCH 0859/1190] S3 Trio32 On-Board VLB: Actually use the DEC Venturis 4xx video BIOS. --- src/video/vid_s3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index d6b91903a..595ec3a17 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -58,6 +58,7 @@ #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" #define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" #define ROM_PHOENIX_TRIO32 "roms/video/s3/86c732p.bin" +#define ROM_PHOENIX_TRIO32_ONBOARD_VLB "roms/machines/dvent/Venturis466_VIDEO.BIN" #define ROM_SPEA_MIRAGE_P64 "roms/video/s3/S3_764VL_SPEAMirageP64VL_ver5_03.BIN" #define ROM_NUMBER9_9FX "roms/video/s3/s3_764.bin" #define ROM_PHOENIX_TRIO64 "roms/video/s3/86c764x1.bin" @@ -9946,7 +9947,7 @@ s3_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); break; case S3_PHOENIX_TRIO32_ONBOARD: - bios_fn = NULL; + bios_fn = ROM_PHOENIX_TRIO32_ONBOARD_VLB; chip = S3_TRIO32; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); From 93025cc1156f7cb5c7d9121a15003e45aab28e13 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:29:30 +0200 Subject: [PATCH 0860/1190] SM(S)C FDC 37c6xx: Return 0xFF on out of bound register read, fixes segmentation fault on the DEC Venturis 4xx. --- src/sio/sio_fdc37c6xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 0f3460565..3afd92e4c 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -232,7 +232,7 @@ fdc37c6xx_read(uint16_t port, void *priv) uint8_t ret = 0xff; if (dev->tries == 2) { - if (port == 0x3f1) + if ((port == 0x3f1) && (dev->cur_reg <= dev->max_reg)) ret = dev->regs[dev->cur_reg]; } From 4a417da09bc5bdc80e463da3750a71261d560575 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:34:14 +0200 Subject: [PATCH 0861/1190] S3: Revert the video BIOS change, it was not necessary. --- src/video/vid_s3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 595ec3a17..d6b91903a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -58,7 +58,6 @@ #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" #define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" #define ROM_PHOENIX_TRIO32 "roms/video/s3/86c732p.bin" -#define ROM_PHOENIX_TRIO32_ONBOARD_VLB "roms/machines/dvent/Venturis466_VIDEO.BIN" #define ROM_SPEA_MIRAGE_P64 "roms/video/s3/S3_764VL_SPEAMirageP64VL_ver5_03.BIN" #define ROM_NUMBER9_9FX "roms/video/s3/s3_764.bin" #define ROM_PHOENIX_TRIO64 "roms/video/s3/86c764x1.bin" @@ -9947,7 +9946,7 @@ s3_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); break; case S3_PHOENIX_TRIO32_ONBOARD: - bios_fn = ROM_PHOENIX_TRIO32_ONBOARD_VLB; + bios_fn = NULL; chip = S3_TRIO32; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); From d27bd54bfae36b17a843189fed6ce9601e053e2d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:48:50 +0200 Subject: [PATCH 0862/1190] SiS 85c4xx: Gate two 471-specific changes in a 471 check, fixes the SiS 461 DECpc machine. --- src/chipset/sis_85c4xx.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 1c1e0614b..f715c5272 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -595,12 +595,14 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) switch (rel_reg) { case 0x00: - if (val & 0x01) { - kbc_at_set_fast_reset(0); - cpu_cpurst_on_sr = 1; - } else { - kbc_at_set_fast_reset(1); - cpu_cpurst_on_sr = 0; + if (dev->is_471) { + if (val & 0x01) { + kbc_at_set_fast_reset(0); + cpu_cpurst_on_sr = 1; + } else { + kbc_at_set_fast_reset(1); + cpu_cpurst_on_sr = 0; + } } break; @@ -614,7 +616,7 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) case 0x08: if (valxor) sis_85c4xx_recalcmapping(dev); - if (rel_reg == 0x08) + if ((rel_reg == 0x08) && dev->is_471) flushmmucache(); break; From bb7454120a71295a49d5b6298f35261946444441 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 6 May 2025 19:58:43 +0200 Subject: [PATCH 0863/1190] TriGem Delhi-III: Rename to eMachines eTower 3xxc. --- 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 6223f1eb7..47320e6fe 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14016,7 +14016,7 @@ const machine_t machines[] = { /* Has the VIA VT82C596A southbridge with on-chip KBC identical to the VIA VT82C42N. */ { - .name = "[VIA MVP3] TriGem Delhi-III", + .name = "[VIA MVP3] eMachines eTower 3xxc", .internal_name = "delhi3", .type = MACHINE_TYPE_SOCKETS7, .chipset = MACHINE_CHIPSET_VIA_APOLLO_MVP3, From 1b1d6bcf458f8629937ac065abe0a0b8f107be4d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 6 May 2025 20:17:23 +0200 Subject: [PATCH 0864/1190] Some cleanup to the recent fixes on the S3 code (May 6th, 2025) See above. --- src/video/vid_s3.c | 114 ++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index d6b91903a..6897aed60 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -288,9 +288,11 @@ typedef struct s3_t { int color_16bit_check; int color_16bit_check_pixtrans; int16_t minus; + int16_t minus_src_24bpp; int rd_mask_16bit_check; int start; int mix_dat_upper; + int overflow; /*For non-threaded FIFO*/ int setup_fifo_slot; @@ -661,13 +663,15 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) s3->accel_start(16, 1, val | (val << 16), 0, s3); } else { - if ((s3->accel.cmd == 0x53f1) || (s3->accel.cmd == 0x53b1)) { - if (s3->accel.cur_x & 0x400) + if (s3->accel.rd_mask_16bit_check) { + if ((s3->accel.cmd == 0x53f1) || (s3->accel.cmd == 0x53b1)) { + if (s3->accel.cur_x & 0x400) + val = (val >> 8) | (val << 8); + + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + val = (val >> 8) | (val << 8); - - s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - - val = (val >> 8) | (val << 8); + } } s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } @@ -803,6 +807,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x82e9: s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x0f) << 8); s3->accel.poly_cy = s3->accel.cur_y; + s3_log("[%04X:%08X] OUT PORTB=%04x, valy=%d.\n", CS, cpu_state.pc, port - 1, s3->accel.cur_y); break; case 0x814a: case 0x82ea: @@ -828,7 +833,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.cur_x_overflow = (s3->accel.cur_x_overflow & 0xff) | (val << 8); s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; s3->accel.poly_x = s3->accel.poly_cx >> 20; - s3_log("[%04X:%08X] OUT PORTB=%04x, val=%04x.\n", CS, cpu_state.pc, port - 1, s3->accel.cur_x); + s3_log("[%04X:%08X] OUT PORTB=%04x, valx=%d, valxover=%d.\n", CS, cpu_state.pc, port - 1, s3->accel.cur_x, s3->accel.cur_x_overflow); break; case 0x854a: case 0x86ea: @@ -921,6 +926,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x9459: case 0x96e9: s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); + s3_log("[%04X:%08X] OUT PORTB=%04x, valmajx=%d.\n", CS, cpu_state.pc, port - 1, s3->accel.maj_axis_pcnt); break; case 0x954a: case 0x96ea: @@ -2965,7 +2971,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) break; case 0x40: - s3->enable_8514 = (val & 0x01); + s3->enable_8514 = val & 0x01; break; case 0x50: @@ -5798,18 +5804,20 @@ s3_accel_in_w(uint16_t port, void *priv) s3->accel_start(8, 1, temp | (temp << 16), 0, s3); } else { if ((s3->bpp == 0) && s3->color_16bit) { - if (s3->accel.cur_x & 0x400) - temp = ((temp >> 8) | (temp << 8)) & 0xffff; - + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) + temp = (temp >> 8) | (temp << 8); + } s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); } } else { if ((s3->bpp == 0) && s3->color_16bit) { - if (s3->accel.cur_x & 0x400) - temp = ((temp >> 8) | (temp << 8)) & 0xffff; - + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.cur_x & 0x400) + temp = (temp >> 8) | (temp << 8); + } s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); @@ -8021,18 +8029,30 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi case 1: /*Draw line*/ if (!cpu_input) { + s3->accel.rd_mask_16bit_check = 0; s3->accel.minus = 0; s3->accel.color_16bit_check_pixtrans = 0; s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - s3->accel.sy = s3->accel.maj_axis_pcnt; - if ((s3->bpp == 0) && s3->color_16bit) - s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); - else - s3->accel.rd_mask_16bit_check = 0; - if ((s3->bpp == 0) && s3->color_16bit && (s3->accel.cur_x & 0x400) && s3->accel.rd_mask_16bit_check) - s3->accel.minus = 0x400; + s3->accel.sy = s3->accel.maj_axis_pcnt; + if ((s3->bpp == 0) && s3->color_16bit) { + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + if (s3->accel.rd_mask_16bit_check) { + if ((s3->accel.cur_x_overflow & 0xc00) == 0xc00) + s3->accel.start = 1; + else { + if (s3->accel.start) { + s3->accel.start = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.start = 0; + if (s3->accel.cur_x_overflow & 0x400) + s3->accel.minus = 0x400; + } + } + } + } if (s3_cpu_src(s3)) return; /*Wait for data from CPU*/ @@ -8041,7 +8061,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (s3->accel.cmd & 0x08) { /*Radial*/ if ((s3->bpp == 0) && s3->color_16bit) { if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.cur_x & 0x400) { + if (s3->accel.minus) { wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); frgd_color = (s3->accel.frgd_color_actual[1] << 8); bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); @@ -8108,11 +8128,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi cpu_dat >>= 16; if (!s3->accel.sy) { - if ((s3->bpp == 0) && s3->color_16bit) { - if (!(s3->accel.cur_x & 0x400)) - s3->accel.color_16bit_check = 1; - else + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) s3->accel.color_16bit_check = 0; + else + s3->accel.color_16bit_check = 1; } break; } @@ -8162,7 +8182,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.temp_cnt = 16; if ((s3->bpp == 0) && s3->color_16bit) { if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.cur_x & 0x400) { + if (s3->accel.minus) { wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); frgd_color = (s3->accel.frgd_color_actual[1] << 8); bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); @@ -8178,7 +8198,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } else { if ((s3->bpp == 0) && s3->color_16bit) { if (s3->accel.rd_mask_16bit_check) { - if (s3->accel.cur_x & 0x400) { + if (s3->accel.minus) { wrt_mask = (s3->accel.wrt_mask_actual[1] << 8); frgd_color = (s3->accel.frgd_color_actual[1] << 8); bkgd_color = (s3->accel.bkgd_color_actual[1] << 8); @@ -8193,12 +8213,18 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - while (count-- && s3->accel.sy >= 0) { + if (!s3->accel.b2e8_pix) + s3_log("CMDFULL=%04x, FRGDMIX=%x, FRGDCOLR=%04x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, CLIPT=%d, CLIPB=%d.\n", s3->accel.cmd, frgd_mix, s3->accel.frgd_color, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, clip_t, clip_b); + + while (count-- && (s3->accel.sy >= 0)) { if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) { mix_dat >>= 16; s3->accel.temp_cnt = 16; } + if (s3->accel.minus) + s3_log("Total pixel cx=%d, cy=%d.\n", s3->accel.cx - s3->accel.minus, s3->accel.cy); + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: @@ -8260,11 +8286,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi cpu_dat >>= 16; if (!s3->accel.sy) { - if ((s3->bpp == 0) && s3->color_16bit) { - if (!(s3->accel.cur_x & 0x400)) - s3->accel.color_16bit_check = 1; - else + if (s3->accel.rd_mask_16bit_check) { + if (s3->accel.minus) s3->accel.color_16bit_check = 0; + else + s3->accel.color_16bit_check = 1; } break; } @@ -8358,7 +8384,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } else { if (s3->accel.cmd & 0x100) { - if (!(s3->accel.cmd & 0x200)) { + if (mix_mask == 0x80) { if (s3->accel.cur_x & 0x400) s3->accel.minus = 0x400; else @@ -8458,8 +8484,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if (s3->accel.mix_dat_upper) - s3_log("CMDFULL=%04x, FRGDMIX=%x, BKGDCOLR=%04x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, OVERFLOW=%d.\n", s3->accel.cmd, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_color, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, (s3->accel.cur_x_overflow & 0xc00) == 0xc00); + s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width); while (count-- && (s3->accel.sy >= 0)) { if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) { @@ -8716,16 +8741,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi case 6: /*BitBlt*/ if (!cpu_input) { /*!cpu_input is trigger to start operation*/ s3->accel.minus = 0; + s3->accel.minus_src_24bpp = 0; s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; s3->accel.dx = s3->accel.destx_distp & 0xfff; s3->accel.dy = s3->accel.desty_axstp & 0xfff; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if ((s3->bpp == 0) && s3->color_16bit) { s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); if (s3->accel.rd_mask_16bit_check) { - if (!(s3->accel.cmd & 0x40) && !(clip_r & 0x400)) + if (!(clip_r & 0x400)) s3->accel.start = 1; else { if (s3->accel.start) { @@ -8745,10 +8774,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } else { s3_log("BitBLT + 0 FULLCMD=%04x: frgdcolor=%04x, s=%d,%d, d=%d,%d, frmix=%x, bkmix=%x, pixcntl=%02x.\n", s3->accel.cmd, frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.dx, s3->accel.dy, frgd_mix, bkgd_mix, s3->accel.multifunc[0xa] & 0xc0); } - - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; s3_log("BitBLT: D(%d,%d).\n", s3->accel.dx, s3->accel.dy); @@ -8773,10 +8798,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if (!vram_mask && (frgd_mix == 3)) - s3_log("CMDFULL=%04x, FRGDMIX=%x, BKGDMIX=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00); + s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width); if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { + s3_log("Special BitBLT.\n"); + while (1) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { READ(s3->accel.src + s3->accel.cx - s3->accel.minus, src_dat); @@ -8820,6 +8846,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } } else { + s3_log("Normal blit.\n"); while (count-- && (s3->accel.sy >= 0)) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { @@ -8912,6 +8939,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy--; s3->accel.dy--; } + s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; From 477956d74328c7ff16a2aafe41e8ad825806bc8b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 01:08:02 +0200 Subject: [PATCH 0865/1190] QT: Rework light/dark mode switches, fixes #5560. --- src/qt/qt_winrawinputfilter.cpp | 54 ++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 306da575f..e94101a77 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -64,6 +64,8 @@ extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); #include "qt_rendererstack.hpp" #include "ui_qt_mainwindow.h" +static bool NewDarkMode = FALSE; + bool windows_is_light_theme() { // based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application @@ -220,6 +222,14 @@ WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *mess if ((((void *) msg->lParam) != nullptr) && (wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0)) { + bool OldDarkMode = NewDarkMode; +#if 0 + if (do_auto_pause && !dopause) { + auto_paused = 1; + plat_pause(1); + } +#endif + if (!windows_is_light_theme()) { QFile f(":qdarkstyle/dark/darkstyle.qss"); @@ -228,45 +238,39 @@ WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *mess else { f.open(QFile::ReadOnly | QFile::Text); QTextStream ts(&f); - qApp->setStyleSheet(ts.readAll()); + qApp->setStyleSheet(ts.readAll()); } - QTimer::singleShot(1000, [this] () { - BOOL DarkMode = TRUE; - auto vid_stack = (RendererStack::Renderer) vid_api; - DwmSetWindowAttribute((HWND) window->winId(), - DWMWA_USE_IMMERSIVE_DARK_MODE, - (LPCVOID) &DarkMode, - sizeof(DarkMode)); - window->ui->stackedWidget->switchRenderer(vid_stack); - for (int i = 1; i < MONITORS_NUM; i++) { - if ((window->renderers[i] != nullptr) && - !window->renderers[i]->isHidden()) - window->renderers[i]->switchRenderer(vid_stack); - } - }); + NewDarkMode = TRUE; } else { qApp->setStyleSheet(""); - QTimer::singleShot(1000, [this] () { - BOOL DarkMode = FALSE; - DwmSetWindowAttribute((HWND) window->winId(), - DWMWA_USE_IMMERSIVE_DARK_MODE, - (LPCVOID) &DarkMode, - sizeof(DarkMode)); - }); + NewDarkMode = FALSE; } - QTimer::singleShot(1000, [this] () { + if (NewDarkMode != OldDarkMode) QTimer::singleShot(1000, [this] () { + BOOL DarkMode = NewDarkMode; + DwmSetWindowAttribute((HWND) window->winId(), + DWMWA_USE_IMMERSIVE_DARK_MODE, + (LPCVOID) &DarkMode, + sizeof(DarkMode)); + window->resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); + for (int i = 1; i < MONITORS_NUM; i++) { auto mon = &(monitors[i]); if ((window->renderers[i] != nullptr) && !window->renderers[i]->isHidden()) window->resizeContentsMonitor(mon->mon_scrnsz_x, - mon->mon_scrnsz_y, - i); + mon->mon_scrnsz_y, i); } + +#if 0 + if (auto_paused) { + plat_pause(0); + auto_paused = 0; + } +#endif }); } break; From a48f9bc7ba2410376a6bc4afc16675e14ce98bc2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 01:54:34 +0200 Subject: [PATCH 0866/1190] Implement the Kana lock LED for AX machines. --- src/device/keyboard.c | 11 ++++++++--- src/device/keyboard_at.c | 10 +++++----- src/device/keyboard_xt.c | 2 +- src/include/86box/keyboard.h | 4 ++-- src/include/86box/machine.h | 2 +- src/machine/machine_table.c | 2 +- src/qt/qt_mainwindow.cpp | 23 +++++++++++++++++++---- src/qt/qt_mainwindow.hpp | 6 +++--- 8 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 30b6f53a8..800e7fb8e 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -67,6 +67,7 @@ static scancode *scan_table; /* scancode table for keyboard */ static volatile uint8_t caps_lock = 0; static volatile uint8_t num_lock = 0; static volatile uint8_t scroll_lock = 0; +static volatile uint8_t kana_lock = 0; static uint8_t shift = 0; static int key5576mode = 0; @@ -108,6 +109,7 @@ keyboard_init(void) num_lock = 0; caps_lock = 0; scroll_lock = 0; + kana_lock = 0; shift = 0; memset(recv_key, 0x00, sizeof(recv_key)); @@ -370,11 +372,12 @@ keyboard_do_break(uint16_t scan) Caps Lock, Num Lock, and Scroll Lock when receving the "Set keyboard LEDs" command. */ void -keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl) +keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl, uint8_t kl) { caps_lock = cl; num_lock = nl; scroll_lock = sl; + kana_lock = kl; } uint8_t @@ -384,7 +387,7 @@ keyboard_get_shift(void) } void -keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl) +keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl, uint8_t *kl) { if (cl) *cl = caps_lock; @@ -392,6 +395,8 @@ keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl) *nl = num_lock; if (sl) *sl = scroll_lock; + if (kl) + *kl = kana_lock; } /* Called by the UI to update the states of Caps Lock, Num Lock, and Scroll Lock. */ @@ -435,7 +440,7 @@ keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl) } } - keyboard_update_states(cl, nl, sl); + keyboard_update_states(cl, nl, sl, kana_lock); } int diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 605f51e90..fbf167e3f 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -3276,7 +3276,7 @@ add_data_kbd(uint16_t val) dev->ignore = 1; - keyboard_get_states(NULL, &num_lock, NULL); + keyboard_get_states(NULL, &num_lock, NULL, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; switch (val) { @@ -3476,7 +3476,7 @@ keyboard_at_bat(void *priv) keyboard_scan = 1; - keyboard_update_states(0, 0, 0); + keyboard_update_states(0, 0, 0, 0); kbc_at_dev_queue_add(dev, 0xaa, 0); } else { bat_counter--; @@ -3511,7 +3511,7 @@ keyboard_at_write(void *priv) switch (dev->command) { case 0xed: /* Set/reset LEDs */ kbc_at_dev_queue_add(dev, 0xfa, 0); - keyboard_update_states(!!(val & 0x4), !!(val & 0x2), val & 0x1); + keyboard_update_states(!!(val & 0x4), !!(val & 0x2), val & 0x1, !!(val & 0x8)); keyboard_at_log("%s: Set/reset LEDs [%02X]\n", dev->name, val); break; @@ -3769,7 +3769,7 @@ keyboard_at_init(const device_t *info) keyboard_send = add_data_kbd; SavedKbd = dev; - keyboard_update_states(0, 0, 0); + keyboard_update_states(0, 0, 0, 0); inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa; @@ -3788,7 +3788,7 @@ keyboard_at_close(void *priv) /* Disable the scancode maps. */ keyboard_set_table(NULL); - keyboard_update_states(0, 0, 0); + keyboard_update_states(0, 0, 0, 0); SavedKbd = NULL; diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index bafc80d88..7e419b39d 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -742,7 +742,7 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) if (!adddata) return; - keyboard_get_states(NULL, &num_lock, NULL); + keyboard_get_states(NULL, &num_lock, NULL, NULL); shift_states = keyboard_get_shift() & STATE_LSHIFT; if (is_amstrad) diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 024b16169..f62896106 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -271,9 +271,9 @@ extern void keyboard_process(void); extern uint16_t keyboard_convert(int ch); extern void keyboard_input(int down, uint16_t scan); extern void keyboard_all_up(void); -extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl); +extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl, uint8_t kl); extern uint8_t keyboard_get_shift(void); -extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl); +extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl, uint8_t *kl); extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); extern int keyboard_recv(uint16_t key); extern int keyboard_recv_ui(uint16_t key); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fb979172c..d8c213d53 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -101,7 +101,7 @@ #define MACHINE_GAMEPORT 0x00008000 /* sys has int game port */ #define MACHINE_SOUND 0x00010000 /* sys has int sound */ #define MACHINE_NIC 0x00020000 /* sys has int NIC */ -#define MACHINE_MODEM 0x00040000 /* sys has int modem */ +#define MACHINE_AX 0x00040000 /* sys adheres to Japanese AX standard */ /* Feature flags for advanced devices. */ #define MACHINE_APM 0x00080000 /* sys has APM */ #define MACHINE_ACPI 0x00100000 /* sys has ACPI */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 47320e6fe..7e0ae8d64 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4804,7 +4804,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_VIDEO_FIXED, + .flags = MACHINE_VIDEO_FIXED | MACHINE_AX, .ram = { .min = 1024, .max = 4096, diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 905a100f4..e966e043a 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -193,7 +193,8 @@ MainWindow::MainWindow(QWidget *parent) scroll_icon_off = QIcon(":/settings/qt/icons/scroll_lock_off.ico"); caps_icon = QIcon(":/settings/qt/icons/caps_lock_on.ico"); caps_icon_off = QIcon(":/settings/qt/icons/caps_lock_off.ico"); - /* TODO: Add Kana indicator here after the keyboard type work is done. */ + kana_icon = QIcon(":/settings/qt/icons/kana_lock_on.ico"); + kana_icon_off = QIcon(":/settings/qt/icons/kana_lock_off.ico"); num_label = new QLabel; num_label->setPixmap(num_icon_off.pixmap(QSize(16, 16))); @@ -207,19 +208,28 @@ MainWindow::MainWindow(QWidget *parent) scroll_label->setPixmap(scroll_icon_off.pixmap(QSize(16, 16))); statusBar()->addPermanentWidget(scroll_label); + kana_label = new QLabel; + kana_label->setPixmap(kana_icon_off.pixmap(QSize(16, 16))); + statusBar()->addPermanentWidget(kana_label); + QTimer* ledKeyboardTimer = new QTimer(this); ledKeyboardTimer->setTimerType(Qt::CoarseTimer); ledKeyboardTimer->setInterval(1); connect(ledKeyboardTimer, &QTimer::timeout, this, [this] () { - uint8_t caps, num, scroll; - keyboard_get_states(&caps, &num, &scroll); + uint8_t caps, num, scroll, kana; + keyboard_get_states(&caps, &num, &scroll, &kana); if (num_label->isVisible()) num_label->setPixmap(num ? this->num_icon.pixmap(QSize(16, 16)) : this->num_icon_off.pixmap(QSize(16, 16))); if (caps_label->isVisible()) caps_label->setPixmap(caps ? this->caps_icon.pixmap(QSize(16, 16)) : this->caps_icon_off.pixmap(QSize(16, 16))); if (scroll_label->isVisible()) - scroll_label->setPixmap(scroll ? this->scroll_icon.pixmap(QSize(16, 16)) : this->scroll_icon_off.pixmap(QSize(16, 16))); + scroll_label->setPixmap(scroll ? this->scroll_icon.pixmap(QSize(16, 16)) : + this->scroll_icon_off.pixmap(QSize(16, 16))); + + if (kana_label->isVisible()) + kana_label->setPixmap(kana ? this->kana_icon.pixmap(QSize(16, 16)) : + this->kana_icon_off.pixmap(QSize(16, 16))); }); ledKeyboardTimer->start(); @@ -253,6 +263,9 @@ MainWindow::MainWindow(QWidget *parent) num_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); scroll_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); caps_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + /* TODO: Base this on keyboard type instead when that's done. */ + kana_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD) && + machine_has_flags(machine, MACHINE_AX)); while (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); #ifdef USE_WACOM @@ -1499,6 +1512,8 @@ MainWindow::refreshMediaMenu() num_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); scroll_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); caps_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + kana_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD) && + machine_has_flags(machine, MACHINE_AX)); } void diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 421b9ce15..917fd43f5 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -191,9 +191,9 @@ private: friend class RendererStack; // For UI variable access by non-primary renderer windows. friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. - QLabel *caps_label, *scroll_label, *num_label; - QIcon caps_icon, scroll_icon, num_icon; - QIcon caps_icon_off, scroll_icon_off, num_icon_off; + QLabel *caps_label, *scroll_label, *num_label, *kana_label; + QIcon caps_icon, scroll_icon, num_icon, kana_icon; + QIcon caps_icon_off, scroll_icon_off, num_icon_off, kana_icon_off; bool isShowMessage = false; }; From 6fb01cf592ec78fac1924d69b8a239c6b9d8875b Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 7 May 2025 10:11:51 +0700 Subject: [PATCH 0867/1190] Added ISA-specific 86c805 (ELSA Winner 1000) Ported from my ELSA_Winner_Series branch. --- src/include/86box/video.h | 1 + src/video/vid_s3.c | 33 ++++++++++++++++++++++++++++++++- src/video/vid_table.c | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index d55275359..1b50d86f8 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -488,6 +488,7 @@ extern const device_t s3_metheus_86c928_isa_device; extern const device_t s3_metheus_86c928_vlb_device; extern const device_t s3_spea_mercury_lite_86c928_pci_device; extern const device_t s3_spea_mirage_86c801_isa_device; +extern const device_t s3_winner1000_805_isa_device; extern const device_t s3_86c805_onboard_vlb_device; extern const device_t s3_spea_mirage_86c805_vlb_device; extern const device_t s3_mirocrystal_8s_805_vlb_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 6897aed60..1f1ab5ede 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -54,6 +54,7 @@ #define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" #define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN" #define ROM_PHOENIX_86C80X "roms/video/s3/805.VBI" +#define ROM_WINNER1000_805 "roms/video/s3/v01_05_00-C.BIN.bin" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" #define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" @@ -117,7 +118,8 @@ enum { S3_NUMBER9_9FX_771, S3_SPEA_MERCURY_LITE_PCI, S3_86C805_ONBOARD, - S3_DIAMOND_STEALTH64_968 + S3_DIAMOND_STEALTH64_968, + S3_WINNER1000_805 }; enum { @@ -3782,6 +3784,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: + case S3_WINNER1000_805: case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; @@ -3950,6 +3953,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: + case S3_WINNER1000_805: case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; @@ -4122,6 +4126,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: + case S3_WINNER1000_805: case S3_PHOENIX_86C805: case S3_SPEA_MIRAGE_86C805: case S3_86C805_ONBOARD: @@ -9835,6 +9840,11 @@ s3_init(const device_t *info) chip = S3_86C801; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; + case S3_WINNER1000_805: + bios_fn = ROM_WINNER1000_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; case S3_86C805_ONBOARD: bios_fn = NULL; chip = S3_86C805; @@ -10316,6 +10326,7 @@ s3_init(const device_t *info) case S3_PHOENIX_86C801: case S3_PHOENIX_86C805: + case S3_WINNER1000_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ s3->id = stepping; @@ -10585,6 +10596,12 @@ s3_phoenix_86c80x_available(void) return rom_present(ROM_PHOENIX_86C80X); } +static int +s3_winner1000_805_available(void) +{ + return rom_present(ROM_WINNER1000_805); +} + static int s3_mirocrystal_8s_805_available(void) { @@ -10974,6 +10991,20 @@ const device_t s3_spea_mirage_86c801_isa_device = { .config = s3_9fx_config }; +const device_t s3_winner1000_805_isa_device = { + .name = "S3 86c805 ISA (ELSA Winner 1000)", + .internal_name = "winner1000_805_isa", + .flags = DEVICE_ISA16, + .local = S3_WINNER1000_805, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + .available = s3_winner1000_805_available, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config +}; + const device_t s3_86c805_onboard_vlb_device = { .name = "S3 86c805 VLB On-Board", .internal_name = "px_s3_805_onboard_vlb", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 36573e9f9..e0ef7ada6 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -115,6 +115,7 @@ video_cards[] = { { .device = &s3_metheus_86c928_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &s3_phoenix_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &s3_spea_mirage_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_winner1000_805_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &sigma_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &tvga8900b_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &tvga8900d_device, .flags = VIDEO_FLAG_TYPE_NONE }, From 5d929c7735b0758ee155c07f622f97ad5d859e8e Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 7 May 2025 10:39:22 +0700 Subject: [PATCH 0868/1190] Move Winner 1000's RAMDAC to ATT491 --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 1f1ab5ede..23713c98b 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -10297,6 +10297,7 @@ s3_init(const device_t *info) case S3_SPEA_MIRAGE_86C801: case S3_SPEA_MIRAGE_86C805: + case S3_WINNER1000_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa2; /*86C801/86C805*/ s3->id = stepping; @@ -10326,7 +10327,6 @@ s3_init(const device_t *info) case S3_PHOENIX_86C801: case S3_PHOENIX_86C805: - case S3_WINNER1000_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ s3->id = stepping; From 1f40db5d9e09092d6610103ef0196047fdc6b6c7 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Wed, 7 May 2025 11:29:11 +0700 Subject: [PATCH 0869/1190] Fixed ROM path --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 23713c98b..e88bbe58f 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -54,7 +54,7 @@ #define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" #define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN" #define ROM_PHOENIX_86C80X "roms/video/s3/805.VBI" -#define ROM_WINNER1000_805 "roms/video/s3/v01_05_00-C.BIN.bin" +#define ROM_WINNER1000_805 "roms/video/s3/v01_05_00-C.BIN" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" #define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" From 20d04c7c0834fbff8b0d4ae162e04e46c3ba707d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 07:20:54 +0200 Subject: [PATCH 0870/1190] Added the ASUS ISA-486C. --- src/chipset/CMakeLists.txt | 1 + src/device/postcard.c | 2 ++ src/include/86box/chipset.h | 3 +++ src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 29 ++++++++++++++++++++++++++ src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+) diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 6018dd045..94ef408f6 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -39,6 +39,7 @@ add_library(chipset OBJECT intel_i450kx.c intel_sio.c intel_piix.c + isa486c.c ../ioapic.c neat.c opti283.c diff --git a/src/device/postcard.c b/src/device/postcard.c index 9e2c629c1..b91d8b402 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -158,6 +158,8 @@ postcard_init(UNUSED(const device_t *info)) postcard_port = 0x84; /* ISA Compaq machines */ else if (strstr(machines[machine].name, "Olivetti")) postcard_port = 0x378; /* Olivetti machines */ + else if (!strcmp(machines[machine].internal_name, "isa486c")) + postcard_port = 0x5080; /* ASUS ISA-486C */ else postcard_port = 0x80; /* AT and clone machines */ postcard_log("POST card initializing on port %04Xh\n", postcard_port); diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 3a65bbce9..fe088b209 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -37,6 +37,9 @@ extern const device_t ali6117d_device; /* AMD */ extern const device_t amd640_device; +/* ASUS */ +extern const device_t isa486c_device; + /* Compaq */ extern const device_t compaq_386_device; extern const device_t compaq_genoa_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d8c213d53..996f2bf5f 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -508,6 +508,7 @@ extern int machine_at_pc916sx_init(const machine_t *); sure this appear here (and in the .c file) in the order and position in which they appear in the machine table. */ extern int machine_at_dataexpert386wb_init(const machine_t *); +extern int machine_at_isa486c_init(const machine_t *); extern int machine_at_genoa486_init(const machine_t *); extern int machine_at_ga486l_init(const machine_t *); extern int machine_at_cougar_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index ed8f75a84..f50e8af42 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2445,6 +2445,35 @@ machine_at_dataexpert386wb_init(const machine_t *model) return ret; } +int +machine_at_isa486c_init(const machine_t *model) +{ + int ret; + +#if 0 + ret = bios_load_linear("roms/machines/isa486c/asus-isa-486c-401a0-040591-657e2c17a0218417632602.bin", + 0x000f0000, 65536, 0); +#else + ret = bios_load_linear("roms/machines/isa486c/128k.bin", + 0x000e0000, 131072, 0); +#endif + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&isa486c_device); + device_add(&port_92_key_device); + + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_genoa486_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 7e0ae8d64..adf132a5d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5998,6 +5998,46 @@ const machine_t machines[] = { }, /* 486 machines - Socket 1 */ + /* Has Award KBC firmware. */ + { + .name = "[ZyMOS Poach] ASUS ISA-486C", + .internal_name = "isa486c", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_ZYMOS_POACH, + .init = machine_at_isa486c_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_APM, + .ram = { + .min = 1024, + .max = 16384, + .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 AMI KF KBC firmware. */ { .name = "[ZyMOS Poach] Genoa Unknown 486", From 9ac25992649e14fe8128067d61ae95b08a0368f1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 07:21:26 +0200 Subject: [PATCH 0871/1190] Correct the BIOS. --- src/machine/m_at_386dx_486.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index f50e8af42..e3838ce32 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2450,13 +2450,8 @@ machine_at_isa486c_init(const machine_t *model) { int ret; -#if 0 ret = bios_load_linear("roms/machines/isa486c/asus-isa-486c-401a0-040591-657e2c17a0218417632602.bin", 0x000f0000, 65536, 0); -#else - ret = bios_load_linear("roms/machines/isa486c/128k.bin", - 0x000e0000, 131072, 0); -#endif if (bios_only || !ret) return ret; From 572c9e176bc5d2b6051aed74cdd9a91e1087e7c6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 May 2025 17:41:59 +0600 Subject: [PATCH 0872/1190] Implement keyboard grabbing for Wayland --- src/qt/CMakeLists.txt | 1 + src/qt/qt_main.cpp | 10 ++ src/qt/qt_mainwindow.cpp | 25 ++- src/qt/wl_mouse.cpp | 37 ++++- ...keyboard-shortcuts-inhibit-unstable-v1.xml | 143 ++++++++++++++++++ 5 files changed, 209 insertions(+), 7 deletions(-) create mode 100644 wl_protocols/keyboard-shortcuts-inhibit-unstable-v1.xml diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 4231034d5..df13d42e2 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -453,6 +453,7 @@ if (UNIX AND NOT APPLE AND NOT HAIKU) set(WL_SOURCE_VAR) ecm_add_wayland_client_protocol(WL_SOURCE_VAR PROTOCOL ${CMAKE_SOURCE_DIR}/wl_protocols/relative-pointer-unstable-v1.xml BASENAME relative-pointer-unstable-v1) ecm_add_wayland_client_protocol(WL_SOURCE_VAR PROTOCOL ${CMAKE_SOURCE_DIR}/wl_protocols/pointer-constraints-unstable-v1.xml BASENAME pointer-constraints-unstable-v1) + ecm_add_wayland_client_protocol(WL_SOURCE_VAR PROTOCOL ${CMAKE_SOURCE_DIR}/wl_protocols/keyboard-shortcuts-inhibit-unstable-v1.xml BASENAME keyboard-shortcuts-inhibit-unstable-v1) target_include_directories(ui PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${Qt${QT_MAJOR}Gui_PRIVATE_INCLUDE_DIRS}) target_sources(ui PRIVATE ${WL_SOURCE_VAR} wl_mouse.cpp) if (XKBCOMMON_FOUND) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 1f1dd6b49..5cea8c698 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -672,6 +672,16 @@ main(int argc, char *argv[]) } else { main_window->show(); } +#ifdef __unix__ + if (QApplication::platformName().contains("wayland")) { + /* Force a sync. */ + (void)main_window->winId(); + QApplication::sync(); + extern void wl_keyboard_grab(QWindow *window); + wl_keyboard_grab(main_window->windowHandle()); + } +#endif + app.installEventFilter(main_window); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e966e043a..3e0f9f001 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -322,7 +322,8 @@ MainWindow::MainWindow(QWidget *parent) if (ui->stackedWidget->mouse_capture_func) ui->stackedWidget->mouse_capture_func(this->windowHandle()); } else { - this->releaseKeyboard(); + if (!(windowState() & Qt::WindowActive)) + this->releaseKeyboard(); if (ui->stackedWidget->mouse_uncapture_func) { ui->stackedWidget->mouse_uncapture_func(); } @@ -1492,8 +1493,26 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) curdopause = dopause; plat_pause(isShowMessage ? 2 : 1); emit setMouseCapture(false); + releaseKeyboard(); } else if (event->type() == QEvent::WindowUnblocked) { plat_pause(curdopause); +#ifdef __unix__ + if (!QApplication::platformName().contains("wayland") && (this->windowState() & Qt::WindowActive)) { + this->grabKeyboard(); + } +#endif + } else if (event->type() == QEvent::WindowActivate) { +#ifdef __unix__ + if (!QApplication::platformName().contains("wayland")) { + this->grabKeyboard(); + } +#endif + } else if (event->type() == QEvent::WindowDeactivate) { +#ifdef __unix__ + if (!QApplication::platformName().contains("wayland")) { + this->releaseKeyboard(); + } +#endif } } @@ -1611,13 +1630,13 @@ MainWindow::getRenderWidgetSize() void MainWindow::focusInEvent(QFocusEvent *event) { - this->grabKeyboard(); + //this->grabKeyboard(); } void MainWindow::focusOutEvent(QFocusEvent *event) { - this->releaseKeyboard(); + //this->releaseKeyboard(); } void diff --git a/src/qt/wl_mouse.cpp b/src/qt/wl_mouse.cpp index 5d6d95a0a..9201c4ec8 100644 --- a/src/qt/wl_mouse.cpp +++ b/src/qt/wl_mouse.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -30,10 +31,12 @@ extern "C" { #include <86box/plat.h> } -static zwp_relative_pointer_manager_v1 *rel_manager = nullptr; -static zwp_relative_pointer_v1 *rel_pointer = nullptr; -static zwp_pointer_constraints_v1 *conf_pointer_interface = nullptr; -static zwp_locked_pointer_v1 *conf_pointer = nullptr; +static zwp_relative_pointer_manager_v1 *rel_manager = nullptr; +static zwp_relative_pointer_v1 *rel_pointer = nullptr; +static zwp_pointer_constraints_v1 *conf_pointer_interface = nullptr; +static zwp_locked_pointer_v1 *conf_pointer = nullptr; +static zwp_keyboard_shortcuts_inhibit_manager_v1 *kbd_manager = nullptr; +static zwp_keyboard_shortcuts_inhibitor_v1 *kbd_inhibitor = nullptr; static bool wl_init_ok = false; @@ -47,6 +50,12 @@ static struct zwp_relative_pointer_v1_listener rel_listener = { rel_mouse_event }; +static struct zwp_keyboard_shortcuts_inhibitor_v1_listener kbd_listener +{ + [](void *data, struct zwp_keyboard_shortcuts_inhibitor_v1 *zwp_keyboard_shortcuts_inhibitor_v1) -> void {}, + [](void *data, struct zwp_keyboard_shortcuts_inhibitor_v1 *zwp_keyboard_shortcuts_inhibitor_v1) -> void {} +}; + static void display_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) @@ -57,16 +66,25 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id, if (!strcmp(interface, "zwp_pointer_constraints_v1")) { conf_pointer_interface = (zwp_pointer_constraints_v1 *) wl_registry_bind(registry, id, &zwp_pointer_constraints_v1_interface, version); } + if (!strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1")) { + kbd_manager = (zwp_keyboard_shortcuts_inhibit_manager_v1 *) wl_registry_bind(registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, version); + } } static void display_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) { plat_mouse_capture(0); + if (kbd_inhibitor) { + zwp_keyboard_shortcuts_inhibitor_v1_destroy(kbd_inhibitor); + kbd_inhibitor = nullptr; + } + zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(kbd_manager); zwp_relative_pointer_manager_v1_destroy(rel_manager); zwp_pointer_constraints_v1_destroy(conf_pointer_interface); rel_manager = nullptr; conf_pointer_interface = nullptr; + kbd_manager = nullptr; } static const struct wl_registry_listener registry_listener = { @@ -90,9 +108,20 @@ wl_init() } } +void +wl_keyboard_grab(QWindow *window) +{ + if (!kbd_inhibitor && kbd_manager) { + kbd_inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(kbd_manager, (wl_surface *) QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window), (wl_seat *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_seat")); + } +} + void wl_mouse_capture(QWindow *window) { + if (!kbd_inhibitor) { + kbd_inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(kbd_manager, (wl_surface *) QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window), (wl_seat *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_seat")); + } if (rel_manager) { rel_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(rel_manager, (wl_pointer *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_pointer")); zwp_relative_pointer_v1_add_listener(rel_pointer, &rel_listener, nullptr); diff --git a/wl_protocols/keyboard-shortcuts-inhibit-unstable-v1.xml b/wl_protocols/keyboard-shortcuts-inhibit-unstable-v1.xml new file mode 100644 index 000000000..27748764d --- /dev/null +++ b/wl_protocols/keyboard-shortcuts-inhibit-unstable-v1.xml @@ -0,0 +1,143 @@ + + + + + Copyright © 2017 Red Hat Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol specifies a way for a client to request the compositor + to ignore its own keyboard shortcuts for a given seat, so that all + key events from that seat get forwarded to a surface. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible + changes may be added together with the corresponding interface + version bump. + Backward incompatible changes are done by bumping the version + number in the protocol and interface names and resetting the + interface version. Once the protocol is to be declared stable, + the 'z' prefix and the version number in the protocol and + interface names are removed and the interface version number is + reset. + + + + + A global interface used for inhibiting the compositor keyboard shortcuts. + + + + + Destroy the keyboard shortcuts inhibitor manager. + + + + + + Create a new keyboard shortcuts inhibitor object associated with + the given surface for the given seat. + + If shortcuts are already inhibited for the specified seat and surface, + a protocol error "already_inhibited" is raised by the compositor. + + + + + + + + + + + + + + A keyboard shortcuts inhibitor instructs the compositor to ignore + its own keyboard shortcuts when the associated surface has keyboard + focus. As a result, when the surface has keyboard focus on the given + seat, it will receive all key events originating from the specified + seat, even those which would normally be caught by the compositor for + its own shortcuts. + + The Wayland compositor is however under no obligation to disable + all of its shortcuts, and may keep some special key combo for its own + use, including but not limited to one allowing the user to forcibly + restore normal keyboard events routing in the case of an unwilling + client. The compositor may also use the same key combo to reactivate + an existing shortcut inhibitor that was previously deactivated on + user request. + + When the compositor restores its own keyboard shortcuts, an + "inactive" event is emitted to notify the client that the keyboard + shortcuts inhibitor is not effectively active for the surface and + seat any more, and the client should not expect to receive all + keyboard events. + + When the keyboard shortcuts inhibitor is inactive, the client has + no way to forcibly reactivate the keyboard shortcuts inhibitor. + + The user can chose to re-enable a previously deactivated keyboard + shortcuts inhibitor using any mechanism the compositor may offer, + in which case the compositor will send an "active" event to notify + the client. + + If the surface is destroyed, unmapped, or loses the seat's keyboard + focus, the keyboard shortcuts inhibitor becomes irrelevant and the + compositor will restore its own keyboard shortcuts but no "inactive" + event is emitted in this case. + + + + + Remove the keyboard shortcuts inhibitor from the associated wl_surface. + + + + + + This event indicates that the shortcut inhibitor is active. + + The compositor sends this event every time compositor shortcuts + are inhibited on behalf of the surface. When active, the client + may receive input events normally reserved by the compositor + (see zwp_keyboard_shortcuts_inhibitor_v1). + + This occurs typically when the initial request "inhibit_shortcuts" + first becomes active or when the user instructs the compositor to + re-enable and existing shortcuts inhibitor using any mechanism + offered by the compositor. + + + + + + This event indicates that the shortcuts inhibitor is inactive, + normal shortcuts processing is restored by the compositor. + + + + From e1a6ebac08b1575da8e4e570c03fca46d807613b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 15:23:50 +0200 Subject: [PATCH 0873/1190] The forgotten chipset/is486c.c. --- src/chipset/isa486c.c | 131 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/chipset/isa486c.c diff --git a/src/chipset/isa486c.c b/src/chipset/isa486c.c new file mode 100644 index 000000000..6494ed1b8 --- /dev/null +++ b/src/chipset/isa486c.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/plat_unused.h> +#include <86box/chipset.h> + +typedef struct isa486c_t { + uint8_t regs[3]; +} isa486c_t; + +static void +isa486c_recalcmapping(isa486c_t *dev) +{ + uint32_t shflags = 0; + uint32_t bases[5] = { 0x000c0000, 0x000c8000, 0x000d0000, 0x000d8000, 0x000e0000 }; + uint32_t sizes[5] = { 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00020000 }; + + if (dev->regs[1] & 0x20) + shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + else + shflags = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; + + shadowbios = 0; + shadowbios_write = 0; + + for (uint8_t i = 0; i < 5; i++) + if (dev->regs[1] & (1 << i)) { + if (i == 4) { + shadowbios = 1; + shadowbios_write = !!(dev->regs[1] & 0x20); + } + + mem_set_mem_state_both(bases[i], sizes[i], shflags); + } else + mem_set_mem_state_both(bases[i], sizes[i], MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + flushmmucache_nopc(); +} + +static void +isa486c_write(uint16_t addr, uint8_t val, void *priv) +{ + isa486c_t *dev = (isa486c_t *) priv; + + switch (addr) { + case 0x0023: + dev->regs[0] = val; + break; + /* + Port 25h: + - Bit 0 = Video BIOS (C000-C7FF) shadow enabled; + - Bit 1 = C800-C8FF shadow enabled; + - Bit 2 = D000-D7FF shadow enabled; + - Bit 3 = D800-DFFF shadow enabled; + - Bit 4 = E000-FFFF shadow enabled (or F0000-FFFFF?); + - Bit 5 = If set, read from ROM, write to shadow; + - Bit 6 = KEN Video & BIOS enabled (cacheability!). + */ + case 0x0025: + dev->regs[1] = val; + isa486c_recalcmapping(dev); + break; + case 0x0027: + dev->regs[2] = val; + break; + } +} + +static uint8_t +isa486c_read(uint16_t addr, void *priv) +{ + isa486c_t *dev = (isa486c_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x0023: + ret = dev->regs[0]; + break; + case 0x0025: + ret = dev->regs[1]; + break; + case 0x0027: + ret = dev->regs[2]; + break; + } + + return ret; +} + +static void +isa486c_close(void *priv) +{ + isa486c_t *dev = (isa486c_t *) priv; + + free(dev); +} + +static void * +isa486c_init(UNUSED(const device_t *info)) +{ + isa486c_t *dev = (isa486c_t *) calloc(1, sizeof(isa486c_t)); + + io_sethandler(0x0023, 0x0001, isa486c_read, NULL, NULL, isa486c_write, NULL, NULL, dev); + io_sethandler(0x0025, 0x0001, isa486c_read, NULL, NULL, isa486c_write, NULL, NULL, dev); + io_sethandler(0x0027, 0x0001, isa486c_read, NULL, NULL, isa486c_write, NULL, NULL, dev); + + return dev; +} + +const device_t isa486c_device = { + .name = "ASUS ISA-486C Gate Array", + .internal_name = "isa486c", + .flags = 0, + .local = 0, + .init = isa486c_init, + .close = isa486c_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; From 39fdda6dd9ef4ccda98f6d61db0a41eb7b077c8e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 May 2025 20:22:38 +0600 Subject: [PATCH 0874/1190] Fix compilation without extra-cmake-modules --- src/qt/qt_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 5cea8c698..3f8476374 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -672,7 +672,7 @@ main(int argc, char *argv[]) } else { main_window->show(); } -#ifdef __unix__ +#ifdef WAYLAND if (QApplication::platformName().contains("wayland")) { /* Force a sync. */ (void)main_window->winId(); From 5918356719158636b24aa14bfa1aef17d44ea050 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 7 May 2025 19:03:10 +0500 Subject: [PATCH 0875/1190] Fix keybinds being saved in native/localized form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keybinds are now both saved and read in portable form and only converted to native one for display purposes, fixing them not being read correctly when certain languages are set. Also get rid of qPrintable() due to it using the system 8-bit codepage instead of UTF-8, and some unnecessary QString ↔ C string conversions Co-Authored-by: Cacodemon345 --- src/include/86box/plat.h | 4 ++-- src/qt/languages/86box.pot | 2 +- src/qt/languages/ca-ES.po | 12 ++++++------ src/qt/languages/cs-CZ.po | 12 ++++++------ src/qt/languages/de-DE.po | 15 ++++++--------- src/qt/languages/es-ES.po | 12 ++++++------ src/qt/languages/fi-FI.po | 12 ++++++------ src/qt/languages/fr-FR.po | 12 ++++++------ src/qt/languages/hr-HR.po | 12 ++++++------ src/qt/languages/hu-HU.po | 12 ++++++------ src/qt/languages/it-IT.po | 12 ++++++------ src/qt/languages/ja-JP.po | 12 ++++++------ src/qt/languages/ko-KR.po | 12 ++++++------ src/qt/languages/nl-NL.po | 12 ++++++------ src/qt/languages/pl-PL.po | 12 ++++++------ src/qt/languages/pt-BR.po | 12 ++++++------ src/qt/languages/pt-PT.po | 12 ++++++------ src/qt/languages/ru-RU.po | 12 ++++++------ src/qt/languages/sk-SK.po | 12 ++++++------ src/qt/languages/sl-SI.po | 12 ++++++------ src/qt/languages/sv-SE.po | 12 ++++++------ src/qt/languages/tr-TR.po | 12 ++++++------ src/qt/languages/uk-UA.po | 12 ++++++------ src/qt/languages/vi-VN.po | 12 ++++++------ src/qt/languages/zh-CN.po | 12 ++++++------ src/qt/languages/zh-TW.po | 12 ++++++------ src/qt/qt_keybind.cpp | 2 +- src/qt/qt_mainwindow.cpp | 7 +++---- src/qt/qt_platform.cpp | 13 +++---------- src/qt/qt_settingsinput.cpp | 10 +++++----- 30 files changed, 159 insertions(+), 170 deletions(-) diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index bbc673dcf..e6a366f4c 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -32,8 +32,8 @@ /* String ID numbers. */ enum { STRING_MOUSE_CAPTURE, /* "Click to capture mouse" */ - STRING_MOUSE_RELEASE, /* "Press F8+F12 to release mouse" */ - STRING_MOUSE_RELEASE_MMB, /* "Press F8+F12 or middle button to release mouse" */ + STRING_MOUSE_RELEASE, /* "Press %1 to release mouse" */ + STRING_MOUSE_RELEASE_MMB, /* "Press %1 or middle button to release mouse" */ STRING_INVALID_CONFIG, /* "Invalid configuration" */ STRING_NO_ST506_ESDI_CDROM, /* "MFM/RLL or ESDI CD-ROM drives never existed" */ STRING_NET_ERROR, /* "Failed to initialize network driver" */ diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index 6e6dd3fc3..d5152cd3d 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -630,7 +630,7 @@ msgstr "" msgid " - PAUSED" msgstr "" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgid "Press %1 to return to windowed mode." msgstr "" msgid "Speed" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 4851106cd..7fe87eb1a 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -630,8 +630,8 @@ msgstr "Error fatal" msgid " - PAUSED" msgstr " - EN PAUSA" -msgid "Press %s to return to windowed mode." -msgstr "Premeu %s per tornar al mode de finestra." +msgid "Press %1 to return to windowed mode." +msgstr "Premeu %1 per tornar al mode de finestra." msgid "Speed" msgstr "Velocitat" @@ -717,11 +717,11 @@ msgstr "Altres perifèrics" msgid "Click to capture mouse" msgstr "Feu clic per capturar el ratolí" -msgid "Press %s to release mouse" -msgstr "Premeu %s per alliberar el ratolí" +msgid "Press %1 to release mouse" +msgstr "Premeu %1 per alliberar el ratolí" -msgid "Press %s or middle button to release mouse" -msgstr "Premeu %s o el botó central per alliberar el ratolí" +msgid "Press %1 or middle button to release mouse" +msgstr "Premeu %1 o el botó central per alliberar el ratolí" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 352fafc31..59a582ca6 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -630,8 +630,8 @@ msgstr "Kritická chyba" msgid " - PAUSED" msgstr " - POZASTAVENO" -msgid "Press %s to return to windowed mode." -msgstr "Stiskněte %s pro návrat z režimu celé obrazovky." +msgid "Press %1 to return to windowed mode." +msgstr "Stiskněte %1 pro návrat z režimu celé obrazovky." msgid "Speed" msgstr "Rychlost" @@ -717,11 +717,11 @@ msgstr "Jiné příslušenství" msgid "Click to capture mouse" msgstr "Klikněte pro zabraní myši" -msgid "Press %s to release mouse" -msgstr "Stiskněte %s pro uvolnění myši" +msgid "Press %1 to release mouse" +msgstr "Stiskněte %1 pro uvolnění myši" -msgid "Press %s or middle button to release mouse" -msgstr "Stiskněte %s nebo prostřední tlačítko pro uvolnění myši" +msgid "Press %1 or middle button to release mouse" +msgstr "Stiskněte %1 nebo prostřední tlačítko pro uvolnění myši" msgid "Bus" msgstr "Sběrnice" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index ce7d52d55..0615dada4 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -630,8 +630,8 @@ msgstr "Fataler Fehler" msgid " - PAUSED" msgstr " - PAUSIERT" -msgid "Press %s to return to windowed mode." -msgstr "%s ab, zur Rückkehr in den Fenstermodus." +msgid "Press %1 to return to windowed mode." +msgstr "%1 ab, zur Rückkehr in den Fenstermodus." msgid "Speed" msgstr "Geschwindigkeit" @@ -717,14 +717,11 @@ msgstr "Andere Peripheriegeräte" msgid "Click to capture mouse" msgstr "Klicken zum Einfangen des Mauszeigers" -msgid "Press %s to release mouse" -msgstr "Drücke %s zur Mausfreigabe" +msgid "Press %1 to release mouse" +msgstr "Drücke %1 zur Mausfreigabe" -msgid "Press %s or middle button to release mouse" -msgstr "Drücke %s oder die mittlere Maustaste zur Mausfreigabe" - -msgid "Ctrl+End" -msgstr "Strg+Ende" +msgid "Press %1 or middle button to release mouse" +msgstr "Drücke %1 oder die mittlere Maustaste zur Mausfreigabe" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 177d08d18..1f9cf10b2 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -630,8 +630,8 @@ msgstr "Error fatal" msgid " - PAUSED" msgstr " - EN PAUSA" -msgid "Press %s to return to windowed mode." -msgstr "Pulsa %s para volver a modo ventana." +msgid "Press %1 to return to windowed mode." +msgstr "Pulsa %1 para volver a modo ventana." msgid "Speed" msgstr "Velocidad" @@ -717,11 +717,11 @@ msgstr "Otros periféricos" msgid "Click to capture mouse" msgstr "Haga click para capturar el ratón" -msgid "Press %s to release mouse" -msgstr "Pulse %s para liberar el ratón" +msgid "Press %1 to release mouse" +msgstr "Pulse %1 para liberar el ratón" -msgid "Press %s or middle button to release mouse" -msgstr "Pulse %s o el botón central para liberar el ratón" +msgid "Press %1 or middle button to release mouse" +msgstr "Pulse %1 o el botón central para liberar el ratón" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index a77b3f6ef..4979332ac 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -630,8 +630,8 @@ msgstr "Vakava virhe" msgid " - PAUSED" msgstr " - TAUKO" -msgid "Press %s to return to windowed mode." -msgstr "Paina %s palataksesi ikkunoituun tilaan." +msgid "Press %1 to return to windowed mode." +msgstr "Paina %1 palataksesi ikkunoituun tilaan." msgid "Speed" msgstr "Nopeus" @@ -717,11 +717,11 @@ msgstr "Muut oheislaitteet" msgid "Click to capture mouse" msgstr "Kaappaa hiiri klikkaamalla" -msgid "Press %s to release mouse" -msgstr "Paina %s vapauttaaksesi hiiren" +msgid "Press %1 to release mouse" +msgstr "Paina %1 vapauttaaksesi hiiren" -msgid "Press %s or middle button to release mouse" -msgstr "Paina %s tai keskipainiketta vapauttaaksesi hiiren" +msgid "Press %1 or middle button to release mouse" +msgstr "Paina %1 tai keskipainiketta vapauttaaksesi hiiren" msgid "Bus" msgstr "Väylä" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index fe3dc4bb4..58de2e4d1 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -630,8 +630,8 @@ msgstr "Erreur fatale" msgid " - PAUSED" msgstr " - EN PAUSE" -msgid "Press %s to return to windowed mode." -msgstr "Appuyez sur %s pour revenir au mode fenêtré." +msgid "Press %1 to return to windowed mode." +msgstr "Appuyez sur %1 pour revenir au mode fenêtré." msgid "Speed" msgstr "Vitesse" @@ -717,11 +717,11 @@ msgstr "Autres périfériques" msgid "Click to capture mouse" msgstr "Cliquer pour capturer la souris" -msgid "Press %s to release mouse" -msgstr "Appuyer sur %s pour libérer la souris" +msgid "Press %1 to release mouse" +msgstr "Appuyer sur %1 pour libérer la souris" -msgid "Press %s or middle button to release mouse" -msgstr "Appuyer sur %s ou le bouton central pour libérer la souris" +msgid "Press %1 or middle button to release mouse" +msgstr "Appuyer sur %1 ou le bouton central pour libérer la souris" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 1eecaa2d0..5f0e60b21 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -630,8 +630,8 @@ msgstr "Fatalna greška" msgid " - PAUSED" msgstr " - ZASTAO" -msgid "Press %s to return to windowed mode." -msgstr "Pritisnite %s za povratak u prozorski način rada." +msgid "Press %1 to return to windowed mode." +msgstr "Pritisnite %1 za povratak u prozorski način rada." msgid "Speed" msgstr "Brzina" @@ -717,11 +717,11 @@ msgstr "Ostali periferni uređaji" msgid "Click to capture mouse" msgstr "Kliknite da uhvatite miš" -msgid "Press %s to release mouse" -msgstr "Pritisnite %s za otpustanje miša" +msgid "Press %1 to release mouse" +msgstr "Pritisnite %1 za otpustanje miša" -msgid "Press %s or middle button to release mouse" -msgstr "Pritisnite %s ili srednji gumb miša za otpuštanje miša" +msgid "Press %1 or middle button to release mouse" +msgstr "Pritisnite %1 ili srednji gumb miša za otpuštanje miša" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 43a1fd9ba..3398859d2 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -630,8 +630,8 @@ msgstr "Végzetes hiba" msgid " - PAUSED" msgstr " - SZÜNETELT" -msgid "Press %s to return to windowed mode." -msgstr "Használja a %s gombokat az ablakhoz való visszatéréshez." +msgid "Press %1 to return to windowed mode." +msgstr "Használja a %1 gombokat az ablakhoz való visszatéréshez." msgid "Speed" msgstr "Sebesség" @@ -717,11 +717,11 @@ msgstr "Egyéb perifériák" msgid "Click to capture mouse" msgstr "Kattintson az egér elfogásához" -msgid "Press %s to release mouse" -msgstr "Nyomja meg az %s-t az egér elengédéséhez" +msgid "Press %1 to release mouse" +msgstr "Nyomja meg az %1-t az egér elengédéséhez" -msgid "Press %s or middle button to release mouse" -msgstr "Nyomja meg az %s-t vagy a középső gombot az egér elengédéséhez" +msgid "Press %1 or middle button to release mouse" +msgstr "Nyomja meg az %1-t vagy a középső gombot az egér elengédéséhez" msgid "Bus" msgstr "Busz" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index b8ded74de..d45a0080b 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -630,8 +630,8 @@ msgstr "Errore fatale" msgid " - PAUSED" msgstr " - IN PAUSA" -msgid "Press %s to return to windowed mode." -msgstr "Usa %s per tornare alla modalità finestra." +msgid "Press %1 to return to windowed mode." +msgstr "Usa %1 per tornare alla modalità finestra." msgid "Speed" msgstr "Velocità" @@ -717,11 +717,11 @@ msgstr "Altre periferiche" msgid "Click to capture mouse" msgstr "Fare clic per catturare mouse" -msgid "Press %s to release mouse" -msgstr "Premi %s per rilasciare il mouse" +msgid "Press %1 to release mouse" +msgstr "Premi %1 per rilasciare il mouse" -msgid "Press %s or middle button to release mouse" -msgstr "Premi %s o pulsante centrale per rilasciare il mouse" +msgid "Press %1 or middle button to release mouse" +msgstr "Premi %1 o pulsante centrale per rilasciare il mouse" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index dc000b175..7883f8a5a 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -630,8 +630,8 @@ msgstr "致命的なエラー" msgid " - PAUSED" msgstr " - 一時停止" -msgid "Press %s to return to windowed mode." -msgstr "%sでウィンドウ モードに戻ります。" +msgid "Press %1 to return to windowed mode." +msgstr "%1でウィンドウ モードに戻ります。" msgid "Speed" msgstr "速度" @@ -717,11 +717,11 @@ msgstr "他の周辺デバイス" msgid "Click to capture mouse" msgstr "左クリックでマウスをキャプチャします" -msgid "Press %s to release mouse" -msgstr "%sキーでマウスを解放します" +msgid "Press %1 to release mouse" +msgstr "%1キーでマウスを解放します" -msgid "Press %s or middle button to release mouse" -msgstr "%sキーまたは中クリックでマウスを解放します" +msgid "Press %1 or middle button to release mouse" +msgstr "%1キーまたは中クリックでマウスを解放します" msgid "Bus" msgstr "バス" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 3ef901789..a9ed452d6 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -630,8 +630,8 @@ msgstr "치명적인 오류" msgid " - PAUSED" msgstr " - 일시 중지됨" -msgid "Press %s to return to windowed mode." -msgstr "%s 키를 누르면 창 모드로 전환합니다." +msgid "Press %1 to return to windowed mode." +msgstr "%1 키를 누르면 창 모드로 전환합니다." msgid "Speed" msgstr "속도" @@ -717,11 +717,11 @@ msgstr "기타 주변기기" msgid "Click to capture mouse" msgstr "이 창을 클릭하면 마우스를 사용합니다" -msgid "Press %s to release mouse" -msgstr "%s키를 누르면 마우스를 해제합니다" +msgid "Press %1 to release mouse" +msgstr "%1키를 누르면 마우스를 해제합니다" -msgid "Press %s or middle button to release mouse" -msgstr "%s키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" +msgid "Press %1 or middle button to release mouse" +msgstr "%1키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" msgid "Bus" msgstr "버스" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 49a32506b..2859916d7 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -630,8 +630,8 @@ msgstr "Fatale fout" msgid " - PAUSED" msgstr " - GEPAUZEERD" -msgid "Press %s to return to windowed mode." -msgstr "Druk op %s om terug te gaan naar de venstermodus." +msgid "Press %1 to return to windowed mode." +msgstr "Druk op %1 om terug te gaan naar de venstermodus." msgid "Speed" msgstr "Snelheid" @@ -717,11 +717,11 @@ msgstr "Andere randapparatuur" msgid "Click to capture mouse" msgstr "Klik om muis vast te leggen" -msgid "Press %s to release mouse" -msgstr "Druk op %s om de muis los te laten" +msgid "Press %1 to release mouse" +msgstr "Druk op %1 om de muis los te laten" -msgid "Press %s or middle button to release mouse" -msgstr "Druk op %s of middelste knop om de muis los te laten" +msgid "Press %1 or middle button to release mouse" +msgstr "Druk op %1 of middelste knop om de muis los te laten" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index d5b5ec3ea..02bdc26fe 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -630,8 +630,8 @@ msgstr "Fatalny błąd" msgid " - PAUSED" msgstr " - PAUSED" -msgid "Press %s to return to windowed mode." -msgstr "Naciśnij klawisze %s aby wrócić to trybu okna." +msgid "Press %1 to return to windowed mode." +msgstr "Naciśnij klawisze %1 aby wrócić to trybu okna." msgid "Speed" msgstr "Szybkość" @@ -717,11 +717,11 @@ msgstr "Inne urządzenia peryferyjne" msgid "Click to capture mouse" msgstr "Kliknij w celu przechwycenia myszy" -msgid "Press %s to release mouse" -msgstr "Naciśnij klawisze %s w celu uwolnienia myszy" +msgid "Press %1 to release mouse" +msgstr "Naciśnij klawisze %1 w celu uwolnienia myszy" -msgid "Press %s or middle button to release mouse" -msgstr "Naciśnij klawisze %s lub środkowy przycisk w celu uwolnienia myszy" +msgid "Press %1 or middle button to release mouse" +msgstr "Naciśnij klawisze %1 lub środkowy przycisk w celu uwolnienia myszy" msgid "Bus" msgstr "Magistrala" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index e33630ccf..4fb974f4d 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -630,8 +630,8 @@ msgstr "Erro fatal" msgid " - PAUSED" msgstr " - PAUSADO" -msgid "Press %s to return to windowed mode." -msgstr "Use %s para retornar ao modo janela." +msgid "Press %1 to return to windowed mode." +msgstr "Use %1 para retornar ao modo janela." msgid "Speed" msgstr "Velocidade" @@ -717,11 +717,11 @@ msgstr "Outros periféricos" msgid "Click to capture mouse" msgstr "Clique para capturar o mouse" -msgid "Press %s to release mouse" -msgstr "Aperte %s para liberar o mouse" +msgid "Press %1 to release mouse" +msgstr "Aperte %1 para liberar o mouse" -msgid "Press %s or middle button to release mouse" -msgstr "Aperte %s ou botão do meio para liberar o mouse" +msgid "Press %1 or middle button to release mouse" +msgstr "Aperte %1 ou botão do meio para liberar o mouse" msgid "Bus" msgstr "Barramento" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index ba1c6976c..86c40fc40 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -630,8 +630,8 @@ msgstr "Erro fatal" msgid " - PAUSED" msgstr " - EM PAUSA" -msgid "Press %s to return to windowed mode." -msgstr "Pressione %s para voltar ao modo de janela." +msgid "Press %1 to return to windowed mode." +msgstr "Pressione %1 para voltar ao modo de janela." msgid "Speed" msgstr "Velocidade" @@ -717,11 +717,11 @@ msgstr "Outros dispositivos" msgid "Click to capture mouse" msgstr "Clique para capturar o rato" -msgid "Press %s to release mouse" -msgstr "Pressione %s para soltar o rato" +msgid "Press %1 to release mouse" +msgstr "Pressione %1 para soltar o rato" -msgid "Press %s or middle button to release mouse" -msgstr "Pressione %s ou tecla média para soltar o rato" +msgid "Press %1 or middle button to release mouse" +msgstr "Pressione %1 ou tecla média para soltar o rato" msgid "Bus" msgstr "Barramento" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index e88f4f0fc..899b905ac 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -630,8 +630,8 @@ msgstr "Неустранимая ошибка" msgid " - PAUSED" msgstr " - ПАУЗА" -msgid "Press %s to return to windowed mode." -msgstr "Нажмите %s для возврата в оконный режим." +msgid "Press %1 to return to windowed mode." +msgstr "Нажмите %1 для возврата в оконный режим." msgid "Speed" msgstr "Скорость" @@ -717,11 +717,11 @@ msgstr "Другая периферия" msgid "Click to capture mouse" msgstr "Щёлкните мышью для захвата курсора" -msgid "Press %s to release mouse" -msgstr "Нажмите %s, чтобы освободить курсор" +msgid "Press %1 to release mouse" +msgstr "Нажмите %1, чтобы освободить курсор" -msgid "Press %s or middle button to release mouse" -msgstr "Нажмите %s или среднюю кнопку мыши, чтобы освободить курсор" +msgid "Press %1 or middle button to release mouse" +msgstr "Нажмите %1 или среднюю кнопку мыши, чтобы освободить курсор" msgid "Bus" msgstr "Шина" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index f11f335d4..624715f76 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -630,8 +630,8 @@ msgstr "Kritická chyba" msgid " - PAUSED" msgstr " - POZASTAVENÝ" -msgid "Press %s to return to windowed mode." -msgstr "Stlačte %s pre návrat z režimu celej obrazovky." +msgid "Press %1 to return to windowed mode." +msgstr "Stlačte %1 pre návrat z režimu celej obrazovky." msgid "Speed" msgstr "Rýchlosť" @@ -717,11 +717,11 @@ msgstr "Iné príslušenstvo" msgid "Click to capture mouse" msgstr "Kliknite pre zabráni myši" -msgid "Press %s to release mouse" -msgstr "Stlačte %s pre uvoľnenie myši" +msgid "Press %1 to release mouse" +msgstr "Stlačte %1 pre uvoľnenie myši" -msgid "Press %s or middle button to release mouse" -msgstr "Stlačte %s alebo prostredné tlačidlo na uvoľnenie myši" +msgid "Press %1 or middle button to release mouse" +msgstr "Stlačte %1 alebo prostredné tlačidlo na uvoľnenie myši" msgid "Bus" msgstr "Zbernica" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index dcb3dbf50..d07a1eac4 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -630,8 +630,8 @@ msgstr "Kritična napaka" msgid " - PAUSED" msgstr " - ZAUSTAVLJEN" -msgid "Press %s to return to windowed mode." -msgstr "Pritisnite %s za povratek iz celozaslonskega načina." +msgid "Press %1 to return to windowed mode." +msgstr "Pritisnite %1 za povratek iz celozaslonskega načina." msgid "Speed" msgstr "Hitrost" @@ -717,11 +717,11 @@ msgstr "Druga periferija" msgid "Click to capture mouse" msgstr "Kliknite za zajem miške" -msgid "Press %s to release mouse" -msgstr "Pritisnite %s za izpust miške" +msgid "Press %1 to release mouse" +msgstr "Pritisnite %1 za izpust miške" -msgid "Press %s or middle button to release mouse" -msgstr "Pritisnite %s ali srednji gumb za izpust miške" +msgid "Press %1 or middle button to release mouse" +msgstr "Pritisnite %1 ali srednji gumb za izpust miške" msgid "Bus" msgstr "Vodilo" diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index 61152c663..e33dbfe21 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -630,8 +630,8 @@ msgstr "Allvarligt fel" msgid " - PAUSED" msgstr " - PAUSAD" -msgid "Press %s to return to windowed mode." -msgstr "Tryck på %s för att återvända till fönsterläge." +msgid "Press %1 to return to windowed mode." +msgstr "Tryck på %1 för att återvända till fönsterläge." msgid "Speed" msgstr "Hastighet" @@ -717,11 +717,11 @@ msgstr "Andra tillbehör" msgid "Click to capture mouse" msgstr "Klicka för att fånga upp musen" -msgid "Press %s to release mouse" -msgstr "Tryck på %s för att släppa musen" +msgid "Press %1 to release mouse" +msgstr "Tryck på %1 för att släppa musen" -msgid "Press %s or middle button to release mouse" -msgstr "Tryck på %s eller mellersta musknappen för att släppa musen" +msgid "Press %1 or middle button to release mouse" +msgstr "Tryck på %1 eller mellersta musknappen för att släppa musen" msgid "Bus" msgstr "Buss" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index de111c59b..24c1c0ba0 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -630,8 +630,8 @@ msgstr "Kritik hata" msgid " - PAUSED" msgstr " - DURAKLATILDI" -msgid "Press %s to return to windowed mode." -msgstr "Pencere moduna geri dönmek için %s tuşlarına basın." +msgid "Press %1 to return to windowed mode." +msgstr "Pencere moduna geri dönmek için %1 tuşlarına basın." msgid "Speed" msgstr "Hız" @@ -717,11 +717,11 @@ msgstr "Diğer cihazlar" msgid "Click to capture mouse" msgstr "Farenin yakalanması için tıklayın" -msgid "Press %s to release mouse" -msgstr "Farenin bırakılması için %s tuşlarına basın" +msgid "Press %1 to release mouse" +msgstr "Farenin bırakılması için %1 tuşlarına basın" -msgid "Press %s or middle button to release mouse" -msgstr "Farenin bırakılması için %s tuşlarına veya tekerlek tuşuna basın" +msgid "Press %1 or middle button to release mouse" +msgstr "Farenin bırakılması için %1 tuşlarına veya tekerlek tuşuna basın" msgid "Bus" msgstr "Veri yolu" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index db9b73491..68b50771a 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -630,8 +630,8 @@ msgstr "Непереробна помилка" msgid " - PAUSED" msgstr " - ПРИЗУПИНЕННЯ" -msgid "Press %s to return to windowed mode." -msgstr "Натисніть %s для повернення у віконний режим." +msgid "Press %1 to return to windowed mode." +msgstr "Натисніть %1 для повернення у віконний режим." msgid "Speed" msgstr "Швидкість" @@ -717,11 +717,11 @@ msgstr "Інша периферія" msgid "Click to capture mouse" msgstr "Клацніть мишею для захвату курсора" -msgid "Press %s to release mouse" -msgstr "Натисніть %s, щоб звільнити курсор" +msgid "Press %1 to release mouse" +msgstr "Натисніть %1, щоб звільнити курсор" -msgid "Press %s or middle button to release mouse" -msgstr "Натисніть %s або середню кнопку миші, щоб звільнити курсор" +msgid "Press %1 or middle button to release mouse" +msgstr "Натисніть %1 або середню кнопку миші, щоб звільнити курсор" msgid "Bus" msgstr "Шина" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index e21466a18..8632234df 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -630,8 +630,8 @@ msgstr "Lỗi nghiêm trọng" msgid " - PAUSED" msgstr " - TẠM DỪNG" -msgid "Press %s to return to windowed mode." -msgstr "Bấm %s để quay lại chế độ cửa sổ." +msgid "Press %1 to return to windowed mode." +msgstr "Bấm %1 để quay lại chế độ cửa sổ." msgid "Speed" msgstr "Vận tốc" @@ -717,11 +717,11 @@ msgstr "Thiết bị ngoại vi khác" msgid "Click to capture mouse" msgstr "Nhấp vào khung hình để 'nhốt' chuột vào" -msgid "Press %s to release mouse" -msgstr "Nhấn %s để thả chuột" +msgid "Press %1 to release mouse" +msgstr "Nhấn %1 để thả chuột" -msgid "Press %s or middle button to release mouse" -msgstr "Nhấn %s hoặc nhấp chuột giữa để thả chuột" +msgid "Press %1 or middle button to release mouse" +msgstr "Nhấn %1 hoặc nhấp chuột giữa để thả chuột" msgid "Bus" msgstr "Bus" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index c29e40dfb..194db4f3d 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -630,8 +630,8 @@ msgstr "致命错误" msgid " - PAUSED" msgstr " - 已暂停" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "按下 Ctrl+Alt+PgDn 返回到窗口模式。" +msgid "Press %1 to return to windowed mode." +msgstr "按下 %1 返回到窗口模式。" msgid "Speed" msgstr "速度" @@ -717,11 +717,11 @@ msgstr "其他外围设备" msgid "Click to capture mouse" msgstr "单击窗口捕捉鼠标" -msgid "Press %s to release mouse" -msgstr "按下 %s 释放鼠标" +msgid "Press %1 to release mouse" +msgstr "按下 %1 释放鼠标" -msgid "Press %s or middle button to release mouse" -msgstr "按下 %s 或鼠标中键释放鼠标" +msgid "Press %1 or middle button to release mouse" +msgstr "按下 %1 或鼠标中键释放鼠标" msgid "Bus" msgstr "总线" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 7de6f8cd3..3bdf6b823 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -630,8 +630,8 @@ msgstr "致命錯誤" msgid " - PAUSED" msgstr " - 已暫停" -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "按下 Ctrl+Alt+PgDn 返回到視窗模式。" +msgid "Press %1 to return to windowed mode." +msgstr "按下 %1 返回到視窗模式。" msgid "Speed" msgstr "速度" @@ -717,11 +717,11 @@ msgstr "其他周邊裝置" msgid "Click to capture mouse" msgstr "點擊視窗捕捉滑鼠" -msgid "Press %s to release mouse" -msgstr "按下 %s 釋放滑鼠" +msgid "Press %1 to release mouse" +msgstr "按下 %1 釋放滑鼠" -msgid "Press %s or middle button to release mouse" -msgstr "按下 %s 或滑鼠中鍵釋放滑鼠" +msgid "Press %1 or middle button to release mouse" +msgstr "按下 %1 或滑鼠中鍵釋放滑鼠" msgid "Bus" msgstr "匯流排" diff --git a/src/qt/qt_keybind.cpp b/src/qt/qt_keybind.cpp index c7ed894b3..e6e87a5e2 100644 --- a/src/qt/qt_keybind.cpp +++ b/src/qt/qt_keybind.cpp @@ -90,7 +90,7 @@ KeyBinder::BindKey(QWidget* widget, QString CurValue) KeyBinder kb(widget); kb.setWindowTitle(tr("Bind Key")); kb.setFixedSize(kb.minimumSizeHint()); - kb.findChild()->setKeySequence(QKeySequence::fromString(CurValue)); + kb.findChild()->setKeySequence(QKeySequence::fromString(CurValue, QKeySequence::NativeText)); kb.setEnabled(true); if (kb.exec() == QDialog::Accepted) { diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e966e043a..3aa29f7f4 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1347,10 +1347,9 @@ MainWindow::on_actionFullscreen_triggered() if (video_fullscreen_first) { bool wasCaptured = mouse_capture == 1; - char strFullscreen[100]; - sprintf(strFullscreen, qPrintable(tr("Press %s to return to windowed mode.")), acc_keys[FindAccelerator("fullscreen")].seq); - - QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), QString(strFullscreen), QMessageBox::Ok, this); + QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), + tr("Press %1 to return to windowed mode.").arg(QKeySequence(acc_keys[FindAccelerator("fullscreen")].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText)), + QMessageBox::Ok, this); QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!video_fullscreen_first); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index be40452fd..a8c25bc2d 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -571,8 +572,6 @@ c16stombs(char dst[], const uint16_t src[], int len) } #endif -# define MOUSE_CAPTURE_KEYSEQ "F8+F12" - #ifdef _WIN32 # if defined(__amd64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) # define LIB_NAME_GS "gsdll64.dll" @@ -595,14 +594,8 @@ ProgSettings::reloadStrings() { translatedstrings.clear(); translatedstrings[STRING_MOUSE_CAPTURE] = QCoreApplication::translate("", "Click to capture mouse").toStdWString(); - - char mouseCaptureKeyseq[100]; - sprintf(mouseCaptureKeyseq, qPrintable(QCoreApplication::translate("", "Press %s to release mouse")), acc_keys[FindAccelerator("release_mouse")].seq); - translatedstrings[STRING_MOUSE_RELEASE] = QString(mouseCaptureKeyseq).toStdWString(); - - sprintf(mouseCaptureKeyseq, qPrintable(QCoreApplication::translate("", "Press %s or middle button to release mouse")), acc_keys[FindAccelerator("release_mouse")].seq); - translatedstrings[STRING_MOUSE_RELEASE_MMB] = QString(mouseCaptureKeyseq).toStdWString(); - + translatedstrings[STRING_MOUSE_RELEASE] = QCoreApplication::translate("", "Press %1 to release mouse").arg(QKeySequence(acc_keys[FindAccelerator("release_mouse")].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText)).toStdWString(); + translatedstrings[STRING_MOUSE_RELEASE_MMB] = QCoreApplication::translate("", "Press %1 or middle button to release mouse").arg(QKeySequence(acc_keys[FindAccelerator("release_mouse")].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText)).toStdWString(); translatedstrings[STRING_INVALID_CONFIG] = QCoreApplication::translate("", "Invalid configuration").toStdWString(); translatedstrings[STRING_NO_ST506_ESDI_CDROM] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").toStdWString(); translatedstrings[STRING_PCAP_ERROR_NO_DEVICES] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index f3729ab3f..a7000414c 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -162,7 +162,7 @@ SettingsInput::refreshInputList() for (int x=0;xtableKeys->setItem(x, 0, new QTableWidgetItem(tr(acc_keys_t[x].desc))); - ui->tableKeys->setItem(x, 1, new QTableWidgetItem(acc_keys_t[x].seq)); + ui->tableKeys->setItem(x, 1, new QTableWidgetItem(QKeySequence(acc_keys_t[x].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText))); ui->tableKeys->setItem(x, 2, new QTableWidgetItem(acc_keys_t[x].name)); } } @@ -201,7 +201,7 @@ SettingsInput::on_tableKeys_cellDoubleClicked(int row, int col) // so we don't test against shortcuts the user already changed. for(int x=0;xshowMessage(MBX_ANSI & MBX_INFO, "Bind conflict", "This key combo is already in use", false); @@ -212,12 +212,12 @@ SettingsInput::on_tableKeys_cellDoubleClicked(int row, int col) // Go ahead and apply the bind. // Find the correct accelerator key entry - int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(row,2)->text())); + int accKeyID = FindAccelerator(ui->tableKeys->item(row,2)->text().toUtf8().constData()); if (accKeyID < 0) return; // this should never happen // Make the change cell->setText(keyseq.toString(QKeySequence::NativeText)); - strcpy(acc_keys_t[accKeyID].seq, qPrintable(keyseq.toString(QKeySequence::NativeText))); + strcpy(acc_keys_t[accKeyID].seq, keyseq.toString(QKeySequence::PortableText).toUtf8().constData()); refreshInputList(); } @@ -242,7 +242,7 @@ SettingsInput::on_pushButtonClearBind_clicked() cell->setText(""); // Find the correct accelerator key entry - int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(cell->row(),2)->text())); + int accKeyID = FindAccelerator(ui->tableKeys->item(cell->row(),2)->text().toUtf8().constData()); if (accKeyID < 0) return; // this should never happen // Make the change From 44376db7f243e6f890411dd8a2383a359de437be Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 19:29:15 +0200 Subject: [PATCH 0876/1190] Ambra DP60: It is the original Batman, so no RZ-1000, and FDC37C665 controlling primary IDE. --- src/machine/m_at_socket4.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 92f88fbe6..03ff03a23 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -219,7 +219,22 @@ machine_at_ambradp60_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_premiere_common_init(model, 0); + machine_at_common_init_ex(model, 2); + + device_add(&amstrad_megapc_nvr_device); + device_add(&ide_pci_device); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_phoenix_device); + device_add(&sio_zb_device); + device_add(&fdc37c665_ide_pri_device); + device_add(&intel_flash_bxt_ami_device); device_add(&i430lx_device); From c42f1e4d122efc15c832858f264683cea844d598 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 7 May 2025 21:01:43 +0500 Subject: [PATCH 0877/1190] Remove the fullscreen hotkey message No longer needed after the hotkeys to enter and exit full screen mode were merged into one --- src/86box.c | 1 - src/config.c | 8 -------- src/include/86box/86box.h | 1 - src/include/86box/video.h | 1 - src/qt/languages/86box.pot | 11 +---------- src/qt/languages/ca-ES.po | 13 ++----------- src/qt/languages/cs-CZ.po | 13 ++----------- src/qt/languages/de-DE.po | 13 ++----------- src/qt/languages/en-GB.po | 4 ++-- src/qt/languages/es-ES.po | 13 ++----------- src/qt/languages/fi-FI.po | 13 ++----------- src/qt/languages/fr-FR.po | 13 ++----------- src/qt/languages/hr-HR.po | 13 ++----------- src/qt/languages/hu-HU.po | 13 ++----------- src/qt/languages/it-IT.po | 13 ++----------- src/qt/languages/ja-JP.po | 13 ++----------- src/qt/languages/ko-KR.po | 13 ++----------- src/qt/languages/nl-NL.po | 13 ++----------- src/qt/languages/pl-PL.po | 13 ++----------- src/qt/languages/pt-BR.po | 13 ++----------- src/qt/languages/pt-PT.po | 13 ++----------- src/qt/languages/ru-RU.po | 13 ++----------- src/qt/languages/sk-SK.po | 13 ++----------- src/qt/languages/sl-SI.po | 13 ++----------- src/qt/languages/sv-SE.po | 13 ++----------- src/qt/languages/tr-TR.po | 13 ++----------- src/qt/languages/uk-UA.po | 13 ++----------- src/qt/languages/vi-VN.po | 13 ++----------- src/qt/languages/zh-CN.po | 13 ++----------- src/qt/languages/zh-TW.po | 13 ++----------- src/qt/qt_mainwindow.cpp | 20 -------------------- src/qt/qt_progsettings.cpp | 2 -- src/qt/qt_progsettings.ui | 7 ------- 33 files changed, 51 insertions(+), 316 deletions(-) diff --git a/src/86box.c b/src/86box.c index 1d7a73060..25dc0e6e9 100644 --- a/src/86box.c +++ b/src/86box.c @@ -168,7 +168,6 @@ int vid_api = 0; /* (C) video r int vid_cga_contrast = 0; /* (C) video */ int video_fullscreen = 0; /* (C) video */ int video_fullscreen_scale = 0; /* (C) video */ -int video_fullscreen_first = 0; /* (C) video */ int enable_overscan = 0; /* (C) video */ int force_43 = 0; /* (C) video */ int video_filter_method = 1; /* (C) video */ diff --git a/src/config.c b/src/config.c index 52a80763a..dfe0190ac 100644 --- a/src/config.c +++ b/src/config.c @@ -128,8 +128,6 @@ load_general(void) video_fullscreen_scale = ini_section_get_int(cat, "video_fullscreen_scale", 1); - video_fullscreen_first = ini_section_get_int(cat, "video_fullscreen_first", 1); - video_filter_method = ini_section_get_int(cat, "video_filter_method", 1); inhibit_multimedia_keys = ini_section_get_int(cat, "inhibit_multimedia_keys", 0); @@ -1832,7 +1830,6 @@ config_load(void) gfxcard[0] = video_get_video_from_internal_name("cga"); vid_api = plat_vidapi("default"); vid_resize = 0; - video_fullscreen_first = 1; video_fullscreen_scale = 1; time_sync = TIME_SYNC_ENABLED; hdc_current[0] = hdc_get_from_internal_name("none"); @@ -1955,11 +1952,6 @@ save_general(void) else ini_section_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); - if (video_fullscreen_first == 1) - ini_section_delete_var(cat, "video_fullscreen_first"); - else - ini_section_set_int(cat, "video_fullscreen_first", video_fullscreen_first); - if (video_filter_method == 1) ini_section_delete_var(cat, "video_filter_method"); else diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index e19665535..76f311d17 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -121,7 +121,6 @@ extern int dpi_scale; /* (C) DPI scaling of the emulated s extern int vid_api; /* (C) video renderer */ extern int vid_cga_contrast; /* (C) video */ extern int video_fullscreen; /* (C) video */ -extern int video_fullscreen_first; /* (C) video */ extern int video_fullscreen_scale; /* (C) video */ extern int enable_overscan; /* (C) video */ extern int force_43; /* (C) video */ diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 1b50d86f8..bbcc94fe7 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -189,7 +189,6 @@ extern uint32_t pal_lookup[256]; #endif extern int video_fullscreen; extern int video_fullscreen_scale; -extern int video_fullscreen_first; extern uint8_t fontdat[2048][8]; extern uint8_t fontdatm[2048][16]; extern uint8_t fontdat2[2048][8]; diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index d5152cd3d..ac379b171 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -630,9 +630,6 @@ msgstr "" msgid " - PAUSED" msgstr "" -msgid "Press %1 to return to windowed mode." -msgstr "" - msgid "Speed" msgstr "" @@ -864,9 +861,6 @@ msgstr "" msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "" -msgid "Entering fullscreen mode" -msgstr "" - msgid "Don't show this message again" msgstr "" @@ -1305,7 +1299,7 @@ msgstr "" msgid "\nFalling back to software rendering." msgstr "" -msgid "<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>" +msgid "

    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.

    " msgstr "" msgid "This machine might have been moved or copied." @@ -2112,9 +2106,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 7fe87eb1a..632af979a 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -630,9 +630,6 @@ msgstr "Error fatal" msgid " - PAUSED" msgstr " - EN PAUSA" -msgid "Press %1 to return to windowed mode." -msgstr "Premeu %1 per tornar al mode de finestra." - msgid "Speed" msgstr "Velocitat" @@ -864,9 +861,6 @@ msgstr "%1 és necessària per a la conversió automàtica de fitxers PostScript msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 és necessària per a la conversió automàtica de fitxers PCL a PDF.\n\nQualsevol document enviat a la impressora genèrica PCL es desarà com a fitxer Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Entrant en mode pantalla completa" - msgid "Don't show this message again" msgstr "No mostreu més aquest missatge" @@ -1305,8 +1299,8 @@ msgstr "Error en inicialitzar OpenGL" msgid "\nFalling back to software rendering." msgstr "\nTornant al renderitzador software." -msgid "<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>" -msgstr "<html><head/><body><p>Quan seleccioneu imatges de suports (CD-ROM, disquet, etc.), el diàleg obert s’iniciarà al mateix directori que el fitxer de configuració 86Box. Aquesta configuració només farà una diferència en les macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Quan seleccioneu imatges de suports (CD-ROM, disquet, etc.), el diàleg obert s’iniciarà al mateix directori que el fitxer de configuració 86Box. Aquesta configuració només farà una diferència en les macOS.

    " msgid "This machine might have been moved or copied." msgstr "Aquesta màquina podria haver estat moguda o copiada." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 59a582ca6..593020962 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -630,9 +630,6 @@ msgstr "Kritická chyba" msgid " - PAUSED" msgstr " - POZASTAVENO" -msgid "Press %1 to return to windowed mode." -msgstr "Stiskněte %1 pro návrat z režimu celé obrazovky." - msgid "Speed" msgstr "Rychlost" @@ -864,9 +861,6 @@ msgstr "%1 je potřeba pro automatický převod PostScript dokumentů do PDF.\n\ msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 je potřeba pro automatický převod PCL dokumentů do PDF.\n\nJakékoliv dokumenty vytisknuté přes obecnou PCL-ovou tiskárnu budou uloženy jako Printer Command Language (.pcl) soubory." -msgid "Entering fullscreen mode" -msgstr "Vstup do režimu celé obrazovky" - msgid "Don't show this message again" msgstr "Nezobrazovat dále tuto zprávu" @@ -1305,8 +1299,8 @@ msgstr "Chyba při inicializaci OpenGL" msgid "\nFalling back to software rendering." msgstr "\nNávrat k softwarovému vykreslování." -msgid "<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>" -msgstr "<html><head/><body><p>Při výběru obrazů médií (CD-ROM, disketa atd.) se otevřené dialogové okno spustí ve stejném adresáři jako konfigurační soubor 86Box. Toto nastavení bude mít pravděpodobně význam pouze v systému MacOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Při výběru obrazů médií (CD-ROM, disketa atd.) se otevřené dialogové okno spustí ve stejném adresáři jako konfigurační soubor 86Box. Toto nastavení bude mít pravděpodobně význam pouze v systému MacOS.

    " msgid "This machine might have been moved or copied." msgstr "Tento počítač mohl být přemístěn nebo zkopírován." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 0615dada4..439346608 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -630,9 +630,6 @@ msgstr "Fataler Fehler" msgid " - PAUSED" msgstr " - PAUSIERT" -msgid "Press %1 to return to windowed mode." -msgstr "%1 ab, zur Rückkehr in den Fenstermodus." - msgid "Speed" msgstr "Geschwindigkeit" @@ -864,9 +861,6 @@ msgstr "%1 wird zur automatischen Konvertierung von PostScript-Dateien ins PDF-F msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 wird zur automatischen Konvertierung von PCL-Dateien ins PDF-Format benötigt.\n\nSämtliche an den generischen PCL-Drucker gesendete Dateien werden als Printer Command Language (*.pcl) Dateien gesichert." -msgid "Entering fullscreen mode" -msgstr "Vollbildmodus wird aktiviert" - msgid "Don't show this message again" msgstr "Diese Nachricht nicht mehr anzeigen" @@ -1305,8 +1299,8 @@ msgstr "Fehler beim Initialisieren von OpenGL" msgid "\nFalling back to software rendering." msgstr "\nRückgriff auf Software-Rendering." -msgid "<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>" -msgstr "<html><head/><body><p>Bei der Auswahl von Medien-Abbildern (CD-ROM, Diskette usw.) wird der Öffnungsdialog im selben Verzeichnis wie die 86Box-Konfigurationsdatei gestartet. Diese Einstellung macht wahrscheinlich nur unter macOS einen Unterschied.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Bei der Auswahl von Medien-Abbildern (CD-ROM, Diskette usw.) wird der Öffnungsdialog im selben Verzeichnis wie die 86Box-Konfigurationsdatei gestartet. Diese Einstellung macht wahrscheinlich nur unter macOS einen Unterschied.

    " msgid "This machine might have been moved or copied." msgstr "Dieses System wurde möglicherweise verschoben oder kopiert." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index 8cc29a71a..550bc3ab4 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -39,8 +39,8 @@ msgstr "Synchronise with video" msgid "Error initializing OpenGL" msgstr "Error initialising OpenGL" -msgid "<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>" -msgstr "<html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialogue will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    When selecting media images (CD-ROM, floppy, etc.) the open dialogue will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.

    " msgid "Color (generic)" msgstr "Colour (generic)" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 1f9cf10b2..363d56c45 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -630,9 +630,6 @@ msgstr "Error fatal" msgid " - PAUSED" msgstr " - EN PAUSA" -msgid "Press %1 to return to windowed mode." -msgstr "Pulsa %1 para volver a modo ventana." - msgid "Speed" msgstr "Velocidad" @@ -864,9 +861,6 @@ msgstr "%1 es necesaria para la conversión automática de archivos PostScript a msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 es necesaria para la conversión automática de archivos PCL a PDF.\n\nCualquier documento enviado a la impresora genérica PCL se guardará como archivo Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Entrando en modo pantalla completa" - msgid "Don't show this message again" msgstr "No mostrar más este mensaje" @@ -1304,8 +1298,8 @@ msgstr "Error al inicializar OpenGL" msgid "\nFalling back to software rendering." msgstr "\nRecurrir al renderizado por software." -msgid "<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>" -msgstr "<html><head/><body><p>Al seleccionar imágenes multimedia (CD-ROM, disquete, etc.), el diálogo de apertura se iniciará en el mismo directorio que el archivo de configuración de 86Box. Es probable que este ajuste sólo suponga una diferencia en macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Al seleccionar imágenes multimedia (CD-ROM, disquete, etc.), el diálogo de apertura se iniciará en el mismo directorio que el archivo de configuración de 86Box. Es probable que este ajuste sólo suponga una diferencia en macOS.

    " msgid "This machine might have been moved or copied." msgstr "Esta máquina puede haber sido movida o copiado." @@ -2105,9 +2099,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 4979332ac..ae4f78bb5 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -630,9 +630,6 @@ msgstr "Vakava virhe" msgid " - PAUSED" msgstr " - TAUKO" -msgid "Press %1 to return to windowed mode." -msgstr "Paina %1 palataksesi ikkunoituun tilaan." - msgid "Speed" msgstr "Nopeus" @@ -864,9 +861,6 @@ msgstr "%1 vaaditaan PostScript-tiedostojen automaattiseen muuntamiseen PDF-tied msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 vaaditaan PCL-tiedostojen automaattiseen muuntamiseen PDF-tiedostoiksi.\n\nKaikki geneeriselle PCL-tulostimelle lähetetyt asiakirjat tallennetaan Printer Command Language (.ps) -tiedostoina." -msgid "Entering fullscreen mode" -msgstr "Siirrytään koko näytön tilaan" - msgid "Don't show this message again" msgstr "Älä näytä tätä viestiä uudelleen" @@ -1308,8 +1302,8 @@ msgstr "Virhe OpenGL:n alustamisessa" msgid "\nFalling back to software rendering." msgstr "\nPaluu ohjelmistoalustusöintiin." -msgid "<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>" -msgstr "<html><head/><body><p>Kun valitset mediakuvia (CD-ROM, levykkeet jne.), avausikkuna käynnistyy samaan hakemistoon kuin 86Boxin konfigurointitiedosto. Tällä asetuksella on todennäköisesti merkitystä vain macOS-käyttöjärjestelmässä.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Kun valitset mediakuvia (CD-ROM, levykkeet jne.), avausikkuna käynnistyy samaan hakemistoon kuin 86Boxin konfigurointitiedosto. Tällä asetuksella on todennäköisesti merkitystä vain macOS-käyttöjärjestelmässä.

    " msgid "This machine might have been moved or copied." msgstr "Kone on saatettu siirtää tai kopioida." @@ -2109,9 +2103,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 58de2e4d1..87530590a 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -630,9 +630,6 @@ msgstr "Erreur fatale" msgid " - PAUSED" msgstr " - EN PAUSE" -msgid "Press %1 to return to windowed mode." -msgstr "Appuyez sur %1 pour revenir au mode fenêtré." - msgid "Speed" msgstr "Vitesse" @@ -864,9 +861,6 @@ msgstr "%1 est nécessaire pour la conversion automatique des fichiers PostScrip msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 est nécessaire pour la conversion automatique des fichiers PCL en PDF.\n\nTous les documents envoyés à l'imprimante générique PCL seront sauvés en tant quefichiers Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Entrer en mode plein écran" - msgid "Don't show this message again" msgstr "Ne pas montrer ce message à nouveau" @@ -1305,8 +1299,8 @@ msgstr "Erreur d'initialisation d'OpenGL" msgid "\nFalling back to software rendering." msgstr "\nSe rabattre sur le rendu logiciel." -msgid "<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>" -msgstr "<html><head/><body><p>Lors de la sélection d'images multimédia (CD-ROM, disquette, etc.), la boîte de dialogue d'ouverture démarrera dans le même répertoire que le fichier de configuration de 86Box. Ce paramètre ne fera probablement une différence que sur macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Lors de la sélection d'images multimédia (CD-ROM, disquette, etc.), la boîte de dialogue d'ouverture démarrera dans le même répertoire que le fichier de configuration de 86Box. Ce paramètre ne fera probablement une différence que sur macOS.

    " msgid "This machine might have been moved or copied." msgstr "Cette machine peut avoir été déplacée ou copiée." @@ -2106,9 +2100,6 @@ msgstr "Demander confirmation avant Hard Reset" msgid "Ask for confirmation before quitting" msgstr "Demander confirmation avant de quitter" -msgid "Display hotkey message when entering full-screen mode" -msgstr "Afficher Raccourcis Clavier avant de passer en plein écran" - msgid "Options" msgstr "Options" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 5f0e60b21..50dd298c2 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -630,9 +630,6 @@ msgstr "Fatalna greška" msgid " - PAUSED" msgstr " - ZASTAO" -msgid "Press %1 to return to windowed mode." -msgstr "Pritisnite %1 za povratak u prozorski način rada." - msgid "Speed" msgstr "Brzina" @@ -864,9 +861,6 @@ msgstr "%1 je potrebno za automatsku konverziju PostScript datoteke u PDF datote msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 je potrebno za automatsku konverziju PCL datoteke u PDF datoteke.\n\nSvi dokumenti poslani na generički PCL pisač bit će spremljeni kao Printer Command Language (.pcl) datoteke." -msgid "Entering fullscreen mode" -msgstr "Ulazim u cijelozaslonski način" - msgid "Don't show this message again" msgstr "Ne pokazi više ovu poruku" @@ -1305,8 +1299,8 @@ msgstr "Nije moguće inicijalizirati OpenGL" msgid "\nFalling back to software rendering." msgstr "\nVraća se na softverski renderer." -msgid "<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>" -msgstr "<html><head/><body><p>Prilikom odabira medijskih slika (CD-ROM, diskete itd.), otvoreni dijalog zopočet će u istom direktoriju kao i konfiguracijska datoteka 86Box-a. Razlika će vjerojatno biti primjetna samo na macOS-u.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Prilikom odabira medijskih slika (CD-ROM, diskete itd.), otvoreni dijalog zopočet će u istom direktoriju kao i konfiguracijska datoteka 86Box-a. Razlika će vjerojatno biti primjetna samo na macOS-u.

    " msgid "This machine might have been moved or copied." msgstr "Ovaj je sistem mogao biti premješten ili kopiran." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 3398859d2..981edad71 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -630,9 +630,6 @@ msgstr "Végzetes hiba" msgid " - PAUSED" msgstr " - SZÜNETELT" -msgid "Press %1 to return to windowed mode." -msgstr "Használja a %1 gombokat az ablakhoz való visszatéréshez." - msgid "Speed" msgstr "Sebesség" @@ -864,9 +861,6 @@ msgstr "%1 szükséges a PostScript fájlok PDF formátumba való automatikus ko msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Lnaugage (.pcl) files." msgstr "%1 szükséges a PCL fájlok PDF formátumba való automatikus konvertálásához.\n\nAz általános PCL nyomtatóra küldött dokumentumok Printer Command Language (.pcl) fájlként kerülnek mentésre." -msgid "Entering fullscreen mode" -msgstr "Teljes képernyős módra váltás" - msgid "Don't show this message again" msgstr "Ne jelenítse meg újra ezt az üzenetet " @@ -1305,8 +1299,8 @@ msgstr "Hiba az OpenGL inicializálásában" msgid "\nFalling back to software rendering." msgstr "\nVisszatérés a szoftveres rendereléshez." -msgid "<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>" -msgstr "<html><head/><body><p>A médiaképek (CD-ROM, floppy stb.) kiválasztásakor a megnyitási párbeszédpanel ugyanabban a könyvtárban indul, mint a 86Box konfigurációs fájl. Ez a beállítás valószínűleg csak a macOS rendszerben jelent különbséget.</p></body></html>" +msgid "

    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.

    " +msgstr "

    A médiaképek (CD-ROM, floppy stb.) kiválasztásakor a megnyitási párbeszédpanel ugyanabban a könyvtárban indul, mint a 86Box konfigurációs fájl. Ez a beállítás valószínűleg csak a macOS rendszerben jelent különbséget.

    " msgid "This machine might have been moved or copied." msgstr "Lehet, hogy ezt a gépet áthelyezték vagy lemásolták." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index d45a0080b..877032c85 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -630,9 +630,6 @@ msgstr "Errore fatale" msgid " - PAUSED" msgstr " - IN PAUSA" -msgid "Press %1 to return to windowed mode." -msgstr "Usa %1 per tornare alla modalità finestra." - msgid "Speed" msgstr "Velocità" @@ -864,9 +861,6 @@ msgstr "%1 è richiesto per la conversione automatica di file PostScript a file msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 è richiesto per la conversione automatica di file PCL a file PDF.\n\nQualsiasi documento mandato alla stampante generica PCL sarà salvato come file Printer Command Language (.cl)." -msgid "Entering fullscreen mode" -msgstr "Entrando nella modalità schermo intero" - msgid "Don't show this message again" msgstr "Non mostrare più questo messaggio" @@ -1305,8 +1299,8 @@ msgstr "Errore nell'inizializzazione di OpenGL" msgid "\nFalling back to software rendering." msgstr "\nRicaduta sul rendering software." -msgid "<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>" -msgstr "<html><head/><body><p>Quando si selezionano immagini multimediali (CD-ROM, floppy, ecc.) la finestra di dialogo di apertura si avvia nella stessa directory del file di configurazione di 86Box. Questa impostazione probabilmente farà la differenza solo su macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Quando si selezionano immagini multimediali (CD-ROM, floppy, ecc.) la finestra di dialogo di apertura si avvia nella stessa directory del file di configurazione di 86Box. Questa impostazione probabilmente farà la differenza solo su macOS.

    " msgid "This machine might have been moved or copied." msgstr "Questa macchina potrebbe essere stata spostata o copiata." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 7883f8a5a..5efd599ed 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -630,9 +630,6 @@ msgstr "致命的なエラー" msgid " - PAUSED" msgstr " - 一時停止" -msgid "Press %1 to return to windowed mode." -msgstr "%1でウィンドウ モードに戻ります。" - msgid "Speed" msgstr "速度" @@ -864,9 +861,6 @@ msgstr "PostScriptファイルをPDFに自動変換するには%1が必要です msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "PCLファイルをPDFに自動変換するには%1が必要です。\n\n汎用PCLプリンターに送信された文書は、Printer Command Language (.pcl) ファイルとして保存されます。" -msgid "Entering fullscreen mode" -msgstr "全画面モードを入力" - msgid "Don't show this message again" msgstr "今後、このメッセージを表示しない" @@ -1305,8 +1299,8 @@ msgstr "OpenGLの初期化エラー" msgid "\nFalling back to software rendering." msgstr "\nソフトウェアレンダリングに逆戻り。" -msgid "<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>" -msgstr "<html><head/><body><p>メディアイメージ(CD-ROM、フロッピーなど)を選択するとき、オープンダイアログは86Box設定ファイルと同じディレクトリで開始します。この設定は、おそらく macOS でのみ違いがあります。</p></body></html>" +msgid "

    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.

    " +msgstr "

    メディアイメージ(CD-ROM、フロッピーなど)を選択するとき、オープンダイアログは86Box設定ファイルと同じディレクトリで開始します。この設定は、おそらく macOS でのみ違いがあります。

    " msgid "This machine might have been moved or copied." msgstr "このマシンは移動されたかコピーされた可能性がある。" @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index a9ed452d6..89dbf5809 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -630,9 +630,6 @@ msgstr "치명적인 오류" msgid " - PAUSED" msgstr " - 일시 중지됨" -msgid "Press %1 to return to windowed mode." -msgstr "%1 키를 누르면 창 모드로 전환합니다." - msgid "Speed" msgstr "속도" @@ -864,9 +861,6 @@ msgstr "%1은(는) PostScript 파일을 PDF로 자동변환하는 데에 필요 msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1은(는) PCL 파일을 PDF로 자동변환하는 데에 필요합니다.\n\n표준 PCL 프린터로 보내신 임의의 문서는 Printer Command Language (.pcl) 파일로 저장됩니다." -msgid "Entering fullscreen mode" -msgstr "전체 화면으로 전환" - msgid "Don't show this message again" msgstr "이 메시지 그만 보기" @@ -1305,8 +1299,8 @@ msgstr "OpenGL 초기화 중 오류 발생" msgid "\nFalling back to software rendering." msgstr "\n소프트웨어 렌더링으로 돌아가기." -msgid "<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>" -msgstr "<html><head/><body><p>미디어 이미지(CD-ROM, 플로피 등)를 선택하면 86Box 구성 파일과 동일한 디렉터리에서 열기 대화 상자가 시작됩니다. 이 설정은 macOS에서만 차이가 있을 수 있습니다.</p></body></html>" +msgid "

    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.

    " +msgstr "

    미디어 이미지(CD-ROM, 플로피 등)를 선택하면 86Box 구성 파일과 동일한 디렉터리에서 열기 대화 상자가 시작됩니다. 이 설정은 macOS에서만 차이가 있을 수 있습니다.

    " msgid "This machine might have been moved or copied." msgstr "이 컴퓨터가 이동되었거나 복사되었을 수 있습니다." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 2859916d7..aa87cd37d 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -630,9 +630,6 @@ msgstr "Fatale fout" msgid " - PAUSED" msgstr " - GEPAUZEERD" -msgid "Press %1 to return to windowed mode." -msgstr "Druk op %1 om terug te gaan naar de venstermodus." - msgid "Speed" msgstr "Snelheid" @@ -864,9 +861,6 @@ msgstr "%1 is vereist voor automatische conversie van PostScript-bestanden naar msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 is vereist voor automatische conversie van PCL-bestanden naar PDF.\n\nAlle documenten die naar de generieke PCL-printer worden gestuurd, worden opgeslagen als Printer Command Language (.pcl) bestanden." -msgid "Entering fullscreen mode" -msgstr "Volledig scherm modus openen" - msgid "Don't show this message again" msgstr "Dit bericht niet meer tonen" @@ -1305,8 +1299,8 @@ msgstr "Fout bij het initialiseren van OpenGL" msgid "\nFalling back to software rendering." msgstr "\nTerugvallen op software rendering." -msgid "<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>" -msgstr "<html><head/><body><p>Bij het selecteren van media-images (CD-ROM, floppy, etc.) zal de \"open dialoog\" starten in dezelfde map als het 86Box configuratiebestand. Deze instelling is doet er waarschijnlijk alleen toe op macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Bij het selecteren van media-images (CD-ROM, floppy, etc.) zal de \"open dialoog\" starten in dezelfde map als het 86Box configuratiebestand. Deze instelling is doet er waarschijnlijk alleen toe op macOS.

    " msgid "This machine might have been moved or copied." msgstr "Deze machine is misschien verplaatst of gekopieerd." @@ -2106,9 +2100,6 @@ msgstr "Vraag om bevestiging voor een harde reset" msgid "Ask for confirmation before quitting" msgstr "Vraag om bevestiging voor afsluiten" -msgid "Display hotkey message when entering full-screen mode" -msgstr "Toon een sneltoetsmelding bij het openen van de volledigschermmodus" - msgid "Options" msgstr "Opties" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 02bdc26fe..7433c1d65 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -630,9 +630,6 @@ msgstr "Fatalny błąd" msgid " - PAUSED" msgstr " - PAUSED" -msgid "Press %1 to return to windowed mode." -msgstr "Naciśnij klawisze %1 aby wrócić to trybu okna." - msgid "Speed" msgstr "Szybkość" @@ -864,9 +861,6 @@ msgstr "%1 jest wymagany do automatycznej konwersji plików PostScript do PDF.\n msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 jest wymagany do automatycznej konwersji plików PCL do PDF.\n\nDokumenty wysłane do generycznej drukarki PCL zostaną zapisane jako pliki Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Przechodzenie do trybu pełnoekranowego" - msgid "Don't show this message again" msgstr "Nie pokazuj więcej tego komunikatu" @@ -1305,8 +1299,8 @@ msgstr "Błąd inicjalizacji OpenGL" msgid "\nFalling back to software rendering." msgstr "\nPowrót do renderowania oprogramowania." -msgid "<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>" -msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itp.) otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Podczas wybierania obrazów nośników (CD-ROM, dyskietka itp.) otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.

    " msgid "This machine might have been moved or copied." msgstr "To urządzenie mogło zostać przeniesione lub skopiowane." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 4fb974f4d..70e6d7b29 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -630,9 +630,6 @@ msgstr "Erro fatal" msgid " - PAUSED" msgstr " - PAUSADO" -msgid "Press %1 to return to windowed mode." -msgstr "Use %1 para retornar ao modo janela." - msgid "Speed" msgstr "Velocidade" @@ -864,9 +861,6 @@ msgstr "%1 é necessário para a conversão automática de arquivos PostScript p msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 é necessário para a conversão automática de arquivos PCL para PDF.\n\nQualquer documento enviado para a impressora genérica PCL será salvo como arquivos Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Entrando no modo de tela cheia" - msgid "Don't show this message again" msgstr "Não exibir esta mensagem novamente" @@ -1305,8 +1299,8 @@ msgstr "Erro ao inicializar o OpenGL" msgid "\nFalling back to software rendering." msgstr "\nVoltando à renderização de software." -msgid "<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>" -msgstr "<html><head/><body><p>Ao selecionar imagens de mídia (CD-ROM, disquete, etc.), a caixa de diálogo de abertura será iniciada no mesmo diretório do arquivo de configuração do 86Box. Essa configuração provavelmente só fará diferença no macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Ao selecionar imagens de mídia (CD-ROM, disquete, etc.), a caixa de diálogo de abertura será iniciada no mesmo diretório do arquivo de configuração do 86Box. Essa configuração provavelmente só fará diferença no macOS.

    " msgid "This machine might have been moved or copied." msgstr "Essa máquina pode ter sido movida ou copiada." @@ -2106,9 +2100,6 @@ msgstr "Perguntar antes de reinicialização completa" msgid "Ask for confirmation before quitting" msgstr "Perguntar antes de sair" -msgid "Display hotkey message when entering full-screen mode" -msgstr "Mostrar mensagem de atalho quando entrar em tela cheia" - msgid "Options" msgstr "Opções" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 86c40fc40..795d44e2b 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -630,9 +630,6 @@ msgstr "Erro fatal" msgid " - PAUSED" msgstr " - EM PAUSA" -msgid "Press %1 to return to windowed mode." -msgstr "Pressione %1 para voltar ao modo de janela." - msgid "Speed" msgstr "Velocidade" @@ -864,9 +861,6 @@ msgstr "%1 é requerido para a conversão automática de ficheiros PostScript pa msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 é requerido para a conversão automática de ficheiros PCL para ficheiros PDF.\n\nQualquer documento enviado para a impressora PCL genérica será gravado como um ficheiro Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "A entrar no modo de tela cheia" - msgid "Don't show this message again" msgstr "Não mostrar mais esta mensagem" @@ -1305,8 +1299,8 @@ msgstr "Erro ao inicializar o OpenGL" msgid "\nFalling back to software rendering." msgstr "\nRecuando para a renderização de software." -msgid "<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>" -msgstr "<html><head/><body><p>Ao selecionar imagens multimédia (CD-ROM, disquete, etc.) a caixa de diálogo de abertura irá começar no mesmo diretório que o ficheiro de configuração da 86Box. Esta configuração provavelmente só fará diferença no macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Ao selecionar imagens multimédia (CD-ROM, disquete, etc.) a caixa de diálogo de abertura irá começar no mesmo diretório que o ficheiro de configuração da 86Box. Esta configuração provavelmente só fará diferença no macOS.

    " msgid "This machine might have been moved or copied." msgstr "Esta máquina pode ter sido deslocada ou copiada." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 899b905ac..af427d670 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -630,9 +630,6 @@ msgstr "Неустранимая ошибка" msgid " - PAUSED" msgstr " - ПАУЗА" -msgid "Press %1 to return to windowed mode." -msgstr "Нажмите %1 для возврата в оконный режим." - msgid "Speed" msgstr "Скорость" @@ -864,9 +861,6 @@ msgstr "Для автоматического преобразования фа msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "Для автоматического преобразования файлов PCL в PDF требуется %1.\n\nВсе документы, отправленные на стандартный принтер PCL, будут сохранены в виде файлов Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Вход в полноэкранный режим" - msgid "Don't show this message again" msgstr "Больше не показывать это сообщение" @@ -1305,8 +1299,8 @@ msgstr "Ошибка инициализации OpenGL" msgid "\nFalling back to software rendering." msgstr "\nПереключение на программный рендеринг." -msgid "<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>" -msgstr "<html><head/><body><p>При выборе образов носителей (CD-ROM, дискет и т. д.) диалог открытия будет запускаться в том же каталоге, что и файл конфигурации 86Box. Эта настройка, скорее всего, будет иметь значение только на macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    При выборе образов носителей (CD-ROM, дискет и т. д.) диалог открытия будет запускаться в том же каталоге, что и файл конфигурации 86Box. Эта настройка, скорее всего, будет иметь значение только на macOS.

    " msgid "This machine might have been moved or copied." msgstr "Возможно, эта машина была перемещена или скопирована." @@ -2112,9 +2106,6 @@ msgstr "Запрашивать подтверждение перед холод msgid "Ask for confirmation before quitting" msgstr "Запрашивать подтверждение перед выходом" -msgid "Display hotkey message when entering full-screen mode" -msgstr "Показывать сообщение о горячей клавише при входе в полноэкранный режим" - msgid "Options" msgstr "Параметры" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 624715f76..ef89f831a 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -630,9 +630,6 @@ msgstr "Kritická chyba" msgid " - PAUSED" msgstr " - POZASTAVENÝ" -msgid "Press %1 to return to windowed mode." -msgstr "Stlačte %1 pre návrat z režimu celej obrazovky." - msgid "Speed" msgstr "Rýchlosť" @@ -864,9 +861,6 @@ msgstr "%1 je potrebná pre automatický prevod PostScript dokumentov do PDF.\n\ msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Lnaugage (.pcl) files." msgstr "%1 je potrebná pre automatický prevod PCL dokumentov do PDF.\n\nAkékoľvek dokumenty vytlačené cez všeobecnú PCLovú tlačiareň budú uložené ako Printer Command Language (.pcl) súbory." -msgid "Entering fullscreen mode" -msgstr "Vstup do režimu celej obrazovky" - msgid "Don't show this message again" msgstr "Nezobrazovať ďalej túto správu" @@ -1306,8 +1300,8 @@ msgstr "Chyba pri inicializácii OpenGL" msgid "\nFalling back to software rendering." msgstr "\nNávrat k softvérovému vykresľovaniu." -msgid "<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>" -msgstr "<html><head/><body><p>Pri výbere multimediálnych obrazov (CD-ROM, disketa atď.) sa dialógové okno otvorenia spustí v rovnakom adresári ako konfiguračný súbor 86Box. Toto nastavenie bude mať pravdepodobne význam len v systéme MacOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Pri výbere multimediálnych obrazov (CD-ROM, disketa atď.) sa dialógové okno otvorenia spustí v rovnakom adresári ako konfiguračný súbor 86Box. Toto nastavenie bude mať pravdepodobne význam len v systéme MacOS.

    " msgid "This machine might have been moved or copied." msgstr "Tento stroj mohol byť premiestnený alebo skopírovaný." @@ -2107,9 +2101,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index d07a1eac4..d4fd10e43 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -630,9 +630,6 @@ msgstr "Kritična napaka" msgid " - PAUSED" msgstr " - ZAUSTAVLJEN" -msgid "Press %1 to return to windowed mode." -msgstr "Pritisnite %1 za povratek iz celozaslonskega načina." - msgid "Speed" msgstr "Hitrost" @@ -864,9 +861,6 @@ msgstr "%1 je potreben za samodejno pretvorbo datotek PostScript v PDF.\n\nVsi d msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Lnaugage (.pcl) files." msgstr "%1 je potreben za samodejno pretvorbo datotek PCL v PDF.\n\nVsi dokumenti, poslani generičnemu tiskalniku PCL bodo shranjeni kot datoteke Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Preklapljam v celozaslonski način" - msgid "Don't show this message again" msgstr "Ne pokaži več tega sporočila" @@ -1305,8 +1299,8 @@ msgstr "Napaka pri inicializaciji OpenGL" msgid "\nFalling back to software rendering." msgstr "\nVrnitev na programsko upodabljanje." -msgid "<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>" -msgstr "<html><head/><body><p>Pri izbiri medijskih slik (CD-ROM, disketa itd.) se bo odprto pogovorno okno začelo v istem imeniku kot konfiguracijska datoteka 86Box. Ta nastavitev bo verjetno imela pomen le v operacijskem sistemu MacOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Pri izbiri medijskih slik (CD-ROM, disketa itd.) se bo odprto pogovorno okno začelo v istem imeniku kot konfiguracijska datoteka 86Box. Ta nastavitev bo verjetno imela pomen le v operacijskem sistemu MacOS.

    " msgid "This machine might have been moved or copied." msgstr "Ta naprava je bila morda premeščena ali kopirana." @@ -2106,9 +2100,6 @@ msgstr "Vprašaj za potrditev pred ponovnim zagonom" msgid "Ask for confirmation before quitting" msgstr "Vprašaj za potrditev pred izhodom" -msgid "Display hotkey message when entering full-screen mode" -msgstr "Prikaži obvestilo o bližnjični tipki pri prehodu v celozaslonski način" - msgid "Options" msgstr "Možnosti" diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index e33dbfe21..efbfab7eb 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -630,9 +630,6 @@ msgstr "Allvarligt fel" msgid " - PAUSED" msgstr " - PAUSAD" -msgid "Press %1 to return to windowed mode." -msgstr "Tryck på %1 för att återvända till fönsterläge." - msgid "Speed" msgstr "Hastighet" @@ -864,9 +861,6 @@ msgstr "%1 krävs för automatisk omvandling av PostScript-filer till PDF.\n\nAl msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 krävs för automatisk omvandling av PCL-filer till PDF.\n\nAlla dokument som skickas till den allmänna PCL-skrivaren kommer att sparas som Printer Command Language-filer (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Startar helskärmsläge" - msgid "Don't show this message again" msgstr "Visa inte detta meddelande igen" @@ -1305,8 +1299,8 @@ msgstr "Fel vid initialisering av OpenGL" msgid "\nFalling back to software rendering." msgstr "\nFaller tillbaka på mjukvarurendering." -msgid "<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>" -msgstr "<html><head/><body><p>Vid val av medieavbildningar (CD-ROM, diskett, osv.) så kommer fönstret att börja i samma mapp som 86Box konfigurationsfil. Denna inställning kommer troligtvis endast göra en skillnad på macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Vid val av medieavbildningar (CD-ROM, diskett, osv.) så kommer fönstret att börja i samma mapp som 86Box konfigurationsfil. Denna inställning kommer troligtvis endast göra en skillnad på macOS.

    " msgid "This machine might have been moved or copied." msgstr "Denna maskin kan ha flyttats eller kopierats." @@ -2112,9 +2106,6 @@ msgstr "Bekräfta innan hård omstart" msgid "Ask for confirmation before quitting" msgstr "Bekräfta innan avslut" -msgid "Display hotkey message when entering full-screen mode" -msgstr "Visa meddelande om snabbtangenter när helskärmsläget startas" - msgid "Options" msgstr "Alternativ" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 24c1c0ba0..73d46a007 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -630,9 +630,6 @@ msgstr "Kritik hata" msgid " - PAUSED" msgstr " - DURAKLATILDI" -msgid "Press %1 to return to windowed mode." -msgstr "Pencere moduna geri dönmek için %1 tuşlarına basın." - msgid "Speed" msgstr "Hız" @@ -864,9 +861,6 @@ msgstr "%1 PostScript dosyalarının otomatik olarak PDF dosyalarına çevirilme msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 PCL dosyalarının otomatik olarak PDF dosyalarına çevirilmesi için gereklidir.\n\nBu bulunmadığından dolayı genel PostScript yazıcısına gönderilen tüm dökümanlar Printer Command Language (.pcl) dosyası olarak kaydedilecektir." -msgid "Entering fullscreen mode" -msgstr "Tam ekran moduna geçiş yapılıyor" - msgid "Don't show this message again" msgstr "Bu mesajı bir daha gösterme" @@ -1305,8 +1299,8 @@ msgstr "OpenGL başlatılırken hata oluştu" msgid "\nFalling back to software rendering." msgstr "\nYazılım işleyicisine geri dönülüyor." -msgid "<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>" -msgstr "<html><head/><body><p>Medya görüntüsü (CD-ROM, disket, vb.) seçme diyaloğu 86Box yapılandırma dosyasıyla aynı dizinde başlayacaktır. Bu ayar muhtemelen sadece macOS üzerinde bir fark meydana getirecektir.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Medya görüntüsü (CD-ROM, disket, vb.) seçme diyaloğu 86Box yapılandırma dosyasıyla aynı dizinde başlayacaktır. Bu ayar muhtemelen sadece macOS üzerinde bir fark meydana getirecektir.

    " msgid "This machine might have been moved or copied." msgstr "Bu makine taşınmış veya kopyalanmış olabilir." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 68b50771a..49a8acf00 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -630,9 +630,6 @@ msgstr "Непереробна помилка" msgid " - PAUSED" msgstr " - ПРИЗУПИНЕННЯ" -msgid "Press %1 to return to windowed mode." -msgstr "Натисніть %1 для повернення у віконний режим." - msgid "Speed" msgstr "Швидкість" @@ -864,9 +861,6 @@ msgstr "%1 потрібно для автоматичного перетворе msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 потрібно для автоматичного перетворення файлів PCL в PDF.\n\nВсі документи, відправлені на загальний принтер PCL, будуть збережені у вигляді файлів Printer Command Language (.ps)." -msgid "Entering fullscreen mode" -msgstr "Вхід у повноекранний режим" - msgid "Don't show this message again" msgstr "Більше не показувати це повідомлення" @@ -1305,8 +1299,8 @@ msgstr "Помилка ініціалізації OpenGL" msgid "\nFalling back to software rendering." msgstr "\nПовернення до програмного рендерингу." -msgid "<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>" -msgstr "<html><head/><body><p>При виборі медіа-образів (CD-ROM, дискета і т.д.) діалогове вікно буде відкриватися в тому ж каталозі, що і файл конфігурації 86Box. Цей параметр, швидше за все, матиме значення лише на macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    При виборі медіа-образів (CD-ROM, дискета і т.д.) діалогове вікно буде відкриватися в тому ж каталозі, що і файл конфігурації 86Box. Цей параметр, швидше за все, матиме значення лише на macOS.

    " msgid "This machine might have been moved or copied." msgstr "Цю машину могли перемістити або скопіювати." @@ -2112,9 +2106,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 8632234df..9fed36393 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -630,9 +630,6 @@ msgstr "Lỗi nghiêm trọng" msgid " - PAUSED" msgstr " - TẠM DỪNG" -msgid "Press %1 to return to windowed mode." -msgstr "Bấm %1 để quay lại chế độ cửa sổ." - msgid "Speed" msgstr "Vận tốc" @@ -864,9 +861,6 @@ msgstr "Cần có %1 để tự động chuyển đổi file PostScript qua PDF. msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "Cần có %1 để tự động chuyển đổi file PCL qua PDF.\n\nMọi tài liệu được đưa qua máy in generic PCL sẽ lưu ở dạng Printer Command Language (.pcl)." -msgid "Entering fullscreen mode" -msgstr "Đang tiến vào chế độ toàn màn hình" - msgid "Don't show this message again" msgstr "Không hiện thông báo này nữa" @@ -1305,8 +1299,8 @@ msgstr "Lỗi khởi tạo OpenGL" msgid "\nFalling back to software rendering." msgstr "\nQuay trở lại kết xuất phần mềm." -msgid "<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>" -msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>" +msgid "

    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.

    " +msgstr "

    Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.

    " msgid "This machine might have been moved or copied." msgstr "Cấu hình máy này có thể đã được di chuyển hoặc sao chép." @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 194db4f3d..d2ed7ce71 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -630,9 +630,6 @@ msgstr "致命错误" msgid " - PAUSED" msgstr " - 已暂停" -msgid "Press %1 to return to windowed mode." -msgstr "按下 %1 返回到窗口模式。" - msgid "Speed" msgstr "速度" @@ -864,9 +861,6 @@ msgstr "%1 是将 PostScript 文件转换为 PDF 所需要的库。\n\n使用通 msgid "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files." msgstr "%1 是将 PCL 文件转换为 PDF 所需要的库。\n\n使用通用 PCL 打印机打印的文档将被保存为 Printer Command Language (.pcl) 文件。" -msgid "Entering fullscreen mode" -msgstr "正在进入全屏模式" - msgid "Don't show this message again" msgstr "不要再显示此消息" @@ -1305,8 +1299,8 @@ msgstr "初始化 OpenGL 时出错" msgid "\nFalling back to software rendering." msgstr "\n回到软件渲染。" -msgid "<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>" -msgstr "<html><head/><body><p>选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。</p></body></html>;" +msgid "

    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.

    " +msgstr "

    选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

    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.

    " +msgstr "

    當選擇媒體映像 (CD-ROM、軟碟等) 時,開啟對話方塊會在與 86Box 設定檔相同的目錄中開始。此設定可能只會在 macOS 上有所影響。

    " msgid "This machine might have been moved or copied." msgstr "這台機器可能已被移動或複製。" @@ -2106,9 +2100,6 @@ msgstr "" msgid "Ask for confirmation before quitting" msgstr "" -msgid "Display hotkey message when entering full-screen mode" -msgstr "" - msgid "Options" msgstr "" diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 9148abea1..bb28b47ee 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1345,26 +1345,6 @@ MainWindow::on_actionFullscreen_triggered() emit resizeContents(vid_resize == 2 ? fixed_size_x : monitors[0].mon_scrnsz_x, vid_resize == 2 ? fixed_size_y : monitors[0].mon_scrnsz_y); } } else { - if (video_fullscreen_first) { - bool wasCaptured = mouse_capture == 1; - - QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), - tr("Press %1 to return to windowed mode.").arg(QKeySequence(acc_keys[FindAccelerator("fullscreen")].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText)), - QMessageBox::Ok, this); - QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); - questionbox.setCheckBox(chkbox); - chkbox->setChecked(!video_fullscreen_first); - - QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) { - video_fullscreen_first = (state == Qt::CheckState::Unchecked); - }); - questionbox.exec(); - config_save(); - - /* (re-capture mouse after dialog). */ - if (wasCaptured) - emit setMouseCapture(true); - } video_fullscreen = 1; setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); ui->menubar->hide(); diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 4894b99c0..825689e78 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -96,7 +96,6 @@ ProgSettings::ProgSettings(QWidget *parent) 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); @@ -111,7 +110,6 @@ ProgSettings::accept() 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() ? 1 : 0; loadTranslators(QCoreApplication::instance()); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index b01199dfd..6020efd77 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -165,13 +165,6 @@
    - - - - Display hotkey message when entering full-screen mode - - -
    From 04a92704d1b351cd7f1292f879e38e76b28ad6ec Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 19:42:18 +0200 Subject: [PATCH 0878/1190] And the PS/ValuePoint P60 as well. --- src/machine/m_at_socket4.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 03ff03a23..30da4e299 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -266,7 +266,8 @@ machine_at_valuepointp60_init(const machine_t *model) pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ps1_pci_device); device_add(&sio_device); - device_add(&fdc37c665_device); + device_add(&ide_rz1000_pci_single_channel_device); + device_add(&fdc37c665_ide_sec_device); device_add(&intel_flash_bxt_ami_device); device_add(&i430lx_device); From baba4b704f38ea9368e23fd1b4e9e3593288d9f1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 19:49:03 +0200 Subject: [PATCH 0879/1190] PS/ValuePoint P60: Only primary IDE, in accordance with the IBM hardware reference. --- src/machine/m_at_socket4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 30da4e299..88474d431 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -254,7 +254,7 @@ machine_at_valuepointp60_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -267,7 +267,7 @@ machine_at_valuepointp60_init(const machine_t *model) device_add(&keyboard_ps2_ps1_pci_device); device_add(&sio_device); device_add(&ide_rz1000_pci_single_channel_device); - device_add(&fdc37c665_ide_sec_device); + device_add(&fdc37c665_device); device_add(&intel_flash_bxt_ami_device); device_add(&i430lx_device); From 5fcef3713d97985de56afbb10412eb4b2d2291df Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 May 2025 00:28:25 +0600 Subject: [PATCH 0880/1190] Add missing tooltips for keyboard lock icons --- src/qt/qt_mainwindow.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index bb28b47ee..3a0f1cb8a 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -198,18 +198,22 @@ MainWindow::MainWindow(QWidget *parent) num_label = new QLabel; num_label->setPixmap(num_icon_off.pixmap(QSize(16, 16))); + num_label->setToolTip(QShortcut::tr("Num Lock")); statusBar()->addPermanentWidget(num_label); caps_label = new QLabel; caps_label->setPixmap(caps_icon_off.pixmap(QSize(16, 16))); + caps_label->setToolTip(QShortcut::tr("Caps Lock")); statusBar()->addPermanentWidget(caps_label); scroll_label = new QLabel; scroll_label->setPixmap(scroll_icon_off.pixmap(QSize(16, 16))); + scroll_label->setToolTip(QShortcut::tr("Scroll Lock")); statusBar()->addPermanentWidget(scroll_label); kana_label = new QLabel; kana_label->setPixmap(kana_icon_off.pixmap(QSize(16, 16))); + kana_label->setToolTip(QShortcut::tr("Kana Lock")); statusBar()->addPermanentWidget(kana_label); QTimer* ledKeyboardTimer = new QTimer(this); @@ -1507,9 +1511,13 @@ MainWindow::refreshMediaMenu() ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled); + num_label->setToolTip(QShortcut::tr("Num Lock")); num_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + scroll_label->setToolTip(QShortcut::tr("Scroll Lock")); scroll_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + caps_label->setToolTip(QShortcut::tr("Caps Lock")); caps_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD)); + kana_label->setToolTip(QShortcut::tr("Kana Lock")); kana_label->setVisible(machine_has_bus(machine, MACHINE_BUS_PS2_PORTS | MACHINE_BUS_AT_KBD) && machine_has_flags(machine, MACHINE_AX)); } From 2becc6fa600af8fa705d09884dc1c070a0e46739 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 7 May 2025 21:27:20 +0200 Subject: [PATCH 0881/1190] P54NP4 fixes of the evening (May 7th, 2025) 1. The 430NX does support PCI IRQ steering, fix it accordingly. 2. Reorder the number of the slots. 3. Add the SIO ZB device to said machine as it must have one. 4. Remove the onboard 810 SCSI controller. --- src/machine/m_at_socket5.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 0d748b85e..4b3bbd49c 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -110,19 +110,19 @@ machine_at_p54np4_init(const machine_t *model) return ret; machine_at_common_init(model); + device_add(&ide_vlb_2ch_device); - pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_init(PCI_CONFIG_TYPE_2 | PCI_CAN_SWITCH_TYPE); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ - pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 06 = Slot 1 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 05 = Slot 2 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 04 = Slot 3 */ + pci_register_slot(0x03, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 03 = Slot 4 */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430nx_device); + device_add(&sio_zb_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c665_ide_pri_device); - device_add(&ncr53c810_onboard_pci_device); device_add(&intel_flash_bxt_device); return ret; From e6a41921cf6e2f86b7ccb55f70ecfe2d21678e9a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 7 May 2025 21:40:22 +0200 Subject: [PATCH 0882/1190] Fix mono pattern position in the Mach64 cards using 24bpp mode (May 7th, 2025) See above. --- src/video/vid_ati_mach64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 4ec9afff8..026634cf2 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -1670,7 +1670,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) case MONO_SRC_PAT: if (mach64->dst_cntl & DST_24_ROT_EN) { if (!mach64->accel.xx_count) - mix = mach64->accel.pattern[dst_y & 7][dst_x & 7]; + mix = mach64->accel.pattern[dst_y & 7][(dst_x / 3) & 7]; } else mix = mach64->accel.pattern[dst_y & 7][dst_x & 7]; break; From 304a47c1bb1744809e2047e9a36508aef9f8c546 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Wed, 7 May 2025 22:49:05 +0200 Subject: [PATCH 0883/1190] Add files via upload --- src/video/vid_et4000w32.c | 160 +++++++++++++++++++++++++++++++------- 1 file changed, 133 insertions(+), 27 deletions(-) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 246decb9c..c772ffdd9 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -43,8 +43,11 @@ #define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" #define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" #define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.bin" +#define BIOS_ROM_PATH_W32P_IMASCAN_VLB "roms/video/et4000w32/tseng_et4000w32p-8.03.bin" +#define BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB "roms/video/et4000w32/m27c256b-at-dip28-miro20td-675dada18e7fa701369657.bin" #define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" #define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" +#define BIOS_ROM_PATH_W32P_REVCD_ONBOARD "roms/video/et4000w32/vid.BIN" #define ACL_WRST 1 #define ACL_RDST 2 @@ -55,7 +58,10 @@ enum { ET4000W32, ET4000W32I, ET4000W32P_REVC, + ET4000W32P_REVCD_ONBOARD, ET4000W32P_VIDEOMAGIC_REVB, + ET4000W32P_IMASCAN_VLB, + ET4000W32P_MIROVIDEO20TD_VLB, ET4000W32P, ET4000W32P_CARDEX, ET4000W32P_DIAMOND @@ -178,7 +184,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); else stg_ramdac_out(addr, val, svga->ramdac, svga); @@ -302,13 +308,13 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) if (svga->hwcursor.cur_xsize == 128) { svga->hwcursor.xoff &= 0x7f; svga->hwcursor.yoff &= 0x7f; - if (et4000->type > ET4000W32P_REVC) { + if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if (svga->bpp == 24) { et4000->adjust_cursor = 2; } } } else { - if (et4000->type > ET4000W32P_REVC) { + if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if ((svga->bpp == 24) && et4000->adjust_cursor) { et4000->adjust_cursor = 0; } @@ -348,7 +354,7 @@ et4000w32p_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) return sdac_ramdac_in(addr, 0, svga->ramdac, svga); else return stg_ramdac_in(addr, svga->ramdac, svga); @@ -503,8 +509,8 @@ et4000w32p_recalctimings(svga_t *svga) svga->hdisp >>= 1; svga->dots_per_clock >>= 1; } - if (et4000->type <= ET4000W32P_REVC) { - if (et4000->type == ET4000W32P_REVC) { + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type == ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if (svga->hdisp != 1024) et4000->adjust_cursor = 1; } else @@ -514,7 +520,7 @@ et4000w32p_recalctimings(svga_t *svga) case 24: svga->hdisp /= 3; svga->dots_per_clock /= 3; - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { svga->hdisp = 640; @@ -548,7 +554,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 0x40: case 0x60: /* 256+ colours */ - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) svga->clock /= 2; switch (svga->bpp) { @@ -729,13 +735,13 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | (val << 8); break; case 0x8e: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->acl.queued.pixel_depth = val & 0x30; else et4000->acl.queued.vbus = val & 0x03; break; case 0x8f: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->acl.queued.xy_dir = val & 0xb7; else et4000->acl.queued.xy_dir = val & 0x03; @@ -759,7 +765,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | (val << 8); break; case 0x9c: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->acl.queued.ctrl_routing = val & 0xdb; else et4000->acl.queued.ctrl_routing = val & 0xb7; @@ -785,7 +791,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) case 0xa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24); et4000->acl.internal = et4000->acl.queued; - if (et4000->type >= ET4000W32P_REVC) { + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { et4000w32p_blit_start(et4000); et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); if (!(et4000->acl.queued.ctrl_routing & 0x43)) { @@ -849,7 +855,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) static void et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank) { - if (et4000->type >= ET4000W32P_REVC) { + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if (!(et4000->acl.status & ACL_XYST)) { et4000w32_log("XY MMU block not started\n"); return; @@ -1087,7 +1093,7 @@ et4000w32p_mmu_read(uint32_t addr, void *priv) case 0x8d: return et4000->acl.internal.dest_off >> 8; case 0x8e: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) return et4000->acl.internal.pixel_depth; return et4000->acl.internal.vbus; case 0x8f: @@ -2779,6 +2785,30 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + break; + + case ET4000W32P_IMASCAN_VLB: + /* ET4000/W32p Imascan RGB */ + et4000->rev = 5; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_IMASCAN_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + break; + + case ET4000W32P_MIROVIDEO20TD_VLB: + /* ET4000/W32p miroVIDEO 20TD LIVE! */ + et4000->rev = 5; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; @@ -2791,6 +2821,18 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; + + case ET4000W32P_REVCD_ONBOARD: + /* ET4000/W32p rev C */ + et4000->rev = 7; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVCD_ONBOARD, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = sdac_getclock; @@ -2890,12 +2932,30 @@ et4000w32p_videomagic_revb_vlb_available(void) return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB); } +int +et4000w32p_imascan_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_IMASCAN_VLB); +} + +int +et4000w32p_mirovideo20td_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB); +} + int et4000w32p_revc_available(void) { return rom_present(BIOS_ROM_PATH_W32P_REVC); } +int +et4000w32p_revcd_onboard_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_REVCD_ONBOARD); +} + int et4000w32p_noncardex_available(void) { @@ -2943,19 +3003,23 @@ et4000w32p_force_redraw(void *priv) static const device_config_t et4000w32p_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = NULL, - .default_int = 2, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { - { .description = "1 MB", .value = 1 }, - { .description = "2 MB", .value = 2 }, - { .description = "" } - }, - .bios = { { 0 } } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } + } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -3017,6 +3081,34 @@ const device_t et4000w32i_vlb_device = { .config = et4000w32p_config }; +const device_t et4000w32p_imascan_vlb_device = { + .name = "Tseng Labs ET4000/w32p VLB (Imascan)", + .internal_name = "et4000w32p_imascan_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_IMASCAN_VLB, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + .available = et4000w32p_imascan_vlb_available, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + +const device_t et4000w32p_mirovideo20td_vlb_device = { + .name = "Tseng Labs ET4000/w32p VLB (miroVIDEO 20TD LIVE!)", + .internal_name = "et4000w32p_mirovideo20td_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_MIROVIDEO20TD_VLB, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + .available = et4000w32p_mirovideo20td_vlb_available, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + const device_t et4000w32p_videomagic_revb_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)", .internal_name = "et4000w32p_videomagic_revb_vlb", @@ -3073,6 +3165,20 @@ const device_t et4000w32p_revc_pci_device = { .config = et4000w32p_config }; +const device_t et4000w32p_revcd_onboard_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. C/D PCI (On-Board)", + .internal_name = "et4000w32p_revc_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P_REVCD_ONBOARD, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + .available = et4000w32p_revcd_onboard_available, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + const device_t et4000w32p_noncardex_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. D VLB", .internal_name = "et4000w32p_nc_vlb", From e6f99168d170351fe87b27354acc4388828098e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 22:51:27 +0200 Subject: [PATCH 0884/1190] ASUS KN97: Change minimum CPU core voltage to 2.8 V, the board does not support the 2.0 V Deschutes CPU's. --- 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 adf132a5d..09183e5c0 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14770,7 +14770,7 @@ const machine_t machines[] = { .block = CPU_BLOCK_NONE, .min_bus = 60000000, .max_bus = 83333333, - .min_voltage = 1800, + .min_voltage = 2800, .max_voltage = 3500, .min_multi = 1.5, .max_multi = 8.0 From 58f342c27726c42c912cdb59764a49a331916396 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 23:02:29 +0200 Subject: [PATCH 0885/1190] RZ-1000: Disable logging. --- src/disk/hdc_ide_rz1000.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/disk/hdc_ide_rz1000.c b/src/disk/hdc_ide_rz1000.c index d93e83859..2c1a09e8e 100644 --- a/src/disk/hdc_ide_rz1000.c +++ b/src/disk/hdc_ide_rz1000.c @@ -55,7 +55,6 @@ typedef struct rz1000_t { static int next_id = 0; -#define ENABLE_RZ1000_LOG 1 #ifdef ENABLE_RZ1000_LOG int rz1000_do_log = ENABLE_RZ1000_LOG; From d6338e42cc0875e54bdce4b86aa30fe636d667ce Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 May 2025 23:08:26 +0200 Subject: [PATCH 0886/1190] Significantly speed up floppy turbo mode when the FDC is using DMA. --- src/floppy/fdc.c | 9 +++++++++ src/floppy/fdd_86f.c | 18 +++++++++++++++--- src/include/86box/fdc.h | 1 + 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index de8508e69..e779ea2d7 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -279,6 +279,15 @@ fdc_is_mfm(fdc_t *fdc) return fdc->mfm ? 1 : 0; } +int +fdc_is_dma(fdc_t *fdc) +{ + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + return 0; + else + return 1; +} + void fdc_request_next_sector_id(fdc_t *fdc) { diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 0a7120b16..24fde57b1 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -2414,16 +2414,28 @@ d86f_turbo_poll(int drive, int side) case STATE_0C_READ_DATA: case STATE_11_SCAN_DATA: case STATE_16_VERIFY_DATA: - d86f_turbo_read(drive, side); + if (fdc_is_dma(d86f_fdc)) + for (int i = 0; i < (128 << dev->last_sector.id.n); i++) + d86f_turbo_read(drive, side); + else + d86f_turbo_read(drive, side); break; case STATE_05_WRITE_DATA: case STATE_09_WRITE_DATA: - d86f_turbo_write(drive, side); + if (fdc_is_dma(d86f_fdc)) + for (int i = 0; i < (128 << dev->last_sector.id.n); i++) + d86f_turbo_write(drive, side); + else + d86f_turbo_write(drive, side); break; case STATE_0D_FORMAT_TRACK: - d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2))); + if (fdc_is_dma(d86f_fdc)) + while (dev->state == STATE_0D_FORMAT_TRACK) + d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2))); + else + d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2))); return; case STATE_IDLE: diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 36cfaeb7a..ed62cb45f 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -206,6 +206,7 @@ extern int fdc_get_drive(fdc_t *fdc); extern int fdc_get_perp(fdc_t *fdc); extern int fdc_get_format_n(fdc_t *fdc); extern int fdc_is_mfm(fdc_t *fdc); +extern int fdc_is_dma(fdc_t *fdc); extern double fdc_get_hut(fdc_t *fdc); extern double fdc_get_hlt(fdc_t *fdc); extern void fdc_request_next_sector_id(fdc_t *fdc); From 7301aaad004a8b3d9fab728230b1dba0188e7d3d Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 8 May 2025 04:52:33 +0200 Subject: [PATCH 0887/1190] Added the ASUS 386/33-64K (Award 4.00 386DX). --- src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 21 +++++++++++++++++++ src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 996f2bf5f..c28add516 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -514,6 +514,7 @@ extern int machine_at_ga486l_init(const machine_t *); extern int machine_at_cougar_init(const machine_t *); extern int machine_at_acc386_init(const machine_t *); +extern int machine_at_asus386_3364k_init(const machine_t *); extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); extern int machine_at_spc6000a_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e3838ce32..e75c5414e 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -72,6 +72,27 @@ machine_at_acc386_init(const machine_t *model) return ret; } +int +machine_at_asus386_3364k_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/asus386_3364k/am27c512dip28-64b53c26be3d8160533563.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&rabbit_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_asus386_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 09183e5c0..e0317f40f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5632,6 +5632,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has Award KBC firmware. */ + { + .name = "[SiS 310] ASUS 386/33-64K", + .internal_name = "asus386_3364k", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_SIS_310, + .init = machine_at_asus386_3364k_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, + .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_APM, + .ram = { + .min = 1024, + .max = 16384, + .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 AMIKey F KBC firmware. */ { .name = "[SiS 310] ASUS ISA-386C", From e621014addfd514b1a89104ea968d677d9c41268 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 8 May 2025 23:56:48 +0200 Subject: [PATCH 0888/1190] Actually fix the timing of the PAS16/Plus SCSI side (May 8th, 2025) See above, fixes the non-audio mamv1.sys SCSI controller driver using CD/HDD reads/writes. --- src/sound/snd_pas16.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index cfefc8df5..9b82d580d 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -792,14 +792,10 @@ pas16_in(uint16_t port, void *priv) if ((scsi_bus->tx_mode == PIO_TX_BUS) && !(ret & 0x80)) ret |= 0x80; - if (ret & 0x80) { - if (scsi_bus->data_repeat < MIN(511, scsi_bus->total_len)) - scsi_bus->data_repeat++; - } else { - if (scsi_bus->data_repeat == MIN(511, scsi_bus->total_len)) - ret = 0x00; - } - pas16_log("%04X:%08X: Port %04x read ret=%02x, status=%02x, txmode=%x, repeat=%d.\n", CS, cpu_state.pc, port + pas16->base, ret, pas16->scsi->status & 0x06, scsi_bus->tx_mode, scsi_bus->data_repeat); + if ((pas16->scsi->status & 0x06) == 0x00) + ret = 0x00; + + pas16_log("%04X:%08X: Port %04x read ret=%02x, status=%02x, txmode=%x, repeat=%d, total=%d.\n", CS, cpu_state.pc, port + pas16->base, ret, pas16->scsi->status & 0x06, scsi_bus->tx_mode, scsi_bus->data_repeat, MIN(511, scsi_bus->total_len)); } break; case 0x5c03: From cc6076f93b5fe05fe60feb069ec57acb2b0ded50 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 9 May 2025 02:23:56 +0200 Subject: [PATCH 0889/1190] Late night S3 changes (May 9th, 2025) 1. Pixtrans on port 0xb2e8 is not available on 864/964 and up (including the trio64) due to color compare taking its place, fixes some graphical glitches in WinXP. 2. The DOS s3id utility identifies the 80x chips correctly, either it's 801 ISA or 805 VLB, but not 805 ISA even if they share the same id, but since it's an ISA card, identify the Elsa Winner 1000 805 ISA as a 801 card. --- src/video/vid_s3.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index e88bbe58f..683d2be34 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1311,7 +1311,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xb148: case 0xb2e8: s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y); - if (s3->accel.multifunc[0xe] & 0x100) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_VISION964)) { s3->accel.b2e8_pix = 0; if (s3->bpp == 3) { if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { @@ -1353,7 +1353,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xb149: case 0xb2e9: s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y); - if (s3->accel.multifunc[0xe] & 0x100) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_VISION964)) { s3->accel.b2e8_pix = 0; if (s3->bpp == 3) { if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { @@ -8414,7 +8414,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Pattern on pixtrans (911/924)*/ count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; @@ -8806,8 +8805,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width); if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { - s3_log("Special BitBLT.\n"); - + pclog("Special BitBLT.\n"); while (1) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { READ(s3->accel.src + s3->accel.cx - s3->accel.minus, src_dat); @@ -8851,7 +8849,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } } else { - s3_log("Normal blit.\n"); + s3_log("Normal blit, srcbase=%08x, dstbase=%08x, full=%04x, wrt_mask=%08x, extmultifunc0e=%03x, frgdmixval=%02x.\n", srcbase, dstbase, s3->accel.cmd, wrt_mask, s3->accel.multifunc[0x0e] & 0x180, s3->accel.frgd_mix); while (count-- && (s3->accel.sy >= 0)) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { @@ -9842,8 +9840,8 @@ s3_init(const device_t *info) break; case S3_WINNER1000_805: bios_fn = ROM_WINNER1000_805; - chip = S3_86C805; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + chip = S3_86C801; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; case S3_86C805_ONBOARD: bios_fn = NULL; From 96d5a04b338ed1b71ec23290df2b7a7ba28faa62 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 May 2025 04:20:22 +0200 Subject: [PATCH 0890/1190] Laser XT 3: EMS memory accesses are now correctly 16-bit. --- src/machine/m_xt_laserxt.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index d298e726b..ec4b41c35 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -154,6 +154,14 @@ lxt_ems_write(uint32_t addr, uint8_t val, void *priv) mem[addr & 0x3fff] = val; } +static void +lxt_ems_writew(uint32_t addr, uint16_t val, void *priv) +{ + uint8_t *mem = (uint8_t *) priv; + + *(uint16_t *) &(mem[addr & 0x3fff]) = val; +} + static uint8_t lxt_ems_read(uint32_t addr, void *priv) { @@ -165,6 +173,17 @@ lxt_ems_read(uint32_t addr, void *priv) return ret; } +static uint16_t +lxt_ems_readw(uint32_t addr, void *priv) +{ + uint8_t *mem = (uint8_t *) priv; + uint8_t ret = 0xff; + + ret = *(uint16_t *) &(mem[addr & 0x3fff]); + + return ret; +} + static lxt_ems_board_t * lxt_ems_init(lxt_t *parent, int en, uint16_t io, uint32_t mem) { @@ -186,10 +205,17 @@ lxt_ems_init(lxt_t *parent, int en, uint16_t io, uint32_t mem) for (uint8_t i = 0; i < 4; i++) { uint8_t *ptr = dev->ram + (i << 14); - mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000, - lxt_ems_read, NULL, NULL, - lxt_ems_write, NULL, NULL, - ptr, 0, ptr); + if (parent->is_lxt3) + mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000, + lxt_ems_read, lxt_ems_readw, NULL, + lxt_ems_write, lxt_ems_writew, NULL, + ptr, 0, ptr); + else + mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000, + lxt_ems_read, NULL, NULL, + lxt_ems_write, NULL, NULL, + ptr, 0, ptr); + mem_mapping_disable(&dev->ems[i].mapping); dev->ems[i].page = 0x7f; From 9a69e1800d1532c45297b64c7d766463927c789a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 May 2025 14:56:55 +0600 Subject: [PATCH 0891/1190] Honour `--nohook` on X11 as well --- src/qt/qt_mainwindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 3a0f1cb8a..aaf625c2d 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -322,7 +322,8 @@ MainWindow::MainWindow(QWidget *parent) mouse_capture = state ? 1 : 0; qt_mouse_capture(mouse_capture); if (mouse_capture) { - this->grabKeyboard(); + if (hook_enabled) + this->grabKeyboard(); if (ui->stackedWidget->mouse_capture_func) ui->stackedWidget->mouse_capture_func(this->windowHandle()); } else { @@ -1481,13 +1482,15 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) plat_pause(curdopause); #ifdef __unix__ if (!QApplication::platformName().contains("wayland") && (this->windowState() & Qt::WindowActive)) { - this->grabKeyboard(); + if (hook_enabled) + this->grabKeyboard(); } #endif } else if (event->type() == QEvent::WindowActivate) { #ifdef __unix__ if (!QApplication::platformName().contains("wayland")) { - this->grabKeyboard(); + if (hook_enabled) + this->grabKeyboard(); } #endif } else if (event->type() == QEvent::WindowDeactivate) { From b0c9ca6b20aee537a4cbf7fdaece49a4a942b1b8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 May 2025 15:28:05 +0600 Subject: [PATCH 0892/1190] Fix stack use-after-return on Linux --- src/qt/qt_rendererstack.cpp | 2 +- src/qt/qt_rendererstack.hpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 431b3609b..79fa78097 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -77,7 +77,7 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index) m_monitor_index = monitor_index; #if defined __unix__ && !defined __HAIKU__ - char auto_mouse_type[16]; + memset(auto_mouse_type, 0, sizeof (auto_mouse_type)); mousedata.mouse_type = getenv("EMU86BOX_MOUSE"); if (!mousedata.mouse_type || (mousedata.mouse_type[0] == '\0') || !stricmp(mousedata.mouse_type, "auto")) { if (QApplication::platformName().contains("wayland")) diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 172dc2fe6..3a76f3ada 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -137,6 +137,8 @@ private: std::atomic_bool rendererTakesScreenshots; std::atomic_bool switchInProgress{false}; + + char auto_mouse_type[16]; }; #endif // QT_RENDERERCONTAINER_HPP From 070c6c4125addb5c0af0f46f62ae10aa4af61ed9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 May 2025 20:21:28 +0200 Subject: [PATCH 0893/1190] Laser XT 3: Fix 16-bit EMS readout, fixes #5572. --- src/machine/m_xt_laserxt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index ec4b41c35..7a6cab5e3 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -176,8 +176,8 @@ lxt_ems_read(uint32_t addr, void *priv) static uint16_t lxt_ems_readw(uint32_t addr, void *priv) { - uint8_t *mem = (uint8_t *) priv; - uint8_t ret = 0xff; + uint8_t *mem = (uint8_t *) priv; + uint16_t ret = 0xff; ret = *(uint16_t *) &(mem[addr & 0x3fff]); From dd6d480facd9b357babbbf432a1ac41e34d1b70d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 9 May 2025 23:41:05 +0200 Subject: [PATCH 0894/1190] Spock/Tribble changes of the evening (May 9th, 2025) Don't duplicate drives into phantom drives. --- src/scsi/scsi_spock.c | 137 +++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 6f0b7aacb..0bb2d70ba 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -130,6 +130,7 @@ typedef struct { int adapter_id; int assign; int present[8]; + int id_connected; int cmd_status; int cir_status; @@ -448,7 +449,6 @@ static void spock_process_imm_cmd(spock_t *scsi) { int i; - int j = 0; int adapter_id; int phys_id; int lun_id; @@ -467,14 +467,23 @@ spock_process_imm_cmd(spock_t *scsi) if (scsi->command & (1 << 23)) { spock_log("Assign: adapter id=%d\n", adapter_id); scsi->dev_id[adapter_id].phys_id = -1; + scsi->id_connected = 0; spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); } else { if (phys_id != scsi->adapter_id) { scsi->dev_id[adapter_id].phys_id = phys_id; scsi->dev_id[adapter_id].lun_id = lun_id; - spock_log("Assign: adapter dev=%x scsi ID=%i LUN=%i.\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id); + if (scsi_device_present(&scsi_devices[scsi->bus][phys_id])) { + scsi->present[scsi->id_connected] = 1; + if (lun_id == 0) + scsi->id_connected++; + } else + scsi->present[scsi->id_connected] = 0; + + spock_log("Assign: adapter dev=%d, scsi ID=%i, LUN=%i, attention devsel=%d, present=%d, connected=%d.\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id, scsi->attention & 0x0f, scsi->present[scsi->id_connected], scsi->id_connected); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); } else { /*Can not assign adapter*/ + scsi->id_connected = 0; spock_log("Assign: PUN=%d, cannot assign adapter.\n", phys_id); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); } @@ -495,35 +504,15 @@ spock_process_imm_cmd(spock_t *scsi) spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; case CMD_RESET: + scsi->id_connected = 0; spock_log("Reset command, attention=%02x.\n", scsi->attention & 0x0f); if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ for (i = 0; i < 8; i++) scsi_device_reset(&scsi_devices[scsi->bus][i]); - for (i = 6; i > -1; i--) { - if (scsi_device_present(&scsi_devices[scsi->bus][i])) { - spock_log("Adapter Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); - scsi->present[j] = i; - j++; - } else { - scsi->present[j] = 0xff; - spock_log("Adapter Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); - } - } - } else if ((scsi->attention & 0x0f) < 7) { /*Device reset*/ + } else if ((scsi->attention & 0x0f) < 7) /*Device reset*/ scsi_device_reset(&scsi_devices[scsi->bus][scsi->attention & 0x0f]); - for (i = 6; i > -1; i--) { - if (scsi_device_present(&scsi_devices[scsi->bus][i])) { - spock_log("Device Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); - scsi->present[j] = i; - j++; - } else { - scsi->present[j] = 0xff; - spock_log("Device Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); - } - } - } scsi->scb_state = 0; spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; @@ -538,7 +527,6 @@ static void spock_execute_cmd(spock_t *scsi, scb_t *scb) { int c; - int j = 0; int old_scb_state; if (scsi->in_reset) { @@ -556,17 +544,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) scsi->dev_id[c].phys_id = -1; scsi->in_reset = 0; - - for (c = 6; c >= 0; c--) { - if (scsi_device_present(&scsi_devices[scsi->bus][c])) { - spock_log("Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type); - scsi->present[j] = c; - j++; - } else { - scsi->present[j] = 0xff; - spock_log("Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type); - } - } + spock_log("Reset.\n"); return; } @@ -698,12 +676,15 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) break; case CMD_DEVICE_INQUIRY: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; - spock_log("Device Inquiry, ID=%d\n", scsi->cdb_id); + spock_log("Device Inquiry, ID=%d, connected=%d, present=%d.\n", scsi->cdb_id, scsi->id_connected, scsi->present[scsi->scb_id + 1]); scsi->cdb[0] = GPCMD_INQUIRY; scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[2] = 0; /*Page code*/ @@ -718,13 +699,16 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_SEND_OTHER_SCSI: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; dma_bm_read(scsi->scb_addr + 0x18, scsi->cdb, 12, 2); - spock_log("Send Other SCSI, SCB ID=%d, PHYS ID=%d, CDB[0]=%02x, CDB_ID=%d, ID Present=%d.\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->cdb[0], scsi->cdb_id, scsi->present[scsi->scb_id]); + spock_log("Send Other SCSI, SCB ID=%d, PHYS ID=%d, LUN=%d, CDB[0]=%02x, CDB_ID=%d, ID Present=%d.\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->dev_id[scsi->scb_id].lun_id, scsi->cdb[0], scsi->cdb_id, scsi->present[scsi->scb_id + 1]); scsi->cdb[1] = (scsi->cdb[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/ scsi->cdb_len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6; scsi->scsi_state = SCSI_STATE_SELECT; @@ -732,10 +716,13 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_READ_DEVICE_CAPACITY: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; spock_log("Device Capacity, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id); scsi->cdb[0] = GPCMD_READ_CDROM_CAPACITY; @@ -754,10 +741,13 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_READ_DATA: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; spock_log("Device Read Data, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id); scsi->cdb[0] = GPCMD_READ_10; @@ -776,10 +766,13 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_WRITE_DATA: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; spock_log("Device Write Data\n"); scsi->cdb[0] = GPCMD_WRITE_10; @@ -798,10 +791,13 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_VERIFY: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; spock_log("Device Verify\n"); scsi->cdb[0] = GPCMD_VERIFY_10; @@ -821,10 +817,13 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_WRITE_VERIFY: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; spock_log("Device Write with Verify\n"); scsi->cdb[0] = GPCMD_WRITE_AND_VERIFY_10; @@ -843,10 +842,13 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) return; case CMD_REQUEST_SENSE: - if (scsi->present[scsi->scb_id] != 0xff) + if (scsi->scb_id != 15) { + if (scsi->present[scsi->scb_id]) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + } else scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - else - scsi->cdb_id = 0xff; spock_log("Device Request Sense, ID=%d\n", scsi->cdb_id); scsi->cdb[0] = GPCMD_REQUEST_SENSE; @@ -870,7 +872,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) if (scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id]) && (scsi->cdb_id != 0xff)) { if (scsi->last_status == SCSI_STATUS_OK) { scsi->scb_state = 3; - spock_log("Status is Good on device ID %d, cdb id = %d.\n", scsi->scb_id, scsi->cdb_id); + spock_log("Status is Good on device ID %d, cdb id = %d, devsel = %d.\n", scsi->scb_id, scsi->cdb_id, scsi->attention & 0x0f); } else if (scsi->last_status == SCSI_STATUS_CHECK_CONDITION) { uint16_t term_stat_block_addr7 = (0xc << 8) | 2; uint16_t term_stat_block_addr8 = 0x20; @@ -905,7 +907,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) } else { spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE); scsi->scb_state = 0; - spock_log("Complete SCB ID = %d.\n", scsi->attention & 0x0f); + spock_log("Complete SCB ID = %d.\n", scsi->scb_id); } break; @@ -1084,10 +1086,10 @@ spock_callback(void *priv) case 4: case 0x0f: /*Start SCB*/ scsi->cmd_status = 1; - scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); - scsi->scb_id = scsi->attention & 0x0f; + scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); + scsi->scb_id = scsi->attention & 0x0f; scsi->cmd_timer = SPOCK_TIME * 2; - spock_log("Start SCB at ID = %d, attention = %02x\n", scsi->scb_id, scsi->attention >> 4); + spock_log("Start SCB at ID = %d, attention = %02x, cdb_id = %d\n", scsi->scb_id, scsi->attention >> 4, scsi->cdb_id); scsi->scb_state = 1; break; @@ -1182,6 +1184,7 @@ spock_reset(void *priv) scsi->in_invalid = 0; scsi->attention_wait = 0; scsi->basic_ctrl = 0; + scsi->id_connected = 0; spock_log("Actual Reset.\n"); } From e800f99f5a2b89b9aad04a0ce39b2726bdb0a88c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 04:53:20 +0200 Subject: [PATCH 0895/1190] Make device.c assume CONFIG_BIOS is first in the config struct and make sure any device_t struct containing such follows that, in order to not have to traverse the entirety of every single device_t's config struct in the Settings dialog - should reduce the dialog's loading times further. --- src/device.c | 37 ++++++++++------------- src/disk/hdc_xta.c | 60 ++++++++++++++++++------------------- src/disk/hdc_xtide.c | 62 +++++++++++++++++++-------------------- src/scsi/scsi_ncr53c400.c | 62 +++++++++++++++++++-------------------- src/video/vid_et4000.c | 46 ++++++++++++++--------------- 5 files changed, 131 insertions(+), 136 deletions(-) diff --git a/src/device.c b/src/device.c index 25f0b55de..ecd523274 100644 --- a/src/device.c +++ b/src/device.c @@ -392,29 +392,24 @@ device_available(const device_t *dev) { if (dev != NULL) { const device_config_t *config = dev->config; - if (config != NULL) { - while (config->type != CONFIG_END) { - if (config->type == CONFIG_BIOS) { - int roms_present = 0; - const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; + if ((config != NULL) && (config->type == CONFIG_BIOS)) { + int roms_present = 0; + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; - /* Go through the ROM's in the device configuration. */ - while ((bios != NULL) && - (bios->name != NULL) && - (bios->internal_name != NULL) && - (bios->files_no != 0)) { - int i = 0; - for (uint8_t bf = 0; bf < bios->files_no; bf++) - i += !!rom_present(bios->files[bf]); - if (i == bios->files_no) - roms_present++; - bios++; - } - - return (roms_present ? -1 : 0); - } - config++; + /* Go through the ROM's in the device configuration. */ + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { + int i = 0; + for (uint8_t bf = 0; bf < bios->files_no; bf++) + i += !!rom_present(bios->files[bf]); + if (i == bios->files_no) + roms_present++; + bios++; } + + return (roms_present ? -1 : 0); } /* No CONFIG_BIOS field present, use the classic available(). */ diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 85581af2d..d54f6ab0c 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1106,6 +1106,36 @@ xta_close(void *priv) static const device_config_t wdxt150_config[] = { // clang-format off + { + .name = "bios_rev", + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "rev_1", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Revision 1.0", + .internal_name = "rev_1", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { WD_REV_1_BIOS_FILE, "" } + }, + { + .name = "Revision 2.0", + .internal_name = "rev_2", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { WD_REV_2_BIOS_FILE, "" } + }, + { .files_no = 0 } + }, + }, { .name = "base", .description = "Address", @@ -1151,36 +1181,6 @@ static const device_config_t wdxt150_config[] = { }, .bios = { { 0 } } }, - { - .name = "bios_rev", - .description = "BIOS Revision", - .type = CONFIG_BIOS, - .default_string = "rev_1", - .default_int = 0, - .file_filter = NULL, - .spinner = { 0 }, - .bios = { - { - .name = "Revision 1.0", - .internal_name = "rev_1", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 8192, - .files = { WD_REV_1_BIOS_FILE, "" } - }, - { - .name = "Revision 2.0", - .internal_name = "rev_2", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 8192, - .files = { WD_REV_2_BIOS_FILE, "" } - }, - { .files_no = 0 } - }, - }, { .name = "", .description = "", .type = CONFIG_END } // clang-format off }; diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 154a28cec..1c8e2c8da 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -252,6 +252,37 @@ xtide_at_close(void *priv) // clang-format off static const device_config_t xtide_config[] = { + { + .name = "bios", + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "xt", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Regular XT", + .internal_name = "xt", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { ROM_PATH_XT, "" } + }, + { + .name = "XT+ (V20/V30/8018x)", + .internal_name = "xt_plus", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { ROM_PATH_XTP, "" } + }, + { .files_no = 0 } + }, + }, { .name = "base", .description = "Address", @@ -348,37 +379,6 @@ static const device_config_t xtide_config[] = { }, .bios = { { 0 } } }, - { - .name = "bios", - .description = "BIOS Revision", - .type = CONFIG_BIOS, - .default_string = "xt", - .default_int = 0, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } }, - .bios = { - { - .name = "Regular XT", - .internal_name = "xt", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 8192, - .files = { ROM_PATH_XT, "" } - }, - { - .name = "XT+ (V20/V30/8018x)", - .internal_name = "xt_plus", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 8192, - .files = { ROM_PATH_XTP, "" } - }, - { .files_no = 0 } - }, - }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index f91dc83a9..0e04e0b5e 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -859,6 +859,37 @@ static const device_config_t ncr53c400_mmio_config[] = { }; static const device_config_t rt1000b_config[] = { + { + .name = "bios_ver", + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v8_10r", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Version 8.10R", + .internal_name = "v8_10r", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { RT1000B_810R_ROM, "" } + }, + { + .name = "Version 8.20R", + .internal_name = "v8_20r", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { RT1000B_820R_ROM, "" } + }, + { .files_no = 0 } + }, + }, { .name = "bios_addr", .description = "BIOS Address", @@ -895,37 +926,6 @@ static const device_config_t rt1000b_config[] = { }, .bios = { { 0 } } }, - { - .name = "bios_ver", - .description = "BIOS Revision", - .type = CONFIG_BIOS, - .default_string = "v8_10r", - .default_int = 0, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } }, - .bios = { - { - .name = "Version 8.10R", - .internal_name = "v8_10r", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 8192, - .files = { RT1000B_810R_ROM, "" } - }, - { - .name = "Version 8.20R", - .internal_name = "v8_20r", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 8192, - .files = { RT1000B_820R_ROM, "" } - }, - { .files_no = 0 } - }, - }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 064d79230..1929d1d16 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -942,22 +942,6 @@ et4000_kasan_available(void) static const device_config_t et4000_tc6058af_config[] = { // clang-format off - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = NULL, - .default_int = 512, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { - { .description = "256 KB", .value = 256 }, - { .description = "512 KB", .value = 512 }, - { .description = "1 MB", .value = 1024 }, - { .description = "" } - }, - .bios = { { 0 } } - }, { .name = "bios_ver", .description = "BIOS Revision", @@ -989,18 +973,12 @@ static const device_config_t et4000_tc6058af_config[] = { { .files_no = 0 } } }, - { .name = "", .description = "", .type = CONFIG_END } -// clang-format on -}; - -static const device_config_t et4000_bios_config[] = { - // clang-format off { .name = "memory", .description = "Memory size", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 1024, + .default_int = 512, .file_filter = NULL, .spinner = { 0 }, .selection = { @@ -1011,6 +989,12 @@ static const device_config_t et4000_bios_config[] = { }, .bios = { { 0 } } }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +static const device_config_t et4000_bios_config[] = { + // clang-format off { .name = "bios_ver", .description = "BIOS Revision", @@ -1042,6 +1026,22 @@ static const device_config_t et4000_bios_config[] = { { .files_no = 0 } } }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1024, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "1 MB", .value = 1024 }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; From 76d5fa79af07f10251eebb0c92265cdffbebfc0e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 05:01:57 +0200 Subject: [PATCH 0896/1190] Improve machine availability checking so that it absolutely never uses the legacy method if the machine has a device and the device has a CONFIG_BIOS setting. --- src/device.c | 63 ++++++++++++++++++++++---------------- src/include/86box/device.h | 2 ++ src/machine/machine.c | 20 +++++++----- 3 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/device.c b/src/device.c index ecd523274..1922806b9 100644 --- a/src/device.c +++ b/src/device.c @@ -390,37 +390,18 @@ device_get_priv(const device_t *dev) int device_available(const device_t *dev) { - if (dev != NULL) { - const device_config_t *config = dev->config; - if ((config != NULL) && (config->type == CONFIG_BIOS)) { - int roms_present = 0; - const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; - - /* Go through the ROM's in the device configuration. */ - while ((bios != NULL) && - (bios->name != NULL) && - (bios->internal_name != NULL) && - (bios->files_no != 0)) { - int i = 0; - for (uint8_t bf = 0; bf < bios->files_no; bf++) - i += !!rom_present(bios->files[bf]); - if (i == bios->files_no) - roms_present++; - bios++; - } - - return (roms_present ? -1 : 0); - } + int ret = machine_device_available(dev); + if (ret == 0) { /* No CONFIG_BIOS field present, use the classic available(). */ if (dev->available != NULL) - return (dev->available()); + ret = (dev->available()); else - return 1; - } + ret = (dev != NULL); + } else + ret = (ret == -1); - /* A NULL device is never available. */ - return 0; + return ret; } uint8_t @@ -964,6 +945,36 @@ machine_get_config_string(char *str) return ret; } +int +machine_device_available(const device_t *dev) +{ + if (dev != NULL) { + const device_config_t *config = dev->config; + if ((config != NULL) && (config->type == CONFIG_BIOS)) { + int roms_present = 0; + const device_config_bios_t *bios = (const device_config_bios_t *) config->bios; + + /* Go through the ROM's in the device configuration. */ + while ((bios != NULL) && + (bios->name != NULL) && + (bios->internal_name != NULL) && + (bios->files_no != 0)) { + int i = 0; + for (uint8_t bf = 0; bf < bios->files_no; bf++) + i += !!rom_present(bios->files[bf]); + if (i == bios->files_no) + roms_present++; + bios++; + } + + return (roms_present ? -1 : -2); + } + } + + /* NULL device or no CONFIG_BIOS field, return 0. */ + return 0; +} + const device_t * device_context_get_device(void) { diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 91ff2daa6..76f12a0c5 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -239,6 +239,8 @@ extern const char *device_get_internal_name(const device_t *dev); extern int machine_get_config_int(char *str); extern const char *machine_get_config_string(char *str); +extern int machine_device_available(const device_t *dev); + extern const device_t device_none; extern const device_t device_internal; diff --git a/src/machine/machine.c b/src/machine/machine.c index b171dd505..505674000 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -139,18 +139,24 @@ machine_init(void) int machine_available(int m) { - int ret; + int ret = 0; const device_t *dev = machine_get_device(m); - bios_only = 1; + if (dev != NULL) + ret = machine_device_available(dev); + /* + Only via machine_init_ex() if the device is NULL or + it lacks a CONFIG_BIOS field (or the CONFIG_BIOS field + is not the first in list. + */ + if (ret == 0) { + bios_only = 1; - ret = device_available(dev); - /* Do not check via machine_init_ex() if the device is not NULL and - it has a CONFIG_BIOS field. */ - if ((dev == NULL) || (ret != -1)) ret = machine_init_ex(m); - bios_only = 0; + bios_only = 0; + } else if (ret == -2) + ret = 0; return !!ret; } From 462e9232b3633ac54e4abf2935cce95ae8426d53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 05:05:56 +0200 Subject: [PATCH 0897/1190] Chaintech 5SBM2: Rename to 5SBM/5SBM2 and add the 4.50PG BIOS from 1996 as an option. --- src/machine/m_at_socket7_3v.c | 49 ++++++++++++++++++++++++++++++++--- src/machine/machine_table.c | 7 ++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 913c82518..04bc6b5ef 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -825,13 +825,56 @@ machine_at_vectra54_init(const machine_t *model) return ret; } +static const device_config_t c5sbm2_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "5sbm2", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "4.50GP (07/17/1995)", .internal_name = "5sbm2", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/5sbm2/5SBM0717.BIN", "" } }, + { .name = "4.50PG (03/21/1996)", .internal_name = "5sbm2_450pg", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/5sbm2/5SBM0326.BIN", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t c5sbm2_device = { + .name = "Chaintech 5SBM/5SBM2 (M103)", + .internal_name = "5sbm2_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = c5sbm2_config +}; + int machine_at_5sbm2_init(const machine_t *model) { - int ret; + int ret = 0; + const char* fn; - ret = bios_load_linear("roms/machines/5sbm2/5SBM0717.BIN", - 0x000e0000, 131072, 0); + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); if (bios_only || !ret) return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e0317f40f..34e69ed24 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -68,6 +68,7 @@ extern const device_t ibmxt286_device; extern const device_t pb450_device; extern const device_t jukopc_device; extern const device_t vendex_device; +extern const device_t c5sbm2_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -11545,7 +11546,7 @@ const machine_t machines[] = { /* SiS 5501 */ /* Has the Lance LT38C41 KBC. */ { - .name = "[SiS 5501] Chaintech 5SBM2 (M103)", + .name = "[SiS 5501] Chaintech 5SBM/5SBM2 (M103)", .internal_name = "5sbm2", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_SIS_5501, @@ -11568,7 +11569,7 @@ const machine_t machines[] = { .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, - .max = 262144, + .max = 131072, .step = 8192 }, .nvrmask = 255, @@ -11576,7 +11577,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &c5sbm2_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From 87557685159765b3f6f6f13f964be89c258dd447 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 05:14:59 +0200 Subject: [PATCH 0898/1190] Chaintech 5SBM/5SBM2: Unicore Upgrade 4.51PG BIOS. --- src/machine/m_at_socket7_3v.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 04bc6b5ef..39dc2d735 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -840,6 +840,8 @@ static const device_config_t c5sbm2_config[] = { .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/5sbm2/5SBM0717.BIN", "" } }, { .name = "4.50PG (03/21/1996)", .internal_name = "5sbm2_450pg", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/5sbm2/5SBM0326.BIN", "" } }, + { .name = "4.51PG (03/15/2000 Unicore Upgrade)", .internal_name = "5sbm2_451pg", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/5sbm2/2A5ICC3A.BIN", "" } }, { .files_no = 0 } }, }, From 1dd460e9a445298d2e43ef936f14cf159d758603 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 06:22:56 +0200 Subject: [PATCH 0899/1190] x86_64 new recompiler: properly handle cases where pccache is not within 2 GB of the beginning of the RAM array. --- src/codegen_new/codegen_backend_x86-64_ops.c | 13 ++++++++++++- 1 file changed, 12 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 fc6c1b492..b03ea88c3 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -780,8 +780,19 @@ host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ codegen_addlong(block, ram_offset); + } else if ((ram_offset < -2147483648LL) || (ram_offset > 2147483647LL) || !(block->flags & CODEBLOCK_NO_IMMEDIATES)) { + // fatal("host_x86_MOV32_REG_ABS - out of range\n"); + // void *q = p; + //uint32_t *r = NULL; + // *r = 5; /* Crash deliberately. */ + codegen_alloc_bytes(block, 18); + codegen_addbyte2(block, 0x41, 0x54); /*PUSH r12*/ + codegen_addbyte2(block, 0x49, 0xbc); /*MOV r12,(uintptr_t) p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_addbyte4(block, 0x41, 0x8b, 0x04 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, [R12]*/ + codegen_addbyte2(block, 0x41, 0x5c); /*POP r12*/ } else { - fatal("host_x86_MOV32_REG_ABS - out of range\n"); + fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIX64 ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram); codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); From b179955a12aea4510d105521df0bc39db2f519ba Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 10 May 2025 12:57:27 +0600 Subject: [PATCH 0900/1190] x64 NDR: Avoid pushes/pops for `host_x86_MOV32_REG_ABS` --- src/codegen_new/codegen_backend_x86-64_ops.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index b03ea88c3..ed218d7c4 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -785,12 +785,11 @@ host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) // void *q = p; //uint32_t *r = NULL; // *r = 5; /* Crash deliberately. */ - codegen_alloc_bytes(block, 18); - codegen_addbyte2(block, 0x41, 0x54); /*PUSH r12*/ - codegen_addbyte2(block, 0x49, 0xbc); /*MOV r12,(uintptr_t) p*/ + codegen_alloc_bytes(block, 8); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV r9,(uintptr_t) p*/ codegen_addquad(block, (uintptr_t) p); - codegen_addbyte4(block, 0x41, 0x8b, 0x04 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, [R12]*/ - codegen_addbyte2(block, 0x41, 0x5c); /*POP r12*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/ } else { fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIX64 ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram); codegen_alloc_bytes(block, 6); From 7529c19ec89721859eb4e2705f7cf28f0b5338b4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 14:25:29 +0200 Subject: [PATCH 0901/1190] Reset all keys on keyboard reset and also make sure to stop the CTRL+ALT+DEL sending on keyboard reset, fixes spurious "Keyboard not present" errors. --- src/86box.c | 28 ++++++++++++++++++++++++++ src/device/keyboard.c | 38 ++++++++++++++++++++++++------------ src/device/keyboard_at.c | 4 ++++ src/include/86box/keyboard.h | 2 ++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/86box.c b/src/86box.c index 25dc0e6e9..f54a69b79 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1250,20 +1250,48 @@ pc_send_ca(uint16_t sc) if (keyboard_mode >= 0x81) { /* Use R-Alt because PS/55 DOS and OS/2 assign L-Alt Kanji */ keyboard_input(1, 0x1D); /* Ctrl key pressed */ + if (keyboard_get_in_reset()) + return; keyboard_input(1, 0x138); /* R-Alt key pressed */ + if (keyboard_get_in_reset()) + return; keyboard_input(1, sc); + if (keyboard_get_in_reset()) + return; usleep(50000); + if (keyboard_get_in_reset()) + return; keyboard_input(0, sc); + if (keyboard_get_in_reset()) + return; keyboard_input(0, 0x138); /* R-Alt key released */ + if (keyboard_get_in_reset()) + return; keyboard_input(0, 0x1D); /* Ctrl key released */ + if (keyboard_get_in_reset()) + return; } else { keyboard_input(1, 0x1D); /* Ctrl key pressed */ + if (keyboard_get_in_reset()) + return; keyboard_input(1, 0x38); /* Alt key pressed */ + if (keyboard_get_in_reset()) + return; keyboard_input(1, sc); + if (keyboard_get_in_reset()) + return; usleep(50000); + if (keyboard_get_in_reset()) + return; keyboard_input(0, sc); + if (keyboard_get_in_reset()) + return; keyboard_input(0, 0x38); /* Alt key released */ + if (keyboard_get_in_reset()) + return; keyboard_input(0, 0x1D); /* Ctrl key released */ + if (keyboard_get_in_reset()) + return; } } diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 800e7fb8e..6a5693f71 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -64,11 +64,12 @@ static int keydelay[512]; #endif static scancode *scan_table; /* scancode table for keyboard */ -static volatile uint8_t caps_lock = 0; -static volatile uint8_t num_lock = 0; -static volatile uint8_t scroll_lock = 0; -static volatile uint8_t kana_lock = 0; -static uint8_t shift = 0; +static volatile uint8_t caps_lock = 0; +static volatile uint8_t num_lock = 0; +static volatile uint8_t scroll_lock = 0; +static volatile uint8_t kana_lock = 0; +static volatile uint8_t kbd_in_reset = 0; +static uint8_t shift = 0; static int key5576mode = 0; @@ -106,11 +107,12 @@ static scconvtbl scconv55_8a[18 + 1] = void keyboard_init(void) { - num_lock = 0; - caps_lock = 0; - scroll_lock = 0; - kana_lock = 0; - shift = 0; + num_lock = 0; + caps_lock = 0; + scroll_lock = 0; + kana_lock = 0; + shift = 0; + kbd_in_reset = 0; memset(recv_key, 0x00, sizeof(recv_key)); memset(recv_key_ui, 0x00, sizeof(recv_key)); @@ -343,9 +345,9 @@ void keyboard_all_up(void) { for (unsigned short i = 0; i < 0x200; i++) { - if (recv_key_ui[i]) { + if (recv_key_ui[i]) recv_key_ui[i] = 0; - } + if (recv_key[i]) { recv_key[i] = 0; key_process(i, 0); @@ -353,6 +355,18 @@ keyboard_all_up(void) } } +void +keyboard_set_in_reset(uint8_t in_reset) +{ + kbd_in_reset = in_reset; +} + +uint8_t +keyboard_get_in_reset(void) +{ + return kbd_in_reset; +} + static uint8_t keyboard_do_break(uint16_t scan) { diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index fbf167e3f..4b1097df4 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -3476,7 +3476,10 @@ keyboard_at_bat(void *priv) keyboard_scan = 1; + keyboard_all_up(); keyboard_update_states(0, 0, 0, 0); + + keyboard_set_in_reset(0); kbc_at_dev_queue_add(dev, 0xaa, 0); } else { bat_counter--; @@ -3714,6 +3717,7 @@ keyboard_at_write(void *priv) break; case 0xff: /* reset */ + keyboard_set_in_reset(1); kbc_at_dev_reset(dev, 1); bat_counter = 1000; break; diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index f62896106..dd8cae54b 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -273,6 +273,8 @@ extern void keyboard_input(int down, uint16_t scan); extern void keyboard_all_up(void); extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl, uint8_t kl); extern uint8_t keyboard_get_shift(void); +extern void keyboard_set_in_reset(uint8_t in_reset); +extern uint8_t keyboard_get_in_reset(void); extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl, uint8_t *kl); extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); extern int keyboard_recv(uint16_t key); From 8577e0b532764353a2f09664753d353c48330c72 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 14:27:36 +0200 Subject: [PATCH 0902/1190] Also suppress any and all keyboard input while the keyboard is in reset. --- src/device/keyboard.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 6a5693f71..16904fe3b 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -240,6 +240,9 @@ key_process(uint16_t scan, int down) void keyboard_input(int down, uint16_t scan) { + if (kbd_in_reset) + return; + /* Special case for E1 1D, translate it to 0100 - special case. */ if ((scan >> 8) == 0xe1) { if ((scan & 0xff) == 0x1d) From 04b9735975e612bf0713d7b55037f5a3bc356e11 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 10 May 2025 22:11:19 +0200 Subject: [PATCH 0903/1190] Quick timer fix on the T128/PAS SCSI (May 10th, 2025) 1. If the timer result is less than 10.0 microseconds, then adjust it to 10.0. Fixes some timing read issues with the T128 (and possibly PAS SCSI). 2. Remove unused variables. --- src/scsi/scsi_t128.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 94166054c..c5a1c4e67 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -241,9 +241,14 @@ t128_callback(void *priv) uint8_t c; uint8_t temp; uint8_t status; + double period = scsi_bus->period / 60.0; - if (scsi_bus->tx_mode != PIO_TX_BUS) - timer_on_auto(&t128->timer, scsi_bus->period / 60.0); + if (scsi_bus->tx_mode != PIO_TX_BUS) { + if (period >= 10.0) + timer_on_auto(&t128->timer, period); + else + timer_on_auto(&t128->timer, 10.0); + } if (scsi_bus->data_wait & 1) { scsi_bus->clear_req = 3; @@ -287,7 +292,6 @@ t128_callback(void *priv) t128->status &= ~0x02; t128->pos = 0; t128->host_pos = 0; - scsi_bus->data_repeat = 0; t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); if (scsi_bus->data_pos >= dev->buffer_length) { t128->block_loaded = 0; @@ -336,7 +340,6 @@ t128_callback(void *priv) t128->status &= ~0x02; t128->pos = 0; t128->host_pos = 0; - scsi_bus->data_repeat = 0; t128_log("T128 blocks read=%d, total len=%d\n", scsi_bus->data_pos, dev->buffer_length); if (scsi_bus->data_pos >= dev->buffer_length) { scsi_bus->bus_out |= BUS_REQ; From e5606f75302ff0181991e2f15552d65a0052f0f4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 10 May 2025 23:14:10 +0200 Subject: [PATCH 0904/1190] Unix net socket: make the client socket non-blocking, fixes #5578. --- src/unix/unix_netsocket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/unix/unix_netsocket.c b/src/unix/unix_netsocket.c index d626d025b..850fa3c6c 100644 --- a/src/unix/unix_netsocket.c +++ b/src/unix/unix_netsocket.c @@ -94,6 +94,8 @@ plat_netsocket_accept(SOCKET socket) if (clientsocket == -1) return -1; + fcntl(clientsocket, F_SETFL, fcntl(clientsocket, F_GETFL, 0) | O_NONBLOCK); + return clientsocket; } From 709771742d4255e066b215d1f9d5a056ff6ea0b1 Mon Sep 17 00:00:00 2001 From: Dave Cuthbert Date: Sat, 10 May 2025 17:19:39 -0400 Subject: [PATCH 0905/1190] Update README.md Small wording tweaks for clarity --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ee0e1e7f1..506eba794 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ Minimum system requirements and recommendations * macOS version: macOS High Sierra 10.13 or newer * 4 GB of RAM or higher -Performance may vary depending on both host and guest configuration. Most emulation logic is executed in a single thread; therefore, systems with better IPC (instructions per clock) generally should be able to emulate higher clock speeds. +Performance may vary depending on host and guest configuration. Most emulation logic is executed in a single thread. Therefore, systems with greater IPC (instructions per clock) capacity should be able to emulate higher clock speeds. -It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines. +For easier handling of multiple virtual machines, use a manager application: * [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux) * [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only) @@ -37,7 +37,7 @@ It is also recommended to use a manager application with 86Box for easier handli * [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested) * [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only) -It is also possible to use 86Box on its own with the `--vmpath`/`-P` command line option. +To use 86Box on its own, use the `--vmpath`/`-P` command line option. Getting started --------------- @@ -47,7 +47,7 @@ See [our documentation](https://86box.readthedocs.io/en/latest/index.html) for a Community --------- -We operate an IRC channel and a Discord server for discussing 86Box, its development and anything related to retro computing. We look forward to hearing from you! +We operate an IRC channel and a Discord server for discussing 86Box, its development, and anything related to retro computing. We look forward to hearing from you! [![Visit our IRC channel](https://kiwiirc.com/buttons/irc.ringoflightning.net/86Box.png)](https://kiwiirc.com/client/irc.ringoflightning.net/?nick=86box|?#86Box) From 3b2ccf2229a15483f259a9afc5ddf20ec238a855 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 11 May 2025 03:46:06 +0600 Subject: [PATCH 0906/1190] Make sockets from incoming connections nonblocking on Windows --- src/qt/win_netsocket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/win_netsocket.c b/src/qt/win_netsocket.c index 55a84d414..d7d467c07 100644 --- a/src/qt/win_netsocket.c +++ b/src/qt/win_netsocket.c @@ -82,10 +82,12 @@ SOCKET plat_netsocket_accept(SOCKET socket) { SOCKET clientsocket = accept(socket, NULL, NULL); + u_long yes = 1; if (clientsocket == INVALID_SOCKET) return -1; + ioctlsocket(clientsocket, FIONBIO, &yes); return clientsocket; } From 750fa33136e05479b3eb5213525687dfd49e176c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 11 May 2025 22:01:24 +0600 Subject: [PATCH 0907/1190] Revert X11-related keyboard grabbing changes (except for `--nohook` ones) --- src/qt/qt_mainwindow.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index aaf625c2d..4594ee5be 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -327,8 +327,7 @@ MainWindow::MainWindow(QWidget *parent) if (ui->stackedWidget->mouse_capture_func) ui->stackedWidget->mouse_capture_func(this->windowHandle()); } else { - if (!(windowState() & Qt::WindowActive)) - this->releaseKeyboard(); + this->releaseKeyboard(); if (ui->stackedWidget->mouse_uncapture_func) { ui->stackedWidget->mouse_uncapture_func(); } @@ -1480,25 +1479,6 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) releaseKeyboard(); } else if (event->type() == QEvent::WindowUnblocked) { plat_pause(curdopause); -#ifdef __unix__ - if (!QApplication::platformName().contains("wayland") && (this->windowState() & Qt::WindowActive)) { - if (hook_enabled) - this->grabKeyboard(); - } -#endif - } else if (event->type() == QEvent::WindowActivate) { -#ifdef __unix__ - if (!QApplication::platformName().contains("wayland")) { - if (hook_enabled) - this->grabKeyboard(); - } -#endif - } else if (event->type() == QEvent::WindowDeactivate) { -#ifdef __unix__ - if (!QApplication::platformName().contains("wayland")) { - this->releaseKeyboard(); - } -#endif } } From f7079384f85ffc7649622fb61c67d309013ab0cd Mon Sep 17 00:00:00 2001 From: WinTP <1789016472@qq.com> Date: Tue, 13 May 2025 13:56:10 +0800 Subject: [PATCH 0908/1190] Update Simplified Chinese translation --- src/qt/languages/zh-CN.po | 72 +++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index d2ed7ce71..2af5abef9 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -849,8 +849,8 @@ msgstr "一个旧式计算机模拟器\n\n作者: Miran Grča (OBattler)、Richa msgid "Hardware not available" msgstr "硬件不可用" -msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection." -msgstr "请确认 %1 已安装且使用兼容 libpcap 的网络连接。" +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "请确认 %1 已安装且使用兼容 %1 的网络连接。" msgid "Invalid configuration" msgstr "无效配置" @@ -1240,7 +1240,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "主机 CD/DVD 驱动器 (%1:)" msgid "&Connected" -msgstr "" +msgstr "已连接(&C)" msgid "Clear image history" msgstr "清除映像历史记录" @@ -1300,7 +1300,7 @@ msgid "\nFalling back to software rendering." msgstr "\n回到软件渲染。" msgid "

    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.

    " -msgstr "

    选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

    选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

    " msgid "This machine might have been moved or copied." msgstr "这台机器可能被移动或复制过。" @@ -1315,7 +1315,7 @@ msgid "I Copied It" msgstr "我已复制这台机器" msgid "86Box Monitor #" -msgstr "86Box 监测器 " +msgstr "86Box 监测器 #" msgid "No MCA devices." msgstr "无 MCA 设备。" @@ -1804,7 +1804,7 @@ msgid "Five + Wheel" msgstr "五键+滚轮" msgid "Five + 2 Wheels" -msgstr "" +msgstr "五键+双滚轮" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 串行 / SMT3(R)V" @@ -2050,25 +2050,25 @@ msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM 磁盘 (最大速度)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Generic] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Generic] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Generic] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Generic] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" @@ -2076,6 +2076,12 @@ msgstr "IBM 8514/A 克隆 (ISA)" msgid "Vendor" msgstr "制造商" +msgid "30 Hz (JMP2 = 1)" +msgstr "30 Hz (JMP2 = 1)" + +msgid "60 Hz (JMP2 = 2)" +msgstr "60 Hz (JMP2 = 2)" + msgid "Generic PC/XT Memory Expansion" msgstr "通用 PC/XT 内存扩展" @@ -2089,61 +2095,61 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。" msgid "Inhibit multimedia keys" -msgstr "" +msgstr "禁止多媒体按键" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "保存设置前要求用户确认" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "硬重置前要求用户确认" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "退出前要求用户确认" msgid "Options" -msgstr "" +msgstr "选项" msgid "Model" -msgstr "" +msgstr "模型" msgid "Model:" -msgstr "" +msgstr "模型:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Vulkan 渲染器初始化失败。" msgid "GLSL Error" -msgstr "" +msgstr "GLSL 错误" msgid "Could not load shader: %1" -msgstr "" +msgstr "无法加载着色器:%1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL 版本需要达到 3.0 或更高。当前 GLSL 版本为 %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "无法加载材质:%1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "无法编译着色器:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "程序未链接:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "着色器管理器" msgid "Shader Configuration" -msgstr "" +msgstr "着色器配置" msgid "Add" -msgstr "" +msgstr "添加" msgid "Move up" -msgstr "" +msgstr "上移" msgid "Move down" -msgstr "" +msgstr "下移" msgid "Could not load file %1" -msgstr "" +msgstr "无法加载文件 %1" From 0157520b767042e022c98f8977f90fb2d3323759 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 13 May 2025 17:05:13 +0200 Subject: [PATCH 0909/1190] PS/2 mouse: fix the "no poll" condition. --- src/device/mouse_ps2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 0d34235fe..2c1722f51 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -333,13 +333,13 @@ ps2_poll(void *priv) atkbc_dev_t *dev = (atkbc_dev_t *) priv; int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3; - int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || !mouse_state_changed()) || - ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size))); + int cond = (mouse_capture || video_fullscreen) && mouse_scan && (dev->mode == MODE_STREAM) && + mouse_state_changed() && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size)); - if (!cond && (dev->mode == MODE_STREAM)) + if (cond) ps2_report_coordinates(dev, 1); - return cond; + return !cond; } /* From e8c8d3373e3bd8ef013907ad8e31c90db83557dd Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 14 May 2025 10:15:14 +0200 Subject: [PATCH 0910/1190] AT KBC: some fixes. --- src/device/kbc_at.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index aaa746570..2b9cf8c18 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2149,6 +2149,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->wantdata = 0; dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } break; @@ -2160,11 +2166,36 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->wantdata = 1; dev->state = STATE_KBC_PARAM; dev->command = 0xd1; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } else if (fast_reset && ((val & 0xf0) == 0xf0)) { pulse_output(dev, val & 0x0f); dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } else if (val == 0xad) { + /* Fast track it because of the Bochs BIOS. */ + kbc_at_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + + dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } else if (val == 0xae) { /* Fast track it because of the LG MultiNet. */ @@ -2172,6 +2203,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) set_enable_kbd(dev, 1); dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } break; From cb6712805973a8a85b1a211fe9aa9d2327fbb9c7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 14 May 2025 19:08:35 +0200 Subject: [PATCH 0911/1190] AT / PS/2 keyboard: abort any pending scan code send and reinitialize queue on set defaults (command F5/F6). --- src/device/kbc_at.c | 1 + src/device/kbc_at_dev.c | 2 +- src/include/86box/keyboard.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 2b9cf8c18..ce80209a7 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -220,6 +220,7 @@ kbc_at_set_fast_reset(const uint8_t new_fast_reset) fast_reset = new_fast_reset; } +#define ENABLE_KBC_AT_LOG 1 #ifdef ENABLE_KBC_AT_LOG int kbc_at_do_log = ENABLE_KBC_AT_LOG; diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index c1041e6e1..cd55f91fa 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -58,7 +58,7 @@ kbc_at_dev_log(const char *fmt, ...) # define kbc_at_dev_log(fmt, ...) #endif -static void +void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main) { if (reset_main) { diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index dd8cae54b..9dfb1c8e4 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -291,6 +291,7 @@ extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t v extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); extern void kbc_at_handler(int set, void *priv); +extern void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main); extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main); extern void kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main); extern void kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa); From f09ebba33031f94d04c036e149482e26443697f6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 14 May 2025 19:18:49 +0200 Subject: [PATCH 0912/1190] Fix the previous commit. --- src/device/kbc_at.c | 1 - src/device/keyboard_at.c | 181 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index ce80209a7..2b9cf8c18 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -220,7 +220,6 @@ kbc_at_set_fast_reset(const uint8_t new_fast_reset) fast_reset = new_fast_reset; } -#define ENABLE_KBC_AT_LOG 1 #ifdef ENABLE_KBC_AT_LOG int kbc_at_do_log = ENABLE_KBC_AT_LOG; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 4b1097df4..ee5036f74 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -428,11 +428,11 @@ static const scancode scancode_set1[512] = { { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */ { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */ { .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */ - { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */ + { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xda, 0 } }, /* 15a */ { .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */ { .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */ { .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */ - { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */ + { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xde, 0 } }, /* 15e */ { .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */ { .mk = { 0 }, .brk = { 0 } }, /* 160 */ { .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */ @@ -3643,6 +3643,13 @@ keyboard_at_write(void *priv) case 0xf6: /* set defaults */ keyboard_at_log("%s: set defaults%s\n", dev->name, (val == 0xf6) ? "" : " and disable keyboard"); + dev->port->out_new = -1; + dev->port->wantcmd = 0; + + kbc_at_dev_queue_reset(dev, 1); + + dev->last_scan_code = 0x00; + keyboard_scan = !(val & 0x01); keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n", dev->name, val, keyboard_scan); @@ -3728,6 +3735,44 @@ keyboard_at_write(void *priv) } } +#ifdef SCAN_CODE_TABLES_COMPARISON +/* Non-translated to translated scan codes. */ +static const uint8_t nont_to_t[256] = { + 0x00, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, + 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, + 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, + 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, + 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, + 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, + 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, + 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, + 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, + 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, + 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, + 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; +#endif + /* * Initialize the device for use by the user. * @@ -3777,6 +3822,138 @@ keyboard_at_init(const device_t *info) inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa; +#ifdef SCAN_CODE_TABLES_COMPARISON + pclog_toggle_suppr(); + + pclog("Scan code set 01 vs. 81 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set1[i].mk[j] == scancode_set81[i].mk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].mk[j], scancode_set81[i].mk[j]); + j++; + } while ((scancode_set1[i].mk[j] != 0) && (scancode_set81[i].mk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 81 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set1[i].brk[j] == scancode_set81[i].brk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].brk[j], scancode_set81[i].brk[j]); + j++; + } while ((scancode_set1[i].brk[j] != 0) && (scancode_set81[i].brk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 02 vs. 82 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set2[i].mk[j] == scancode_set82[i].mk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set2[i].mk[j], scancode_set82[i].mk[j]); + j++; + } while ((scancode_set2[i].mk[j] != 0) && (scancode_set82[i].mk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 02 vs. 82 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set2[i].brk[j] == scancode_set82[i].brk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set2[i].brk[j], scancode_set82[i].brk[j]); + j++; + } while ((scancode_set2[i].brk[j] != 0) && (scancode_set82[i].brk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 02 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + int k = 0; + int was_f0 = 0; + do { + if (scancode_set2[i].mk[k] == 0xf0) + was_f0 = 1; + else { + uint8_t code = nont_to_t[scancode_set2[i].mk[k]]; + + if (was_f0) { + if (code & 0x80) + code = 0x00; + else + code |= 0x80; + + was_f0 = 0; + } + + if (scancode_set1[i].mk[j] == code) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].mk[j], code); + + j++; + } + + k++; + } while ((scancode_set1[i].mk[j] != 0) && (scancode_set2[i].mk[k] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 02 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + int k = 0; + int was_f0 = 0; + do { + if (scancode_set2[i].brk[k] == 0xf0) + was_f0 = 1; + else { + uint8_t code = nont_to_t[scancode_set2[i].brk[k]]; + + if (was_f0) { + if (code & 0x80) + code = 0x00; + else + code |= 0x80; + + was_f0 = 0; + } + + if (scancode_set1[i].brk[j] == code) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].brk[j], code); + + j++; + } + + k++; + } while ((scancode_set1[i].brk[j] != 0) && (scancode_set2[i].brk[k] != 0)); + pclog("\n"); + } + + pclog_toggle_suppr(); + + fatal("Comparison finished\n"); +#endif + /* Return our private data to the I/O layer. */ return dev; } From 4fb38db2f8694c3856fb77f1600400d8acdd7f26 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 14 May 2025 20:12:17 +0200 Subject: [PATCH 0913/1190] Update machine.h Add the Phoenix BIOS variant for the Micronics 09-00021 (part 1) --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c28add516..8abd8fef1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -519,6 +519,7 @@ extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); extern int machine_at_spc6000a_init(const machine_t *); extern int machine_at_micronics386_init(const machine_t *); +extern int machine_at_micronics386px_init(const machine_t *); extern int machine_at_ecs386v_init(const machine_t *); extern int machine_at_tandy4000_init(const machine_t *); From bf07f6452e4781ba1cd8ee2c2ca1db8169ed1e53 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 14 May 2025 20:15:21 +0200 Subject: [PATCH 0914/1190] Add the Phoenix BIOS variant for the Micronics 09-00021 (part 2) --- src/machine/m_at_286_386sx.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b084bfbbd..c9fb124cb 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -281,6 +281,26 @@ machine_at_micronics386_init(const machine_t *model) return ret; } +int +machine_at_micronics386px_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-LO.BIN", + "roms/machines/micronics386/386-Micronics-09-00021-HI.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_init(model); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_scat_init(const machine_t *model, int is_v4, int is_ami) { From b334bd09aff796983da71dec7c8f4057e85795b9 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 14 May 2025 20:18:24 +0200 Subject: [PATCH 0915/1190] Add the Phoenix BIOS variant for the Micronics 09-00021 (part 3) --- src/machine/machine_table.c | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 34e69ed24..5acee0350 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5435,7 +5435,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[ISA] Micronics 09-00021", + .name = "[ISA] Micronics 09-00021 (Tandon BIOS)", .internal_name = "micronics386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_DISCRETE, @@ -5474,6 +5474,46 @@ const machine_t machines[] = { .net_device = NULL }, /* Has IBM AT KBC firmware. */ + { + .name = "[ISA] Micronics 09-00021 (Phoenix BIOS)", + .internal_name = "micronics386px", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_micronics386px_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, + .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_APM, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .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 = "[ISA] Tandy 4000", .internal_name = "tandy4000", From c804a2892a9f1b48f4fc80503d75c77e7410de79 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 15 May 2025 00:27:46 +0200 Subject: [PATCH 0916/1190] Some more Compaq AT changes of the night (May 15th, 2025) 1. Properly return the flat panel display bit in port 0x1bc6, fixes adapt.com and the corresponding Portable identification in the disk cmos. 2. Preliminary MDA mapping on the Plasma display, per bit 3 toggling of port 0x23c6. 3. Implemented port 0x17c6. 4. Cleanups. --- src/machine/m_at_compaq.c | 552 +++++++++++++++++++++----------------- 1 file changed, 304 insertions(+), 248 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 904122bad..c0b254388 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -61,11 +61,6 @@ enum { /*Very rough estimate*/ #define VID_CLOCK (double) (651 * 416 * 60) -static uint8_t cga_crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - /* Mapping of attributes to colours */ static uint32_t amber; static uint32_t black; @@ -97,7 +92,10 @@ compaq_plasma_display_get(void) typedef struct compaq_plasma_t { cga_t cga; + uint8_t ctl_mode; + uint8_t port_13c6; uint8_t port_23c6; + uint8_t port_27c6; uint8_t internal_monitor; uint8_t attrmap; } compaq_plasma_t; @@ -116,16 +114,18 @@ compaq_plasma_recalctimings(compaq_plasma_t *self) double _dispofftime; double disptime; - if (!self->internal_monitor && !(self->port_23c6 & 1)) { + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { cga_recalctimings(&self->cga); return; } disptime = 651; _dispontime = 640; - _dispofftime = disptime - _dispontime; - self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); - self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST / 2; + _dispofftime *= CGACONST / 2; + self->cga.dispontime = (uint64_t) (_dispontime); + self->cga.dispofftime = (uint64_t) (_dispofftime); } static void @@ -144,9 +144,9 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; self->cga.vram[addr & 0x7fff] = val; + compaq_plasma_waitstates(&self->cga); } - static uint8_t compaq_plasma_read(uint32_t addr, void *priv) { @@ -163,49 +163,59 @@ static void compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t old; + + if (self->port_23c6 & 0x08) { + if ((addr >= 0x3d0) && (addr <= 0x3dc)) + addr ^= 0x60; + } switch (addr) { /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: case 0x3d4: + case 0x3d6: cga_out(addr, val, &self->cga); break; /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: case 0x3d5: - old = self->cga.crtc[self->cga.crtcreg]; - self->cga.crtc[self->cga.crtcreg] = val & cga_crtcmask[self->cga.crtcreg]; - + case 0x3d7: /* Register 0x12 controls the attribute mappings for the * plasma screen. */ if (self->cga.crtcreg == 0x12) { self->attrmap = val; compaq_plasma_recalcattrs(self); - break; + return; } + cga_out(addr, val, &self->cga); - if (old != val) { - if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) { - self->cga.fullchange = changeframecount; - compaq_plasma_recalctimings(self); - } - } + compaq_plasma_recalctimings(self); break; case 0x3d8: case 0x3d9: + case 0x3db: + case 0x3dc: cga_out(addr, val, &self->cga); break; case 0x13c6: - compaq_plasma_display_set((val & 8) ? 1 : 0); + self->port_13c6 = val; + compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); break; case 0x23c6: self->port_23c6 = val; - if (val & 8) /* Disable internal CGA */ - mem_mapping_disable(&self->cga.mapping); + if (val & 0x08) /* Disable internal CGA */ + mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x8000); else - mem_mapping_enable(&self->cga.mapping); + mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x8000); + break; + + case 0x27c6: + self->port_27c6 = val; break; default: @@ -219,40 +229,53 @@ compaq_plasma_in(uint16_t addr, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; uint8_t ret = 0xff; + if (self->port_23c6 & 0x08) { + if ((addr >= 0x3d0) && (addr <= 0x3dc)) + addr ^= 0x60; + } + switch (addr) { case 0x3d4: case 0x3da: + case 0x3db: + case 0x3dc: ret = cga_in(addr, &self->cga); break; + case 0x3d1: + case 0x3d3: case 0x3d5: + case 0x3d7: if (self->cga.crtcreg == 0x12) { ret = self->attrmap & 0x0f; - if (self->internal_monitor) + if (compaq_plasma_display_get()) ret |= 0x30; /* Plasma / CRT */ } else ret = cga_in(addr, &self->cga); + break; + + case 0x3d8: + ret = self->cga.cgamode; break; case 0x13c6: - ret = compaq_plasma_display_get() ? 8 : 0; - ret |= 4; + ret = self->port_13c6; + break; + + case 0x17c6: + ret = 0xf6; break; case 0x1bc6: - ret = 0; - if (compaq_plasma_display_get()) { - if ((self->cga.cgamode & 0x12) == 0x12) { - if (self->port_23c6 & 8) - ret |= 0x40; - else - ret |= 0x20; - } - } + ret = 0x40; break; case 0x23c6: - ret = 0; + ret = self->port_23c6; + break; + + case 0x27c6: + ret = self->port_27c6 & 0x3f; break; default: @@ -276,6 +299,8 @@ compaq_plasma_poll(void *priv) int cursorline; int blink = 0; int underline = 0; + int c; + int x; uint32_t ink = 0; uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; uint32_t bg = black; @@ -292,230 +317,252 @@ compaq_plasma_poll(void *priv) } /* graphic mode and not mode 40h */ - if (!self->internal_monitor && !(self->port_23c6 & 1)) { + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { + /* standard cga mode */ cga_poll(&self->cga); return; - } + } else { + /* mode 40h or text mode */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + self->cga.linepos = 1; + if (self->cga.cgadispon) { + if (self->cga.displine == 0) + video_wait_for_buffer(); - /* mode 40h or text mode */ - if (!self->cga.linepos) { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - if (self->cga.cgadispon) { - if (self->cga.displine == 0) { - video_wait_for_buffer(); - } - if (self->cga.cgamode & 2) { - if (self->cga.cgamode & 0x10) { - /* 640x400 mode */ - if (self->port_23c6 & 1) /* 640*400 */ { - addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7FFF]; - addr++; + /* 80-col */ + if (self->cga.cgamode & 0x01) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; + ma += (self->cga.displine >> 4) * 80; - for (uint8_t c = 0; c < 8; c++) { - ink = (dat & 0x80) ? fg : bg; - if (!(self->cga.cgamode & 8)) - ink = black; - (buffer32->line[self->cga.displine])[x * 8 + c] = ink; - dat <<= 1; + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + + /* for each text column */ + for (x = 0; x < 80; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else + chr = attr = 0; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + blink = ((attr & 0x80) << 3) + 7 + 16; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ma++; + } + } + /* 40-col */ + else if (!(self->cga.cgamode & 0x02)) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; + ma += (self->cga.displine >> 4) * 40; + + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + + for (x = 0; x < 40; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else + chr = attr = 0; + + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + blink = ((attr & 0x80) << 3) + 7 + 16; + } + + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (self->cga.sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ma++; } } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7fff]; - addr++; + if (self->cga.cgamode & 0x10) { + /* 640x400 mode */ + if (self->port_23c6 & 0x01) /* 640*400 */ { + addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - for (uint8_t c = 0; c < 4; c++) { - pattern = (dat & 0xC0) >> 6; - if (!(self->cga.cgamode & 8)) - pattern = 0; - - switch (pattern & 3) { - case 0: - ink0 = ink1 = black; - break; - case 1: - if (self->cga.displine & 1) { - ink0 = black; - ink1 = black; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 2: - if (self->cga.displine & 1) { - ink0 = black; - ink1 = amber; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 3: - ink0 = ink1 = amber; - break; - - default: - break; + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(self->cga.cgamode & 0x08)) + ink = black; + buffer32->line[self->cga.displine][(x << 3) + c] = ink; + dat <<= 1; } - buffer32->line[self->cga.displine][x * 8 + 2 * c] = ink0; - buffer32->line[self->cga.displine][x * 8 + 2 * c + 1] = ink1; - dat <<= 2; - } - } - } - } else if (self->cga.cgamode & 1) { - /* 80-col */ - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) * 2; - ma += (self->cga.displine >> 4) * 80; - - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); - - /* for each text column */ - for (uint8_t x = 0; x < 80; x++) { - /* video output enabled */ - chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; - attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); - /* blink active */ - if (self->cga.cgamode & 0x20) { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if (blink) { - /* set blinking */ - cols[1] = cols[0]; } } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - ++ma; - } - } else { /* 40-col */ - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) * 2; - ma += (self->cga.displine >> 4) * 40; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(self->cga.cgamode & 0x08)) + pattern = 0; - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; + break; + case 1: + case 2: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = amber; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 3: + ink0 = ink1 = amber; + break; - for (uint8_t x = 0; x < 40; x++) { - chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; - attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); - /* blink active */ - if (self->cga.cgamode & 0x20) { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if (blink) { - /* set blinking */ - cols[1] = cols[0]; + default: + break; + } + buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0; + buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1; + dat <<= 2; + } } - } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c * 2)] = buffer32->line[self->cga.displine][(x << 4) + (c * 2) + 1] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; } } - } - self->cga.displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (self->cga.displine == 400) { /* Start of VSYNC */ - self->cga.cgastat |= 8; - self->cga.cgadispon = 0; - } - if (self->cga.displine == 416) { /* End of VSYNC */ - self->cga.displine = 0; - self->cga.cgastat &= ~8; - self->cga.cgadispon = 1; - } - } else { - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; + self->cga.displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (self->cga.displine == 400) { /* Start of VSYNC */ + self->cga.cgastat |= 8; + self->cga.cgadispon = 0; + } + if (self->cga.displine == 416) { /* End of VSYNC */ + self->cga.displine = 0; + self->cga.cgastat &= ~8; + self->cga.cgadispon = 1; + } + } else { + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - self->cga.linepos = 0; + self->cga.linepos = 0; - if (self->cga.displine == 400) { - /* Hardcode 640x400 window size */ - if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) { + if (self->cga.displine == 400) { xsize = 640; ysize = 400; - if (xsize < 64) - xsize = 656; - if (ysize < 32) - ysize = 200; - set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); + if ((self->cga.cgamode & 0x08) || video_force_resize_get()) { + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + /* ogc specific */ + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; + + /* Fixed 640x400 resolution */ + video_res_x = 640; + video_res_y = 400; + + if (self->cga.cgamode & 0x02) { + if (self->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + self->cga.cgablink++; } - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; - - /* Fixed 640x400 resolution */ - video_res_x = 640; - video_res_y = 400; - - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) - video_bpp = 1; - else - video_bpp = 2; - } else - video_bpp = 0; - - self->cga.cgablink++; } } } @@ -560,7 +607,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) /* Set up colours */ amber = makecol(0xff, 0x7d, 0x00); - black = makecol(0x64, 0x0c, 0x00); + black = makecol(0x64, 0x19, 0x00); /* Initialize the attribute mapping. Start by defaulting everything * to black on amber, and with bold set by bit 3 */ @@ -631,12 +678,14 @@ compaq_plasma_init(UNUSED(const device_t *info)) { compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); if (compaq_machine_type == COMPAQ_PORTABLEIII) loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); else loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49); + cga_init(&self->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); + self->cga.composite = 0; self->cga.revision = 0; @@ -644,12 +693,16 @@ compaq_plasma_init(UNUSED(const device_t *info)) self->internal_monitor = 1; cga_comp_init(self->cga.revision); - timer_add(&self->cga.timer, compaq_plasma_poll, self, 1); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); - io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x13c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x1bc6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x23c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + timer_set_callback(&self->cga.timer, compaq_plasma_poll); + timer_set_p(&self->cga.timer, self); + + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); + for (int i = 1; i <= 2; i++) { + io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + } + io_sethandler(0x03d0, 0x000c, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); /* Default attribute mapping is 4 */ self->attrmap = 4; @@ -793,7 +846,8 @@ machine_at_compaq_init(const machine_t *model, int type) switch (type) { case COMPAQ_PORTABLEII: - machine_at_init(model); + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; case COMPAQ_PORTABLEIII: @@ -801,7 +855,9 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); - machine_at_init(model); + + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; case COMPAQ_PORTABLEIII386: From 6aec346cc5e88f5012a9a764ba5c729373fcb174 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 May 2025 04:11:29 +0200 Subject: [PATCH 0917/1190] AT keyboard: Fix last scan code resending, fixes E0-prefixed keys on some machines. --- src/device/kbc_at_dev.c | 10 ++++++---- src/device/keyboard_at.c | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index cd55f91fa..b20e38860 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -95,10 +95,6 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main) dev->cmd_queue[dev->cmd_queue_end] = val; dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf; } - - /* TODO: This should be done on actual send to host. */ - if (val != 0xfe) - dev->last_scan_code = val; } static void @@ -123,6 +119,8 @@ kbc_at_dev_poll(void *priv) (dev->queue_start != dev->queue_end)) { kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]); dev->port->out_new = dev->queue[dev->queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask; } if (dev->ignore || !(*dev->scan) || dev->port->wantcmd) @@ -143,6 +141,8 @@ kbc_at_dev_poll(void *priv) if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; } if (dev->cmd_queue_start == dev->cmd_queue_end) @@ -166,6 +166,8 @@ kbc_at_dev_poll(void *priv) if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; } if (dev->cmd_queue_start == dev->cmd_queue_end) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index ee5036f74..7fa2b9706 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -3494,7 +3494,6 @@ keyboard_at_invalid_cmd(atkbc_dev_t *dev) kbc_at_dev_queue_add(dev, inv_cmd_response, 0); } - static void keyboard_at_write(void *priv) { @@ -3719,7 +3718,6 @@ keyboard_at_write(void *priv) /* TODO: This is supposed to resend multiple bytes after some commands. */ case 0xfe: /* resend last scan code */ keyboard_at_log("%s: resend last scan code\n", dev->name); - kbc_at_dev_queue_add(dev, 0xfa, 0); kbc_at_dev_queue_add(dev, dev->last_scan_code, 0); break; From 4331d78b829427024a4e46e338655c279929f92c Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 May 2025 04:26:14 +0200 Subject: [PATCH 0918/1190] Added the DTK PKM-0031Y. --- src/chipset/CMakeLists.txt | 1 + src/chipset/sl82c461.c | 362 +++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 3 + src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 21 ++ src/machine/machine_table.c | 40 ++++ 6 files changed, 428 insertions(+) create mode 100644 src/chipset/sl82c461.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 94ef408f6..7d17b9983 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -72,6 +72,7 @@ add_library(chipset OBJECT sis_5572_usb.c sis_5595_pmu.c sis_55xx.c + sl82c461.c via_vt82c49x.c via_vt82c505.c gc100.c diff --git a/src/chipset/sl82c461.c b/src/chipset/sl82c461.c new file mode 100644 index 000000000..f94aa2e99 --- /dev/null +++ b/src/chipset/sl82c461.c @@ -0,0 +1,362 @@ +/* + * 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. + * + * Implementation of the Symphony SL82C461 (Haydn II) chipset. + * + * Symphony SL82C461 Configuration Registers (WARNING: May be inaccurate!): + * + * - Register 00h: + * - Bit 6: External cache present (if clear, AMI BIOS'es will not + * allow enabling external cache). + * + * - Register 01h: + * - Bit 0: Fast Gate A20 Enable (Handler mostly). + * Is it? Enabling/disabling fast gate A20 doesn't appear + * to do much to any register at all. + * + * - Register 02h: + * - Bit 0: Optional Chipset Turbo Pin; + * - Bits 4-2: + * - 000 = CLK2/3; + * - 001 = CLK2/4; + * - 010 = CLK2/5; + * - 011 = 7.159 MHz (ATCLK2); + * - 100 = CLK2/6; + * - 110 = CLK2/2.5; + * - 111 = CLK2/2. + * + * - Register 06h: + * - Bit 2: Decoupled Refresh Option. + * + * - Register 08h: + * - Bits 3, 2: I/O Recovery Time (SYSCLK): + * - 0, 0 = 0; + * - 1, 1 = 12. + * - Bit 1: Extended ALE. + * + * - Register 25h: + * Bit 7 here causes AMI 111192 CMOS Setup to return 7168 KB RAM + * instead of 6912 KB. This is 256 KB off. Relocation? + * Also, returning bit 5 clear instead of set, causes the AMI BIOS + * to set bits 0,1 of register 45h to 1,0 instead of 0,1. + * + * - Register 2Dh: + * - Bit 7: Enable 256KB Memory Relocation; + * - Bit 6: Enable 384KB Memory Relocation, bit 7 must also be set. + * + * - Register 2Eh: + * - Bit 7: CC000-CFFFF Shadow Read Enable; + * - Bit 6: CC000-CFFFF Shadow Write Enable; + * - Bit 5: C8000-CBFFF Shadow Read Enable; + * - Bit 4: C8000-CBFFF Shadow Write Enable; + * - Bit 3: C4000-C7FFF Shadow Read Enable; + * - Bit 2: C4000-C7FFF Shadow Write Enable; + * - Bit 1: C0000-C3FFF Shadow Read Enable; + * - Bit 0: C0000-C3FFF Shadow Write Enable. + * + * - Register 2Fh: + * - Bit 7: DC000-DFFFF Shadow Read Enable; + * - Bit 6: DC000-DFFFF Shadow Write Enable; + * - Bit 5: D8000-DBFFF Shadow Read Enable; + * - Bit 4: D8000-DBFFF Shadow Write Enable; + * - Bit 3: D4000-D7FFF Shadow Read Enable; + * - Bit 2: D4000-D7FFF Shadow Write Enable; + * - Bit 1: D0000-D3FFF Shadow Read Enable; + * - Bit 0: D0000-D3FFF Shadow Write Enable. + * + * - Register 30h: + * - Bit 7: E0000-EFFFF Shadow Read Enable; + * - Bit 6: E0000-EFFFF Shadow Write Enable. + * + * - Register 31h: + * - Bit 7: F0000-FFFFF Shadow Read Enable; + * - Bit 6: F0000-FFFFF Shadow Write Enable. + * + * - Register 33h (NOTE: Waitstates also affect register 32h): + * - Bits 3, 0: + * - 0,0 = 0 W/S; + * - 1,0 = 1 W/S; + * - 1,1 = 2 W/S. + * + * - Register 40h: + * - Bit 3: External Cache Enabled (0 = yes, 1 = no); + * I also see bits 5, 4, 3 of register 44h affected: + * - 38h (so all 3 set) when cache is disabled; + * - 00h (all 3 clear) when it's enabled. + * + * - Register 45h: + * - Bit 3: Video Shadow RAM Cacheable; + * - Bit 4: Adapter Shadow RAM Cacheable; + * - Bit 5: BIOS Shadow RAM Cacheable. + * + * Authors: Miran Grca, + * Tiseno100, + * + * Copyright 2025 Miran Grca. + * Copyright 2021-2025 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/chipset.h> + +typedef struct { + uint8_t index; + uint8_t regs[256]; + uint8_t shadow[4]; +} sl82c461_t; + +#ifdef ENABLE_SL82C461_LOG +int sl82c461_do_log = ENABLE_SL82C461_LOG; + +static void +sl82c461_log(const char *fmt, ...) +{ + va_list ap; + + if (sl82c461_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define sl82c461_log(fmt, ...) +#endif + +static void +sl82c461_recalcmapping(sl82c461_t *dev) +{ + int do_shadow = 0; + + for (uint32_t i = 0; i < 8; i += 2) { + if ((dev->regs[0x2e] ^ dev->shadow[0x00]) & (3 << i)) { + uint32_t base = 0x000c0000 + ((i >> 1) << 14); + uint32_t read = ((dev->regs[0x2e] >> i) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x2e] >> i) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00004000, read | write); + + do_shadow++; + } + + if ((dev->regs[0x2f] ^ dev->shadow[0x01]) & (3 << i)) { + uint32_t base = 0x000d0000 + ((i >> 1) << 14); + uint32_t read = ((dev->regs[0x2f] >> i) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x2f] >> i) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00004000, read | write); + + do_shadow++; + } + } + + if ((dev->regs[0x30] ^ dev->shadow[0x02]) & 0xc0) { + uint32_t base = 0x000e0000; + uint32_t read = ((dev->regs[0x30] >> 6) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x30] >> 6) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00010000, read | write); + + do_shadow++; + } + + if ((dev->regs[0x31] ^ dev->shadow[0x03]) & 0xc0) { + uint32_t base = 0x000f0000; + uint32_t read = ((dev->regs[0x31] >> 6) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x31] >> 6) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + shadowbios = !!((dev->regs[0x31] >> 6) & 0x02); + shadowbios_write = !!((dev->regs[0x31] >> 6) & 0x01); + + mem_set_mem_state_both(base, 0x00010000, read | write); + + do_shadow++; + } + + if (do_shadow) { + memcpy(dev->shadow, &(dev->regs[0x2e]), 4 * sizeof(uint8_t)); + flushmmucache_nopc(); + } +} + +static void +sl82c461_write(uint16_t addr, uint8_t val, void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + + sl82c461_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + if (addr & 0x0001) { + dev->regs[dev->index] = val; + + switch (dev->index) { + case 0x01: + /* NOTE: This is to be verified. */ + mem_a20_alt = val & 1; + mem_a20_recalc(); + break; + case 0x02: { + double bus_clk; + switch (val & 0x1c) { + case 0x00: + bus_clk = cpu_busspeed / 3.0; + break; + case 0x04: + bus_clk = cpu_busspeed / 4.0; + break; + case 0x08: + bus_clk = cpu_busspeed / 5.0; + break; + default: + case 0x0c: + bus_clk = 7159091.0; + break; + case 0x10: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x18: + bus_clk = cpu_busspeed / 2.5; + break; + case 0x1c: + bus_clk = cpu_busspeed / 2.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + break; + } case 0x2d: + switch (val & 0xc0) { + case 0xc0: + mem_remap_top(384); + break; + case 0x80: + mem_remap_top(256); + break; + default: + case 0x00: + mem_remap_top(0); + break; + } + break; + case 0x2e ... 0x31: + sl82c461_recalcmapping(dev); + break; + case 0x33: + switch (val & 0x09) { + default: + case 0x00: + cpu_waitstates = 0; + break; + case 0x08: + cpu_waitstates = 1; + break; + case 0x09: + cpu_waitstates = 2; + break; + } + cpu_update_waitstates(); + break; + case 0x40: + cpu_cache_ext_enabled = !(val & 0x08); + cpu_update_waitstates(); + break; + } + } else + dev->index = val; +} + +static uint8_t +sl82c461_read(uint16_t addr, void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + uint8_t ret = 0x00; + + if (addr & 0x0001) + if (dev->index == 0x00) + ret = dev->regs[dev->index] | 0x40; + else + ret = dev->regs[dev->index]; + else + ret = dev->index; + + sl82c461_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +static void +sl82c461_close(void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + + free(dev); +} + +static void * +sl82c461_init(const device_t *info) +{ + sl82c461_t *dev = (sl82c461_t *) calloc(1, sizeof(sl82c461_t)); + + dev->regs[0x00] = 0x40; + + dev->regs[0x02] = 0x0c; + dev->regs[0x40] = 0x08; + + memset(dev->shadow, 0xff, 4 * sizeof(uint8_t)); + + mem_a20_alt = 0x00; + mem_a20_recalc(); + + cpu_set_isa_speed(7159091.0); + + sl82c461_recalcmapping(dev); + + cpu_waitstates = 0; + cpu_cache_ext_enabled = 0; + + cpu_update_waitstates(); + + io_sethandler(0x00a8, 2, + sl82c461_read, NULL, NULL, + sl82c461_write, NULL, NULL, dev); + + return dev; +} + +const device_t sl82c461_device = { + .name = "Symphony SL82C461 (Haydn II)", + .internal_name = "sis_85c471", + .flags = 0, + .local = 0, + .init = sl82c461_init, + .close = sl82c461_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index fe088b209..94884383b 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -159,6 +159,9 @@ extern const device_t stpc_atlas_device; extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; +/* Symphony */ +extern const device_t sl82c461_device; + /* UMC */ extern const device_t umc_8886f_device; extern const device_t umc_8886af_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 8abd8fef1..77768832e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -555,6 +555,7 @@ extern int machine_at_aptiva510_init(const machine_t *); extern int machine_at_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); +extern int machine_at_dtk461_init(const machine_t *); extern int machine_at_sis401_init(const machine_t *); extern int machine_at_isa486_init(const machine_t *); extern int machine_at_av4_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e75c5414e..fded8c094 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -134,6 +134,27 @@ machine_at_tandy4000_init(const machine_t *model) return ret; } +int +machine_at_dtk461_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dtk461/DTK.BIO", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sl82c461_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_sis401_common_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5acee0350..e60ccf71d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6403,6 +6403,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMIKey F KBC firmware. */ + { + .name = "[Symphony SL42C460] DTK PKM-0031Y", + .internal_name = "dtk461", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SYMPHONY_SL82C460, + .init = machine_at_dtk461_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_APM, + .ram = { + .min = 1024, + .max = 65536, + .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 + }, /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, but it does not write a byte after C9, which is consistent with AMIKey, so From 4beee4452b8e83cc0cb0da70dc0289ab004629f7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 May 2025 05:15:15 +0200 Subject: [PATCH 0919/1190] Siemens D824: Use the VL82C113 (should be 114 but the only datasheet available of it, has no registers, but says it's backwards compatible with the 113). --- src/machine/m_at_386dx_486.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index fded8c094..0e382d0c4 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -443,7 +443,11 @@ machine_at_d824_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); - device_add(&keyboard_ps2_device); + /* + Technically, it should be the VL82C114 but we do not have + a proper datasheet of it that tells us the registers. + */ + device_add(&vl82c113_device); device_add(&ide_isa_device); device_add(&fdc37c651_device); From 1995ee582a7e15cfb4dbd8b4db940ffe78b3e243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Thu, 15 May 2025 06:46:10 +0200 Subject: [PATCH 0920/1190] DTK PKM-0031Y: Fix RAM limits. --- 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 e60ccf71d..e5310d7c0 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6428,7 +6428,7 @@ const machine_t machines[] = { .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 65536, + .max = 32768, .step = 1024 }, .nvrmask = 127, From 94313fed0373296af47857a8bb79cfc63127d9c9 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Thu, 15 May 2025 17:44:54 -0300 Subject: [PATCH 0921/1190] AC97: Add Winbond W83971D codec --- src/include/86box/snd_ac97.h | 2 ++ src/sound/snd_ac97_codec.c | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/include/86box/snd_ac97.h b/src/include/86box/snd_ac97.h index 45a921863..a365f5afa 100644 --- a/src/include/86box/snd_ac97.h +++ b/src/include/86box/snd_ac97.h @@ -100,6 +100,7 @@ #define AC97_CODEC_STAC9708 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08) #define AC97_CODEC_STAC9721 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09) #define AC97_CODEC_TR28023 AC97_VENDOR_ID('T', 'R', 'A', 0x03) +#define AC97_CODEC_W83971D AC97_VENDOR_ID('W', 'E', 'C', 0x01) #define AC97_CODEC_WM9701A AC97_VENDOR_ID('W', 'M', 'L', 0x00) typedef struct ac97_vendor_reg_t { @@ -150,6 +151,7 @@ extern const device_t cs4297a_device; extern const device_t stac9708_device; extern const device_t stac9721_device; extern const device_t tr28023_device; +extern const device_t w83971d_device; extern const device_t wm9701a_device; extern const device_t ac97_via_device; diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index e92830f67..4a9c1e6c6 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -104,6 +104,12 @@ static const struct { .extid_flags = 0, .pcsr_mask = 0x3f }, + { + .device = &w83971d_device, + .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = (27 << AC97_3D_SHIFT), + .pcsr_mask = 0x3f + }, { .device = &wm9701a_device, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, @@ -284,8 +290,9 @@ line_gain: case 0x22: /* 3D Control */ switch (ac97_codecs[dev->model].reset_flags >> AC97_3D_SHIFT) { - case 1: /* Analog Devices */ - case 6: /* Crystal */ + case 1: /* Analog Devices */ + case 6: /* Crystal */ + case 27: /* Winbond */ val &= 0x000f; break; @@ -764,6 +771,20 @@ const device_t tr28023_device = { .config = NULL }; +const device_t w83971d_device = { + .name = "Winbond W83971D", + .internal_name = "w83971d", + .flags = DEVICE_AC97, + .local = AC97_CODEC_W83971D, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t wm9701a_device = { .name = "Wolfson WM9701A", .internal_name = "wm9701a", From 2007632e73d6db3566bc3383d172f4931fc6c662 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Thu, 15 May 2025 17:45:27 -0300 Subject: [PATCH 0922/1190] AC97: Remove redundant initializers --- src/sound/snd_ac97_codec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index 4a9c1e6c6..1b28a8aab 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -68,7 +68,6 @@ static const struct { .device = &cs4297_device, .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_AUXOUT_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, .pcsr_mask = 0x7f, .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x5a, 0x0301, 0x0000}, {0}} }, @@ -100,8 +99,6 @@ static const struct { { .device = &tr28023_device, .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_POP | AC97_MS | AC97_LPBK, - .reset_flags = 0, - .extid_flags = 0, .pcsr_mask = 0x3f }, { @@ -114,7 +111,6 @@ static const struct { .device = &wm9701a_device, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .reset_flags = AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, .pcsr_mask = 0x3f } // clang-format on From 941766f2e84ec581f29c06f92e21db3361878b8d Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 16 May 2025 05:04:48 +0200 Subject: [PATCH 0923/1190] Added the ZEOS Martin. --- src/chipset/vl82c480.c | 117 +++++++++++++++++++++++++++-------- src/include/86box/machine.h | 1 + src/include/86box/nvr.h | 1 + src/machine/m_at_286_386sx.c | 4 +- src/machine/m_at_386dx_486.c | 42 ++++++++++--- src/machine/machine_table.c | 65 +++++++++++++++---- src/nvr_at.c | 42 ++++++++++++- src/sio/sio_vl82c113.c | 6 +- 8 files changed, 226 insertions(+), 52 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 496544c63..8ca2c5847 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -24,34 +24,37 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/io.h> +#include <86box/machine.h> #include <86box/mem.h> #include <86box/nmi.h> #include <86box/port_92.h> #include <86box/chipset.h> typedef struct vl82c480_t { - uint8_t idx; - uint8_t regs[256]; + uint8_t idx; + uint8_t regs[256]; + uint32_t banks[4]; } vl82c480_t; static int -vl82c480_shflags(uint8_t access) +vl82c480_shflags(uint8_t access, uint8_t access2) { int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + int wp = ((access2 & 0x03) == 0x01); switch (access) { default: case 0x00: - ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); break; case 0x01: - ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); break; case 0x02: - ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; + ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); break; case 0x03: - ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; + ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); break; } @@ -59,27 +62,60 @@ vl82c480_shflags(uint8_t access) } static void -vl82c480_recalc(vl82c480_t *dev) +vl82c480_recalc_shadow(vl82c480_t *dev) { uint32_t base; uint8_t access; + uint8_t access2; shadowbios = 0; shadowbios_write = 0; for (uint8_t i = 0; i < 6; i++) { for (uint8_t j = 0; j < 8; j += 2) { - base = 0x000a0000 + (i << 16) + (j << 13); - access = (dev->regs[0x0d + i] >> j) & 3; - mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); + base = 0x000a0000 + (i << 16) + (j << 13); + access = (dev->regs[0x0d + i] >> j) & 3; + access2 = (dev->regs[0x13 + i] >> j) & 3; + mem_set_mem_state(base, 0x4000, vl82c480_shflags(access, access2)); shadowbios |= ((base >= 0xe0000) && (access & 0x02)); - shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); + shadowbios_write |= ((base >= 0xe0000) && (access & 0x01) && !(access2 & 0x01)); } } flushmmucache(); } +static void +vl82c480_recalc_banks(vl82c480_t *dev) +{ + uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; + uint8_t shifts[4] = { 0, 4, 0, 4 }; + uint8_t regs[4] = { 0x02, 0x02, 0x03, 0x03 }; + uint32_t total = 0; + + for (uint8_t i = 0; i < 4; i++) { + uint8_t shift = shifts[i]; + uint8_t reg = regs[i]; + uint8_t cfg = (dev->regs[reg] >> shift) & 0x7; + uint32_t size = sizes[cfg]; + + total += MIN(dev->banks[i], size); + } + + if (total > 1024) { + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10); + } else { + if (total >= 1024) + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + else + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_high_mapping); + } + + flushmmucache(); +} + static void vl82c480_write(uint16_t addr, uint8_t val, void *priv) { @@ -91,16 +127,24 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) break; case 0xed: - if (dev->idx >= 0x01 && dev->idx <= 0x24) { + if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) || + ((dev->idx >= 0x20) && (dev->idx <= 0x24))) { switch (dev->idx) { default: dev->regs[dev->idx] = val; break; + case 0x02: case 0x03: + dev->regs[dev->idx] = val; + if (!strcmp(machine_get_internal_name(), "martin")) + vl82c480_recalc_banks(dev); + break; case 0x04: if (dev->regs[0x00] == 0x98) dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); else dev->regs[dev->idx] = val; + if (!strcmp(machine_get_internal_name(), "martin")) + dev->regs[dev->idx] &= 0x1f; break; case 0x05: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); @@ -108,14 +152,11 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) case 0x07: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); break; - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: + case 0x0d ... 0x18: dev->regs[dev->idx] = val; - vl82c480_recalc(dev); + vl82c480_recalc_shadow(dev); + if (dev->idx >= 0x13) + flushmmucache(); break; } } @@ -124,8 +165,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) /* TODO: This is actually Fast A20 disable. */ #if 0 case 0xee: - if (mem_a20_alt) - outb(0x92, inb(0x92) & ~2); + mem_a20_alt = 0x00; + mem_a20_recalc(); break; #endif @@ -146,14 +187,16 @@ vl82c480_read(uint16_t addr, void *priv) break; case 0xed: - ret = dev->regs[dev->idx]; + if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) || + ((dev->idx >= 0x20) && (dev->idx <= 0x24))) + ret = dev->regs[dev->idx]; break; /* TODO: This is actually Fast A20 enable. */ #if 0 case 0xee: - if (!mem_a20_alt) - outb(0x92, inb(0x92) | 2); + mem_a20_alt = 0x02; + mem_a20_recalc(); break; #endif @@ -180,7 +223,9 @@ vl82c480_close(void *priv) static void * vl82c480_init(const device_t *info) { - vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); + vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); + uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; + uint32_t ms = mem_size; dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; @@ -191,9 +236,27 @@ vl82c480_init(const device_t *info) dev->regs[0x07] = 0x21; dev->regs[0x08] = 0x38; + for (uint8_t i = 0; i < 4; i++) { + uint32_t size = 0; + + for (uint8_t j = 2; i < 7; j++) { + if (ms >= sizes[j]) + size = sizes[j]; + else + break; + } + + ms -= size; + + dev->banks[i] = size; + + if ((ms == 0) || (size == 0)) + break; + } + io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev); - device_add(&port_92_device); + device_add(&port_92_pci_device); return dev; } diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 77768832e..24bfb245e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -545,6 +545,7 @@ extern int machine_at_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); +extern int machine_at_martin_init(const machine_t *); extern int machine_at_403tg_init(const machine_t *); extern int machine_at_403tg_d_init(const machine_t *); diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 0f7d22172..273fc0a37 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -99,6 +99,7 @@ extern const device_t ami_1994_nvr_device; extern const device_t ami_1995_nvr_device; extern const device_t via_nvr_device; extern const device_t p6rp4_nvr_device; +extern const device_t martin_nvr_device; extern const device_t elt_nvr_device; #endif diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index c9fb124cb..e7aa66662 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -724,7 +724,9 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5402_onboard_device); - machine_at_common_ide_init(model); + machine_at_common_init_ex(model, 2); + + device_add(&ide_isa_device); device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */ device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0e382d0c4..0b47c285f 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -412,14 +412,16 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); - - device_add(&vl82c480_device); - if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + device_add(&vl82c113_device); + + device_add(&ide_isa_device); device_add(&fdc37c651_ide_device); return ret; @@ -436,13 +438,13 @@ machine_at_d824_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); - - device_add(&vl82c480_device); - if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + /* Technically, it should be the VL82C114 but we do not have a proper datasheet of it that tells us the registers. @@ -455,6 +457,30 @@ machine_at_d824_init(const machine_t *model) return ret; } +int +machine_at_martin_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/martin/NONSCSI.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + device_add(&vl82c113_device); + + device_add(&ide_vlb_device); + device_add(&fdc37c651_ide_device); + + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_acera1g_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e60ccf71d..281505469 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6526,7 +6526,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ + /* Has a VLSI VL82C114 Combination I/O which holds the KBC. */ { .name = "[VLSI 82C481] Siemens Nixdorf D824", .internal_name = "d824", @@ -6554,7 +6554,7 @@ const machine_t machines[] = { .max = 32768, .step = 2048 }, - .nvrmask = 127, + .nvrmask = 255, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -6773,6 +6773,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMI MegaKey KBC. */ + { + .name = "[i420TX] J-Bond PCI400C-A", + .internal_name = "pci400ca", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_pci400ca_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_SCSI, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = &keyboard_at_ami_device, + .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 + }, /* This has a standalone AMI Megakey 1993, which is type 'P'. */ { .name = "[IMS 8848] Tekram G486IP", @@ -6934,13 +6974,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC. */ + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { - .name = "[i420TX] J-Bond PCI400C-A", - .internal_name = "pci400ca", + .name = "[VLSI 82C480] ZEOS Martin", + .internal_name = "martin", .type = MACHINE_TYPE_486_S2, - .chipset = MACHINE_CHIPSET_INTEL_420TX, - .init = machine_at_pci400ca_init, + .chipset = MACHINE_CHIPSET_VLSI_VL82C480, + .init = machine_at_martin_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -6955,15 +6995,15 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, - .flags = MACHINE_SCSI, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { - .min = 1024, + .min = 2048, .max = 65536, - .step = 1024 + .step = 2048 }, .nvrmask = 127, - .kbc_device = &keyboard_at_ami_device, + .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, @@ -6975,7 +7015,6 @@ const machine_t machines[] = { .net_device = NULL }, - /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ /* Has a Fujitsu MBL8042H KBC. */ diff --git a/src/nvr_at.c b/src/nvr_at.c index bde80b434..2acfa47a4 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -296,6 +296,7 @@ #define FLAG_P6RP4_HACK 0x10 #define FLAG_PIIX4 0x20 #define FLAG_MULTI_BANK 0x40 +#define FLAG_MARTIN_HACK 0x80 typedef struct local_t { int8_t stat; @@ -733,6 +734,13 @@ nvr_read(uint16_t addr, void *priv) ret = REGD_VRT; break; + case 0x11: + if (local->flags & FLAG_MARTIN_HACK) + ret = nvr->regs[local->addr[addr_id]] | 0x02; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + case 0x2c: if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) ret = nvr->regs[local->addr[addr_id]] & 0x7f; @@ -771,6 +779,17 @@ nvr_read(uint16_t addr, void *priv) ret = checksum >> 8; else ret = checksum & 0xff; + } else if (!nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) { + for (i = 0x10; i <= 0x2d; i++) { + if (i == 0x11) + checksum += (nvr->regs[i] | 0x02); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x2e) + ret = checksum >> 8; + else + ret = checksum & 0xff; } else ret = nvr->regs[local->addr[addr_id]]; break; @@ -1123,9 +1142,11 @@ nvr_at_init(const device_t *info) if (info->local & 0x10) { local->def = 0x00; local->flags |= FLAG_AMI_1992_HACK; - } else if (info->local == 36) + } else if ((info->local == 36) || (info->local == 68)) { local->def = 0x00; - else + if (info->local == 68) + local->flags |= FLAG_MARTIN_HACK; + } else local->def = 0xff; nvr->irq = 8; local->cent = RTC_CENTURY_AT; @@ -1160,6 +1181,9 @@ nvr_at_init(const device_t *info) /* Initialize the generic NVR. */ nvr_init(nvr); + if (nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) + nvr->regs[0x11] = nvr->regs[0x2f] = 0x02; + if (nvr_at_inited == 0) { /* Start the timers. */ timer_add(&local->update_timer, timer_update, nvr, 0); @@ -1426,6 +1450,20 @@ const device_t amstrad_megapc_nvr_device = { .config = NULL }; +const device_t martin_nvr_device = { + .name = "Zeos Martin NVRAM", + .internal_name = "martin_nvr", + .flags = DEVICE_ISA16, + .local = 68, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + .available = NULL, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + const device_t elt_nvr_device = { .name = "Epson Equity LT NVRAM", .internal_name = "elt_nvr", diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c index ee18b1893..b000fe5dd 100644 --- a/src/sio/sio_vl82c113.c +++ b/src/sio/sio_vl82c113.c @@ -22,6 +22,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/keyboard.h> +#include <86box/machine.h> #include <86box/nvr.h> #include <86box/sio.h> #include <86box/plat_unused.h> @@ -133,7 +134,10 @@ vl82c113_init(UNUSED(const device_t *info)) { vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); - dev->nvr = device_add(&at_nvr_device); + if (!strcmp(machine_get_internal_name(), "martin")) + dev->nvr = device_add(&martin_nvr_device); + else + dev->nvr = device_add(&amstrad_megapc_nvr_device); dev->nvr_enabled = 1; dev->nvr_base = 0x0070; From 948f50667e2845976010020e0c83bc2a94015b61 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 16 May 2025 18:18:23 +0200 Subject: [PATCH 0924/1190] the ZEOS Martin Board actually has VLB Slots. --- 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 ffdf902a3..2e72dd1fa 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6995,7 +6995,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2, + .bus_flags = MACHINE_PS2_VLB, .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, From 34bd61fd1bdd6862a6abe7ff356742e96445d32e Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 16 May 2025 18:21:51 +0200 Subject: [PATCH 0925/1190] Correct the ET4000/W32p file. --- src/video/vid_et4000w32.c | 160 +++++++------------------------------- 1 file changed, 27 insertions(+), 133 deletions(-) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c772ffdd9..246decb9c 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -43,11 +43,8 @@ #define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" #define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" #define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.bin" -#define BIOS_ROM_PATH_W32P_IMASCAN_VLB "roms/video/et4000w32/tseng_et4000w32p-8.03.bin" -#define BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB "roms/video/et4000w32/m27c256b-at-dip28-miro20td-675dada18e7fa701369657.bin" #define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" #define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" -#define BIOS_ROM_PATH_W32P_REVCD_ONBOARD "roms/video/et4000w32/vid.BIN" #define ACL_WRST 1 #define ACL_RDST 2 @@ -58,10 +55,7 @@ enum { ET4000W32, ET4000W32I, ET4000W32P_REVC, - ET4000W32P_REVCD_ONBOARD, ET4000W32P_VIDEOMAGIC_REVB, - ET4000W32P_IMASCAN_VLB, - ET4000W32P_MIROVIDEO20TD_VLB, ET4000W32P, ET4000W32P_CARDEX, ET4000W32P_DIAMOND @@ -184,7 +178,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); else stg_ramdac_out(addr, val, svga->ramdac, svga); @@ -308,13 +302,13 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) if (svga->hwcursor.cur_xsize == 128) { svga->hwcursor.xoff &= 0x7f; svga->hwcursor.yoff &= 0x7f; - if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type > ET4000W32P_REVC) { if (svga->bpp == 24) { et4000->adjust_cursor = 2; } } } else { - if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type > ET4000W32P_REVC) { if ((svga->bpp == 24) && et4000->adjust_cursor) { et4000->adjust_cursor = 0; } @@ -354,7 +348,7 @@ et4000w32p_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) return sdac_ramdac_in(addr, 0, svga->ramdac, svga); else return stg_ramdac_in(addr, svga->ramdac, svga); @@ -509,8 +503,8 @@ et4000w32p_recalctimings(svga_t *svga) svga->hdisp >>= 1; svga->dots_per_clock >>= 1; } - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { - if (et4000->type == ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type <= ET4000W32P_REVC) { + if (et4000->type == ET4000W32P_REVC) { if (svga->hdisp != 1024) et4000->adjust_cursor = 1; } else @@ -520,7 +514,7 @@ et4000w32p_recalctimings(svga_t *svga) case 24: svga->hdisp /= 3; svga->dots_per_clock /= 3; - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { svga->hdisp = 640; @@ -554,7 +548,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 0x40: case 0x60: /* 256+ colours */ - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) svga->clock /= 2; switch (svga->bpp) { @@ -735,13 +729,13 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | (val << 8); break; case 0x8e: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.pixel_depth = val & 0x30; else et4000->acl.queued.vbus = val & 0x03; break; case 0x8f: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.xy_dir = val & 0xb7; else et4000->acl.queued.xy_dir = val & 0x03; @@ -765,7 +759,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | (val << 8); break; case 0x9c: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.ctrl_routing = val & 0xdb; else et4000->acl.queued.ctrl_routing = val & 0xb7; @@ -791,7 +785,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) case 0xa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24); et4000->acl.internal = et4000->acl.queued; - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type >= ET4000W32P_REVC) { et4000w32p_blit_start(et4000); et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); if (!(et4000->acl.queued.ctrl_routing & 0x43)) { @@ -855,7 +849,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) static void et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank) { - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type >= ET4000W32P_REVC) { if (!(et4000->acl.status & ACL_XYST)) { et4000w32_log("XY MMU block not started\n"); return; @@ -1093,7 +1087,7 @@ et4000w32p_mmu_read(uint32_t addr, void *priv) case 0x8d: return et4000->acl.internal.dest_off >> 8; case 0x8e: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) return et4000->acl.internal.pixel_depth; return et4000->acl.internal.vbus; case 0x8f: @@ -2785,30 +2779,6 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - break; - - case ET4000W32P_IMASCAN_VLB: - /* ET4000/W32p Imascan RGB */ - et4000->rev = 5; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_IMASCAN_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - break; - - case ET4000W32P_MIROVIDEO20TD_VLB: - /* ET4000/W32p miroVIDEO 20TD LIVE! */ - et4000->rev = 5; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; @@ -2821,18 +2791,6 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; - - case ET4000W32P_REVCD_ONBOARD: - /* ET4000/W32p rev C */ - et4000->rev = 7; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVCD_ONBOARD, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = sdac_getclock; @@ -2932,30 +2890,12 @@ et4000w32p_videomagic_revb_vlb_available(void) return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB); } -int -et4000w32p_imascan_vlb_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P_IMASCAN_VLB); -} - -int -et4000w32p_mirovideo20td_vlb_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB); -} - int et4000w32p_revc_available(void) { return rom_present(BIOS_ROM_PATH_W32P_REVC); } -int -et4000w32p_revcd_onboard_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P_REVCD_ONBOARD); -} - int et4000w32p_noncardex_available(void) { @@ -3003,23 +2943,19 @@ et4000w32p_force_redraw(void *priv) static const device_config_t et4000w32p_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -3081,34 +3017,6 @@ const device_t et4000w32i_vlb_device = { .config = et4000w32p_config }; -const device_t et4000w32p_imascan_vlb_device = { - .name = "Tseng Labs ET4000/w32p VLB (Imascan)", - .internal_name = "et4000w32p_imascan_vlb", - .flags = DEVICE_VLB, - .local = ET4000W32P_IMASCAN_VLB, - .init = et4000w32p_init, - .close = et4000w32p_close, - .reset = NULL, - .available = et4000w32p_imascan_vlb_available, - .speed_changed = et4000w32p_speed_changed, - .force_redraw = et4000w32p_force_redraw, - .config = et4000w32p_config -}; - -const device_t et4000w32p_mirovideo20td_vlb_device = { - .name = "Tseng Labs ET4000/w32p VLB (miroVIDEO 20TD LIVE!)", - .internal_name = "et4000w32p_mirovideo20td_vlb", - .flags = DEVICE_VLB, - .local = ET4000W32P_MIROVIDEO20TD_VLB, - .init = et4000w32p_init, - .close = et4000w32p_close, - .reset = NULL, - .available = et4000w32p_mirovideo20td_vlb_available, - .speed_changed = et4000w32p_speed_changed, - .force_redraw = et4000w32p_force_redraw, - .config = et4000w32p_config -}; - const device_t et4000w32p_videomagic_revb_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)", .internal_name = "et4000w32p_videomagic_revb_vlb", @@ -3165,20 +3073,6 @@ const device_t et4000w32p_revc_pci_device = { .config = et4000w32p_config }; -const device_t et4000w32p_revcd_onboard_pci_device = { - .name = "Tseng Labs ET4000/w32p Rev. C/D PCI (On-Board)", - .internal_name = "et4000w32p_revc_pci", - .flags = DEVICE_PCI, - .local = ET4000W32P_REVCD_ONBOARD, - .init = et4000w32p_init, - .close = et4000w32p_close, - .reset = NULL, - .available = et4000w32p_revcd_onboard_available, - .speed_changed = et4000w32p_speed_changed, - .force_redraw = et4000w32p_force_redraw, - .config = et4000w32p_config -}; - const device_t et4000w32p_noncardex_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. D VLB", .internal_name = "et4000w32p_nc_vlb", From e98424a8ae988d9e49c9f27d19122194a09c43f9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 02:35:11 +0200 Subject: [PATCH 0926/1190] Added the ICS SB486PV. --- src/chipset/intel_4x0.c | 7 ++- src/device.c | 10 +++- src/device/kbc_at.c | 5 +- src/include/86box/machine.h | 3 +- src/include/86box/sio.h | 3 ++ src/machine/m_at_386dx_486.c | 93 ++++++++++++++++++++++++++++++++++-- src/machine/machine_table.c | 42 ++++++++++++++++ src/sio/sio_82091aa.c | 14 ++++++ src/video/vid_cl54xx.c | 8 ++-- 9 files changed, 172 insertions(+), 13 deletions(-) diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index f9d6af150..84bd872f8 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1656,7 +1656,12 @@ i4x0_init(const device_t *info) regs[0x57] = 0x31; regs[0x59] = 0x0f; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; - dev->max_drb = 3; + /* At the very least the 420ZX seems to read to 0x64, per the SB486PV. */ + if (dev->type == INTEL_420ZX) { + regs[0x64] = 0x02; + dev->max_drb = 4; + } else + dev->max_drb = 3; dev->drb_unit = 1; dev->drb_default = 0x02; break; diff --git a/src/device.c b/src/device.c index 1922806b9..910ff4ff9 100644 --- a/src/device.c +++ b/src/device.c @@ -897,8 +897,14 @@ device_is_valid(const device_t *device, int mch) { int ret = 1; - if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) - ret = machine_has_bus(mch, device->flags & DEVICE_BUS); + if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) { + /* Hide PCI devices on machines with only an internal PCI bus. */ + if ((device->flags & DEVICE_PCI) && + machine_has_flags(mch, MACHINE_PCI_INTERNAL)) + ret = 0; + else + ret = machine_has_bus(mch, device->flags & DEVICE_BUS); + } return ret; } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 2b9cf8c18..a8a8c51cc 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1336,7 +1336,10 @@ write64_ami(void *priv, uint8_t val) kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n"); if (!(dev->flags & DEVICE_PCI)) write_p2(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + if (strstr(machine_get_internal_name(), "sb486pv") != NULL) + kbc_delay_to_ob(dev, 0x03, 0, 0x00); + else + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; return 0; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 24bfb245e..febce3fa1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -105,7 +105,7 @@ /* Feature flags for advanced devices. */ #define MACHINE_APM 0x00080000 /* sys has APM */ #define MACHINE_ACPI 0x00100000 /* sys has ACPI */ -#define MACHINE_HWM 0x00200000 /* sys has hw monitor */ +#define MACHINE_PCI_INTERNAL 0x00200000 /* sys has only internal PCI */ #define MACHINE_CARTRIDGE 0x00400000 /* sys has cartridge bays */ /* Feature flags for internal storage controllers. */ #define MACHINE_MFM 0x00800000 /* sys has int MFM/RLL */ @@ -588,6 +588,7 @@ extern int machine_at_sb486p_init(const machine_t *); extern int machine_at_486sp3_init(const machine_t *); extern int machine_at_486sp3c_init(const machine_t *); extern int machine_at_486sp3g_init(const machine_t *); +extern int machine_at_sb486pv_init(const machine_t *); extern int machine_at_486ap4_init(const machine_t *); extern int machine_at_g486vpa_init(const machine_t *); extern int machine_at_486vipio2_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index bdff29f7f..06bf57f8f 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -71,7 +71,10 @@ extern const device_t fdc37m60x_370_device; /* ITE */ extern const device_t it8661f_device; extern const device_t it8671f_device; + +/* Intel */ extern const device_t i82091aa_device; +extern const device_t i82091aa_26e_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_pri_device; extern const device_t i82091aa_ide_device; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0b47c285f..c2cf82352 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -756,7 +756,6 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } - static const device_config_t pb450_config[] = { // clang-format off { @@ -1640,6 +1639,91 @@ machine_at_486sp3g_init(const machine_t *model) return ret; } +static const device_config_t sb486pv_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "sb486pv", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "AMI 062594 (0108)", .internal_name = "sb486pv", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/41-0108-062594-SATURN2.rom", "" } }, + { .name = "AMI 062594 (0301)", .internal_name = "sb486pv_94", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/0301-062594-SATURN2.rom", "" } }, + { .name = "AMI 071595 (1301)", .internal_name = "sb486pv_95", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/amiboot.rom", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t sb486pv_device = { + .name = "ICS SB486PV", + .internal_name = "sb486pv_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = sb486pv_config +}; + +int +machine_at_sb486pv_init(const machine_t *model) +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + else + ret = bios_load_linear_inverted(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init(model); + // machine_at_common_init_ex(model, 2); + + // device_add(&amstrad_megapc_nvr_device); + device_add(&ide_pci_device); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0e, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0f, PCI_CARD_VIDEO, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sio_zb_device); + device_add(&ide_rz1000_pci_single_channel_device); + device_add(&i82091aa_26e_device); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + device_add(&intel_flash_bxt_device); + else + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420zx_device); + + return ret; +} + int machine_at_486ap4_init(const machine_t *model) { @@ -1833,12 +1917,11 @@ machine_at_sbc490_init(const machine_t *model) pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&ali1489_device); device_add(&fdc37c665_device); - - if (gfxcard[0] == VID_INTERNAL) - device_add(&tgui9440_onboard_pci_device); - device_add(&keyboard_ps2_ami_device); device_add(&sst_flash_29ee010_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index ffdf902a3..3f69865c3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -69,6 +69,7 @@ extern const device_t pb450_device; extern const device_t jukopc_device; extern const device_t vendex_device; extern const device_t c5sbm2_device; +extern const device_t sb486pv_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -8515,6 +8516,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has an AMI MEGAKey 'P' or 'R' keyboard controller. */ + { + .name = "[i420ZX] ICS SB486PV", + .internal_name = "sb486pv", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_INTEL_420ZX, + .init = machine_at_sb486pv_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 + }, + /* Has PCI but no user-facing slots. */ + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM | MACHINE_PCI_INTERNAL, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &sb486pv_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5436_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ { .name = "[IMS 8848] J-Bond PCI400C-B", diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index d3cd5017a..71f8749f2 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -295,6 +295,20 @@ const device_t i82091aa_device = { .config = NULL }; +const device_t i82091aa_26e_device = { + .name = "Intel 82091AA Super I/O (Port 26Eh)", + .internal_name = "i82091aa_26e", + .flags = 0, + .local = 0x140, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t i82091aa_398_device = { .name = "Intel 82091AA Super I/O (Port 398h)", .internal_name = "i82091aa_398", diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 43c4e22b2..dbb9d5993 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -33,6 +33,7 @@ #include <86box/pci.h> #include <86box/rom.h> #include <86box/device.h> +#include <86box/machine.h> #include <86box/timer.h> #include <86box/video.h> #include <86box/i2c.h> @@ -4316,7 +4317,8 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5436: - if (info->local & 0x200) { + if ((info->local & 0x200) && + !strstr(machine_get_internal_name(), "sb486pv")) { romfn = NULL; gd54xx->has_bios = 0; } else @@ -4461,8 +4463,8 @@ gd54xx_init(const device_t *info) } io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) { - if (romfn == NULL) + if (gd54xx->pci && (id >= CIRRUS_ID_CLGD5430)) { + if (info->local & 0x200) pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); else pci_add_card(PCI_ADD_NORMAL, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); From 2a58d761b94397775b2410f1cb1639b9729e64fb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 03:05:46 +0200 Subject: [PATCH 0927/1190] VL82C480: Fix and clean-up the DRAM banks calculation code, closes #5592. --- src/chipset/vl82c480.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 8ca2c5847..56e9f1d71 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -237,20 +237,16 @@ vl82c480_init(const device_t *info) dev->regs[0x08] = 0x38; for (uint8_t i = 0; i < 4; i++) { - uint32_t size = 0; - - for (uint8_t j = 2; i < 7; j++) { + for (uint8_t j = 2; j < 7; j++) { if (ms >= sizes[j]) - size = sizes[j]; + dev->banks[i] = sizes[j]; else break; } - ms -= size; + ms -= dev->banks[i]; - dev->banks[i] = size; - - if ((ms == 0) || (size == 0)) + if ((ms == 0) || (dev->banks[i] == 0)) break; } From 5ebed5dc57e96453e9ff6b77f8c2357575156b6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 03:09:21 +0200 Subject: [PATCH 0928/1190] POST Card: Some Compaq-related fixes. --- src/device/postcard.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/device/postcard.c b/src/device/postcard.c index b91d8b402..95a4df646 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -147,14 +147,17 @@ postcard_init(UNUSED(const device_t *info)) if (machine_has_bus(machine, MACHINE_BUS_MCA)) postcard_port = 0x680; /* MCA machines */ - else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 ")) + else if (strstr(machines[machine].name, " PS/2 ") || + strstr(machine_getname_ex(machine), " PS/1 ")) postcard_port = 0x190; /* ISA PS/2 machines */ else if (strstr(machines[machine].name, " IBM XT ")) postcard_port = 0x60; /* IBM XT */ else if (strstr(machines[machine].name, " IBM PCjr")) { postcard_port = 0x10; /* IBM PCjr */ postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */ - } else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI)) + } else if (strstr(machines[machine].name, " Compaq ") && + !strstr(machines[machine].name, " Presario ") && + !strstr(machines[machine].name, " ProSignia ")) postcard_port = 0x84; /* ISA Compaq machines */ else if (strstr(machines[machine].name, "Olivetti")) postcard_port = 0x378; /* Olivetti machines */ From 1eb4355d769c17cebc2d23814c72f061d32ba0ac Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 03:16:52 +0200 Subject: [PATCH 0929/1190] FDC: Remove an excess commented out line. --- src/floppy/fdc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index e779ea2d7..e7166d1ba 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -81,7 +81,6 @@ int fdc_current[FDC_MAX] = { 0, 0 }; volatile int fdcinited = 0; -// #define ENABLE_FDC_LOG 1 #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; From b97a23aa571256d9f3c67fe6962b8833b88474b1 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 17 May 2025 05:28:45 +0200 Subject: [PATCH 0930/1190] WIP Plasma code --- src/machine/m_at_compaq.c | 191 +++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 74 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index c0b254388..ddd3f2a0c 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -84,20 +84,14 @@ compaq_plasma_display_set(uint8_t internal) cpq_st_display_internal = internal; } -static uint8_t -compaq_plasma_display_get(void) -{ - return cpq_st_display_internal; -} - typedef struct compaq_plasma_t { cga_t cga; - uint8_t ctl_mode; + mem_mapping_t font_ram_mapping; + uint8_t *font_ram; uint8_t port_13c6; uint8_t port_23c6; uint8_t port_27c6; uint8_t internal_monitor; - uint8_t attrmap; } compaq_plasma_t; static int compaq_machine_type = 0; @@ -119,13 +113,11 @@ compaq_plasma_recalctimings(compaq_plasma_t *self) return; } - disptime = 651; - _dispontime = 640; + disptime = 651; + _dispontime = 640; _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST / 2; - _dispofftime *= CGACONST / 2; - self->cga.dispontime = (uint64_t) (_dispontime); - self->cga.dispofftime = (uint64_t) (_dispofftime); + self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); } static void @@ -160,14 +152,31 @@ compaq_plasma_read(uint32_t addr, void *priv) } static void -compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) +compaq_plasma_font_write(uint32_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - if (self->port_23c6 & 0x08) { - if ((addr >= 0x3d0) && (addr <= 0x3dc)) - addr ^= 0x60; - } + addr &= 0x1fff; + + self->font_ram[addr] = val; +} +static uint8_t +compaq_plasma_font_read(uint32_t addr, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t ret = 0x00; + + addr &= 0x1fff; + + ret = self->font_ram[addr]; + + return ret; +} + +static void +compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; switch (addr) { /* Emulated CRTC, register select */ @@ -183,21 +192,11 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (self->cga.crtcreg == 0x12) { - self->attrmap = val; - compaq_plasma_recalcattrs(self); - return; - } cga_out(addr, val, &self->cga); - compaq_plasma_recalctimings(self); break; case 0x3d8: case 0x3d9: - case 0x3db: - case 0x3dc: cga_out(addr, val, &self->cga); break; @@ -208,10 +207,15 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x23c6: self->port_23c6 = val; - if (val & 0x08) /* Disable internal CGA */ - mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x8000); - else - mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x8000); + pclog("Write 23c6=%02x.\n", val); + if (val & 0x08) { /* Disable internal CGA */ + mem_mapping_disable(&self->cga.mapping); + mem_mapping_enable(&self->font_ram_mapping); + } else { + mem_mapping_enable(&self->cga.mapping); + mem_mapping_disable(&self->font_ram_mapping); + } + compaq_plasma_recalcattrs(self); break; case 0x27c6: @@ -229,11 +233,6 @@ compaq_plasma_in(uint16_t addr, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; uint8_t ret = 0xff; - if (self->port_23c6 & 0x08) { - if ((addr >= 0x3d0) && (addr <= 0x3dc)) - addr ^= 0x60; - } - switch (addr) { case 0x3d4: case 0x3da: @@ -246,13 +245,8 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x3d3: case 0x3d5: case 0x3d7: - if (self->cga.crtcreg == 0x12) { - ret = self->attrmap & 0x0f; - if (compaq_plasma_display_get()) - ret |= 0x30; /* Plasma / CRT */ - } else - ret = cga_in(addr, &self->cga); - break; + ret = cga_in(addr, &self->cga); + break; case 0x3d8: ret = self->cga.cgamode; @@ -260,10 +254,16 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x13c6: ret = self->port_13c6; +#if 0 + if ((self->cga.cgamode & 0x28) == 0x00) + ret |= 0x04; +#endif + pclog("Read 13c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x17c6: - ret = 0xf6; + ret = 0xe6; + pclog("Read 17c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x1bc6: @@ -272,6 +272,7 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x23c6: ret = self->port_23c6; + pclog("Read 23c6=%02x.\n", ret); break; case 0x27c6: @@ -350,12 +351,15 @@ compaq_plasma_poll(void *priv) chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; /* text attributes */ attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; - } else - chr = attr = 0; + } else { + chr = 0x00; + attr = 0x00; + } /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + underline = ((attr & 0x07) == 0x01); + underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -376,8 +380,13 @@ compaq_plasma_poll(void *priv) /* Set intensity bit */ cols[1] = normcols[attr][1]; cols[0] = normcols[attr][0]; - blink = ((attr & 0x80) << 3) + 7 + 16; } + + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + chr_addr |= 0x1000; + /* character underline active and 7th row of pixels in character height being drawn */ if (underline && (sc == 7)) { /* for each pixel in character width */ @@ -385,12 +394,25 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } else { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } + if (attr & 0x03) { + if ((self->port_23c6 >> 5) == 1) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); + } else if ((self->port_23c6 >> 5) == 4) { + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16); + } + } + } ma++; } } @@ -412,13 +434,15 @@ compaq_plasma_poll(void *priv) chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; /* text attributes */ attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; - } else - chr = attr = 0; - + } else { + chr = 0x00; + attr = 0x00; + } /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + underline = ((attr & 0x07) == 0x01); + underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -439,22 +463,40 @@ compaq_plasma_poll(void *priv) /* Set intensity bit */ cols[1] = normcols[attr][1]; cols[0] = normcols[attr][0]; - blink = ((attr & 0x80) << 3) + 7 + 16; } + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + chr_addr |= 0x1000; + /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (self->cga.sc == 7)) { + if (underline && (sc == 7)) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } else { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } + if (attr & 0x03) { + if ((self->port_23c6 >> 5) == 1) + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black); + } + else if ((self->port_23c6 >> 5) == 4) + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); + } + } ma++; } } else { @@ -493,6 +535,14 @@ compaq_plasma_poll(void *priv) ink0 = ink1 = black; break; case 1: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = black; + } else { + ink0 = amber; + ink1 = black; + } + break; case 2: if (self->cga.displine & 0x01) { ink0 = black; @@ -545,7 +595,7 @@ compaq_plasma_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - /* ogc specific */ + /* Plasma specific */ video_blit_memtoscreen(0, 0, xsize, ysize); frames++; @@ -622,7 +672,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x11; n <= 0xFF; n++) { if ((n & 7) == 0) continue; - if (self->attrmap & 4) { /* Inverse */ + if ((self->port_23c6 >> 5) == 1) { /* Inverse */ blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; } else { /* Normal */ @@ -635,7 +685,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x01; n <= 0x0E; n++) { if (n == 7) continue; - if (self->attrmap & 1) { + if ((self->port_23c6 >> 5) == 1) { blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; blinkcols[n + 128][0] = amber; @@ -678,11 +728,6 @@ compaq_plasma_init(UNUSED(const device_t *info)) { compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); - if (compaq_machine_type == COMPAQ_PORTABLEIII) - loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); - else - loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49); - cga_init(&self->cga); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); @@ -691,24 +736,21 @@ compaq_plasma_init(UNUSED(const device_t *info)) self->cga.vram = malloc(0x8000); self->internal_monitor = 1; + self->font_ram = malloc(0x2000); cga_comp_init(self->cga.revision); timer_set_callback(&self->cga.timer, compaq_plasma_poll); timer_set_p(&self->cga.timer, self); mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); + mem_mapping_add(&self->font_ram_mapping, 0xb8000, 0x02000, compaq_plasma_font_read, NULL, NULL, compaq_plasma_font_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); for (int i = 1; i <= 2; i++) { io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); } - io_sethandler(0x03d0, 0x000c, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - /* Default attribute mapping is 4 */ - self->attrmap = 4; - compaq_plasma_recalcattrs(self); - - self->cga.cgastat = 0xf4; overscan_x = overscan_y = 16; self->cga.rgb_type = device_get_config_int("rgb_type"); @@ -725,6 +767,7 @@ compaq_plasma_close(void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; free(self->cga.vram); + free(self->font_ram); free(self); } From f7c27285825a234b8846af20635ca0e18e796f56 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 05:41:53 +0200 Subject: [PATCH 0931/1190] Fix the incorrect high intensity attribute bit checking (bit 3 is 0x08, not 0x03!). --- src/machine/m_at_compaq.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index ddd3f2a0c..1d1770b46 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -355,11 +355,12 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } + uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ underline = ((attr & 0x07) == 0x01); - underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -384,7 +385,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -400,7 +401,7 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if (attr & 0x03) { + if (hi_bit) { if ((self->port_23c6 >> 5) == 1) { for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); @@ -438,11 +439,12 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } + uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ underline = ((attr & 0x07) == 0x01); - underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -467,7 +469,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -483,7 +485,7 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if (attr & 0x03) { + if (hi_bit) { if ((self->port_23c6 >> 5) == 1) for (c = 0; c < 8; c++) { buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); From 45316f9be0c8e25f5538fda428b6d8574eb488ff Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 06:18:48 +0200 Subject: [PATCH 0932/1190] Potential fix for MS OS/2. --- src/machine/m_at_compaq.c | 64 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 1d1770b46..98803ca94 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -135,7 +135,10 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - self->cga.vram[addr & 0x7fff] = val; + if (self->port_23c6 & 0x08) + self->font_ram[addr & 0x1fff] = val; + else + self->cga.vram[addr & 0x7fff] = val; compaq_plasma_waitstates(&self->cga); } @@ -146,29 +149,11 @@ compaq_plasma_read(uint32_t addr, void *priv) uint8_t ret; compaq_plasma_waitstates(&self->cga); - ret = (self->cga.vram[addr & 0x7fff]); - return ret; -} - -static void -compaq_plasma_font_write(uint32_t addr, uint8_t val, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - - addr &= 0x1fff; - - self->font_ram[addr] = val; -} -static uint8_t -compaq_plasma_font_read(uint32_t addr, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t ret = 0x00; - - addr &= 0x1fff; - - ret = self->font_ram[addr]; + if (self->port_23c6 & 0x08) + ret = (self->font_ram[addr & 0x1fff]); + else + ret = (self->cga.vram[addr & 0x7fff]); return ret; } @@ -203,18 +188,20 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x13c6: self->port_13c6 = val; compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); + /* + For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA; + Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA; + This leads me to believe bit 2 is not relevant to the mode. + */ + if ((val & 0x03) == 0x03) + mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000); + else + mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000); break; case 0x23c6: self->port_23c6 = val; pclog("Write 23c6=%02x.\n", val); - if (val & 0x08) { /* Disable internal CGA */ - mem_mapping_disable(&self->cga.mapping); - mem_mapping_enable(&self->font_ram_mapping); - } else { - mem_mapping_enable(&self->cga.mapping); - mem_mapping_disable(&self->font_ram_mapping); - } compaq_plasma_recalcattrs(self); break; @@ -725,6 +712,15 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) } } +void +compaq_dump(void) +{ + FILE *f = fopen("d:\\86boxnew\\compaq_plasma_vram.dmp", "wb"); + for (int i = 0; i < 65536; i++) + fputc(mem_readb_phys(0x000b0000 + i), f); + fclose(f); +} + static void * compaq_plasma_init(UNUSED(const device_t *info)) { @@ -744,8 +740,10 @@ compaq_plasma_init(UNUSED(const device_t *info)) timer_set_callback(&self->cga.timer, compaq_plasma_poll); timer_set_p(&self->cga.timer, self); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); - mem_mapping_add(&self->font_ram_mapping, 0xb8000, 0x02000, compaq_plasma_font_read, NULL, NULL, compaq_plasma_font_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, + compaq_plasma_read, NULL, NULL, + compaq_plasma_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, self); for (int i = 1; i <= 2; i++) { io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); @@ -768,6 +766,8 @@ compaq_plasma_close(void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; + compaq_dump(); + free(self->cga.vram); free(self->font_ram); free(self); From 9772aeae4de7b83101a82dfd11b96308f3deebe3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 06:21:12 +0200 Subject: [PATCH 0933/1190] Clean up the excess logging. --- src/machine/m_at_compaq.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 98803ca94..1f5ecdb58 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -201,7 +201,6 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x23c6: self->port_23c6 = val; - pclog("Write 23c6=%02x.\n", val); compaq_plasma_recalcattrs(self); break; @@ -245,12 +244,10 @@ compaq_plasma_in(uint16_t addr, void *priv) if ((self->cga.cgamode & 0x28) == 0x00) ret |= 0x04; #endif - pclog("Read 13c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x17c6: ret = 0xe6; - pclog("Read 17c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x1bc6: @@ -259,7 +256,6 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x23c6: ret = self->port_23c6; - pclog("Read 23c6=%02x.\n", ret); break; case 0x27c6: @@ -712,15 +708,6 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) } } -void -compaq_dump(void) -{ - FILE *f = fopen("d:\\86boxnew\\compaq_plasma_vram.dmp", "wb"); - for (int i = 0; i < 65536; i++) - fputc(mem_readb_phys(0x000b0000 + i), f); - fclose(f); -} - static void * compaq_plasma_init(UNUSED(const device_t *info)) { @@ -766,8 +753,6 @@ compaq_plasma_close(void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - compaq_dump(); - free(self->cga.vram); free(self->font_ram); free(self); From dc9101c00c247232fc2a458919c892974bcfc420 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 06:56:52 +0200 Subject: [PATCH 0934/1190] VL82C480: Remove the incorrect implementation of registers 13h to 18h, fixes the Siemens-Nixdorf D824. --- src/chipset/vl82c480.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 56e9f1d71..6354ac15a 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -37,24 +37,23 @@ typedef struct vl82c480_t { } vl82c480_t; static int -vl82c480_shflags(uint8_t access, uint8_t access2) +vl82c480_shflags(uint8_t access) { int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - int wp = ((access2 & 0x03) == 0x01); switch (access) { default: case 0x00: - ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); + ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; break; case 0x01: - ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); + ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; break; case 0x02: - ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); + ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; break; case 0x03: - ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); + ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; break; } @@ -66,7 +65,6 @@ vl82c480_recalc_shadow(vl82c480_t *dev) { uint32_t base; uint8_t access; - uint8_t access2; shadowbios = 0; shadowbios_write = 0; @@ -75,10 +73,9 @@ vl82c480_recalc_shadow(vl82c480_t *dev) for (uint8_t j = 0; j < 8; j += 2) { base = 0x000a0000 + (i << 16) + (j << 13); access = (dev->regs[0x0d + i] >> j) & 3; - access2 = (dev->regs[0x13 + i] >> j) & 3; - mem_set_mem_state(base, 0x4000, vl82c480_shflags(access, access2)); + mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); shadowbios |= ((base >= 0xe0000) && (access & 0x02)); - shadowbios_write |= ((base >= 0xe0000) && (access & 0x01) && !(access2 & 0x01)); + shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); } } @@ -152,11 +149,9 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) case 0x07: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); break; - case 0x0d ... 0x18: + case 0x0d ... 0x12: dev->regs[dev->idx] = val; vl82c480_recalc_shadow(dev); - if (dev->idx >= 0x13) - flushmmucache(); break; } } From ddd271f6eee42c875523a10ee19eb1fdf2b8240b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 21:02:06 +0200 Subject: [PATCH 0935/1190] Honore the fixed bits of flags when pushing them to the stack, fixes #5093. --- src/codegen_new/codegen_ops_stack.c | 4 ++++ src/cpu/x86_ops_flag.h | 17 ++++------------- src/cpu/x86_ops_flag_2386.h | 17 ++++------------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index fca9c9efa..f93289197 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -390,6 +390,8 @@ ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUS uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); uop_CALL_FUNC(ir, flags_rebuild); sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5); + uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002); uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); SUB_SP(ir, 2); @@ -406,6 +408,8 @@ ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNU uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); uop_CALL_FUNC(ir, flags_rebuild); + uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5); + uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002); if (cpu_CR4_mask & CR4_VME) uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); else if (CPUID) diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index a0fa612a8..7e7324341 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) temp = (cpu_state.flags & ~I_FLAG) | 0x3000; if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; + temp = (temp & 0x7fd5) | 2; PUSH_W(temp); } else { x86gpf(NULL, 0); @@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) } } else { flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); @@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat)) else tempw = cpu_state.eflags & 4; flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); @@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { - x86gpf(NULL, 0); - return 1; - } - tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) - cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; flags_extract(); #ifdef USE_DEBUG_REGS_486 rf_flag_no_clear = 1; diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h index c9a2d5ab2..787b268dc 100644 --- a/src/cpu/x86_ops_flag_2386.h +++ b/src/cpu/x86_ops_flag_2386.h @@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) temp = (cpu_state.flags & ~I_FLAG) | 0x3000; if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; + temp = (temp & 0x7fd5) | 2; PUSH_W(temp); } else { x86gpf(NULL, 0); @@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) } } else { flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); @@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat)) else tempw = cpu_state.eflags & 4; flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); @@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { - x86gpf(NULL, 0); - return 1; - } - tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) - cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; flags_extract(); rf_flag_no_clear = 1; From 30d7c8f51ca42b4a598b4b1b25a9712e9e531fef Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 22:56:15 +0200 Subject: [PATCH 0936/1190] The recently introduced x86_64 variant of host_x86_MOV32_REG_ABS() was allocating the wrong number of bytes. --- src/codegen_new/codegen_backend_x86-64_ops.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index ed218d7c4..1569e693c 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -781,14 +781,9 @@ host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ codegen_addlong(block, ram_offset); } else if ((ram_offset < -2147483648LL) || (ram_offset > 2147483647LL) || !(block->flags & CODEBLOCK_NO_IMMEDIATES)) { - // fatal("host_x86_MOV32_REG_ABS - out of range\n"); - // void *q = p; - //uint32_t *r = NULL; - // *r = 5; /* Crash deliberately. */ - codegen_alloc_bytes(block, 8); + codegen_alloc_bytes(block, 13); codegen_addbyte2(block, 0x49, 0xb9); /*MOV r9,(uintptr_t) p*/ codegen_addquad(block, (uintptr_t) p); - codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/ } else { fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIX64 ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram); From b3147ee4732112a62723d6b74a1d6bd44b50476f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 02:20:18 +0200 Subject: [PATCH 0937/1190] LOCK instruction: ensure it is always illegal on opcodes 90h and ECh. --- src/codegen/codegen_x86-64.c | 13 ++++++++++++- src/codegen/codegen_x86.c | 13 ++++++++++++- src/codegen_new/codegen.c | 13 +++++++++++-- src/cpu/x86_ops_misc.h | 2 +- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index c424cf8c5..fb775a2d0 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -818,6 +818,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int over = 0; int pc_off = 0; int test_modrm = 1; + int in_lock = 0; int c; uint32_t op87 = 0x00000000; @@ -956,6 +957,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xf0: /*LOCK*/ + in_lock = 0; break; case 0xf2: /*REPNE*/ @@ -1013,6 +1015,9 @@ generate_call: STORE_IMM_ADDR_L((uintptr_t) &x87_op, op87); } + if (in_lock && ((opcode == 0x90) || (opcode == 0xec))) + goto codegen_skip; + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); if (new_pc) { @@ -1040,7 +1045,13 @@ generate_call: } } - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; +codegen_skip: + if (in_lock && ((opcode == 0x90) || (opcode == 0xec))) + /* This is always ILLEGAL. */ + op = x86_dynarec_opcodes_3DNOW[0xff]; + else + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (op_ssegs != last_ssegs) { last_ssegs = op_ssegs; addbyte(0xC6); /*MOVB $0,(ssegs)*/ diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index bf34c2de8..e0b9b633a 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1857,6 +1857,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int over = 0; int pc_off = 0; int test_modrm = 1; + int in_lock = 0; int c; uint32_t op87 = 0x00000000; @@ -1996,6 +1997,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xf0: /*LOCK*/ + in_lock = 1; break; case 0xf2: /*REPNE*/ @@ -2054,6 +2056,9 @@ generate_call: STORE_IMM_ADDR_L((uintptr_t) &x87_op, op87); } + if (in_lock && ((opcode == 0x90) || (opcode == 0xec))) + goto codegen_skip; + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); if (new_pc) { @@ -2080,7 +2085,13 @@ generate_call: } } - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; +codegen_skip: + if (in_lock && ((opcode == 0x90) || (opcode == 0xec))) + /* This is always ILLEGAL. */ + op = x86_dynarec_opcodes_3DNOW[0xff]; + else + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (op_ssegs != last_ssegs) { last_ssegs = op_ssegs; diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 44dd408ab..26a74016a 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -395,6 +395,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p int over = 0; int test_modrm = 1; int pc_off = 0; + int in_lock = 0; uint32_t next_pc = 0; uint16_t op87 = 0x0000; #ifdef DEBUG_EXTRA @@ -556,6 +557,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xf0: /*LOCK*/ + in_lock = 1; break; case 0xf2: /*REPNE*/ @@ -675,6 +677,9 @@ generate_call: goto codegen_skip; #endif + if (in_lock && ((opcode == 0x90) || (opcode == 0xec))) + goto codegen_skip; + if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc); if (new_pc) { @@ -692,13 +697,17 @@ generate_call: } } - // codegen_skip: +codegen_skip: if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { op_table = x86_dynarec_opcodes; recomp_op_table = recomp_opcodes; } - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (in_lock && ((opcode == 0x90) || (opcode == 0xec))) + /* This is always ILLEGAL. */ + op = x86_dynarec_opcodes_3DNOW[0xff]; + else + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || (op_table == x86_dynarec_opcodes_3DNOW)) { int stack_offset = 0; diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index ffc79f0e8..5ae28abc4 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -753,7 +753,7 @@ opLOCK(uint32_t fetchdat) return 0; cpu_state.pc++; - ILLEGAL_ON((fetchdat & 0xff) == 0x90); + ILLEGAL_ON(((fetchdat & 0xff) == 0x90) || ((fetchdat & 0xff) == 0xec)); CLOCK_CYCLES(4); PREFETCH_PREFIX(); From 20b2b1c90177b5a60bcd7ad7f8b3e70342aa35d3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 02:40:49 +0200 Subject: [PATCH 0938/1190] RZ-1000: Do not initialize the second IDE channel if the controller is single-channel. --- src/disk/hdc_ide_rz1000.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/disk/hdc_ide_rz1000.c b/src/disk/hdc_ide_rz1000.c index 2c1a09e8e..e2c7179ad 100644 --- a/src/disk/hdc_ide_rz1000.c +++ b/src/disk/hdc_ide_rz1000.c @@ -272,7 +272,10 @@ rz1000_init(const device_t *info) dev->channels = ((info->local & 0x60000) >> 17) & 0x03; - device_add(&ide_pci_2ch_device); + if (dev->channels & 0x02) + device_add(&ide_pci_2ch_device); + else + device_add(&ide_pci_device); if (info->local & 0x80000) pci_add_card(PCI_ADD_NORMAL, rz1000_pci_read, rz1000_pci_write, dev, &dev->pci_slot); From d6231de1bcff03db0cb808d06da6099927a9d4b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 05:59:13 +0200 Subject: [PATCH 0939/1190] Added the Dell 466/NP, closes #3585. --- src/include/86box/machine.h | 2 ++ src/include/86box/video.h | 1 + src/machine/m_at_386dx_486.c | 37 ++++++++++++++++++++++++++++--- src/machine/machine_table.c | 40 +++++++++++++++++++++++++++++++++ src/video/vid_cl54xx.c | 43 +++++++++++++++++------------------- 5 files changed, 97 insertions(+), 26 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index febce3fa1..c76761b3c 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -532,6 +532,8 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); extern int machine_at_decpclpv_init(const machine_t *); +extern int machine_at_dell466np_init(const machine_t *); + extern int machine_at_acerv10_init(const machine_t *); extern int machine_at_acera1g_init(const machine_t *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index bbcc94fe7..085dd5f80 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -365,6 +365,7 @@ extern const device_t gd5428_boca_isa_device; extern const device_t gd5428_mca_device; extern const device_t gd5426_mca_device; extern const device_t gd5428_onboard_device; +extern const device_t gd5428_onboard_vlb_device; extern const device_t gd5429_isa_device; extern const device_t gd5429_vlb_device; extern const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index c2cf82352..e03b6d65d 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -545,16 +545,47 @@ machine_at_decpclpv_init(const machine_t *model) device_add(&sis_85c461_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&s3_86c805_onboard_vlb_device); + device_add(machine_get_vid_device(machine)); + + device_add(&keyboard_ps2_phoenix_pci_device); - /* TODO: Phoenix MultiKey KBC */ - device_add(&keyboard_ps2_ami_pci_device); device_add(&ide_isa_2ch_device); device_add(&fdc37c663_ide_device); return ret; } +int +machine_at_dell466np_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dell466np/466np.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sis_85c461_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + else { + for (uint16_t i = 0; i < 32768; i++) + rom[i] = mem_readb_phys(0x000c0000 + i); + } + mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000); + mem_mapping_set_exec(&bios_mapping, rom); + + device_add(&keyboard_ps2_phoenix_pci_device); + + device_add(&ide_isa_device); + device_add(&fdc37c661_ide_device); + + return ret; +} + static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 9b53257bf..ee3485373 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6934,6 +6934,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Uses a ???? KBC. */ + { + .name = "[SiS 461] Dell 466/NP", + .internal_name = "dell466np", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_SIS_461, + .init = machine_at_dell466np_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, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .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 = &gd5428_onboard_vlb_device, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send any non-standard keyboard controller commands and wants a PS/2 mouse, so it's an IBM PS/2 KBC (Type 1) firmware. */ { diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index dbb9d5993..13f96501c 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4273,7 +4273,10 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5428: - if (info->local & 0x100) + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else if (info->local & 0x100) if (gd54xx->vlb) romfn = BIOS_GD5428_DIAMOND_B1_VLB_PATH; else { @@ -4750,26 +4753,6 @@ static const device_config_t gd5426_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t gd5428_onboard_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = NULL, - .default_int = 2048, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { - { .description = "512 KB", .value = 512 }, - { .description = "1 MB", .value = 1024 }, - { .description = "2 MB", .value = 2048 }, - { .description = "" } - }, - .bios = { { 0 } } - }, - { .name = "", .description = "", .type = CONFIG_END } -}; - static const device_config_t gd5429_config[] = { { .name = "memory", @@ -5176,7 +5159,7 @@ const device_t gd5428_onboard_device = { .available = gd5428_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5428_onboard_config + .config = gd5426_config }; const device_t gd5428_vlb_onboard_device = { @@ -5190,7 +5173,21 @@ const device_t gd5428_vlb_onboard_device = { .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5428_onboard_config + .config = gd5426_config +}; + +const device_t gd5428_onboard_vlb_device = { + .name = "Cirrus Logic GD5428 (VLB) (On-Board) (Dell)", + .internal_name = "cl_gd5428_onboard_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5428 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + .available = NULL, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config }; const device_t gd5429_isa_device = { From 8b4adebfd2bc22bc5f795c98ef288fd55b8ddae2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 06:17:24 +0200 Subject: [PATCH 0940/1190] AOpen AP5S: Add two more BIOS'es, including a 4.50PG, fulfills #643. --- src/machine/m_at_386dx_486.c | 3 -- src/machine/m_at_socket7_3v.c | 55 +++++++++++++++++++++++++++++++---- src/machine/machine_table.c | 3 +- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e03b6d65d..46b93a37f 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1727,9 +1727,6 @@ machine_at_sb486pv_init(const machine_t *model) device_context_restore(); machine_at_common_init(model); - // machine_at_common_init_ex(model, 2); - - // device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 39dc2d735..b587a8551 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -706,17 +706,62 @@ machine_at_gw2kma_init(const machine_t *model) return ret; } +static const device_config_t ap5s_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ap5s", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "04/22/96 1.20 4.50PG", .internal_name = "ap5s_450pg", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/ap5s/ap5s120.bin", "" } }, + { .name = "11/13/96 1.50 4.51PG", .internal_name = "ap5s", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/ap5s/AP5S150.BIN", "" } }, + { .name = "06/25/97 1.60 4.51PG", .internal_name = "ap5s_latest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/ap5s/ap5s160.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ap5s_device = { + .name = "AOpen AP5S", + .internal_name = "ap5s_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ap5s_config +}; + int machine_at_ap5s_init(const machine_t *model) { - int ret; + int ret = 0; + const char* fn; - ret = bios_load_linear("roms/machines/ap5s/AP5S150.BIN", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) + /* No ROMs available */ + if (!device_available(model->device)) return ret; + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + else + ret = bios_load_linear_inverted(fn, 0x000e0000, 131072, 0); + device_context_restore(); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index ee3485373..17fde9581 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -70,6 +70,7 @@ extern const device_t jukopc_device; extern const device_t vendex_device; extern const device_t c5sbm2_device; extern const device_t sb486pv_device; +extern const device_t ap5s_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -11820,7 +11821,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ap5s_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From 8ff85bf36b638c6f804956bef0283cd5b5d1473f Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sun, 18 May 2025 11:25:17 +0700 Subject: [PATCH 0941/1190] Moved "device" to .vid_device on SBC-490 --- 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 17fde9581..45986a50a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7857,10 +7857,10 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = &tgui9440_onboard_pci_device, + .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &tgui9440_onboard_pci_device, .snd_device = NULL, .net_device = NULL }, From 3f93bde031d29fbb0e43990212d478f8776e7281 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 06:44:37 +0200 Subject: [PATCH 0942/1190] AOpen AP5S: Fix BIOS loading. --- src/machine/m_at_socket7_3v.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index b587a8551..5b5724e37 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -756,10 +756,7 @@ machine_at_ap5s_init(const machine_t *model) device_context(model->device); fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); - if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) - ret = bios_load_linear(fn, 0x000e0000, 131072, 0); - else - ret = bios_load_linear_inverted(fn, 0x000e0000, 131072, 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); machine_at_common_init_ex(model, 2); From 7b9b2bc10df309d3b818e4e25e6b5022785dbc5c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 08:14:46 +0200 Subject: [PATCH 0943/1190] Some FDC, SM(S)C FDC37C66x, and VLSI VL82C480 changes. --- src/chipset/vl82c480.c | 20 +++++++++++++++----- src/floppy/fdc.c | 35 +++++++++++++++++++++++++++++----- src/include/86box/fdc.h | 42 +++++++++++++++++++++-------------------- src/sio/sio_fdc37c6xx.c | 5 ++++- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 6354ac15a..acb3568af 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -132,7 +132,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) break; case 0x02: case 0x03: dev->regs[dev->idx] = val; - if (!strcmp(machine_get_internal_name(), "martin")) + if (!strcmp(machine_get_internal_name(), "martin") || + !strcmp(machine_get_internal_name(), "prolineamt")) vl82c480_recalc_banks(dev); break; case 0x04: @@ -140,8 +141,6 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); else dev->regs[dev->idx] = val; - if (!strcmp(machine_get_internal_name(), "martin")) - dev->regs[dev->idx] &= 0x1f; break; case 0x05: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); @@ -221,6 +220,9 @@ vl82c480_init(const device_t *info) vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; uint32_t ms = mem_size; + uint8_t min_i = !strcmp(machine_get_internal_name(), "prolineamt") ? 1 : 0; + uint8_t min_j = !strcmp(machine_get_internal_name(), "prolineamt") ? 4 : 2; + uint8_t max_j = !strcmp(machine_get_internal_name(), "prolineamt") ? 8 : 7; dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; @@ -231,8 +233,16 @@ vl82c480_init(const device_t *info) dev->regs[0x07] = 0x21; dev->regs[0x08] = 0x38; - for (uint8_t i = 0; i < 4; i++) { - for (uint8_t j = 2; j < 7; j++) { + if (!strcmp(machine_get_internal_name(), "prolineamt")) { + dev->banks[0] = 4096; + + /* Bank 0 is ignored if 64 MB is installed. */ + if (ms != 65536) + ms -= 4096; + } + + if (ms > 0) for (uint8_t i = min_i; i < 4; i++) { + for (uint8_t j = min_j; j < max_j; j++) { if (ms >= sizes[j]) dev->banks[i] = sizes[j]; else diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index e7166d1ba..b43daa32c 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -469,9 +469,11 @@ fdc_update_drv2en(fdc_t *fdc, int drv2en) void fdc_update_rate(fdc_t *fdc, int drive) { - if (((fdc->rwc[drive] == 1) || (fdc->rwc[drive] == 2)) && fdc->enh_mode) + if (((fdc->rwc[drive] == 1) || (fdc->rwc[drive] == 2)) && + fdc->enh_mode && !(fdc->flags & FDC_FLAG_SMC661)) fdc->bit_rate = 500; - else if ((fdc->rwc[drive] == 3) && fdc->enh_mode) + else if ((fdc->rwc[drive] == 3) && fdc->enh_mode && + !(fdc->flags & FDC_FLAG_SMC661)) fdc->bit_rate = 250; else switch (fdc->rate) { default: @@ -535,7 +537,7 @@ fdc_get_bitcell_period(fdc_t *fdc) static int fdc_get_densel(fdc_t *fdc, int drive) { - if (fdc->enh_mode) { + if (fdc->enh_mode && !(fdc->flags & FDC_FLAG_SMC661)) { switch (fdc->rwc[drive]) { case 1: case 3: @@ -770,8 +772,13 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) return; case 3: /* TDR */ if (fdc->enh_mode) { - drive = real_drive(fdc, fdc->dor & 3); - fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); + if (fdc->flags & FDC_FLAG_SMC661) { + fdc_set_swap(fdc, !!(val & 0x20)); + fdc_update_densel_force(fdc, (val & 0x18) >> 3); + } else { + drive = real_drive(fdc, fdc->dor & 3); + fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); + } } /* Bit 2: FIFO test mode (PS/55 5550-S,T only. Undocumented) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. @@ -1391,6 +1398,8 @@ fdc_read(uint16_t addr, void *priv) /* PS/55 POST throws an error and halt if ret = 1 or 2, somehow. */ } else if (!fdc->enh_mode) ret = 0x20; + else if (fdc->flags & FDC_FLAG_SMC661) + ret = (fdc->densel_force << 3) | ((!!fdc->swap) << 5) | (fdc->media_id << 6); else ret = (fdc->rwc[drive] << 4) | (fdc->media_id << 6); break; @@ -2401,6 +2410,8 @@ fdc_init(const device_t *info) fdc_t *fdc = (fdc_t *) calloc(1, sizeof(fdc_t)); fdc->flags = info->local; + if (fdc->flags & FDC_FLAG_SMC661) + pclog("661!\n"); if (fdc->flags & FDC_FLAG_SEC) fdc->irq = FDC_SECONDARY_IRQ; @@ -2644,6 +2655,20 @@ const device_t fdc_at_actlow_device = { .config = NULL }; +const device_t fdc_at_smc_661_device = { + .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37C661/2)", + .internal_name = "fdc_at_smc", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_SMC661, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc_at_smc_device = { .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .internal_name = "fdc_at_smc", diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index ed62cb45f..53511daac 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -38,26 +38,27 @@ #define FDC_QUATERNARY_IRQ 6 #define FDC_QUATERNARY_DMA 2 -#define FDC_FLAG_PCJR 0x01 /* PCjr */ -#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ -#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ -#define FDC_FLAG_PS2 0x08 /* PS/1, PS/2 ISA */ -#define FDC_FLAG_PS2_MCA 0x10 /* PS/2 MCA */ -#define FDC_FLAG_SUPERIO 0x20 /* Super I/O chips */ -#define FDC_FLAG_START_RWC_1 0x40 /* W83877F, W83977F */ -#define FDC_FLAG_MORE_TRACKS 0x80 /* W83877F, W83977F, PC87306, PC87309 */ -#define FDC_FLAG_NSC 0x100 /* PC87306, PC87309 */ -#define FDC_FLAG_TOSHIBA 0x200 /* T1000, T1200 */ -#define FDC_FLAG_AMSTRAD 0x400 /* Non-AT Amstrad machines */ -#define FDC_FLAG_UMC 0x800 /* UMC UM8398 */ -#define FDC_FLAG_ALI 0x1000 /* ALi M512x / M1543C */ -#define FDC_FLAG_NO_DSR_RESET 0x2000 /* Has no DSR reset */ -#define FDC_FLAG_DENSEL_INVERT 0x4000 /* Invert DENSEL polarity */ -#define FDC_FLAG_FINTR 0x8000 /* Raise FINTR on data command finish */ -#define FDC_FLAG_NEC 0x10000 /* Is NEC upd765-compatible */ -#define FDC_FLAG_SEC 0x20000 /* Is Secondary */ -#define FDC_FLAG_TER 0x40000 /* Is Tertiary */ -#define FDC_FLAG_QUA 0x80000 /* Is Quaternary */ +#define FDC_FLAG_PCJR 0x01 /* PCjr */ +#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ +#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ +#define FDC_FLAG_PS2 0x08 /* PS/1, PS/2 ISA */ +#define FDC_FLAG_PS2_MCA 0x10 /* PS/2 MCA */ +#define FDC_FLAG_SUPERIO 0x20 /* Super I/O chips */ +#define FDC_FLAG_START_RWC_1 0x40 /* W83877F, W83977F */ +#define FDC_FLAG_MORE_TRACKS 0x80 /* W83877F, W83977F, PC87306, PC87309 */ +#define FDC_FLAG_NSC 0x100 /* PC87306, PC87309 */ +#define FDC_FLAG_TOSHIBA 0x200 /* T1000, T1200 */ +#define FDC_FLAG_AMSTRAD 0x400 /* Non-AT Amstrad machines */ +#define FDC_FLAG_UMC 0x800 /* UMC UM8398 */ +#define FDC_FLAG_ALI 0x1000 /* ALi M512x / M1543C */ +#define FDC_FLAG_NO_DSR_RESET 0x2000 /* Has no DSR reset */ +#define FDC_FLAG_DENSEL_INVERT 0x4000 /* Invert DENSEL polarity */ +#define FDC_FLAG_FINTR 0x8000 /* Raise FINTR on data command finish */ +#define FDC_FLAG_NEC 0x10000 /* Is NEC upd765-compatible */ +#define FDC_FLAG_SEC 0x20000 /* Is Secondary */ +#define FDC_FLAG_TER 0x40000 /* Is Tertiary */ +#define FDC_FLAG_QUA 0x80000 /* Is Quaternary */ +#define FDC_FLAG_SMC661 0x100000 /* SM(s)C FDC37C661 - different TDR enhanced mode */ typedef struct fdc_t { uint8_t dor; @@ -260,6 +261,7 @@ extern const device_t fdc_at_sec_device; extern const device_t fdc_at_ter_device; extern const device_t fdc_at_qua_device; extern const device_t fdc_at_actlow_device; +extern const device_t fdc_at_smc_661_device; extern const device_t fdc_at_smc_device; extern const device_t fdc_at_ali_device; extern const device_t fdc_at_winbond_device; diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 3afd92e4c..aa66af883 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -314,7 +314,10 @@ fdc37c6xx_init(const device_t *info) { fdc37c6xx_t *dev = (fdc37c6xx_t *) calloc(1, sizeof(fdc37c6xx_t)); - dev->fdc = device_add(&fdc_at_smc_device); + if (dev->chip_id >= 0x63) + dev->fdc = device_add(&fdc_at_smc_device); + else + dev->fdc = device_add(&fdc_at_smc_661_device); dev->chip_id = info->local & 0xff; dev->has_ide = (info->local >> 8) & 0xff; From 196289d6e50c1f2f76fd220030117e61290775a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 08:17:04 +0200 Subject: [PATCH 0944/1190] AT KBC fixes for the Dell. --- src/device/kbc_at.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index a8a8c51cc..58aab476c 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1088,12 +1088,24 @@ write64_generic(void *priv, uint8_t val) /* (B0 or F0) | (0x04 or 0x0c) */ kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00); } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) { - /* (B0 or F0) | (0x08 or 0x0c) */ - uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) | - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c); - if (!strcmp(machine_get_internal_name(), "alfredo")) - p1_out &= 0xef; - kbc_delay_to_ob(dev, p1_out, 0, 0x00); + if (!strcmp(machine_get_internal_name(), "dell466np")) { + /* + Dell 466/NP: + - Bit 2: Keyboard fuse (must be set); + - Bit 4: Password disable jumper (must be clear); + - Bit 5: Manufacturing jumper (must be set); + */ + uint8_t p1 = 0x24; + kbc_delay_to_ob(dev, p1, 0, 0x01); + } else { + /* (B0 or F0) | (0x08 or 0x0c) */ + uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) | + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c); + if (!strcmp(machine_get_internal_name(), "alfredo")) + p1_out &= 0xef; + + kbc_delay_to_ob(dev, p1_out, 0, 0x00); + } } else if (kbc_ven == KBC_VEN_COMPAQ) kbc_delay_to_ob(dev, dev->p1 | (hasfpu ? 0x00 : 0x04), 0, 0x00); else From 76c3ad9868bf83c8f90a860e4a6ce15ca6053942 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 08:18:18 +0200 Subject: [PATCH 0945/1190] Removed an excess logging line. --- src/floppy/fdc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index b43daa32c..cf5ae41bf 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2410,8 +2410,6 @@ fdc_init(const device_t *info) fdc_t *fdc = (fdc_t *) calloc(1, sizeof(fdc_t)); fdc->flags = info->local; - if (fdc->flags & FDC_FLAG_SMC661) - pclog("661!\n"); if (fdc->flags & FDC_FLAG_SEC) fdc->irq = FDC_SECONDARY_IRQ; From 5dc99cc137b1815b67069a29dc29d5453069ba2f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 08:37:02 +0200 Subject: [PATCH 0946/1190] SiS 85c46x and 471 - implement AT bus speed configuration. --- src/chipset/sis_85c4xx.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index f715c5272..be5bd668e 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -15,6 +15,7 @@ * * Copyright 2019-2020 Miran Grca. */ +#include #include #include #include @@ -631,6 +632,41 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) sis_85c4xx_recalcremap(dev); break; + case 0x10: + if (dev->reg_base == 0x50) { + double bus_clk; + + switch (val & 0xe0) { + default: + case 0x00: + bus_clk = 7159091.0; + break; + case 0x02: + bus_clk = cpu_busspeed / 10.0; + break; + case 0x04: + bus_clk = cpu_busspeed / 8.0; + break; + case 0x06: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x80: + bus_clk = cpu_busspeed / 5.0; + break; + case 0xa0: + bus_clk = cpu_busspeed / 4.0; + break; + case 0xc0: + bus_clk = cpu_busspeed / 3.0; + break; + case 0xe0: + bus_clk = cpu_busspeed / 2.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + } + break; + case 0x13: if (dev->is_471 && (valxor & 0xf0)) { smram_disable(dev->smram); @@ -813,6 +849,9 @@ sis_85c4xx_reset(void *priv) dev->force_flush = 1; sis_85c4xx_recalcmapping(dev); + + if (dev->reg_base == 0x50) + cpu_set_isa_speed((int) round(7159091.0)); } static void From 3b7515a4ff5b1b3ae611e19a50995f5e26b27ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 18 May 2025 09:11:13 +0200 Subject: [PATCH 0947/1190] Treat port 0x84, even if something is listening to it, as a delay port, fixes the Dell 466/NP on faster CPU's. --- src/io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io.c b/src/io.c index 9554c971d..45dd4cb3d 100644 --- a/src/io.c +++ b/src/io.c @@ -445,10 +445,10 @@ outb(uint16_t port, uint8_t val) } } - if (!found) { + if (!found || (port == 0x84)) { cycles -= io_delay; #ifdef USE_DYNAREC - if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) + if (cpu_use_dynarec && ((port == 0x84) || (port == 0xeb) || (port == 0xed))) update_tsc(); #endif } From 643389e0fe0e1435d3581125a9c52adf9f9ffd3c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 18 May 2025 13:44:04 +0600 Subject: [PATCH 0948/1190] Revert "SAASound filter fixes" This reverts commit 14ffb89f4d01fe01353e97edf7b874d9f6944477. --- src/sound/saasound/SAAImpl.cpp | 1 + src/sound/saasound/SAAImpl.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sound/saasound/SAAImpl.cpp b/src/sound/saasound/SAAImpl.cpp index cb5d8f739..f136eefc6 100644 --- a/src/sound/saasound/SAAImpl.cpp +++ b/src/sound/saasound/SAAImpl.cpp @@ -306,6 +306,7 @@ void scale_for_output(unsigned int left_input, unsigned int right_input, void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples) { unsigned int left_mixed, right_mixed; + static double filterout_z1_left_mixed = 0, filterout_z1_right_mixed = 0; #if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) BYTE* pBufferStart = pBuffer; diff --git a/src/sound/saasound/SAAImpl.h b/src/sound/saasound/SAAImpl.h index 6cd3048fe..61fa79c58 100755 --- a/src/sound/saasound/SAAImpl.h +++ b/src/sound/saasound/SAAImpl.h @@ -36,8 +36,6 @@ private: unsigned int m_nSampleRate; unsigned int m_nOversample; bool m_bHighpass; - double filterout_z1_left_mixed = 0; - double filterout_z1_right_mixed = 0; #ifdef USE_CONFIG_FILE SAAConfig m_Config; #endif From 5fce54a7f0f36f886c836945c64e69a35d32c7a8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 18 May 2025 13:44:22 +0600 Subject: [PATCH 0949/1190] Revert "CMS: Divide SAA samples by 2 so that the sum remains within the -32767 to 32768 range and avoids clipping." This reverts commit c63d900a9383b74fbd8a5fa7209a0b2a6364a913. --- src/sound/snd_cms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 9491e3076..c6591b1fc 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -34,7 +34,7 @@ cms_get_buffer(int32_t *buffer, int len, void *priv) cms_update(cms); for (int c = 0; c < len * 2; c++) - buffer[c] += (cms->buffer[c] / 2); + buffer[c] += cms->buffer[c]; cms->pos = 0; } @@ -47,7 +47,7 @@ cms_get_buffer_2(int32_t *buffer, int len, void *priv) cms_update(cms); for (int c = 0; c < len * 2; c++) - buffer[c] += (cms->buffer2[c] / 2); + buffer[c] += cms->buffer2[c]; cms->pos2 = 0; } From 9cfe5141d4595cf84b0afec21be56c592aba3ae7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 18 May 2025 13:44:49 +0600 Subject: [PATCH 0950/1190] Revert "Port Sound Blaster 1.x/2.x SAA1099 emulation to SAASound" This reverts commit b644016d1e0a7a917637c2fadcf8d8056d09b4ab. --- src/sound/snd_sb.c | 65 ++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 4a17fe20b..e89946486 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -41,7 +41,6 @@ #include <86box/sound.h> #include "cpu.h" #include <86box/timer.h> -#include "saasound/SAASound.h" #include <86box/snd_sb.h> #include <86box/plat_unused.h> @@ -146,42 +145,6 @@ sb_log(const char *fmt, ...) # define sb_log(fmt, ...) #endif -void -sb_cms_get_buffer(int32_t *buffer, int len, void *priv) -{ - sb_t *sb = (sb_t *) priv; - - cms_update(&sb->cms); - - for (int c = 0; c < len * 2; c++) { - if (sb->mixer_enabled) { - buffer[c] += sb->cms.buffer[c] * sb->mixer_sb2.fm; - } - else - buffer[c] += sb->cms.buffer[c]; - } - - sb->cms.pos = 0; -} - -void -sb_cms_get_buffer_2(int32_t *buffer, int len, void *priv) -{ - sb_t *sb = (sb_t *) priv; - - cms_update(&sb->cms); - - for (int c = 0; c < len * 2; c++) { - if (sb->mixer_enabled) { - buffer[c] += sb->cms.buffer2[c] * sb->mixer_sb2.fm; - } - else - buffer[c] += sb->cms.buffer2[c]; - } - - sb->cms.pos2 = 0; -} - /* SB 1, 1.5, MCV, and 2 do not have a mixer, so signal is hardwired. */ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) @@ -192,10 +155,23 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) sb_dsp_update(&sb->dsp); + if (sb->cms_enabled) + cms_update(&sb->cms); + for (int c = 0; c < len * 2; c += 2) { double out_l = 0.0; double out_r = 0.0; + if (sb->cms_enabled) { + out_l += sb->cms.buffer[c]; + out_r += sb->cms.buffer[c + 1]; + } + + if (sb->cms_enabled && sb->mixer_enabled) { + out_l *= mixer->fm; + out_r *= mixer->fm; + } + /* TODO: Recording: I assume it has direct mic and line in like SB2. It is unclear from the docs if it has a filter, but it probably does. */ /* TODO: Recording: Mic and line In with AGC. */ @@ -216,6 +192,9 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) } sb->dsp.pos = 0; + + if (sb->cms_enabled) + sb->cms.pos = 0; } static void @@ -2911,13 +2890,6 @@ sb_init(UNUSED(const device_t *info)) cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); - - sb->cms.saasound = newSAASND(); - SAASNDSetSoundParameters(sb->cms.saasound, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); - sb->cms.saasound2 = newSAASND(); - SAASNDSetSoundParameters(sb->cms.saasound2, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); - wavetable_add_handler(sb_cms_get_buffer, sb); - wavetable_add_handler(sb_cms_get_buffer_2, sb); } if (mixer_addr > 0x000) { @@ -4072,11 +4044,6 @@ sb_close(void *priv) sb_t *sb = (sb_t *) priv; sb_dsp_close(&sb->dsp); - if (sb->cms_enabled) { - deleteSAASND(sb->cms.saasound); - deleteSAASND(sb->cms.saasound2); - } - free(sb); } From 5390f50e516aaa8ec4370db30cc528a1757bd4b3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 18 May 2025 13:47:06 +0600 Subject: [PATCH 0951/1190] Revert "Switch to SAASound for CMS" This reverts commit fd618440618e3d6e426d60e59921fd8495531b09. --- src/include/86box/snd_cms.h | 23 +- src/sound/CMakeLists.txt | 3 - src/sound/saasound/CMakeLists.txt | 16 - src/sound/saasound/SAAAmp.cpp | 203 --------- src/sound/saasound/SAAAmp.h | 44 -- src/sound/saasound/SAAConfig.h | 41 -- src/sound/saasound/SAADevice.cpp | 392 ----------------- src/sound/saasound/SAADevice.h | 69 --- src/sound/saasound/SAAEnv.cpp | 380 ---------------- src/sound/saasound/SAAEnv.h | 54 --- src/sound/saasound/SAAFreq.cpp | 287 ------------ src/sound/saasound/SAAFreq.dat | 141 ------ src/sound/saasound/SAAFreq.h | 72 --- src/sound/saasound/SAAImpl.cpp | 489 --------------------- src/sound/saasound/SAAImpl.h | 75 ---- src/sound/saasound/SAANoise.cpp | 180 -------- src/sound/saasound/SAANoise.h | 54 --- src/sound/saasound/SAASndC.cpp | 100 ----- src/sound/saasound/SAASndC.h | 102 ----- src/sound/saasound/SAASound.cpp | 13 - src/sound/saasound/SAASound.h | 130 ------ src/sound/saasound/defns.h | 59 --- src/sound/saasound/resource.h | 15 - src/sound/saasound/saasound_cmake_config.h | 14 - src/sound/saasound/types.h | 34 -- src/sound/snd_cms.c | 140 ++++-- 26 files changed, 115 insertions(+), 3015 deletions(-) delete mode 100644 src/sound/saasound/CMakeLists.txt delete mode 100755 src/sound/saasound/SAAAmp.cpp delete mode 100755 src/sound/saasound/SAAAmp.h delete mode 100644 src/sound/saasound/SAAConfig.h delete mode 100644 src/sound/saasound/SAADevice.cpp delete mode 100644 src/sound/saasound/SAADevice.h delete mode 100755 src/sound/saasound/SAAEnv.cpp delete mode 100755 src/sound/saasound/SAAEnv.h delete mode 100755 src/sound/saasound/SAAFreq.cpp delete mode 100755 src/sound/saasound/SAAFreq.dat delete mode 100755 src/sound/saasound/SAAFreq.h delete mode 100644 src/sound/saasound/SAAImpl.cpp delete mode 100755 src/sound/saasound/SAAImpl.h delete mode 100755 src/sound/saasound/SAANoise.cpp delete mode 100755 src/sound/saasound/SAANoise.h delete mode 100755 src/sound/saasound/SAASndC.cpp delete mode 100644 src/sound/saasound/SAASndC.h delete mode 100755 src/sound/saasound/SAASound.cpp delete mode 100644 src/sound/saasound/SAASound.h delete mode 100644 src/sound/saasound/defns.h delete mode 100755 src/sound/saasound/resource.h delete mode 100644 src/sound/saasound/saasound_cmake_config.h delete mode 100755 src/sound/saasound/types.h diff --git a/src/include/86box/snd_cms.h b/src/include/86box/snd_cms.h index 8201fe32c..8eec22935 100644 --- a/src/include/86box/snd_cms.h +++ b/src/include/86box/snd_cms.h @@ -7,20 +7,23 @@ #define MASTER_CLOCK 7159090 typedef struct cms_t { -#ifdef SAASOUND_H_INCLUDED - SAASND saasound; - SAASND saasound2; -#else - void* saasound; - void* saasound2; -#endif + int addrs[2]; + uint8_t regs[2][32]; + uint16_t latch[2][6]; + int freq[2][6]; + float count[2][6]; + int vol[2][6][2]; + int stat[2][6]; + uint16_t noise[2][2]; + uint16_t noisefreq[2][2]; + int noisecount[2][2]; + int noisetype[2][2]; uint8_t latched_data; - int16_t buffer[WTBUFLEN * 2]; - int16_t buffer2[WTBUFLEN * 2]; + int16_t buffer[SOUNDBUFLEN * 2]; - int pos, pos2; + int pos; } cms_t; extern void cms_update(cms_t *cms); diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index d575717a0..0a04b0ff1 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -180,9 +180,6 @@ endif() add_subdirectory(ymfm) target_link_libraries(86Box ymfm) -add_subdirectory(saasound) -target_link_libraries(86Box saasound) - if(GUSMAX) target_compile_definitions(snd PRIVATE USE_GUSMAX) endif() diff --git a/src/sound/saasound/CMakeLists.txt b/src/sound/saasound/CMakeLists.txt deleted file mode 100644 index 2db75493e..000000000 --- a/src/sound/saasound/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -add_library(saasound OBJECT - SAAAmp.cpp - SAAAmp.h - SAADevice.cpp - SAADevice.h - SAAEnv.cpp - SAAEnv.h - SAAFreq.cpp - SAAFreq.h - SAAImpl.cpp - SAAImpl.h - SAANoise.cpp - SAANoise.h - SAASndC.cpp - SAASndC.h - SAASound.cpp) \ No newline at end of file diff --git a/src/sound/saasound/SAAAmp.cpp b/src/sound/saasound/SAAAmp.cpp deleted file mode 100755 index 8f2473fb1..000000000 --- a/src/sound/saasound/SAAAmp.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAAmp.cpp: implementation of the CSAAAmp class. -// This class handles Tone/Noise mixing, Envelope application and -// amplification. -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" -#include "types.h" -#include "SAANoise.h" -#include "SAAEnv.h" -#include "SAAFreq.h" -#include "SAAAmp.h" -#include "defns.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSAAAmp::CSAAAmp(CSAAFreq * const ToneGenerator, const CSAANoise * const NoiseGenerator, const CSAAEnv * const EnvGenerator) -: -m_pcConnectedToneGenerator(ToneGenerator), -m_pcConnectedNoiseGenerator(NoiseGenerator), -m_pcConnectedEnvGenerator(EnvGenerator), -m_bUseEnvelope(EnvGenerator != NULL) -{ - leftlevel = 0; - leftlevela0x0e = 0; - rightlevel = 0; - rightlevela0x0e = 0; - m_nMixMode = 0; - m_bMute=true; - m_bSync = false; - m_nOutputIntermediate=0; - last_level_byte=0; - SetAmpLevel(0x00); - -} - -CSAAAmp::~CSAAAmp() -{ - // Nothing to do -} - -void CSAAAmp::SetAmpLevel(BYTE level_byte) -{ - // if level unchanged since last call then do nothing - if (level_byte != last_level_byte) - { - last_level_byte = level_byte; - leftlevel = level_byte & 0x0f; - leftlevela0x0e = leftlevel & 0x0e; - - rightlevel = (level_byte >> 4) & 0x0f; - rightlevela0x0e = rightlevel & 0x0e; - } - -} - -void CSAAAmp::SetToneMixer(BYTE bEnabled) -{ - if (bEnabled == 0) - { - // clear mixer bit - m_nMixMode &= ~(0x01); - } - else - { - // set mixer bit - m_nMixMode |= 0x01; - } -} - -void CSAAAmp::SetNoiseMixer(BYTE bEnabled) -{ - if (bEnabled == 0) - { - m_nMixMode &= ~(0x02); - } - else - { - m_nMixMode |= 0x02; - } -} - -void CSAAAmp::Mute(bool bMute) -{ - // m_bMute refers to the GLOBAL mute setting (register 28 bit 0) - // NOT the per-channel mixer settings !! - m_bMute = bMute; -} - -void CSAAAmp::Sync(bool bSync) -{ - // m_bSync refers to the GLOBAL sync setting (register 28 bit 1) - m_bSync = bSync; -} - -void CSAAAmp::Tick(void) -{ - // updates m_nOutputIntermediate to 0, 1 or 2 - // - - // connected oscillator always ticks (this isn't really connected to the amp) - int level = m_pcConnectedToneGenerator->Tick(); - - switch (m_nMixMode) - { - case 0: - // no tone or noise for this channel - m_nOutputIntermediate = 0; - break; - case 1: - // tone only for this channel - m_nOutputIntermediate = level * 2; - // NOTE: ConnectedToneGenerator returns either 0 or 1 - break; - case 2: - // noise only for this channel - m_nOutputIntermediate = m_pcConnectedNoiseGenerator->Level() * 2; - // NOTE: ConnectedNoiseGenerator()->Level() returns either 0 or 1 - break; - case 3: - // tone+noise for this channel ... mixing algorithm : - // tone noise output - // 0 0 0 - // 1 0 2 - // 0 1 0 - // 1 1 1 - // = 2 * tone - 1 * (tone & noise) - // = tone * (2 - noise) - m_nOutputIntermediate = level * (2 - m_pcConnectedNoiseGenerator->Level()); - break; - } - // intermediate is between 0 and 2 -} - -inline int CSAAAmp::EffectiveAmplitude(int amp, int env) const -{ - // Return the effective amplitude of the low-pass-filtered result of the logical - // AND of the amplitude PDM and envelope PDM patterns. This is a more accurate - // evaluation of the SAA than simply returning amp * env , based on how the SAA - // implements pulse-density modulation. - static const int pdm[16][16] = { - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,2,2,2,2,2,2,2,2,4,4,4,4}, - {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8}, - {0,1,1,2,4,5,5,6,6,7,7,8,10,11,11,12}, - {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, - {0,1,2,3,6,7,8,9,10,11,12,13,16,17,18,19}, - {0,2,3,5,6,8,9,11,12,14,15,17,18,20,21,23}, - {0,2,3,5,8,10,11,13,14,16,17,19,22,24,25,27}, - {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30}, - {0,2,4,6,10,12,14,16,18,20,22,24,28,30,32,34}, - {0,3,5,8,10,13,15,18,20,23,25,28,30,33,35,38}, - {0,3,5,8,12,15,17,20,22,25,27,30,34,37,39,42}, - {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}, - {0,3,6,9,14,17,20,23,26,29,32,35,40,43,46,49}, - {0,4,7,11,14,18,21,25,28,32,35,39,42,46,49,53}, - {0,4,7,11,16,20,23,27,30,34,37,41,46,50,53,57} - }; - - return(pdm[amp][env] * 4); -} - -void CSAAAmp::TickAndOutputStereo(unsigned int & left, unsigned int & right) -{ - // This returns a value between 0 and 480 inclusive. - // This represents the full dynamic range of one output mixer (tone, or noise+tone, at full volume, - // without envelopes enabled). Note that, with envelopes enabled, the actual dynamic range - // is reduced on-chip to just over 88% of this (424), so the "loudest" output requires disabling envs. - // NB for 6 channels at full volume, with simple additive mixing, you would see a combined - // output of 2880, and a multiplier of 11 (=31680) fits comfortably within 16-bit signed output range. - - if (m_bSync) - { - // TODO check this - left = right = 0; - return; - } - - // first, do the Tick: - Tick(); - - // now calculate the returned amplitude for this sample: - //////////////////////////////////////////////////////// - - if (m_bMute) - { - left = right = 0; - } - else if (m_bUseEnvelope && m_pcConnectedEnvGenerator->IsActive()) - { - left = EffectiveAmplitude(m_pcConnectedEnvGenerator->LeftLevel(), leftlevela0x0e) * (2 - m_nOutputIntermediate); - right = EffectiveAmplitude(m_pcConnectedEnvGenerator->RightLevel(), rightlevela0x0e) * (2 - m_nOutputIntermediate); - } - else - { - left = leftlevel * m_nOutputIntermediate * 16; - right = rightlevel * m_nOutputIntermediate * 16; - } -} diff --git a/src/sound/saasound/SAAAmp.h b/src/sound/saasound/SAAAmp.h deleted file mode 100755 index 4a6761f21..000000000 --- a/src/sound/saasound/SAAAmp.h +++ /dev/null @@ -1,44 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAAmp.h: interface for the CSAAAmp class. -// This class handles Tone/Noise mixing, Envelope application and -// amplification. -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAAAMP_H_INCLUDED -#define SAAAMP_H_INCLUDED - -class CSAAAmp -{ -private: - int leftlevel; - int leftlevela0x0e; - int rightlevel; - int rightlevela0x0e; - int m_nOutputIntermediate; - unsigned int m_nMixMode; - CSAAFreq * const m_pcConnectedToneGenerator; // not const because amp calls ->Tick() - const CSAANoise * const m_pcConnectedNoiseGenerator; - const CSAAEnv * const m_pcConnectedEnvGenerator; - const bool m_bUseEnvelope; - mutable bool m_bMute; - mutable bool m_bSync; - mutable BYTE last_level_byte; - int EffectiveAmplitude(int amp, int env) const; - -public: - CSAAAmp(CSAAFreq * const ToneGenerator, const CSAANoise * const NoiseGenerator, const CSAAEnv * const EnvGenerator); - ~CSAAAmp(); - - void SetAmpLevel(BYTE level_byte); // really just a BYTE - void SetToneMixer(BYTE bEnabled); - void SetNoiseMixer(BYTE bEnabled); - void Mute(bool bMute); - void Sync(bool bSync); - void Tick(void); - void TickAndOutputStereo(unsigned int & left, unsigned int & right); - -}; - -#endif // SAAAMP_H_INCLUDED diff --git a/src/sound/saasound/SAAConfig.h b/src/sound/saasound/SAAConfig.h deleted file mode 100644 index a655ec59f..000000000 --- a/src/sound/saasound/SAAConfig.h +++ /dev/null @@ -1,41 +0,0 @@ -// Part of SAASound copyright 2020 Dave Hooper -// -// SAAConfig.h: configuration file handler class -// -////////////////////////////////////////////////////////////////////// - -#include "defns.h" -#ifdef USE_CONFIG_FILE - -#ifndef SAA_CONFIG_H_INCLUDED -#define SAA_CONFIG_H_INCLUDED - -#define INI_READONLY -#define INI_ANSIONLY /*nb not really 'ANSI', this just forces all read/write to use 8-bit char*/ -#include "minIni/minIni.h" - -class SAAConfig -{ -private: - minIni m_minIni; - bool m_bHasReadConfig; - -public: - bool m_bGenerateRegisterLogs; - bool m_bGeneratePcmLogs; - bool m_bGeneratePcmSeparateChannels; - t_string m_strRegisterLogPath; - t_string m_strPcmOutputPath; - unsigned int m_nOversample; - bool m_bHighpass; - double m_nBoost; - - SAAConfig(); - void ReadConfig(); - - t_string getChannelPcmOutputPath(int); -}; - -#endif // SAA_CONFIG_H_INCLUDED - -#endif // USE_CONFIG_FILE \ No newline at end of file diff --git a/src/sound/saasound/SAADevice.cpp b/src/sound/saasound/SAADevice.cpp deleted file mode 100644 index 718b05a95..000000000 --- a/src/sound/saasound/SAADevice.cpp +++ /dev/null @@ -1,392 +0,0 @@ -// Part of SAASound copyright 2020 Dave Hooper -// -// SAADevice.cpp: connecting the subcomponents of the SAA1099 together. -// This class handles device inputs and outputs (clocking, data and -// address bus, and simulated output) -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" -#include "types.h" -#include "SAAEnv.h" -#include "SAANoise.h" -#include "SAAFreq.h" -#include "SAAAmp.h" -#include "SAASound.h" -#include "SAAImpl.h" -#include "defns.h" - - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSAADevice::CSAADevice() - : - m_nCurrentSaaReg(0), - m_bOutputEnabled(false), - m_bSync(false), - m_bHighpass(true), - m_nOversample(0), - m_Noise0(0xffffffff), - m_Noise1(0xffffffff), - m_Env0(), - m_Env1(), - m_Osc0(&m_Noise0, NULL), - m_Osc1(NULL, &m_Env0), - m_Osc2(NULL, NULL), - m_Osc3(&m_Noise1, NULL), - m_Osc4(NULL, &m_Env1), - m_Osc5(NULL, NULL), - m_Amp0(&m_Osc0, &m_Noise0, NULL), - m_Amp1(&m_Osc1, &m_Noise0, NULL), - m_Amp2(&m_Osc2, &m_Noise0, &m_Env0), - m_Amp3(&m_Osc3, &m_Noise1, NULL), - m_Amp4(&m_Osc4, &m_Noise1, NULL), - m_Amp5(&m_Osc5, &m_Noise1, &m_Env1) -{ - // Create and link up the objects that make up the emulator - Noise[0] = &m_Noise0; - Noise[1] = &m_Noise1; - Env[0] = &m_Env0; - Env[1] = &m_Env1; - - // Create oscillators (tone generators) and link to noise generators and - // envelope controllers - Osc[0] = &m_Osc0; - Osc[1] = &m_Osc1; - Osc[2] = &m_Osc2; - Osc[3] = &m_Osc3; - Osc[4] = &m_Osc4; - Osc[5] = &m_Osc5; - - // Create amplification/mixing stages and link to appropriate oscillators, - // noise generators and envelope controllers - Amp[0] = &m_Amp0; - Amp[1] = &m_Amp1; - Amp[2] = &m_Amp2; - Amp[3] = &m_Amp3; - Amp[4] = &m_Amp4; - Amp[5] = &m_Amp5; - - _SetClockRate(EXTERNAL_CLK_HZ); - _SetOversample(DEFAULT_OVERSAMPLE); -} - -CSAADevice::~CSAADevice() -{ -} - -////////////////////////////////////////////////////////////////////// -// CSAASound members -////////////////////////////////////////////////////////////////////// - -void CSAADevice::_SetClockRate(unsigned int nClockRate) -{ - m_Osc0._SetClockRate(nClockRate); - m_Osc1._SetClockRate(nClockRate); - m_Osc2._SetClockRate(nClockRate); - m_Osc3._SetClockRate(nClockRate); - m_Osc4._SetClockRate(nClockRate); - m_Osc5._SetClockRate(nClockRate); - m_Noise0._SetClockRate(nClockRate); - m_Noise1._SetClockRate(nClockRate); -} - -void CSAADevice::_SetSampleRate(unsigned int nSampleRate) -{ - m_Osc0._SetSampleRate(nSampleRate); - m_Osc1._SetSampleRate(nSampleRate); - m_Osc2._SetSampleRate(nSampleRate); - m_Osc3._SetSampleRate(nSampleRate); - m_Osc4._SetSampleRate(nSampleRate); - m_Osc5._SetSampleRate(nSampleRate); - m_Noise0._SetSampleRate(nSampleRate); - m_Noise1._SetSampleRate(nSampleRate); -} - -void CSAADevice::_SetOversample(unsigned int nOversample) -{ - if (((int) nOversample) != m_nOversample) - { - m_nOversample = nOversample; - m_Osc0._SetOversample(nOversample); - m_Osc1._SetOversample(nOversample); - m_Osc2._SetOversample(nOversample); - m_Osc3._SetOversample(nOversample); - m_Osc4._SetOversample(nOversample); - m_Osc5._SetOversample(nOversample); - m_Noise0._SetOversample(nOversample); - m_Noise1._SetOversample(nOversample); - } -} - -void CSAADevice::_WriteData(BYTE nData) -{ -#if defined(DEBUG) || defined(DEBUGSAA) - m_Reg[m_nCurrentSaaReg] = nData; -#endif - - // route nData to the appropriate place - switch (m_nCurrentSaaReg) - { - // Amplitude data (==> Amp) - case 0: - m_Amp0.SetAmpLevel(nData); - break; - case 1: - m_Amp1.SetAmpLevel(nData); - break; - case 2: - m_Amp2.SetAmpLevel(nData); - break; - case 3: - m_Amp3.SetAmpLevel(nData); - break; - case 4: - m_Amp4.SetAmpLevel(nData); - break; - case 5: - m_Amp5.SetAmpLevel(nData); - break; - - // Freq data (==> Osc) - case 8: - m_Osc0.SetFreqOffset(nData); - break; - case 9: - m_Osc1.SetFreqOffset(nData); - break; - case 10: - m_Osc2.SetFreqOffset(nData); - break; - case 11: - m_Osc3.SetFreqOffset(nData); - break; - case 12: - m_Osc4.SetFreqOffset(nData); - break; - case 13: - m_Osc5.SetFreqOffset(nData); - break; - - // Freq octave data (==> Osc) for channels 0,1 - case 16: - m_Osc0.SetFreqOctave(nData & 0x07); - m_Osc1.SetFreqOctave((nData >> 4) & 0x07); - break; - - // Freq octave data (==> Osc) for channels 2,3 - case 17: - m_Osc2.SetFreqOctave(nData & 0x07); - m_Osc3.SetFreqOctave((nData >> 4) & 0x07); - break; - - // Freq octave data (==> Osc) for channels 4,5 - case 18: - m_Osc4.SetFreqOctave(nData & 0x07); - m_Osc5.SetFreqOctave((nData >> 4) & 0x07); - break; - - // Tone mixer control (==> Amp) - case 20: - m_Amp0.SetToneMixer(nData & 0x01); - m_Amp1.SetToneMixer(nData & 0x02); - m_Amp2.SetToneMixer(nData & 0x04); - m_Amp3.SetToneMixer(nData & 0x08); - m_Amp4.SetToneMixer(nData & 0x10); - m_Amp5.SetToneMixer(nData & 0x20); - break; - - // Noise mixer control (==> Amp) - case 21: - m_Amp0.SetNoiseMixer(nData & 0x01); - m_Amp1.SetNoiseMixer(nData & 0x02); - m_Amp2.SetNoiseMixer(nData & 0x04); - m_Amp3.SetNoiseMixer(nData & 0x08); - m_Amp4.SetNoiseMixer(nData & 0x10); - m_Amp5.SetNoiseMixer(nData & 0x20); - break; - - // Noise frequency/source control (==> Noise) - case 22: - m_Noise0.SetSource(nData & 0x03); - m_Noise1.SetSource((nData >> 4) & 0x03); - break; - - // Envelope control data (==> Env) for envelope controller #0 - case 24: - m_Env0.SetEnvControl(nData); - break; - - // Envelope control data (==> Env) for envelope controller #1 - case 25: - m_Env1.SetEnvControl(nData); - break; - - // Global enable and reset (sync) controls - case 28: - { - // Reset (sync) bit - bool bSync = bool(nData & 0x02); - if (bSync != m_bSync) - { - // Sync all devices - // This amounts to telling them all to reset to a - // known state, which is also a state that doesn't change - // (i.e. no audio output, although there are some exceptions) - // bSync=true => all devices are sync (aka reset); - // bSync=false => all devices are allowed to run and generate changing output - m_Osc0.Sync(bSync); - m_Osc1.Sync(bSync); - m_Osc2.Sync(bSync); - m_Osc3.Sync(bSync); - m_Osc4.Sync(bSync); - m_Osc5.Sync(bSync); - m_Noise0.Sync(bSync); - m_Noise1.Sync(bSync); - m_Amp0.Sync(bSync); - m_Amp1.Sync(bSync); - m_Amp2.Sync(bSync); - m_Amp3.Sync(bSync); - m_Amp4.Sync(bSync); - m_Amp5.Sync(bSync); - m_bSync = bSync; - } - - // Global mute bit - bool bOutputEnabled = bool(nData & 0x01); - if (bOutputEnabled != m_bOutputEnabled) - { - // unmute all amps - sound 'enabled' - m_Amp0.Mute(!bOutputEnabled); - m_Amp1.Mute(!bOutputEnabled); - m_Amp2.Mute(!bOutputEnabled); - m_Amp3.Mute(!bOutputEnabled); - m_Amp4.Mute(!bOutputEnabled); - m_Amp5.Mute(!bOutputEnabled); - m_bOutputEnabled = bOutputEnabled; - } - } - break; - - default: - // anything else means data is being written to a register - // that is not used within the SAA-1099 architecture - // hence, we ignore it. - {} - } -} - -void CSAADevice::_WriteAddress(BYTE nReg) -{ - m_nCurrentSaaReg = nReg & 31; - if (m_nCurrentSaaReg == 24) - { - m_Env0.ExternalClock(); - } - else if (m_nCurrentSaaReg == 25) - { - m_Env1.ExternalClock(); - } -} - -#if 1 -BYTE CSAADevice::_ReadAddress(void) -{ - // Not a real hardware function of the SAA-1099, which is write-only - // However, this is used by SAAImpl to generate debug logs (if enabled) - return(m_nCurrentSaaReg); -} -#endif -#if defined(DEBUG) -BYTE CSAADevice::_ReadData(void) -{ - // Not a real hardware function of the SAA-1099, which is write-only - // This is only compiled for Debug builds - return(m_Reg[m_nCurrentSaaReg]); -} -#endif - -void CSAADevice::_TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed) -{ - unsigned int temp_left, temp_right; - unsigned int accum_left = 0, accum_right = 0; - for (int i = 1 << m_nOversample; i > 0; i--) - { - m_Noise0.Tick(); - m_Noise1.Tick(); - m_Amp0.TickAndOutputStereo(temp_left, temp_right); - accum_left += temp_left; - accum_right += temp_right; - m_Amp1.TickAndOutputStereo(temp_left, temp_right); - accum_left += temp_left; - accum_right += temp_right; - m_Amp2.TickAndOutputStereo(temp_left, temp_right); - accum_left += temp_left; - accum_right += temp_right; - m_Amp3.TickAndOutputStereo(temp_left, temp_right); - accum_left += temp_left; - accum_right += temp_right; - m_Amp4.TickAndOutputStereo(temp_left, temp_right); - accum_left += temp_left; - accum_right += temp_right; - m_Amp5.TickAndOutputStereo(temp_left, temp_right); - accum_left += temp_left; - accum_right += temp_right; - } - left_mixed = accum_left; - right_mixed = accum_right; -} - -void CSAADevice::_TickAndOutputSeparate(unsigned int& left_mixed, unsigned int& right_mixed, - unsigned int& left0, unsigned int& right0, - unsigned int& left1, unsigned int& right1, - unsigned int& left2, unsigned int& right2, - unsigned int& left3, unsigned int& right3, - unsigned int& left4, unsigned int& right4, - unsigned int& left5, unsigned int& right5 -) -{ - unsigned int temp_left, temp_right; - unsigned int accum_left = 0, accum_right = 0; - left0 = left1 = left2 = left3 = left4 = left5 = 0; - right0 = right1 = right2 = right3 = right4 = right5 = 0; - for (int i = 1 << m_nOversample; i > 0; i--) - { - m_Noise0.Tick(); - m_Noise1.Tick(); - m_Amp0.TickAndOutputStereo(temp_left, temp_right); - left0 += temp_left; - right0 += temp_right; - accum_left += temp_left; - accum_right += temp_right; - m_Amp1.TickAndOutputStereo(temp_left, temp_right); - left1 += temp_left; - right1 += temp_right; - accum_left += temp_left; - accum_right += temp_right; - m_Amp2.TickAndOutputStereo(temp_left, temp_right); - left2 += temp_left; - right2 += temp_right; - accum_left += temp_left; - accum_right += temp_right; - m_Amp3.TickAndOutputStereo(temp_left, temp_right); - left3 += temp_left; - right3 += temp_right; - accum_left += temp_left; - accum_right += temp_right; - m_Amp4.TickAndOutputStereo(temp_left, temp_right); - left4 += temp_left; - right4 += temp_right; - accum_left += temp_left; - accum_right += temp_right; - m_Amp5.TickAndOutputStereo(temp_left, temp_right); - left5 += temp_left; - right5 += temp_right; - accum_left += temp_left; - accum_right += temp_right; - } - left_mixed = accum_left; - right_mixed = accum_right; -} \ No newline at end of file diff --git a/src/sound/saasound/SAADevice.h b/src/sound/saasound/SAADevice.h deleted file mode 100644 index 7b697821f..000000000 --- a/src/sound/saasound/SAADevice.h +++ /dev/null @@ -1,69 +0,0 @@ -// Part of SAASound copyright 2020 Dave Hooper -// -// SAADevice.h: connecting the subcomponents of the SAA1099 together. -// This class handles device inputs and outputs (clocking, data and -// address bus, and simulated output) -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAADEVICE_H_INCLUDED -#define SAADEVICE_H_INCLUDED - -#include "SAASound.h" -#include "SAANoise.h" -#include "SAAEnv.h" -#include "SAAFreq.h" -#include "SAAAmp.h" - -class CSAADevice -{ -private: - int m_nCurrentSaaReg; - bool m_bOutputEnabled; - bool m_bSync; - bool m_bHighpass; - int m_nOversample; - - CSAANoise m_Noise0, m_Noise1; - CSAAEnv m_Env0, m_Env1; - CSAAFreq m_Osc0, m_Osc1, m_Osc2, m_Osc3, m_Osc4, m_Osc5; - CSAAAmp m_Amp0, m_Amp1, m_Amp2, m_Amp3, m_Amp4, m_Amp5; - - CSAANoise* Noise[2]; - CSAAEnv* Env[2]; - CSAAFreq* Osc[6]; - CSAAAmp* Amp[6]; - -#if defined(DEBUG) || defined(DEBUGSAA) - BYTE m_Reg[32]; -#endif - -public: - CSAADevice(); - ~CSAADevice(); - - void _WriteAddress(BYTE nReg); - void _WriteData(BYTE nData); -#if 1 - BYTE _ReadAddress(void); -#endif -#if defined(DEBUG) - BYTE _ReadData(void); -#endif - - void _SetClockRate(unsigned int nClockRate); - void _SetSampleRate(unsigned int nSampleRate); - void _SetOversample(unsigned int nOversample); - void _TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed); - void _TickAndOutputSeparate(unsigned int& left_mixed, unsigned int& right_mixed, - unsigned int& left0, unsigned int& right0, - unsigned int& left1, unsigned int& right1, - unsigned int& left2, unsigned int& right2, - unsigned int& left3, unsigned int& right3, - unsigned int& left4, unsigned int& right4, - unsigned int& left5, unsigned int& right5 - ); - -}; - -#endif // SAADEVICE_H_INCLUDED \ No newline at end of file diff --git a/src/sound/saasound/SAAEnv.cpp b/src/sound/saasound/SAAEnv.cpp deleted file mode 100755 index 049f51f96..000000000 --- a/src/sound/saasound/SAAEnv.cpp +++ /dev/null @@ -1,380 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAEnv.cpp: implementation of the CSAAEnv class. -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" -#include "types.h" -#include "SAAEnv.h" - - -////////////////////////////////////////////////////////////////////// -// Static member initialisation -////////////////////////////////////////////////////////////////////// - -const ENVDATA CSAAEnv::cs_EnvData[8] = -{ - {1,false, { {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, - {1,true, { {{15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15},{15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15}}, - {{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14},{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}}}}, - {1,false, { {{15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, - {{14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, - {1,true, { {{15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, - {{14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, - {2,false, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}}, - {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}}}}, - {2,true, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}}, - {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {14,14,12,12,10,10,8,8,6,6,4,4,2,2,0,0}}}}, - {1,false, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, - {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}, - {1,true, { {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, - {{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}} -}; - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSAAEnv::CSAAEnv() -: -m_bEnabled(false), -m_nPhase(0), -m_nPhasePosition(0), -m_bEnvelopeEnded(true), -m_nResolution(1), -m_bNewData(false), -m_nNextData(0) -{ - // initialise itself with the value 'zero' - SetEnvControl(0); -} - -CSAAEnv::~CSAAEnv() -{ - // Nothing to do -} - -void CSAAEnv::InternalClock(void) -{ - // will only do something if envelope clock mode is set to internal - // and the env control is enabled - if (m_bEnabled && (!m_bClockExternally)) Tick(); -} - -void CSAAEnv::ExternalClock(void) -{ - // will only do something if envelope clock mode is set to external - // and the env control is enabled - if (m_bClockExternally && m_bEnabled) Tick(); -} - -void CSAAEnv::SetEnvControl(int nData) -{ - // process immediate stuff first: - // start with the Enabled flag. if env is disabled, - // there's not much to do - bool bEnabled = ((nData & 0x80)==0x80); - if (!bEnabled && !m_bEnabled) - return; - m_bEnabled = bEnabled; - if (!m_bEnabled) - { - // env control was enabled, and now disabled - // Any subsequent env control changes are immediate. - m_bEnvelopeEnded = true; - return; - } - - // Resolution (3bit/4bit) is also immediately processed - int new_resolution = ((nData & 0x10) == 0x10) ? 2 : 1; - // NOTE: undocumented behaviour when changing resolution mid-waveform - // Empirically, the following matches observations: - // * When ticking the env generator with 4-bit resolution, the position += 1 - // * When ticking the env generator with 3-bit resolution, the position += 2 - // * When changing between 4-bit resolution and 3-bit resolution - // without ticking the env generator, the position is unchanged - // (although, effectively, the LSB is ignored. Purely as an implementation - // detail, I'm implementing this as clearing the LSB ie LSB=0; see next point) - // * When changing between 3-bit resolution and 4-bit resolution - // without ticking the env generator, the position LSB is set to 1 - // See test case: envext_34b - // - if (m_nResolution == 1 && new_resolution == 2) - { - // change from 4-bit to 3-bit - m_nPhasePosition &= 0xe; - } - else if (m_nResolution == 2 && new_resolution == 1) - { - // change from 3-bit to 4-bit - m_nPhasePosition |= 0x1; - } - m_nResolution = new_resolution; - - // now buffered stuff: but only if it's ok to, and only if the - // envgenerator is not disabled. otherwise it just stays buffered until - // the Tick() function sets m_bEnvelopeEnded to true and realises there is - // already some new data waiting - if (m_bEnvelopeEnded) - { - SetNewEnvData(nData); // also does the SetLevels() call for us. - m_bNewData=false; - } - else - { - // since the 'next resolution' changes arrive unbuffered, we - // may need to change the current level because of this: - SetLevels(); - - // store current new data, and set the newdata flag: - m_bNewData = true; - m_nNextData = nData; - } - -} - -int CSAAEnv::LeftLevel(void) const -{ - return m_nLeftLevel; -} - -int CSAAEnv::RightLevel(void) const -{ - return m_nRightLevel; -} - -inline void CSAAEnv::Tick(void) -{ - // if disabled, do nothing - if (!m_bEnabled) // m_bEnabled is set directly, not buffered, so this is ok - { - // for sanity, reset stuff: - m_bEnvelopeEnded = true; - m_nPhase = 0; - m_nPhasePosition = 0; - return; - } - - // else : m_bEnabled - - - if (m_bEnvelopeEnded) - { - // do nothing - // (specifically, don't change the values of m_bEnvelopeEnded, - // m_nPhase and m_nPhasePosition, as these will still be needed - // by SetLevels() should it be called again) - - return; - } - - - // else : !m_bEnvelopeEnded - // Continue playing the same envelope ... - // increments the phaseposition within an envelope. - // also handles looping and resolution appropriately. - // Changes the level of the envelope accordingly - // through calling SetLevels() . This must be called after making - // any changes that will affect the output levels of the env controller!! - // SetLevels also handles left-right channel inverting - - // increment phase position - m_nPhasePosition += m_nResolution; - - // if this means we've gone past 16 (the end of a phase) - // then change phase, and if necessary, loop - // Refer to datasheet for meanings of (3) and (4) in following text - // w.r.t SAA1099 envelopes - - // Note that we will always reach position (3) or (4), even if we keep toggling - // resolution from 4-bit to 3-bit and back, because the counter will always wrap to 0. - // In fact it's quite elegant: - // No matter how you increment and toggle and increment and toggle, the counter - // will at some point be either 0xe (either 4-bit mode or 3-bit mode) or 0xf (4-bit mode only). - // Depending on the mode, even if you change the mode, the next increment, - // or the one after it, will then take it to 0. - // 0xe + 2 (3bit mode) => 0x0 - // 0xe + 1 (4bit mode) => 0xf - // 0xf + 1 (4bit mode) => 0x0 - // 0xe -> (toggle 3bit mode to 4bit mode) => 0xf - // 0xe -> (toggle 4bit mode to 3bit mode) => 0xe - // 0xf -> (toggle 4bit mode to 3bit mode) => 0xe - // - // but there is a subtlety (of course), which is that any changes at point (3) - // can take place immediately you hit point (3), but changes at point (4) are actually - // only acted upon when the counter transitions from 0xe (or 0xf) to 0x0 (which also - // means that, for these looping envelopes, which are the ones that have a point(4), - // immediately after the counter wrapping to 0x0, a write to the env data register will - // NOT set the waveform and will NOT reset the phase/phaseposition (even though it - // will still let you toggle the 4bit/3bit mode, which will change the phaseposition LSB!) - // See test case: envext_34c - - bool bProcessNewDataIfAvailable = false; - if (m_nPhasePosition >= 16) - { - m_nPhase++; - - // if we should loop, then do so - and we've reached position (4) - // otherwise, if we shouldn't loop, - // then we've reached position (3) and so we say that - // we're ok for new data. - if (m_nPhase == m_nNumberOfPhases) - { - // at position (3) or (4) - if (!m_bLooping) - { - // position (3) only - // note that it seems that the sustain level is ALWAYS zero - // in the case of non-looping waveforms - m_bEnvelopeEnded = true; - bProcessNewDataIfAvailable = true; - } - else - { - // position (4) only - // note that any data already latched is ONLY acted upon - // at THIS point. If (after this Tick has completed) any new - // env data is written, it will NOT be acted upon, until - // we get back to position (4) again. - // this is why m_bEnvelopeEnded (which affects the behaviour - // of the SetEnvControl method) is FALSE here. - // See test case: envext_34c (as noted earlier) - m_bEnvelopeEnded = false; - // set phase pointer to start of envelope for loop - // and reset m_nPhasePosition - m_nPhase=0; - m_nPhasePosition -= 16; - bProcessNewDataIfAvailable = true; - } - } - else // (m_nPhase < m_nNumberOfPhases) - { - // not at position (3) or (4) ... - // (i.e., we're in the middle of an envelope with - // more than one phase. Specifically, we're in - // the middle of envelope 4 or 5 - the - // triangle envelopes - but that's not important) - - // any commands sent to this envelope controller - // will be buffered. Set the flag to indicate this. - m_bEnvelopeEnded = false; - m_nPhasePosition -= 16; - } - } - else // (m_nPhasePosition < 16) - { - // still within the same phase; - // but, importantly, we are no longer at the start of the phase ... - // so new data cannot be acted on immediately, and must - // be buffered - m_bEnvelopeEnded = false; - // Phase and PhasePosition have already been updated. - // SetLevels() will need to be called to actually calculate - // the output 'level' of this envelope controller - } - - - // if we have new (buffered) data, now is the time to act on it - if (m_bNewData && bProcessNewDataIfAvailable) - { - m_bNewData = false; - SetNewEnvData(m_nNextData); - } - else - { - // ok, we didn't have any new buffered date to act on, - // so we just call SetLevels() to calculate the output level - // for whatever the current envelope is - SetLevels(); - } - -} - -inline void CSAAEnv::SetLevels(void) -{ - // sets m_nLeftLevel - // Also sets m_nRightLevel in terms of m_nLeftLevel - // and m_bInvertRightChannel - - // m_nResolution: 1 means 4-bit resolution; 2 means 3-bit resolution. Resolution of envelope waveform. - - // Note that this is handled 'immediately', and doesn't wait for synchronisation of - // the envelope waveform (this is important, see test case EnvExt_imm) - // It is therefore possible to switch between 4-bit and 3-bit resolution in the middle of - // an envelope waveform. if you are at an 'odd' phase position, you would be able to hear - // the difference. if you are at an 'even' phase position, the volume level for 4-bit - // and 3-bit would be the same. - // NOTE: additional test cases are required. - - switch (m_nResolution) - { - case 1: // 4 bit res waveforms - default: - { - // special case: if envelope is not a looping one, and we're at the end - // then our level should be zero (all of the non-looping waveforms have - // a sustain level of zero): - if (m_bEnvelopeEnded && !m_bLooping) - m_nLeftLevel = 0; - else - m_nLeftLevel = m_pEnvData->nLevels[0][m_nPhase][m_nPhasePosition]; - - if (m_bInvertRightChannel) - m_nRightLevel = 15-m_nLeftLevel; - else - m_nRightLevel = m_nLeftLevel; - break; - } - case 2: // 3 bit res waveforms - { - // special case: if envelope is not a looping one, and we're at the end - // then our level should be zero (all of the non-looping waveforms have - // a sustain level of zero): - if (m_bEnvelopeEnded && !m_bLooping) - m_nLeftLevel = 0; - else - m_nLeftLevel = m_pEnvData->nLevels[1][m_nPhase][m_nPhasePosition]; - if (m_bInvertRightChannel) - m_nRightLevel = 14-m_nLeftLevel; - else - m_nRightLevel = m_nLeftLevel; - break; - } - } -} - - -inline void CSAAEnv::SetNewEnvData(int nData) -{ - // loads envgenerator's registers according to the bits set - // in nData - - m_nPhase = 0; - m_nPhasePosition = 0; - m_pEnvData = &(cs_EnvData[(nData >> 1) & 0x07]); - m_bInvertRightChannel = ((nData & 0x01) == 0x01); - m_bClockExternally = ((nData & 0x20) == 0x20); - m_nNumberOfPhases = m_pEnvData->nNumberOfPhases; - m_bLooping = m_pEnvData->bLooping; - m_nResolution = (((nData & 0x10)==0x10) ? 2 : 1); - m_bEnabled = ((nData & 0x80) == 0x80); - if (m_bEnabled) - { - m_bEnvelopeEnded = false; - // is this right? - // YES. See test case EnvExt_34c (setting data multiple times - // when at a point (3) resets the waveform so you're no longer - // at a point (3). - } - else - { - // DISABLED - so set stuff accordingly - m_bEnvelopeEnded = true; - m_nPhase = 0; - m_nPhasePosition = 0; - } - - SetLevels(); -} diff --git a/src/sound/saasound/SAAEnv.h b/src/sound/saasound/SAAEnv.h deleted file mode 100755 index 131659c06..000000000 --- a/src/sound/saasound/SAAEnv.h +++ /dev/null @@ -1,54 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAEnv.h: interface for the CSAAEnv class. -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAAENV_H_INCLUDED -#define SAAENV_H_INCLUDED - -class CSAAEnv -{ -private: - int m_nLeftLevel, m_nRightLevel; - ENVDATA const * m_pEnvData; - - bool m_bEnabled; - bool m_bInvertRightChannel; - BYTE m_nPhase; - BYTE m_nPhasePosition; - bool m_bEnvelopeEnded; - char m_nPhaseAdd[2]; - char m_nCurrentPhaseAdd; - bool m_bLooping; - char m_nNumberOfPhases; - char m_nResolution; - char m_nInitialLevel; - bool m_bNewData; - BYTE m_nNextData; - bool m_bClockExternally; - static const ENVDATA cs_EnvData[8]; - - void Tick(void); - void SetLevels(void); - void SetNewEnvData(int nData); - -public: - CSAAEnv(); - ~CSAAEnv(); - - void InternalClock(void); - void ExternalClock(void); - void SetEnvControl(int nData); // really just a BYTE - int LeftLevel(void) const; - int RightLevel(void) const; - bool IsActive(void) const; - -}; - -inline bool CSAAEnv::IsActive(void) const -{ - return m_bEnabled; -} - -#endif // SAAENV_H_INCLUDED diff --git a/src/sound/saasound/SAAFreq.cpp b/src/sound/saasound/SAAFreq.cpp deleted file mode 100755 index 61a04f6ad..000000000 --- a/src/sound/saasound/SAAFreq.cpp +++ /dev/null @@ -1,287 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAFreq.cpp: implementation of the CSAAFreq class. -// only 7-bit fractional accuracy on oscillator periods. I may consider fixing that. -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" -#include "types.h" -#include "SAANoise.h" -#include "SAAEnv.h" -#include "SAAFreq.h" -#include "defns.h" - -#ifdef SAAFREQ_FIXED_CLOCKRATE -// 'load in' the data for the static frequency lookup table -// precomputed for a fixed clockrate -// See: tools/freqdat.py -const unsigned long CSAAFreq::m_FreqTable[2048] = { -#include "SAAFreq.dat" -}; -#else -unsigned long CSAAFreq::m_FreqTable[2048]; -unsigned long CSAAFreq::m_nClockRate = 0; -#endif // SAAFREQ_FIXED_CLOCKRATE - -const int INITIAL_LEVEL = 1; - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSAAFreq::CSAAFreq(CSAANoise * const NoiseGenerator, CSAAEnv * const EnvGenerator) -: -m_nCounter(0), -m_nAdd(0), -m_nCounter_low(0), -m_nOversample(0), -m_nCounterLimit_low(1), -m_nLevel(INITIAL_LEVEL), -m_nCurrentOffset(0), -m_nCurrentOctave(0), -m_nNextOffset(0), -m_nNextOctave(0), -m_bIgnoreOffsetData(false), -m_bNewData(false), -m_bSync(false), -m_nSampleRate(SAMPLE_RATE_HZ), -m_pcConnectedNoiseGenerator(NoiseGenerator), -m_pcConnectedEnvGenerator(EnvGenerator), -m_nConnectedMode((NoiseGenerator == NULL) ? ((EnvGenerator == NULL) ? 0 : 1) : 2) -{ - _SetClockRate(EXTERNAL_CLK_HZ); - SetAdd(); // current octave, current offset -} - -CSAAFreq::~CSAAFreq() -{ - // Nothing to do -} - -void CSAAFreq::SetFreqOffset(BYTE nOffset) -{ - // nOffset between 0 and 255 - - if (!m_bSync) - { - m_nNextOffset = nOffset; - m_bNewData=true; - if (m_nNextOctave==m_nCurrentOctave) - { - // According to Philips, if you send the SAA-1099 - // new Octave data and then new Offset data in that - // order, on the next half-cycle of the current frequency - // generator, ONLY the octave data is acted upon. - // The offset data will be acted upon next time. - - // ?? TEST CASE : if you set the octave and then the offset - // but the octave you set it to is the same one it already was. - // Will this ignore the offset data? - // Do you get the same behaviour if you set offset THEN octave - // even if you set octave to the same value it was before? - - m_bIgnoreOffsetData=true; - } - } - else - { - // updates straightaway if m_bSync - m_bNewData=false; - m_bIgnoreOffsetData = false; - m_nCurrentOffset = nOffset; - m_nNextOffset = nOffset; - m_nCurrentOctave = m_nNextOctave; - SetAdd(); - } - -} - -void CSAAFreq::SetFreqOctave(BYTE nOctave) -{ - // nOctave between 0 and 7 - - if (!m_bSync) - { - m_nNextOctave = nOctave; - m_bNewData=true; - m_bIgnoreOffsetData = false; - } - else - { - // updates straightaway if m_bSync - m_bNewData=false; - m_bIgnoreOffsetData = false; - m_nCurrentOctave = nOctave; - m_nNextOctave = nOctave; - m_nCurrentOffset = m_nNextOffset; - SetAdd(); - } -} - -void CSAAFreq::UpdateOctaveOffsetData(void) -{ - // loads the buffered new octave and new offset data into the current registers - // and sets up the new frequency for this frequency generator (i.e. sets up m_nAdd) - // - called during Sync, and called when waveform half-cycle completes - - // How the SAA-1099 really treats new data: - // if only new octave data is present, - // then set new period based on just the octave data - // Otherwise, if only new offset data is present, - // then set new period based on just the offset data - // Otherwise, if new octave data is present, and new offset data is present, - // and the offset data was set BEFORE the octave data, - // then set new period based on both the octave and offset data - // Else, if the offset data came AFTER the new octave data - // then set new period based on JUST THE OCTAVE DATA, and continue - // signalling the offset data as 'new', so it will be acted upon - // next half-cycle - // - // Weird, I know. But that's how it works. Philips even documented as much. - - if (!m_bNewData) - { - // optimise for the most common case! No new data! - return; - } - - m_nCurrentOctave=m_nNextOctave; - if (!m_bIgnoreOffsetData) - { - m_nCurrentOffset=m_nNextOffset; - m_bNewData=false; - } - m_bIgnoreOffsetData=false; - - SetAdd(); -} - -void CSAAFreq::_SetSampleRate(unsigned int nSampleRate) -{ - m_nSampleRate = nSampleRate; -} - -void CSAAFreq::_SetOversample(unsigned int oversample) -{ - // oversample is a power of 2 i.e. - // if oversample == 2 then 4x oversample - // if oversample == 6 then 64x oversample - if (oversample < m_nOversample) - { - m_nCounter_low <<= (m_nOversample - oversample); - } - else - { - m_nCounter_low >>= (oversample - m_nOversample); - } - - m_nCounterLimit_low = 1<= (m_nSampleRate<<12)) - { - m_nCounter -= (m_nSampleRate<<12); - m_nCounter_low++; - if (m_nCounter_low >= m_nCounterLimit_low) - { - // period elapsed for (at least) one half-cycle of - // current frequency - m_nCounter_low = 0; - // flip state - from 0 to 1 or vice versa - m_nLevel = 1 - m_nLevel; - - // trigger any connected devices - switch (m_nConnectedMode) - { - case 1: - // env trigger - m_pcConnectedEnvGenerator->InternalClock(); - break; - - case 2: - // noise trigger - m_pcConnectedNoiseGenerator->Trigger(); - break; - - default: - // do nothing - break; - } - - // get new frequency (set period length m_nAdd) if new data is waiting: - UpdateOctaveOffsetData(); - } - } - - return m_nLevel; -} - -void CSAAFreq::SetAdd(void) -{ - // nOctave between 0 and 7; nOffset between 0 and 255 - - // Used to be: - // m_nAdd = (15625 << nOctave) / (511 - nOffset); - // Now just table lookup: - m_nAdd = m_FreqTable[m_nCurrentOctave<<8 | m_nCurrentOffset]; -} - -void CSAAFreq::Sync(bool bSync) -{ - m_bSync = bSync; - - // update straightaway if m_bSync - if (m_bSync) - { - m_nCounter = 0; - m_nCounter_low = 0; - - // this seems to need to be required to make the Fred59 SPACE DEMO audio work correctly - m_nLevel = INITIAL_LEVEL; - - m_nCurrentOctave=m_nNextOctave; - m_nCurrentOffset=m_nNextOffset; - SetAdd(); - } -} diff --git a/src/sound/saasound/SAAFreq.dat b/src/sound/saasound/SAAFreq.dat deleted file mode 100755 index 04fb9081a..000000000 --- a/src/sound/saasound/SAAFreq.dat +++ /dev/null @@ -1,141 +0,0 @@ -/* -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// Precalculated oscillator frequency period steps -// Higher scaling for better accuracy. -// -// After construction, it's important to SetSampleRate before -// trying to use the generator. -// (Just because the CSAANoise object has a default samplerate -// doesn't mean you should rely on it) -// -////////////////////////////////////////////////////////////////////// -*/ - 250489 , 250980 , 251473 , 251969 , 252465 , 252964 , 253465 , 253968 , 254473 , 254980 , 255489 , 256000 , 256513 , 257028 , 257545 , 258065 , - 258586 , 259109 , 259635 , 260163 , 260692 , 261224 , 261759 , 262295 , 262834 , 263374 , 263918 , 264463 , 265010 , 265560 , 266112 , 266667 , - 267223 , 267782 , 268344 , 268908 , 269474 , 270042 , 270613 , 271186 , 271762 , 272340 , 272921 , 273504 , 274090 , 274678 , 275269 , 275862 , - 276458 , 277056 , 277657 , 278261 , 278867 , 279476 , 280088 , 280702 , 281319 , 281938 , 282561 , 283186 , 283814 , 284444 , 285078 , 285714 , - 286353 , 286996 , 287640 , 288288 , 288939 , 289593 , 290249 , 290909 , 291572 , 292237 , 292906 , 293578 , 294253 , 294931 , 295612 , 296296 , - 296984 , 297674 , 298368 , 299065 , 299766 , 300469 , 301176 , 301887 , 302600 , 303318 , 304038 , 304762 , 305489 , 306220 , 306954 , 307692 , - 308434 , 309179 , 309927 , 310680 , 311436 , 312195 , 312958 , 313725 , 314496 , 315271 , 316049 , 316832 , 317618 , 318408 , 319202 , 320000 , - 320802 , 321608 , 322418 , 323232 , 324051 , 324873 , 325700 , 326531 , 327366 , 328205 , 329049 , 329897 , 330749 , 331606 , 332468 , 333333 , - 334204 , 335079 , 335958 , 336842 , 337731 , 338624 , 339523 , 340426 , 341333 , 342246 , 343164 , 344086 , 345013 , 345946 , 346883 , 347826 , - 348774 , 349727 , 350685 , 351648 , 352617 , 353591 , 354571 , 355556 , 356546 , 357542 , 358543 , 359551 , 360563 , 361582 , 362606 , 363636 , - 364672 , 365714 , 366762 , 367816 , 368876 , 369942 , 371014 , 372093 , 373178 , 374269 , 375367 , 376471 , 377581 , 378698 , 379822 , 380952 , - 382090 , 383234 , 384384 , 385542 , 386707 , 387879 , 389058 , 390244 , 391437 , 392638 , 393846 , 395062 , 396285 , 397516 , 398754 , 400000 , - 401254 , 402516 , 403785 , 405063 , 406349 , 407643 , 408946 , 410256 , 411576 , 412903 , 414239 , 415584 , 416938 , 418301 , 419672 , 421053 , - 422442 , 423841 , 425249 , 426667 , 428094 , 429530 , 430976 , 432432 , 433898 , 435374 , 436860 , 438356 , 439863 , 441379 , 442907 , 444444 , - 445993 , 447552 , 449123 , 450704 , 452297 , 453901 , 455516 , 457143 , 458781 , 460432 , 462094 , 463768 , 465455 , 467153 , 468864 , 470588 , - 472325 , 474074 , 475836 , 477612 , 479401 , 481203 , 483019 , 484848 , 486692 , 488550 , 490421 , 492308 , 494208 , 496124 , 498054 , 500000 , - 500978 , 501961 , 502947 , 503937 , 504931 , 505929 , 506931 , 507937 , 508946 , 509960 , 510978 , 512000 , 513026 , 514056 , 515091 , 516129 , - 517172 , 518219 , 519270 , 520325 , 521385 , 522449 , 523517 , 524590 , 525667 , 526749 , 527835 , 528926 , 530021 , 531120 , 532225 , 533333 , - 534447 , 535565 , 536688 , 537815 , 538947 , 540084 , 541226 , 542373 , 543524 , 544681 , 545842 , 547009 , 548180 , 549356 , 550538 , 551724 , - 552916 , 554113 , 555315 , 556522 , 557734 , 558952 , 560175 , 561404 , 562637 , 563877 , 565121 , 566372 , 567627 , 568889 , 570156 , 571429 , - 572707 , 573991 , 575281 , 576577 , 577878 , 579186 , 580499 , 581818 , 583144 , 584475 , 585812 , 587156 , 588506 , 589862 , 591224 , 592593 , - 593968 , 595349 , 596737 , 598131 , 599532 , 600939 , 602353 , 603774 , 605201 , 606635 , 608076 , 609524 , 610979 , 612440 , 613909 , 615385 , - 616867 , 618357 , 619855 , 621359 , 622871 , 624390 , 625917 , 627451 , 628993 , 630542 , 632099 , 633663 , 635236 , 636816 , 638404 , 640000 , - 641604 , 643216 , 644836 , 646465 , 648101 , 649746 , 651399 , 653061 , 654731 , 656410 , 658098 , 659794 , 661499 , 663212 , 664935 , 666667 , - 668407 , 670157 , 671916 , 673684 , 675462 , 677249 , 679045 , 680851 , 682667 , 684492 , 686327 , 688172 , 690027 , 691892 , 693767 , 695652 , - 697548 , 699454 , 701370 , 703297 , 705234 , 707182 , 709141 , 711111 , 713092 , 715084 , 717087 , 719101 , 721127 , 723164 , 725212 , 727273 , - 729345 , 731429 , 733524 , 735632 , 737752 , 739884 , 742029 , 744186 , 746356 , 748538 , 750733 , 752941 , 755162 , 757396 , 759644 , 761905 , - 764179 , 766467 , 768769 , 771084 , 773414 , 775758 , 778116 , 780488 , 782875 , 785276 , 787692 , 790123 , 792570 , 795031 , 797508 , 800000 , - 802508 , 805031 , 807571 , 810127 , 812698 , 815287 , 817891 , 820513 , 823151 , 825806 , 828479 , 831169 , 833876 , 836601 , 839344 , 842105 , - 844884 , 847682 , 850498 , 853333 , 856187 , 859060 , 861953 , 864865 , 867797 , 870748 , 873720 , 876712 , 879725 , 882759 , 885813 , 888889 , - 891986 , 895105 , 898246 , 901408 , 904594 , 907801 , 911032 , 914286 , 917563 , 920863 , 924188 , 927536 , 930909 , 934307 , 937729 , 941176 , - 944649 , 948148 , 951673 , 955224 , 958801 , 962406 , 966038 , 969697 , 973384 , 977099 , 980843 , 984615 , 988417 , 992248 , 996109 , 1000000 , - 1001957 , 1003922 , 1005894 , 1007874 , 1009862 , 1011858 , 1013861 , 1015873 , 1017893 , 1019920 , 1021956 , 1024000 , 1026052 , 1028112 , 1030181 , 1032258 , - 1034343 , 1036437 , 1038540 , 1040650 , 1042770 , 1044898 , 1047035 , 1049180 , 1051335 , 1053498 , 1055670 , 1057851 , 1060041 , 1062241 , 1064449 , 1066667 , - 1068894 , 1071130 , 1073375 , 1075630 , 1077895 , 1080169 , 1082452 , 1084746 , 1087049 , 1089362 , 1091684 , 1094017 , 1096360 , 1098712 , 1101075 , 1103448 , - 1105832 , 1108225 , 1110629 , 1113043 , 1115468 , 1117904 , 1120350 , 1122807 , 1125275 , 1127753 , 1130243 , 1132743 , 1135255 , 1137778 , 1140312 , 1142857 , - 1145414 , 1147982 , 1150562 , 1153153 , 1155756 , 1158371 , 1160998 , 1163636 , 1166287 , 1168950 , 1171625 , 1174312 , 1177011 , 1179724 , 1182448 , 1185185 , - 1187935 , 1190698 , 1193473 , 1196262 , 1199063 , 1201878 , 1204706 , 1207547 , 1210402 , 1213270 , 1216152 , 1219048 , 1221957 , 1224880 , 1227818 , 1230769 , - 1233735 , 1236715 , 1239709 , 1242718 , 1245742 , 1248780 , 1251834 , 1254902 , 1257985 , 1261084 , 1264198 , 1267327 , 1270471 , 1273632 , 1276808 , 1280000 , - 1283208 , 1286432 , 1289673 , 1292929 , 1296203 , 1299492 , 1302799 , 1306122 , 1309463 , 1312821 , 1316195 , 1319588 , 1322997 , 1326425 , 1329870 , 1333333 , - 1336815 , 1340314 , 1343832 , 1347368 , 1350923 , 1354497 , 1358090 , 1361702 , 1365333 , 1368984 , 1372654 , 1376344 , 1380054 , 1383784 , 1387534 , 1391304 , - 1395095 , 1398907 , 1402740 , 1406593 , 1410468 , 1414365 , 1418283 , 1422222 , 1426184 , 1430168 , 1434174 , 1438202 , 1442254 , 1446328 , 1450425 , 1454545 , - 1458689 , 1462857 , 1467049 , 1471264 , 1475504 , 1479769 , 1484058 , 1488372 , 1492711 , 1497076 , 1501466 , 1505882 , 1510324 , 1514793 , 1519288 , 1523810 , - 1528358 , 1532934 , 1537538 , 1542169 , 1546828 , 1551515 , 1556231 , 1560976 , 1565749 , 1570552 , 1575385 , 1580247 , 1585139 , 1590062 , 1595016 , 1600000 , - 1605016 , 1610063 , 1615142 , 1620253 , 1625397 , 1630573 , 1635783 , 1641026 , 1646302 , 1651613 , 1656958 , 1662338 , 1667752 , 1673203 , 1678689 , 1684211 , - 1689769 , 1695364 , 1700997 , 1706667 , 1712375 , 1718121 , 1723906 , 1729730 , 1735593 , 1741497 , 1747440 , 1753425 , 1759450 , 1765517 , 1771626 , 1777778 , - 1783972 , 1790210 , 1796491 , 1802817 , 1809187 , 1815603 , 1822064 , 1828571 , 1835125 , 1841727 , 1848375 , 1855072 , 1861818 , 1868613 , 1875458 , 1882353 , - 1889299 , 1896296 , 1903346 , 1910448 , 1917603 , 1924812 , 1932075 , 1939394 , 1946768 , 1954198 , 1961686 , 1969231 , 1976834 , 1984496 , 1992218 , 2000000 , - 2003914 , 2007843 , 2011788 , 2015748 , 2019724 , 2023715 , 2027723 , 2031746 , 2035785 , 2039841 , 2043912 , 2048000 , 2052104 , 2056225 , 2060362 , 2064516 , - 2068687 , 2072874 , 2077079 , 2081301 , 2085540 , 2089796 , 2094070 , 2098361 , 2102669 , 2106996 , 2111340 , 2115702 , 2120083 , 2124481 , 2128898 , 2133333 , - 2137787 , 2142259 , 2146751 , 2151261 , 2155789 , 2160338 , 2164905 , 2169492 , 2174098 , 2178723 , 2183369 , 2188034 , 2192719 , 2197425 , 2202151 , 2206897 , - 2211663 , 2216450 , 2221258 , 2226087 , 2230937 , 2235808 , 2240700 , 2245614 , 2250549 , 2255507 , 2260486 , 2265487 , 2270510 , 2275556 , 2280624 , 2285714 , - 2290828 , 2295964 , 2301124 , 2306306 , 2311512 , 2316742 , 2321995 , 2327273 , 2332574 , 2337900 , 2343249 , 2348624 , 2354023 , 2359447 , 2364896 , 2370370 , - 2375870 , 2381395 , 2386946 , 2392523 , 2398126 , 2403756 , 2409412 , 2415094 , 2420804 , 2426540 , 2432304 , 2438095 , 2443914 , 2449761 , 2455635 , 2461538 , - 2467470 , 2473430 , 2479419 , 2485437 , 2491484 , 2497561 , 2503667 , 2509804 , 2515971 , 2522167 , 2528395 , 2534653 , 2540943 , 2547264 , 2553616 , 2560000 , - 2566416 , 2572864 , 2579345 , 2585859 , 2592405 , 2598985 , 2605598 , 2612245 , 2618926 , 2625641 , 2632391 , 2639175 , 2645995 , 2652850 , 2659740 , 2666667 , - 2673629 , 2680628 , 2687664 , 2694737 , 2701847 , 2708995 , 2716180 , 2723404 , 2730667 , 2737968 , 2745308 , 2752688 , 2760108 , 2767568 , 2775068 , 2782609 , - 2790191 , 2797814 , 2805479 , 2813187 , 2820937 , 2828729 , 2836565 , 2844444 , 2852368 , 2860335 , 2868347 , 2876404 , 2884507 , 2892655 , 2900850 , 2909091 , - 2917379 , 2925714 , 2934097 , 2942529 , 2951009 , 2959538 , 2968116 , 2976744 , 2985423 , 2994152 , 3002933 , 3011765 , 3020649 , 3029586 , 3038576 , 3047619 , - 3056716 , 3065868 , 3075075 , 3084337 , 3093656 , 3103030 , 3112462 , 3121951 , 3131498 , 3141104 , 3150769 , 3160494 , 3170279 , 3180124 , 3190031 , 3200000 , - 3210031 , 3220126 , 3230284 , 3240506 , 3250794 , 3261146 , 3271565 , 3282051 , 3292605 , 3303226 , 3313916 , 3324675 , 3335505 , 3346405 , 3357377 , 3368421 , - 3379538 , 3390728 , 3401993 , 3413333 , 3424749 , 3436242 , 3447811 , 3459459 , 3471186 , 3482993 , 3494881 , 3506849 , 3518900 , 3531034 , 3543253 , 3555556 , - 3567944 , 3580420 , 3592982 , 3605634 , 3618375 , 3631206 , 3644128 , 3657143 , 3670251 , 3683453 , 3696751 , 3710145 , 3723636 , 3737226 , 3750916 , 3764706 , - 3778598 , 3792593 , 3806691 , 3820896 , 3835206 , 3849624 , 3864151 , 3878788 , 3893536 , 3908397 , 3923372 , 3938462 , 3953668 , 3968992 , 3984436 , 4000000 , - 4007828 , 4015686 , 4023576 , 4031496 , 4039448 , 4047431 , 4055446 , 4063492 , 4071571 , 4079681 , 4087824 , 4096000 , 4104208 , 4112450 , 4120724 , 4129032 , - 4137374 , 4145749 , 4154158 , 4162602 , 4171079 , 4179592 , 4188139 , 4196721 , 4205339 , 4213992 , 4222680 , 4231405 , 4240166 , 4248963 , 4257796 , 4266667 , - 4275574 , 4284519 , 4293501 , 4302521 , 4311579 , 4320675 , 4329810 , 4338983 , 4348195 , 4357447 , 4366738 , 4376068 , 4385439 , 4394850 , 4404301 , 4413793 , - 4423326 , 4432900 , 4442516 , 4452174 , 4461874 , 4471616 , 4481400 , 4491228 , 4501099 , 4511013 , 4520971 , 4530973 , 4541020 , 4551111 , 4561247 , 4571429 , - 4581655 , 4591928 , 4602247 , 4612613 , 4623025 , 4633484 , 4643991 , 4654545 , 4665148 , 4675799 , 4686499 , 4697248 , 4708046 , 4718894 , 4729792 , 4740741 , - 4751740 , 4762791 , 4773893 , 4785047 , 4796253 , 4807512 , 4818824 , 4830189 , 4841608 , 4853081 , 4864608 , 4876190 , 4887828 , 4899522 , 4911271 , 4923077 , - 4934940 , 4946860 , 4958838 , 4970874 , 4982968 , 4995122 , 5007335 , 5019608 , 5031941 , 5044335 , 5056790 , 5069307 , 5081886 , 5094527 , 5107232 , 5120000 , - 5132832 , 5145729 , 5158690 , 5171717 , 5184810 , 5197970 , 5211196 , 5224490 , 5237852 , 5251282 , 5264781 , 5278351 , 5291990 , 5305699 , 5319481 , 5333333 , - 5347258 , 5361257 , 5375328 , 5389474 , 5403694 , 5417989 , 5432361 , 5446809 , 5461333 , 5475936 , 5490617 , 5505376 , 5520216 , 5535135 , 5550136 , 5565217 , - 5580381 , 5595628 , 5610959 , 5626374 , 5641873 , 5657459 , 5673130 , 5688889 , 5704735 , 5720670 , 5736695 , 5752809 , 5769014 , 5785311 , 5801700 , 5818182 , - 5834758 , 5851429 , 5868195 , 5885057 , 5902017 , 5919075 , 5936232 , 5953488 , 5970845 , 5988304 , 6005865 , 6023529 , 6041298 , 6059172 , 6077151 , 6095238 , - 6113433 , 6131737 , 6150150 , 6168675 , 6187311 , 6206061 , 6224924 , 6243902 , 6262997 , 6282209 , 6301538 , 6320988 , 6340557 , 6360248 , 6380062 , 6400000 , - 6420063 , 6440252 , 6460568 , 6481013 , 6501587 , 6522293 , 6543131 , 6564103 , 6585209 , 6606452 , 6627832 , 6649351 , 6671010 , 6692810 , 6714754 , 6736842 , - 6759076 , 6781457 , 6803987 , 6826667 , 6849498 , 6872483 , 6895623 , 6918919 , 6942373 , 6965986 , 6989761 , 7013699 , 7037801 , 7062069 , 7086505 , 7111111 , - 7135889 , 7160839 , 7185965 , 7211268 , 7236749 , 7262411 , 7288256 , 7314286 , 7340502 , 7366906 , 7393502 , 7420290 , 7447273 , 7474453 , 7501832 , 7529412 , - 7557196 , 7585185 , 7613383 , 7641791 , 7670412 , 7699248 , 7728302 , 7757576 , 7787072 , 7816794 , 7846743 , 7876923 , 7907336 , 7937984 , 7968872 , 8000000 , - 8015656 , 8031373 , 8047151 , 8062992 , 8078895 , 8094862 , 8110891 , 8126984 , 8143141 , 8159363 , 8175649 , 8192000 , 8208417 , 8224900 , 8241449 , 8258065 , - 8274747 , 8291498 , 8308316 , 8325203 , 8342159 , 8359184 , 8376278 , 8393443 , 8410678 , 8427984 , 8445361 , 8462810 , 8480331 , 8497925 , 8515593 , 8533333 , - 8551148 , 8569038 , 8587002 , 8605042 , 8623158 , 8641350 , 8659619 , 8677966 , 8696391 , 8714894 , 8733475 , 8752137 , 8770878 , 8789700 , 8808602 , 8827586 , - 8846652 , 8865801 , 8885033 , 8904348 , 8923747 , 8943231 , 8962801 , 8982456 , 9002198 , 9022026 , 9041943 , 9061947 , 9082040 , 9102222 , 9122494 , 9142857 , - 9163311 , 9183857 , 9204494 , 9225225 , 9246050 , 9266968 , 9287982 , 9309091 , 9330296 , 9351598 , 9372998 , 9394495 , 9416092 , 9437788 , 9459584 , 9481481 , - 9503480 , 9525581 , 9547786 , 9570093 , 9592506 , 9615023 , 9637647 , 9660377 , 9683215 , 9706161 , 9729216 , 9752381 , 9775656 , 9799043 , 9822542 , 9846154 , - 9869880 , 9893720 , 9917676 , 9941748 , 9965937 , 9990244 , 10014670 , 10039216 , 10063882 , 10088670 , 10113580 , 10138614 , 10163772 , 10189055 , 10214464 , 10240000 , - 10265664 , 10291457 , 10317380 , 10343434 , 10369620 , 10395939 , 10422392 , 10448980 , 10475703 , 10502564 , 10529563 , 10556701 , 10583979 , 10611399 , 10638961 , 10666667 , - 10694517 , 10722513 , 10750656 , 10778947 , 10807388 , 10835979 , 10864721 , 10893617 , 10922667 , 10951872 , 10981233 , 11010753 , 11040431 , 11070270 , 11100271 , 11130435 , - 11160763 , 11191257 , 11221918 , 11252747 , 11283747 , 11314917 , 11346260 , 11377778 , 11409471 , 11441341 , 11473389 , 11505618 , 11538028 , 11570621 , 11603399 , 11636364 , - 11669516 , 11702857 , 11736390 , 11770115 , 11804035 , 11838150 , 11872464 , 11906977 , 11941691 , 11976608 , 12011730 , 12047059 , 12082596 , 12118343 , 12154303 , 12190476 , - 12226866 , 12263473 , 12300300 , 12337349 , 12374622 , 12412121 , 12449848 , 12487805 , 12525994 , 12564417 , 12603077 , 12641975 , 12681115 , 12720497 , 12760125 , 12800000 , - 12840125 , 12880503 , 12921136 , 12962025 , 13003175 , 13044586 , 13086262 , 13128205 , 13170418 , 13212903 , 13255663 , 13298701 , 13342020 , 13385621 , 13429508 , 13473684 , - 13518152 , 13562914 , 13607973 , 13653333 , 13698997 , 13744966 , 13791246 , 13837838 , 13884746 , 13931973 , 13979522 , 14027397 , 14075601 , 14124138 , 14173010 , 14222222 , - 14271777 , 14321678 , 14371930 , 14422535 , 14473498 , 14524823 , 14576512 , 14628571 , 14681004 , 14733813 , 14787004 , 14840580 , 14894545 , 14948905 , 15003663 , 15058824 , - 15114391 , 15170370 , 15226766 , 15283582 , 15340824 , 15398496 , 15456604 , 15515152 , 15574144 , 15633588 , 15693487 , 15753846 , 15814672 , 15875969 , 15937743 , 16000000 , - 16031311 , 16062745 , 16094303 , 16125984 , 16157791 , 16189723 , 16221782 , 16253968 , 16286282 , 16318725 , 16351297 , 16384000 , 16416834 , 16449799 , 16482897 , 16516129 , - 16549495 , 16582996 , 16616633 , 16650407 , 16684318 , 16718367 , 16752556 , 16786885 , 16821355 , 16855967 , 16890722 , 16925620 , 16960663 , 16995851 , 17031185 , 17066667 , - 17102296 , 17138075 , 17174004 , 17210084 , 17246316 , 17282700 , 17319239 , 17355932 , 17392781 , 17429787 , 17466951 , 17504274 , 17541756 , 17579399 , 17617204 , 17655172 , - 17693305 , 17731602 , 17770065 , 17808696 , 17847495 , 17886463 , 17925602 , 17964912 , 18004396 , 18044053 , 18083885 , 18123894 , 18164080 , 18204444 , 18244989 , 18285714 , - 18326622 , 18367713 , 18408989 , 18450450 , 18492099 , 18533937 , 18575964 , 18618182 , 18660592 , 18703196 , 18745995 , 18788991 , 18832184 , 18875576 , 18919169 , 18962963 , - 19006961 , 19051163 , 19095571 , 19140187 , 19185012 , 19230047 , 19275294 , 19320755 , 19366430 , 19412322 , 19458432 , 19504762 , 19551313 , 19598086 , 19645084 , 19692308 , - 19739759 , 19787440 , 19835351 , 19883495 , 19931873 , 19980488 , 20029340 , 20078431 , 20127764 , 20177340 , 20227160 , 20277228 , 20327543 , 20378109 , 20428928 , 20480000 , - 20531328 , 20582915 , 20634761 , 20686869 , 20739241 , 20791878 , 20844784 , 20897959 , 20951407 , 21005128 , 21059126 , 21113402 , 21167959 , 21222798 , 21277922 , 21333333 , - 21389034 , 21445026 , 21501312 , 21557895 , 21614776 , 21671958 , 21729443 , 21787234 , 21845333 , 21903743 , 21962466 , 22021505 , 22080863 , 22140541 , 22200542 , 22260870 , - 22321526 , 22382514 , 22443836 , 22505495 , 22567493 , 22629834 , 22692521 , 22755556 , 22818942 , 22882682 , 22946779 , 23011236 , 23076056 , 23141243 , 23206799 , 23272727 , - 23339031 , 23405714 , 23472779 , 23540230 , 23608069 , 23676301 , 23744928 , 23813953 , 23883382 , 23953216 , 24023460 , 24094118 , 24165192 , 24236686 , 24308605 , 24380952 , - 24453731 , 24526946 , 24600601 , 24674699 , 24749245 , 24824242 , 24899696 , 24975610 , 25051988 , 25128834 , 25206154 , 25283951 , 25362229 , 25440994 , 25520249 , 25600000 , - 25680251 , 25761006 , 25842271 , 25924051 , 26006349 , 26089172 , 26172524 , 26256410 , 26340836 , 26425806 , 26511327 , 26597403 , 26684039 , 26771242 , 26859016 , 26947368 , - 27036304 , 27125828 , 27215947 , 27306667 , 27397993 , 27489933 , 27582492 , 27675676 , 27769492 , 27863946 , 27959044 , 28054795 , 28151203 , 28248276 , 28346021 , 28444444 , - 28543554 , 28643357 , 28743860 , 28845070 , 28946996 , 29049645 , 29153025 , 29257143 , 29362007 , 29467626 , 29574007 , 29681159 , 29789091 , 29897810 , 30007326 , 30117647 , - 30228782 , 30340741 , 30453532 , 30567164 , 30681648 , 30796992 , 30913208 , 31030303 , 31148289 , 31267176 , 31386973 , 31507692 , 31629344 , 31751938 , 31875486 , 32000000 , - 32062622 , 32125490 , 32188605 , 32251969 , 32315582 , 32379447 , 32443564 , 32507937 , 32572565 , 32637450 , 32702595 , 32768000 , 32833667 , 32899598 , 32965795 , 33032258 , - 33098990 , 33165992 , 33233266 , 33300813 , 33368635 , 33436735 , 33505112 , 33573770 , 33642710 , 33711934 , 33781443 , 33851240 , 33921325 , 33991701 , 34062370 , 34133333 , - 34204593 , 34276151 , 34348008 , 34420168 , 34492632 , 34565401 , 34638478 , 34711864 , 34785563 , 34859574 , 34933902 , 35008547 , 35083512 , 35158798 , 35234409 , 35310345 , - 35386609 , 35463203 , 35540130 , 35617391 , 35694989 , 35772926 , 35851204 , 35929825 , 36008791 , 36088106 , 36167770 , 36247788 , 36328160 , 36408889 , 36489978 , 36571429 , - 36653244 , 36735426 , 36817978 , 36900901 , 36984199 , 37067873 , 37151927 , 37236364 , 37321185 , 37406393 , 37491991 , 37577982 , 37664368 , 37751152 , 37838337 , 37925926 , - 38013921 , 38102326 , 38191142 , 38280374 , 38370023 , 38460094 , 38550588 , 38641509 , 38732861 , 38824645 , 38916865 , 39009524 , 39102625 , 39196172 , 39290168 , 39384615 , - 39479518 , 39574879 , 39670702 , 39766990 , 39863747 , 39960976 , 40058680 , 40156863 , 40255528 , 40354680 , 40454321 , 40554455 , 40655087 , 40756219 , 40857855 , 40960000 , - 41062657 , 41165829 , 41269521 , 41373737 , 41478481 , 41583756 , 41689567 , 41795918 , 41902813 , 42010256 , 42118252 , 42226804 , 42335917 , 42445596 , 42555844 , 42666667 , - 42778068 , 42890052 , 43002625 , 43115789 , 43229551 , 43343915 , 43458886 , 43574468 , 43690667 , 43807487 , 43924933 , 44043011 , 44161725 , 44281081 , 44401084 , 44521739 , - 44643052 , 44765027 , 44887671 , 45010989 , 45134986 , 45259669 , 45385042 , 45511111 , 45637883 , 45765363 , 45893557 , 46022472 , 46152113 , 46282486 , 46413598 , 46545455 , - 46678063 , 46811429 , 46945559 , 47080460 , 47216138 , 47352601 , 47489855 , 47627907 , 47766764 , 47906433 , 48046921 , 48188235 , 48330383 , 48473373 , 48617211 , 48761905 , - 48907463 , 49053892 , 49201201 , 49349398 , 49498489 , 49648485 , 49799392 , 49951220 , 50103976 , 50257669 , 50412308 , 50567901 , 50724458 , 50881988 , 51040498 , 51200000 , - 51360502 , 51522013 , 51684543 , 51848101 , 52012698 , 52178344 , 52345048 , 52512821 , 52681672 , 52851613 , 53022654 , 53194805 , 53368078 , 53542484 , 53718033 , 53894737 , - 54072607 , 54251656 , 54431894 , 54613333 , 54795987 , 54979866 , 55164983 , 55351351 , 55538983 , 55727891 , 55918089 , 56109589 , 56302405 , 56496552 , 56692042 , 56888889 , - 57087108 , 57286713 , 57487719 , 57690141 , 57893993 , 58099291 , 58306050 , 58514286 , 58724014 , 58935252 , 59148014 , 59362319 , 59578182 , 59795620 , 60014652 , 60235294 , - 60457565 , 60681481 , 60907063 , 61134328 , 61363296 , 61593985 , 61826415 , 62060606 , 62296578 , 62534351 , 62773946 , 63015385 , 63258687 , 63503876 , 63750973 , 64000000 diff --git a/src/sound/saasound/SAAFreq.h b/src/sound/saasound/SAAFreq.h deleted file mode 100755 index 478754621..000000000 --- a/src/sound/saasound/SAAFreq.h +++ /dev/null @@ -1,72 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAFreq.h: interface for the CSAAFreq class. -// Note about Samplerates: 0=44100, 1=22050; 2=11025 -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAAFREQ_H_INCLUDE -#define SAAFREQ_H_INCLUDE - -#include "defns.h" - -class CSAAFreq -{ -private: -#ifdef SAAFREQ_FIXED_CLOCKRATE - // 'load in' the data for the static frequency lookup table - // precomputed for a fixed clockrate - // See: tools/freqdat.py - const static unsigned long m_FreqTable[2048]; -#else - // we'll calculate the frequency lookup table at runtime. - static unsigned long m_FreqTable[2048]; - static unsigned long m_nClockRate; -#endif - - unsigned long m_nCounter; - unsigned long m_nAdd; - unsigned long m_nCounter_low; - unsigned int m_nOversample; - unsigned long m_nCounterLimit_low; - int m_nLevel; - - int m_nCurrentOffset; - int m_nCurrentOctave; - int m_nNextOffset; - int m_nNextOctave; - bool m_bIgnoreOffsetData; - bool m_bNewData; - bool m_bSync; - - unsigned long m_nSampleRate; - CSAANoise * const m_pcConnectedNoiseGenerator; - CSAAEnv * const m_pcConnectedEnvGenerator; - const int m_nConnectedMode; // 0 = nothing; 1 = envgenerator; 2 = noisegenerator - - void UpdateOctaveOffsetData(void); - void SetAdd(void); - -public: - CSAAFreq(CSAANoise * const pcNoiseGenerator, CSAAEnv * const pcEnvGenerator); - ~CSAAFreq(); - void SetFreqOffset(BYTE nOffset); - void SetFreqOctave(BYTE nOctave); - void _SetSampleRate(unsigned int nSampleRate); - void _SetOversample(unsigned int oversample); - void _SetClockRate(int nClockRate); - void Sync(bool bSync); - int Tick(void); - int Level(void) const; - -}; - -inline int CSAAFreq::Level(void) const -{ - if (m_bSync) - return 1; - - return m_nLevel; -} - -#endif // SAAFREQ_H_INCLUDE diff --git a/src/sound/saasound/SAAImpl.cpp b/src/sound/saasound/SAAImpl.cpp deleted file mode 100644 index f136eefc6..000000000 --- a/src/sound/saasound/SAAImpl.cpp +++ /dev/null @@ -1,489 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAAImpl.cpp: implementation of the CSAASound class. -// the bones of the 'virtual SAA-1099' emulation -// -// the actual sound generation is carried out in the other classes; -// this class provides the output stage and the external interface only -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" - -#include "types.h" -#include "SAAImpl.h" -#include "defns.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSAASoundInternal::CSAASoundInternal() - : -m_chip(), -m_uParam(0), -m_uParamRate(0), -m_nClockRate(EXTERNAL_CLK_HZ), -m_nSampleRate(SAMPLE_RATE_HZ), -m_nOversample(DEFAULT_OVERSAMPLE), -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) -m_bHighpass(false), -m_nDebugSample(0) -#else -m_bHighpass(false) -#endif -{ -#ifdef USE_CONFIG_FILE - m_Config.ReadConfig(); -#endif - -#if defined(DEBUGSAA) - m_dbgfile.open(_T(DEBUG_SAA_REGISTER_LOG), std::ios_base::out); - m_pcmfile.open(_T(DEBUG_SAA_PCM_LOG), std::ios_base::out | std::ios_base::binary); -#elif defined(USE_CONFIG_FILE) - if (m_Config.m_bGenerateRegisterLogs) - m_dbgfile.open(m_Config.m_strRegisterLogPath, std::ios_base::out); - if (m_Config.m_bGeneratePcmLogs) - m_pcmfile.open(m_Config.m_strPcmOutputPath, std::ios_base::out | std::ios_base::binary); - - if (m_Config.m_bGeneratePcmLogs && m_Config.m_bGeneratePcmSeparateChannels) - { - for (int i = 0; i < 6; i++) - { - m_channel_pcmfile[i].open(m_Config.getChannelPcmOutputPath(i), std::ios_base::out | std::ios_base::binary); - } - } - - -#endif - // set parameters - // TODO support defaults and overrides from config file - // m_chip.SetSoundParameters(SAAP_FILTER | SAAP_11025 | SAAP_8BIT | SAAP_MONO); - // reset the virtual SAA - // m_chip.Clear(); - - m_chip._SetClockRate(m_nClockRate); - m_chip._SetOversample(m_nOversample); -} - -CSAASoundInternal::~CSAASoundInternal() -{ - // -} - -////////////////////////////////////////////////////////////////////// -// CSAASound members -////////////////////////////////////////////////////////////////////// - -void CSAASoundInternal::SetClockRate(unsigned int nClockRate) -{ - m_nClockRate = nClockRate; - m_chip._SetClockRate(m_nClockRate); -} - -void CSAASoundInternal::Clear(void) -{ - // reinitialises virtual SAA: - // sets reg 28 to 0x02; - sync and disabled - // sets regs 00-31 (except 28) to 0x00; - // sets reg 28 to 0x00; - // sets current reg to 0 - WriteAddressData(28,2); - for (int i=31; i>=0; i--) - { - if (i!=28) WriteAddressData(i,0); - } - WriteAddressData(28,0); - WriteAddress(0); -} - -void CSAASoundInternal::WriteData(BYTE nData) -{ - // originated from an OUT 255,d call - m_chip._WriteData(nData); -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) -#ifdef USE_CONFIG_FILE - if (m_Config.m_bGenerateRegisterLogs) - { -#endif - m_dbgfile << m_nDebugSample << " " << (int)m_chip._ReadAddress() << ":" << (int)nData << std::endl; -#ifdef USE_CONFIG_FILE - } -#endif -#endif -} - -void CSAASoundInternal::WriteAddress(BYTE nReg) -{ - // originated from an OUT 511,r call - m_chip._WriteAddress(nReg); -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) -#ifdef USE_CONFIG_FILE - if (m_Config.m_bGenerateRegisterLogs) - { -#endif - m_dbgfile << m_nDebugSample << " " << (int)nReg << ":"; - if (nReg==24) - { - m_dbgfile << ""; - } - else if (nReg==25) - { - m_dbgfile << ""; - } - m_dbgfile << std::endl; -#ifdef USE_CONFIG_FILE - } -#endif -#endif -} - -void CSAASoundInternal::WriteAddressData(BYTE nReg, BYTE nData) -{ - // performs WriteAddress(nReg) followed by WriteData(nData) - m_chip._WriteAddress(nReg); - m_chip._WriteData(nData); -} - -#if 1 -BYTE CSAASoundInternal::ReadAddress(void) -{ - // Not a real hardware function of the SAA-1099, which is write-only - return(m_chip._ReadAddress()); -} -#else -BYTE CSAASoundInternal::ReadAddress(void) -{ - // Not a real hardware function of the SAA-1099, which is write-only - return(0); -} -#endif - -void CSAASoundInternal::SetSoundParameters(SAAPARAM uParam) -{ - // set samplerate properties from uParam (deprecated but still supported) - unsigned int nSampleRate = m_nSampleRate; - switch (uParam & SAAP_MASK_SAMPLERATE) - { - case SAAP_44100: - nSampleRate = 44100; - m_uParamRate = (m_uParamRate & ~SAAP_MASK_SAMPLERATE) | SAAP_44100; - break; - case SAAP_22050: - nSampleRate = 22050; - m_uParamRate = (m_uParamRate & ~SAAP_MASK_SAMPLERATE) | SAAP_22050; - break; - case SAAP_11025: - nSampleRate = 11025; - m_uParamRate = (m_uParamRate & ~SAAP_MASK_SAMPLERATE) | SAAP_11025; - break; - case 0:// change nothing! - default: - break; - } - - if (nSampleRate != m_nSampleRate) - { - m_nSampleRate = nSampleRate; - m_chip._SetSampleRate(m_nSampleRate); - } - - // set filter properties from uParam - m_uParam = (m_uParam & ~SAAP_MASK_FILTER) | (uParam & SAAP_MASK_FILTER); - - m_bHighpass=true; -} - -void CSAASoundInternal::SetSampleRate(unsigned int nSampleRate) -{ - if (nSampleRate != m_nSampleRate) - { - m_nSampleRate = nSampleRate; - m_chip._SetSampleRate(m_nSampleRate); - } -} - -void CSAASoundInternal::SetOversample(unsigned int nOversample) -{ - if (nOversample != m_nOversample) - { - m_nOversample = nOversample; - m_chip._SetOversample(m_nOversample); - } -} - -SAAPARAM CSAASoundInternal::GetCurrentSoundParameters(void) -{ - return m_uParam | m_uParamRate; -} - -unsigned short CSAASoundInternal::GetCurrentBytesPerSample(void) -{ - // 16 bit stereo => 4 bytes per sample - return 4; -} - -/*static*/ unsigned short CSAASound::GetBytesPerSample(SAAPARAM uParam) -{ - // 16 bit stereo => 4 bytes per sample - switch (uParam & (SAAP_MASK_CHANNELS | SAAP_MASK_BITDEPTH)) - { - case SAAP_STEREO | SAAP_16BIT: - return 4; - default: - return 0; - } -} - -unsigned long CSAASoundInternal::GetCurrentSampleRate(void) -{ - return CSAASound::GetSampleRate(m_uParamRate); -} - -/*static*/ unsigned long CSAASound::GetSampleRate(SAAPARAM uParam) // static member function -{ - switch (uParam & SAAP_MASK_SAMPLERATE) - { - case SAAP_11025: - return 11025; - case SAAP_22050: - return 22050; - case SAAP_44100: - return 44100; - default: - return 0; - } -} - -#if defined(USE_CONFIG_FILE) || (defined(DEFAULT_BOOST) && DEFAULT_BOOST>1) -#define DO_BOOST -#endif - -void scale_for_output(unsigned int left_input, unsigned int right_input, - double oversample_scalar, bool highpass, double boost, - double& filterout_z1_left, double& filterout_z1_right, - BYTE* &pBuffer) -{ - double float_left = (double)left_input; - double float_right = (double)right_input; - float_left /= oversample_scalar; - float_right /= oversample_scalar; - - // scale output into good range - float_left *= DEFAULT_UNBOOSTED_MULTIPLIER; - float_right *= DEFAULT_UNBOOSTED_MULTIPLIER; - - if (highpass) - { - /* cutoff = 5 Hz (say) - const double b1 = exp(-2.0 * M_PI * (Fc/Fs)) - const double a0 = 1.0 - b1; - */ - const double b1 = 0.99928787; - const double a0 = 1.0 - b1; - - filterout_z1_left = float_left * a0 + filterout_z1_left * b1; - filterout_z1_right = float_right * a0 + filterout_z1_right * b1; - float_left -= filterout_z1_left; - float_right -= filterout_z1_right; - } - - // multiply by boost, if defined -#if defined(DO_BOOST) - float_left *= boost; - float_right *= boost; -#endif - // convert to 16-bit signed range with hard clipping - signed short left_output = (signed short)(float_left > 32767 ? 32767 : float_left < -32768 ? -32768 : float_left); - signed short right_output = (signed short)(float_right > 32767 ? 32767 : float_right < -32768 ? -32768 : float_right); - - *pBuffer++ = left_output & 0x00ff; - *pBuffer++ = (left_output >> 8) & 0x00ff; - *pBuffer++ = right_output & 0x00ff; - *pBuffer++ = (right_output >> 8) & 0x00ff; -} - -void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples) -{ - unsigned int left_mixed, right_mixed; - static double filterout_z1_left_mixed = 0, filterout_z1_right_mixed = 0; - -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) - BYTE* pBufferStart = pBuffer; - unsigned long nTotalSamples = nSamples; -#endif - -#if defined(DO_BOOST) -#if defined(USE_CONFIG_FILE) - double nBoost = m_Config.m_nBoost; -#else - double nBoost = DEFAULT_BOOST; -#endif -#else - double nBoost = 1.0; -#endif - - double oversample = double(1 << m_nOversample); - -#if defined(USE_CONFIG_FILE) - static double filterout_z1_left_0 = 0, filterout_z1_right_0 = 0; - static double filterout_z1_left_1 = 0, filterout_z1_right_1 = 0; - static double filterout_z1_left_2 = 0, filterout_z1_right_2 = 0; - static double filterout_z1_left_3 = 0, filterout_z1_right_3 = 0; - static double filterout_z1_left_4 = 0, filterout_z1_right_4 = 0; - static double filterout_z1_left_5 = 0, filterout_z1_right_5 = 0; - - if (m_Config.m_bGeneratePcmLogs && m_Config.m_bGeneratePcmSeparateChannels) - { - unsigned int left0, right0, left1, right1, left2, right2, left3, right3, left4, right4, left5, right5; - BYTE* pChannelBufferPtr[6] = { m_pChannelBuffer[0], m_pChannelBuffer[1], m_pChannelBuffer[2], m_pChannelBuffer[3], m_pChannelBuffer[4], m_pChannelBuffer[5] }; - - while (nSamples--) - { - m_chip._TickAndOutputSeparate(left_mixed, right_mixed, - left0, right0, - left1, right1, - left2, right2, - left3, right3, - left4, right4, - left5, right5); - scale_for_output(left_mixed, right_mixed, oversample, m_bHighpass, nBoost, filterout_z1_left_mixed, filterout_z1_right_mixed, pBuffer); - - // and the separate channels - scale_for_output(left0, right0, oversample, m_bHighpass, nBoost, filterout_z1_left_0, filterout_z1_right_0, pChannelBufferPtr[0]); - scale_for_output(left1, right1, oversample, m_bHighpass, nBoost, filterout_z1_left_1, filterout_z1_right_1, pChannelBufferPtr[1]); - scale_for_output(left2, right2, oversample, m_bHighpass, nBoost, filterout_z1_left_2, filterout_z1_right_2, pChannelBufferPtr[2]); - scale_for_output(left3, right3, oversample, m_bHighpass, nBoost, filterout_z1_left_3, filterout_z1_right_3, pChannelBufferPtr[3]); - scale_for_output(left4, right4, oversample, m_bHighpass, nBoost, filterout_z1_left_4, filterout_z1_right_4, pChannelBufferPtr[4]); - scale_for_output(left5, right5, oversample, m_bHighpass, nBoost, filterout_z1_left_5, filterout_z1_right_5, pChannelBufferPtr[5]); - - // flush channel output PCM buffers when full - if (pChannelBufferPtr[0] >= m_pChannelBuffer[0] + CHANNEL_BUFFER_SIZE) - { - for (int i = 0; i < 6; i++) - { - m_channel_pcmfile[i].write((const char*)m_pChannelBuffer[i], CHANNEL_BUFFER_SIZE); - pChannelBufferPtr[i] = m_pChannelBuffer[i]; - } - } - } - // flush remaining channel PCM output data - if (pChannelBufferPtr[0] >= m_pChannelBuffer[0]) - { - for (int i = 0; i < 6; i++) - { - m_channel_pcmfile[i].write((const char*)m_pChannelBuffer[i], pChannelBufferPtr[i]-m_pChannelBuffer[i]); - } - } - } - else - { -#endif - while (nSamples--) - { - m_chip._TickAndOutputStereo(left_mixed, right_mixed); - scale_for_output(left_mixed, right_mixed, oversample, m_bHighpass, nBoost, filterout_z1_left_mixed, filterout_z1_right_mixed, pBuffer); - } - -#if defined(USE_CONFIG_FILE) - } -#endif - -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) -#ifdef USE_CONFIG_FILE - if (m_Config.m_bGeneratePcmLogs) - { -#endif - m_pcmfile.write((const char *)pBufferStart, nTotalSamples * (unsigned long)GetCurrentBytesPerSample()); - m_nDebugSample += nTotalSamples; -#ifdef USE_CONFIG_FILE - } -#endif - -#endif -} - -/////////////////////////////////////////////////////// - -LPCSAASOUND SAAAPI CreateCSAASound(void) -{ - return (new CSAASoundInternal); -} - -void SAAAPI DestroyCSAASound(LPCSAASOUND object) -{ - delete (object); -} - - -/* thoughts on lowpass filtering as part of oversampling. -I tried this and really it didn't seem to make a lot of (audible) difference. - -// lowpass oversample filter adds complexity and not particularly audibly better than simple averaging. -// use_lowpass_oversample_filter_average_output adds an additional averaging step to the output of the oversample -// filter. this seems critical, because without this, the raw output of the lowpass filter is full of aliases -// If use_lowpass_oversample_filter is False, then the _average_output flag is ignored. -// Default, use_lowpass_oversample_filter is False, it sounds just fine really. - -//#define USE_LOWPASS_OVERSAMPLE_FILTER -#undef USE_LOWPASS_OVERSAMPLE_FILTER -//#define USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT -#undef USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT - -#ifdef USE_LOWPASS_OVERSAMPLE_FILTER -static double oversample_lp_filterout_z1_left_stages[10] = { 0,0,0,0,0,0,0,0,0,0 }; -static double oversample_lp_filterout_z1_right_stages[10] = { 0,0,0,0,0,0,0,0,0,0 }; -double averaged_filterout_left = 0.0, averaged_filterout_right = 0.0; -const int nStages = 10; -for (int i = 0; i < 1 << m_nOversample; i++) -{ - Noise[0]->Tick(); - Noise[1]->Tick(); - f_left = f_right = 0; - for (int c = 0; c < 6; c++) - { - Amp[c]->TickAndOutputStereo(temp_left, temp_right); - f_left += (double)temp_left; - f_right += (double)temp_right; - } - // apply lowpass here. - // HACK: ASSUME m_nOversample is 64 (I was experimenting only using the 64x oversample anyway) - // therefore Fs = 44100*64 - // let's set Fc = 10kHz - // so Fc/Fs = 0.00354308390022675736961451247166 - // const double b1 = exp(-2.0 * M_PI * (Fc/Fs)) - // const double a0 = 1.0 - b1; - // const double b1 = 0.9779841137335348363722276130195; - const double b1 = 0.977; - const double a0 = 1.0 - b1; - - oversample_lp_filterout_z1_left_stages[0] = f_left * a0 + oversample_lp_filterout_z1_left_stages[0] * b1; - for (int stage = 1; stage < nStages; stage++) - oversample_lp_filterout_z1_left_stages[stage] = oversample_lp_filterout_z1_left_stages[stage - 1] * a0 + oversample_lp_filterout_z1_left_stages[stage] * b1; - oversample_lp_filterout_z1_right_stages[0] = f_right * a0 + oversample_lp_filterout_z1_right_stages[0] * b1; - for (int stage = 1; stage < nStages; stage++) - oversample_lp_filterout_z1_right_stages[stage] = oversample_lp_filterout_z1_right_stages[stage - 1] * a0 + oversample_lp_filterout_z1_right_stages[stage] * b1; - -#ifdef USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT - averaged_filterout_left += oversample_lp_filterout_4z1_left; - averaged_filterout_right += oversample_lp_filterout_4z1_right; -#endif -} - -// by the end of this loop we will have computed the oversample lowpass filter m_nOversample times -// and yielded exactly ONE sample output. -#ifdef USE_LOWPASS_OVERSAMPLE_FILTER_AVERAGE_OUTPUT -f_left = averaged_filterout_left / (1 << m_nOversample); -f_right = averaged_filterout_right / (1 << m_nOversample); -#else -f_left = oversample_lp_filterout_z1_left_stages[nStages - 1]; -f_right = oversample_lp_filterout_z1_right_stages[nStages - 1]; -#endif - -#else - // do the simple 1/N averaging which is easier and sounds good enough - -#endif - -*/ - diff --git a/src/sound/saasound/SAAImpl.h b/src/sound/saasound/SAAImpl.h deleted file mode 100755 index 61fa79c58..000000000 --- a/src/sound/saasound/SAAImpl.h +++ /dev/null @@ -1,75 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// This is the internal implementation (header file) of the SAASound object. -// This is done so that the external interface to the object always stays the same -// (SAASound.h) even though the internal object can change -// .. Meaning future releases don't require relinking everyone elses code against -// the updated saasound stuff -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAAIMPL_H_INCLUDED -#define SAAIMPL_H_INCLUDED - -#include "SAASound.h" -#include "SAADevice.h" -#ifdef USE_CONFIG_FILE -#include "SAAConfig.h" -#endif - -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) -#include -#include -#include - -#if defined(USE_CONFIG_FILE) -const int CHANNEL_BUFFER_SIZE=1024; -#endif -#endif - -class CSAASoundInternal : public CSAASound -{ -private: - CSAADevice m_chip; - int m_uParam, m_uParamRate; - unsigned int m_nClockRate; - unsigned int m_nSampleRate; - unsigned int m_nOversample; - bool m_bHighpass; -#ifdef USE_CONFIG_FILE - SAAConfig m_Config; -#endif -#if defined(DEBUGSAA) || defined(USE_CONFIG_FILE) - unsigned long m_nDebugSample; - std::ofstream m_dbgfile, m_pcmfile; -#if defined(USE_CONFIG_FILE) - std::ofstream m_channel_pcmfile[6]; - BYTE m_pChannelBuffer[6][CHANNEL_BUFFER_SIZE]; -#endif -#endif - -public: - CSAASoundInternal(); - ~CSAASoundInternal(); - - void SetClockRate(unsigned int nClockRate); - void SetSampleRate(unsigned int nClockRate); - void SetOversample(unsigned int nOversample); - void SetSoundParameters(SAAPARAM uParam); - void WriteAddress(BYTE nReg); - void WriteData(BYTE nData); - void WriteAddressData(BYTE nReg, BYTE nData); - BYTE ReadAddress(void); - void Clear(void); - - SAAPARAM GetCurrentSoundParameters(void); - unsigned long GetCurrentSampleRate(void); - static unsigned long GetSampleRate(SAAPARAM uParam); - unsigned short GetCurrentBytesPerSample(void); - static unsigned short GetBytesPerSample(SAAPARAM uParam); - - void GenerateMany(BYTE * pBuffer, unsigned long nSamples); - -}; - -#endif // SAAIMPL_H_INCLUDED diff --git a/src/sound/saasound/SAANoise.cpp b/src/sound/saasound/SAANoise.cpp deleted file mode 100755 index 1cf3458dd..000000000 --- a/src/sound/saasound/SAANoise.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAANoise.cpp: implementation of the CSAANoise class. -// One noise generator -// -// After construction, it's important to SetSampleRate before -// trying to use the generator. -// (Just because the CSAANoise object has a default samplerate -// doesn't mean you should rely on it) -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" - -#include "types.h" -#include "SAANoise.h" -#include "defns.h" - - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSAANoise::CSAANoise() -: -m_nCounter(0), -m_nCounter_low(0), -m_nOversample(0), -m_nCounterLimit_low(1), -m_bSync(false), -m_nSampleRate(SAMPLE_RATE_HZ), -m_nSourceMode(0), -m_nRand(1) -{ - _SetClockRate(EXTERNAL_CLK_HZ); - m_nAdd = m_nAddBase; -} - -CSAANoise::CSAANoise(unsigned long seed) -: -m_nCounter(0), -m_nCounter_low(0), -m_nOversample(0), -m_nCounterLimit_low(1), -m_bSync(false), -m_nSampleRate(SAMPLE_RATE_HZ), -m_nSourceMode(0), -m_nRand(seed) -{ - _SetClockRate(EXTERNAL_CLK_HZ); - m_nAdd = m_nAddBase; -} - -CSAANoise::~CSAANoise() -{ - // Nothing to do -} - -void CSAANoise::_SetClockRate(int nClockRate) -{ - // at 8MHz the clock rate is 31.250kHZ - // This is simply the clock rate divided by 256 i.e. 2^8 - // We then shift this by 2^12 (like the Freq) for better - // period accuracy. So that's the same as shifting by (12-8) - m_nAddBase = nClockRate << (12 - 8); -} - -void CSAANoise::Seed(unsigned long seed) -{ - m_nRand = seed; -} - -void CSAANoise::SetSource(int nSource) -{ - m_nSourceMode = nSource; - m_nAdd = m_nAddBase >> m_nSourceMode; -} - -void CSAANoise::Trigger(void) -{ - // Trigger only does anything useful when we're - // clocking from the frequency generator - i.e - // if bUseFreqGen = true (i.e. SourceMode = 3) - - // So if we're clocking from the noise generator - // clock (ie, SourceMode = 0, 1 or 2) then do nothing - -// No point actually checking m_bSync here ... because if sync is true, -// then frequency generators won't actually be generating Trigger pulses -// so we wouldn't even get here! - // EXCEPT - cool edge case: if sync is set, then actually the Noise Generator - // is triggered on EVERY CLOCK PULSE (i.e. 8MHz noise). So indeed it is correct - // to not check for sync here. NEEDS TEST CASE. - - if (m_nSourceMode == 3) - { - ChangeLevel(); - } -} - -void CSAANoise::Tick(void) -{ - // Tick only does anything useful when we're - // clocking from the noise generator clock - // (ie, SourceMode = 0, 1 or 2) - - // So, if SourceMode = 3 (ie, we're clocking from a - // frequency generator ==> bUseFreqGen = true) - // then do nothing - if ( (!m_bSync) && (m_nSourceMode!=3) ) - { - m_nCounter += m_nAdd; - while (m_nCounter >= (m_nSampleRate<<12)) - { - m_nCounter -= (m_nSampleRate<<12); - m_nCounter_low++; - if (m_nCounter_low >= m_nCounterLimit_low) - { - m_nCounter_low = 0; - ChangeLevel(); - } - } - } -} - -void CSAANoise::Sync(bool bSync) -{ - if (bSync) - { - m_nCounter = 0; - m_nCounter_low = 0; - } - m_bSync = bSync; -} - - -void CSAANoise::_SetSampleRate(int nSampleRate) -{ - m_nSampleRate = nSampleRate; -} - - -void CSAANoise::_SetOversample(unsigned int oversample) -{ - // oversample is a power of 2 i.e. - // if oversample == 2 then 4x oversample - // if oversample == 6 then 64x oversample - if (oversample < m_nOversample) - { - m_nCounter_low <<= (m_nOversample - oversample); - } - else - { - m_nCounter_low >>= (oversample - m_nOversample); - } - - m_nCounterLimit_low = 1<> 1) ^ 0x20400; - } - else - { - m_nRand >>= 1; - } -} diff --git a/src/sound/saasound/SAANoise.h b/src/sound/saasound/SAANoise.h deleted file mode 100755 index 61a65dee8..000000000 --- a/src/sound/saasound/SAANoise.h +++ /dev/null @@ -1,54 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAANoise.h: interface for the CSAANoise class. -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAANOISE_H_INCLUDED -#define SAANOISE_H_INCLUDED - -class CSAANoise -{ -private: - unsigned long m_nCounter; - unsigned long m_nAdd; - unsigned long m_nCounter_low; - unsigned int m_nOversample; - unsigned long m_nCounterLimit_low; - bool m_bSync; // see description of "SYNC" bit of register 28 - unsigned long m_nSampleRate; // = 44100 when RateMode=0, for example - int m_nSourceMode; - unsigned long m_nAddBase; // nAdd for 31.25 kHz noise at 44.1 kHz samplerate - - // pseudo-random number generator - unsigned long m_nRand; - - void ChangeLevel(void); - - -public: - CSAANoise(); - CSAANoise(unsigned long seed); - ~CSAANoise(); - - void SetSource(int nSource); - void Trigger(void); - void _SetSampleRate(int nSampleRate); - void _SetOversample(unsigned int oversample); - void _SetClockRate(int nClockRate); - void Seed(unsigned long seed); - - void Tick(void); - int Level(void) const; - void Sync(bool bSync); - -}; - -inline int CSAANoise::Level(void) const -{ - // returns 0 or 1 - return (m_nRand & 0x00000001); -} - - -#endif // SAANOISE_H_INCLUDED diff --git a/src/sound/saasound/SAASndC.cpp b/src/sound/saasound/SAASndC.cpp deleted file mode 100755 index 9af0d76e7..000000000 --- a/src/sound/saasound/SAASndC.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// Thanks to this file (and associated header file) you can now -// use CSAASound from within a standard 'C' program -// -////////////////////////////////////////////////////////////////////// - -#include "SAASound.h" -#include "types.h" -#include "SAAEnv.h" -#include "SAANoise.h" -#include "SAAFreq.h" -#include "SAAAmp.h" -#include "SAASound.h" -#include "SAAImpl.h" - -SAASND SAAAPI newSAASND(void) -{ - return (SAASND)(new CSAASoundInternal()); -} - -void SAAAPI deleteSAASND(SAASND object) -{ - delete (LPCSAASOUND)(object); -} - -void SAAAPI SAASNDSetClockRate(SAASND object, unsigned int nClockRate) -{ - ((LPCSAASOUND)(object))->SetClockRate(nClockRate); -} - -void SAAAPI SAASNDSetSoundParameters(SAASND object, SAAPARAM uParam) -{ - ((LPCSAASOUND)(object))->SetSoundParameters(uParam); -} - -void SAAAPI SAASNDWriteAddress(SAASND object, BYTE nReg) -{ - ((LPCSAASOUND)(object))->WriteAddress(nReg); -} - -void SAAAPI SAASNDWriteData(SAASND object, BYTE nData) -{ - ((LPCSAASOUND)(object))->WriteData(nData); -} - -void SAAAPI SAASNDWriteAddressData(SAASND object, BYTE nReg, BYTE nData) -{ - ((LPCSAASOUND)(object))->WriteAddressData(nReg, nData); -} - -void SAAAPI SAASNDClear(SAASND object) -{ - ((LPCSAASOUND)(object))->Clear(); -} - -SAAPARAM SAAAPI SAASNDGetCurrentSoundParameters(SAASND object) -{ - return ((LPCSAASOUND)(object))->GetCurrentSoundParameters(); -} - -unsigned short SAAAPI SAASNDGetCurrentBytesPerSample(SAASND object) -{ - return ((LPCSAASOUND)(object))->GetCurrentBytesPerSample(); -} - -unsigned short SAAAPI SAASNDGetBytesPerSample(SAAPARAM uParam) -{ - return CSAASound::GetBytesPerSample(uParam); -} - -unsigned long SAAAPI SAASNDGetCurrentSampleRate(SAASND object) -{ - return ((LPCSAASOUND)(object))->GetCurrentSampleRate(); -} - -unsigned long SAAAPI SAASNDGetSampleRate(SAAPARAM uParam) -{ - return CSAASound::GetSampleRate(uParam); -} - -void SAAAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples) -{ - ((LPCSAASOUND)(object))->GenerateMany(pBuffer, nSamples); -} - -void SAAAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate) -{ - return ((LPCSAASOUND)(object))->SetSampleRate(nSampleRate); -} - -void SAAAPI SAASNDSetOversample(SAASND object, unsigned int nOversample) -{ - return ((LPCSAASOUND)(object))->SetOversample(nOversample); -} - -BYTE SAAAPI SAASNDReadAddress(SAASND object) -{ - return ((LPCSAASOUND)(object))->ReadAddress(); -} diff --git a/src/sound/saasound/SAASndC.h b/src/sound/saasound/SAASndC.h deleted file mode 100644 index c6fd65765..000000000 --- a/src/sound/saasound/SAASndC.h +++ /dev/null @@ -1,102 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// ********** -// * PUBLIC * -// ********** -// -// SAASndC.h: "C-style" interface for the CSAASound class. -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAASNDC_H_INCLUDED -#define SAASNDC_H_INCLUDED - -#ifdef _MSC_VER -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 -#endif - -#ifndef SAASOUND_H_INCLUDED - -// Parameters for use with SetSoundParameters, for example, -// SetSoundParameters(SAAP_NOFILTER | SAAP_44100 | SAAP_16BIT | SAAP_STEREO); -#define SAAP_FILTER_HIGHPASS_SIMPLE 0x00000400 -#define SAAP_FILTER_OVERSAMPLE64x 0x00000300 -#define SAAP_FILTER_OVERSAMPLE2x 0x00000200 -#define SAAP_FILTER SAAP_FILTER_OVERSAMPLE2x -#define SAAP_NOFILTER 0x00000100 -#define SAAP_44100 0x00000030 -#define SAAP_22050 0x00000020 -#define SAAP_11025 0x00000010 -#define SAAP_16BIT 0x0000000c -#define SAAP_8BIT 0x00000004 -#define SAAP_STEREO 0x00000003 -#define SAAP_MONO 0x00000001 - -// Bitmasks for use with GetCurrentSoundParameters, for example, -// unsigned long CurrentSampleRateParameter = GetCurrentSoundParameters() -#define SAAP_MASK_FILTER 0x00000f00 -#define SAAP_MASK_FILTER_HIGHPASS 0x00000c00 -#define SAAP_MASK_FILTER_OVERSAMPLE 0x00000300 -#define SAAP_MASK_SAMPLERATE 0x000000030 -#define SAAP_MASK_BITDEPTH 0x0000000c -#define SAAP_MASK_CHANNELS 0x00000003 - -typedef unsigned long SAAPARAM; - - -#ifndef BYTE -#define BYTE unsigned char -#endif - -#ifdef WIN32 -#ifndef WINAPI -#define WINAPI __stdcall -#endif -#define EXTAPI __declspec(dllexport) WINAPI -#else // Win32 -#ifndef WINAPI -#define WINAPI /**/ -#endif -#define EXTAPI /**/ -#endif // Win32 - -#endif // SAASOUND_H_INCLUDED - -typedef void * SAASND; - -// the following are implemented as calls, etc, to a class. - -#ifdef __cplusplus -extern "C" { -#endif - -SAASND EXTAPI newSAASND(void); -void EXTAPI deleteSAASND(SAASND object); - -void EXTAPI SAASNDSetSoundParameters(SAASND object, SAAPARAM uParam); -void EXTAPI SAASNDWriteAddress(SAASND object, BYTE nReg); -void EXTAPI SAASNDWriteData(SAASND object, BYTE nData); -void EXTAPI SAASNDWriteAddressData(SAASND object, BYTE nReg, BYTE nData); -void EXTAPI SAASNDClear(SAASND object); -BYTE EXTAPI SAASNDReadAddress(SAASND object); - -SAAPARAM EXTAPI SAASNDGetCurrentSoundParameters(SAASND object); -unsigned short EXTAPI SAASNDGetCurrentBytesPerSample(SAASND object); -unsigned short EXTAPI SAASNDGetBytesPerSample(SAAPARAM uParam); -unsigned long EXTAPI SAASNDGetCurrentSampleRate(SAASND object); -unsigned long EXTAPI SAASNDGetSampleRate(SAAPARAM uParam); - -void EXTAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples); - -void EXTAPI SAASNDSetClockRate(SAASND object, unsigned int nClockRate); -void EXTAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate); -void EXTAPI SAASNDSetOversample(SAASND object, unsigned int nOversample); - - -#ifdef __cplusplus -}; // extern "C" -#endif - -#endif // SAASNDC_H_INCLUDED diff --git a/src/sound/saasound/SAASound.cpp b/src/sound/saasound/SAASound.cpp deleted file mode 100755 index c5e33d862..000000000 --- a/src/sound/saasound/SAASound.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAASound.cpp - dummy function -// -////////////////////////////////////////////////////////////////////// - -#include - -// Provide something so the compiler doesn't optimise us out of existance -int SomeFunction () -{ - return 42; -} diff --git a/src/sound/saasound/SAASound.h b/src/sound/saasound/SAASound.h deleted file mode 100644 index a5e9265ac..000000000 --- a/src/sound/saasound/SAASound.h +++ /dev/null @@ -1,130 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// SAASound.h: interface for the CSAASound class. -// -// This corresponds to the public (exported) DLL interface, so all -// APIs and client factory methods belong here. -// -// Compatibility notes : the intention is for this to be fully backwards -// compatible across minor and patch versions. Any backwards breaking changes -// should be reflected as a major version increment. New functionality can be added -// in minor versions so long as backwards compatiblity is maintained -// -// Version 3.3.0 (4th Dec 2018) -// -////////////////////////////////////////////////////////////////////// - -#ifndef SAASOUND_H_INCLUDED -#define SAASOUND_H_INCLUDED - -// define this if you want to output diagnostic text and PCM files -//#define DEBUGSAA - -// Parameters for use with SetSoundParameters, for example, -// SetSoundParameters(SAAP_NOFILTER | SAAP_44100 | SAA_16BIT | SAA_STEREO); -// SAAP_FILTER_HIGHPASS_SIMPLE can be ORd with SAAP_FILTER_OVERSAMPLE64x/2x -#define SAAP_FILTER_HIGHPASS_SIMPLE 0x00000400 -#define SAAP_FILTER_OVERSAMPLE64x 0x00000300 -#define SAAP_FILTER_OVERSAMPLE2x 0x00000200 -#define SAAP_FILTER SAAP_FILTER_OVERSAMPLE2x -#define SAAP_NOFILTER 0x00000100 -#define SAAP_44100 0x00000030 -#define SAAP_22050 0x00000020 -#define SAAP_11025 0x00000010 -#define SAAP_16BIT 0x0000000c -#define SAAP_8BIT 0x00000004 -#define SAAP_STEREO 0x00000003 -#define SAAP_MONO 0x00000001 - -// Bitmasks for use with GetCurrentSoundParameters, for example, -// unsigned long CurrentSampleRateParameter = GetCurrentSoundParameters() -#define SAAP_MASK_FILTER 0x00000f00 -#define SAAP_MASK_FILTER_HIGHPASS 0x00000c00 -#define SAAP_MASK_FILTER_OVERSAMPLE 0x00000300 -#define SAAP_MASK_SAMPLERATE 0x000000030 -#define SAAP_MASK_BITDEPTH 0x0000000c -#define SAAP_MASK_CHANNELS 0x00000003 - -typedef unsigned long SAAPARAM; - - -#ifndef BYTE -#define BYTE unsigned char -#endif - -#ifdef _WIN32 -#define SAAAPI _stdcall -#else -#define SAAAPI -#endif - - -#ifdef __cplusplus - -class CSAASound -{ -public: - virtual ~CSAASound() { } - - virtual void SetSoundParameters (SAAPARAM uParam) = 0; - virtual void WriteAddress (BYTE nReg) = 0; - virtual void WriteData (BYTE nData) = 0; - virtual void WriteAddressData (BYTE nReg, BYTE nData) = 0; - virtual void Clear () = 0; - virtual BYTE ReadAddress () = 0; - - virtual SAAPARAM GetCurrentSoundParameters () = 0; - virtual unsigned long GetCurrentSampleRate () = 0; - static unsigned long GetSampleRate (SAAPARAM uParam); - virtual unsigned short GetCurrentBytesPerSample () = 0; - static unsigned short GetBytesPerSample (SAAPARAM uParam); - - virtual void GenerateMany (BYTE * pBuffer, unsigned long nSamples) = 0; - - virtual void SetClockRate(unsigned int nClockRate) = 0; - virtual void SetSampleRate(unsigned int nSampleRate) = 0; - virtual void SetOversample(unsigned int nOversample) = 0; -}; - -typedef class CSAASound * LPCSAASOUND; - -LPCSAASOUND SAAAPI CreateCSAASound(void); -void SAAAPI DestroyCSAASound(LPCSAASOUND object); - -#endif // __cplusplus - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void * SAASND; - -// "C-style" interface for the CSAASound class -SAASND SAAAPI newSAASND(void); -void SAAAPI deleteSAASND(SAASND object); - -void SAAAPI SAASNDSetSoundParameters(SAASND object, SAAPARAM uParam); -void SAAAPI SAASNDWriteAddress(SAASND object, BYTE nReg); -void SAAAPI SAASNDWriteData(SAASND object, BYTE nData); -void SAAAPI SAASNDWriteAddressData(SAASND object, BYTE nReg, BYTE nData); -void SAAAPI SAASNDClear(SAASND object); - -SAAPARAM SAAAPI SAASNDGetCurrentSoundParameters(SAASND object); -unsigned short SAAAPI SAASNDGetCurrentBytesPerSample(SAASND object); -unsigned short SAAAPI SAASNDGetBytesPerSample(SAAPARAM uParam); -unsigned long SAAAPI SAASNDGetCurrentSampleRate(SAASND object); -unsigned long SAAAPI SAASNDGetSampleRate(SAAPARAM uParam); - -void SAAAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples); -void SAAAPI SAASNDSetClockRate(SAASND object, unsigned int nClockRate); -void SAAAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate); -void SAAAPI SAASNDSetOversample(SAASND object, unsigned int nOversample); - -BYTE SAAAPI SAASNDReadAddress(SAASND object); - -#ifdef __cplusplus -}; // extern "C" -#endif - -#endif // SAASOUND_H_INCLUDED diff --git a/src/sound/saasound/defns.h b/src/sound/saasound/defns.h deleted file mode 100644 index e81d1c819..000000000 --- a/src/sound/saasound/defns.h +++ /dev/null @@ -1,59 +0,0 @@ -// Part of SAASound copyright 2020 Dave Hooper -// -// defns.h: compile-time configuration parameters -// -////////////////////////////////////////////////////////////////////// - -#ifndef DEFNS_H_INCLUDED -#define DEFNS_H_INCLUDED - -#define HAVE_CONFIG_H -#ifdef HAVE_CONFIG_H -// using CMAKE -#include "saasound_cmake_config.h" -#else - -// initial default SAA1099 crystal clock rate in HZ (can be changed subsequently by calling SetClockRate) -#define EXTERNAL_CLK_HZ 8000000 - -// define SAAFREQ_FIXED_CLOCKRATE if the above external clock rate is the only supported clock rate -// i.e. only support a single compile-time clock rate (=> this also prevents using the SetClockRate method) -#undef SAAFREQ_FIXED_CLOCKRATE -// #define SAAFREQ_FIXED_CLOCKRATE - -// initial default sample rate (audio samplerate) -#define SAMPLE_RATE_HZ 44100 - -// initial default oversample (audio quality) recommend 0<=oversample<=6 -#define DEFAULT_OVERSAMPLE 6 - -// Whether to dump out a log of all register and value changes and raw output pcm -//#define DEBUGSAA -#undef DEBUGSAA - -// the (default) names of the register output and pcm output log files. -// If you're using a config file, you can change these (or, if you enable -// debugging via the config file settings, but leave the filenames unspecified, -// it will use these defaults) -#define DEBUG_SAA_REGISTER_LOG "debugsaa.txt" -#define DEBUG_SAA_PCM_LOG "debugsaa.pcm" -// Whether to include support for these debug logs via config file (only making -// sense if USE_CONFIG_FILE is also defined) - -// Whether to support a startup configuration file that is parsed at load time -// #undef USE_CONFIG_FILE -#define USE_CONFIG_FILE - -// and if so, what is its location -#ifdef USE_CONFIG_FILE -#define CONFIG_FILE_PATH "SAASound.cfg" -#endif // USE_CONFIG_FILE - -#define DEFAULT_UNBOOSTED_MULTIPLIER 11.35 - -#define DEFAULT_BOOST 1 - - -#endif // HAVE_CONFIG_H - -#endif // DEFNS_H_INCLUDED diff --git a/src/sound/saasound/resource.h b/src/sound/saasound/resource.h deleted file mode 100755 index 0b893bf3a..000000000 --- a/src/sound/saasound/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by SAASound.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/sound/saasound/saasound_cmake_config.h b/src/sound/saasound/saasound_cmake_config.h deleted file mode 100644 index da914a71b..000000000 --- a/src/sound/saasound/saasound_cmake_config.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#define EXTERNAL_CLK_HZ 7159090 -/* #undef SAAFREQ_FIXED_CLOCKRATE */ -#define SAMPLE_RATE_HZ 44100 -#define DEFAULT_OVERSAMPLE 6 -#define DEFAULT_UNBOOSTED_MULTIPLIER 11.3 -#define DEFAULT_BOOST 1 -/* #undef DEBUGSAA */ -#define DEBUG_SAA_REGISTER_LOG "debugsaa.txt" -#define DEBUG_SAA_PCM_LOG "debugsaa.pcm" - -/* #undef USE_CONFIG_FILE */ -#define CONFIG_FILE_PATH "SAASound.cfg" diff --git a/src/sound/saasound/types.h b/src/sound/saasound/types.h deleted file mode 100755 index 4eb62f485..000000000 --- a/src/sound/saasound/types.h +++ /dev/null @@ -1,34 +0,0 @@ -// Part of SAASound copyright 1998-2018 Dave Hooper -// -// handy typedefs -// -////////////////////////////////////////////////////////////////////// - -#ifndef TYPES_H_INCLUDED -#define TYPES_H_INCLUDED - -#if defined(__i386__) || defined(WIN32) || \ - (defined(__alpha__) || defined(__alpha)) || \ - defined(__arm__) || \ - (defined(__mips__) && defined(__MIPSEL__)) -#else -#define __BIG_ENDIAN -#endif - - -#ifndef NULL -#define NULL 0 -#endif - -typedef struct -{ - int nNumberOfPhases; - bool bLooping; - int nLevels[2][2][16]; // [Resolution][Phase][Withinphase] -} ENVDATA; - -#ifdef WIN32 -extern "C" void _stdcall OutputDebugStringA (char*); -#endif - -#endif diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index c6591b1fc..66dff80f3 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -8,7 +8,6 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> -#include "saasound/SAASound.h" #include <86box/snd_cms.h> #include <86box/sound.h> #include <86box/plat_unused.h> @@ -16,13 +15,62 @@ void cms_update(cms_t *cms) { - if (cms->pos < wavetable_pos_global) { - SAASNDGenerateMany(cms->saasound, (unsigned char*)&cms->buffer[cms->pos], wavetable_pos_global - cms->pos); - cms->pos = wavetable_pos_global; - } - if (cms->pos2 < wavetable_pos_global) { - SAASNDGenerateMany(cms->saasound2, (unsigned char*)&cms->buffer2[cms->pos2], wavetable_pos_global - cms->pos2); - cms->pos2 = wavetable_pos_global; + for (; cms->pos < sound_pos_global; cms->pos++) { + int16_t out_l = 0; + int16_t out_r = 0; + + for (uint8_t c = 0; c < 4; c++) { + switch (cms->noisetype[c >> 1][c & 1]) { + case 0: + cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 256; + break; + case 1: + cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 512; + break; + case 2: + cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 1024; + break; + case 3: + cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; + break; + + default: + break; + } + } + for (uint8_t c = 0; c < 2; c++) { + if (cms->regs[c][0x1C] & 1) { + for (uint8_t d = 0; d < 6; d++) { + if (cms->regs[c][0x14] & (1 << d)) { + if (cms->stat[c][d]) + out_l += (cms->vol[c][d][0] * 90); + if (cms->stat[c][d]) + out_r += (cms->vol[c][d][1] * 90); + cms->count[c][d] += cms->freq[c][d]; + if (cms->count[c][d] >= 24000) { + cms->count[c][d] -= 24000; + cms->stat[c][d] ^= 1; + } + } else if (cms->regs[c][0x15] & (1 << d)) { + if (cms->noise[c][d / 3] & 1) + out_l += (cms->vol[c][d][0] * 90); + if (cms->noise[c][d / 3] & 1) + out_r += (cms->vol[c][d][0] * 90); + } + } + for (uint8_t d = 0; d < 2; d++) { + cms->noisecount[c][d] += cms->noisefreq[c][d]; + while (cms->noisecount[c][d] >= 24000) { + cms->noisecount[c][d] -= 24000; + cms->noise[c][d] <<= 1; + if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40))) + cms->noise[c][d] |= 1; + } + } + } + } + cms->buffer[cms->pos << 1] = out_l; + cms->buffer[(cms->pos << 1) + 1] = out_r; } } @@ -39,39 +87,63 @@ cms_get_buffer(int32_t *buffer, int len, void *priv) cms->pos = 0; } -void -cms_get_buffer_2(int32_t *buffer, int len, void *priv) -{ - cms_t *cms = (cms_t *) priv; - - cms_update(cms); - - for (int c = 0; c < len * 2; c++) - buffer[c] += cms->buffer2[c]; - - cms->pos2 = 0; -} - void cms_write(uint16_t addr, uint8_t val, void *priv) { cms_t *cms = (cms_t *) priv; + int voice; + int chip = (addr & 2) >> 1; switch (addr & 0xf) { case 0x1: /* SAA #1 Register Select Port */ - SAASNDWriteAddress(cms->saasound, val & 31); + cms->addrs[0] = val & 31; break; case 0x3: /* SAA #2 Register Select Port */ - SAASNDWriteAddress(cms->saasound2, val & 31); + cms->addrs[1] = val & 31; break; case 0x0: /* SAA #1 Data Port */ - cms_update(cms); - SAASNDWriteData(cms->saasound, val); - break; case 0x2: /* SAA #2 Data Port */ cms_update(cms); - SAASNDWriteData(cms->saasound2, val); + cms->regs[chip][cms->addrs[chip] & 31] = val; + switch (cms->addrs[chip] & 31) { + case 0x00: + case 0x01: + case 0x02: /*Volume*/ + case 0x03: + case 0x04: + case 0x05: + voice = cms->addrs[chip] & 7; + cms->vol[chip][voice][0] = val & 0xf; + cms->vol[chip][voice][1] = val >> 4; + break; + case 0x08: + case 0x09: + case 0x0A: /*Frequency*/ + case 0x0B: + case 0x0C: + case 0x0D: + voice = cms->addrs[chip] & 7; + cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val; + cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); + break; + case 0x10: + case 0x11: + case 0x12: /*Octave*/ + voice = (cms->addrs[chip] & 3) << 1; + cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8); + cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4); + cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); + cms->freq[chip][voice + 1] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255)); + break; + case 0x16: /*Noise*/ + cms->noisetype[chip][0] = val & 3; + cms->noisetype[chip][1] = (val >> 4) & 3; + break; + + default: + break; + } break; case 0x6: /* GameBlaster Write Port */ @@ -91,9 +163,9 @@ cms_read(uint16_t addr, void *priv) switch (addr & 0xf) { case 0x1: /* SAA #1 Register Select Port */ - return SAASNDReadAddress(cms->saasound); + return cms->addrs[0]; case 0x3: /* SAA #2 Register Select Port */ - return SAASNDReadAddress(cms->saasound2); + return cms->addrs[1]; case 0x4: /* GameBlaster Read port (Always returns 0x7F) */ return 0x7f; case 0xa: /* GameBlaster Read Port */ @@ -113,12 +185,7 @@ cms_init(UNUSED(const device_t *info)) uint16_t addr = device_get_config_hex16("base"); io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); - cms->saasound = newSAASND(); - SAASNDSetSoundParameters(cms->saasound, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); - cms->saasound2 = newSAASND(); - SAASNDSetSoundParameters(cms->saasound2, SAAP_44100 | SAAP_16BIT | SAAP_NOFILTER | SAAP_STEREO); - wavetable_add_handler(cms_get_buffer, cms); - wavetable_add_handler(cms_get_buffer_2, cms); + sound_add_handler(cms_get_buffer, cms); return cms; } @@ -127,9 +194,6 @@ cms_close(void *priv) { cms_t *cms = (cms_t *) priv; - deleteSAASND(cms->saasound); - deleteSAASND(cms->saasound2); - free(cms); } From cdae57e7b4a28cd70f86a13be0d48724127e3193 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Sun, 18 May 2025 21:05:23 +0300 Subject: [PATCH 0952/1190] Preliminary attempt at implementing the Dell OptiPlex GN+ --- src/include/86box/machine.h | 1 + src/machine/m_at_socket7.c | 34 ++++++++++++++++++++++++++++ src/machine/machine_table.c | 44 +++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c76761b3c..5153c4627 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -751,6 +751,7 @@ extern int machine_at_gw2kte_init(const machine_t *); extern int machine_at_ma23c_init(const machine_t *); extern int machine_at_nupro592_init(const machine_t *); extern int machine_at_tx97_init(const machine_t *); +extern int machine_at_optiplex_gn_init(const machine_t *); #ifdef USE_AN430TX extern int machine_at_an430tx_init(const machine_t *); #endif /* USE_AN430TX */ diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 319856d41..17c89e39d 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -969,6 +969,40 @@ machine_at_tx97_init(const machine_t *model) return ret; } +int +machine_at_optiplex_gn_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/optiplex_gn/Gn_a11.rom", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); /* 3C905, not yet emulated */ + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87307_15c_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + #ifdef USE_AN430TX int machine_at_an430tx_init(const machine_t *model) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 45986a50a..f28079888 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13103,6 +13103,50 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* According to Dell specifications, it can have either National Semiconductor PC87307 or PC87309 + Super I/O. All known instances have the former, although other similar Dells of the era have + pinouts for accompanying either so this likely also does. + + The KBC is likely an AMIKey-2 clone. */ + { + .name = "[i430TX] Dell OptiPlex GN+", + .internal_name = "optiplex_gn", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_optiplex_gn_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO, /* Video: S3 86C785 (Trio64V2/GX), ethernet: 3C905 */ + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_trio64v2_dx_onboard_pci_device, /* Stop-gap measure until the Trio64V2/GX is emulated, as both use the same VBIOS */ + .snd_device = NULL, + .net_device = NULL + }, /* [TEST] Has AMI Megakey '5' KBC firmware on the SM(S)C FDC37C67x Super I/O chip. */ { .name = "[i430TX] Gateway E-1000", From 9441b6f2cf04238f51c39d3e875ac76555ae0467 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 20:42:28 +0200 Subject: [PATCH 0953/1190] PC87309: Make the Super I/O chip relocatable. --- src/sio/sio_pc87309.c | 45 ++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index da53802c1..2219ede17 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -41,15 +41,19 @@ typedef struct pc87309_t { uint8_t regs[48]; uint8_t ld_regs[256][208]; uint8_t pm[8]; + uint8_t baddr; uint16_t pm_base; int cur_reg; fdc_t *fdc; serial_t *uart[2]; } pc87309_t; -static void fdc_handler(pc87309_t *dev); -static void lpt1_handler(pc87309_t *dev); -static void serial_handler(pc87309_t *dev, int uart); +static void fdc_handler(pc87309_t *dev); +static void lpt1_handler(pc87309_t *dev); +static void serial_handler(pc87309_t *dev, int uart); + +static void pc87309_write(uint16_t port, uint8_t val, void *priv); +static uint8_t pc87309_read(uint16_t port, void *priv); static void pc87309_pm_write(uint16_t port, uint8_t val, void *priv) @@ -104,6 +108,26 @@ pc87309_pm_init(pc87309_t *dev, uint16_t addr) pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); } +static void +superio_handler(pc87309_t *dev) +{ + io_removehandler(0x15c, 0x0002, + pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + io_removehandler(0x02e, 0x0002, + pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + + switch (dev->baddr) { + case 2: + io_sethandler(0x15c, 0x0002, + pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + break; + case 3: + io_sethandler(0x02e, 0x0002, + pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + break; + } +} + static void fdc_handler(pc87309_t *dev) { @@ -197,6 +221,7 @@ pc87309_write(uint16_t port, uint8_t val, void *priv) break; case 0x22: dev->regs[dev->cur_reg] = val & 0x7f; + superio_handler(dev); break; default: if (dev->cur_reg >= 0x30) { @@ -379,6 +404,7 @@ pc87309_reset(pc87309_t *dev) dev->regs[0x20] = dev->id; dev->regs[0x21] = 0x04; + dev->regs[0x22] = dev->baddr; dev->ld_regs[0x00][0x01] = 0x01; dev->ld_regs[0x00][0x30] = 0x03; @@ -453,6 +479,8 @@ pc87309_reset(pc87309_t *dev) serial_remove(dev->uart[0]); serial_remove(dev->uart[1]); fdc_reset(dev->fdc); + + superio_handler(dev); } static void @@ -472,19 +500,10 @@ pc87309_init(const device_t *info) dev->fdc = device_add(&fdc_at_nsc_device); - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->baddr = (info->local & 0x100) ? 2 : 3; pc87309_reset(dev); - if (info->local & 0x100) { - io_sethandler(0x15c, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - } else { - io_sethandler(0x02e, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - } - return dev; } From a262a519cbba418fd918b5e1ef2828f34d5006eb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 May 2025 20:48:29 +0200 Subject: [PATCH 0954/1190] PC87309: Actually fix relocation so it's implemented according to the PC87309 datasheet, not the PC87306 one. --- src/sio/sio_pc87309.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index 2219ede17..5e417aefb 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -116,12 +116,16 @@ superio_handler(pc87309_t *dev) io_removehandler(0x02e, 0x0002, pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - switch (dev->baddr) { - case 2: + switch (dev->regs[0x21] & 0x0b) { + case 0x02: + case 0x08: + case 0x0a: io_sethandler(0x15c, 0x0002, pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); break; - case 3: + case 0x03: + case 0x09: + case 0x0b: io_sethandler(0x02e, 0x0002, pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); break; @@ -218,10 +222,10 @@ pc87309_write(uint16_t port, uint8_t val, void *priv) case 0x07: case 0x21: dev->regs[dev->cur_reg] = val; + superio_handler(dev); break; case 0x22: dev->regs[dev->cur_reg] = val & 0x7f; - superio_handler(dev); break; default: if (dev->cur_reg >= 0x30) { @@ -403,8 +407,7 @@ pc87309_reset(pc87309_t *dev) memset(dev->pm, 0x00, 0x08); dev->regs[0x20] = dev->id; - dev->regs[0x21] = 0x04; - dev->regs[0x22] = dev->baddr; + dev->regs[0x21] = 0x04 | dev->baddr; dev->ld_regs[0x00][0x01] = 0x01; dev->ld_regs[0x00][0x30] = 0x03; @@ -500,7 +503,7 @@ pc87309_init(const device_t *info) dev->fdc = device_add(&fdc_at_nsc_device); - dev->baddr = (info->local & 0x100) ? 2 : 3; + dev->baddr = (info->local & 0x100) ? 8 : 9; pc87309_reset(dev); From d5a63540067b599350e90669b871b7c75ecd4dea Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Mon, 19 May 2025 15:53:39 +0300 Subject: [PATCH 0955/1190] Add the Dell OptiPlex GXL/GXM --- src/include/86box/machine.h | 1 + src/machine/m_at_socket5.c | 32 +++++++++++++++++++++++++++++ src/machine/machine_table.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c76761b3c..e9dc5bda9 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -672,6 +672,7 @@ extern int machine_at_tek932_init(const machine_t *); extern int machine_at_acerv30_init(const machine_t *); extern int machine_at_apollo_init(const machine_t *); +extern int machine_at_optiplex_gxl_init(const machine_t *); extern int machine_at_zappa_init(const machine_t *); extern int machine_at_powermatev_init(const machine_t *); extern int machine_at_hawk_init(const machine_t *); diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 4b3bbd49c..9981f8e85 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -236,6 +236,38 @@ machine_at_apollo_init(const machine_t *model) return ret; } +int +machine_at_optiplex_gxl_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/optiplex_gxl/DELL.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x10, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&pc87332_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + static void machine_at_zappa_gpio_init(void) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 45986a50a..d9e6f2940 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -10553,6 +10553,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a National Semiconductor PC87332VLJ Super I/O with AMIKey 'F' KBC firmware. */ + { + .name = "[i430FX] Dell OptiPlex GXL/GXM", + .internal_name = "optiplex_gxl", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_optiplex_gxl_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, /* Video: S3 Trio64V+ (86C765), Network: 3Com ETHERLINK III (3C509B) */ + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL /* not yet emulated */ + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ From ec613f16085fe70ce6fe02518f0e716cc2117a58 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Mon, 19 May 2025 16:18:32 +0300 Subject: [PATCH 0956/1190] Add the onboard sound for the OptiPlex GXL/GXM --- src/machine/m_at_socket5.c | 4 ++++ src/machine/machine_table.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 9981f8e85..7c5ab697a 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -40,6 +40,7 @@ #include <86box/sio.h> #include <86box/video.h> #include <86box/machine.h> +#include <86box/sound.h> int machine_at_plato_init(const machine_t *model) @@ -259,6 +260,9 @@ machine_at_optiplex_gxl_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); + if (sound_card_current[0] == SOUND_INTERNAL) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d9e6f2940..3e50442c1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -10575,7 +10575,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, /* Video: S3 Trio64V+ (86C765), Network: 3Com ETHERLINK III (3C509B) */ + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM, /* Video: S3 Trio64V+ (86C765), Sound: Creative ViBRA 16S (CT2504), Network: 3Com ETHERLINK III (3C509B) */ .ram = { .min = 8192, .max = 131072, @@ -10590,7 +10590,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, - .snd_device = NULL, + .snd_device = &sb_vibra16s_onboard_device, .net_device = NULL /* not yet emulated */ }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the From d7282ddc46d2059cf1973d0b07d8dacfd5592850 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Mon, 19 May 2025 16:28:01 +0300 Subject: [PATCH 0957/1190] Block the Cyrix Cx6x86 from the Dell OptiPlex GXL/GXM as it cannot POST with it --- 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 3e50442c1..f4031c0b7 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -10566,7 +10566,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_Cx6x86), .min_bus = 60000000, .max_bus = 66666667, .min_voltage = 3380, From e04628cc7cf13131f872c8bc8304eb0c29fa8fbf Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 19 May 2025 19:25:21 +0200 Subject: [PATCH 0958/1190] Trident pattern and memory access changes (May 19th, 2025) 1. DirectDraw memory address fixes of the day (removing the bit 6 of crtc 2a side of the if in recalctimings). 2. In spite of no documentration or NDA manuals, get data from the pattern registers as best as possible in 32bpp mode, this fixes patterns in 32bpp mode using various stuff. --- src/video/vid_tgui9440.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index af203f327..6fbdb7c3f 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -125,6 +125,7 @@ typedef struct tgui_t { uint8_t rop; uint32_t flags; uint8_t pattern[0x80]; + uint8_t pattern_32bpp[0x100]; int command; int offset; uint16_t ger22; @@ -142,6 +143,7 @@ typedef struct tgui_t { uint32_t pattern_8[8 * 8]; uint32_t pattern_16[8 * 8]; uint32_t pattern_32[8 * 8]; + int pattern_32_idx; } accel; uint8_t copy_latch[16]; /*TGUI9400CXi only*/ @@ -756,7 +758,7 @@ tgui_recalctimings(svga_t *svga) if (svga->vdisp == 1020) svga->vdisp += 2; - if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) + if (tgui->oldctrl2 & 0x10) svga->ma_latch <<= 1; svga->lowres = !(svga->crtc[0x2a] & 0x40); @@ -2280,6 +2282,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) if (count == -1) tgui->accel.x = tgui->accel.y = 0; + tgui->accel.pattern_32_idx = 0; + if (tgui->accel.flags & TGUI_SOLIDFILL) { for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { @@ -2298,22 +2302,21 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) if (tgui->accel.bpp == 0) { for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { - tgui->accel.pattern_8[(y * 8) + (7 - x)] = tgui->accel.pattern[x + y * 8]; + tgui->accel.pattern_8[(y * 8) + x] = tgui->accel.pattern[x + y * 8]; } } pattern_data = tgui->accel.pattern_8; } else if (tgui->accel.bpp == 1) { for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { - tgui->accel.pattern_16[(y * 8) + (7 - x)] = tgui->accel.pattern[x * 2 + y * 16] | (tgui->accel.pattern[x * 2 + y * 16 + 1] << 8); + tgui->accel.pattern_16[(y * 8) + x] = tgui->accel.pattern[x * 2 + y * 16] | (tgui->accel.pattern[x * 2 + y * 16 + 1] << 8); } } pattern_data = tgui->accel.pattern_16; } else { - for (y = 0; y < 4; y++) { + for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { - tgui->accel.pattern_32[(y * 8) + (7 - x)] = tgui->accel.pattern[x * 4 + y * 32] | (tgui->accel.pattern[x * 4 + y * 32 + 1] << 8) | (tgui->accel.pattern[x * 4 + y * 32 + 2] << 16) | (tgui->accel.pattern[x * 4 + y * 32 + 3] << 24); - tgui->accel.pattern_32[((y + 4) * 8) + (7 - x)] = tgui->accel.pattern[x * 4 + y * 32] | (tgui->accel.pattern[x * 4 + y * 32 + 1] << 8) | (tgui->accel.pattern[x * 4 + y * 32 + 2] << 16) | (tgui->accel.pattern[x * 4 + y * 32 + 3] << 24); + tgui->accel.pattern_32[(y * 8) + x] = tgui->accel.pattern_32bpp[x * 4 + y * 32] | (tgui->accel.pattern_32bpp[x * 4 + y * 32 + 1] << 8) | (tgui->accel.pattern_32bpp[x * 4 + y * 32 + 2] << 16) | (tgui->accel.pattern_32bpp[x * 4 + y * 32 + 3] << 24); } } pattern_data = tgui->accel.pattern_32; @@ -2396,6 +2399,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) count -= 3; } + READ(tgui->accel.dst, dst_dat); pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; @@ -3192,6 +3196,8 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *priv) case 0x21fe: case 0x21ff: tgui->accel.pattern[addr & 0x7f] = val; + tgui->accel.pattern_32bpp[tgui->accel.pattern_32_idx] = val; + tgui->accel.pattern_32_idx = (tgui->accel.pattern_32_idx + 1) & 0xff; break; default: From 9f46d0b9d8c700e5c04d89e4229958a75906e310 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Mon, 19 May 2025 20:59:08 +0300 Subject: [PATCH 0959/1190] Fix the initialization and general purpose I/O (GPIO) pins for the OptiPlex GXL/GXM --- src/device/kbc_at.c | 11 ++++++++++- src/machine/m_at_socket5.c | 5 +++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 58aab476c..7413b45cf 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1096,7 +1096,16 @@ write64_generic(void *priv, uint8_t val) - Bit 5: Manufacturing jumper (must be set); */ uint8_t p1 = 0x24; - kbc_delay_to_ob(dev, p1, 0, 0x01); + kbc_delay_to_ob(dev, p1, 0, 0x00); + } else if (!strcmp(machine_get_internal_name(), "optiplex_gxl")) { + /* + Dell OptiPlex GXL/GXM: + - Bit 3: Password disable jumper (must be clear); + - Bit 4: Keyboard fuse (must be set); + - Bit 5: Manufacturing jumper (must be set); + */ + uint8_t p1 = 0x30; + kbc_delay_to_ob(dev, p1, 0, 0x00); } else { /* (B0 or F0) | (0x08 or 0x0c) */ uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) | diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 7c5ab697a..5572d0484 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -248,7 +248,8 @@ machine_at_optiplex_gxl_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -263,7 +264,7 @@ machine_at_optiplex_gxl_init(const machine_t *model) if (sound_card_current[0] == SOUND_INTERNAL) machine_snd = device_add(machine_get_snd_device(machine)); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_phoenix_pci_device); device_add(&i430fx_device); device_add(&piix_device); device_add(&pc87332_device); From dbc2baebe915f443e5ce0cb6c81739cdc0cd9d1e Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 19 May 2025 22:22:03 +0200 Subject: [PATCH 0960/1190] Small ATI Mach8 changes (May 19th, 2025) 1. Report the ATI 28800 of the Graphics Ultra as 28800-6. 2. Access the upper word properly on vdisp. 3. Make sure there's enough vsyncstart/vtotal space for a full vertical display. --- src/video/vid_ati_mach8.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 8423f096b..a9544e724 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2510,6 +2510,12 @@ mach_in(uint16_t addr, void *priv) case 0xa9: temp = svga->vc & 0xff; break; + case 0xaa: + if (ATI_GRAPHICS_ULTRA) + temp = 0x06; + else + temp = 0x00; + break; case 0xb0: temp = mach->regs[0xb0] | 0x80; temp &= ~0x18; @@ -2699,12 +2705,10 @@ mach_set_resolution(mach_t *mach, svga_t *svga) 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("VSYNCSTART=%d, VTOTAL=%d, interlace=%02x, vdisp=%d.\n", dev->v_syncstart, dev->v_total, dev->interlace, dev->vdisp); if (ATI_8514A_ULTRA) { if ((mach->accel.clock_sel & 0x01) && @@ -3233,7 +3237,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (len == 1) { 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 & 0x20)) { - WRITE8(port, dev->v_disp, val); + WRITE8(port, dev->v_disp, val >> 8); dev->v_disp &= 0x1fff; } } @@ -3267,7 +3271,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (len == 1) { 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_sync_start, val); + WRITE8(port, dev->v_sync_start, val >> 8); dev->v_sync_start &= 0x1fff; } } From 06f4491193967cec42871b0748bf73f3d68cc6f0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 20 May 2025 20:33:22 +0200 Subject: [PATCH 0961/1190] Mach8 mode changes of the day (May 20th, 2025) Make the previously Mach8 add-on only mode changes also available to the Graphics Ultra, should fix incorrect resolutions after switching from fullscreen DOS prompt to windowed and viceversa under Win98 (and SE). --- src/video/vid_ati_mach8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index a9544e724..0b5673d69 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2710,7 +2710,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga) mach_log("VSYNCSTART=%d, VTOTAL=%d, interlace=%02x, vdisp=%d.\n", dev->v_syncstart, dev->v_total, dev->interlace, dev->vdisp); - if (ATI_8514A_ULTRA) { + if (!ATI_MACH32) { if ((mach->accel.clock_sel & 0x01) && !(dev->accel.advfunc_cntl & 0x01)) ret = 2; From 39a3d1ded022201f2a48f0d63646ba2ece313682 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 21 May 2025 14:04:55 +0600 Subject: [PATCH 0962/1190] Backport RxConfig fixes from QEMU --- src/network/net_rtl8139.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 5138b5168..0d07a8f83 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -2549,6 +2549,12 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) break; + case RxConfig: + rtl8139_log("RxConfig write(b) val=0x%02x\n", val); + rtl8139_RxConfig_write(s, + (rtl8139_RxConfig_read(s) & 0xFFFFFF00) | val); + break; + default: rtl8139_log("not implemented write(b) addr=0x%x val=0x%02x\n", addr, val); break; From accce358e8231aca604336df4925d2b643a7e6af Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Wed, 21 May 2025 12:04:55 +0300 Subject: [PATCH 0963/1190] Fix the Password "Disabled by Jumper" error on Dimension XPS Pxxx and Pxxxa/Mxxxa --- src/device/kbc_at.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 7413b45cf..60ca29fc1 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1106,6 +1106,14 @@ write64_generic(void *priv, uint8_t val) */ uint8_t p1 = 0x30; kbc_delay_to_ob(dev, p1, 0, 0x00); + } else if (!strcmp(machine_get_internal_name(), "dellplato") | !strcmp(machine_get_internal_name(), "dellhannibalp")) { + /* + Dell Dimension XPS Pxxx & Pxxxa/Mxxxa: + - Bit 3: Password disable jumper (must be clear); + - Bit 4: Clear CMOS jumper (must be set); + */ + uint8_t p1 = 0x10; + kbc_delay_to_ob(dev, p1, 0, 0x00); } else { /* (B0 or F0) | (0x08 or 0x0c) */ uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) | From b18f69c037060ae0ccc79457a138da0d52c061b0 Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Wed, 21 May 2025 12:18:54 +0300 Subject: [PATCH 0964/1190] Fix a small typo that causes some checks to fail --- src/device/kbc_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 60ca29fc1..7b6bea0c4 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1106,7 +1106,7 @@ write64_generic(void *priv, uint8_t val) */ uint8_t p1 = 0x30; kbc_delay_to_ob(dev, p1, 0, 0x00); - } else if (!strcmp(machine_get_internal_name(), "dellplato") | !strcmp(machine_get_internal_name(), "dellhannibalp")) { + } else if (!strcmp(machine_get_internal_name(), "dellplato") || !strcmp(machine_get_internal_name(), "dellhannibalp")) { /* Dell Dimension XPS Pxxx & Pxxxa/Mxxxa: - Bit 3: Password disable jumper (must be clear); From e76a89bcc80cb693efaa9f6165df8868add35f11 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 21 May 2025 13:32:17 +0200 Subject: [PATCH 0965/1190] Windows: Change cursor clipping from cursor warping to ClipCursor(), fixes #5498. --- src/qt/qt_rendererstack.cpp | 16 +++++++++++++++- src/qt/qt_ui.cpp | 23 +++++++++++++++++++++++ src/qt/qt_winrawinputfilter.cpp | 4 ++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 79fa78097..c210f4dc2 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -61,6 +61,11 @@ struct mouseinputdata { static mouseinputdata mousedata; extern MainWindow *main_window; + +#ifdef Q_OS_WINDOWS +HWND rw_hwnd; +#endif + RendererStack::RendererStack(QWidget *parent, int monitor_index) : QStackedWidget(parent) , ui(new Ui::RendererStack) @@ -251,7 +256,9 @@ RendererStack::mouseMoveEvent(QMouseEvent *event) leaveEvent((QEvent *) event); ignoreNextMouseEvent--; } +#if !defined _WIN32 QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2))); +#endif ignoreNextMouseEvent = 2; oldPos = event->pos(); #endif @@ -405,8 +412,15 @@ RendererStack::createRenderer(Renderer renderer) } #endif } - if (current.get() == nullptr) + if (current.get() == nullptr) { +#ifdef Q_OS_WINDOWS + rw_hwnd = NULL; +#endif return; + } +#ifdef Q_OS_WINDOWS + rw_hwnd = (HWND) this->winId(); +#endif current->setFocusPolicy(Qt::NoFocus); current->setFocusProxy(this); current->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 5a6bda852..e54d64269 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "qt_mainwindow.hpp" #include "qt_machinestatus.hpp" @@ -122,6 +123,8 @@ plat_resize(int w, int h, int monitor_index) main_window->resizeContents(w, h); } +extern HWND rw_hwnd; + void plat_mouse_capture(int on) { @@ -129,6 +132,26 @@ plat_mouse_capture(int on) return; main_window->setMouseCapture(on > 0 ? true : false); + +#if defined _WIN32 + if (on) { + QCursor cursor(Qt::BlankCursor); + + QApplication::setOverrideCursor(cursor); + QApplication::changeOverrideCursor(cursor); + + RECT rect; + + GetWindowRect(rw_hwnd, &rect); + + ClipCursor(&rect); + + } else { + ClipCursor(NULL); + + QApplication::restoreOverrideCursor(); + } +#endif } int diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index e94101a77..a62d71920 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -395,7 +395,7 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) mouse_scale(delta_x, delta_y); - HWND wnd = (HWND)window->winId(); + /* HWND wnd = (HWND)window->winId(); RECT rect; @@ -404,5 +404,5 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) int left = rect.left + (rect.right - rect.left) / 2; int top = rect.top + (rect.bottom - rect.top) / 2; - SetCursorPos(left, top); + SetCursorPos(left, top); */ } From 75e76899da86b832e9d6631bf1a5c9a4d4cc1e5b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 21 May 2025 13:43:23 +0200 Subject: [PATCH 0966/1190] S3 911/924 high color: check if rd_mask is not 0 (May 21st, 2025) This fixes wrong colors in certain instances of Windows 95 builds' 911/924 drivers. --- src/video/vid_s3.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 683d2be34..99521f061 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -8042,7 +8042,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.sy = s3->accel.maj_axis_pcnt; if ((s3->bpp == 0) && s3->color_16bit) { - s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask; if (s3->accel.rd_mask_16bit_check) { if ((s3->accel.cur_x_overflow & 0xc00) == 0xc00) s3->accel.start = 1; @@ -8353,7 +8353,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.dest = dstbase + s3->accel.cy * s3->width; if ((s3->bpp == 0) && s3->color_16bit) { - s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask; if (s3->accel.rd_mask_16bit_check) { if (s3->accel.cmd == 0x41b3) { if (frgd_mix == 0) { @@ -8478,9 +8478,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3_cpu_src(s3)) && !(s3->accel.cmd & 0x200)) { s3_log("FIXME: S3 911/924 15/16bpp documentation needed.\n"); } else { - if (!cpu_input && (s3->accel.cur_x & 0x400)) + if (!cpu_input && (s3->accel.cur_x & 0x400)) { + s3_log("No Input.\n"); break; - else if (cpu_input && (s3->accel.cmd == 0x53b3) && (s3->accel.cur_x & 0x400)) + } else if (cpu_input && (s3->accel.cmd == 0x53b3) && (s3->accel.cur_x & 0x400)) break; } } @@ -8756,7 +8757,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy = s3->accel.cur_y & 0xfff; if ((s3->bpp == 0) && s3->color_16bit) { - s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00); + s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask; if (s3->accel.rd_mask_16bit_check) { if (!(clip_r & 0x400)) s3->accel.start = 1; @@ -8805,7 +8806,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width); if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { - pclog("Special BitBLT.\n"); + s3_log("Special BitBLT.\n"); while (1) { if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) { READ(s3->accel.src + s3->accel.cx - s3->accel.minus, src_dat); From 05ac5b62b0364019a7e229f81d05685c0dd9e719 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 21 May 2025 13:45:12 +0200 Subject: [PATCH 0967/1190] Add some forgotten #ifdef. --- src/qt/qt_ui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index e54d64269..6e0b3cfbb 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -123,7 +123,9 @@ plat_resize(int w, int h, int monitor_index) main_window->resizeContents(w, h); } +#if defined _WIN32 extern HWND rw_hwnd; +#endif void plat_mouse_capture(int on) From 07c1bb5534d92694e4441d0e835722711c6c986b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 22 May 2025 00:19:57 +0600 Subject: [PATCH 0968/1190] Fix cursor clipping on Windows --- src/qt/qt_rendererstack.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index c210f4dc2..31cc495b0 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -663,6 +663,14 @@ RendererStack::setFocusRenderer() void RendererStack::onResize(int width, int height) { +#ifdef Q_OS_WINDOWS + if (mouse_capture) { + RECT rect; + if (GetWindowRect((HWND)this->winId(), &rect)) { + ClipCursor(&rect); + } + } +#endif if (rendererWindow) { rendererWindow->r_monitor_index = m_monitor_index; rendererWindow->onResize(width, height); From 455622492bbd1d129938638071f92e8300e4a18e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 21 May 2025 20:49:54 +0200 Subject: [PATCH 0969/1190] All the required fixes - the Dell OptiPlex Gn+ now works correctly. --- src/acpi.c | 8 +- src/chipset/intel_piix.c | 39 +- src/device/kbc_at.c | 381 +++++++++++------- src/device/postcard.c | 54 +++ src/dma.c | 2 +- src/floppy/fdc.c | 25 +- src/include/86box/fdc.h | 1 + src/include/86box/keyboard.h | 4 +- src/include/86box/sio.h | 18 +- src/lpt.c | 4 +- src/machine/m_at_slot1.c | 2 +- src/machine/m_at_slot2.c | 2 +- src/machine/m_at_socket7.c | 13 +- src/machine/m_at_socket8.c | 9 +- src/machine/machine_table.c | 20 +- src/nvr_at.c | 5 +- src/sio/sio_fdc37c93x.c | 2 +- src/sio/sio_pc87307.c | 750 +++++++++++++++++++++++------------ src/sio/sio_pc87309.c | 643 +++++++++++++++++++----------- 19 files changed, 1310 insertions(+), 672 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index e9549adb0..e7a0de53d 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -36,6 +36,7 @@ #include <86box/pit.h> #include <86box/apm.h> #include <86box/acpi.h> +#include <86box/dma.h> #include <86box/machine.h> #include <86box/i2c.h> #include <86box/video.h> @@ -1025,8 +1026,13 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p nvr_reg_write(0x000f, 0xff, dev->nvr); } - if (sus_typ & SUS_RESET_PCI) + if (sus_typ & SUS_RESET_PCI) { + /* DMA is part of the southbridge so it responds to PCI reset. */ + dma_reset(); + dma_set_at(1); + device_reset_all(DEVICE_PCI); + } if (sus_typ & SUS_RESET_CPU) cpu_alt_reset = 0; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index ed9fd9460..b73285f70 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -155,6 +155,7 @@ piix_ide_handlers(piix_t *dev, int bus) uint16_t side; if (bus & 0x01) { + piix_log("Disabling primary IDE...\n"); ide_pri_disable(); if (dev->type == 5) { @@ -170,11 +171,14 @@ piix_ide_handlers(piix_t *dev, int bus) ide_set_side(0, side); } - if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) + if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) { + piix_log("Enabling primary IDE...\n"); ide_pri_enable(); + } } if (bus & 0x02) { + piix_log("Disabling secondary IDE...\n"); ide_sec_disable(); if (dev->type == 5) { @@ -190,8 +194,10 @@ piix_ide_handlers(piix_t *dev, int bus) ide_set_side(1, side); } - if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) + if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) { + piix_log("Enabling secondary IDE...\n"); ide_sec_enable(); + } } } @@ -465,6 +471,13 @@ piix_write(int func, int addr, uint8_t val, void *priv) uint8_t *fregs; uint16_t base; + /* Dell OptiPlex Gn+ shows that register 02:FF is aliased in 01:FF. */ + if ((dev->type == 4) && (func == 1) && (addr == 0xff)) + func = 2; + + if ((func == 1) || (addr == 0xf8) || (addr == 0xf9)) + piix_log("[W] %02X:%02X = %02X\n", func, addr, val); + /* Return on unsupported function. */ if (dev->max_func > 0) { if (func > dev->max_func) @@ -736,6 +749,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) fregs[addr] = val; break; case 0xb0: + if (val & 0x10) + warning("Write %02X to B0\n", val); if (dev->type == 4) fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73); else if (dev->type == 5) @@ -745,6 +760,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) alt_access = !!(val & 0x20); break; case 0xb1: + if (val & 0x18) + warning("Write %02X to B1\n", val); if (dev->type > 3) fregs[addr] = val & 0xdf; break; @@ -923,6 +940,12 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (dev->type > 4) fregs[addr] = val; break; + case 0xf8: + case 0xf9: + /* Undocumented! */ + if (dev->type == 4) + fregs[addr] = val; + break; default: break; } @@ -1169,6 +1192,10 @@ piix_read(int func, int addr, void *priv) uint8_t ret = 0xff; const uint8_t *fregs; + /* Dell OptiPlex Gn+ shows that register 02:FF is aliased in 01:FF. */ + if ((dev->type == 4) && (func == 1) && (addr == 0xff)) + func = 2; + if ((dev->type == 3) && (func == 2) && (dev->max_func == 1) && (addr >= 0x40)) ret = 0x00; @@ -1199,7 +1226,7 @@ piix_reset_hard(piix_t *dev) sff_set_slot(dev->bm[1], dev->pci_slot); sff_set_irq_pin(dev->bm[1], PCI_INTA); - sff_set_irq_line(dev->bm[1], 14); + sff_set_irq_line(dev->bm[1], 15); sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); } @@ -1315,6 +1342,10 @@ piix_reset_hard(piix_t *dev) fregs[0x45] = 0x55; fregs[0x46] = 0x01; } + if (dev->type == 4) { + fregs[0xf8] = 0x30; + fregs[0xf9] = 0x0f; + } if ((dev->type == 1) && (dev->rev == 2)) dev->max_func = 0; /* It starts with IDE disabled, then enables it. */ else @@ -1678,7 +1709,7 @@ const device_t piix4_device = { .name = "Intel 82371AB/EB (PIIX4/PIIX4E)", .internal_name = "piix4", .flags = DEVICE_PCI, - .local = 0x71100004, + .local = 0x71100014, .init = piix_init, .close = piix_close, .reset = piix_reset, diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 58aab476c..78fc32ffd 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -145,6 +145,11 @@ typedef struct atkbc_t { /* Internal FIFO for the purpose of commands with multi-byte output. */ uint8_t key_ctrl_queue[64]; + uint8_t handler_enable[2]; + + uint16_t base_addr[2]; + uint16_t irq[2]; + uint32_t flags; /* Main timers. */ @@ -157,8 +162,13 @@ typedef struct atkbc_t { /* Local copies of the pointers to both ports for easier swapping (AMI '5' MegaKey). */ kbc_at_port_t *ports[2]; - uint8_t (*write60_ven)(void *priv, uint8_t val); - uint8_t (*write64_ven)(void *priv, uint8_t val); + struct { + uint8_t (*read)(uint16_t port, void *priv); + void (*write)(uint16_t port, uint8_t val, void *priv); + } handlers[2]; + + uint8_t (*write_cmd_data_ven)(void *priv, uint8_t val); + uint8_t (*write_cmd_ven)(void *priv, uint8_t val); } atkbc_t; /* Keyboard controller ports. */ @@ -167,8 +177,6 @@ kbc_at_port_t *kbc_at_ports[2] = { NULL, NULL }; static uint8_t kbc_ami_revision = '8'; static uint8_t kbc_award_revision = 0x42; -static uint8_t kbc_handler_set = 0; - static void (*kbc_at_do_poll)(atkbc_t *dev); /* Non-translated to translated scan codes. */ @@ -362,12 +370,19 @@ kbc_do_irq(atkbc_t *dev) if (dev->do_irq) { /* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */ - picint_common(1 << 1, 0, 0, NULL); - picint_common(1 << 12, 0, 0, NULL); - if (dev->channel >= 2) - picint_common(1 << 12, 0, 1, NULL); - else - picint_common(1 << 1, 0, 1, NULL); + if (dev->irq[0] != 0xffff) + picint_common(1 << dev->irq[0], 0, 0, NULL); + + if (dev->irq[1] != 0xffff) + picint_common(1 << dev->irq[1], 0, 0, NULL); + + if (dev->channel >= 2) { + if (dev->irq[1] != 0xffff) + picint_common(1 << dev->irq[1], 0, 1, NULL); + } else { + if (dev->irq[0] != 0xffff) + picint_common(1 << dev->irq[0], 0, 1, NULL); + } dev->do_irq = 0; } @@ -404,7 +419,9 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) } else if (dev->mem[0x20] & 0x01) kbc_set_do_irq(dev, channel); } else if (dev->mem[0x20] & 0x01) - picintlevel(1 << 1, &dev->irq_state); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ + /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ + if (dev->irq[0] != 0xffff) + picintlevel(1 << dev->irq[0], &dev->irq_state); #ifdef WRONG_CONDITION if ((dev->channel > 0) || dev->is_asic || (kbc_ven == KBC_VEN_IBM_PS1) || (kbc_ven == KBC_VEN_IBM)) @@ -784,10 +801,12 @@ write_p2(atkbc_t *dev, uint8_t val) /* PS/2: Handle IRQ's. */ if (dev->misc_flags & FLAG_PS2) { /* IRQ 12 */ - picint_common(1 << 12, 0, val & 0x20, NULL); + if (dev->irq[1] != 0xffff) + picint_common(1 << dev->irq[1], 0, val & 0x20, NULL); /* IRQ 1 */ - picint_common(1 << 1, 0, val & 0x10, NULL); + if (dev->irq[0] != 0xffff) + picint_common(1 << dev->irq[0], 0, val & 0x10, NULL); } #endif @@ -932,7 +951,7 @@ pulse_poll(void *priv) } static uint8_t -write64_generic(void *priv, uint8_t val) +write_cmd_generic(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; uint8_t current_drive; @@ -1161,7 +1180,7 @@ write64_generic(void *priv, uint8_t val) } static uint8_t -write60_ami(void *priv, uint8_t val) +write_cmd_data_ami(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1231,7 +1250,7 @@ kbc_at_set_ps2(void *priv, const uint8_t ps2) } static uint8_t -write64_ami(void *priv, uint8_t val) +write_cmd_ami(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; @@ -1436,11 +1455,11 @@ write64_ami(void *priv, uint8_t val) break; } - return write64_generic(dev, val); + return write_cmd_generic(dev, val); } static uint8_t -write60_phoenix(void *priv, uint8_t val) +write_cmd_data_phoenix(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1513,7 +1532,7 @@ write60_phoenix(void *priv, uint8_t val) } static uint8_t -write64_phoenix(void *priv, uint8_t val) +write_cmd_phoenix(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1659,11 +1678,11 @@ write64_phoenix(void *priv, uint8_t val) break; } - return write64_generic(dev, val); + return write_cmd_generic(dev, val); } static uint8_t -write64_siemens(void *priv, uint8_t val) +write_cmd_siemens(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1692,11 +1711,11 @@ write64_siemens(void *priv, uint8_t val) break; } - return write64_ami(dev, val); + return write_cmd_ami(dev, val); } static uint8_t -write60_quadtel(void *priv, UNUSED(uint8_t val)) +write_cmd_data_quadtel(void *priv, UNUSED(uint8_t val)) { const atkbc_t *dev = (atkbc_t *) priv; @@ -1713,7 +1732,7 @@ write60_quadtel(void *priv, UNUSED(uint8_t val)) } static uint8_t -write64_olivetti(void *priv, uint8_t val) +write_cmd_olivetti(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1734,11 +1753,11 @@ write64_olivetti(void *priv, uint8_t val) break; } - return write64_generic(dev, val); + return write_cmd_generic(dev, val); } static uint8_t -write64_quadtel(void *priv, uint8_t val) +write_cmd_quadtel(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1757,11 +1776,11 @@ write64_quadtel(void *priv, uint8_t val) break; } - return write64_generic(dev, val); + return write_cmd_generic(dev, val); } static uint8_t -write60_toshiba(void *priv, uint8_t val) +write_cmd_data_toshiba(void *priv, uint8_t val) { const atkbc_t *dev = (atkbc_t *) priv; @@ -1779,7 +1798,7 @@ write60_toshiba(void *priv, uint8_t val) } static uint8_t -write64_toshiba(void *priv, uint8_t val) +write_cmd_toshiba(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; @@ -1868,7 +1887,7 @@ write64_toshiba(void *priv, uint8_t val) break; } - return write64_generic(dev, val); + return write_cmd_generic(dev, val); } static void @@ -1912,8 +1931,10 @@ kbc_at_process_cmd(void *priv) /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ dev->p1 = dev->p1 & 0xff; write_p2(dev, 0x4b); - picintc(0x1000); - picintc(0x0002); + if (dev->irq[1] != 0xffff) + picintc(1 << dev->irq[1]); + if (dev->irq[0] != 0xffff) + picintc(1 << dev->irq[0]); } dev->status = (dev->status & 0x0f) | 0x60; @@ -1932,7 +1953,8 @@ kbc_at_process_cmd(void *priv) /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ dev->p1 = dev->p1 & 0xff; write_p2(dev, 0xcf); - picintclevel(0x0002, &dev->irq_state); + if (dev->irq[0] != 0xffff) + picintclevel(1 << dev->irq[0], &dev->irq_state); dev->irq_state = 0; } @@ -2047,8 +2069,8 @@ kbc_at_process_cmd(void *priv) * that. Otherwise, or if that handler fails, * log a bad command. */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, dev->ib); + if (dev->write_cmd_ven) + bad = dev->write_cmd_ven(dev, dev->ib); kbc_at_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib); } @@ -2134,8 +2156,8 @@ kbc_at_process_cmd(void *priv) * it returns an error, log a bad * controller command. */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, dev->ib); + if (dev->write_cmd_data_ven) + bad = dev->write_cmd_data_ven(dev, dev->ib); if (bad) { kbc_at_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib); @@ -2145,7 +2167,7 @@ kbc_at_process_cmd(void *priv) } static void -kbc_at_write(uint16_t port, uint8_t val, void *priv) +kbc_at_port_1_write(uint16_t port, uint8_t val, void *priv) { atkbc_t *dev = (atkbc_t *) priv; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; @@ -2153,83 +2175,89 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val); - switch (port) { - case 0x60: - dev->status &= ~STAT_CD; - if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) { - kbc_at_log("ATkbc: write P2\n"); + dev->status &= ~STAT_CD; - /* Fast A20 - ignore all other bits. */ - write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02)); + if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) { + kbc_at_log("ATkbc: write P2\n"); - dev->wantdata = 0; - dev->state = STATE_MAIN_IBF; + /* Fast A20 - ignore all other bits. */ + write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02)); - /* - Explicitly clear IBF so that any preceding - command is not executed. - */ - dev->status &= ~STAT_IFULL; - return; - } - break; + dev->wantdata = 0; + dev->state = STATE_MAIN_IBF; - case 0x64: - dev->status |= STAT_CD; - if (fast_a20 && (val == 0xd1)) { - kbc_at_log("ATkbc: write P2\n"); - dev->wantdata = 1; - dev->state = STATE_KBC_PARAM; - dev->command = 0xd1; + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } - /* - Explicitly clear IBF so that any preceding - command is not executed. - */ - dev->status &= ~STAT_IFULL; - return; - } else if (fast_reset && ((val & 0xf0) == 0xf0)) { - pulse_output(dev, val & 0x0f); + dev->ib = val; + dev->status |= STAT_IFULL; +} - dev->state = STATE_MAIN_IBF; +static void +kbc_at_port_2_write(uint16_t port, uint8_t val, void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t fast_a20 = (kbc_ven != KBC_VEN_SIEMENS); - /* - Explicitly clear IBF so that any preceding - command is not executed. - */ - dev->status &= ~STAT_IFULL; - return; - } else if (val == 0xad) { - /* Fast track it because of the Bochs BIOS. */ - kbc_at_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); + kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val); - dev->state = STATE_MAIN_IBF; + dev->status |= STAT_CD; - /* - Explicitly clear IBF so that any preceding - command is not executed. - */ - dev->status &= ~STAT_IFULL; - return; - } else if (val == 0xae) { - /* Fast track it because of the LG MultiNet. */ - kbc_at_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); + if (fast_a20 && (val == 0xd1)) { + kbc_at_log("ATkbc: write P2\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + dev->command = 0xd1; - dev->state = STATE_MAIN_IBF; + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } else if (fast_reset && ((val & 0xf0) == 0xf0)) { + pulse_output(dev, val & 0x0f); - /* - Explicitly clear IBF so that any preceding - command is not executed. - */ - dev->status &= ~STAT_IFULL; - return; - } - break; + dev->state = STATE_MAIN_IBF; - default: - break; + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } else if (val == 0xad) { + /* Fast track it because of the Bochs BIOS. */ + kbc_at_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + + dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } else if (val == 0xae) { + /* Fast track it because of the LG MultiNet. */ + kbc_at_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + + dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; } dev->ib = val; @@ -2237,7 +2265,7 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) } static uint8_t -kbc_at_read(uint16_t port, void *priv) +kbc_at_port_1_read(uint16_t port, void *priv) { atkbc_t *dev = (atkbc_t *) priv; uint8_t ret = 0xff; @@ -2245,26 +2273,32 @@ kbc_at_read(uint16_t port, void *priv) if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) cycles -= ISA_CYCLES(8); - switch (port) { - case 0x60: - ret = dev->ob; - dev->status &= ~STAT_OFULL; - /* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit. - This also means that in AT mode, the IRQ is level-triggered. */ - if (!(dev->misc_flags & FLAG_PS2)) - picintclevel(1 << 1, &dev->irq_state); - if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1)) - cpu_override_dynarec = 0; - break; + ret = dev->ob; + dev->status &= ~STAT_OFULL; + /* + TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit. + This also means that in AT mode, the IRQ is level-triggered. + */ + if (!(dev->misc_flags & FLAG_PS2) && (dev->irq[0] != 0xffff)) + picintclevel(1 << dev->irq[0], &dev->irq_state); + if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1)) + cpu_override_dynarec = 0; - case 0x64: - ret = dev->status; - break; + kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret); - default: - kbc_at_log("ATkbc: read(%04x) invalid!\n",port); - break; - } + return ret; +} + +static uint8_t +kbc_at_port_2_read(uint16_t port, void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 0xff; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) + cycles -= ISA_CYCLES(8); + + ret = dev->status; kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret); @@ -2303,11 +2337,14 @@ kbc_at_reset(void *priv) if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { dev->misc_flags |= FLAG_PS2; kbc_at_do_poll = kbc_at_poll_ps2; - picintc(0x1000); - picintc(0x0002); + if (dev->irq[1] != 0xffff) + picintc(1 << dev->irq[1]); + if (dev->irq[0] != 0xffff) + picintc(1 << dev->irq[0]); } else { kbc_at_do_poll = kbc_at_poll_at; - picintclevel(0x0002, &dev->irq_state); + if (dev->irq[0] != 0xffff) + picintclevel(1 << dev->irq[0], &dev->irq_state); dev->irq_state = 0; } @@ -2350,21 +2387,52 @@ kbc_at_close(void *priv) } void -kbc_at_handler(int set, void *priv) +kbc_at_port_handler(int num, int set, uint16_t port, void *priv) { - if (kbc_handler_set) { - io_removehandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); - io_removehandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); + atkbc_t *dev = (atkbc_t *) priv; + + if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000)) { + pclog("Disabling keyboard controller port %i at %04X...\n", num, dev->base_addr[num]); + + io_removehandler(dev->base_addr[num], 1, + dev->handlers[num].read, NULL, NULL, + dev->handlers[num].write, NULL, NULL, priv); } - kbc_handler_set = set; + dev->handler_enable[num] = set; + dev->base_addr[num] = port; - if (kbc_handler_set) { - io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); - io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); + if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000)) { + pclog("Enabling keyboard controller port %i at %04X...\n", num, dev->base_addr[num]); + + io_sethandler(dev->base_addr[num], 1, + dev->handlers[num].read, NULL, NULL, + dev->handlers[num].write, NULL, NULL, priv); } } +void +kbc_at_handler(int set, uint16_t port, void *priv) +{ + kbc_at_port_handler(0, set, port, priv); + kbc_at_port_handler(1, set, port + 0x0004, priv); +} + +void +kbc_at_set_irq(int num, uint16_t irq, void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + + if (dev->irq[num] != 0xffff) { + if ((num == 0) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1)) + picintclevel(1 << dev->irq[num], &dev->irq_state); + else + picintc(1 << dev->irq[num]); + } + + dev->irq[num] = irq; +} + static void * kbc_at_init(const device_t *info) { @@ -2383,16 +2451,21 @@ kbc_at_init(const device_t *info) if (info->flags & DEVICE_PCI) dev->misc_flags |= FLAG_PCI; - kbc_handler_set = 0; - kbc_at_handler(1, dev); + dev->handlers[0].read = kbc_at_port_1_read; + dev->handlers[0].write = kbc_at_port_1_write; + dev->handlers[1].read = kbc_at_port_2_read; + dev->handlers[1].write = kbc_at_port_2_write; + + dev->irq[0] = 1; + dev->irq[1] = 12; timer_add(&dev->kbc_poll_timer, kbc_at_poll, dev, 1); timer_add(&dev->pulse_cb, pulse_poll, dev, 0); timer_add(&dev->kbc_dev_poll_timer, kbc_at_dev_poll, dev, 1); - dev->write60_ven = NULL; - dev->write64_ven = NULL; + dev->write_cmd_data_ven = NULL; + dev->write_cmd_ven = NULL; kbc_ami_revision = '8'; kbc_award_revision = 0x42; @@ -2401,8 +2474,8 @@ kbc_at_init(const device_t *info) case KBC_VEN_SIEMENS: kbc_ami_revision = '8'; kbc_award_revision = 0x42; - dev->write60_ven = write60_ami; - dev->write64_ven = write64_siemens; + dev->write_cmd_data_ven = write_cmd_data_ami; + dev->write_cmd_ven = write_cmd_siemens; break; case KBC_VEN_ACER: @@ -2411,24 +2484,24 @@ kbc_at_init(const device_t *info) case KBC_VEN_IBM_PS1: case KBC_VEN_IBM: case KBC_VEN_COMPAQ: - dev->write64_ven = write64_generic; + dev->write_cmd_ven = write_cmd_generic; break; case KBC_VEN_OLIVETTI: - dev->write64_ven = write64_olivetti; + dev->write_cmd_ven = write_cmd_olivetti; break; case KBC_VEN_ALI: kbc_ami_revision = 'F'; kbc_award_revision = 0x43; - dev->write60_ven = write60_ami; - dev->write64_ven = write64_ami; + dev->write_cmd_data_ven = write_cmd_data_ami; + dev->write_cmd_ven = write_cmd_ami; break; case KBC_VEN_TRIGEM_AMI: kbc_ami_revision = 'Z'; - dev->write60_ven = write60_ami; - dev->write64_ven = write64_ami; + dev->write_cmd_data_ven = write_cmd_data_ami; + dev->write_cmd_ven = write_cmd_ami; break; case KBC_VEN_AMI: @@ -2451,23 +2524,23 @@ kbc_at_init(const device_t *info) else kbc_ami_revision = 'F'; - dev->write60_ven = write60_ami; - dev->write64_ven = write64_ami; + dev->write_cmd_data_ven = write_cmd_data_ami; + dev->write_cmd_ven = write_cmd_ami; break; case KBC_VEN_PHOENIX: - dev->write60_ven = write60_phoenix; - dev->write64_ven = write64_phoenix; + dev->write_cmd_data_ven = write_cmd_data_phoenix; + dev->write_cmd_ven = write_cmd_phoenix; break; case KBC_VEN_QUADTEL: - dev->write60_ven = write60_quadtel; - dev->write64_ven = write64_quadtel; + dev->write_cmd_data_ven = write_cmd_data_quadtel; + dev->write_cmd_ven = write_cmd_quadtel; break; case KBC_VEN_TOSHIBA: - dev->write60_ven = write60_toshiba; - dev->write64_ven = write64_toshiba; + dev->write_cmd_data_ven = write_cmd_data_toshiba; + dev->write_cmd_ven = write_cmd_toshiba; break; default: @@ -2493,6 +2566,8 @@ kbc_at_init(const device_t *info) fast_reset = 0x00; + kbc_at_handler(1, 0x0060, dev); + return dev; } diff --git a/src/device/postcard.c b/src/device/postcard.c index 95a4df646..058684c0b 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -30,11 +30,13 @@ #include "cpu.h" uint8_t postcard_codes[POSTCARDS_NUM]; +char postcard_diags[5] = { 0 }; static uint16_t postcard_port; static uint8_t postcard_written[POSTCARDS_NUM]; static uint8_t postcard_ports_num = 1; static uint8_t postcard_prev_codes[POSTCARDS_NUM]; +static char postcard_prev_diags[5] = { 0 }; #define UISTR_LEN 32 static char postcard_str[UISTR_LEN]; /* UI output string */ @@ -97,6 +99,22 @@ postcard_setui(void) ps[1][0], ps[1][1], ps[1][2], ps[1][3]); break; } + } else if (strstr(machines[machine].name, " Dell ")) { + char dell_diags[10] = { 0 }; + + if (!postcard_written[1]) + snprintf(dell_diags, sizeof(dell_diags), "---- ----"); + else if (postcard_written[1] == 1) + snprintf(dell_diags, sizeof(dell_diags), "%s ----", postcard_diags); + else + snprintf(dell_diags, sizeof(dell_diags), "%s %s", postcard_diags, postcard_prev_diags); + + if (!postcard_written[0]) + snprintf(postcard_str, sizeof(postcard_str), "POST: -- -- %s", dell_diags); + else if (postcard_written[0] == 1) + snprintf(postcard_str, sizeof(postcard_str), "POST: %02X -- %s", postcard_codes[0], dell_diags); + else + snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X %s", postcard_codes[0], postcard_prev_codes[0], dell_diags); } else { if (!postcard_written[0]) snprintf(postcard_str, sizeof(postcard_str), "POST: -- --"); @@ -122,6 +140,9 @@ postcard_reset(void) memset(postcard_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t)); memset(postcard_prev_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t)); + memset(postcard_diags, 0x00, 5 * sizeof(char)); + memset(postcard_prev_diags, 0x00, 5 * sizeof(char)); + postcard_setui(); } @@ -140,6 +161,35 @@ postcard_write(uint16_t port, uint8_t val, UNUSED(void *priv)) postcard_setui(); } +static int +postcard_cmp_diags(uint32_t val) +{ + int ret = 0; + char *pv = (char *) &val; + + for (int i = 0; i < 4; i++) + ret = ret || (pv[i] != postcard_diags[3 - i]); + + return ret; +} + +static void +postcard_writel(uint16_t port, uint32_t val, UNUSED(void *priv)) +{ + char *pv = (char *) &val; + + if (postcard_written[1] && !postcard_cmp_diags(val)) + return; + + *(uint32_t *) postcard_prev_diags = *(uint32_t *) postcard_diags; + for (int i = 0; i < 4; i++) + postcard_diags[i] = pv[3 - i]; + if (postcard_written[1] < 2) + postcard_written[1]++; + + postcard_setui(); +} + static void * postcard_init(UNUSED(const device_t *info)) { @@ -173,6 +223,10 @@ postcard_init(UNUSED(const device_t *info)) io_sethandler(postcard_port, postcard_ports_num, NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); + if (strstr(machines[machine].name, " Dell ")) + io_sethandler(0x00e0, 0x0001, + NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL); + return postcard_write; } diff --git a/src/dma.c b/src/dma.c index 4edeb39f8..2265947b9 100644 --- a/src/dma.c +++ b/src/dma.c @@ -856,7 +856,7 @@ dma16_read(uint16_t addr, UNUSED(void *priv)) break; } - dma_log("dma16_read(%08X) = %02X\n", port, ret); + dma_log("dma16_read(%08X) = %02X\n", addr, ret); return ret; } diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index cf5ae41bf..ebc16cbfd 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -377,6 +377,15 @@ fdc_set_power_down(fdc_t *fdc, uint8_t power_down) fdc->power_down = power_down; } +void +fdc_toggle_flag(fdc_t *fdc, int flag, int on) +{ + if (on) + fdc->flags |= flag; + else + fdc->flags &= ~flag; +} + void fdc_update_max_track(fdc_t *fdc, int max_track) { @@ -1484,7 +1493,7 @@ fdc_read(uint16_t addr, void *priv) fdc->step = 0; break; default: - ret = 0xFF; + ret = 0xff; } fdc_log("[%04X:%08X] Read FDC %04X %02X [%i:%02X]\n", CS, cpu_state.pc, addr, ret, drive, fdc->dor & (0x10 << drive)); return ret; @@ -2235,9 +2244,13 @@ fdc_set_base(fdc_t *fdc, int base) { int super_io = (fdc->flags & FDC_FLAG_SUPERIO); + if (base == 0x0000) { + fdc->base_address = base; + return; + } + if (fdc->flags & FDC_FLAG_NSC) { - io_sethandler(base + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_sethandler(base + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_sethandler(base + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } else { if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { @@ -2266,10 +2279,12 @@ fdc_remove(fdc_t *fdc) { int super_io = (fdc->flags & FDC_FLAG_SUPERIO); + if (fdc->base_address == 0x0000) + return; + fdc_log("FDC Removed (%04X)\n", fdc->base_address); if (fdc->flags & FDC_FLAG_NSC) { - io_removehandler(fdc->base_address + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } else { if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 53511daac..c98a03f67 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -183,6 +183,7 @@ extern uint8_t fdc_get_densel_polarity(fdc_t *fdc); extern void fdc_update_densel_force(fdc_t *fdc, int densel_force); extern void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate); extern void fdc_update_drv2en(fdc_t *fdc, int drv2en); +extern void fdc_toggle_flag(fdc_t *fdc, int flag, int on); extern void fdc_noidam(fdc_t *fdc); extern void fdc_nosector(fdc_t *fdc); diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 9dfb1c8e4..b9bac0821 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -289,7 +289,9 @@ extern uint8_t kbc_at_read_p(void *priv, uint8_t port, uint8_t mask); extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t val); extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); -extern void kbc_at_handler(int set, void *priv); +extern void kbc_at_port_handler(int num, int set, uint16_t port, void *priv); +extern void kbc_at_handler(int set, uint16_t port, void *priv); +extern void kbc_at_set_irq(int num, uint16_t irq, void *priv); extern void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main); extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 06bf57f8f..358cd8c9a 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -92,13 +92,23 @@ extern const device_t pc87332_398_ide_device; extern const device_t pc87332_398_ide_sec_device; extern const device_t pc87332_398_ide_fdcon_device; +#define PCX7307_PC87307 0x00c0 +#define PCX7307_PC97307 0x00cf + +#define PC87309_PC87309 0x00e0 + +#define PCX730X_CHIP_ID 0x00ff + +#define PCX730X_AMI 0x0200 /* AMI '5' Megakey KBC firmware. */ +#define PCX730X_PHOENIX_42 0x0500 /* Phoenix Multikey/42 1.37 KBC firmware. */ +#define PCX730X_PHOENIX_42I 0x0700 /* Phoenix Multikey/42i 4.16 KBC firmware. */ +#define PCX730X_KBC 0x0f00 + +#define PCX730X_15C 0x2000 + extern const device_t pc87307_device; -extern const device_t pc87307_15c_device; -extern const device_t pc87307_both_device; -extern const device_t pc97307_device; extern const device_t pc87309_device; -extern const device_t pc87309_15c_device; /* LG Prime */ extern const device_t prime3b_device; diff --git a/src/lpt.c b/src/lpt.c index 26174d96b..072f4a34c 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -229,9 +229,9 @@ void lpt_port_setup(int i, uint16_t port) { if (lpt_ports[i].enabled) { - if (lpt_ports[i].addr != 0xffff) + if ((lpt_ports[i].addr != 0xffff) && (lpt_ports[i].addr != 0x0000)) io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - if (port != 0xffff) + if ((port != 0xffff) && (port != 0x0000)) io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); lpt_ports[i].addr = port; } else diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index b2f05d33e..773826316 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -584,7 +584,7 @@ machine_at_s1846_init(const machine_t *model) pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440bx_device); device_add(&piix4e_device); - device_add(&pc87309_device); + device_add_params(&pc87309_device, (void *) (PCX730X_AMI | PC87309_PC87309)); device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); diff --git a/src/machine/m_at_slot2.c b/src/machine/m_at_slot2.c index da160c138..37c0acdfd 100644 --- a/src/machine/m_at_slot2.c +++ b/src/machine/m_at_slot2.c @@ -141,7 +141,7 @@ machine_at_fw6400gx_init(const machine_t *model) device_add(&i440gx_device); device_add(&piix4e_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87309_15c_device); + device_add_params(&pc87309_device, (void *) (PCX730X_15C | PCX730X_AMI | PC87309_PC87309)); device_add(ics9xxx_get(ICS9250_08)); device_add(&sst_flash_29ee020_device); spd_register(SPD_TYPE_SDRAM, 0xF, 512); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 17c89e39d..9ceebe2e0 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -984,19 +984,21 @@ machine_at_optiplex_gn_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */ - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */ pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); /* 3C905, not yet emulated */ pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430tx_device); device_add(&piix4_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87307_15c_device); + device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); @@ -1040,8 +1042,7 @@ machine_at_an430tx_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i430tx_device); device_add(&piix4_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87307_both_device); + device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42I | PCX7307_PC97307)); device_add(&intel_flash_bxt_ami_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 006e0f419..aabfb9b4f 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -250,8 +250,7 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_intel_ami_pci_device); - device_add(&pc87307_device); + device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307)); device_add(&intel_flash_bxt_ami_device); @@ -287,8 +286,7 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_intel_ami_pci_device); - device_add(&pc87307_device); + device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307)); device_add(&intel_flash_bxt_ami_device); @@ -324,8 +322,7 @@ machine_at_ap440fx_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87307_device); + device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307)); device_add(&intel_flash_bxt_ami_device); if (sound_card_current[0] == SOUND_INTERNAL) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f28079888..f16f4e5ae 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13103,11 +13103,15 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* According to Dell specifications, it can have either National Semiconductor PC87307 or PC87309 - Super I/O. All known instances have the former, although other similar Dells of the era have - pinouts for accompanying either so this likely also does. + /* + According to Dell specifications, it can have either National Semiconductor + PC87307 or PC87309 Super I/O. All known instances have the former, although + other similar Dells of the era have pinouts for accompanying either so this + likely also does. - The KBC is likely an AMIKey-2 clone. */ + The KBC is either an AMI '5' MegaKey, Phoenix MultiKey/42 1.37, or Phoenix + MultiKey/42i 4.16. + */ { .name = "[i430TX] Dell OptiPlex GN+", .internal_name = "optiplex_gn", @@ -13129,7 +13133,8 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO, /* Video: S3 86C785 (Trio64V2/GX), ethernet: 3C905 */ + /* Video: S3 86C785 (Trio64V2/GX), ethernet: 3C905. */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO | MACHINE_SOUND, .ram = { .min = 8192, .max = 262144, @@ -13143,8 +13148,9 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &s3_trio64v2_dx_onboard_pci_device, /* Stop-gap measure until the Trio64V2/GX is emulated, as both use the same VBIOS */ - .snd_device = NULL, + /* Stop-gap measure until the Trio64V2/GX is emulated, as both use the same VBIOS. */ + .vid_device = &s3_trio64v2_dx_onboard_pci_device, + .snd_device = &sb_vibra16xv_onboard_device, .net_device = NULL }, /* [TEST] Has AMI Megakey '5' KBC firmware on the SM(S)C FDC37C67x Super I/O chip. */ diff --git a/src/nvr_at.c b/src/nvr_at.c index 2acfa47a4..4deda98be 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -1107,9 +1107,10 @@ nvr_at_init(const device_t *info) case 1: /* standard AT */ case 5: /* AMI WinBIOS 1994 */ case 6: /* AMI BIOS 1995 */ - if ((info->local & 0x1f) == 0x11) + if ((info->local & 0x1f) == 0x11) { local->flags |= FLAG_PIIX4; - else { + local->def = 0x00; + } else { local->def = 0x00; if ((info->local & 0x1f) == 0x15) local->flags |= FLAG_AMI_1994_HACK; diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index ebc500c96..dce5b11dc 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -894,7 +894,7 @@ fdc37c93x_kbc_handler(fdc37c93x_t *dev) dev->kbc_base = local_enable ? 0x0060 : 0x0000; if (dev->kbc_base != old_base) - kbc_at_handler(local_enable, dev->kbc); + kbc_at_handler(local_enable, dev->kbc_base, dev->kbc); } static void diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index ae21d34af..7bc9bb441 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -8,11 +8,9 @@ * * Emulation of the NatSemi PC87307 Super I/O chip. * - * - * * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020-2025 Miran Grca. */ #include #include @@ -24,45 +22,89 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/lpt.h> +#include <86box/machine.h> #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> #include <86box/rom.h> #include <86box/serial.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/keyboard.h> #include <86box/sio.h> #include <86box/plat_fallthrough.h> +#include "cpu.h" typedef struct pc87307_t { uint8_t id; + uint8_t baddr; uint8_t pm_idx; uint8_t regs[48]; uint8_t ld_regs[256][208]; uint8_t pcregs[16]; - uint8_t gpio[2][4]; + uint8_t gpio[2][8]; uint8_t pm[8]; + uint16_t superio_base; uint16_t gpio_base; uint16_t gpio_base2; uint16_t pm_base; int cur_reg; + void *kbc; fdc_t *fdc; serial_t *uart[2]; } pc87307_t; -static void fdc_handler(pc87307_t *dev); -static void lpt1_handler(pc87307_t *dev); -static void serial_handler(pc87307_t *dev, int uart); +enum { + LD_KBD = 0, + LD_MOUSE, + LD_RTC, + LD_FDC, + LD_LPT, + LD_UART2, + LD_UART1, + LD_GPIO, + LD_PM +} pc87307_ld_t; + +#define LD_MIN LD_KBD +#define LD_MAX LD_PM + +static void fdc_handler(pc87307_t *dev); +static void lpt1_handler(pc87307_t *dev); +static void serial_handler(pc87307_t *dev, int uart); +static void kbc_handler(pc87307_t *dev); +static void pc87307_write(uint16_t port, uint8_t val, void *priv); +static uint8_t pc87307_read(uint16_t port, void *priv); + +#ifdef ENABLE_PC87307_LOG +int pc87307_do_log = ENABLE_PC87307_LOG; + +static void +pc87307_log(const char *fmt, ...) +{ + va_list ap; + + if (pc87307_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define pc87307_log(fmt, ...) +#endif static void pc87307_gpio_write(uint16_t port, uint8_t val, void *priv) { pc87307_t *dev = (pc87307_t *) priv; - uint8_t bank = ((port & 0xfffc) == dev->gpio_base2); + uint8_t bank = !!(dev->regs[0x22] & 0x80); - dev->gpio[bank][port & 3] = val; + /* Bit 7 of SCNF2 = bank. */ + pc87307_log("[%04X:%08X] [W] (%04X) Bank %i = %02X\n", + CS, cpu_state.pc, port, bank, val); + + dev->gpio[bank][port & 0x0007] = val; } uint8_t @@ -70,20 +112,36 @@ pc87307_gpio_read(uint16_t port, void *priv) { const pc87307_t *dev = (pc87307_t *) priv; uint8_t pins = 0xff; - uint8_t bank = ((port & 0xfffc) == dev->gpio_base2); - uint8_t mask; - uint8_t ret = dev->gpio[bank][port & 0x0003]; + uint8_t bank = !!(dev->regs[0x22] & 0x80); + uint8_t ret = dev->gpio[bank][port & 0x0007]; switch (port & 0x0003) { case 0x0000: - mask = dev->gpio[bank][0x0001]; - ret = (ret & mask) | (pins & ~mask); + if (bank == 0) { + uint8_t mask = dev->gpio[0][1]; + pins = 0x7f; + ret = (ret & mask) | (pins & ~mask); + } + break; + case 0x0004: + if (bank == 0) { + uint8_t mask = dev->gpio[0][5]; + pins = 0xfb; + ret = (ret & mask) | (pins & ~mask); + } else + ret = 0xff; break; default: + if (bank == 1) + ret = 0xff; break; } + /* Bit 7 of SCNF2 = bank. */ + pc87307_log("[%04X:%08X] [R] (%04X) Bank %i = %02X\n", + CS, cpu_state.pc, port, bank, ret); + return ret; } @@ -123,6 +181,7 @@ pc87307_pm_write(uint16_t port, uint8_t val, void *priv) dev->pm[dev->pm_idx] = val; else { dev->pm_idx = val & 0x07; + switch (dev->pm_idx) { case 0x00: fdc_handler(dev); @@ -167,20 +226,49 @@ pc87307_pm_init(pc87307_t *dev, uint16_t addr) pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); } +static void +kbc_handler(pc87307_t *dev) +{ + uint8_t active = (dev->ld_regs[LD_KBD][0x00] & 0x01) && + (dev->pm[0x00] & 0x01); + uint8_t active_2 = dev->ld_regs[LD_MOUSE][0x00] & 0x01; + uint8_t irq = (dev->ld_regs[LD_KBD][0x40] & 0x0f); + uint8_t irq_2 = (dev->ld_regs[LD_MOUSE][0x40] & 0x0f); + uint16_t addr = (dev->ld_regs[LD_KBD][0x30] << 8) | + dev->ld_regs[LD_KBD][0x31]; + uint16_t addr_2 = (dev->ld_regs[LD_KBD][0x32] << 8) | + dev->ld_regs[LD_KBD][0x33]; + + pc87307_log("%02X, %02X, %02X, %02X, %04X, %04X\n", + active, active_2, irq, irq_2, addr, addr_2); + + if (addr <= 0xfff8) { + pc87307_log("Enabling KBC #1 on %04X...\n", addr); + kbc_at_port_handler(0, active, addr, dev->kbc); + } + + if (addr_2 <= 0xfff8) { + pc87307_log("Enabling KBC #2 on %04X...\n", addr_2); + kbc_at_port_handler(1, active, addr_2, dev->kbc); + } + + kbc_at_set_irq(0, active ? irq : 0xffff, dev->kbc); + kbc_at_set_irq(1, (active && active_2) ? irq_2 : 0xffff, dev->kbc); +} + static void fdc_handler(pc87307_t *dev) { - uint8_t irq; - uint8_t active; - uint16_t addr; - fdc_remove(dev->fdc); - active = (dev->ld_regs[0x03][0x00] & 0x01) && (dev->pm[0x00] & 0x08); - addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002; - irq = (dev->ld_regs[0x03][0x40] & 0x0f); + uint8_t active = (dev->ld_regs[LD_FDC][0x00] & 0x01) && + (dev->pm[0x00] & 0x08); + uint8_t irq = (dev->ld_regs[LD_FDC][0x40] & 0x0f); + uint16_t addr = ((dev->ld_regs[LD_FDC][0x30] << 8) | + dev->ld_regs[LD_FDC][0x31]) & 0xfff8; if (active && (addr <= 0xfff8)) { + pc87307_log("Enabling FDC on %04X, IRQ %i...\n", addr, irq); fdc_set_base(dev->fdc, addr); fdc_set_irq(dev->fdc, irq); } @@ -189,268 +277,405 @@ fdc_handler(pc87307_t *dev) static void lpt1_handler(pc87307_t *dev) { - uint8_t irq; - uint8_t active; - uint16_t addr; - - lpt1_remove(); - - active = (dev->ld_regs[0x04][0x00] & 0x01) && (dev->pm[0x00] & 0x10); - addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; - irq = (dev->ld_regs[0x04][0x40] & 0x0f); + uint8_t active = (dev->ld_regs[LD_LPT][0x00] & 0x01) && + (dev->pm[0x00] & 0x10); + uint8_t irq = (dev->ld_regs[LD_LPT][0x40] & 0x0f); + uint16_t addr = (dev->ld_regs[LD_LPT][0x30] << 8) | + dev->ld_regs[LD_LPT][0x31]; if (active && (addr <= 0xfffc)) { + pc87307_log("Enabling LPT1 on %04X...\n", addr); lpt1_setup(addr); - lpt1_irq(irq); - } + } else + lpt1_setup(0xffff); + + lpt1_irq(irq); } static void serial_handler(pc87307_t *dev, int uart) { - uint8_t irq; - uint8_t active; - uint16_t addr; - serial_remove(dev->uart[uart]); - active = (dev->ld_regs[0x06 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart))); - addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31]; - irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f); + uint8_t active = (dev->ld_regs[LD_UART1 - uart][0x00] & 0x01) && + (dev->pm[0x00] & (1 << (6 - uart))); + uint8_t irq = (dev->ld_regs[LD_UART1 - uart][0x40] & 0x0f); + uint16_t addr = (dev->ld_regs[LD_UART1 - uart][0x30] << 8) | + dev->ld_regs[LD_UART1 - uart][0x31]; - if (active && (addr <= 0xfff8)) + if (active && (addr <= 0xfff8)) { + pc87307_log("Enabling COM%i on %04X...\n", uart + 1, addr); serial_setup(dev->uart[uart], addr, irq); + } else + serial_setup(dev->uart[uart], 0x0000, irq); } static void gpio_handler(pc87307_t *dev) { - uint8_t active; - uint16_t addr; - pc87307_gpio_remove(dev); - active = (dev->ld_regs[0x07][0x00] & 0x01); - addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31]; + uint8_t active = (dev->ld_regs[LD_GPIO][0x00] & 0x01); + uint16_t addr = (dev->ld_regs[LD_GPIO][0x30] << 8) | + dev->ld_regs[LD_GPIO][0x31]; + uint16_t addr_2 = (dev->ld_regs[LD_GPIO][0x32] << 8) | + dev->ld_regs[LD_GPIO][0x33]; - if (active) + if (active) { + pc87307_log("Enabling GPIO #1 on %04X...\n", addr); pc87307_gpio_init(dev, 0, addr); - - addr = (dev->ld_regs[0x07][0x32] << 8) | dev->ld_regs[0x07][0x33]; - - if (active) - pc87307_gpio_init(dev, 1, addr); + pc87307_log("Enabling GPIO #2 on %04X...\n", addr_2); + pc87307_gpio_init(dev, 1, addr_2); + } } static void pm_handler(pc87307_t *dev) { - uint8_t active; - uint16_t addr; - pc87307_pm_remove(dev); - active = (dev->ld_regs[0x08][0x00] & 0x01); - addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31]; + uint8_t active = (dev->ld_regs[LD_PM][0x00] & 0x01); + uint16_t addr = (dev->ld_regs[LD_PM][0x30] << 8) | + dev->ld_regs[LD_PM][0x31]; - if (active) + if (active) { + pc87307_log("Enabling power management on %04X...\n", addr); pc87307_pm_init(dev, addr); + } +} + +static void +superio_handler(pc87307_t *dev) +{ + if (dev->superio_base != 0x0000) + io_removehandler(dev->superio_base, 0x0002, + pc87307_read, NULL, NULL, + pc87307_write, NULL, NULL, dev); + + switch (dev->regs[0x22] & 0x03) { + default: + dev->superio_base = 0x0000; + break; case 0x02: + dev->superio_base = 0x015c; + break; + case 0x03: + dev->superio_base = 0x002e; + break; + } + + if (dev->superio_base != 0x0000) { + pc87307_log("Enabling Super I/O on %04X...\n", dev->superio_base); + io_sethandler(dev->superio_base, 0x0002, + pc87307_read, NULL, NULL, + pc87307_write, NULL, NULL, dev); + } } static void pc87307_write(uint16_t port, uint8_t val, void *priv) { - pc87307_t *dev = (pc87307_t *) priv; - uint8_t index; - - index = (port & 1) ? 0 : 1; + pc87307_t *dev = (pc87307_t *) priv; + uint8_t ld = dev->regs[0x07]; + uint8_t reg = dev->cur_reg - 0x30; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t old = dev->regs[dev->cur_reg]; if (index) { dev->cur_reg = val; return; } else { +#ifdef ENABLE_PC87307_LOG + if (dev->cur_reg >= 0x30) + pc87307_log("[%04X:%08X] [W] (%04X) %02X:%02X = %02X\n", + CS, cpu_state.pc, port, ld, dev->cur_reg, val); + else + pc87307_log("[%04X:%08X] [W] (%04X) %02X = %02X\n", + CS, cpu_state.pc, port, dev->cur_reg, val); +#endif switch (dev->cur_reg) { case 0x00: - case 0x02: - case 0x03: - case 0x06: - case 0x07: - case 0x21: + case 0x02: case 0x03: + case 0x06: case 0x07: dev->regs[dev->cur_reg] = val; break; + case 0x21: + dev->regs[dev->cur_reg] = val; + fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !!(val & 0x04)); + break; case 0x22: - dev->regs[dev->cur_reg] = val & 0x7f; + dev->regs[dev->cur_reg] = val; + superio_handler(dev); break; case 0x23: - dev->regs[dev->cur_reg] = val & 0x0f; + dev->regs[dev->cur_reg] = (old & 0xf0) | (val & 0x0f); break; case 0x24: dev->pcregs[dev->regs[0x23]] = val; break; default: - if (dev->cur_reg >= 0x30) { - if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; - } + if (dev->cur_reg >= 0x30) + old = dev->ld_regs[ld][reg]; break; } } switch (dev->cur_reg) { case 0x30: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; - switch (dev->regs[0x07]) { - case 0x03: + switch (ld) { + default: + break; + case LD_KBD: case LD_MOUSE: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_RTC: + dev->ld_regs[ld][reg] = val; + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_handler(dev); break; - case 0x04: + case LD_LPT: + dev->ld_regs[ld][reg] = val; lpt1_handler(dev); break; - case 0x05: + case LD_UART2: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 1); break; - case 0x06: + case LD_UART1: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 0); break; - case 0x07: + case LD_GPIO: + dev->ld_regs[ld][reg] = val; gpio_handler(dev); break; - case 0x08: + case LD_PM: + dev->ld_regs[ld][reg] = val; pm_handler(dev); break; - - default: - break; } break; + /* I/O Range Check. */ + case 0x31: + switch (ld) { + default: + break; + case LD_MIN ... LD_MAX: + if (ld != LD_MOUSE) + dev->ld_regs[ld][reg] = val; + break; + } + break; + /* Base Address 0 MSB. */ case 0x60: - if (dev->regs[0x07] == 0x04) { - val &= 0x03; - } - fallthrough; - case 0x62: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; - if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07)) - break; - switch (dev->regs[0x07]) { - case 0x03: + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_RTC: + dev->ld_regs[ld][reg] = val; + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_handler(dev); break; - case 0x04: + case LD_LPT: + dev->ld_regs[ld][reg] = (old & 0xfc) | (val & 0x03); lpt1_handler(dev); break; - case 0x05: + case LD_UART2: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 1); break; - case 0x06: + case LD_UART1: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 0); break; - case 0x07: + case LD_GPIO: + dev->ld_regs[ld][reg] = val; gpio_handler(dev); break; - case 0x08: + case LD_PM: + dev->ld_regs[ld][reg] = val; pm_handler(dev); break; - - default: - break; } break; + /* Base Address 0 LSB. */ case 0x61: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb; + switch (ld) { + default: break; - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; + case LD_KBD: + dev->ld_regs[ld][reg] = (old & 0x04) | (val & 0xfb); + kbc_handler(dev); + break; + case LD_RTC: + dev->ld_regs[ld][reg] = (old & 0x01) | (val & 0xfe); + break; + case LD_FDC: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); fdc_handler(dev); break; - case 0x04: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; + case LD_LPT: + dev->ld_regs[ld][reg] = (old & 0x03) | (val & 0xfc); lpt1_handler(dev); break; - case 0x05: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + case LD_UART2: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); serial_handler(dev, 1); break; - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + case LD_UART1: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); serial_handler(dev, 0); break; - case 0x07: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + case LD_GPIO: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); gpio_handler(dev); break; - case 0x08: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; + case LD_PM: + dev->ld_regs[ld][reg] = (old & 0x01) | (val & 0xfe); pm_handler(dev); break; - - default: - break; } break; + /* Base Address 1 MSB (undocumented for Logical Device 7). */ + case 0x62: + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_GPIO: + dev->ld_regs[ld][reg] = val; + gpio_handler(dev); + break; + } + break; + /* Base Address 1 LSB (undocumented for Logical Device 7). */ case 0x63: - if (dev->regs[0x07] == 0x00) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04; - else if (dev->regs[0x07] == 0x07) { - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; - gpio_handler(dev); - } - break; - case 0x70: - case 0x74: - case 0x75: - switch (dev->regs[0x07]) { - case 0x03: - fdc_handler(dev); - break; - case 0x04: - lpt1_handler(dev); - break; - case 0x05: - serial_handler(dev, 1); - break; - case 0x06: - serial_handler(dev, 0); - break; - case 0x07: - gpio_handler(dev); - break; - case 0x08: - pm_handler(dev); - break; - + switch (ld) { default: break; + case LD_KBD: + dev->ld_regs[ld][reg] = (old & 0x04) | (val & 0xfb); + kbc_handler(dev); + break; + case LD_GPIO: + dev->ld_regs[ld][reg] = (old & 0x01) | (val & 0xfe); + gpio_handler(dev); + break; } break; - case 0xf0: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; + /* Interrupt Select. */ + case 0x70: + switch (ld) { + default: break; - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; + case LD_KBD: case LD_MOUSE: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_RTC: + dev->ld_regs[ld][reg] = val; + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; + fdc_handler(dev); + break; + case LD_LPT: + dev->ld_regs[ld][reg] = val; + lpt1_handler(dev); + break; + case LD_UART2: + dev->ld_regs[ld][reg] = val; + serial_handler(dev, 1); + break; + case LD_UART1: + dev->ld_regs[ld][reg] = val; + serial_handler(dev, 0); + break; + } + break; + /* Interrupt Type. */ + case 0x71: + switch (ld) { + default: + break; + case LD_MIN ... LD_MAX: + if ((ld == LD_KBD) || (ld == LD_MOUSE)) + dev->ld_regs[ld][reg] = (old & 0xfc) | (val & 0x03); + else + dev->ld_regs[ld][reg] = (old & 0xfd) | (val & 0x02); + break; + } + break; + /* DMA Channel Select 0. */ + case 0x74: + switch (ld) { + default: + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; + fdc_handler(dev); + break; + case LD_LPT: + dev->ld_regs[ld][reg] = val; + lpt1_handler(dev); + break; + case LD_UART2: + dev->ld_regs[ld][reg] = val; + break; + } + break; + /* DMA Channel Select 1. */ + case 0x75: + switch (ld) { + default: + break; + case LD_UART2: + dev->ld_regs[ld][reg] = val; + break; + } + break; + /* Configuration Register 0. */ + case 0xf0: + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = val; + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); break; - case 0x04: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; + case LD_LPT: + dev->ld_regs[ld][reg] = val; lpt1_handler(dev); break; - case 0x05: - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; - break; - - default: + case LD_UART2: case LD_UART1: + dev->ld_regs[ld][reg] = val; break; } break; + /* Configuration Register 1. */ case 0xf1: - if (dev->regs[0x07] == 0x03) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; + switch (ld) { + default: + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; + break; + } break; default: @@ -458,32 +683,46 @@ pc87307_write(uint16_t port, uint8_t val, void *priv) } } -uint8_t +static uint8_t pc87307_read(uint16_t port, void *priv) { - const pc87307_t *dev = (pc87307_t *) priv; - uint8_t ret = 0xff; - uint8_t index; - - index = (port & 1) ? 0 : 1; + const pc87307_t *dev = (pc87307_t *) priv; + uint8_t ld = dev->regs[0x07]; + uint8_t reg = dev->cur_reg - 0x30; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; if (index) ret = dev->cur_reg; else { if (dev->cur_reg >= 0x30) - ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; + ret = dev->ld_regs[ld][reg]; else if (dev->cur_reg == 0x24) ret = dev->pcregs[dev->regs[0x23]]; + /* Write-only registers. */ + else if ((dev->cur_reg == 0x00) || + (dev->cur_reg == 0x02) || (dev->cur_reg == 0x03)) + ret = 0x00; else ret = dev->regs[dev->cur_reg]; +#ifdef EANBLE_PC87307_LOG + if (dev->cur_reg >= 0x30) + pc87307_log("[%04X:%08X] [R] (%04X) %02X:%02X = %02X\n", + CS, cpu_state.pc, port, ld, dev->cur_reg, ret); + else + pc87307_log("[%04X:%08X] [R] (%04X) %02X = %02X\n", + CS, cpu_state.pc, port, dev->cur_reg, ret); +#endif } return ret; } void -pc87307_reset(pc87307_t *dev) +pc87307_reset(void *priv) { + pc87307_t *dev = (pc87307_t *) priv; + memset(dev->regs, 0x00, 0x30); for (uint16_t i = 0; i < 256; i++) memset(dev->ld_regs[i], 0x00, 0xd0); @@ -493,77 +732,77 @@ pc87307_reset(pc87307_t *dev) dev->regs[0x20] = dev->id; dev->regs[0x21] = 0x04; + dev->regs[0x22] = dev->baddr; - dev->ld_regs[0x00][0x01] = 0x01; - dev->ld_regs[0x00][0x31] = 0x60; - dev->ld_regs[0x00][0x33] = 0x64; - dev->ld_regs[0x00][0x40] = 0x01; - dev->ld_regs[0x00][0x41] = 0x02; - dev->ld_regs[0x00][0x44] = 0x04; - dev->ld_regs[0x00][0x45] = 0x04; - dev->ld_regs[0x00][0xc0] = 0x40; + dev->ld_regs[LD_KBD ][0x00] = 0x01; + dev->ld_regs[LD_KBD ][0x31] = 0x60; + dev->ld_regs[LD_KBD ][0x33] = 0x64; + dev->ld_regs[LD_KBD ][0x40] = 0x01; + dev->ld_regs[LD_KBD ][0x41] = 0x02; + dev->ld_regs[LD_KBD ][0x44] = 0x04; + dev->ld_regs[LD_KBD ][0x45] = 0x04; + dev->ld_regs[LD_KBD ][0xc0] = 0x40; - dev->ld_regs[0x01][0x40] = 0x0c; - dev->ld_regs[0x01][0x41] = 0x02; - dev->ld_regs[0x01][0x44] = 0x04; - dev->ld_regs[0x01][0x45] = 0x04; + dev->ld_regs[LD_MOUSE][0x40] = 0x0c; + dev->ld_regs[LD_MOUSE][0x41] = 0x02; + dev->ld_regs[LD_MOUSE][0x44] = 0x04; + dev->ld_regs[LD_MOUSE][0x45] = 0x04; - dev->ld_regs[0x02][0x00] = 0x01; - dev->ld_regs[0x02][0x31] = 0x70; - dev->ld_regs[0x02][0x40] = 0x08; - dev->ld_regs[0x02][0x44] = 0x04; - dev->ld_regs[0x02][0x45] = 0x04; + dev->ld_regs[LD_RTC ][0x00] = 0x01; + dev->ld_regs[LD_RTC ][0x31] = 0x70; + dev->ld_regs[LD_RTC ][0x40] = 0x08; + dev->ld_regs[LD_RTC ][0x44] = 0x04; + dev->ld_regs[LD_RTC ][0x45] = 0x04; - dev->ld_regs[0x03][0x01] = 0x01; - dev->ld_regs[0x03][0x30] = 0x03; - dev->ld_regs[0x03][0x31] = 0xf2; - dev->ld_regs[0x03][0x40] = 0x06; - dev->ld_regs[0x03][0x41] = 0x03; - dev->ld_regs[0x03][0x44] = 0x02; - dev->ld_regs[0x03][0x45] = 0x04; - dev->ld_regs[0x03][0xc0] = 0x02; + dev->ld_regs[LD_FDC ][0x01] = 0x01; + dev->ld_regs[LD_FDC ][0x30] = 0x03; + dev->ld_regs[LD_FDC ][0x31] = 0xf0; + dev->ld_regs[LD_FDC ][0x32] = 0x03; + dev->ld_regs[LD_FDC ][0x33] = 0xf7; + dev->ld_regs[LD_FDC ][0x40] = 0x06; + dev->ld_regs[LD_FDC ][0x41] = 0x03; + dev->ld_regs[LD_FDC ][0x44] = 0x02; + dev->ld_regs[LD_FDC ][0x45] = 0x04; + dev->ld_regs[LD_FDC ][0xc0] = 0x02; - dev->ld_regs[0x04][0x30] = 0x02; - dev->ld_regs[0x04][0x31] = 0x78; - dev->ld_regs[0x04][0x40] = 0x07; - dev->ld_regs[0x04][0x44] = 0x04; - dev->ld_regs[0x04][0x45] = 0x04; - dev->ld_regs[0x04][0xc0] = 0xf2; + dev->ld_regs[LD_LPT ][0x30] = 0x02; + dev->ld_regs[LD_LPT ][0x31] = 0x78; + dev->ld_regs[LD_LPT ][0x40] = 0x07; + dev->ld_regs[LD_LPT ][0x44] = 0x04; + dev->ld_regs[LD_LPT ][0x45] = 0x04; + dev->ld_regs[LD_LPT ][0xc0] = 0xf2; - dev->ld_regs[0x05][0x30] = 0x02; - dev->ld_regs[0x05][0x31] = 0xf8; - dev->ld_regs[0x05][0x40] = 0x03; - dev->ld_regs[0x05][0x41] = 0x03; - dev->ld_regs[0x05][0x44] = 0x04; - dev->ld_regs[0x05][0x45] = 0x04; - dev->ld_regs[0x05][0xc0] = 0x02; + dev->ld_regs[LD_UART2][0x30] = 0x02; + dev->ld_regs[LD_UART2][0x31] = 0xf8; + dev->ld_regs[LD_UART2][0x40] = 0x03; + dev->ld_regs[LD_UART2][0x41] = 0x03; + dev->ld_regs[LD_UART2][0x44] = 0x04; + dev->ld_regs[LD_UART2][0x45] = 0x04; + dev->ld_regs[LD_UART2][0xc0] = 0x02; - dev->ld_regs[0x06][0x30] = 0x03; - dev->ld_regs[0x06][0x31] = 0xf8; - dev->ld_regs[0x06][0x40] = 0x04; - dev->ld_regs[0x06][0x41] = 0x03; - dev->ld_regs[0x06][0x44] = 0x04; - dev->ld_regs[0x06][0x45] = 0x04; - dev->ld_regs[0x06][0xc0] = 0x02; + dev->ld_regs[LD_UART1][0x30] = 0x03; + dev->ld_regs[LD_UART1][0x31] = 0xf8; + dev->ld_regs[LD_UART1][0x40] = 0x04; + dev->ld_regs[LD_UART1][0x41] = 0x03; + dev->ld_regs[LD_UART1][0x44] = 0x04; + dev->ld_regs[LD_UART1][0x45] = 0x04; + dev->ld_regs[LD_UART1][0xc0] = 0x02; - dev->ld_regs[0x07][0x44] = 0x04; - dev->ld_regs[0x07][0x45] = 0x04; + dev->ld_regs[LD_GPIO ][0x44] = 0x04; + dev->ld_regs[LD_GPIO ][0x45] = 0x04; - dev->ld_regs[0x08][0x44] = 0x04; - dev->ld_regs[0x08][0x45] = 0x04; + dev->ld_regs[LD_PM ][0x44] = 0x04; + dev->ld_regs[LD_PM ][0x45] = 0x04; -#if 0 - dev->gpio[0] = 0xff; - dev->gpio[1] = 0xfb; -#endif dev->gpio[0][0] = 0xff; dev->gpio[0][1] = 0x00; dev->gpio[0][2] = 0x00; dev->gpio[0][3] = 0xff; - dev->gpio[1][0] = 0xff; + dev->gpio[0][4] = 0xff; + dev->gpio[0][5] = 0x00; + dev->gpio[0][6] = 0x00; + dev->gpio[0][7] = 0xff; dev->gpio[1][1] = 0x00; - dev->gpio[1][2] = 0x00; - dev->gpio[1][3] = 0xff; dev->pm[0] = 0xff; dev->pm[1] = 0xff; @@ -576,10 +815,17 @@ pc87307_reset(pc87307_t *dev) 0 = 360 rpm @ 500 kbps for 3.5" 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ - lpt1_remove(); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, 0); fdc_reset(dev->fdc); + + kbc_handler(dev); + fdc_handler(dev); + lpt1_handler(dev); + serial_handler(dev, 0); + serial_handler(dev, 1); + gpio_handler(dev); + pm_handler(dev); + superio_handler(dev); } static void @@ -602,16 +848,26 @@ pc87307_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - pc87307_reset(dev); + switch (info->local & PCX730X_KBC) { + default: + case PCX730X_AMI: + dev->kbc = device_add(&keyboard_ps2_intel_ami_pci_device); + break; + /* Optiplex! */ + case PCX730X_PHOENIX_42: + dev->kbc = device_add(&keyboard_ps2_phoenix_device); + break; + case PCX730X_PHOENIX_42I: + dev->kbc = device_add(&keyboard_ps2_phoenix_pci_device); + break; + } - if (info->local & 0x100) { - io_sethandler(0x02e, 0x0002, - pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); - } - if (info->local & 0x200) { - io_sethandler(0x15c, 0x0002, - pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); - } + if (info->local & PCX730X_15C) + dev->baddr = 0x02; + else + dev->baddr = 0x03; + + pc87307_reset(dev); return dev; } @@ -623,7 +879,7 @@ const device_t pc87307_device = { .local = 0x1c0, .init = pc87307_init, .close = pc87307_close, - .reset = NULL, + .reset = pc87307_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -637,7 +893,7 @@ const device_t pc87307_15c_device = { .local = 0x2c0, .init = pc87307_init, .close = pc87307_close, - .reset = NULL, + .reset = pc87307_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -651,7 +907,7 @@ const device_t pc87307_both_device = { .local = 0x3c0, .init = pc87307_init, .close = pc87307_close, - .reset = NULL, + .reset = pc87307_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, @@ -665,7 +921,7 @@ const device_t pc97307_device = { .local = 0x1cf, .init = pc87307_init, .close = pc87307_close, - .reset = NULL, + .reset = pc87307_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index 5e417aefb..d2d3f4ac0 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -8,11 +8,9 @@ * * Emulation of the NatSemi PC87309 Super I/O chip. * - * - * * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020-2025 Miran Grca. */ #include #include @@ -24,44 +22,81 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/lpt.h> +#include <86box/machine.h> #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> #include <86box/rom.h> #include <86box/serial.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/keyboard.h> #include <86box/sio.h> +#include <86box/plat_fallthrough.h> +#include "cpu.h" typedef struct pc87309_t { uint8_t id; + uint8_t baddr; uint8_t pm_idx; uint8_t regs[48]; uint8_t ld_regs[256][208]; uint8_t pm[8]; - uint8_t baddr; + uint16_t superio_base; uint16_t pm_base; int cur_reg; + void *kbc; fdc_t *fdc; serial_t *uart[2]; } pc87309_t; +enum { + LD_FDC = 0, + LD_LPT, + LD_UART2, + LD_UART1, + LD_PM, + LD_KBD, + LD_MOUSE +} pc87309_ld_t; + +#define LD_MIN LD_FDC +#define LD_MAX LD_MOUSE + static void fdc_handler(pc87309_t *dev); static void lpt1_handler(pc87309_t *dev); static void serial_handler(pc87309_t *dev, int uart); - +static void kbc_handler(pc87309_t *dev); static void pc87309_write(uint16_t port, uint8_t val, void *priv); static uint8_t pc87309_read(uint16_t port, void *priv); +#ifdef ENABLE_PC87309_LOG +int pc87309_do_log = ENABLE_PC87309_LOG; + +static void +pc87309_log(const char *fmt, ...) +{ + va_list ap; + + if (pc87309_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define pc87309_log(fmt, ...) +#endif + static void pc87309_pm_write(uint16_t port, uint8_t val, void *priv) { pc87309_t *dev = (pc87309_t *) priv; - if (port & 1) { + if (port & 1) dev->pm[dev->pm_idx] = val; + else { + dev->pm_idx = val & 0x07; switch (dev->pm_idx) { case 0x00: @@ -74,8 +109,7 @@ pc87309_pm_write(uint16_t port, uint8_t val, void *priv) default: break; } - } else - dev->pm_idx = val & 0x07; + } } uint8_t @@ -109,43 +143,48 @@ pc87309_pm_init(pc87309_t *dev, uint16_t addr) } static void -superio_handler(pc87309_t *dev) +kbc_handler(pc87309_t *dev) { - io_removehandler(0x15c, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - io_removehandler(0x02e, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + uint8_t active = (dev->ld_regs[LD_KBD][0x00] & 0x01) && + (dev->pm[0x00] & 0x01); + uint8_t active_2 = dev->ld_regs[LD_MOUSE][0x00] & 0x01; + uint8_t irq = (dev->ld_regs[LD_KBD][0x40] & 0x0f); + uint8_t irq_2 = (dev->ld_regs[LD_MOUSE][0x40] & 0x0f); + uint16_t addr = (dev->ld_regs[LD_KBD][0x30] << 8) | + dev->ld_regs[LD_KBD][0x31]; + uint16_t addr_2 = (dev->ld_regs[LD_KBD][0x32] << 8) | + dev->ld_regs[LD_KBD][0x33]; - switch (dev->regs[0x21] & 0x0b) { - case 0x02: - case 0x08: - case 0x0a: - io_sethandler(0x15c, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - break; - case 0x03: - case 0x09: - case 0x0b: - io_sethandler(0x02e, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - break; + pc87309_log("%02X, %02X, %02X, %02X, %04X, %04X\n", + active, active_2, irq, irq_2, addr, addr_2); + + if (addr <= 0xfff8) { + pc87309_log("Enabling KBC #1 on %04X...\n", addr); + kbc_at_port_handler(0, active, addr, dev->kbc); } + + if (addr_2 <= 0xfff8) { + pc87309_log("Enabling KBC #2 on %04X...\n", addr_2); + kbc_at_port_handler(1, active, addr_2, dev->kbc); + } + + kbc_at_set_irq(0, active ? irq : 0xffff, dev->kbc); + kbc_at_set_irq(1, (active && active_2) ? irq_2 : 0xffff, dev->kbc); } static void fdc_handler(pc87309_t *dev) { - uint8_t irq; - uint8_t active; - uint16_t addr; - fdc_remove(dev->fdc); - active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08); - addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002; - irq = (dev->ld_regs[0x00][0x40] & 0x0f); + uint8_t active = (dev->ld_regs[LD_FDC][0x00] & 0x01) && + (dev->pm[0x00] & 0x08); + uint8_t irq = (dev->ld_regs[LD_FDC][0x40] & 0x0f); + uint16_t addr = ((dev->ld_regs[LD_FDC][0x30] << 8) | + dev->ld_regs[LD_FDC][0x31]) & 0xfff8; - if (active) { + if (active && (addr <= 0xfff8)) { + pc87309_log("Enabling FDC on %04X, IRQ %i...\n", addr, irq); fdc_set_base(dev->fdc, addr); fdc_set_irq(dev->fdc, irq); } @@ -154,222 +193,351 @@ fdc_handler(pc87309_t *dev) static void lpt1_handler(pc87309_t *dev) { - uint8_t irq; - uint8_t active; - uint16_t addr; + uint8_t active = (dev->ld_regs[LD_LPT][0x00] & 0x01) && + (dev->pm[0x00] & 0x10); + uint8_t irq = (dev->ld_regs[LD_LPT][0x40] & 0x0f); + uint16_t addr = (dev->ld_regs[LD_LPT][0x30] << 8) | + dev->ld_regs[LD_LPT][0x31]; - lpt1_remove(); - - active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10); - addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31]; - irq = (dev->ld_regs[0x01][0x40] & 0x0f); - - if (active) { + if (active && (addr <= 0xfffc)) { + pc87309_log("Enabling LPT1 on %04X...\n", addr); lpt1_setup(addr); - lpt1_irq(irq); - } + } else + lpt1_setup(0xffff); + + lpt1_irq(irq); } static void serial_handler(pc87309_t *dev, int uart) { - uint8_t irq; - uint8_t active; - uint16_t addr; - serial_remove(dev->uart[uart]); - active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart))); - addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31]; - irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f); + uint8_t active = (dev->ld_regs[LD_UART1 - uart][0x00] & 0x01) && + (dev->pm[0x00] & (1 << (6 - uart))); + uint8_t irq = (dev->ld_regs[LD_UART1 - uart][0x40] & 0x0f); + uint16_t addr = (dev->ld_regs[LD_UART1 - uart][0x30] << 8) | + dev->ld_regs[LD_UART1 - uart][0x31]; - if (active) + if (active && (addr <= 0xfff8)) { + pc87309_log("Enabling COM%i on %04X...\n", uart + 1, addr); serial_setup(dev->uart[uart], addr, irq); + } else + serial_setup(dev->uart[uart], 0x0000, irq); } static void pm_handler(pc87309_t *dev) { - uint8_t active; - uint16_t addr; - pc87309_pm_remove(dev); - active = (dev->ld_regs[0x04][0x00] & 0x01); - addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; + uint8_t active = (dev->ld_regs[LD_PM][0x00] & 0x01); + uint16_t addr = (dev->ld_regs[LD_PM][0x30] << 8) | + dev->ld_regs[LD_PM][0x31]; - if (active) + if (active) { + pc87309_log("Enabling power management on %04X...\n", addr); pc87309_pm_init(dev, addr); + } +} + +static void +superio_handler(pc87309_t *dev) +{ + if (dev->superio_base != 0x0000) + io_removehandler(dev->superio_base, 0x0002, + pc87309_read, NULL, NULL, + pc87309_write, NULL, NULL, dev); + + switch (dev->regs[0x22] & 0x0b) { + default: + dev->superio_base = 0x0000; + break; + case 0x02: + case 0x08: case 0x0a: + dev->superio_base = 0x015c; + break; + case 0x03: + case 0x09: case 0x0b: + dev->superio_base = 0x002e; + break; + } + + if (dev->superio_base != 0x0000) { + pc87309_log("Enabling Super I/O on %04X...\n", dev->superio_base); + io_sethandler(dev->superio_base, 0x0002, + pc87309_read, NULL, NULL, + pc87309_write, NULL, NULL, dev); + } } static void pc87309_write(uint16_t port, uint8_t val, void *priv) { - pc87309_t *dev = (pc87309_t *) priv; - uint8_t index; - - index = (port & 1) ? 0 : 1; + pc87309_t *dev = (pc87309_t *) priv; + uint8_t ld = dev->regs[0x07]; + uint8_t reg = dev->cur_reg - 0x30; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t old = dev->regs[dev->cur_reg]; if (index) { dev->cur_reg = val; return; } else { +#ifdef ENABLE_PC87309_LOG + if (dev->cur_reg >= 0x30) + pc87309_log("[%04X:%08X] [W] (%04X) %02X:%02X = %02X\n", + CS, cpu_state.pc, port, ld, dev->cur_reg, val); + else + pc87309_log("[%04X:%08X] [W] (%04X) %02X = %02X\n", + CS, cpu_state.pc, port, dev->cur_reg, val); +#endif switch (dev->cur_reg) { case 0x00: - case 0x02: - case 0x03: - case 0x06: - case 0x07: + case 0x02: case 0x03: + case 0x06: case 0x07: + dev->regs[dev->cur_reg] = val; + break; case 0x21: dev->regs[dev->cur_reg] = val; + fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !!(val & 0x04)); superio_handler(dev); break; case 0x22: - dev->regs[dev->cur_reg] = val & 0x7f; + dev->regs[dev->cur_reg] = val; break; default: - if (dev->cur_reg >= 0x30) { - if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; - } + if (dev->cur_reg >= 0x30) + old = dev->ld_regs[ld][reg]; break; } } switch (dev->cur_reg) { case 0x30: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; - switch (dev->regs[0x07]) { - case 0x00: + switch (ld) { + default: + break; + case LD_KBD: case LD_MOUSE: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_handler(dev); break; - case 0x01: + case LD_LPT: + dev->ld_regs[ld][reg] = val; lpt1_handler(dev); break; - case 0x02: + case LD_UART2: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 1); break; - case 0x03: + case LD_UART1: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 0); break; - case 0x04: + case LD_PM: + dev->ld_regs[ld][reg] = val; pm_handler(dev); break; - - default: - break; } break; + /* I/O Range Check. */ + case 0x31: + switch (ld) { + default: + break; + case LD_MIN ... LD_MAX: + if (ld != LD_MOUSE) + dev->ld_regs[ld][reg] = val; + break; + } + break; + /* Base Address 0 MSB. */ case 0x60: - case 0x62: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; - if (dev->cur_reg == 0x62) - break; - switch (dev->regs[0x07]) { - case 0x00: + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_handler(dev); break; - case 0x01: + case LD_LPT: + dev->ld_regs[ld][reg] = (old & 0xfc) | (val & 0x03); lpt1_handler(dev); break; - case 0x02: + case LD_UART2: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 1); break; - case 0x03: + case LD_UART1: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 0); break; - case 0x04: + case LD_PM: + dev->ld_regs[ld][reg] = val; pm_handler(dev); break; - - default: - break; } break; - case 0x63: - if (dev->regs[0x07] == 0x06) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04; - break; + /* Base Address 0 LSB. */ case 0x61: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = (old & 0x04) | (val & 0xfb); + kbc_handler(dev); + break; + case LD_FDC: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); fdc_handler(dev); break; - case 0x01: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; + case LD_LPT: + dev->ld_regs[ld][reg] = (old & 0x03) | (val & 0xfc); lpt1_handler(dev); break; - case 0x02: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + case LD_UART2: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); serial_handler(dev, 1); break; - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + case LD_UART1: + dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8); serial_handler(dev, 0); break; - case 0x04: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; + case LD_PM: + dev->ld_regs[ld][reg] = (old & 0x01) | (val & 0xfe); pm_handler(dev); break; - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - break; - - default: - break; } break; + /* Base Address 1 MSB (undocumented for Logical Device 7). */ + case 0x62: + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + } + break; + /* Base Address 1 LSB (undocumented for Logical Device 7). */ + case 0x63: + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = (old & 0x04) | (val & 0xfb); + kbc_handler(dev); + break; + } + break; + /* Interrupt Select. */ case 0x70: - case 0x74: - case 0x75: - switch (dev->regs[0x07]) { - case 0x00: + switch (ld) { + default: + break; + case LD_KBD: case LD_MOUSE: + dev->ld_regs[ld][reg] = val; + kbc_handler(dev); + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_handler(dev); break; - case 0x01: + case LD_LPT: + dev->ld_regs[ld][reg] = val; lpt1_handler(dev); break; - case 0x02: + case LD_UART2: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 1); break; - case 0x03: + case LD_UART1: + dev->ld_regs[ld][reg] = val; serial_handler(dev, 0); break; - case 0x04: - pm_handler(dev); - break; - - default: - break; } break; + /* Interrupt Type. */ + case 0x71: + switch (ld) { + default: + break; + case LD_MIN ... LD_MAX: + if ((ld == LD_KBD) || (ld == LD_MOUSE)) + dev->ld_regs[ld][reg] = (old & 0xfc) | (val & 0x03); + else + dev->ld_regs[ld][reg] = (old & 0xfd) | (val & 0x02); + break; + } + break; + /* DMA Channel Select 0. */ + case 0x74: + switch (ld) { + default: + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; + fdc_handler(dev); + break; + case LD_LPT: + dev->ld_regs[ld][reg] = val; + lpt1_handler(dev); + break; + case LD_UART2: + dev->ld_regs[ld][reg] = val; + break; + } + break; + /* DMA Channel Select 1. */ + case 0x75: + switch (ld) { + default: + break; + case LD_UART2: + dev->ld_regs[ld][reg] = val; + break; + } + break; + /* Configuration Register 0. */ case 0xf0: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; + switch (ld) { + default: + break; + case LD_KBD: + dev->ld_regs[ld][reg] = val; + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); break; - case 0x01: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; + case LD_LPT: + dev->ld_regs[ld][reg] = val; lpt1_handler(dev); break; - case 0x02: - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; - break; - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; - break; - - default: + case LD_UART2: case LD_UART1: + dev->ld_regs[ld][reg] = val; break; } break; + /* Configuration Register 1. */ case 0xf1: - if (dev->regs[0x07] == 0x00) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; + switch (ld) { + default: + break; + case LD_FDC: + dev->ld_regs[ld][reg] = val; + break; + } break; default: @@ -377,30 +545,44 @@ pc87309_write(uint16_t port, uint8_t val, void *priv) } } -uint8_t +static uint8_t pc87309_read(uint16_t port, void *priv) { - const pc87309_t *dev = (pc87309_t *) priv; - uint8_t ret = 0xff; - uint8_t index; - - index = (port & 1) ? 0 : 1; + const pc87309_t *dev = (pc87309_t *) priv; + uint8_t ld = dev->regs[0x07]; + uint8_t reg = dev->cur_reg - 0x30; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; if (index) - ret = dev->cur_reg & 0x1f; + ret = dev->cur_reg; else { if (dev->cur_reg >= 0x30) - ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; + ret = dev->ld_regs[ld][reg]; + /* Write-only registers. */ + else if ((dev->cur_reg == 0x00) || + (dev->cur_reg == 0x02) || (dev->cur_reg == 0x03)) + ret = 0x00; else ret = dev->regs[dev->cur_reg]; +#ifdef ENABLE_PC87309_LOG + if (dev->cur_reg >= 0x30) + pc87309_log("[%04X:%08X] [R] (%04X) %02X:%02X = %02X\n", + CS, cpu_state.pc, port, ld, dev->cur_reg, ret); + else + pc87309_log("[%04X:%08X] [R] (%04X) %02X = %02X\n", + CS, cpu_state.pc, port, dev->cur_reg, ret); +#endif } return ret; } void -pc87309_reset(pc87309_t *dev) +pc87309_reset(void *priv) { + pc87309_t *dev = (pc87309_t *) priv; + memset(dev->regs, 0x00, 0x30); for (uint16_t i = 0; i < 256; i++) memset(dev->ld_regs[i], 0x00, 0xd0); @@ -409,65 +591,56 @@ pc87309_reset(pc87309_t *dev) dev->regs[0x20] = dev->id; dev->regs[0x21] = 0x04 | dev->baddr; - dev->ld_regs[0x00][0x01] = 0x01; - dev->ld_regs[0x00][0x30] = 0x03; - dev->ld_regs[0x00][0x31] = 0xf2; - dev->ld_regs[0x00][0x40] = 0x06; - dev->ld_regs[0x00][0x41] = 0x03; - dev->ld_regs[0x00][0x44] = 0x02; - dev->ld_regs[0x00][0x45] = 0x04; - dev->ld_regs[0x00][0xc0] = 0x02; + dev->ld_regs[LD_KBD ][0x00] = 0x01; + dev->ld_regs[LD_KBD ][0x31] = 0x60; + dev->ld_regs[LD_KBD ][0x33] = 0x64; + dev->ld_regs[LD_KBD ][0x40] = 0x01; + dev->ld_regs[LD_KBD ][0x41] = 0x02; + dev->ld_regs[LD_KBD ][0x44] = 0x04; + dev->ld_regs[LD_KBD ][0x45] = 0x04; + dev->ld_regs[LD_KBD ][0xc0] = 0x40; - dev->ld_regs[0x01][0x30] = 0x02; - dev->ld_regs[0x01][0x31] = 0x78; - dev->ld_regs[0x01][0x40] = 0x07; - dev->ld_regs[0x01][0x44] = 0x04; - dev->ld_regs[0x01][0x45] = 0x04; - dev->ld_regs[0x01][0xc0] = 0xf2; + dev->ld_regs[LD_MOUSE][0x40] = 0x0c; + dev->ld_regs[LD_MOUSE][0x41] = 0x02; + dev->ld_regs[LD_MOUSE][0x44] = 0x04; + dev->ld_regs[LD_MOUSE][0x45] = 0x04; - dev->ld_regs[0x02][0x30] = 0x02; - dev->ld_regs[0x02][0x31] = 0xf8; - dev->ld_regs[0x02][0x40] = 0x03; - dev->ld_regs[0x02][0x41] = 0x03; - dev->ld_regs[0x02][0x44] = 0x04; - dev->ld_regs[0x02][0x45] = 0x04; - dev->ld_regs[0x02][0xc0] = 0x02; + dev->ld_regs[LD_FDC ][0x01] = 0x01; + dev->ld_regs[LD_FDC ][0x30] = 0x03; + dev->ld_regs[LD_FDC ][0x31] = 0xf0; + dev->ld_regs[LD_FDC ][0x32] = 0x03; + dev->ld_regs[LD_FDC ][0x33] = 0xf7; + dev->ld_regs[LD_FDC ][0x40] = 0x06; + dev->ld_regs[LD_FDC ][0x41] = 0x03; + dev->ld_regs[LD_FDC ][0x44] = 0x02; + dev->ld_regs[LD_FDC ][0x45] = 0x04; + dev->ld_regs[LD_FDC ][0xc0] = 0x02; - dev->ld_regs[0x03][0x30] = 0x03; - dev->ld_regs[0x03][0x31] = 0xf8; - dev->ld_regs[0x03][0x40] = 0x04; - dev->ld_regs[0x03][0x41] = 0x03; - dev->ld_regs[0x03][0x44] = 0x04; - dev->ld_regs[0x03][0x45] = 0x04; - dev->ld_regs[0x03][0xc0] = 0x02; + dev->ld_regs[LD_LPT ][0x30] = 0x02; + dev->ld_regs[LD_LPT ][0x31] = 0x78; + dev->ld_regs[LD_LPT ][0x40] = 0x07; + dev->ld_regs[LD_LPT ][0x44] = 0x04; + dev->ld_regs[LD_LPT ][0x45] = 0x04; + dev->ld_regs[LD_LPT ][0xc0] = 0xf2; - dev->ld_regs[0x04][0x44] = 0x04; - dev->ld_regs[0x04][0x45] = 0x04; + dev->ld_regs[LD_UART2][0x30] = 0x02; + dev->ld_regs[LD_UART2][0x31] = 0xf8; + dev->ld_regs[LD_UART2][0x40] = 0x03; + dev->ld_regs[LD_UART2][0x41] = 0x03; + dev->ld_regs[LD_UART2][0x44] = 0x04; + dev->ld_regs[LD_UART2][0x45] = 0x04; + dev->ld_regs[LD_UART2][0xc0] = 0x02; - dev->ld_regs[0x05][0x40] = 0x0c; - dev->ld_regs[0x05][0x41] = 0x02; - dev->ld_regs[0x05][0x44] = 0x04; - dev->ld_regs[0x05][0x45] = 0x04; + dev->ld_regs[LD_UART1][0x30] = 0x03; + dev->ld_regs[LD_UART1][0x31] = 0xf8; + dev->ld_regs[LD_UART1][0x40] = 0x04; + dev->ld_regs[LD_UART1][0x41] = 0x03; + dev->ld_regs[LD_UART1][0x44] = 0x04; + dev->ld_regs[LD_UART1][0x45] = 0x04; + dev->ld_regs[LD_UART1][0xc0] = 0x02; - dev->ld_regs[0x06][0x01] = 0x01; - dev->ld_regs[0x06][0x31] = 0x60; - dev->ld_regs[0x06][0x33] = 0x64; - dev->ld_regs[0x06][0x40] = 0x01; - dev->ld_regs[0x06][0x41] = 0x02; - dev->ld_regs[0x06][0x44] = 0x04; - dev->ld_regs[0x06][0x45] = 0x04; - dev->ld_regs[0x06][0xc0] = 0x40; - - dev->regs[0x00] = 0x0B; - dev->regs[0x01] = 0x01; - dev->regs[0x03] = 0x01; - dev->regs[0x05] = 0x0D; - dev->regs[0x08] = 0x70; - dev->regs[0x09] = 0xC0; - dev->regs[0x0b] = 0x80; - dev->regs[0x0f] = 0x1E; - dev->regs[0x12] = 0x30; - dev->regs[0x19] = 0xEF; + dev->ld_regs[LD_PM ][0x44] = 0x04; + dev->ld_regs[LD_PM ][0x45] = 0x04; dev->pm[0] = 0x79; dev->pm[4] = 0x0e; @@ -478,11 +651,15 @@ pc87309_reset(pc87309_t *dev) 0 = 360 rpm @ 500 kbps for 3.5" 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ - lpt1_remove(); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, 0); fdc_reset(dev->fdc); + kbc_handler(dev); + fdc_handler(dev); + lpt1_handler(dev); + serial_handler(dev, 0); + serial_handler(dev, 1); + pm_handler(dev); superio_handler(dev); } @@ -503,7 +680,27 @@ pc87309_init(const device_t *info) dev->fdc = device_add(&fdc_at_nsc_device); - dev->baddr = (info->local & 0x100) ? 8 : 9; + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + switch (info->local & PCX730X_KBC) { + default: + case PCX730X_AMI: + dev->kbc = device_add(&keyboard_ps2_intel_ami_pci_device); + break; + /* Optiplex! */ + case PCX730X_PHOENIX_42: + dev->kbc = device_add(&keyboard_ps2_phoenix_device); + break; + case PCX730X_PHOENIX_42I: + dev->kbc = device_add(&keyboard_ps2_phoenix_pci_device); + break; + } + + if (info->local & PCX730X_15C) + dev->baddr = 0x0a; + else + dev->baddr = 0x0b; pc87309_reset(dev); @@ -514,24 +711,10 @@ const device_t pc87309_device = { .name = "National Semiconductor PC87309 Super I/O", .internal_name = "pc87309", .flags = 0, - .local = 0xe0, + .local = 0, .init = pc87309_init, .close = pc87309_close, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t pc87309_15c_device = { - .name = "National Semiconductor PC87309 Super I/O (Port 15Ch)", - .internal_name = "pc87309_15c", - .flags = 0, - .local = 0x1e0, - .init = pc87309_init, - .close = pc87309_close, - .reset = NULL, + .reset = pc87309_reset, .available = NULL, .speed_changed = NULL, .force_redraw = NULL, From d8a53f6fdb09ed94c965282db9872139b2fbdcf7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 21 May 2025 20:55:00 +0200 Subject: [PATCH 0970/1190] Make it use the A12 BIOS. --- src/machine/m_at_socket7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 9ceebe2e0..3d51e1a06 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -974,7 +974,7 @@ machine_at_optiplex_gn_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/optiplex_gn/Gn_a11.rom", + ret = bios_load_linear("roms/machines/optiplex_gn/DELL.ROM", 0x000c0000, 262144, 0); if (bios_only || !ret) From e9a1768da935313187c2312f357966a1324bdae4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 22 May 2025 00:35:07 +0200 Subject: [PATCH 0971/1190] KBC AT: Remove some excess logging. --- src/device/kbc_at.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 78fc32ffd..f068b8699 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2391,24 +2391,18 @@ kbc_at_port_handler(int num, int set, uint16_t port, void *priv) { atkbc_t *dev = (atkbc_t *) priv; - if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000)) { - pclog("Disabling keyboard controller port %i at %04X...\n", num, dev->base_addr[num]); - + if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000)) io_removehandler(dev->base_addr[num], 1, dev->handlers[num].read, NULL, NULL, dev->handlers[num].write, NULL, NULL, priv); - } dev->handler_enable[num] = set; dev->base_addr[num] = port; - if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000)) { - pclog("Enabling keyboard controller port %i at %04X...\n", num, dev->base_addr[num]); - + if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000)) io_sethandler(dev->base_addr[num], 1, dev->handlers[num].read, NULL, NULL, dev->handlers[num].write, NULL, NULL, priv); - } } void From f6dd42ca87010f7dcc1fb08979322aee61448198 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 22 May 2025 00:54:57 +0200 Subject: [PATCH 0972/1190] Packard Bell PB410: Fix on-board video. --- src/machine/m_at_386dx_486.c | 2 +- src/machine/machine_table.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 46b93a37f..c1f471ff3 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -396,7 +396,7 @@ machine_at_pb410a_init(const machine_t *model) device_add(&phoenix_486_jumper_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&ht216_32_pb410a_device); + device_add(machine_get_vid_device(machine)); return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f16f4e5ae..e864f580b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6647,7 +6647,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &ht216_32_pb410a_device, .snd_device = NULL, .net_device = NULL }, From c8fbee1b62845e9894a849509527573cc96d48d1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 22 May 2025 06:20:04 +0200 Subject: [PATCH 0973/1190] Fixes to the two recently NSC Super I/O chips and the two boards that use the PC87309 (Tyan Tsunami ATX and the Freeway). --- src/machine/m_at_slot1.c | 1 - src/machine/m_at_slot2.c | 1 - src/sio/sio_pc87307.c | 4 +++- src/sio/sio_pc87309.c | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 773826316..c764b4229 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -585,7 +585,6 @@ machine_at_s1846_init(const machine_t *model) device_add(&i440bx_device); device_add(&piix4e_device); device_add_params(&pc87309_device, (void *) (PCX730X_AMI | PC87309_PC87309)); - device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); diff --git a/src/machine/m_at_slot2.c b/src/machine/m_at_slot2.c index 37c0acdfd..7bf412823 100644 --- a/src/machine/m_at_slot2.c +++ b/src/machine/m_at_slot2.c @@ -140,7 +140,6 @@ machine_at_fw6400gx_init(const machine_t *model) device_add(&i440gx_device); device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); device_add_params(&pc87309_device, (void *) (PCX730X_15C | PCX730X_AMI | PC87309_PC87309)); device_add(ics9xxx_get(ICS9250_08)); device_add(&sst_flash_29ee020_device); diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index 7bc9bb441..7e51c5975 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -12,11 +12,13 @@ * * Copyright 2020-2025 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/timer.h> @@ -400,7 +402,7 @@ pc87307_write(uint16_t port, uint8_t val, void *priv) break; case 0x21: dev->regs[dev->cur_reg] = val; - fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !!(val & 0x04)); + fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !(val & 0x04)); break; case 0x22: dev->regs[dev->cur_reg] = val; diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index d2d3f4ac0..8bbbb7036 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -12,11 +12,13 @@ * * Copyright 2020-2025 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/timer.h> @@ -249,7 +251,7 @@ superio_handler(pc87309_t *dev) pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); - switch (dev->regs[0x22] & 0x0b) { + switch (dev->regs[0x21] & 0x0b) { default: dev->superio_base = 0x0000; break; @@ -300,7 +302,7 @@ pc87309_write(uint16_t port, uint8_t val, void *priv) break; case 0x21: dev->regs[dev->cur_reg] = val; - fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !!(val & 0x04)); + fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !(val & 0x04)); superio_handler(dev); break; case 0x22: From 2139e3dd511cd0d9a099c4a558499a3ed50efd6b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 23 May 2025 00:34:12 +0600 Subject: [PATCH 0974/1190] Attempt to make OpenGL 3.0 filter settings consistent --- src/qt/qt_openglrenderer.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 45bae6ea7..9ca2d887e 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1503,6 +1503,7 @@ OpenGLRenderer::render() /* loop through each pass */ for (i = 0; i < shader->num_passes; ++i) { + bool resetFiltering = false; struct shader_pass *pass = &shader->passes[i]; memcpy(pass->state.input_size, input->state.output_size, 2 * sizeof(GLfloat)); @@ -1524,8 +1525,14 @@ OpenGLRenderer::render() glw.glBindFramebuffer(GL_FRAMEBUFFER, pass->fbo.id); glw.glViewport(0, 0, pass->state.output_size[0], pass->state.output_size[1]); - } else + } else { + resetFiltering = true; + glw.glBindTexture(GL_TEXTURE_2D, input->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); glw.glViewport(window_rect.x, window_rect.y, window_rect.w, window_rect.h); + } glw.glClearColor(0, 0, 0, 1); glw.glClear(GL_COLOR_BUFFER_BIT); @@ -1570,6 +1577,13 @@ OpenGLRenderer::render() glw.glBindTexture(GL_TEXTURE_2D, 0); } + if (resetFiltering) { + glw.glBindTexture(GL_TEXTURE_2D, input->fbo.texture.id); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, input->fbo.texture.min_filter); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, input->fbo.texture.mag_filter); + glw.glBindTexture(GL_TEXTURE_2D, 0); + } + input = pass; } @@ -1637,6 +1651,11 @@ OpenGLRenderer::render() pass->state.output_texture_size[j] = next_pow2(pass->state.output_size[j]); } + glw.glBindTexture(GL_TEXTURE_2D, input->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); + glw.glViewport(window_rect.x, window_rect.y, window_rect.w, window_rect.h); glw.glClearColor(0, 0, 0, 1); From 0278077a4ba75ed62ced41aa0a8b32cdc742ab8c Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Thu, 22 May 2025 22:48:52 +0300 Subject: [PATCH 0975/1190] Add the Dell OptiPlex GXa --- src/include/86box/machine.h | 2 +- src/machine/m_at_slot1.c | 33 +++++++++++++++++++++++++++++ src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index cbf2fda15..be9f17505 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -822,8 +822,8 @@ extern int machine_at_p65up5_cpknd_init(const machine_t *); extern int machine_at_kn97_init(const machine_t *); extern int machine_at_lx6_init(const machine_t *); +extern int machine_at_optiplex_gxa_init(const machine_t *); extern int machine_at_spitfire_init(const machine_t *); - extern int machine_at_ma30d_init(const machine_t *); extern int machine_at_p6i440e2_init(const machine_t *); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index c764b4229..d7a47c901 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -150,6 +150,39 @@ machine_at_lx6_init(const machine_t *model) return ret; } +int +machine_at_optiplex_gxa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/optiplex_gxa/DELL.ROM", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + + device_add(&i440lx_device); + device_add(&piix4_device); + device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307)); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + int machine_at_spitfire_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 10ce1694b..d2bd76ca6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15170,6 +15170,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a National Semiconductor PC87307 Super I/O with on-chip KBC, which has one of these + firmwares: AMI '5' MegaKey, Phoenix MultiKey/42 1.37, or Phoenix MultiKey/42i 4.16. */ + { + .name = "[i440LX] Dell OptiPlex GXa", + .internal_name = "optiplex_gxa", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440LX, + .init = machine_at_optiplex_gxa_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK(CPU_PENTIUMPRO, CPU_CYRIX3S), + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 5.0 + }, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Video: ATi 3D Rage Pro, Network: 3Com 3C905, Sound: Crystal CS4236B */ + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, /* not yet emulated */ + .snd_device = &cs4236b_onboard_device, + .net_device = NULL /* not yet emulated */ + }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { From 734885b930c90e7b94a10dad668ff83adea9df3f Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Fri, 23 May 2025 00:01:42 +0300 Subject: [PATCH 0976/1190] Fix the onboard audio on the OptiPlex GXa --- 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 d2bd76ca6..de830cb89 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15208,7 +15208,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, /* not yet emulated */ - .snd_device = &cs4236b_onboard_device, + .snd_device = &cs4236b_device, .net_device = NULL /* not yet emulated */ }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix From 8c2ee25b39e9fcc4f50ee1e4c32f401ac2f31e9c Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Fri, 23 May 2025 00:13:55 +0300 Subject: [PATCH 0977/1190] Fix a small mistake with the IRQ table of the OptiPlex GXA --- src/machine/m_at_slot1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index d7a47c901..54cf1a03a 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -167,7 +167,7 @@ machine_at_optiplex_gxa_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); From 8d971d06966e7565cacea9de2b4b70a13c23a0ba Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Fri, 23 May 2025 11:10:05 +0300 Subject: [PATCH 0978/1190] Add the Dell Dimension XPS Pro___n --- src/include/86box/machine.h | 1 + src/machine/m_at_socket8.c | 36 +++++++++++++++++++++++++++++++ src/machine/machine_table.c | 42 ++++++++++++++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index be9f17505..ced3397e1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -804,6 +804,7 @@ extern int machine_at_686nx_init(const machine_t *); extern int machine_at_acerv60n_init(const machine_t *); extern int machine_at_lgibmx61_init(const machine_t *); extern int machine_at_vs440fx_init(const machine_t *); +extern int machine_at_dellvenus_init(const machine_t *); extern int machine_at_gw2kvenus_init(const machine_t *); extern int machine_at_ap440fx_init(const machine_t *); extern int machine_at_mb600n_init(const machine_t *); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index aabfb9b4f..d81b41502 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -260,6 +260,42 @@ machine_at_vs440fx_init(const machine_t *model) return ret; } +int +machine_at_dellvenus_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2("roms/machines/dellvenus/1006CS1J.BIO", + "roms/machines/dellvenus/1006CS1J.BI1", + "roms/machines/dellvenus/1006CS1J.BI2", + "roms/machines/dellvenus/1006CS1J.BI3", + "roms/machines/dellvenus/1006CS1J.RCV", + 0x3a000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i440fx_device); + device_add(&piix3_device); + device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307)); + + device_add(&intel_flash_bxt_ami_device); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + + return ret; +} + int machine_at_gw2kvenus_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index de830cb89..9a9cb5cf1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14675,7 +14675,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* It's a Intel VS440FX with a Gateway 2000 OEM BIOS */ + /* It's an Intel VS440FX with a Dell OEM BIOS */ + { + .name = "[i440FX] Dell Dimension XPS Pro___n", + .internal_name = "dellvenus", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_dellvenus_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 3.5 + }, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .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 = &cs4236_onboard_device, + .net_device = NULL + }, + /* It's an Intel VS440FX with a Gateway 2000 OEM BIOS */ { .name = "[i440FX] Gateway 2000 Venus", .internal_name = "gw2kvenus", From 054be5c76cca2ed3820607b3bd0dbc368ec60620 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Fri, 23 May 2025 22:50:05 +0700 Subject: [PATCH 0979/1190] Machine table fixes 1. Unblock original i486 and Am486 CPUs and correct minimum RAM on Acer P3 (since it was copied from Soyo 4SAW2 a while ago) 2. Correct RAM step on few machines with SiS chipset 3. Correct minimum RAM on PCChips M579 and M729 respectively 4. Gigabyte GA-5SG100 does support 60MHZ bus speed according to its manual, so change its minimum bus speed to 60MHZ --- src/machine/machine_table.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 9a9cb5cf1..6f004ee78 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8650,7 +8650,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET3, - .block = CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), + .block = CPU_BLOCK_NONE, .min_bus = 0, .max_bus = 0, .min_voltage = 0, @@ -8661,7 +8661,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, .ram = { - .min = 2048, + .min = 1024, .max = 131072, .step = 1024 }, @@ -13838,7 +13838,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 1572864, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, @@ -13878,7 +13878,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 1572864, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, @@ -13920,7 +13920,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 786432, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, @@ -14084,7 +14084,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { - .min = 1024, + .min = 8192, .max = 1572864, .step = 8192 }, @@ -14443,7 +14443,7 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 66666667, + .min_bus = 60000000, .max_bus = 100000000, .min_voltage = 2000, .max_voltage = 3520, @@ -14455,7 +14455,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 786432, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, @@ -15027,7 +15027,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: C-Media CMI8330 */ .ram = { - .min = 1024, + .min = 8192, .max = 1572864, .step = 8192 }, From 8556d05acd5c64ee531b59806dd9c191a2e96792 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Fri, 23 May 2025 22:54:27 +0700 Subject: [PATCH 0980/1190] Revert minimum RAM on Acer P3 --- 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 6f004ee78..ba24ea742 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8661,7 +8661,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, .ram = { - .min = 1024, + .min = 2048, .max = 131072, .step = 1024 }, From e083daf4bb545e015611738db45badb64334a3df Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 24 May 2025 06:17:16 +0200 Subject: [PATCH 0981/1190] Fix on-board audio on the GXL and the jumpers on the XPS P60 and 560/L. --- src/chipset/intel_piix.c | 5 +++- src/chipset/intel_sio.c | 18 ++++++++++++- src/device/CMakeLists.txt | 1 + src/device/kbc_at.c | 4 ++- src/device/postcard.c | 6 +++-- src/include/86box/chipset.h | 2 ++ src/include/86box/machine.h | 1 + src/machine/m_at_socket4.c | 14 ++++++---- src/machine/m_at_socket5.c | 1 + src/machine/machine_table.c | 6 +++++ src/sound/snd_sb.c | 52 ++++++++++++++++++++----------------- 11 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index b73285f70..9867a0fa7 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1621,7 +1621,10 @@ piix_init(const device_t *info) else cpu_set_isa_pci_div(3); - dma_alias_set(); + if (dev->type > 1) + dma_alias_set(); + else + dma_alias_set_piix(); if (dev->type < 4) pci_enable_mirq(0); diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index 9b6d28ab1..b11ec0765 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -355,7 +355,23 @@ sio_config_read(uint16_t port, UNUSED(void *priv)) ret = 0xff; break; case 5: - ret = 0xd3; + /* + Dell Dimension XPS P60 jumpers: + - Bit 5: Disable CMOS Setup (1 = yes, 0 = no). + + Dell OptiPlex 560/L jumpers: + - Bit 1: Password (1 = disable, 0 = enable); + - Bit 5: Clear CMOS (1 = no, 0 = yes). + - Bits 7, 6: Board type: + - 0, 0 = L; + - 0, 1 = MT; + - 1, 0 = M; + - 1, 1 = M. + */ + if (!strcmp(machine_get_internal_name(), "opti560l")) + ret = 0x20; + else + ret = 0xd3; switch (cpu_pci_speed) { case 20000000: diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index bbbab22fd..486d40b07 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(dev OBJECT cartridge.c cassette.c clock_ics9xxx.c + dell_jumper.c hasp.c hwm.c hwm_gl518sm.c diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 9a1800ed9..dc93a4fba 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1125,7 +1125,9 @@ write_cmd_generic(void *priv, uint8_t val) */ uint8_t p1 = 0x30; kbc_delay_to_ob(dev, p1, 0, 0x00); - } else if (!strcmp(machine_get_internal_name(), "dellplato") || !strcmp(machine_get_internal_name(), "dellhannibalp")) { + } else if (!strcmp(machine_get_internal_name(), "dellplato") || + !strcmp(machine_get_internal_name(), "dellhannibalp") || + !strcmp(machine_get_internal_name(), "dellxp60")) { /* Dell Dimension XPS Pxxx & Pxxxa/Mxxxa: - Bit 3: Password disable jumper (must be clear); diff --git a/src/device/postcard.c b/src/device/postcard.c index 058684c0b..19d81b692 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -99,7 +99,8 @@ postcard_setui(void) ps[1][0], ps[1][1], ps[1][2], ps[1][3]); break; } - } else if (strstr(machines[machine].name, " Dell ")) { + } else if (strstr(machines[machine].name, " Dell ") && + (machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX)) { char dell_diags[10] = { 0 }; if (!postcard_written[1]) @@ -223,7 +224,8 @@ postcard_init(UNUSED(const device_t *info)) io_sethandler(postcard_port, postcard_ports_num, NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); - if (strstr(machines[machine].name, " Dell ")) + if (strstr(machines[machine].name, " Dell ") && + (machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX)) io_sethandler(0x00e0, 0x0001, NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL); diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 94884383b..688a5fecb 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -197,6 +197,8 @@ extern const device_t vlsi_scamp_device; extern const device_t wd76c10_device; /* Miscellaneous Hardware */ +extern const device_t dell_jumper_device; + extern const device_t nec_mate_unk_device; extern const device_t phoenix_486_jumper_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index ced3397e1..0dbbe98c5 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -385,6 +385,7 @@ extern int machine_get_min_ram(int m); extern int machine_get_max_ram(int m); extern int machine_get_ram_granularity(int m); extern int machine_get_type(int m); +extern int machine_get_chipset(int m); extern void machine_close(void); extern int machine_has_mouse(void); extern int machine_is_sony(void); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 88474d431..033a2e5fe 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -157,7 +157,9 @@ machine_at_dellxp60_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + + device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); @@ -170,7 +172,7 @@ machine_at_dellxp60_init(const machine_t *model) pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); - device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&keyboard_ps2_phoenix_device); device_add(&sio_zb_device); device_add(&fdc37c665_device); device_add(&intel_flash_bxt_ami_device); @@ -189,8 +191,10 @@ machine_at_opti560l_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + machine_at_common_init_ex(model, 2); + + device_add(&amstrad_megapc_nvr_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -199,7 +203,7 @@ machine_at_opti560l_init(const machine_t *model) pci_register_slot(0x08, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); - device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&keyboard_ps2_phoenix_device); device_add(&sio_zb_device); device_add(&i82091aa_device); device_add(&intel_flash_bxt_ami_device); diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 5572d0484..442281811 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -268,6 +268,7 @@ machine_at_optiplex_gxl_init(const machine_t *model) device_add(&i430fx_device); device_add(&piix_device); device_add(&pc87332_device); + device_add(&dell_jumper_device); device_add(&intel_flash_bxt_device); return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 9a9cb5cf1..2664e1819 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -17346,6 +17346,12 @@ machine_get_type(int m) return (machines[m].type); } +int +machine_get_chipset(int m) +{ + return (machines[m].chipset); +} + int machine_get_machine_from_internal_name(const char *s) { diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index e89946486..14726d358 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -2091,35 +2091,39 @@ sb_vibra16s_onboard_relocate_base(uint16_t new_addr, void *priv) sb_t *sb = (sb_t *) priv; uint16_t addr = sb->dsp.sb_addr; - io_removehandler(addr, 0x0004, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_removehandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_removehandler(addr + 4, 0x0002, - sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, - sb); + if (addr != 0x0000) { + io_removehandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + } sb_dsp_setaddr(&sb->dsp, 0); addr = new_addr; - io_sethandler(addr, 0x0004, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_sethandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_sethandler(addr + 4, 0x0002, - sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, - sb); + if (addr != 0x0000) { + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + } sb_dsp_setaddr(&sb->dsp, addr); } From fa5f1224cafb09af021774f843eaf1a31a01095a Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 24 May 2025 07:10:49 +0200 Subject: [PATCH 0982/1190] Implement the DEC/Intel 21152-AB PCI bridge for the Dell Gn+/GXa riser card. --- src/device/pci_bridge.c | 64 ++++++++++++++++++++++++++++++++++---- src/include/86box/pci.h | 1 + src/machine/m_at_slot1.c | 10 +++--- src/machine/m_at_socket7.c | 4 ++- 4 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 7dda00aee..8893acf69 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -30,8 +30,10 @@ #include <86box/mem.h> #include <86box/device.h> #include <86box/pci.h> +#include <86box/plat_fallthrough.h> #define PCI_BRIDGE_DEC_21150 0x10110022 +#define PCI_BRIDGE_DEC_21152 0x10110024 #define AGP_BRIDGE_ALI_M5243 0x10b95243 #define AGP_BRIDGE_ALI_M5247 0x10b95247 #define AGP_BRIDGE_INTEL_440LX 0x80867181 @@ -242,12 +244,15 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x40: if (dev->local == PCI_BRIDGE_DEC_21150) val &= 0x32; + else if (dev->local == PCI_BRIDGE_DEC_21152) + val &= 0x12; break; case 0x41: if (AGP_BRIDGE_VIA(dev->local)) val &= 0x7e; - else if (dev->local == PCI_BRIDGE_DEC_21150) + else if ((dev->local == PCI_BRIDGE_DEC_21150) || + (dev->local == PCI_BRIDGE_DEC_21152)) val &= 0x07; break; @@ -257,18 +262,22 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) break; case 0x43: - if (dev->local == PCI_BRIDGE_DEC_21150) + if ((dev->local == PCI_BRIDGE_DEC_21150) || + (dev->local == PCI_BRIDGE_DEC_21152)) val &= 0x03; break; case 0x64: - if (dev->local == PCI_BRIDGE_DEC_21150) + if ((dev->local == PCI_BRIDGE_DEC_21150) || + (dev->local == PCI_BRIDGE_DEC_21152)) val &= 0x7e; break; case 0x69: if (dev->local == PCI_BRIDGE_DEC_21150) val &= 0x3f; + else if (dev->local == PCI_BRIDGE_DEC_21152) + val = (val & 0x01) | 0x3e; break; case 0x86: @@ -302,6 +311,15 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) break; case 0xe0: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } else if (dev->local == PCI_BRIDGE_DEC_21152) + val &= 0x03; + else + return; + break; + case 0xe1: if (AGP_BRIDGE_ALI(dev->local)) { if (!(dev->ctl & 0x20)) @@ -399,6 +417,14 @@ pci_bridge_reset(void *priv) /* command and status */ switch (dev->local) { + case PCI_BRIDGE_DEC_21152: + dev->regs[0x08] = 0x03; + dev->regs[0x34] = 0xdc; + dev->regs[0x69] = 0x3e; + dev->regs[0xdc] = 0x01; + dev->regs[0xde] = 0x01; + dev->regs[0xe2] = 0x80; + fallthrough; case PCI_BRIDGE_DEC_21150: dev->regs[0x06] = 0x80; dev->regs[0x07] = 0x02; @@ -490,6 +516,8 @@ pci_bridge_init(const device_t *info) uint8_t interrupt_count; uint8_t interrupt_mask; uint8_t slot_count; + uint8_t dell_slots[3] = { 0x09, 0x0a, 0x0b }; + uint8_t dell_interrupts[3][4] = { { 1, 2, 3, 4 }, { 4, 2, 1, 3 }, { 1, 3, 4, 2 } }; pci_bridge_t *dev = (pci_bridge_t *) calloc(1, sizeof(pci_bridge_t)); @@ -499,7 +527,10 @@ pci_bridge_init(const device_t *info) pci_bridge_reset(dev); - pci_add_bridge(AGP_BRIDGE(dev->local), pci_bridge_read, pci_bridge_write, dev, &dev->slot); + if (info->local == PCI_BRIDGE_DEC_21152) + pci_add_card(PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev, &dev->slot); + else + pci_add_bridge(AGP_BRIDGE(dev->local), pci_bridge_read, pci_bridge_write, dev, &dev->slot); interrupt_count = sizeof(interrupts); interrupt_mask = interrupt_count - 1; @@ -513,16 +544,23 @@ pci_bridge_init(const device_t *info) if (info->local == PCI_BRIDGE_DEC_21150) slot_count = 9; /* 9 bus masters */ + else if (info->local == PCI_BRIDGE_DEC_21152) + slot_count = 3; /* 3 bus masters */ else slot_count = 1; /* AGP bridges always have 1 slot */ for (uint8_t i = 0; i < slot_count; i++) { + uint8_t slot = i; + if (info->local == PCI_BRIDGE_DEC_21152) { + slot = dell_slots[i]; + memcpy(interrupts, dell_interrupts[i], 4); + } /* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */ pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", - dev->bus_index, i, interrupts[i & interrupt_mask], + dev->bus_index, slot, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]); - pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, + pci_register_bus_slot(dev->bus_index, slot, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], @@ -547,6 +585,20 @@ const device_t dec21150_device = { .config = NULL }; +const device_t dec21152_device = { + .name = "DEC 21152 PCI Bridge", + .internal_name = "dec21152", + .flags = DEVICE_PCI, + .local = PCI_BRIDGE_DEC_21152, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + /* AGP bridges */ const device_t ali5243_agp_device = { .name = "ALi M5243 AGP Bridge", diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 097fcf502..462b4f821 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -286,6 +286,7 @@ extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); #ifdef EMU_DEVICE_H extern const device_t dec21150_device; +extern const device_t dec21152_device; extern const device_t ali5243_agp_device; extern const device_t ali5247_agp_device; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 54cf1a03a..a147d0e13 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -164,18 +164,20 @@ machine_at_optiplex_gxa_init(const machine_t *model) machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0F, PCI_CARD_BRIDGE, 1, 2, 3, 4); if (sound_card_current[0] == SOUND_INTERNAL) device_add(machine_get_snd_device(machine)); device_add(&i440lx_device); device_add(&piix4_device); + device_add(&dec21152_device); device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 3d51e1a06..7d2441e18 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -24,7 +24,6 @@ #include <86box/mem.h> #include <86box/io.h> #include <86box/rom.h> -#include <86box/pci.h> #include <86box/device.h> #include <86box/chipset.h> #include <86box/hdc.h> @@ -45,6 +44,7 @@ #include <86box/scsi_ncr53c8xx.h> #include <86box/thread.h> #include <86box/network.h> +#include <86box/pci.h> int machine_at_acerv35n_init(const machine_t *model) @@ -989,6 +989,7 @@ machine_at_optiplex_gn_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */ pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); /* 3C905, not yet emulated */ pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + pci_register_slot(0x0F, PCI_CARD_BRIDGE, 1, 2, 3, 4); if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); @@ -998,6 +999,7 @@ machine_at_optiplex_gn_init(const machine_t *model) device_add(&i430tx_device); device_add(&piix4_device); + device_add(&dec21152_device); device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); From e1a4f3fbaa19be6e6cc694ff1b116a94bbc47148 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 24 May 2025 08:23:28 +0200 Subject: [PATCH 0983/1190] Forgot the dell_jumper.c. --- src/device/dell_jumper.c | 175 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/device/dell_jumper.c diff --git a/src/device/dell_jumper.c b/src/device/dell_jumper.c new file mode 100644 index 000000000..12fc3d13b --- /dev/null +++ b/src/device/dell_jumper.c @@ -0,0 +1,175 @@ +/* + * 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. + * + * Implementation of the Dell 486 and 586 Jumper Readout. + * + * Register 0x02: + * - Bit 0: ATX power: 1 = off, 0 = on. + * + * Register 0x05: + * - Appears to be: 0x02 = On-board audio enabled; + * 0x07 = On-board audio disabled. + * + * Register 0x07: + * - Bit 0: On-board NIC: 1 = present, 0 = absent; + * - Bit 1: On-board audio: 1 = present, 0 = absent; + * - Bits 4-2: + * - 0, 0, 0 = GXL; + * - 0, 0, 1 = GL+; + * - 0, 1, 0 = GXMT; + * - 0, 1, 1 = GMT+; + * - 1, 0, 0 = GXM; + * - 1, 0, 1 = GM+; + * - 1, 1, 0 = WS; + * - 1, 1, 1 = GWS+. + * + * Authors: Miran Grca, + * + * Copyright 2025 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/sound.h> +#include <86box/chipset.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> + +typedef struct dell_jumper_t { + uint8_t index; + uint8_t regs[256]; +} dell_jumper_t; + +#ifdef ENABLE_DELL_JUMPER_LOG +int dell_jumper_do_log = ENABLE_DELL_JUMPER_LOG; + +static void +dell_jumper_log(const char *fmt, ...) +{ + va_list ap; + + if (dell_jumper_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define dell_jumper_log(fmt, ...) +#endif + +static void +dell_jumper_write(uint16_t addr, uint8_t val, void *priv) +{ + dell_jumper_t *dev = (dell_jumper_t *) priv; + + dell_jumper_log("Dell Jumper: Write %02x\n", val); + + if (addr & 1) switch (dev->index) { + default: + dev->regs[dev->index] = val; + break; + case 0x02: + dev->regs[dev->index] = val; + if (val & 0x04) + /* Soft power off. */ + plat_power_off(); + break; + case 0x05: + dev->regs[dev->index] = (dev->regs[dev->index] & 0x02) | (val & 0xfd); + if (machine_snd != NULL) switch (val & 0x05) { + default: + case 0x05: + sb_vibra16s_onboard_relocate_base(0x0000, machine_snd); + break; + case 0x00: + sb_vibra16s_onboard_relocate_base(0x0220, machine_snd); + break; + } + break; + case 0x07: + break; + } else + dev->index = val; +} + +static uint8_t +dell_jumper_read(uint16_t addr, void *priv) +{ + const dell_jumper_t *dev = (dell_jumper_t *) priv; + uint8_t ret = 0xff; + + dell_jumper_log("Dell Jumper: Read %02x\n", dev->jumper); + + if (addr & 1) + ret = dev->regs[dev->index]; + else + ret = dev->index; + + return ret; +} + +static void +dell_jumper_reset(void *priv) +{ + dell_jumper_t *dev = (dell_jumper_t *) priv; + + dev->index = 0x00; + memset(dev->regs, 0x00, 256); + + if (sound_card_current[0] == SOUND_INTERNAL) + /* GXL, on-board audio present, on-board NIC absent. */ + dev->regs[0x07] = 0x02; + else + /* GXL, on-board audio absent, on-board NIC absent. */ + dev->regs[0x07] = 0x00; +} + +static void +dell_jumper_close(void *priv) +{ + dell_jumper_t *dev = (dell_jumper_t *) priv; + + free(dev); +} + +static void * +dell_jumper_init(const device_t *info) +{ + dell_jumper_t *dev = (dell_jumper_t *) calloc(1, sizeof(dell_jumper_t)); + + dell_jumper_reset(dev); + + io_sethandler(0x00e8, 0x0002, dell_jumper_read, NULL, NULL, dell_jumper_write, NULL, NULL, dev); + + return dev; +} + +const device_t dell_jumper_device = { + .name = "Dell Jumper Readout", + .internal_name = "dell_jumper", + .flags = 0, + .local = 0, + .init = dell_jumper_init, + .close = dell_jumper_close, + .reset = dell_jumper_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; From 121e5f6b60e8579a8d8eaa9ab22db5bf782496da Mon Sep 17 00:00:00 2001 From: Jester Date: Sat, 24 May 2025 14:32:43 +0200 Subject: [PATCH 0984/1190] Update m_xt_olivetti.c add Olivetti M240 BIOS 2.12 --- src/machine/m_xt_olivetti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 34ca441ec..7cfab9c11 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -2366,8 +2366,8 @@ machine_xt_m240_init(const machine_t *model) m24_kbd_t *m24_kbd; nvr_t *nvr; - ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pchj_2.11_low.bin", - "roms/machines/m240/olivetti_m240_pchk_2.11_high.bin", + ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pchj_2.12_low.bin", + "roms/machines/m240/olivetti_m240_pchk_2.12_high.bin", 0x000f8000, 32768, 0); if (bios_only || !ret) From dac9f6ee8a26d83ba415d2693f237bfafec707cd Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 24 May 2025 21:04:10 +0700 Subject: [PATCH 0985/1190] RAM step corrections for SiS 5600 machines --- 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 4bbf7f412..f72da7338 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -16108,7 +16108,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 1572864, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, @@ -16148,7 +16148,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 1572864, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, @@ -16909,7 +16909,7 @@ const machine_t machines[] = { .ram = { .min = 8192, .max = 1572864, - .step = 1024 + .step = 8192 }, .nvrmask = 255, .kbc_device = NULL, From 1754deff4dda4286cc0a091f6c46cdc91f60a49e Mon Sep 17 00:00:00 2001 From: Jester Date: Sat, 24 May 2025 18:00:53 +0200 Subject: [PATCH 0986/1190] Fix wrong filename used for M240 BIOS I only updated the number, but should have changed the correct filename, oopsie --- src/machine/m_xt_olivetti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 7cfab9c11..acdb77fd1 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -2366,8 +2366,8 @@ machine_xt_m240_init(const machine_t *model) m24_kbd_t *m24_kbd; nvr_t *nvr; - ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pchj_2.12_low.bin", - "roms/machines/m240/olivetti_m240_pchk_2.12_high.bin", + ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pchm_2.12_low.bin", + "roms/machines/m240/olivetti_m240_pchl_2.12_high.bin", 0x000f8000, 32768, 0); if (bios_only || !ret) From a1a3ed22f4a9defc0bb0eaa923ff607ab37a8582 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 25 May 2025 01:39:58 +0200 Subject: [PATCH 0987/1190] Fix RZ-1000 so the AMI 062594 BIOS'es of the SB486PV don't disable it. --- src/disk/hdc_ide_rz1000.c | 41 +++--------------------------------- src/machine/m_at_386dx_486.c | 1 - 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/src/disk/hdc_ide_rz1000.c b/src/disk/hdc_ide_rz1000.c index e2c7179ad..06586b267 100644 --- a/src/disk/hdc_ide_rz1000.c +++ b/src/disk/hdc_ide_rz1000.c @@ -130,38 +130,6 @@ rz1000_pci_write(int func, int addr, uint8_t val, void *priv) rz1000_ide_handlers(dev); } break; - case 0x10: - dev->regs[0x10] = (val & 0xf8) | 1; - rz1000_ide_handlers(dev); - break; - case 0x11: - dev->regs[0x11] = val; - rz1000_ide_handlers(dev); - break; - case 0x14: - dev->regs[0x14] = (val & 0xfc) | 1; - rz1000_ide_handlers(dev); - break; - case 0x15: - dev->regs[0x15] = val; - rz1000_ide_handlers(dev); - break; - case 0x18: - dev->regs[0x18] = (val & 0xf8) | 1; - rz1000_ide_handlers(dev); - break; - case 0x19: - dev->regs[0x19] = val; - rz1000_ide_handlers(dev); - break; - case 0x1c: - dev->regs[0x1c] = (val & 0xfc) | 1; - rz1000_ide_handlers(dev); - break; - case 0x1d: - dev->regs[0x1d] = val; - rz1000_ide_handlers(dev); - break; case 0x40 ... 0x4f: dev->regs[addr] = val; break; @@ -233,16 +201,13 @@ rz1000_reset(void *priv) dev->regs[0x01] = 0x10; dev->regs[0x02] = 0x00; /* RZ-1000 */ dev->regs[0x03] = 0x10; - dev->regs[0x04] = 0x01; + dev->regs[0x04] = 0x00; dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ dev->regs[0x08] = 0x02; /* Revision 02 */ dev->regs[0x09] = dev->local; /* Programming interface */ dev->regs[0x0a] = 0x01; /* IDE controller */ dev->regs[0x0b] = 0x01; /* Mass storage controller */ - dev->regs[0x3c] = 0x14; /* IRQ 14 */ - dev->regs[0x3d] = 0x01; /* INTA */ - dev->irq_mode[0] = dev->irq_mode[1] = 0; dev->irq_pin = PCI_INTA; dev->irq_line = 14; @@ -299,7 +264,7 @@ const device_t ide_rz1000_pci_device = { .name = "PC Technology RZ-1000 PCI", .internal_name = "ide_rz1000_pci", .flags = DEVICE_PCI, - .local = 0x6000a, + .local = 0x60000, .init = rz1000_init, .close = rz1000_close, .reset = rz1000_reset, @@ -313,7 +278,7 @@ const device_t ide_rz1000_pci_single_channel_device = { .name = "PC Technology RZ-1000 PCI", .internal_name = "ide_rz1000_pci_single_channel", .flags = DEVICE_PCI, - .local = 0x2000a, + .local = 0x20000, .init = rz1000_init, .close = rz1000_close, .reset = rz1000_reset, diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index c1f471ff3..9f7534244 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1727,7 +1727,6 @@ machine_at_sb486pv_init(const machine_t *model) device_context_restore(); machine_at_common_init(model); - device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); From c58ef2be81956e40150b6c24969b83e65abf4227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 25 May 2025 11:03:21 +0200 Subject: [PATCH 0988/1190] IBM PS/ValuePoint P60: Remove RZ-1000 - primary IDE is controlled by the Super I/O chip, fixes #5628. --- src/machine/m_at_socket4.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 033a2e5fe..2d4e1a51a 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -270,8 +270,7 @@ machine_at_valuepointp60_init(const machine_t *model) pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ps1_pci_device); device_add(&sio_device); - device_add(&ide_rz1000_pci_single_channel_device); - device_add(&fdc37c665_device); + device_add(&fdc37c665_ide_device); device_add(&intel_flash_bxt_ami_device); device_add(&i430lx_device); From 72c093e7db61f2289445cca975406668b323e641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 25 May 2025 11:07:27 +0200 Subject: [PATCH 0989/1190] AEWIN AW-O671R: Set vid_device. --- 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 f72da7338..a3a02bfcd 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -16502,7 +16502,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &chips_69000_onboard_device, .snd_device = NULL, .net_device = NULL }, From 6f6e64e321bf33d9c3eabcc62a62b7a7c279c2f1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 25 May 2025 15:42:57 +0600 Subject: [PATCH 0990/1190] Some minor fixes --- src/video/vid_chips_69000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index c9830f0ed..8267e271c 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -2247,8 +2247,8 @@ chips_69000_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x13: - chips->linear_mapping.base = val << 24; mem_mapping_disable(&chips->linear_mapping); + chips->linear_mapping.base = val << 24; 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)); @@ -2785,6 +2785,8 @@ chips_69000_disable_handlers(chips_69000_t *chips) mem_mapping_disable(&chips->svga.mapping); if (!chips->on_board) mem_mapping_disable(&chips->bios_rom.mapping); + + chips->linear_mapping.base = 0; /* Save all the mappings and the timers because they are part of linked lists. */ reset_state->linear_mapping = chips->linear_mapping; From c26b2ac2abe3bbfb628e44bcec846dd789fd473f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 25 May 2025 12:27:21 +0200 Subject: [PATCH 0991/1190] AEWin: Make slot 0D PCI_CARD_VIDEO so the on-board video works. --- src/machine/m_at_socket370.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 3f8db4e8c..ff299ee50 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -386,7 +386,7 @@ machine_at_awo671r_init(const machine_t *model) pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_VIDEO, 2, 3, 4, 1); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440bx_device); device_add(&piix4e_device); @@ -394,9 +394,8 @@ machine_at_awo671r_init(const machine_t *model) device_add_inst(&w83977ef_device, 2); device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); - if (gfxcard[0] == VID_INTERNAL) { - device_add(&chips_69000_onboard_device); - } + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; From d67788331e45386ea6f45f0ae10c31f54a063a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 25 May 2025 15:40:02 +0200 Subject: [PATCH 0992/1190] Fix PIIX4 revision. --- src/chipset/intel_piix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 9867a0fa7..e0d80f348 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1712,7 +1712,7 @@ const device_t piix4_device = { .name = "Intel 82371AB/EB (PIIX4/PIIX4E)", .internal_name = "piix4", .flags = DEVICE_PCI, - .local = 0x71100014, + .local = 0x71100004, .init = piix_init, .close = piix_close, .reset = piix_reset, From e277fb894bdf9a50208cc3c7609b70444f8eef34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 25 May 2025 20:16:51 +0200 Subject: [PATCH 0993/1190] PC87309: Swap keyboard and mouse to their correct logical devices. --- src/sio/sio_pc87309.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index 8bbbb7036..5a3f0d828 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -58,8 +58,8 @@ enum { LD_UART2, LD_UART1, LD_PM, - LD_KBD, - LD_MOUSE + LD_MOUSE, + LD_KBD } pc87309_ld_t; #define LD_MIN LD_FDC From 343c011f6b50194a4fef9c7f57ad87263f9773d1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 26 May 2025 00:28:27 +0600 Subject: [PATCH 0994/1190] Rename "AMD PCnet-VL" to "AMD PCnet-32" --- src/network/net_pcnet.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index b13fd8438..16fd7c65c 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -3256,8 +3256,12 @@ const device_t pcnet_am79c960_eb_device = { .config = pcnet_isa_config }; +/* + Used to be incorrectly called "AMD PCnet-VL" but the real name of the chip is "AMD PCnet-32" per the relevant datasheet. + https://theretroweb.com/chip/documentation/am79c965-66c24a7e6969d347126123.pdf +*/ const device_t pcnet_am79c960_vlb_device = { - .name = "AMD PCnet-VL", + .name = "AMD PCnet-32", .internal_name = "pcnetvlb", .flags = DEVICE_VLB, .local = DEV_AM79C960_VLB, From 853830f8bb6a6e50f4b8ddd8d88d19966fddeef4 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 25 May 2025 19:21:33 -0400 Subject: [PATCH 0995/1190] Add Mindscape Music Board Ported from PCem --- src/include/86box/snd_mmb.h | 42 ++++ src/include/86box/sound.h | 3 + src/sound/CMakeLists.txt | 4 + src/sound/ayumi/CMakeLists.txt | 14 ++ src/sound/ayumi/LICENSE | 21 ++ src/sound/ayumi/ayumi.c | 338 ++++++++++++++++++++++++++++++++ src/sound/ayumi/ayumi.h | 71 +++++++ src/sound/snd_mmb.c | 339 +++++++++++++++++++++++++++++++++ src/sound/sound.c | 1 + 9 files changed, 833 insertions(+) create mode 100644 src/include/86box/snd_mmb.h create mode 100644 src/sound/ayumi/CMakeLists.txt create mode 100644 src/sound/ayumi/LICENSE create mode 100644 src/sound/ayumi/ayumi.c create mode 100644 src/sound/ayumi/ayumi.h create mode 100644 src/sound/snd_mmb.c diff --git a/src/include/86box/snd_mmb.h b/src/include/86box/snd_mmb.h new file mode 100644 index 000000000..6e5f7d3a8 --- /dev/null +++ b/src/include/86box/snd_mmb.h @@ -0,0 +1,42 @@ +/* + * 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. + * + * Mindscape Music Board emulation. + * + * Authors: Roy Baer, + * Jasmine Iwanek, + * + * Copyright 2025 Roy Baer. + * Copyright 2025 Jasmine Iwanek. + */ +#ifndef _SOUND_SND_MMB_H_ +#define _SOUND_SND_MMB_H_ + +#define MMB_FREQ FREQ_48000 + +/* NOTE: + * The constant clock rate is a deviation from the real hardware which has + * the design flaw that the clock rate is always half the ISA bus clock. + */ +#define MMB_CLOCK 2386364 + +typedef struct ay_3_891x_s { + uint8_t index; + uint8_t regs[16]; + struct ayumi chip; +} ay_3_891x_t; + +typedef struct mmb_s { + ay_3_891x_t first; + ay_3_891x_t second; + + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; +} mmb_t; + +#endif /* _SOUND_SND_MMB_H_ */ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index a30095c66..b2e202ddb 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -205,6 +205,9 @@ extern const device_t ps1snd_device; extern const device_t ssi2001_device; extern const device_t entertainer_device; +/* Mindscape Music Board */ +extern const device_t mmb_device; + /* Pro Audio Spectrum Plus, 16, and 16D */ extern const device_t pasplus_device; extern const device_t pas16_device; diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 0a04b0ff1..3aaf49bb3 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -41,6 +41,7 @@ add_library(snd OBJECT snd_sb.c snd_sb_dsp.c snd_emu8k.c + snd_mmb.c snd_mpu401.c snd_pas16.c snd_sn76489.c @@ -177,6 +178,9 @@ if(MUNT) endif() endif() +add_subdirectory(ayumi) +target_link_libraries(86Box ayumi) + add_subdirectory(ymfm) target_link_libraries(86Box ymfm) diff --git a/src/sound/ayumi/CMakeLists.txt b/src/sound/ayumi/CMakeLists.txt new file mode 100644 index 000000000..f3e4b18c7 --- /dev/null +++ b/src/sound/ayumi/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# 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. +# + +add_library(ayumi STATIC + ayumi.c +) diff --git a/src/sound/ayumi/LICENSE b/src/sound/ayumi/LICENSE new file mode 100644 index 000000000..25371edc6 --- /dev/null +++ b/src/sound/ayumi/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) Peter Sovietov, http://sovietov.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/src/sound/ayumi/ayumi.c b/src/sound/ayumi/ayumi.c new file mode 100644 index 000000000..861b0fd45 --- /dev/null +++ b/src/sound/ayumi/ayumi.c @@ -0,0 +1,338 @@ +/* Author: Peter Sovietov */ + +#include +#include +#include "ayumi.h" + +static const double AY_dac_table[] = { + 0.0, 0.0, + 0.00999465934234, 0.00999465934234, + 0.0144502937362, 0.0144502937362, + 0.0210574502174, 0.0210574502174, + 0.0307011520562, 0.0307011520562, + 0.0455481803616, 0.0455481803616, + 0.0644998855573, 0.0644998855573, + 0.107362478065, 0.107362478065, + 0.126588845655, 0.126588845655, + 0.20498970016, 0.20498970016, + 0.292210269322, 0.292210269322, + 0.372838941024, 0.372838941024, + 0.492530708782, 0.492530708782, + 0.635324635691, 0.635324635691, + 0.805584802014, 0.805584802014, + 1.0, 1.0 +}; + +static const double YM_dac_table[] = { + 0.0, 0.0, + 0.00465400167849, 0.00772106507973, + 0.0109559777218, 0.0139620050355, + 0.0169985503929, 0.0200198367285, + 0.024368657969, 0.029694056611, + 0.0350652323186, 0.0403906309606, + 0.0485389486534, 0.0583352407111, + 0.0680552376593, 0.0777752346075, + 0.0925154497597, 0.111085679408, + 0.129747463188, 0.148485542077, + 0.17666895552, 0.211551079576, + 0.246387426566, 0.281101701381, + 0.333730067903, 0.400427252613, + 0.467383840696, 0.53443198291, + 0.635172045472, 0.75800717174, + 0.879926756695, 1.0 +}; + +static void reset_segment(struct ayumi* ay); + +static int update_tone(struct ayumi* ay, int index) { + struct tone_channel* ch = &ay->channels[index]; + ch->tone_counter += 1; + if (ch->tone_counter >= ch->tone_period) { + ch->tone_counter = 0; + ch->tone ^= 1; + } + return ch->tone; +} + +static int update_noise(struct ayumi* ay) { + int bit0x3; + ay->noise_counter += 1; + if (ay->noise_counter >= (ay->noise_period << 1)) { + ay->noise_counter = 0; + bit0x3 = ((ay->noise ^ (ay->noise >> 3)) & 1); + ay->noise = (ay->noise >> 1) | (bit0x3 << 16); + } + return ay->noise & 1; +} + +static void slide_up(struct ayumi* ay) { + ay->envelope += 1; + if (ay->envelope > 31) { + ay->envelope_segment ^= 1; + reset_segment(ay); + } +} + +static void slide_down(struct ayumi* ay) { + ay->envelope -= 1; + if (ay->envelope < 0) { + ay->envelope_segment ^= 1; + reset_segment(ay); + } +} + +static void hold_top(struct ayumi* ay) { + (void) ay; +} + +static void hold_bottom(struct ayumi* ay) { + (void) ay; +} + +static void (* const Envelopes[][2])(struct ayumi*) = { + {slide_down, hold_bottom}, + {slide_down, hold_bottom}, + {slide_down, hold_bottom}, + {slide_down, hold_bottom}, + {slide_up, hold_bottom}, + {slide_up, hold_bottom}, + {slide_up, hold_bottom}, + {slide_up, hold_bottom}, + {slide_down, slide_down}, + {slide_down, hold_bottom}, + {slide_down, slide_up}, + {slide_down, hold_top}, + {slide_up, slide_up}, + {slide_up, hold_top}, + {slide_up, slide_down}, + {slide_up, hold_bottom} +}; + +static void reset_segment(struct ayumi* ay) { + if (Envelopes[ay->envelope_shape][ay->envelope_segment] == slide_down + || Envelopes[ay->envelope_shape][ay->envelope_segment] == hold_top) { + ay->envelope = 31; + return; + } + ay->envelope = 0; +} + +int update_envelope(struct ayumi* ay) { + ay->envelope_counter += 1; + if (ay->envelope_counter >= ay->envelope_period) { + ay->envelope_counter = 0; + Envelopes[ay->envelope_shape][ay->envelope_segment](ay); + } + return ay->envelope; +} + +static void update_mixer(struct ayumi* ay) { + int i; + int out; + int noise = update_noise(ay); + int envelope = update_envelope(ay); + ay->left = 0; + ay->right = 0; + for (i = 0; i < TONE_CHANNELS; i += 1) { + out = (update_tone(ay, i) | ay->channels[i].t_off) & (noise | ay->channels[i].n_off); + out *= ay->channels[i].e_on ? envelope : ay->channels[i].volume * 2 + 1; + ay->left += ay->dac_table[out] * ay->channels[i].pan_left; + ay->right += ay->dac_table[out] * ay->channels[i].pan_right; + } +} + +int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr) { + int i; + memset(ay, 0, sizeof(struct ayumi)); + ay->step = clock_rate / (sr * 8 * DECIMATE_FACTOR); + ay->dac_table = is_ym ? YM_dac_table : AY_dac_table; + ay->noise = 1; + ayumi_set_envelope(ay, 1); + for (i = 0; i < TONE_CHANNELS; i += 1) { + ayumi_set_tone(ay, i, 1); + } + return ay->step < 1; +} + +void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp) { + if (is_eqp) { + ay->channels[index].pan_left = sqrt(1 - pan); + ay->channels[index].pan_right = sqrt(pan); + } else { + ay->channels[index].pan_left = 1 - pan; + ay->channels[index].pan_right = pan; + } +} + +void ayumi_set_tone(struct ayumi* ay, int index, int period) { + period &= 0xfff; + ay->channels[index].tone_period = (period == 0) | period; +} + +void ayumi_set_noise(struct ayumi* ay, int period) { + period &= 0x1f; + ay->noise_period = (period == 0) | period; +} + +void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on) { + ay->channels[index].t_off = t_off & 1; + ay->channels[index].n_off = n_off & 1; + ay->channels[index].e_on = e_on; +} + +void ayumi_set_volume(struct ayumi* ay, int index, int volume) { + ay->channels[index].volume = volume & 0xf; +} + +void ayumi_set_envelope(struct ayumi* ay, int period) { + period &= 0xffff; + ay->envelope_period = (period == 0) | period; +} + +void ayumi_set_envelope_shape(struct ayumi* ay, int shape) { + ay->envelope_shape = shape & 0xf; + ay->envelope_counter = 0; + ay->envelope_segment = 0; + reset_segment(ay); +} + +static double decimate(double* x) { + double y = -0.0000046183113992051936 * (x[1] + x[191]) + + -0.00001117761640887225 * (x[2] + x[190]) + + -0.000018610264502005432 * (x[3] + x[189]) + + -0.000025134586135631012 * (x[4] + x[188]) + + -0.000028494281690666197 * (x[5] + x[187]) + + -0.000026396828793275159 * (x[6] + x[186]) + + -0.000017094212558802156 * (x[7] + x[185]) + + 0.000023798193576966866 * (x[9] + x[183]) + + 0.000051281160242202183 * (x[10] + x[182]) + + 0.00007762197826243427 * (x[11] + x[181]) + + 0.000096759426664120416 * (x[12] + x[180]) + + 0.00010240229300393402 * (x[13] + x[179]) + + 0.000089344614218077106 * (x[14] + x[178]) + + 0.000054875700118949183 * (x[15] + x[177]) + + -0.000069839082210680165 * (x[17] + x[175]) + + -0.0001447966132360757 * (x[18] + x[174]) + + -0.00021158452917708308 * (x[19] + x[173]) + + -0.00025535069106550544 * (x[20] + x[172]) + + -0.00026228714374322104 * (x[21] + x[171]) + + -0.00022258805927027799 * (x[22] + x[170]) + + -0.00013323230495695704 * (x[23] + x[169]) + + 0.00016182578767055206 * (x[25] + x[167]) + + 0.00032846175385096581 * (x[26] + x[166]) + + 0.00047045611576184863 * (x[27] + x[165]) + + 0.00055713851457530944 * (x[28] + x[164]) + + 0.00056212565121518726 * (x[29] + x[163]) + + 0.00046901918553962478 * (x[30] + x[162]) + + 0.00027624866838952986 * (x[31] + x[161]) + + -0.00032564179486838622 * (x[33] + x[159]) + + -0.00065182310286710388 * (x[34] + x[158]) + + -0.00092127787309319298 * (x[35] + x[157]) + + -0.0010772534348943575 * (x[36] + x[156]) + + -0.0010737727700273478 * (x[37] + x[155]) + + -0.00088556645390392634 * (x[38] + x[154]) + + -0.00051581896090765534 * (x[39] + x[153]) + + 0.00059548767193795277 * (x[41] + x[151]) + + 0.0011803558710661009 * (x[42] + x[150]) + + 0.0016527320270369871 * (x[43] + x[149]) + + 0.0019152679330965555 * (x[44] + x[148]) + + 0.0018927324805381538 * (x[45] + x[147]) + + 0.0015481870327877937 * (x[46] + x[146]) + + 0.00089470695834941306 * (x[47] + x[145]) + + -0.0010178225878206125 * (x[49] + x[143]) + + -0.0020037400552054292 * (x[50] + x[142]) + + -0.0027874356824117317 * (x[51] + x[141]) + + -0.003210329988021943 * (x[52] + x[140]) + + -0.0031540624117984395 * (x[53] + x[139]) + + -0.0025657163651900345 * (x[54] + x[138]) + + -0.0014750752642111449 * (x[55] + x[137]) + + 0.0016624165446378462 * (x[57] + x[135]) + + 0.0032591192839069179 * (x[58] + x[134]) + + 0.0045165685815867747 * (x[59] + x[133]) + + 0.0051838984346123896 * (x[60] + x[132]) + + 0.0050774264697459933 * (x[61] + x[131]) + + 0.0041192521414141585 * (x[62] + x[130]) + + 0.0023628575417966491 * (x[63] + x[129]) + + -0.0026543507866759182 * (x[65] + x[127]) + + -0.0051990251084333425 * (x[66] + x[126]) + + -0.0072020238234656924 * (x[67] + x[125]) + + -0.0082672928192007358 * (x[68] + x[124]) + + -0.0081033739572956287 * (x[69] + x[123]) + + -0.006583111539570221 * (x[70] + x[122]) + + -0.0037839040415292386 * (x[71] + x[121]) + + 0.0042781252851152507 * (x[73] + x[119]) + + 0.0084176358598320178 * (x[74] + x[118]) + + 0.01172566057463055 * (x[75] + x[117]) + + 0.013550476647788672 * (x[76] + x[116]) + + 0.013388189369997496 * (x[77] + x[115]) + + 0.010979501242341259 * (x[78] + x[114]) + + 0.006381274941685413 * (x[79] + x[113]) + + -0.007421229604153888 * (x[81] + x[111]) + + -0.01486456304340213 * (x[82] + x[110]) + + -0.021143584622178104 * (x[83] + x[109]) + + -0.02504275058758609 * (x[84] + x[108]) + + -0.025473530942547201 * (x[85] + x[107]) + + -0.021627310017882196 * (x[86] + x[106]) + + -0.013104323383225543 * (x[87] + x[105]) + + 0.017065133989980476 * (x[89] + x[103]) + + 0.036978919264451952 * (x[90] + x[102]) + + 0.05823318062093958 * (x[91] + x[101]) + + 0.079072012081405949 * (x[92] + x[100]) + + 0.097675998716952317 * (x[93] + x[99]) + + 0.11236045936950932 * (x[94] + x[98]) + + 0.12176343577287731 * (x[95] + x[97]) + + 0.125 * x[96]; + memcpy(&x[FIR_SIZE - DECIMATE_FACTOR], x, DECIMATE_FACTOR * sizeof(double)); + return y; +} + +void ayumi_process(struct ayumi* ay) { + int i; + double y1; + double* c_left = ay->interpolator_left.c; + double* y_left = ay->interpolator_left.y; + double* c_right = ay->interpolator_right.c; + double* y_right = ay->interpolator_right.y; + double* fir_left = &ay->fir_left[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR]; + double* fir_right = &ay->fir_right[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR]; + ay->fir_index = (ay->fir_index + 1) % (FIR_SIZE / DECIMATE_FACTOR - 1); + for (i = DECIMATE_FACTOR - 1; i >= 0; i -= 1) { + ay->x += ay->step; + if (ay->x >= 1) { + ay->x -= 1; + y_left[0] = y_left[1]; + y_left[1] = y_left[2]; + y_left[2] = y_left[3]; + y_right[0] = y_right[1]; + y_right[1] = y_right[2]; + y_right[2] = y_right[3]; + update_mixer(ay); + y_left[3] = ay->left; + y_right[3] = ay->right; + y1 = y_left[2] - y_left[0]; + c_left[0] = 0.5 * y_left[1] + 0.25 * (y_left[0] + y_left[2]); + c_left[1] = 0.5 * y1; + c_left[2] = 0.25 * (y_left[3] - y_left[1] - y1); + y1 = y_right[2] - y_right[0]; + c_right[0] = 0.5 * y_right[1] + 0.25 * (y_right[0] + y_right[2]); + c_right[1] = 0.5 * y1; + c_right[2] = 0.25 * (y_right[3] - y_right[1] - y1); + } + fir_left[i] = (c_left[2] * ay->x + c_left[1]) * ay->x + c_left[0]; + fir_right[i] = (c_right[2] * ay->x + c_right[1]) * ay->x + c_right[0]; + } + ay->left = decimate(fir_left); + ay->right = decimate(fir_right); +} + +static double dc_filter(struct dc_filter* dc, int index, double x) { + dc->sum += -dc->delay[index] + x; + dc->delay[index] = x; + return x - dc->sum / DC_FILTER_SIZE; +} + +void ayumi_remove_dc(struct ayumi* ay) { + ay->left = dc_filter(&ay->dc_left, ay->dc_index, ay->left); + ay->right = dc_filter(&ay->dc_right, ay->dc_index, ay->right); + ay->dc_index = (ay->dc_index + 1) & (DC_FILTER_SIZE - 1); +} diff --git a/src/sound/ayumi/ayumi.h b/src/sound/ayumi/ayumi.h new file mode 100644 index 000000000..f15939514 --- /dev/null +++ b/src/sound/ayumi/ayumi.h @@ -0,0 +1,71 @@ +/* Author: Peter Sovietov */ + +#ifndef AYUMI_H +#define AYUMI_H + +enum { + TONE_CHANNELS = 3, + DECIMATE_FACTOR = 8, + FIR_SIZE = 192, + DC_FILTER_SIZE = 1024 +}; + +struct tone_channel { + int tone_period; + int tone_counter; + int tone; + int t_off; + int n_off; + int e_on; + int volume; + double pan_left; + double pan_right; +}; + +struct interpolator { + double c[4]; + double y[4]; +}; + +struct dc_filter { + double sum; + double delay[DC_FILTER_SIZE]; +}; + +struct ayumi { + struct tone_channel channels[TONE_CHANNELS]; + int noise_period; + int noise_counter; + int noise; + int envelope_counter; + int envelope_period; + int envelope_shape; + int envelope_segment; + int envelope; + const double* dac_table; + double step; + double x; + struct interpolator interpolator_left; + struct interpolator interpolator_right; + double fir_left[FIR_SIZE * 2]; + double fir_right[FIR_SIZE * 2]; + int fir_index; + struct dc_filter dc_left; + struct dc_filter dc_right; + int dc_index; + double left; + double right; +}; + +int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr); +void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp); +void ayumi_set_tone(struct ayumi* ay, int index, int period); +void ayumi_set_noise(struct ayumi* ay, int period); +void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on); +void ayumi_set_volume(struct ayumi* ay, int index, int volume); +void ayumi_set_envelope(struct ayumi* ay, int period); +void ayumi_set_envelope_shape(struct ayumi* ay, int shape); +void ayumi_process(struct ayumi* ay); +void ayumi_remove_dc(struct ayumi* ay); + +#endif diff --git a/src/sound/snd_mmb.c b/src/sound/snd_mmb.c new file mode 100644 index 000000000..35a72efbc --- /dev/null +++ b/src/sound/snd_mmb.c @@ -0,0 +1,339 @@ +/* + * 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. + * + * Mindscape Music Board emulation. + * + * Authors: Roy Baer, + * Jasmine Iwanek, + * + * Copyright 2025 Roy Baer. + * Copyright 2025 Jasmine Iwanek. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/sound.h> +//#i nclude "cpu.h" +#include "ayumi/ayumi.h" +#include <86box/snd_mmb.h> +#include <86box/plat_unused.h> + +#ifdef ENABLE_MMB_LOG +int mmb_do_log = ENABLE_MMB_LOG; + +static void +mmb_log(const char *fmt, ...) +{ + va_list ap; + + if (mmb_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define mmb_log(fmt, ...) +#endif + +void +mmb_update(mmb_t *mmb) +{ + for (; mmb->pos < sound_pos_global; mmb->pos++) { + ayumi_process(&mmb->first.chip); + ayumi_process(&mmb->second.chip); + + ayumi_remove_dc(&mmb->first.chip); + ayumi_remove_dc(&mmb->second.chip); + + mmb->buffer[mmb->pos << 1] = (mmb->first.chip.left + mmb->second.chip.left) * 16000; + mmb->buffer[(mmb->pos << 1) + 1] = (mmb->first.chip.right + mmb->second.chip.right) * 16000; + } +} + +void +mmb_get_buffer(int32_t *buffer, int len, void *priv) +{ + mmb_t *mmb = (mmb_t *) priv; + + mmb_update(mmb); + + for (int c = 0; c < len * 2; c++) + buffer[c] += mmb->buffer[c]; + + mmb->pos = 0; +} + +void +mmb_write(uint16_t addr, uint8_t val, void *priv) +{ + mmb_t *mmb = (mmb_t *) priv; + + mmb_update(mmb); + + mmb_log("mmb_write(%04X): activity now: %02X\n", addr, val); + + switch (addr & 3) { + case 0: + mmb->first.index = val; + break; + case 2: + mmb->second.index = val; + break; + case 1: + case 3: + { + ay_3_891x_t *ay = ((addr & 2) == 0) ? &mmb->first : &mmb->second; + + switch (ay->index) { + case 0: + ay->regs[0] = val; + ayumi_set_tone(&ay->chip, 0, (ay->regs[1] << 8) | ay->regs[0]); + break; + case 1: + ay->regs[1] = val & 0xf; + ayumi_set_tone(&ay->chip, 0, (ay->regs[1] << 8) | ay->regs[0]); + break; + case 2: + ay->regs[2] = val; + ayumi_set_tone(&ay->chip, 1, (ay->regs[3] << 8) | ay->regs[2]); + break; + case 3: + ay->regs[3] = val & 0xf; + ayumi_set_tone(&ay->chip, 1, (ay->regs[3] << 8) | ay->regs[2]); + break; + case 4: + ay->regs[4] = val; + ayumi_set_tone(&ay->chip, 2, (ay->regs[5] << 8) | ay->regs[4]); + break; + case 5: + ay->regs[5] = val & 0xf; + ayumi_set_tone(&ay->chip, 2, (ay->regs[5] << 8) | ay->regs[4]); + break; + case 6: + ay->regs[6] = val & 0x1f; + ayumi_set_noise(&ay->chip, ay->regs[6]); + break; + case 7: + ay->regs[7] = val; + ayumi_set_mixer(&ay->chip, 0, val & 1, (val >> 3) & 1, (ay->regs[8] >> 4) & 1); + ayumi_set_mixer(&ay->chip, 1, (val >> 1) & 1, (val >> 4) & 1, (ay->regs[9] >> 4) & 1); + ayumi_set_mixer(&ay->chip, 2, (val >> 2) & 1, (val >> 5) & 1, (ay->regs[10] >> 4) & 1); + break; + case 8: + ay->regs[8] = val; + ayumi_set_volume(&ay->chip, 0, val & 0xf); + ayumi_set_mixer(&ay->chip, 0, ay->regs[7] & 1, (ay->regs[7] >> 3) & 1, (val >> 4) & 1); + break; + case 9: + ay->regs[9] = val; + ayumi_set_volume(&ay->chip, 1, val & 0xf); + ayumi_set_mixer(&ay->chip, 1, (ay->regs[7] >> 1) & 1, (ay->regs[7] >> 4) & 1, (val >> 4) & 1); + break; + case 10: + ay->regs[10] = val; + ayumi_set_volume(&ay->chip, 2, val & 0xf); + ayumi_set_mixer(&ay->chip, 2, (ay->regs[7] >> 2) & 1, (ay->regs[7] >> 5) & 1, (val >> 4) & 1); + break; + case 11: + ay->regs[11] = val; + ayumi_set_envelope(&ay->chip, (ay->regs[12] >> 8) | ay->regs[11]); + break; + case 12: + ay->regs[12] = val; + ayumi_set_envelope(&ay->chip, (ay->regs[12] >> 8) | ay->regs[11]); + break; + case 13: + ay->regs[13] = val; + ayumi_set_envelope_shape(&ay->chip, val & 0xf); + break; + case 14: + ay->regs[14] = val; + break; + case 15: + ay->regs[15] = val; + break; + + default: + break; + } + break; + } + + default: + break; + } +} + +uint8_t +mmb_read(uint16_t addr, void *priv) +{ + mmb_t *mmb = (mmb_t *) priv; + ay_3_891x_t *ay = ((addr & 2) == 0) ? &mmb->first : &mmb->second; + uint8_t ret = 0; + + switch (ay->index) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + ret = ay->regs[ay->index]; + break; + case 14: + if (ay->regs[7] & 0x40) + ret = ay->regs[14]; + break; + case 15: + if (ay->regs[7] & 0x80) + ret = ay->regs[15]; + break; + + default: + break; + } + + mmb_log("mmb_read(%04X): activity now: %02X\n", addr, ret); + + return ret; +} + +void * +mmb_init(UNUSED(const device_t *info)) +{ + mmb_t *mmb = calloc(1, sizeof(mmb_t)); +# if 0 + uint16_t addr = (device_get_config_int("addr96") << 6) | (device_get_config_int("addr52") << 2); +#else + uint16_t addr = 0x300; + +#endif + sound_add_handler(mmb_get_buffer, mmb); + + ayumi_configure(&mmb->first.chip, 0, MMB_CLOCK, MMB_FREQ); + ayumi_configure(&mmb->second.chip, 0, MMB_CLOCK, MMB_FREQ); + + for (uint8_t i = 0; i < 3; i++) { + ayumi_set_pan(&mmb->first.chip, i, 0.5, 1); + ayumi_set_pan(&mmb->second.chip, i, 0.5, 1); + } + + io_sethandler(addr, 0x0004, + mmb_read, NULL, NULL, + mmb_write, NULL, NULL, + mmb); + + return mmb; +} + +void +mmb_close(void *priv) +{ + mmb_t *mmb = (mmb_t *) priv; + + free(mmb); +} + +// clang-format off +#if 0 +static device_config_t mmb_config[] = { + { + .name = "addr96", + .description = "Base address A9...A6", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 12, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0000", .value = 0 }, + { .description = "0001", .value = 1 }, + { .description = "0010", .value = 2 }, + { .description = "0011", .value = 3 }, + { .description = "0100", .value = 4 }, + { .description = "0101", .value = 5 }, + { .description = "0110", .value = 6 }, + { .description = "0111", .value = 7 }, + { .description = "1000", .value = 8 }, + { .description = "1001", .value = 9 }, + { .description = "1010", .value = 10 }, + { .description = "1011", .value = 11 }, + { .description = "1100", .value = 12 }, + { .description = "1101", .value = 13 }, + { .description = "1110", .value = 14 }, + { .description = "1111", .value = 15 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "addr52", + .description = "Base address A5...A2", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0000", .value = 0 }, + { .description = "0001", .value = 1 }, + { .description = "0010", .value = 2 }, + { .description = "0011", .value = 3 }, + { .description = "0100", .value = 4 }, + { .description = "0101", .value = 5 }, + { .description = "0110", .value = 6 }, + { .description = "0111", .value = 7 }, + { .description = "1000", .value = 8 }, + { .description = "1001", .value = 9 }, + { .description = "1010", .value = 10 }, + { .description = "1011", .value = 11 }, + { .description = "1100", .value = 12 }, + { .description = "1101", .value = 13 }, + { .description = "1110", .value = 14 }, + { .description = "1111", .value = 15 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .type = CONFIG_END } +}; +#endif +// clang-format on + +const device_t mmb_device = { + .name = "Mindscape Music Board", + .internal_name = "mmb", + .flags = DEVICE_ISA, + .local = 0, + .init = mmb_init, + .close = mmb_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, +#if 0 + .config = mmb_config +#else + .config = NULL +#endif +}; diff --git a/src/sound/sound.c b/src/sound/sound.c index 0c8dffe12..c3ecc8632 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -137,6 +137,7 @@ static const SOUND_CARD sound_cards[] = { { &sb_vibra16xv_device }, { &ssi2001_device }, { &entertainer_device }, + { &mmb_device }, { &pasplus_device }, { &pas16_device }, { &pas16d_device }, From 4033f81c4888b211d06afdf38cf19c6da650e2b2 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 25 May 2025 20:15:14 -0400 Subject: [PATCH 0996/1190] Clean up sound/CMakeLists.txt --- src/sound/CMakeLists.txt | 9 +++++---- src/sound/esfmu/CMakeLists.txt | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/sound/esfmu/CMakeLists.txt diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 3aaf49bb3..fb3c9b43d 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -49,8 +49,6 @@ add_library(snd OBJECT snd_wss.c snd_ym7128.c snd_optimc.c - esfmu/esfm.c - esfmu/esfm_registers.c snd_opl_esfm.c ) @@ -181,6 +179,9 @@ endif() add_subdirectory(ayumi) target_link_libraries(86Box ayumi) +add_subdirectory(esfmu) +target_link_libraries(86Box esfmu) + add_subdirectory(ymfm) target_link_libraries(86Box ymfm) @@ -193,8 +194,8 @@ if(OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) endif() -find_package(PkgConfig ) -pkg_check_modules(SERIALPORT libserialport) +find_package(PkgConfig) +pkg_check_modules(SERIALPORT libserialport) if(SERIALPORT_FOUND OR DEFINED LIBSERIALPORT_ROOT) add_compile_definitions(USE_LIBSERIALPORT=1) diff --git a/src/sound/esfmu/CMakeLists.txt b/src/sound/esfmu/CMakeLists.txt new file mode 100644 index 000000000..2505038f1 --- /dev/null +++ b/src/sound/esfmu/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# 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. +# + +add_library(esfmu STATIC + esfm.c + esfm_registers.c +) From 09f63b6466450c7b22df74584ded24d71048d2de Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 May 2025 04:47:45 +0200 Subject: [PATCH 0997/1190] Assorted fixes, the Compaq Presario 7100 486 no longer crashes on CTRL+ALT+DEL. --- src/chipset/umc_hb4.c | 53 ++----------------------------------------- src/device/kbc_at.c | 4 +++- src/mem/mem.c | 12 ++++++---- src/mem/smram.c | 15 +++++++++--- 4 files changed, 24 insertions(+), 60 deletions(-) diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index 889691988..55901b32e 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -270,6 +270,8 @@ hb4_smram(hb4_t *dev) } umc_smram_recalc(dev->smram_base >> 12, 1); + + flushmmucache(); } static void @@ -398,55 +400,6 @@ hb4_close(void *priv) free(dev); } -static void -ims8848_write(uint16_t addr, uint8_t val, void *priv) -{ - hb4_t *dev = (hb4_t *) priv; - - switch (addr) { - case 0x22: - dev->idx = val; - break; - case 0x23: - if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) - dev->access_data = 1; - break; - case 0x24: - if (dev->access_data) - dev->access_data = 0; - break; - - default: - break; - } -} - -static uint8_t -ims8848_read(uint16_t addr, void *priv) -{ - uint8_t ret = 0xff; - hb4_t *dev = (hb4_t *) priv; - - switch (addr) { - case 0x22: - ret = dev->idx; - break; - case 0x23: - ret = (dev->idx >> 4) | (dev->idx << 4); - break; - case 0x24: - if (dev->access_data) { - ret = dev->pci_conf[dev->idx]; - dev->access_data = 0; - } - break; - default: - break; - } - - return ret; -} - static void * hb4_init(UNUSED(const device_t *info)) { @@ -463,8 +416,6 @@ hb4_init(UNUSED(const device_t *info)) dev->smram_base = 0x000a0000; hb4_reset(dev); - io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); - return dev; } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index dc93a4fba..8840a0e4d 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -830,7 +830,9 @@ write_p2(atkbc_t *dev, uint8_t val) softresetx86(); /* Pulse reset! */ cpu_set_edx(); flushmmucache(); - if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw")) + if ((kbc_ven == KBC_VEN_ALI) || + !strcmp(machine_get_internal_name(), "spc7700plw") || + !strcmp(machine_get_internal_name(), "pl4600c")) smbase = 0x00030000; /* Yes, this is a hack, but until someone gets ahold of the real PCD-2L diff --git a/src/mem/mem.c b/src/mem/mem.c index 07d897172..d365ecffb 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -2994,10 +2994,12 @@ mem_init(void) } static void -umc_page_recalc(uint32_t c, int set) +umc_page_recalc(uint32_t c, uint32_t phys, int set) { + uint32_t target = set ? phys : c; + if (set) { - pages[c].mem = &ram[(c & 0xff) << 12]; + pages[c].mem = &ram[(target & 0xff) << 12]; pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; @@ -3010,8 +3012,8 @@ umc_page_recalc(uint32_t c, int set) #ifdef USE_NEW_DYNAREC pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[(c & 0xff) * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[(c & 0xff) * 64]; + pages[c].byte_dirty_mask = &byte_dirty_mask[(target & 0xff) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(target & 0xff) * 64]; #endif } @@ -3019,7 +3021,7 @@ void umc_smram_recalc(uint32_t start, int set) { for (uint32_t c = start; c < (start + 0x0020); c++) - umc_page_recalc(c, set); + umc_page_recalc(c, c - start + 0x000a0000, set); } static void diff --git a/src/mem/smram.c b/src/mem/smram.c index afbc5475c..928760f3a 100644 --- a/src/mem/smram.c +++ b/src/mem/smram.c @@ -59,9 +59,12 @@ smram_read(uint32_t addr, void *priv) const smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (new_addr >= (1 << 30)) return mem_read_ram_2gb(new_addr, priv); - else if (!use_separate_smram || (new_addr >= 0xa0000)) + else +#endif + if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_ram(new_addr, priv); else return dev->mapping.exec[addr - dev->host_base]; @@ -73,9 +76,12 @@ smram_readw(uint32_t addr, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (new_addr >= (1 << 30)) return mem_read_ram_2gbw(new_addr, priv); - else if (!use_separate_smram || (new_addr >= 0xa0000)) + else +#endif + if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_ramw(new_addr, priv); else return *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]); @@ -87,9 +93,12 @@ smram_readl(uint32_t addr, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (new_addr >= (1 << 30)) return mem_read_ram_2gbl(new_addr, priv); - else if (!use_separate_smram || (new_addr >= 0xa0000)) + else +#endif + if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_raml(new_addr, priv); else return *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]); From 8e895903ed2373372f2b0a2e22669e21abdfddae Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 26 May 2025 04:38:28 -0400 Subject: [PATCH 0998/1190] Alternate font support for MDA and Hercules --- src/include/86box/video.h | 35 +++++---- src/machine/m_amstrad.c | 2 +- src/machine/m_pcjr.c | 2 +- src/video/vid_hercules.c | 44 ++++++++++-- src/video/vid_mda.c | 45 +++++++++++- src/video/vid_table.c | 2 +- src/video/video.c | 144 ++++++++++++++++++-------------------- 7 files changed, 176 insertions(+), 98 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 085dd5f80..6a73c6462 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -36,6 +36,10 @@ using atomic_int = std::atomic_int; #define getcolg(color) (((color) >> 8) & 0xFF) #define getcolb(color) ((color) & 0xFF) +#ifdef __cplusplus +extern "C" { +#endif + enum { VID_NONE = 0, VID_INTERNAL @@ -49,10 +53,6 @@ enum { FULLSCR_SCALE_INT43 }; -#ifdef __cplusplus -extern "C" { -#endif - enum { VIDEO_ISA = 0, VIDEO_MCA, @@ -71,6 +71,11 @@ enum { #define VIDEO_FLAG_TYPE_SECONDARY VIDEO_FLAG_TYPE_SPECIAL +#define FONT_IBM_MDA_437_PATH "roms/video/mda/mda.rom" +#define FONT_IBM_MDA_437_NORDIC_PATH "roms/video/mda/4733197.bin" +#define FONT_KAM_PATH "roms/video/mda/kam.bin" +#define FONT_KAMCL16_PATH "roms/video/mda/kamcl16.bin" + typedef struct video_timings_t { int type; int write_b; @@ -189,15 +194,15 @@ extern uint32_t pal_lookup[256]; #endif extern int video_fullscreen; extern int video_fullscreen_scale; -extern uint8_t fontdat[2048][8]; -extern uint8_t fontdatm[2048][16]; -extern uint8_t fontdat2[2048][8]; -extern uint8_t fontdatm2[2048][16]; -extern uint8_t fontdatw[512][32]; -extern uint8_t fontdat8x12[256][16]; -extern uint8_t fontdat12x18[256][36]; -extern dbcs_font_t *fontdatksc5601; -extern dbcs_font_t *fontdatksc5601_user; +extern uint8_t fontdat[2048][8]; /* IBM CGA font */ +extern uint8_t fontdatm[2048][16]; /* IBM MDA font */ +extern uint8_t fontdat2[2048][8]; /* IBM CGA 2nd instance font */ +extern uint8_t fontdatm2[2048][16]; /* IBM MDA 2nd instance font */ +extern uint8_t fontdatw[512][32]; /* Wyse700 font */ +extern uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ +extern uint8_t fontdat12x18[256][36]; /* IM1024 font */ +extern dbcs_font_t *fontdatksc5601; /* Korean KSC-5601 font */ +extern dbcs_font_t *fontdatksc5601_user; /* Korean KSC-5601 user defined font */ extern uint32_t *video_6to8; extern uint32_t *video_8togs; extern uint32_t *video_8to32; @@ -277,8 +282,8 @@ extern uint8_t video_force_resize_get_monitor(int monitor_index); extern void video_force_resize_set_monitor(uint8_t res, int monitor_index); extern void video_update_timing(void); -extern void loadfont_ex(char *s, int format, int offset); -extern void loadfont(char *s, int format); +extern void loadfont_ex(char *fn, int format, int offset); +extern void loadfont(char *fn, int format); extern int get_actual_size_x(void); extern int get_actual_size_y(void); diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 3dba578bd..814d95ffd 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2936,7 +2936,7 @@ machine_amstrad_init(const machine_t *model, int type) break; case AMS_PC1640: - loadfont("roms/video/mda/mda.rom", 0); + loadfont(FONT_IBM_MDA_437_PATH, 0); device_context(&vid_1640_device); ams->language = device_get_config_int("language"); vid_init_1640(ams); diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index d4d3b09cf..cb69bd9e5 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -1541,7 +1541,7 @@ machine_pcjr_init(UNUSED(const machine_t *model)) /* Initialize the video controller. */ video_reset(gfxcard[0]); - loadfont("roms/video/mda/mda.rom", 0); + loadfont(FONT_IBM_MDA_437_PATH, 0); device_context(&pcjr_device); pcjr_vid_init(pcjr); device_context_restore(); diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 00374d08f..af8ad08f8 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -543,14 +543,33 @@ hercules_init(UNUSED(const device_t *info)) dev->vram = (uint8_t *) malloc(0x10000); + switch(device_get_config_int("font")) { + case 0: + loadfont(FONT_IBM_MDA_437_PATH, 0); + break; + case 1: + loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0); + break; + case 2: + loadfont(FONT_KAM_PATH, 0); + break; + case 3: + loadfont(FONT_KAMCL16_PATH, 0); + break; + } + timer_add(&dev->timer, hercules_poll, dev, 1); mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, - hercules_read, NULL, NULL, hercules_write, NULL, NULL, - NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev); + hercules_read, NULL, NULL, + hercules_write, NULL, NULL, + NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, + dev); - io_sethandler(0x03b0, 16, - hercules_in, NULL, NULL, hercules_out, NULL, NULL, dev); + io_sethandler(0x03b0, 0x0010, + hercules_in, NULL, NULL, + hercules_out, NULL, NULL, + dev); for (uint16_t c = 0; c < 256; c++) { dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; @@ -642,6 +661,23 @@ static const device_config_t hercules_config[] = { .selection = { { 0 } }, .bios = { { 0 } } }, + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "US (CP 437)", .value = 0 }, + { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, + { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, + { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 66a0fbb71..7b6e54806 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -317,8 +317,32 @@ mda_standalone_init(UNUSED(const device_t *info)) mda->vram = malloc(0x1000); - mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); - io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); + switch(device_get_config_int("font")) { + case 0: + loadfont(FONT_IBM_MDA_437_PATH, 0); + break; + case 1: + loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0); + break; + + case 2: + loadfont(FONT_KAM_PATH, 0); + break; + case 3: + loadfont(FONT_KAMCL16_PATH, 0); + break; + } + + mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, + mda_read, NULL, NULL, + mda_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, + mda); + + io_sethandler(0x03b0, 0x0010, + mda_in, NULL, NULL, + mda_out, NULL, NULL, + mda); mda_init(mda); @@ -369,6 +393,23 @@ static const device_config_t mda_config[] = { }, .bios = { { 0 } } }, + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "US (CP 437)", .value = 0 }, + { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, + { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, + { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index e0ef7ada6..33a7f30ca 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -328,7 +328,7 @@ video_reset(int card) card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0); monitor_index_global = 0; - loadfont("roms/video/mda/mda.rom", 0); + loadfont(FONT_IBM_MDA_437_PATH, 0); for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if ((card != VID_NONE) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY) && diff --git a/src/video/video.c b/src/video/video.c index 0773e61ce..11edbc3f4 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -1006,76 +1006,73 @@ video_force_resize_set_monitor(uint8_t res, int monitor_index) } void -loadfont_common(FILE *f, int format) +loadfont_common(FILE *fp, int format) { - int c; - int d; - switch (format) { case 0: /* MDA */ - for (c = 0; c < 256; c++) - for (d = 0; d < 8; d++) - fontdatm[c][d] = fgetc(f) & 0xff; - for (c = 0; c < 256; c++) - for (d = 0; d < 8; d++) - fontdatm[c][d + 8] = fgetc(f) & 0xff; - (void) fseek(f, 4096 + 2048, SEEK_SET); - for (c = 0; c < 256; c++) - for (d = 0; d < 8; d++) - fontdat[c][d] = fgetc(f) & 0xff; + for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x8 cell (lines 0-7) */ + for (uint8_t d = 0; d < 8; d++) + fontdatm[c][d] = fgetc(fp) & 0xff; + for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x8 cell (lines 8-13 + padding lines) */ + for (uint8_t d = 0; d < 8; d++) + fontdatm[c][d + 8] = fgetc(fp) & 0xff; + (void) fseek(fp, 4096 + 2048, SEEK_SET); + for (uint16_t c = 0; c < 256; c++) + for (uint8_t d = 0; d < 8; d++) /* 8x8 CGA (thick, primary) */ + fontdat[c][d] = fgetc(fp) & 0xff; break; case 1: /* PC200 */ - for (d = 0; d < 4; d++) { + for (uint8_t d = 0; d < 4; d++) { /* There are 4 fonts in the ROM */ - for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ - (void) !fread(&fontdatm[256 * d + c][0], 1, 16, f); - for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ - (void) !fread(&fontdat[256 * d + c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); + for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ + (void) !fread(&fontdatm[256 * d + c][0], 1, 16, fp); + for (uint16_t c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ + (void) !fread(&fontdat[256 * d + c][0], 1, 8, fp); + fseek(fp, 8, SEEK_CUR); } } break; default: case 2: /* CGA */ - for (c = 0; c < 256; c++) - for (d = 0; d < 8; d++) - fontdat[c][d] = fgetc(f) & 0xff; + for (uint16_t c = 0; c < 256; c++) + for (uint8_t d = 0; d < 8; d++) + fontdat[c][d] = fgetc(fp) & 0xff; break; case 3: /* Wyse 700 */ - for (c = 0; c < 512; c++) - for (d = 0; d < 32; d++) - fontdatw[c][d] = fgetc(f) & 0xff; + for (uint16_t c = 0; c < 512; c++) + for (uint8_t d = 0; d < 32; d++) + fontdatw[c][d] = fgetc(fp) & 0xff; break; case 4: /* MDSI Genius */ - for (c = 0; c < 256; c++) - for (d = 0; d < 16; d++) - fontdat8x12[c][d] = fgetc(f) & 0xff; + for (uint16_t c = 0; c < 256; c++) + for (uint8_t d = 0; d < 16; d++) + fontdat8x12[c][d] = fgetc(fp) & 0xff; break; - case 5: /* Toshiba 3100e */ - for (d = 0; d < 2048; d += 512) { /* Four languages... */ - for (c = d; c < d + 256; c++) { - (void) !fread(&fontdatm[c][8], 1, 8, f); + case 5: /* Toshiba 3100e */ + for (uint16_t d = 0; d < 2048; d += 512) { /* Four languages... */ + for (uint16_t c = d; c < d + 256; c++) { + (void) !fread(&fontdatm[c][8], 1, 8, fp); } - for (c = d + 256; c < d + 512; c++) { - (void) !fread(&fontdatm[c][8], 1, 8, f); + for (uint16_t c = d + 256; c < d + 512; c++) { + (void) !fread(&fontdatm[c][8], 1, 8, fp); } - for (c = d; c < d + 256; c++) { - (void) !fread(&fontdatm[c][0], 1, 8, f); + for (uint16_t c = d; c < d + 256; c++) { + (void) !fread(&fontdatm[c][0], 1, 8, fp); } - for (c = d + 256; c < d + 512; c++) { - (void) !fread(&fontdatm[c][0], 1, 8, f); + for (uint16_t c = d + 256; c < d + 512; c++) { + (void) !fread(&fontdatm[c][0], 1, 8, fp); } - fseek(f, 4096, SEEK_CUR); /* Skip blank section */ - for (c = d; c < d + 256; c++) { - (void) !fread(&fontdat[c][0], 1, 8, f); + fseek(fp, 4096, SEEK_CUR); /* Skip blank section */ + for (uint16_t c = d; c < d + 256; c++) { + (void) !fread(&fontdat[c][0], 1, 8, fp); } - for (c = d + 256; c < d + 512; c++) { - (void) !fread(&fontdat[c][0], 1, 8, f); + for (uint16_t c = d + 256; c < d + 512; c++) { + (void) !fread(&fontdat[c][0], 1, 8, fp); } } break; @@ -1087,65 +1084,64 @@ loadfont_common(FILE *f, int format) if (!fontdatksc5601_user) fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t)); - for (c = 0; c < 16384; c++) { - for (d = 0; d < 32; d++) - fontdatksc5601[c].chr[d] = fgetc(f) & 0xff; + for (uint32_t c = 0; c < 16384; c++) { + for (uint8_t d = 0; d < 32; d++) + fontdatksc5601[c].chr[d] = fgetc(fp) & 0xff; } break; case 7: /* Sigma Color 400 */ /* The first 4k of the character ROM holds an 8x8 font */ - for (c = 0; c < 256; c++) { - (void) !fread(&fontdat[c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); + for (uint16_t c = 0; c < 256; c++) { + (void) !fread(&fontdat[c][0], 1, 8, fp); + fseek(fp, 8, SEEK_CUR); } /* The second 4k holds an 8x16 font */ - for (c = 0; c < 256; c++) { - if (fread(&fontdatm[c][0], 1, 16, f) != 16) + for (uint16_t c = 0; c < 256; c++) { + if (fread(&fontdatm[c][0], 1, 16, fp) != 16) fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c); } break; - case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ - for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */ - for (d = 0; d < 8; d++) - fontdat[c][d] = fgetc(f) & 0xff; + case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ + for (uint16_t c = 0; c < 2048; c++) /* Allow up to 2048 chars */ + for (uint8_t d = 0; d < 8; d++) + fontdat[c][d] = fgetc(fp) & 0xff; break; case 9: /* Image Manager 1024 native font */ - for (c = 0; c < 256; c++) - (void) !fread(&fontdat12x18[c][0], 1, 36, f); + for (uint16_t c = 0; c < 256; c++) + (void) !fread(&fontdat12x18[c][0], 1, 36, fp); break; - case 10: /* Pravetz */ - for (c = 0; c < 1024; c++) /* Allow up to 1024 chars */ - for (d = 0; d < 8; d++) - fontdat[c][d] = fgetc(f) & 0xff; + case 10: /* Pravetz */ + for (uint16_t c = 0; c < 1024; c++) /* Allow up to 1024 chars */ + for (uint8_t d = 0; d < 8; d++) + fontdat[c][d] = fgetc(fp) & 0xff; break; - case 11: /* PC200 */ - for (d = 0; d < 4; d++) { + for (uint8_t d = 0; d < 4; d++) { /* There are 4 fonts in the ROM */ - for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ - (void) !fread(&fontdatm2[256 * d + c][0], 1, 16, f); - for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ - (void) !fread(&fontdat2[256 * d + c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); + for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ + (void) !fread(&fontdatm2[256 * d + c][0], 1, 16, fp); + for (uint16_t c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ + (void) !fread(&fontdat2[256 * d + c][0], 1, 8, fp); + fseek(fp, 8, SEEK_CUR); } } break; } - (void) fclose(f); + (void) fclose(fp); } void -loadfont_ex(char *s, int format, int offset) +loadfont_ex(char *fn, int format, int offset) { FILE *fp; - fp = rom_fopen(s, "rb"); + fp = rom_fopen(fn, "rb"); if (fp == NULL) return; @@ -1154,9 +1150,9 @@ loadfont_ex(char *s, int format, int offset) } void -loadfont(char *s, int format) +loadfont(char *fn, int format) { - loadfont_ex(s, format, 0); + loadfont_ex(fn, format, 0); } uint32_t From eac0006e7fc6923cac973dbe4c69fa478e3fd1ab Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Tue, 27 May 2025 23:40:14 +0300 Subject: [PATCH 0999/1190] Add the Dell System 200 machine --- src/include/86box/machine.h | 1 + src/machine/m_at_286_386sx.c | 18 ++++++++++++++++ src/machine/machine_table.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0dbbe98c5..ac26f7a50 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -475,6 +475,7 @@ extern int machine_at_spc4216p_init(const machine_t *); extern int machine_at_spc4620p_init(const machine_t *); extern int machine_at_kmxc02_init(const machine_t *); extern int machine_at_deskmaster286_init(const machine_t *); +extern int machine_at_dells200_init(const machine_t *); extern int machine_at_pc8_init(const machine_t *); extern int machine_at_3302_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index e7aa66662..8400e4ae8 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -261,6 +261,24 @@ machine_at_px286_init(const machine_t *model) return ret; } +int +machine_at_dells200_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/dells200/dellL200256_LO_@DIP28.BIN", + "roms/machines/dells200/Dell200256_HI_@DIP28.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_ide_init(model); + device_add(&keyboard_at_device); + + return ret; +} + int machine_at_micronics386_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a3a02bfcd..d2ef357e1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2975,6 +2975,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC + firmware. */ + { + .name = "[ISA] Dell System 200", + .internal_name = "dells200", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_at_dells200_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 12000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .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 = "[ISA] MR BIOS 286 clone", From cebf27f02d134c77877ef430a9d690795e245d12 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 04:09:47 +0200 Subject: [PATCH 1000/1190] Finish the Dell System 200 work. --- src/chipset/CMakeLists.txt | 1 + src/chipset/cs8220.c | 289 +++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 1 + src/include/86box/machine.h | 1 + src/machine/m_at_286_386sx.c | 10 +- src/machine/machine_table.c | 89 +++++------ 6 files changed, 345 insertions(+), 46 deletions(-) create mode 100644 src/chipset/cs8220.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 7d17b9983..7a8233003 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(chipset OBJECT 82c100.c acc2168.c + cs8220.c cs8230.c ali1429.c ali1435.c diff --git a/src/chipset/cs8220.c b/src/chipset/cs8220.c new file mode 100644 index 000000000..4c08ecef5 --- /dev/null +++ b/src/chipset/cs8220.c @@ -0,0 +1,289 @@ +/* + * 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 C&T CS8220 ("PC/AT") chipset. + * + * Authors: Miran Grca, + * + * Copyright 2025 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/chipset.h> + +typedef struct { + uint32_t virt; + uint32_t phys; + + uint32_t size; + + mem_mapping_t mapping; +} ram_bank_t; + +typedef struct { + uint8_t regs[3]; + + ram_bank_t ram_banks[3]; +} cs8220_t; + +static uint8_t +cs8220_mem_read(uint32_t addr, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint8_t ret = 0xff; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + ret = ram[addr]; + + return ret; +} + +static uint16_t +cs8220_mem_readw(uint32_t addr, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + uint16_t ret = 0xffff; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + ret = *(uint16_t *) &(ram[addr]); + + return ret; +} + +static void +cs8220_mem_write(uint32_t addr, uint8_t val, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + ram[addr] = val; +} + +static void +cs8220_mem_writew(uint32_t addr, uint16_t val, void *priv) +{ + ram_bank_t *dev = (ram_bank_t *) priv; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + *(uint16_t *) &(ram[addr]) = val; +} + +static uint8_t +cs8220_in(uint16_t port, void *priv) { + cs8220_t *dev = (cs8220_t *) priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x00a4 ... 0x00a5: + ret = dev->regs[port & 0x0001]; + break; + case 0x00ab: + ret = dev->regs[2]; + break; + } + + return ret; +} + +static void +cs8220_out(uint16_t port, uint8_t val, void *priv) { + cs8220_t *dev = (cs8220_t *) priv; + + switch (port) { + case 0x00a4: + dev->regs[0] = val; + mem_a20_alt = val & 0x40; + mem_a20_recalc(); + break; + case 0x00a5: + dev->regs[1] = val; + if (val & 0x01) { + mem_mapping_set_addr(&dev->ram_banks[0].mapping, 0, 0x000040000); + mem_mapping_disable(&dev->ram_banks[1].mapping); + mem_mapping_disable(&dev->ram_banks[2].mapping); + } else { + mem_mapping_set_addr(&dev->ram_banks[0].mapping, 0, dev->ram_banks[0].size); + mem_mapping_enable(&dev->ram_banks[1].mapping); + mem_mapping_enable(&dev->ram_banks[2].mapping); + } + break; + case 0x00ab: + dev->regs[2] = val; + break; + } +} + +static void +cs8220_close(void *priv) +{ + cs8220_t *dev = (cs8220_t *) priv; + + free(dev); +} + +static void * +cs8220_init(UNUSED(const device_t *info)) +{ + cs8220_t *dev = (cs8220_t *) calloc(1, sizeof(cs8220_t)); + + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); + + /* + Dell System 200: 640 kB soldered on-board, any other RAM is expansion. + */ + if (!strcmp(machine_get_internal_name(), "dells200")) switch (mem_size) { + default: + dev->ram_banks[2].virt = 0x00100000; + dev->ram_banks[2].phys = 0x000a0000; + dev->ram_banks[2].size = (mem_size << 10) - 0x000a0000; + fallthrough; + case 640: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00080000; + dev->ram_banks[1].virt = 0x00080000; + dev->ram_banks[1].phys = 0x00080000; + dev->ram_banks[1].size = 0x00020000; + break; + /* + We are limited to steps of equal size, so we have to simulate some + memory expansions to work around the chipset's limits. + */ + } else switch (mem_size) { + case 256: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00020000; + dev->ram_banks[1].virt = 0x00020000; + dev->ram_banks[1].phys = 0x00020000; + dev->ram_banks[1].size = 0x00020000; + break; + case 384: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00020000; + /* Pretend there's a 128k expansion. */ + dev->ram_banks[2].virt = 0x00020000; + dev->ram_banks[2].phys = 0x00020000; + dev->ram_banks[2].size = 0x00040000; + break; + case 512: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00080000; + break; + default: + dev->ram_banks[2].virt = 0x00100000; + dev->ram_banks[2].phys = 0x000a0000; + dev->ram_banks[2].size = (mem_size << 10) - 0x000a0000; + fallthrough; + case 640: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00080000; + dev->ram_banks[1].virt = 0x00080000; + dev->ram_banks[1].phys = 0x00080000; + dev->ram_banks[1].size = 0x00020000; + break; + case 768: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00080000; + dev->ram_banks[1].virt = 0x00080000; + dev->ram_banks[1].phys = 0x00080000; + dev->ram_banks[1].size = 0x00020000; + /* Pretend there's a 128k expansion. */ + dev->ram_banks[2].virt = 0x00100000; + dev->ram_banks[2].phys = 0x00080000; + dev->ram_banks[2].size = 0x00020000; + break; + case 896: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00080000; + dev->ram_banks[1].virt = 0x00080000; + dev->ram_banks[1].phys = 0x00080000; + dev->ram_banks[1].size = 0x00020000; + /* Pretend there's a 256k expansion. */ + dev->ram_banks[2].virt = 0x00100000; + dev->ram_banks[2].phys = 0x00080000; + dev->ram_banks[2].size = 0x00040000; + break; + case 1024: + dev->ram_banks[0].virt = 0x00000000; + dev->ram_banks[0].phys = 0x00000000; + dev->ram_banks[0].size = 0x00080000; + dev->ram_banks[1].virt = 0x00100000; + dev->ram_banks[1].phys = 0x00080000; + dev->ram_banks[1].size = 0x00080000; + break; + } + + if (dev->ram_banks[0].size > 0x00000000) + mem_mapping_add(&dev->ram_banks[0].mapping, dev->ram_banks[0].virt, dev->ram_banks[0].size, + cs8220_mem_read, cs8220_mem_readw, NULL, + cs8220_mem_write, cs8220_mem_writew, NULL, + ram + dev->ram_banks[0].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[0])); + + if (dev->ram_banks[1].size > 0x00000000) + mem_mapping_add(&dev->ram_banks[1].mapping, dev->ram_banks[1].virt, dev->ram_banks[1].size, + cs8220_mem_read, cs8220_mem_readw, NULL, + cs8220_mem_write, cs8220_mem_writew, NULL, + ram + dev->ram_banks[1].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[1])); + + if (dev->ram_banks[2].size > 0x00000000) + mem_mapping_add(&dev->ram_banks[2].mapping, dev->ram_banks[2].virt, dev->ram_banks[2].size, + cs8220_mem_read, cs8220_mem_readw, NULL, + cs8220_mem_write, cs8220_mem_writew, NULL, + ram + dev->ram_banks[2].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[2])); + + io_sethandler(0x00a4, 0x0002, + cs8220_in, NULL, NULL, cs8220_out, NULL, NULL, dev); + io_sethandler(0x00ab, 0x0001, + cs8220_in, NULL, NULL, cs8220_out, NULL, NULL, dev); + + return dev; +} + +const device_t cs8220_device = { + .name = "C&T CS8220 (PC/AT)", + .internal_name = "cs8220", + .flags = 0, + .local = 0, + .init = cs8220_init, + .close = cs8220_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 688a5fecb..e11af5e4d 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -55,6 +55,7 @@ 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; +extern const device_t cs8220_device; extern const device_t cs8230_device; extern const device_t cs4031_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index ac26f7a50..137880a11 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -211,6 +211,7 @@ enum { MACHINE_CHIPSET_SCAT_SX, MACHINE_CHIPSET_NEAT, MACHINE_CHIPSET_NEAT_SX, + MACHINE_CHIPSET_CT_AT, 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 8400e4ae8..2b181c499 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -273,8 +273,14 @@ machine_at_dells200_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); - device_add(&keyboard_at_device); + machine_at_common_init(model); + + device_add(&cs8220_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&keyboard_at_phoenix_device); return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d2ef357e1..4b5f82f5d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -117,11 +117,12 @@ const machine_filter_t machine_chipsets[] = { { "ALi ALADDiN IV+", MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS }, { "ALi ALADDiN V", MACHINE_CHIPSET_ALI_ALADDIN_V }, { "ALi ALADDiN-PRO II", MACHINE_CHIPSET_ALI_ALADDIN_PRO_II }, + { "C&T PC/AT", MACHINE_CHIPSET_CT_AT }, + { "C&T 386/AT", MACHINE_CHIPSET_CT_386 }, { "C&T 82C235 SCAT", MACHINE_CHIPSET_SCAT }, { "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 }, { "Contaq 82C597", MACHINE_CHIPSET_CONTAQ_82C597 }, @@ -2975,47 +2976,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC - firmware. */ - { - .name = "[ISA] Dell System 200", - .internal_name = "dells200", - .type = MACHINE_TYPE_286, - .chipset = MACHINE_CHIPSET_PROPRIETARY, - .init = machine_at_dells200_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_286, - .block = CPU_BLOCK_NONE, - .min_bus = 6000000, - .max_bus = 12000000, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, - .ram = { - .min = 640, - .max = 16384, - .step = 128 - }, - .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 = "[ISA] MR BIOS 286 clone", @@ -3460,6 +3420,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC + firmware. */ + { + .name = "[C&T PC/AT] Dell System 200", + .internal_name = "dells200", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_CT_AT, + .init = machine_at_dells200_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 12000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .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 Quadtel KBC firmware. */ { .name = "[GC103] Quadtel 286 clone", @@ -5280,7 +5281,7 @@ const machine_t machines[] = { }, /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { - .name = "[C&T 386] ECS 386/32", + .name = "[C&T 386/AT] ECS 386/32", .internal_name = "ecs386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_CT_386, @@ -5320,7 +5321,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[C&T 386] Samsung SPC-6000A", + .name = "[C&T 386/AT] Samsung SPC-6000A", .internal_name = "spc6000a", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_CT_386, From 83224dcadefa4cb3b3a99779e47c5ea35f3e27c4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 04:20:25 +0200 Subject: [PATCH 1001/1190] Bring the AN430TX out of the Dev branch in form of the Packard Bell PB790. --- CMakeLists.txt | 1 - src/chipset/intel_4x0.c | 13 +++-- src/machine/CMakeLists.txt | 8 --- src/machine/m_at_socket7.c | 30 +++++------- src/machine/machine_table.c | 97 +++++++++++++++++++------------------ 5 files changed, 71 insertions(+), 78 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b78295fd..3ad83fb4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,7 +173,6 @@ endif() # Option Description Def. Condition Otherwise # ------ ----------- ---- ------------ --------- cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) -cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF) cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF) cmake_dependent_option(G100 "Matrox Productiva G100" ON "DEV_BRANCH" OFF) cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF) diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 84bd872f8..8e6ce97c3 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1013,7 +1013,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) case INTEL_430TX: if (!dev->smram_locked) { i4x0_smram_handler_phase0(dev); - regs[0x71] = (regs[0x71] & 0x20) | (val & 0xdf); + regs[0x71] = (regs[0x71] & 0x60) | (val & 0x9f); + regs[0x71] &= (val & 0x40); i4x0_smram_handler_phase1(dev); } break; @@ -1041,9 +1042,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) regs[0x72] = (val & 0x7f); else regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78); - dev->smram_locked = (val & 0x10); - if (dev->smram_locked) - regs[0x72] &= 0xbf; + if (val & 0x08) { + dev->smram_locked = (val & 0x10); + if (dev->smram_locked) + regs[0x72] &= 0xbf; + } } } else { if (dev->smram_locked) @@ -1577,6 +1580,8 @@ i4x0_reset(void *priv) dev->regs[0x68 + i] = 0x00; } + dev->smram_locked = 0; + if (dev->type >= INTEL_430FX) { dev->regs[0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */ i4x0_write(0, 0x72, 0x02, priv); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 4098f2553..20d60c075 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -57,14 +57,6 @@ add_library(mch OBJECT m_at_misc.c ) -if(AN430TX) - target_compile_definitions(mch PRIVATE USE_AN430TX) -endif() - -if(DESKPRO386) - target_compile_definitions(mch PRIVATE USE_DESKPRO386) -endif() - if(OLIVETTI) target_compile_definitions(mch PRIVATE USE_OLIVETTI) endif() diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 7d2441e18..d4b71f92f 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1007,27 +1007,17 @@ machine_at_optiplex_gn_init(const machine_t *model) return ret; } -#ifdef USE_AN430TX int machine_at_an430tx_init(const machine_t *model) { int ret; -# if 1 - ret = bios_load_linear_combined2("roms/machines/an430tx/P10-0095.BIO", - "roms/machines/an430tx/P10-0095.BI1", - "roms/machines/an430tx/P10-0095.BI2", - "roms/machines/an430tx/P10-0095.BI3", - "roms/machines/an430tx/P10-0095.RCV", + ret = bios_load_linear_combined2("roms/machines/an430tx/ANP0911A.BIO", + "roms/machines/an430tx/ANP0911A.BI1", + "roms/machines/an430tx/ANP0911A.BI2", + "roms/machines/an430tx/ANP0911A.BI3", + "roms/machines/an430tx/ANP0911A.RCV", 0x3a000, 160); -# else - ret = bios_load_linear_combined2("roms/machines/an430tx/P06-0062.BIO", - "roms/machines/an430tx/P06-0062.BI1", - "roms/machines/an430tx/P06-0062.BI2", - "roms/machines/an430tx/P06-0062.BI3", - "roms/machines/an430tx/P10-0095.RCV", - 0x3a000, 160); -# endif if (bios_only || !ret) return ret; @@ -1036,21 +1026,25 @@ machine_at_an430tx_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ - // pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); /* PIIX4 */ pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); device_add(&i430tx_device); device_add(&piix4_device); +#ifdef FOLLOW_THE_SPECIFICATION device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42I | PCX7307_PC97307)); +#else + /* The technical specification says Phoenix, a real machnine HWINFO dump says AMI '5'. */ + device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC97307)); +#endif device_add(&intel_flash_bxt_ami_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); return ret; } -#endif /* USE_AN430TX */ int machine_at_ym430tx_init(const machine_t *model) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 4b5f82f5d..add0c2b7c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13275,49 +13275,6 @@ const machine_t machines[] = { .snd_device = &cs4236b_device, .net_device = &pcnet_am79c973_onboard_device }, -#ifdef USE_AN430TX - /* This has the Phoenix MultiKey KBC firmware. */ - { - .name = "[i430TX] Intel AN430TX (Anchorage)", - .internal_name = "an430tx", - .type = MACHINE_TYPE_SOCKET7, - .chipset = MACHINE_CHIPSET_INTEL_430TX, - .init = machine_at_an430tx_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, - CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), - .min_bus = 60000000, - .max_bus = 66666667, - .min_voltage = 2800, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 3.5 - }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, - .ram = { - .min = 8192, - .max = 262144, - .step = 8192 - }, - .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 - }, -#endif /* USE_AN430TX */ /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ { .name = "[i430TX] Intel YM430TX (Yamamoto)", @@ -13359,9 +13316,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* PhoenixBIOS 4.0 Rel 6.0 for 430TX, has onboard Yamaha YMF701 which is not emulated yet. */ - /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix - MultiKey/42 (version 1.38) KBC firmware. */ + /* + PhoenixBIOS 4.0 Rel 6.0 for 430TX, has onboard Yamaha YMF701 which + is not emulated yet. + + Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix + MultiKey/42 (version 1.38) KBC firmware. + */ { .name = "[i430TX] Micronics Thunderbolt", .internal_name = "thunderbolt", @@ -13383,7 +13344,8 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Yamaha YMF701-S */ + /* Machine has internal sound: Yamaha YMF701-S */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -13442,6 +13404,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ + { + .name = "[i430TX] Packard Bell PB790", + .internal_name = "an430tx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_an430tx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P, + CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L), + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .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 + }, /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. A picture shows a VIA VT82C42N KBC though, so it could be a case of that KBC with AMI firmware. */ { From 265b69c7eaef196c9a98683beb73ec2772798ca1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 04:34:00 +0200 Subject: [PATCH 1002/1190] And machine.h - this should fix compile. --- src/include/86box/machine.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 137880a11..320847e7b 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -756,11 +756,9 @@ extern int machine_at_ma23c_init(const machine_t *); extern int machine_at_nupro592_init(const machine_t *); extern int machine_at_tx97_init(const machine_t *); extern int machine_at_optiplex_gn_init(const machine_t *); -#ifdef USE_AN430TX -extern int machine_at_an430tx_init(const machine_t *); -#endif /* USE_AN430TX */ extern int machine_at_ym430tx_init(const machine_t *); extern int machine_at_thunderbolt_init(const machine_t *); +extern int machine_at_an430tx_init(const machine_t *); extern int machine_at_mb540n_init(const machine_t *); extern int machine_at_56a5_init(const machine_t *); extern int machine_at_p5mms98_init(const machine_t *); From 76e9a20e12975d1cfd9bcf3b01b29b216cecf966 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 05:51:40 +0200 Subject: [PATCH 1003/1190] Bring the Olivetti M290 out of the Dev branch. --- CMakeLists.txt | 1 - src/chipset/CMakeLists.txt | 5 +---- src/chipset/olivetti_eva.c | 27 +++++++++------------------ src/include/86box/machine.h | 2 -- src/machine/CMakeLists.txt | 4 ---- src/machine/m_at_286_386sx.c | 10 +++++----- src/machine/machine_table.c | 2 -- 7 files changed, 15 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ad83fb4a..161394778 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,6 @@ cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) cmake_dependent_option(PCL "Generic PCL5e Printer" ON "DEV_BRANCH" OFF) diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 7a8233003..7817ac052 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -43,6 +43,7 @@ add_library(chipset OBJECT isa486c.c ../ioapic.c neat.c + olivetti_eva.c opti283.c opti291.c opti391.c @@ -86,7 +87,3 @@ add_library(chipset OBJECT vl82c480.c wd76c10.c ) - -if(OLIVETTI) - target_sources(chipset PRIVATE olivetti_eva.c) -endif() diff --git a/src/chipset/olivetti_eva.c b/src/chipset/olivetti_eva.c index 7defac6ae..0dcbdd21f 100644 --- a/src/chipset/olivetti_eva.c +++ b/src/chipset/olivetti_eva.c @@ -73,26 +73,24 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv) break; case 0x069: dev->reg_069 = val; - /* - * Unfortunately, if triggered, the BIOS remapping function fails causing - * a fatal error. Therefore, this code section is currently commented. - */ -#if 0 - if (val & 1) { + mem_remap_top(0); + if (val == 0x01) { /* * Set the register to 7 or above for the BIOS to trigger the * memory remapping function if shadowing is active. */ - dev->reg_069 = 0x7; + dev->reg_069 = 0x07; } - if (val & 8) { + if (val & 0x08) { /* * Activate shadowing for region e0000-fffff */ mem_remap_top(256); - mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else { + mem_remap_top(384); + mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } -#endif break; default: break; @@ -143,7 +141,7 @@ olivetti_eva_init(UNUSED(const device_t *info)) dev->reg_067 = 0x00; /* RAM enable registers */ - dev->reg_069 = 0x0; + dev->reg_069 = 0x00; io_sethandler(0x0065, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); io_sethandler(0x0067, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); @@ -152,13 +150,6 @@ olivetti_eva_init(UNUSED(const device_t *info)) /* When shadowing is not enabled in BIOS, all upper memory is available as XMS */ mem_remap_top(384); - /* - * Default settings when NVRAM is cleared activate shadowing. - * Thus, to avoid boot errors, remap only 256k from UMB to XMS. - * Remove this block once BIOS memory remapping works. - */ - mem_remap_top(256); - return dev; } diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 320847e7b..d6725ec9a 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -481,9 +481,7 @@ extern int machine_at_dells200_init(const machine_t *); extern int machine_at_pc8_init(const machine_t *); extern int machine_at_3302_init(const machine_t *); -#ifdef USE_OLIVETTI extern int machine_at_m290_init(const machine_t *); -#endif /* USE_OLIVETTI */ extern int machine_at_shuttle386sx_init(const machine_t *); extern int machine_at_adi386sx_init(const machine_t *); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 20d60c075..2e3bc02bc 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -57,10 +57,6 @@ add_library(mch OBJECT m_at_misc.c ) -if(OLIVETTI) - target_compile_definitions(mch PRIVATE USE_OLIVETTI) -endif() - if(OPEN_AT) target_compile_definitions(mch PRIVATE USE_OPEN_AT) endif() diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 2b181c499..853829ccc 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -1069,7 +1069,6 @@ machine_at_pc916sx_init(const machine_t *model) return ret; } -#ifdef USE_OLIVETTI int machine_at_m290_init(const machine_t *model) { @@ -1081,15 +1080,16 @@ machine_at_m290_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 4); - device_add(&keyboard_at_olivetti_device); + machine_at_common_init_ex(model, 6); + device_add(&amstrad_megapc_nvr_device); + + device_add(&olivetti_eva_device); device_add(&port_6x_olivetti_device); if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); - device_add(&olivetti_eva_device); + device_add(&keyboard_at_olivetti_device); return ret; } -#endif /* USE_OLIVETTI */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index add0c2b7c..8cdc7444b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3096,7 +3096,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#ifdef USE_OLIVETTI /* Has Olivetti KBC firmware. */ { .name = "[ISA] Olivetti M290", @@ -3137,7 +3136,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* USE_OLIVETTI */ #ifdef USE_OPEN_AT /* Has IBM AT KBC firmware. */ { From 6426c375ee7acba5d1dc3b90f88675fe9416677d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 06:45:18 +0200 Subject: [PATCH 1004/1190] And chipset.h. --- src/include/86box/chipset.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index e11af5e4d..e0e775fa1 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -113,6 +113,9 @@ extern const device_t slc90e66_device; extern const device_t ioapic_device; +/* Olivetti */ +extern const device_t olivetti_eva_device; + /* OPTi */ extern const device_t opti283_device; extern const device_t opti291_device; @@ -204,8 +207,4 @@ extern const device_t nec_mate_unk_device; extern const device_t phoenix_486_jumper_device; extern const device_t phoenix_486_jumper_pci_device; - -#ifdef USE_OLIVETTI -extern const device_t olivetti_eva_device; -#endif /* USE_OLIVETTI */ #endif /*EMU_CHIPSET_H*/ From d49a71ee6e7841378b1b9a69105805e9f7b8f55d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 09:48:53 +0200 Subject: [PATCH 1005/1190] Remove the GUS Max from the Dev branch. --- CMakeLists.txt | 1 - src/include/86box/sound.h | 1 + src/sound/CMakeLists.txt | 4 --- src/sound/snd_gus.c | 69 ++++++++++++--------------------------- src/sound/sound.c | 1 + 5 files changed, 23 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 161394778..a632b71ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,7 +175,6 @@ endif() cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF) cmake_dependent_option(G100 "Matrox Productiva G100" ON "DEV_BRANCH" OFF) -cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index b2e202ddb..985abe777 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -197,6 +197,7 @@ extern const device_t ct5880_onboard_device; /* Gravis UltraSound and UltraSound Max */ extern const device_t gus_device; +extern const device_t gus_max_device; /* IBM PS/1 Audio Card */ extern const device_t ps1snd_device; diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index fb3c9b43d..66a0ee4e3 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -185,10 +185,6 @@ target_link_libraries(86Box esfmu) add_subdirectory(ymfm) target_link_libraries(86Box ymfm) -if(GUSMAX) - target_compile_definitions(snd PRIVATE USE_GUSMAX) -endif() - if(OPL4ML) target_compile_definitions(snd PRIVATE USE_OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 1885581a5..fff679e81 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -17,9 +17,7 @@ #include <86box/sound.h> #include "cpu.h" #include <86box/timer.h> -#ifdef USE_GUSMAX -# include <86box/snd_ad1848.h> -#endif /*USE_GUSMAX */ +#include <86box/snd_ad1848.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> @@ -145,11 +143,9 @@ typedef struct gus_t { uint8_t usrr; -#ifdef USE_GUSMAX uint8_t max_ctrl; ad1848_t ad1848; -#endif /*USE_GUSMAX */ } gus_t; static int gus_gf1_irqs[8] = { -1, 2, 5, 3, 7, 11, 12, 15 }; @@ -257,9 +253,7 @@ writegus(uint16_t addr, uint8_t val, void *priv) int d; int old; uint16_t port; -#ifdef USE_GUSMAX uint16_t csioport; -#endif /*USE_GUSMAX */ if ((addr == 0x388) || (addr == 0x389)) port = addr; @@ -607,10 +601,9 @@ writegus(uint16_t addr, uint8_t val, void *priv) gus->irq_midi = gus->irq; } else gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; -#ifdef USE_GUSMAX + if (gus->type == GUS_MAX) ad1848_setirq(&gus->ad1848, gus->irq); -#endif /*USE_GUSMAX */ gus->sb_nmi = val & 0x80; } else { @@ -623,10 +616,9 @@ writegus(uint16_t addr, uint8_t val, void *priv) gus->dma2 = gus->dma; } else gus->dma2 = gus_dmas[(val >> 3) & 7]; -#ifdef USE_GUSMAX + if (gus->type == GUS_MAX) ad1848_setdma(&gus->ad1848, gus->dma2); -#endif /*USE_GUSMAX */ } break; case 1: @@ -684,7 +676,6 @@ writegus(uint16_t addr, uint8_t val, void *priv) break; case 0x306: case 0x706: -#ifdef USE_GUSMAX if (gus->type == GUS_MAX) { if (gus->dma >= 4) val |= 0x10; @@ -704,7 +695,6 @@ writegus(uint16_t addr, uint8_t val, void *priv) } } } -#endif /*USE_GUSMAX */ break; default: @@ -756,11 +746,9 @@ readgus(uint16_t addr, void *priv) return val; case 0x20F: -#ifdef USE_GUSMAX if (gus->type == GUS_MAX) val = 0x02; else -#endif /*USE_GUSMAX */ val = 0x00; break; @@ -879,11 +867,9 @@ readgus(uint16_t addr, void *priv) break; case 0x306: case 0x706: -#ifdef USE_GUSMAX if (gus->type == GUS_MAX) val = 0x0a; /* GUS MAX */ else -#endif /*USE_GUSMAX */ val = 0xff; /*Pre 3.7 - no mixer*/ break; @@ -1183,24 +1169,20 @@ gus_get_buffer(int32_t *buffer, int len, void *priv) { gus_t *gus = (gus_t *) priv; -#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) ad1848_update(&gus->ad1848); -#endif /*USE_GUSMAX */ + gus_update(gus); for (int c = 0; c < len * 2; c++) { -#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) buffer[c] += (int32_t) (gus->ad1848.buffer[c] / 2); -#endif /*USE_GUSMAX */ buffer[c] += (int32_t) gus->buffer[c & 1][c >> 1]; } -#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) gus->ad1848.pos = 0; -#endif /*USE_GUSMAX */ + gus->pos = 0; } @@ -1333,9 +1315,7 @@ gus_reset(void *priv) gus->usrr = 0; -#ifdef USE_GUSMAX gus->max_ctrl = 0; -#endif /*USE_GUSMAX */ gus->irq_state = 0; gus->midi_irq_state = 0; @@ -1373,7 +1353,7 @@ gus_init(UNUSED(const device_t *info)) gus->uart_out = 1; - gus->type = device_get_config_int("type"); + gus->type = info->local; gus->base = device_get_config_hex16("base"); @@ -1382,7 +1362,6 @@ gus_init(UNUSED(const device_t *info)) io_sethandler(0x0506 + gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); -#ifdef USE_GUSMAX if (gus->type == GUS_MAX) { ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231); ad1848_setirq(&gus->ad1848, 5); @@ -1390,7 +1369,6 @@ gus_init(UNUSED(const device_t *info)) io_sethandler(0x10C + gus->base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &gus->ad1848); } -#endif /*USE_GUSMAX */ timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); @@ -1423,31 +1401,12 @@ gus_speed_changed(void *priv) else gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); -#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) ad1848_speed_changed(&gus->ad1848); -#endif /*USE_GUSMAX */ } static const device_config_t gus_config[] = { // clang-format off - { - .name = "type", - .description = "GUS type", - .type = CONFIG_SELECTION, - .default_string = NULL, - .default_int = 0, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { - { .description = "Classic", .value = GUS_CLASSIC }, -#ifdef USE_GUSMAX - { .description = "MAX", .value = GUS_MAX }, -#endif /*USE_GUSMAX */ - { NULL } - }, - .bios = { { 0 } } - }, { .name = "base", .description = "Address", @@ -1502,7 +1461,21 @@ const device_t gus_device = { .name = "Gravis UltraSound", .internal_name = "gus", .flags = DEVICE_ISA16, - .local = 0, + .local = GUS_CLASSIC, + .init = gus_init, + .close = gus_close, + .reset = gus_reset, + .available = NULL, + .speed_changed = gus_speed_changed, + .force_redraw = NULL, + .config = gus_config +}; + +const device_t gus_max_device = { + .name = "Gravis UltraSound MAX", + .internal_name = "gus", + .flags = DEVICE_ISA16, + .local = GUS_MAX, .init = gus_init, .close = gus_close, .reset = gus_reset, diff --git a/src/sound/sound.c b/src/sound/sound.c index c3ecc8632..7bf27a136 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -115,6 +115,7 @@ static const SOUND_CARD sound_cards[] = { { &ess_ess0102_pnp_device }, { &ess_ess0968_pnp_device }, { &gus_device }, + { &gus_max_device }, { &sb_1_device }, { &sb_15_device }, { &sb_2_device }, From e9c7795c7a06ddbe2e3197685cce375d40be42d7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 09:51:08 +0200 Subject: [PATCH 1006/1190] Remove the OpenAT entirely - its BIOS never rearched any sort of actually usable state (and is also not actually Open, just visible source). --- CMakeLists.txt | 1 - src/include/86box/machine.h | 3 --- src/machine/CMakeLists.txt | 4 --- src/machine/m_at.c | 18 ------------- src/machine/machine_table.c | 51 ++----------------------------------- 5 files changed, 2 insertions(+), 75 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a632b71ce..777ede9ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,7 +178,6 @@ cmake_dependent_option(G100 "Matrox Productiva G100" cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) cmake_dependent_option(PCL "Generic PCL5e Printer" ON "DEV_BRANCH" OFF) cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d6725ec9a..98667f244 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -448,9 +448,6 @@ extern int machine_at_pb286_init(const machine_t *); extern int machine_at_siemens_init(const machine_t *); // Siemens PCD-2L. N82330 discrete machine. It segfaults in some places extern int machine_at_wellamerastar_init(const machine_t *); // Wells American A*Star with custom award BIOS -#ifdef USE_OPEN_AT -extern int machine_at_openat_init(const machine_t *); -#endif /* USE_OPEN_AT */ /* m_at_286_386sx.c */ extern int machine_at_tg286m_init(const machine_t *); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 2e3bc02bc..8cd54edec 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -56,7 +56,3 @@ add_library(mch OBJECT m_at_socket370.c m_at_misc.c ) - -if(OPEN_AT) - target_compile_definitions(mch PRIVATE USE_OPEN_AT) -endif() diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 86fbe3776..13cd831ba 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -388,21 +388,3 @@ machine_at_wellamerastar_init(const machine_t *model) return ret; } - -#ifdef USE_OPEN_AT -int -machine_at_openat_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/openat/bios.bin", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_ibm_common_init(model); - - return ret; -} -#endif /* USE_OPEN_AT */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8cdc7444b..408deb615 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8,17 +8,12 @@ * * Handling of the emulated machines. * - * NOTES: OpenAT wip for 286-class machine with open BIOS. - * PS2_M80-486 wip, pending receipt of TRM's for machine. - * - * - * * Authors: Miran Grca, * Fred N. van Kempen, * Jasmine Iwanek, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2025 Miran Grca. + * Copyright 2017-2025 Fred N. van Kempen. * Copyright 2025 Jasmine Iwanek. */ #include @@ -3136,48 +3131,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#ifdef USE_OPEN_AT - /* Has IBM AT KBC firmware. */ - { - .name = "[ISA] OpenAT", - .internal_name = "openat", - .type = MACHINE_TYPE_286, - .chipset = MACHINE_CHIPSET_DISCRETE, - .init = machine_at_openat_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_286, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, - .ram = { - .min = 256, - .max = 15872, - .step = 128 - }, - .nvrmask = 63, - .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 - }, -#endif /* USE_OPEN_AT */ /* Has IBM AT KBC firmware. */ { .name = "[ISA] Phoenix IBM AT", From 802355e982d1995e6fa2a0a34ad3b48c98f226ca Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 12:57:07 -0300 Subject: [PATCH 1007/1190] Add proper on-board CS4235 to delhi3 --- 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 408deb615..780f8d474 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4456,7 +4456,7 @@ const machine_t machines[] = { .net_device = NULL }, { - .name = "[ALI M1409] Acer 100T", + .name = "[ALi M1409] Acer 100T", .internal_name = "acer100t", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_ALI_M1409, @@ -14420,7 +14420,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &cs4235_device, + .snd_device = &cs4235_onboard_device, .net_device = NULL }, From d3cc0df2bb5f99f7f6862840aab13f3e5484fa29 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 13:20:34 -0300 Subject: [PATCH 1008/1190] CS423x: Remove delhi3 PnP disable command hack as it's no longer required (there's a clean nvr issue elsewhere) --- src/sound/snd_cs423x.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 17ea48dd3..74382a53b 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -650,15 +650,7 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], dev->pnp_size); /* Disable PnP key if the PKD bit is set, or if it was disabled by command 0x55. */ - /* But wait! The TriGem Delhi-III BIOS sends command 0x55, and its behavior doesn't - line up with real hardware (still listed in the POST summary and seen by software). - Disable the PnP key disabling mechanism until someone figures something out. */ -#if 0 isapnp_enable_card(dev->pnp_card, ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) ? ISAPNP_CARD_NO_KEY : ISAPNP_CARD_ENABLE); -#else - if ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) - pclog("CS423x: Attempted to disable PnP key\n"); -#endif } /* Update some register bits based on the config data in RAM if requested. */ From 9ebcc443508eede6fd572379f49e2f3c627ae13b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 May 2025 19:41:27 +0200 Subject: [PATCH 1009/1190] Add the Dell System 333s/L. --- src/chipset/scamp.c | 2 +- src/device/kbc_at.c | 13 +++++-- src/device/postcard.c | 8 +++-- src/include/86box/machine.h | 1 + src/include/86box/video.h | 1 + src/machine/m_at_286_386sx.c | 70 ++++++++++++++++++++++++++++++++++++ src/machine/machine_table.c | 42 ++++++++++++++++++++++ src/sio/sio_detect.c | 7 ++-- src/video/vid_cl54xx.c | 19 +++++++++- 9 files changed, 152 insertions(+), 11 deletions(-) diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 8e7892c2e..855175dcd 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -1177,7 +1177,7 @@ scamp_init(UNUSED(const device_t *info)) dev->mem_flags[i] = MEM_FLAG_READ | MEM_FLAG_WRITE; scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_RW); - if (i >= 60) + if (i >= 56) scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS); } } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 8840a0e4d..dd2d5a636 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1079,7 +1079,14 @@ write_cmd_generic(void *priv, uint8_t val) /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN)) fixed_bits |= 0x40; - if (kbc_ven == KBC_VEN_IBM_PS1) { + if (!strcmp(machine_get_internal_name(), "dells333sl")) { + /* + Dell System 333s/L: + - Bit 5: Stuck in reboot loop if clear. + */ + uint8_t p1 = 0x20 | (video_is_mda() ? 0x40 : 0x00); + kbc_delay_to_ob(dev, p1, 0, 0x00); + } else if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); /* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */ kbc_delay_to_ob(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), @@ -1114,7 +1121,7 @@ write_cmd_generic(void *priv, uint8_t val) Dell 466/NP: - Bit 2: Keyboard fuse (must be set); - Bit 4: Password disable jumper (must be clear); - - Bit 5: Manufacturing jumper (must be set); + - Bit 5: Manufacturing jumper (must be set). */ uint8_t p1 = 0x24; kbc_delay_to_ob(dev, p1, 0, 0x00); @@ -1123,7 +1130,7 @@ write_cmd_generic(void *priv, uint8_t val) Dell OptiPlex GXL/GXM: - Bit 3: Password disable jumper (must be clear); - Bit 4: Keyboard fuse (must be set); - - Bit 5: Manufacturing jumper (must be set); + - Bit 5: Manufacturing jumper (must be set). */ uint8_t p1 = 0x30; kbc_delay_to_ob(dev, p1, 0, 0x00); diff --git a/src/device/postcard.c b/src/device/postcard.c index 19d81b692..27f5a5aa3 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -100,7 +100,8 @@ postcard_setui(void) break; } } else if (strstr(machines[machine].name, " Dell ") && - (machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX)) { + ((machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX) || + (machine_get_chipset(machine) >= MACHINE_CHIPSET_VLSI_SCAMP))) { char dell_diags[10] = { 0 }; if (!postcard_written[1]) @@ -225,8 +226,9 @@ postcard_init(UNUSED(const device_t *info)) NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); if (strstr(machines[machine].name, " Dell ") && - (machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX)) - io_sethandler(0x00e0, 0x0001, + ((machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX) || + (machine_get_chipset(machine) >= MACHINE_CHIPSET_VLSI_SCAMP))) + io_sethandler(is486 ? 0x00e0 : 0x00e4, 0x0001, NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL); return postcard_write; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 98667f244..d4d5e8618 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -485,6 +485,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_dells333sl_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 *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 6a73c6462..bd3101d84 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -356,6 +356,7 @@ extern const device_t gd5401_isa_device; extern const device_t gd5402_isa_device; extern const device_t gd5402_onboard_device; extern const device_t gd5420_isa_device; +extern const device_t gd5420_onboard_device; extern const device_t gd5422_isa_device; extern const device_t gd5424_vlb_device; extern const device_t gd5426_isa_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 853829ccc..6ac5b0195 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -37,6 +37,7 @@ #include <86box/hdc.h> #include <86box/nvr.h> #include <86box/port_6x.h> +#define USE_SIO_DETECT #include <86box/sio.h> #include <86box/serial.h> #include <86box/video.h> @@ -760,6 +761,75 @@ machine_at_cmdsl386sx25_init(const machine_t *model) return ret; } +static const device_config_t dells333sl_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "dells333sl", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "J01 (Jostens Learning Corporation OEM)", .internal_name = "dells333sl_j01", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/dells333sl/DELL386.BIN", "" } }, + { .name = "A02", .internal_name = "dells333sl", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/dells333sl/Dell_386SX_30807_UBIOS_B400_VLSI_VL82C311_Cirrus_Logic_GD5420.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t dells333sl_device = { + .name = "Dell System 333s/L", + .internal_name = "dells333sl_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = dells333sl_config +}; + +int +machine_at_dells333sl_init(const machine_t *model) +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 262144, 0); + memcpy(rom, &(rom[0x00020000]), 131072); + mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000); + mem_mapping_set_exec(&bios_mapping, rom); + device_context_restore(); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + machine_at_common_init_ex(model, 2); + + device_add(&ide_isa_device); + + device_add(&pc87311_device); + device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */ + + device_add(&vlsi_scamp_device); + + return ret; +} + int machine_at_dataexpert386sx_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 408deb615..e18581082 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -66,6 +66,7 @@ extern const device_t vendex_device; extern const device_t c5sbm2_device; extern const device_t sb486pv_device; extern const device_t ap5s_device; +extern const device_t dells333sl_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -4942,6 +4943,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC + firmware. */ + { + .name = "[SCAMP] Dell System 333s/L", + .internal_name = "dells333sl", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_VLSI_SCAMP, + .init = machine_at_dells333sl_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 = 10000000, + .max_bus = 33333333, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &dells333sl_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5420_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ { .name = "[SCAMP] Samsung SPC-6033P", diff --git a/src/sio/sio_detect.c b/src/sio/sio_detect.c index ffa0ec9d0..d36522fe0 100644 --- a/src/sio/sio_detect.c +++ b/src/sio/sio_detect.c @@ -47,11 +47,12 @@ sio_detect_write(uint16_t port, uint8_t val, void *priv) static uint8_t sio_detect_read(uint16_t port, void *priv) { - const sio_detect_t *dev = (sio_detect_t *) priv; + /*const sio_detect_t *dev = (sio_detect_t *) priv*/; + uint8_t ret = 0xff /*dev->regs[port & 1]*/; - pclog("sio_detect_read : port=%04x = %02X\n", port, dev->regs[port & 1]); + pclog("sio_detect_read : port=%04x = %02X\n", port, ret); - return 0xff /*dev->regs[port & 1]*/; + return ret; } static void diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 13f96501c..0d02c10c3 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4247,7 +4247,10 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5420: - romfn = BIOS_GD5420_PATH; + if (info->local & 0x200) + romfn = NULL; + else + romfn = BIOS_GD5420_PATH; break; case CIRRUS_ID_CLGD5422: @@ -4978,6 +4981,20 @@ const device_t gd5420_isa_device = { .config = gd542x_config, }; +const device_t gd5420_onboard_device = { + .name = "Cirrus Logic GD5420 (ISA)", + .internal_name = "cl_gd5420_isa", + .flags = DEVICE_ISA16, + .local = CIRRUS_ID_CLGD5420 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + .available = NULL, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config, +}; + const device_t gd5422_isa_device = { .name = "Cirrus Logic GD5422 (ISA)", .internal_name = "cl_gd5422_isa", From 30324bb859a60e76fec7cebfcb7af302674391bd Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 15:13:52 -0300 Subject: [PATCH 1010/1190] Add internal PCI flag to STPC SBCs without PCI slots --- src/machine/machine_table.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 780f8d474..52c483ff5 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9422,7 +9422,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, /* Machine has internal video: ST STPC Atlas */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL, /* Machine has internal video: ST STPC Atlas */ .ram = { .min = 32768, .max = 163840, @@ -9463,7 +9463,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: ST STPC Atlas */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL | MACHINE_USB, /* Machine has internal video: ST STPC Atlas */ .ram = { .min = 32768, .max = 163840, @@ -9504,7 +9504,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal video: ST STPC Atlas and NIC: Realtek RTL8139C+ */ + .flags = MACHINE_IDE | MACHINE_APM | MACHINE_PCI_INTERNAL, /* Machine has internal video: ST STPC Atlas and NIC: Realtek RTL8139C+ */ .ram = { .min = 32768, .max = 131072, @@ -9545,7 +9545,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL, .ram = { .min = 32768, .max = 98304, @@ -9586,7 +9586,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL, .ram = { .min = 32768, .max = 131072, From 81af1f8195361cf8b7bcc5a8813076dda9f9d7f0 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 15:35:43 -0300 Subject: [PATCH 1011/1190] De-underscore the ASUS 386/33-64K --- src/include/86box/machine.h | 2 +- src/machine/m_at_386dx_486.c | 4 ++-- src/machine/machine_table.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 98667f244..53b47c4c1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -512,7 +512,7 @@ extern int machine_at_ga486l_init(const machine_t *); extern int machine_at_cougar_init(const machine_t *); extern int machine_at_acc386_init(const machine_t *); -extern int machine_at_asus386_3364k_init(const machine_t *); +extern int machine_at_asus3863364k_init(const machine_t *); extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); extern int machine_at_spc6000a_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 9f7534244..b81a6bda7 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -73,11 +73,11 @@ machine_at_acc386_init(const machine_t *model) } int -machine_at_asus386_3364k_init(const machine_t *model) +machine_at_asus3863364k_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/asus386_3364k/am27c512dip28-64b53c26be3d8160533563.bin", + ret = bios_load_linear("roms/machines/asus3863364k/am27c512dip28-64b53c26be3d8160533563.bin", 0x000f0000, 65536, 0); if (bios_only || !ret) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 52c483ff5..63d19c8c6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5671,10 +5671,10 @@ const machine_t machines[] = { /* Has Award KBC firmware. */ { .name = "[SiS 310] ASUS 386/33-64K", - .internal_name = "asus386_3364k", + .internal_name = "asus3863364k", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_SIS_310, - .init = machine_at_asus386_3364k_init, + .init = machine_at_asus3863364k_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, From 4a3eb800828e2ce176cc446be97563f84ea4556c Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 15:36:53 -0300 Subject: [PATCH 1012/1190] De-underscore the Dell OptiPlex machines --- src/include/86box/machine.h | 6 +++--- src/machine/m_at_slot1.c | 4 ++-- src/machine/m_at_socket5.c | 4 ++-- src/machine/m_at_socket7.c | 4 ++-- src/machine/machine_table.c | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 53b47c4c1..155e6aecc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -670,7 +670,7 @@ extern int machine_at_tek932_init(const machine_t *); extern int machine_at_acerv30_init(const machine_t *); extern int machine_at_apollo_init(const machine_t *); -extern int machine_at_optiplex_gxl_init(const machine_t *); +extern int machine_at_optiplexgxl_init(const machine_t *); extern int machine_at_zappa_init(const machine_t *); extern int machine_at_powermatev_init(const machine_t *); extern int machine_at_hawk_init(const machine_t *); @@ -750,7 +750,7 @@ extern int machine_at_gw2kte_init(const machine_t *); extern int machine_at_ma23c_init(const machine_t *); extern int machine_at_nupro592_init(const machine_t *); extern int machine_at_tx97_init(const machine_t *); -extern int machine_at_optiplex_gn_init(const machine_t *); +extern int machine_at_optiplexgn_init(const machine_t *); extern int machine_at_ym430tx_init(const machine_t *); extern int machine_at_thunderbolt_init(const machine_t *); extern int machine_at_an430tx_init(const machine_t *); @@ -819,7 +819,7 @@ extern int machine_at_p65up5_cpknd_init(const machine_t *); extern int machine_at_kn97_init(const machine_t *); extern int machine_at_lx6_init(const machine_t *); -extern int machine_at_optiplex_gxa_init(const machine_t *); +extern int machine_at_optiplexgxa_init(const machine_t *); extern int machine_at_spitfire_init(const machine_t *); extern int machine_at_ma30d_init(const machine_t *); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index a147d0e13..280462858 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -151,11 +151,11 @@ machine_at_lx6_init(const machine_t *model) } int -machine_at_optiplex_gxa_init(const machine_t *model) +machine_at_optiplexgxa_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/optiplex_gxa/DELL.ROM", + ret = bios_load_linear("roms/machines/optiplexgxa/DELL.ROM", 0x000c0000, 262144, 0); if (bios_only || !ret) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 442281811..0d50fead8 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -238,11 +238,11 @@ machine_at_apollo_init(const machine_t *model) } int -machine_at_optiplex_gxl_init(const machine_t *model) +machine_at_optiplexgxl_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/optiplex_gxl/DELL.ROM", + ret = bios_load_linear("roms/machines/optiplexgxl/DELL.ROM", 0x000e0000, 131072, 0); if (bios_only || !ret) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index d4b71f92f..dbc59ef17 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -970,11 +970,11 @@ machine_at_tx97_init(const machine_t *model) } int -machine_at_optiplex_gn_init(const machine_t *model) +machine_at_optiplexgn_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/optiplex_gn/DELL.ROM", + ret = bios_load_linear("roms/machines/optiplexgn/DELL.ROM", 0x000c0000, 262144, 0); if (bios_only || !ret) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 63d19c8c6..4c6d90cea 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -10549,10 +10549,10 @@ const machine_t machines[] = { /* Has a National Semiconductor PC87332VLJ Super I/O with AMIKey 'F' KBC firmware. */ { .name = "[i430FX] Dell OptiPlex GXL/GXM", - .internal_name = "optiplex_gxl", + .internal_name = "optiplexgxl", .type = MACHINE_TYPE_SOCKET5, .chipset = MACHINE_CHIPSET_INTEL_430FX, - .init = machine_at_optiplex_gxl_init, + .init = machine_at_optiplexgxl_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -13147,10 +13147,10 @@ const machine_t machines[] = { */ { .name = "[i430TX] Dell OptiPlex GN+", - .internal_name = "optiplex_gn", + .internal_name = "optiplexgn", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, - .init = machine_at_optiplex_gn_init, + .init = machine_at_optiplexgn_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -15210,10 +15210,10 @@ const machine_t machines[] = { firmwares: AMI '5' MegaKey, Phoenix MultiKey/42 1.37, or Phoenix MultiKey/42i 4.16. */ { .name = "[i440LX] Dell OptiPlex GXa", - .internal_name = "optiplex_gxa", + .internal_name = "optiplexgxa", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_INTEL_440LX, - .init = machine_at_optiplex_gxa_init, + .init = machine_at_optiplexgxa_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, From 72a52318f56e274d6f66553d1a872604d07bed20 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 16:08:44 -0300 Subject: [PATCH 1013/1190] POST card: Streamline printing of the Dell ASCII mode --- src/device/postcard.c | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/device/postcard.c b/src/device/postcard.c index 27f5a5aa3..ec031c2b8 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -36,6 +36,7 @@ static uint16_t postcard_port; static uint8_t postcard_written[POSTCARDS_NUM]; static uint8_t postcard_ports_num = 1; static uint8_t postcard_prev_codes[POSTCARDS_NUM]; +static uint8_t postcard_dell_mode = 0; static char postcard_prev_diags[5] = { 0 }; #define UISTR_LEN 32 static char postcard_str[UISTR_LEN]; /* UI output string */ @@ -99,31 +100,23 @@ postcard_setui(void) ps[1][0], ps[1][1], ps[1][2], ps[1][3]); break; } - } else if (strstr(machines[machine].name, " Dell ") && - ((machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX) || - (machine_get_chipset(machine) >= MACHINE_CHIPSET_VLSI_SCAMP))) { - char dell_diags[10] = { 0 }; - - if (!postcard_written[1]) - snprintf(dell_diags, sizeof(dell_diags), "---- ----"); - else if (postcard_written[1] == 1) - snprintf(dell_diags, sizeof(dell_diags), "%s ----", postcard_diags); - else - snprintf(dell_diags, sizeof(dell_diags), "%s %s", postcard_diags, postcard_prev_diags); - - if (!postcard_written[0]) - snprintf(postcard_str, sizeof(postcard_str), "POST: -- -- %s", dell_diags); - else if (postcard_written[0] == 1) - snprintf(postcard_str, sizeof(postcard_str), "POST: %02X -- %s", postcard_codes[0], dell_diags); - else - snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X %s", postcard_codes[0], postcard_prev_codes[0], dell_diags); } else { + char dell_diags[11] = { 0 }; + if (postcard_dell_mode) { + if (!postcard_written[1]) + snprintf(dell_diags, sizeof(dell_diags), " ---- ----"); + else if (postcard_written[1] == 1) + snprintf(dell_diags, sizeof(dell_diags), " %s ----", postcard_diags); + else + snprintf(dell_diags, sizeof(dell_diags), " %s %s", postcard_diags, postcard_prev_diags); + } + if (!postcard_written[0]) - snprintf(postcard_str, sizeof(postcard_str), "POST: -- --"); + snprintf(postcard_str, sizeof(postcard_str), "POST: -- --%s", dell_diags); else if (postcard_written[0] == 1) - snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --", postcard_codes[0]); + snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --%s", postcard_codes[0], dell_diags); else - snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X", postcard_codes[0], postcard_prev_codes[0]); + snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X%s", postcard_codes[0], postcard_prev_codes[0], dell_diags); } ui_sb_bugui(postcard_str); @@ -225,9 +218,9 @@ postcard_init(UNUSED(const device_t *info)) io_sethandler(postcard_port, postcard_ports_num, NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); - if (strstr(machines[machine].name, " Dell ") && - ((machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX) || - (machine_get_chipset(machine) >= MACHINE_CHIPSET_VLSI_SCAMP))) + postcard_dell_mode = strstr(machines[machine].name, " Dell ") && + (machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX); + if (postcard_dell_mode) io_sethandler(is486 ? 0x00e0 : 0x00e4, 0x0001, NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL); From 2b71002daba7a02480507f480815d01cb8c05aba Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 28 May 2025 16:35:38 -0300 Subject: [PATCH 1014/1190] PCI: Fix and delegate bridge initialization on Dell riser machines --- src/device/pci_bridge.c | 45 +++++++++++++++++++------------------ src/include/86box/machine.h | 2 ++ src/include/86box/pci.h | 1 + src/machine/m_at_slot1.c | 4 ++-- src/machine/m_at_socket7.c | 13 +++++++++-- src/pci.c | 4 ++-- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 8893acf69..bf49baf14 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -87,6 +87,14 @@ pci_bridge_set_ctl(void *priv, uint8_t ctl) dev->ctl = ctl; } +uint8_t +pci_bridge_get_bus_index(void *priv) +{ + pci_bridge_t *dev = (pci_bridge_t *) priv; + + return dev->bus_index; +} + static void pci_bridge_write(int func, int addr, uint8_t val, void *priv) { @@ -513,11 +521,9 @@ static void * pci_bridge_init(const device_t *info) { uint8_t interrupts[4]; - uint8_t interrupt_count; uint8_t interrupt_mask; + uint8_t add_type; uint8_t slot_count; - uint8_t dell_slots[3] = { 0x09, 0x0a, 0x0b }; - uint8_t dell_interrupts[3][4] = { { 1, 2, 3, 4 }, { 4, 2, 1, 3 }, { 1, 3, 4, 2 } }; pci_bridge_t *dev = (pci_bridge_t *) calloc(1, sizeof(pci_bridge_t)); @@ -527,40 +533,35 @@ pci_bridge_init(const device_t *info) pci_bridge_reset(dev); - if (info->local == PCI_BRIDGE_DEC_21152) - pci_add_card(PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev, &dev->slot); - else - pci_add_bridge(AGP_BRIDGE(dev->local), pci_bridge_read, pci_bridge_write, dev, &dev->slot); - - interrupt_count = sizeof(interrupts); - interrupt_mask = interrupt_count - 1; + interrupt_mask = sizeof(interrupts) - 1; if (dev->slot < 32) { - for (uint8_t i = 0; i < interrupt_count; i++) + for (uint8_t i = 0; i <= interrupt_mask; i++) interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i); } pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]); - if (info->local == PCI_BRIDGE_DEC_21150) + if (info->local == PCI_BRIDGE_DEC_21150) { slot_count = 9; /* 9 bus masters */ - else if (info->local == PCI_BRIDGE_DEC_21152) - slot_count = 3; /* 3 bus masters */ - else + add_type = PCI_ADD_NORMAL; + } else if (info->local == PCI_BRIDGE_DEC_21152) { + slot_count = 0; /* 4 bus masters, but slots are added by the Dell machines */ + add_type = PCI_ADD_BRIDGE; + } else { slot_count = 1; /* AGP bridges always have 1 slot */ + add_type = PCI_ADD_AGPBRIDGE; + } + + pci_add_bridge(add_type, pci_bridge_read, pci_bridge_write, dev, &dev->slot); for (uint8_t i = 0; i < slot_count; i++) { - uint8_t slot = i; - if (info->local == PCI_BRIDGE_DEC_21152) { - slot = dell_slots[i]; - memcpy(interrupts, dell_interrupts[i], 4); - } /* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */ pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", - dev->bus_index, slot, interrupts[i & interrupt_mask], + dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]); - pci_register_bus_slot(dev->bus_index, slot, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, + pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 4129cead7..3231acd80 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -722,6 +722,8 @@ extern int machine_at_vectra54_init(const machine_t *); extern int machine_at_5sbm2_init(const machine_t *); /* m_at_socket7.c */ +extern void machine_at_optiplex_21152_init(void); + extern int machine_at_acerv35n_init(const machine_t *); extern int machine_at_p55t2p4_init(const machine_t *); extern int machine_at_m7shi_init(const machine_t *); diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 462b4f821..8887f89f4 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -283,6 +283,7 @@ extern void pci_init(int flags); /* PCI bridge stuff. */ extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); +extern uint8_t pci_bridge_get_bus_index(void *priv); #ifdef EMU_DEVICE_H extern const device_t dec21150_device; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 280462858..2ac805bee 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -170,14 +170,14 @@ machine_at_optiplexgxa_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0F, PCI_CARD_BRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_BRIDGE, 0, 0, 0, 0); if (sound_card_current[0] == SOUND_INTERNAL) device_add(machine_get_snd_device(machine)); device_add(&i440lx_device); device_add(&piix4_device); - device_add(&dec21152_device); + machine_at_optiplex_21152_init(); device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index dbc59ef17..46c7b7623 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -46,6 +46,15 @@ #include <86box/network.h> #include <86box/pci.h> +void +machine_at_optiplex_21152_init(void) +{ + uint8_t bus_index = pci_bridge_get_bus_index(device_add(&dec21152_device)); + pci_register_bus_slot(bus_index, 0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_bus_slot(bus_index, 0x0a, PCI_CARD_NORMAL, 4, 2, 1, 3); + pci_register_bus_slot(bus_index, 0x0b, PCI_CARD_NORMAL, 1, 3, 4, 2); +} + int machine_at_acerv35n_init(const machine_t *model) { @@ -989,7 +998,7 @@ machine_at_optiplexgn_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */ pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); /* 3C905, not yet emulated */ pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - pci_register_slot(0x0F, PCI_CARD_BRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_BRIDGE, 0, 0, 0, 0); if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); @@ -999,7 +1008,7 @@ machine_at_optiplexgn_init(const machine_t *model) device_add(&i430tx_device); device_add(&piix4_device); - device_add(&dec21152_device); + machine_at_optiplex_21152_init(); device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307)); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); diff --git a/src/pci.c b/src/pci.c index c3020ca73..94ab9d5f2 100644 --- a/src/pci.c +++ b/src/pci.c @@ -855,10 +855,10 @@ pci_register_card(int pci_card) /* Add an instance of the PCI bridge. */ void -pci_add_bridge(uint8_t agp, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot) +pci_add_bridge(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot) { pci_card_t *card; - uint8_t bridge_slot = agp ? pci_find_slot(PCI_ADD_AGPBRIDGE, 0xff) : last_normal_pci_card_id; + uint8_t bridge_slot = (add_type == PCI_ADD_NORMAL) ? last_normal_pci_card_id : pci_find_slot(add_type, 0xff); if (bridge_slot != PCI_CARD_INVALID) { card = &pci_cards[bridge_slot]; From 25f0a26ea1f786b299ad3e8bd79ee831e322f5ba Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 May 2025 09:45:49 +0200 Subject: [PATCH 1015/1190] Vastly improve the ALi M1409 emulation (all of shadow RAM now work, as does bus speed and external cache setting), and fix the "Writing unimplemented Cyrix register FF" error as well. --- src/chipset/ali1409.c | 272 ++++++++++++++++++++++++++++++++---------- src/cpu/cpu.c | 2 +- 2 files changed, 210 insertions(+), 64 deletions(-) diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c index 5009a6505..619843cda 100644 --- a/src/chipset/ali1409.c +++ b/src/chipset/ali1409.c @@ -61,91 +61,238 @@ ali1409_log(const char *fmt, ...) #endif typedef struct ali_1409_t { - uint8_t is_g; uint8_t index; uint8_t cfg_locked; - uint8_t reg_57h; uint8_t regs[256]; + uint8_t shadow[4]; uint8_t last_reg; } ali1409_t; +/* + This here is because from the two BIOS'es I used to reverse engineer this, + it is unclear which of the two interpretations of the shadow RAM register + operation is correct. + The 16 kB interpretation appears to work fine right now but it may be wrong, + so I left the 32 kB interpretation in as well. + */ +#ifdef INTERPRETATION_32KB +#define SHADOW_SIZE 0x00008000 +#else +#define SHADOW_SIZE 0x00004000 +#endif + +static void +ali1409_shadow_recalc(ali1409_t *dev) +{ + uint32_t base = 0x000c0000; + + for (uint8_t i = 0; i < 4; i++) { + uint8_t reg = 0x08 + i; + +#ifdef INTERPRETATION_32KB + for (uint8_t j = 0; j < 4; j += 2) { + uint8_t mask = (0x03 << j); +#else + for (uint8_t j = 0; j < 4; j++) { + uint8_t mask = (0x01 << j); +#endif + uint8_t r_on = dev->regs[reg] & 0x10; + uint8_t w_on = dev->regs[reg] & 0x20; + uint8_t val = dev->regs[reg] & mask; + uint8_t xor = (dev->shadow[i] ^ dev->regs[reg]) & (mask | 0x30); + int read = r_on ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + int write = w_on ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + + if (xor) { +#ifdef INTERPRETATION_32KB + switch (val >> j) { + case 0x00: + mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 0x01: + mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | write); + break; + case 0x02: + mem_set_mem_state_both(base, SHADOW_SIZE, read | write); + break; + case 0x03: + mem_set_mem_state_both(base, SHADOW_SIZE, read | MEM_WRITE_EXTANY); + break; + } +#else + switch (val >> j) { + case 0x00: + mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 0x01: + mem_set_mem_state_both(base, SHADOW_SIZE, read | write); + break; + } +#endif + } + + base += SHADOW_SIZE; + } + + dev->shadow[i] = dev->regs[reg]; + } + + flushmmucache_nopc(); +} static void ali1409_write(uint16_t addr, uint8_t val, void *priv) { ali1409_t *dev = (ali1409_t *) priv; - ali1409_log ("INPUT:addr %02x ,Value %02x \n" , addr , val); + ali1409_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); - if (addr & 1) { - if (dev->cfg_locked) { - if (dev->last_reg == 0x14 && val == 0x09) - dev->cfg_locked = 0; + if (addr & 0x0001) { + if (dev->cfg_locked) { + if ((dev->last_reg == 0x14) && (val == 0x09)) + dev->cfg_locked = 0; - dev->last_reg = val; - return; - } + dev->last_reg = val; + return; + } - if (dev->index == 0xff && val == 0xff) - dev->cfg_locked = 1; - else { - ali1409_log("Write reg %02x %02x %08x\n", dev->index, val, cs); - dev->regs[dev->index] = val; + /* It appears writing anything at all to register 0xFF locks it again. */ + if (dev->index == 0xff) + dev->cfg_locked = 1; + else if (dev->index < 0x44) { + ali1409_log("[%04X:%08X] [W] Register %02X = %02X\n", CS, cpu_state.pc, dev->index, val); - switch (dev->index) { - case 0xa: - switch ((val >> 4) & 3) { - case 0: - mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } + if (dev->index < 0x10) { + dev->regs[dev->index] = val; + + /* + There are still a lot of unknown here, but unfortunately, this is + as far as I have been able to come with two BIOS'es that are + available (the Acer 100T and an AMI Color dated 07/07/91). + */ + switch (dev->index) { + case 0x02: + /* + - Bit 7: The RAS address hold time: + - 0: 1/2 T; + - 1: 1 T. + - Bits 6-4: The RAS precharge time: + - 0, 0, 0: 1.5 T; + - 0, 0, 1: 2 T; + - 0, 1, 0: 2.5 T; + - 0, 1, 1: 3 T; + - 1, 0, 0: 3.5 T; + - 1, 0, 1: 4 T; + - 1, 1, 0: Reserved; + - 1, 1, 1: Reserved. + - Bit 3: Early miss cycle: + - 0: Disabled; + - 1: Enabled. + */ + break; + case 0x03: + /* + - Bit 6: CAS pulse for read cycle: + - 0: 1 T; + - 1: 1.5 T or 2 T. + I can not get the 2.5 T or 3 T setting to apply so + I have no idea what bit governs that. + - Bits 5, 4: CAS pulse for write cycle: + - 0, 0: 0.5 T or 1 T; + - 0, 1: 1.5 T or 2 T; + - 1, 0: 2.5 T or 3 T; + - 1, 1: Reserved. + - Bit 3: CAS active for read cycle: + - 0: Disabled; + - 1: Enabled. + - Bit 2: CAS active for write cycle: + - 0: Disabled; + - 1: Enabled. + */ + break; + case 0x06: + /* + - Bits 6-4: Clock divider: + - 0, 0, 0: / 2; + - 0, 0, 1: / 4; + - 0, 1, 0: / 8; + - 0, 1, 1: Reserved; + - 1, 0, 0: / 3; + - 1, 0, 1: / 6; + - 1, 1, 0: / 5; + - 1, 1, 1: / 10. + */ + switch ((val >> 4) & 7) { + default: + case 3: /* Reserved */ + cpu_set_isa_speed(7159091); break; - case 0xb: - switch ((val >> 4) & 3) { - case 0: - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 2: - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY| MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } + + case 0: + cpu_set_isa_speed(cpu_busspeed / 2); + break; + + case 1: + cpu_set_isa_speed(cpu_busspeed / 4); + break; + + case 2: + cpu_set_isa_speed(cpu_busspeed / 8); + break; + + case 4: + cpu_set_isa_speed(cpu_busspeed / 3); + break; + + case 5: + cpu_set_isa_speed(cpu_busspeed / 6); + break; + + case 6: + cpu_set_isa_speed(cpu_busspeed / 5); + break; + + case 7: + cpu_set_isa_speed(cpu_busspeed / 10); break; } + break; + case 0x08 ... 0x0b: + ali1409_shadow_recalc(dev); + break; + case 0x0c: + /* + This appears to be turbo in bit 4 (1 = on, 0 = off), + and bus speed in the rest of the bits. + */ + break; + case 0x0d: + cpu_cache_ext_enabled = !!(val & 0x08); + cpu_update_waitstates(); + break; } - } else - dev->index = val; + } + } + } else + dev->index = val; } static uint8_t ali1409_read(uint16_t addr, void *priv) { - ali1409_log ("reading at %02X\n",addr); const ali1409_t *dev = (ali1409_t *) priv; uint8_t ret = 0xff; if (dev->cfg_locked) ret = 0xff; - if (addr & 1) { - if ((dev->index >= 0xc0 || dev->index == 0x20) && cpu_iscyrix) - ret = 0xff; + else if (addr & 0x0001) { + if (dev->index < 0x44) ret = dev->regs[dev->index]; - } else - ret = dev->index; + } else + ret = dev->index; + + ali1409_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + return ret; } @@ -166,17 +313,16 @@ ali1409_init(UNUSED(const device_t *info)) dev->cfg_locked = 1; - /* M1409 Ports: - 22h Index Port - 23h Data Port - */ - - ali1409_log ("Bus speed: %i", cpu_busspeed); - + ali1409_log("Bus speed: %i\n", cpu_busspeed); io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); - io_sethandler(0x037f, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); - io_sethandler(0x03f3, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + + dev->regs[0x0f] = 0x08; + + cpu_set_isa_speed(7159091); + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); return dev; } diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index d13dfe041..ec026d95e 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -4264,7 +4264,7 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) cyrix_addr = val; else if (addr < 0xf1) switch (cyrix_addr) { default: - if (cyrix_addr >= 0xc0) + if ((cyrix_addr >= 0xc0) && (cyrix_addr != 0xff)) fatal("Writing unimplemented Cyrix register %02X\n", cyrix_addr); break; From 168282875c991cc37e5c16f70e14a6d3f60aeb91 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 29 May 2025 14:09:27 +0500 Subject: [PATCH 1016/1190] Fix conversion to/from VHD-compatible CHS geometry not working properly --- src/qt/qt_harddiskdialog.cpp | 67 +++++++++++++++++++++--------------- src/qt/qt_harddiskdialog.hpp | 6 ++++ 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index 9e5563536..ae1c60971 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -199,7 +199,7 @@ HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index) * than a tenth of a percent change in size. */ static void -adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry) +adjust_86box_geometry_for_vhd(_86BoxGeom *_86box_geometry, MVHDGeom *vhd_geometry) { if (_86box_geometry->cyl <= 65535) { vhd_geometry->cyl = _86box_geometry->cyl; @@ -226,10 +226,10 @@ adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry) } static HarddiskDialog *callbackPtr = nullptr; -static MVHDGeom -create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, uint8_t heads, uint8_t spt) +static _86BoxGeom +create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint32_t cyl, uint32_t heads, uint32_t spt) { - MVHDGeom _86box_geometry = { + _86BoxGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt @@ -256,10 +256,10 @@ create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, return _86box_geometry; } -static MVHDGeom -create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize) +static _86BoxGeom +create_drive_vhd_dynamic(const QString &fileName, uint32_t cyl, uint32_t heads, uint32_t spt, int blocksize) { - MVHDGeom _86box_geometry = { + _86BoxGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt @@ -287,7 +287,7 @@ create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, u return _86box_geometry; } -static MVHDGeom +static _86BoxGeom create_drive_vhd_diff(const QString &fileName, const QString &parentFileName, int blocksize) { int vhd_error = 0; @@ -299,25 +299,31 @@ create_drive_vhd_diff(const QString &fileName, const QString &parentFileName, in options.parent_path = parentFilenameBytes.data(); options.type = MVHD_TYPE_DIFF; - MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); - MVHDGeom vhd_geometry; + MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); + MVHDGeom vhd_geometry; + _86BoxGeom _86box_geometry; if (vhd == NULL) { - vhd_geometry.cyl = 0; - vhd_geometry.heads = 0; - vhd_geometry.spt = 0; + _86box_geometry.cyl = 0; + _86box_geometry.heads = 0; + _86box_geometry.spt = 0; } else { vhd_geometry = mvhd_get_geometry(vhd); if (vhd_geometry.spt > 63) { - vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63); - vhd_geometry.heads = 16; - vhd_geometry.spt = 63; + _86box_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63); + _86box_geometry.heads = 16; + _86box_geometry.spt = 63; + } else { + _86box_geometry.cyl = vhd_geometry.cyl; + _86box_geometry.heads = vhd_geometry.heads; + _86box_geometry.spt = vhd_geometry.spt; } + mvhd_close(vhd); } - return vhd_geometry; + return _86box_geometry; } void @@ -409,7 +415,7 @@ HarddiskDialog::onCreateNewFile() } else if (img_format >= IMG_FMT_VHD_FIXED) { /* VHD file */ file.close(); - MVHDGeom _86box_geometry {}; + _86BoxGeom _86box_geometry {}; int block_size = ui->comboBoxBlockSize->currentIndex() == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL; switch (img_format) { case IMG_FMT_VHD_FIXED: @@ -493,10 +499,14 @@ HarddiskDialog::onCreateNewFile() } static void -adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) +adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry, _86BoxGeom *_86box_geometry) { - if (vhd_geometry->spt <= 63) + if (vhd_geometry->spt <= 63) { + _86box_geometry->cyl = vhd_geometry->cyl; + _86box_geometry->heads = vhd_geometry->heads; + _86box_geometry->spt = vhd_geometry->spt; return; + } int desired_sectors = vhd_geometry->cyl * vhd_geometry->heads * vhd_geometry->spt; if (desired_sectors > 267321600) @@ -506,9 +516,9 @@ adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) if (remainder > 0) desired_sectors -= remainder; - vhd_geometry->cyl = desired_sectors / (16 * 63); - vhd_geometry->heads = 16; - vhd_geometry->spt = 63; + _86box_geometry->cyl = desired_sectors / (16 * 63); + _86box_geometry->heads = 16; + _86box_geometry->spt = 63; } void @@ -602,11 +612,12 @@ HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck) } } - MVHDGeom vhd_geom = mvhd_get_geometry(vhd); - adjust_vhd_geometry_for_86box(&vhd_geom); - cylinders = vhd_geom.cyl; - heads = vhd_geom.heads; - sectors = vhd_geom.spt; + MVHDGeom vhd_geom = mvhd_get_geometry(vhd); + _86BoxGeom _86box_geom; + adjust_vhd_geometry_for_86box(&vhd_geom, &_86box_geom); + cylinders = _86box_geom.cyl; + heads = _86box_geom.heads; + sectors = _86box_geom.spt; size = static_cast(cylinders * heads * sectors * 512); mvhd_close(vhd); } else { diff --git a/src/qt/qt_harddiskdialog.hpp b/src/qt/qt_harddiskdialog.hpp index 9de61c51b..62ec6e963 100644 --- a/src/qt/qt_harddiskdialog.hpp +++ b/src/qt/qt_harddiskdialog.hpp @@ -64,4 +64,10 @@ private: void recalcSelection(); }; +typedef struct _86BoxGeom { + uint32_t cyl; + uint32_t heads; + uint32_t spt; +} _86BoxGeom; + #endif // QT_HARDDISKDIALOG_HPP From a690870ada032332c0816330efb2d38aa3b34264 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Thu, 29 May 2025 19:50:11 +0200 Subject: [PATCH 1017/1190] Add SNI D943 machine entry. --- src/machine/m_at_socket7_3v.c | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 5b5724e37..ca096c6ad 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -612,6 +612,91 @@ machine_at_8500tuc_init(const machine_t *model) return ret; } +int +machine_at_d943_init(const machine_t *model) + +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 2, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 3, 2, 4); + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_pci_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_EDO, 0x7, 256); + + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5436_onboard_pci_device); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&sb_vibra16s_onboard_device); + + return ret; +} + +static const device_config_t d943_config[] = { + // clang-format off + { + .name = "bios_versions", + .description = "BIOS Versions", + .type = CONFIG_BIOS, + .default_string = "d943_oct96", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 4.05 Revision 1.02.943 (10/28/1996)", .internal_name = "d943_oct96", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct96.bin", "" } }, + { .name = "Version 4.05 Revision 1.03.943 (12/12/1996)", .internal_name = "d943_dec96", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_dec96.bin", "" } }, + { .name = "Version 4.05 Revision 1.05.943 (09/04/1997)", .internal_name = "d943_sept97", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_sept97.bin", "" } }, + { .name = "Version 4.05 Revision 1.06.943 (10/29/1997)", .internal_name = "d943_oct97", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct97.bin", "" } }, + + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + + + +const device_t d943_device = { + .name = "Siemens-Nixdorf D943", + .internal_name = "d943", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = &d943_config[0] +}; + int machine_at_p55t2s_init(const machine_t *model) { From 657dd522f4053e18a90048386fb791bf8c9df5ac Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Thu, 29 May 2025 19:52:15 +0200 Subject: [PATCH 1018/1190] Add SNI D943 machine table entry. --- src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5626b0728..d9231cc75 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -66,6 +66,7 @@ extern const device_t vendex_device; extern const device_t c5sbm2_device; extern const device_t sb486pv_device; extern const device_t ap5s_device; +extern const device_t d943_device; extern const device_t dells333sl_device; const machine_filter_t machine_types[] = { @@ -11777,6 +11778,46 @@ const machine_t machines[] = { .net_device = NULL }, + { + .name = "[i430HX] Siemens-Nixdorf D943", + .internal_name = "d943", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_d943_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI , + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 511, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &d943_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5436_onboard_pci_device, + .snd_device = &sb_vibra16s_onboard_device, + .net_device = NULL + }, + /* 430VX */ /* Has a SM(S)C FDC37C932FR Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ From 8f551991a48feab9297056d95ad1d2ff5310e6ee Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Thu, 29 May 2025 19:54:03 +0200 Subject: [PATCH 1019/1190] Update SNI D943 Audio and Video code. --- src/machine/m_at_socket7_3v.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index ca096c6ad..7dd1f9bf0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -646,11 +646,11 @@ machine_at_d943_init(const machine_t *model) spd_register(SPD_TYPE_EDO, 0x7, 256); - if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5436_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); if (sound_card_current[0] == SOUND_INTERNAL) - device_add(&sb_vibra16s_onboard_device); + machine_snd = device_add(machine_get_snd_device(machine)); return ret; } From 8f78320aaf105f1cd62160ac7035bda70fa23832 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Thu, 29 May 2025 19:54:55 +0200 Subject: [PATCH 1020/1190] Add SNI D943 machine definition. --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 3231acd80..c8166a973 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -708,6 +708,7 @@ extern int machine_at_fmb_init(const machine_t *); extern int machine_at_acerm3a_init(const machine_t *); extern int machine_at_ap53_init(const machine_t *); extern int machine_at_8500tuc_init(const machine_t *); +extern int machine_at_d943_init(const machine_t *); extern int machine_at_p55t2s_init(const machine_t *); extern int machine_at_p5vxb_init(const machine_t *); From 94f49282ac4854f244e676eae44ed91a94bfff0b Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Thu, 29 May 2025 20:01:53 +0200 Subject: [PATCH 1021/1190] Remove unnecessary Machine flag from the D943. --- 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 d9231cc75..a961e9997 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11799,7 +11799,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI , + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_GAMEPORT | MACHINE_APM, .ram = { .min = 8192, .max = 131072, From 3b9b96700753269ec0fccb3aa1d3e896743d3ef7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 May 2025 10:32:54 +0200 Subject: [PATCH 1022/1190] GUS MAX: Fix the internal name, fixes #5640. --- src/sound/snd_gus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index fff679e81..5044c6f54 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1473,7 +1473,7 @@ const device_t gus_device = { const device_t gus_max_device = { .name = "Gravis UltraSound MAX", - .internal_name = "gus", + .internal_name = "gusmax", .flags = DEVICE_ISA16, .local = GUS_MAX, .init = gus_init, From c6da2caff2c8847f46fa20d00265b69723624104 Mon Sep 17 00:00:00 2001 From: cold-brewed <47337035+cold-brewed@users.noreply.github.com> Date: Sat, 8 Jun 2024 13:25:09 -0400 Subject: [PATCH 1023/1190] vmm preview --- src/86box.c | 25 +- src/include/86box/86box.h | 2 + src/qt/CMakeLists.txt | 38 + src/qt/assets/86box-wizard.png | Bin 0 -> 8314 bytes src/qt/assets/systemicons/cpq_deskpro.png | Bin 0 -> 244984 bytes src/qt/assets/systemicons/cpq_port_386.png | Bin 0 -> 250814 bytes src/qt/assets/systemicons/cpq_port_II.png | Bin 0 -> 161871 bytes src/qt/assets/systemicons/cpq_port_III.png | Bin 0 -> 202844 bytes src/qt/assets/systemicons/cpq_portable.png | Bin 0 -> 140593 bytes src/qt/assets/systemicons/cpq_pres_2240.png | Bin 0 -> 166186 bytes src/qt/assets/systemicons/cpq_pres_4500.png | Bin 0 -> 132431 bytes src/qt/assets/systemicons/ibm330.png | Bin 0 -> 186586 bytes src/qt/assets/systemicons/ibm_at.png | Bin 0 -> 283163 bytes src/qt/assets/systemicons/ibm_pc_81.png | Bin 0 -> 295676 bytes src/qt/assets/systemicons/ibm_pc_82.png | Bin 0 -> 295676 bytes src/qt/assets/systemicons/ibm_pcjr.png | Bin 0 -> 296020 bytes src/qt/assets/systemicons/ibm_ps2_m70.png | Bin 0 -> 219165 bytes src/qt/assets/systemicons/ibm_ps2_m80.png | Bin 0 -> 265107 bytes src/qt/assets/systemicons/ibm_psvp_486.png | Bin 0 -> 217113 bytes src/qt/assets/systemicons/ibm_psvp_p60.png | Bin 0 -> 217113 bytes src/qt/assets/systemicons/ibm_xt_82.png | Bin 0 -> 295676 bytes src/qt/assets/systemicons/ibm_xt_86.png | Bin 0 -> 295676 bytes src/qt/assets/systemicons/olivetti_m19.png | Bin 0 -> 262763 bytes src/qt/assets/systemicons/olivetti_m21.png | Bin 0 -> 324694 bytes src/qt/assets/systemicons/olivetti_m24.png | Bin 0 -> 209215 bytes src/qt/assets/systemicons/olivetti_m24sp.png | Bin 0 -> 209215 bytes src/qt/assets/systemicons/os_archlinux_x2.png | Bin 0 -> 3833 bytes src/qt/assets/systemicons/os_cloud_x2.png | Bin 0 -> 1551 bytes src/qt/assets/systemicons/os_debian_x2.png | Bin 0 -> 5228 bytes src/qt/assets/systemicons/os_dos_x2.png | Bin 0 -> 3718 bytes src/qt/assets/systemicons/os_fedora_x2.png | Bin 0 -> 3449 bytes src/qt/assets/systemicons/os_freebsd_x2.png | Bin 0 -> 3969 bytes src/qt/assets/systemicons/os_gentoo_x2.png | Bin 0 -> 3845 bytes src/qt/assets/systemicons/os_jrockitve_x2.png | Bin 0 -> 3703 bytes src/qt/assets/systemicons/os_l4_x2.png | Bin 0 -> 4348 bytes src/qt/assets/systemicons/os_linux22_x2.png | Bin 0 -> 5219 bytes src/qt/assets/systemicons/os_linux24_x2.png | Bin 0 -> 5161 bytes src/qt/assets/systemicons/os_linux26_x2.png | Bin 0 -> 5274 bytes src/qt/assets/systemicons/os_linux_x2.png | Bin 0 -> 4364 bytes src/qt/assets/systemicons/os_macosx_x2.png | Bin 0 -> 3783 bytes src/qt/assets/systemicons/os_mandriva_x2.png | Bin 0 -> 3858 bytes src/qt/assets/systemicons/os_netbsd_x2.png | Bin 0 -> 4123 bytes src/qt/assets/systemicons/os_netware_x2.png | Bin 0 -> 4623 bytes src/qt/assets/systemicons/os_openbsd_x2.png | Bin 0 -> 6027 bytes src/qt/assets/systemicons/os_opensuse_x2.png | Bin 0 -> 7361 bytes src/qt/assets/systemicons/os_oracle_x2.png | Bin 0 -> 5728 bytes .../systemicons/os_oraclesolaris_x2.png | Bin 0 -> 2694 bytes src/qt/assets/systemicons/os_os2_other_x2.png | Bin 0 -> 5728 bytes src/qt/assets/systemicons/os_os2ecs_x2.png | Bin 0 -> 4796 bytes src/qt/assets/systemicons/os_os2warp3_x2.png | Bin 0 -> 5940 bytes src/qt/assets/systemicons/os_os2warp45_x2.png | Bin 0 -> 4476 bytes src/qt/assets/systemicons/os_os2warp4_x2.png | Bin 0 -> 4129 bytes src/qt/assets/systemicons/os_other_x2.png | Bin 0 -> 4271 bytes src/qt/assets/systemicons/os_qnx_x2.png | Bin 0 -> 6414 bytes src/qt/assets/systemicons/os_redhat_x2.png | Bin 0 -> 5231 bytes src/qt/assets/systemicons/os_solaris_x2.png | Bin 0 -> 4358 bytes .../assets/systemicons/os_turbolinux_x2.png | Bin 0 -> 4018 bytes src/qt/assets/systemicons/os_ubuntu_x2.png | Bin 0 -> 4050 bytes src/qt/assets/systemicons/os_win10_x2.png | Bin 0 -> 6135 bytes src/qt/assets/systemicons/os_win2k3_x2.png | Bin 0 -> 6250 bytes src/qt/assets/systemicons/os_win2k8_x2.png | Bin 0 -> 6322 bytes src/qt/assets/systemicons/os_win2k_x2.png | Bin 0 -> 5948 bytes src/qt/assets/systemicons/os_win31_x2.png | Bin 0 -> 6116 bytes src/qt/assets/systemicons/os_win7_x2.png | Bin 0 -> 5835 bytes src/qt/assets/systemicons/os_win81_x2.png | Bin 0 -> 6134 bytes src/qt/assets/systemicons/os_win8_x2.png | Bin 0 -> 6158 bytes src/qt/assets/systemicons/os_win95_x2.png | Bin 0 -> 6296 bytes src/qt/assets/systemicons/os_win98_x2.png | Bin 0 -> 6491 bytes src/qt/assets/systemicons/os_win_other_x2.png | Bin 0 -> 5454 bytes src/qt/assets/systemicons/os_winme_x2.png | Bin 0 -> 5959 bytes src/qt/assets/systemicons/os_winnt4_x2.png | Bin 0 -> 6045 bytes src/qt/assets/systemicons/os_winvista_x2.png | Bin 0 -> 6013 bytes src/qt/assets/systemicons/os_winxp_x2.png | Bin 0 -> 6340 bytes src/qt/assets/systemicons/os_xandros_x2.png | Bin 0 -> 3209 bytes src/qt/assets/systemicons/pb_bora_pro.png | Bin 0 -> 172596 bytes src/qt/assets/systemicons/pb_pb410.png | Bin 0 -> 209719 bytes src/qt/assets/systemicons/pb_pb640.png | Bin 0 -> 177292 bytes src/qt/assets/systemicons/pb_pb680.png | Bin 0 -> 172604 bytes src/qt/assets/systemicons/tandy_1000.png | Bin 0 -> 160013 bytes src/qt/assets/systemicons/tandy_1000_hx.png | Bin 0 -> 179510 bytes src/qt/assets/systemicons/tandy_1000_sl2.png | Bin 0 -> 213622 bytes src/qt/assets/systemicons/toshiba_t1000.png | Bin 0 -> 157081 bytes src/qt/assets/systemicons/toshiba_t1200.png | Bin 0 -> 291942 bytes .../assets/systemicons/toshiba_t1200_hdd.png | Bin 0 -> 291942 bytes src/qt/icons/green-square-16.png | Bin 0 -> 115 bytes src/qt/icons/pause-16.png | Bin 0 -> 123 bytes src/qt/icons/play-16.png | Bin 0 -> 156 bytes src/qt/icons/red-power-16.png | Bin 0 -> 174 bytes src/qt/icons/red-square-16.png | Bin 0 -> 118 bytes src/qt/icons/stop-16.png | Bin 0 -> 120 bytes src/qt/icons/yellow-square-16.png | Bin 0 -> 117 bytes src/qt/qt_downloader.cpp | 95 ++ src/qt/qt_downloader.hpp | 57 ++ src/qt/qt_main.cpp | 45 + src/qt/qt_mainwindow.cpp | 1 + src/qt/qt_mainwindow.hpp | 4 + src/qt/qt_updatecheck.cpp | 360 +++++++ src/qt/qt_updatecheck.hpp | 104 ++ src/qt/qt_updatecheckdialog.cpp | 90 ++ src/qt/qt_updatecheckdialog.hpp | 47 + src/qt/qt_updatecheckdialog.ui | 106 +++ src/qt/qt_updatedetails.cpp | 111 +++ src/qt/qt_updatedetails.hpp | 43 + src/qt/qt_updatedetails.ui | 192 ++++ src/qt/qt_vmmanager_addmachine.cpp | 361 +++++++ src/qt/qt_vmmanager_addmachine.hpp | 115 +++ src/qt/qt_vmmanager_clientsocket.cpp | 236 +++++ src/qt/qt_vmmanager_clientsocket.hpp | 71 ++ src/qt/qt_vmmanager_config.cpp | 76 ++ src/qt/qt_vmmanager_config.hpp | 46 + src/qt/qt_vmmanager_details.cpp | 345 +++++++ src/qt/qt_vmmanager_details.hpp | 89 ++ src/qt/qt_vmmanager_details.ui | 293 ++++++ src/qt/qt_vmmanager_detailsection.cpp | 294 ++++++ src/qt/qt_vmmanager_detailsection.hpp | 101 ++ src/qt/qt_vmmanager_detailsection.ui | 91 ++ src/qt/qt_vmmanager_listviewdelegate.cpp | 241 +++++ src/qt/qt_vmmanager_listviewdelegate.hpp | 67 ++ src/qt/qt_vmmanager_main.cpp | 518 ++++++++++ src/qt/qt_vmmanager_main.hpp | 167 ++++ src/qt/qt_vmmanager_main.ui | 119 +++ src/qt/qt_vmmanager_mainwindow.cpp | 178 ++++ src/qt/qt_vmmanager_mainwindow.hpp | 59 ++ src/qt/qt_vmmanager_mainwindow.ui | 224 +++++ src/qt/qt_vmmanager_model.cpp | 163 ++++ src/qt/qt_vmmanager_model.hpp | 91 ++ src/qt/qt_vmmanager_preferences.cpp | 82 ++ src/qt/qt_vmmanager_preferences.hpp | 46 + src/qt/qt_vmmanager_preferences.ui | 130 +++ src/qt/qt_vmmanager_protocol.cpp | 131 +++ src/qt/qt_vmmanager_protocol.hpp | 93 ++ src/qt/qt_vmmanager_serversocket.cpp | 207 ++++ src/qt/qt_vmmanager_serversocket.hpp | 82 ++ src/qt/qt_vmmanager_system.cpp | 888 ++++++++++++++++++ src/qt/qt_vmmanager_system.hpp | 188 ++++ src/qt_resources.qrc | 91 ++ 136 files changed, 7194 insertions(+), 9 deletions(-) create mode 100644 src/qt/assets/86box-wizard.png create mode 100644 src/qt/assets/systemicons/cpq_deskpro.png create mode 100644 src/qt/assets/systemicons/cpq_port_386.png create mode 100644 src/qt/assets/systemicons/cpq_port_II.png create mode 100644 src/qt/assets/systemicons/cpq_port_III.png create mode 100644 src/qt/assets/systemicons/cpq_portable.png create mode 100644 src/qt/assets/systemicons/cpq_pres_2240.png create mode 100644 src/qt/assets/systemicons/cpq_pres_4500.png create mode 100644 src/qt/assets/systemicons/ibm330.png create mode 100644 src/qt/assets/systemicons/ibm_at.png create mode 100644 src/qt/assets/systemicons/ibm_pc_81.png create mode 100644 src/qt/assets/systemicons/ibm_pc_82.png create mode 100644 src/qt/assets/systemicons/ibm_pcjr.png create mode 100644 src/qt/assets/systemicons/ibm_ps2_m70.png create mode 100644 src/qt/assets/systemicons/ibm_ps2_m80.png create mode 100644 src/qt/assets/systemicons/ibm_psvp_486.png create mode 100644 src/qt/assets/systemicons/ibm_psvp_p60.png create mode 100644 src/qt/assets/systemicons/ibm_xt_82.png create mode 100644 src/qt/assets/systemicons/ibm_xt_86.png create mode 100644 src/qt/assets/systemicons/olivetti_m19.png create mode 100644 src/qt/assets/systemicons/olivetti_m21.png create mode 100644 src/qt/assets/systemicons/olivetti_m24.png create mode 100644 src/qt/assets/systemicons/olivetti_m24sp.png create mode 100644 src/qt/assets/systemicons/os_archlinux_x2.png create mode 100644 src/qt/assets/systemicons/os_cloud_x2.png create mode 100644 src/qt/assets/systemicons/os_debian_x2.png create mode 100644 src/qt/assets/systemicons/os_dos_x2.png create mode 100644 src/qt/assets/systemicons/os_fedora_x2.png create mode 100644 src/qt/assets/systemicons/os_freebsd_x2.png create mode 100644 src/qt/assets/systemicons/os_gentoo_x2.png create mode 100644 src/qt/assets/systemicons/os_jrockitve_x2.png create mode 100644 src/qt/assets/systemicons/os_l4_x2.png create mode 100644 src/qt/assets/systemicons/os_linux22_x2.png create mode 100644 src/qt/assets/systemicons/os_linux24_x2.png create mode 100644 src/qt/assets/systemicons/os_linux26_x2.png create mode 100644 src/qt/assets/systemicons/os_linux_x2.png create mode 100644 src/qt/assets/systemicons/os_macosx_x2.png create mode 100644 src/qt/assets/systemicons/os_mandriva_x2.png create mode 100644 src/qt/assets/systemicons/os_netbsd_x2.png create mode 100644 src/qt/assets/systemicons/os_netware_x2.png create mode 100644 src/qt/assets/systemicons/os_openbsd_x2.png create mode 100644 src/qt/assets/systemicons/os_opensuse_x2.png create mode 100644 src/qt/assets/systemicons/os_oracle_x2.png create mode 100644 src/qt/assets/systemicons/os_oraclesolaris_x2.png create mode 100644 src/qt/assets/systemicons/os_os2_other_x2.png create mode 100644 src/qt/assets/systemicons/os_os2ecs_x2.png create mode 100644 src/qt/assets/systemicons/os_os2warp3_x2.png create mode 100644 src/qt/assets/systemicons/os_os2warp45_x2.png create mode 100644 src/qt/assets/systemicons/os_os2warp4_x2.png create mode 100644 src/qt/assets/systemicons/os_other_x2.png create mode 100644 src/qt/assets/systemicons/os_qnx_x2.png create mode 100644 src/qt/assets/systemicons/os_redhat_x2.png create mode 100644 src/qt/assets/systemicons/os_solaris_x2.png create mode 100644 src/qt/assets/systemicons/os_turbolinux_x2.png create mode 100644 src/qt/assets/systemicons/os_ubuntu_x2.png create mode 100644 src/qt/assets/systemicons/os_win10_x2.png create mode 100644 src/qt/assets/systemicons/os_win2k3_x2.png create mode 100644 src/qt/assets/systemicons/os_win2k8_x2.png create mode 100644 src/qt/assets/systemicons/os_win2k_x2.png create mode 100644 src/qt/assets/systemicons/os_win31_x2.png create mode 100644 src/qt/assets/systemicons/os_win7_x2.png create mode 100644 src/qt/assets/systemicons/os_win81_x2.png create mode 100644 src/qt/assets/systemicons/os_win8_x2.png create mode 100644 src/qt/assets/systemicons/os_win95_x2.png create mode 100644 src/qt/assets/systemicons/os_win98_x2.png create mode 100644 src/qt/assets/systemicons/os_win_other_x2.png create mode 100644 src/qt/assets/systemicons/os_winme_x2.png create mode 100644 src/qt/assets/systemicons/os_winnt4_x2.png create mode 100644 src/qt/assets/systemicons/os_winvista_x2.png create mode 100644 src/qt/assets/systemicons/os_winxp_x2.png create mode 100644 src/qt/assets/systemicons/os_xandros_x2.png create mode 100644 src/qt/assets/systemicons/pb_bora_pro.png create mode 100644 src/qt/assets/systemicons/pb_pb410.png create mode 100644 src/qt/assets/systemicons/pb_pb640.png create mode 100644 src/qt/assets/systemicons/pb_pb680.png create mode 100644 src/qt/assets/systemicons/tandy_1000.png create mode 100644 src/qt/assets/systemicons/tandy_1000_hx.png create mode 100644 src/qt/assets/systemicons/tandy_1000_sl2.png create mode 100644 src/qt/assets/systemicons/toshiba_t1000.png create mode 100644 src/qt/assets/systemicons/toshiba_t1200.png create mode 100644 src/qt/assets/systemicons/toshiba_t1200_hdd.png create mode 100644 src/qt/icons/green-square-16.png create mode 100644 src/qt/icons/pause-16.png create mode 100644 src/qt/icons/play-16.png create mode 100644 src/qt/icons/red-power-16.png create mode 100644 src/qt/icons/red-square-16.png create mode 100644 src/qt/icons/stop-16.png create mode 100644 src/qt/icons/yellow-square-16.png create mode 100644 src/qt/qt_downloader.cpp create mode 100644 src/qt/qt_downloader.hpp create mode 100644 src/qt/qt_updatecheck.cpp create mode 100644 src/qt/qt_updatecheck.hpp create mode 100644 src/qt/qt_updatecheckdialog.cpp create mode 100644 src/qt/qt_updatecheckdialog.hpp create mode 100644 src/qt/qt_updatecheckdialog.ui create mode 100644 src/qt/qt_updatedetails.cpp create mode 100644 src/qt/qt_updatedetails.hpp create mode 100644 src/qt/qt_updatedetails.ui create mode 100644 src/qt/qt_vmmanager_addmachine.cpp create mode 100644 src/qt/qt_vmmanager_addmachine.hpp create mode 100644 src/qt/qt_vmmanager_clientsocket.cpp create mode 100644 src/qt/qt_vmmanager_clientsocket.hpp create mode 100644 src/qt/qt_vmmanager_config.cpp create mode 100644 src/qt/qt_vmmanager_config.hpp create mode 100644 src/qt/qt_vmmanager_details.cpp create mode 100644 src/qt/qt_vmmanager_details.hpp create mode 100644 src/qt/qt_vmmanager_details.ui create mode 100644 src/qt/qt_vmmanager_detailsection.cpp create mode 100644 src/qt/qt_vmmanager_detailsection.hpp create mode 100644 src/qt/qt_vmmanager_detailsection.ui create mode 100644 src/qt/qt_vmmanager_listviewdelegate.cpp create mode 100644 src/qt/qt_vmmanager_listviewdelegate.hpp create mode 100644 src/qt/qt_vmmanager_main.cpp create mode 100644 src/qt/qt_vmmanager_main.hpp create mode 100644 src/qt/qt_vmmanager_main.ui create mode 100644 src/qt/qt_vmmanager_mainwindow.cpp create mode 100644 src/qt/qt_vmmanager_mainwindow.hpp create mode 100644 src/qt/qt_vmmanager_mainwindow.ui create mode 100644 src/qt/qt_vmmanager_model.cpp create mode 100644 src/qt/qt_vmmanager_model.hpp create mode 100644 src/qt/qt_vmmanager_preferences.cpp create mode 100644 src/qt/qt_vmmanager_preferences.hpp create mode 100644 src/qt/qt_vmmanager_preferences.ui create mode 100644 src/qt/qt_vmmanager_protocol.cpp create mode 100644 src/qt/qt_vmmanager_protocol.hpp create mode 100644 src/qt/qt_vmmanager_serversocket.cpp create mode 100644 src/qt/qt_vmmanager_serversocket.hpp create mode 100644 src/qt/qt_vmmanager_system.cpp create mode 100644 src/qt/qt_vmmanager_system.hpp diff --git a/src/86box.c b/src/86box.c index f54a69b79..c17e697e1 100644 --- a/src/86box.c +++ b/src/86box.c @@ -251,6 +251,8 @@ struct accelKey def_acc_keys[NUM_ACCELS] = { .seq="Ctrl+Alt+M" } }; +char vmm_path[1024] = { '\0'}; /* TEMPORARY - VM manager path to scan for VMs */ +int vmm_enabled = 0; /* Statistics. */ extern int mmuflush; @@ -598,8 +600,8 @@ pc_show_usage(char *s) #ifdef _WIN32 "-D or --debug\t\t\t- force debug output logging\n" #endif -#if 0 - "-E or --nographic\t\t- forces the old behavior\n" +#if 1 + "-E or --vmmpath\t\t- vm manager path\n" #endif "-F or --fullscreen\t\t- start in fullscreen mode\n" "-G or --lang langid\t\t- start with specified language\n" @@ -732,13 +734,14 @@ usage: } else if (!strcasecmp(argv[c], "--debug") || !strcasecmp(argv[c], "-D")) { force_debug = 1; #endif -#ifdef ENABLE_NG - } else if (!strcasecmp(argv[c], "--nographic") || !strcasecmp(argv[c], "-E")) { - /* Currently does nothing, but if/when we implement a built-in manager, - it's going to force the manager not to run, allowing the old usage - without parameter. */ - ng = 1; -#endif +//#ifdef ENABLE_NG + } else if (!strcasecmp(argv[c], "--vmmpath") || + !strcasecmp(argv[c], "-E")) { + /* Using this variable for vm manager path + Temporary solution!*/ + if ((c+1) == argc) goto usage; + strcpy(vmm_path, argv[++c]); + //#endif } else if (!strcasecmp(argv[c], "--fullscreen") || !strcasecmp(argv[c], "-F")) { start_in_fullscreen = 1; } else if (!strcasecmp(argv[c], "--logfile") || !strcasecmp(argv[c], "-L")) { @@ -1025,6 +1028,10 @@ usage: } pclog("# Configuration file: %s\n#\n\n", cfg_path); + if (strlen(vmm_path) != 0) { + vmm_enabled = 1; + pclog("# VM Manager enabled. Path: %s\n", vmm_path); + } /* * We are about to read the configuration file, which MAY * put data into global variables (the hard- and floppy diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 76f311d17..488585ce2 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -176,6 +176,8 @@ extern char usr_path[1024]; /* path (dir) of user data */ extern char cfg_path[1024]; /* full path of config file */ extern int open_dir_usr_path; /* default file open dialog directory of usr_path */ extern char uuid[MAX_UUID_LEN]; /* UUID or machine identifier */ +extern char vmm_path[1024]; /* VM Manager path to scan (temporary) */ +extern int vmm_enabled; #ifndef USE_NEW_DYNAREC extern FILE *stdlog; /* file to log output to */ #endif diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index df13d42e2..dc430d68c 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -189,6 +189,44 @@ add_library(ui STATIC qt_mediahistorymanager.cpp qt_mediahistorymanager.hpp + qt_updatecheck.cpp + qt_updatecheck.hpp + qt_updatecheckdialog.cpp + qt_updatecheckdialog.hpp + qt_updatedetails.cpp + qt_updatedetails.hpp + qt_downloader.cpp + qt_downloader.hpp + + qt_vmmanager_clientsocket.cpp + qt_vmmanager_clientsocket.hpp + qt_vmmanager_serversocket.cpp + qt_vmmanager_serversocket.hpp + qt_vmmanager_protocol.cpp + qt_vmmanager_protocol.hpp + qt_vmmanager_details.hpp + qt_vmmanager_details.cpp + qt_vmmanager_details.ui + qt_vmmanager_addmachine.cpp + qt_vmmanager_addmachine.hpp + qt_vmmanager_detailsection.cpp + qt_vmmanager_detailsection.hpp + qt_vmmanager_listviewdelegate.hpp + qt_vmmanager_listviewdelegate.cpp + qt_vmmanager_preferences.cpp + qt_vmmanager_preferences.hpp + qt_vmmanager_main.hpp + qt_vmmanager_main.cpp + qt_vmmanager_main.ui + qt_vmmanager_model.cpp + qt_vmmanager_model.hpp + qt_vmmanager_system.cpp + qt_vmmanager_system.hpp + qt_vmmanager_config.cpp + qt_vmmanager_config.hpp + qt_vmmanager_mainwindow.cpp + qt_vmmanager_mainwindow.hpp + ../qt_resources.qrc ./qdarkstyle/dark/darkstyle.qrc diff --git a/src/qt/assets/86box-wizard.png b/src/qt/assets/86box-wizard.png new file mode 100644 index 0000000000000000000000000000000000000000..19ecda8c7d42c1aa6824aa28b43eb58535035ac6 GIT binary patch literal 8314 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/cpq_deskpro.png b/src/qt/assets/systemicons/cpq_deskpro.png new file mode 100644 index 0000000000000000000000000000000000000000..1bbca68a3f105d3aaa534e5b32305be166200a74 GIT binary patch literal 244984 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%0AMzs z3!SRRJomV_&tEx|+c(&C4)f(9n%NA_#~fQdn;)UK7Wb<*&#sgHr)^u@-`^vKh*@1vbOwrZ zAJPfmIR~D|Omsha_V4|K;ZUwO6Y+7W2_gk()-|W75r6IVHgHTDKQKKs;a_r zxx`?5ESF2tI@~gBT+VV+ql_*=!)Cz}eF$I6OK+j1hg;!&DXGFyQ?BoU{&u zrHEi3M!kxQoTxc=97bwm398~Ql_4?lVlhXuMWpn}^gfVlr+%g#!@t$xnzZaGCm9#pEU(qjVo`1}S_dGM+ZMxdv--eSJ+grvRQm ze-5n_f{;+jv%gp2OCj#H^4*6 zYDBgQGdW#pN!CTL10o!81hnCWhCR3;psp#(*V-OKQ=@Jgv~7#N?$*avHB4nFHLx~tZa~-d=(hLRS_|uYIP3W7kiuU}KqAfb1w^C; zT5*@d$gvQFpl(E7z@>svCTm5s8c+63Rp$XcZbDnNy0vTfRiT; z0wg+XVI4hZO2->ux%G^!+2J4^$>SYKnIGfWkP4;XIr{^n>|*}_F@-RV$mji&eC|H+ zHSV2b>*Ta(PVfy zPDxF~PwKviqVOFpeM0FR4=sGiT#Ud}Kj$4HDlYnH%^8Lci^T$-1&E0RnDiT|0LWPv zW6EIk-bZ8V$Jzg50RYSw^VN$NFYdnl^2UgsO=?CgwhC{Fw<1Wkg}IGJ?ieVAAeNvW$K5;vTqXMqvRNp`#f?!pUH z1iWQe8eeJ)WuE*?j z7Q9J*A0gZaPyFR(p6r+T^A<6G-jm`$h!4Vaa@$*u?eEc9QrbwTkBxbxWKE?{apK52RbsYD}RLOsx!I zfXi+8k%pJ*oy5;iLNRLH*O0o(&W#l53n5@ClUe)awH{*XPPxK{7qY;1wBm`e04O^E z{59Ttw7U*{M<@QenXx5R;MMEbc>VSrzWeSq-oL-V&D||_TcYSmr6AQDPo6F*SHp3) zz$x_3!8wm^Z~z>vPdW}7XT;!GBO;(Uj#?Q7%iR5eX?H;&-@k!{xXH)APiNfUsQ;;? zy)u}rIPOwpHVcINzRw+&oLo91i)&R?c>DG(pRNPynhNW#8_@S1*6S?}4-ffX9$8xt?|TBE35B5_a*jq>jHhv?bB@Ej9E6ZqXoKU^6F4_ux7m=$ zSb(FGX)JnhaKP!Ggg(wAHtrzQb@d>p0f;fih>Ei~9v|QH0-$Q@|LfoWFaPFW7-P0V z2%p<(A;U2rY!ZFnKbQ|^;Z7#%#mU7d6nVe!m>7kPo8BWSxR|KBB*kqePH=4+woHHIOm_#mF%_u!D7Dj_i`c%+-FHhh};t( zRX*?T7>iB8ZV}DO_okxvW7fV@muV}t6I8{jw}@Jl)S_N+N5i_r9U zj@#M8U@FE<393123?jFDR#TWSHuYZM?-+YVJrbUz*N)R7|tZ-z{ zb4~y*vL*)T+Ya5(1Cqq6+89Jfot>sypzFIlgHBK<5~Eol5FImZcxmIEc!&kJt{FO1 zKFUqK#4MLxj*?|i{(1R6krRn>HMCObyB@Cb7f@b#D*VpJeI#nyBu-$HP zetwSauEURh_(RO+b4GdJk=56GynOYFteCYy*LB=&G#Fai?3c?Wr*1mT7YlgjG6<+V zNTp)npnKvz_H(k1jDI|xpyyMu)iU{z5 zPNG$%$&Bx)=(;BP!Lu2lq(?OXh)>Y-sXUgG;Sc#mBrGH zMMO&Os_UA(_Iz01K&T1uC68GIPrwrz_CvunB8@~<=Auib#>iSFi@AQXfN@J* zBuXRl=TeHJ_LI;i?|1U^^Y^3Hq=56J%Lo}+Dl-#ce7+$UWMp$A`=K!!O;w?uHE8OJ z?2LjsRo3=c-QHoh+cJyZW(BxX$r2i2q@WZ==OI*5)iZ{e#iZU7lV1t}ux3JO-r%Ky zGNj6v5QtJRxJPq%k;x;h)VWAwkA28g3EiR4D#x9dm^)eNzDuZG=RJA9Jw-4(>xlso zBL?fRTCee+|I1JD+u!~cU;X26Az%pOY#Ml>*&<7cb5a4$1q_3w_~?Fs9V|4vER@o) zo@})O%fb7ZO4ibNk?71-&QmWCC_Ez(|o*^^hdgOhit{AzYA>y!tHY%Shs6 z-_vye*L6*6OR+9hN~0TkNMka^FS0n(7~)&ZYRaNWIVEW=SuU4QN@2ZTW3$=d=;#RZ z`5Xra2e`Sp$KBmME-o%8hPdzfI;8?O2`IJJfCB8`DC8*PlBxJ{)-vRW3d5>0ST2@0 zK0ZdXm}gw}`hJD;^K;yFW9VDV7qi@{OY6d5dk97M&tkDa zC|C(01ehw35+C({j|BifPESwQ%jL3Luh-r=$KtM}u1>09p64SXO60kckOEOeSZ{On zDV2m^YMYOq788uKwvpZ@5J3SMS65enpb(wY(=&u1p^Ra{RZ_N=C)E)QLoF}GA}ld_ z<#{)WATMoF`2%SKIS#hcX)SkftTOD z#CP9)ht+NiI00QZI68R&1OXQU0*EN+9CZ)u;CQY~o27FO^LhbOX?SZPqrlJ)SZ`N= zP&hd~1-QLWs`!fU14}vy9`h-w;7L`;!9fv%LvE~NxKZg^h-CjuoB2LVf4>`$I!NW8 z2NuKzA8>ql1XUSyeTQxsuvjipH#M|WXxkRUFyQd;Fn1_ZL49_1hQq@{c<*t0d&?x# zf!rU3n2?GG7Ntswq3_WRWc}63WZnSyeon9J;OGd42S+$LIYnL780-Kg1vZ;4&d=Xr zyV+u}JzaC`cp03{V?m)6bR;m5HX2o>Nv{$KVNSN_QB2u14V-t`Z6h=D0y&QR@$pyy z;MuchH^;}vcNZ5ILkJ;A1(kf#UsvL8oW7w zi{Jk4D}4L)x46E&!}Zl2tflvPuolh-7`>!GAR*vAxS)uL-co1|1nC8Qgi=*@9e~r~ ztaUUV3K9R)-~0{!{lEV|vF$qa!+=@{a_|It|EU9|c$^dn*Q_K$6s)U|d0a&&P?Od8 zvM88j5&u1AfcUJr8HNGY+Q}#-5&6j8>2P{{g4t}A|83uO&{c)w<0EXgTMS)~&1M7V zC<#<+&C2{CuR$+gzMNd^ZA-KD^tq=Kzmf`rBNs;9)Y;7tWXxh+fCRp0r)M}mK1Nkl zSg*GnxOIo^cAMMxCGjxCh~>7{7SLKvHz+aAi1z_BK16QyCYoH#r@b`)8aKA|x_B;@ zTA1a@H^jVGW(ci%SUH#P$G9<4TiyqUC_<*TmG6r-hQn9V^OW2z8MO#G%2?7IGl5aS zV-A*$Q3P#j?AaFrq_6P#wd6!qLj%amKY^O1dO4~i+AtdDk$IlNEBpwjK)udTyn{sPz3$)#}_HmJ-Ze9sjO8#h0#ua-{I!HBZ&>U<+Fk z;>28NfMDuxJDsR6?x-n)FFh(F|(rLo^&$j1<#Ul29cfKy`ovU9Ii@`_be@VYU3l?1>wp5VQevCR9&6eVH4I1QCc0k*tFmv8+DpKRo}RY_I~`1aLH zbe)B+8nQIb4&c1Uz_+LENo8*>i2=QD5d{fFAvM4@GASiYtx|GC4pP#Zick`!4wyGH zf(3ct2S0d@+xuJm@P|Lf<<%7lWralafc2E85xE;jDV2Z{l)RU^B#uLU6jXMV_+)2H z=;eqBC!pMDQ&CX1{z>pT&w)(q^%}MxaCmTtS<|5Fd)%+?i9E;(|G`?ke)9$~P@X{w z^GPS~B&M6s=Q-K1X&NpFMqLU8fsq!0vKKTCmIpXEIE1My8rum8?;LJ#Z}H7H-=gpP zA}b}09Y(+!-8TWAPAXaGn?#jT()Jw?vxY}&g{rEvxHW5U!q^$1oB-Bc`@AtuGi*p41s?^M|*CVf)H=d{EaAK309<8Fme zW08VsVFfW38i~nIHB|T@z^7c8XrL&`&!6-GanxgkK;4Z(w>v&|~OZ8X0i(Z0cz!R?8zg660~7CPoh#6_g;(gN%S=RzpgLkWx?P@lq?) zRSluoVyK7@knD8ERCyzyg}Tg}Na}pcotuzx#32MYJCG2LJ01~Kka_P3FU^T|!(cJ= z7Cr_v%^XHo=)J@F`8i&{d4sE~8@xNe#OqgYv0ksyTgL%Fl*`~kM2HGPDuh7oZSU!n z+I1Ar(+xcUiREGmAq^Q}mB!4}+%k7#u0o77Hc<-E2ZZR+)HB-HATVzhsA?h;o<02t zE=1hjuTnWpQj$Q$*sP|E1Zgxh1nNp*=sLVVe~XRhA}5W|#At^U1ywS|=Z*wQDo&Qm z1-z$CJEicY;=ozT*)U22O%3lHw%cvS2}>!^S%>SZD+ndwt;@p8G-fO9y2EW7ep(VuEUy zv4Mq!Y)+!{!uk1)&xy8_uTew@PmnSUESF?Lu={|Oo-eb~1T~Cg1qPQ`sOy*^%1*HO zV^i5c3K_$OH3fSLAeBr=*c@mq-#YLvE_Knq{+jI!dY!uM6fX?KgK+7L{v5p$WR;)r z_$!inq>1U z>p;}#5EQTNYL{rFmcVUbvMNWhy-)LbU@evY#qKOeb2`9+e|Vhk?zJp<$Eh>u5!=?= z%A^V3n!Qg(D6@94O8vdiUgTl*%+lU{1Ydw+NdP;YGDe6M);mA+k-%x|cQS6j<{xe( zq+|hH-?#|SZd=74_?d688{RP;O4C+$$d{ytlO%W5{e3QCkPoFh)l%#3|0!&U`B!R3 zcK<@1Ek@JFiuZ>>n`@DVisPo*QY<3jah4s%5tSHUVFP>vv?a>A7l)?4T<{kIZBeMa zb8uLwJ*h7m+8DCg=4~*ucf1!|pG1jIhG~L%tkbtZ#U-N}_V5^=vrN1^g^w;nCQN}rglQ9Vmv#?KIn*l|{>hd}uhdR+x2 zDnz&bqe#CljcJvrOvPhJZ+&w}k$1O@jyP$`^xO4z=qP%N)x^h%@L&f2Mb@c6~1b&%nH9a*It+2>J z<%%RZ7^xD^qD)%oyHV`0FSmr2trf#=r$op4-o=y9lLP7{B1NPiLXo(#II;>5HZ495 z<%u#gi<5GV^z(5n152!w7bL?FEy1lddE+xF6}*Fii3j_kszhCt{SOJWZy`F3>Y_}A z{zdOY(E8o1gjVWb*(@9wcP$B~zs8P$%d@UF{?w;cimcpqVlA58+0;gqt}K@lZyE5pSFvz*%#N0s)>SWBy-MSA_bv1Um? z#fB!Htt>d~Vzne%g|Z)xBW6lsupxzj7h27lKQ57-{Uj2#)R<0*py9}f0Li3bGBOD75ATP+#jJU}7k=dATkQ>kLJ zf1G?wrIvT}N12PdN_OU>6qii1Pk<)*$_Rzet*UMiq@f(;{AY7?`pa16BL-zzs?;1) z;z$4Z-}PxVW3VW>&qy!6Fg4pp++WrLW)?jIUkv@Dfc2@(kI+g+ zW(<`=r7#doHKZRw9pZr@uZ1Ms?{XoDM8^6s5raM2kB}c0+E#c2+mg|W;lD46$6$H~wV|xgjGoDY@E*mJxao^rVKa2e z8UCLOfci-7B}5nIgoDq>fSp!YOd&mSMu;Dwz!f|H`48HvyAY5jX3!%X(UQKM!Fa?X z%YgmjiA8ZPpBXR6x5Xb-szB0^YG;Tr(-I2#7xa-9=b5sL=b%}AbuU8(1O{3N{g_yb z*08%7)VO}c1LzeCZXdV*CeZ!;#}V>66&00BXf*L?tYC`OlwKt35i7Bn%(VgeyNkE* z%nD1I-^^b-pXq+b-rxE*MD)f&trZmr`yiB3C*W936`&#yx>yyU5~NuMyX?^>O8rzq z*d83LI@+f8A)OBOlfCgBgGYRHbmx~cQvgpFaB7HM(Z*G8sfcK>lhPpHmEbVQC-Jbs zG>A$v>Z-vtS44b8h&4oj3ntg@QicysEL01ZkB3V*hT&Kb3r`j;1+FxF-XEql z{T8T;WgaAl-XD;-l+OEnIPcC?tkMK`Sg;dw?Zh76*gjFsryzBcH4N%?Xj`N#)k?f( z{KPp?TX<`vB7w0_fh8sseHEFBUkoz(!W6}+f-+=~FuE0oZ^jx#Su9=9=x>*b&wSjv zhSyFz?;JdzMCV>l_b=0&v4{^zp@~B;39d$K zpZe&)-&hu``BIh~OGb+Ue@zd?@QFYZMm(+-wG>VeN%tU4W(N8*AHBnof@e1dLo}~@ zS8l7|I({zTaoI9x(m>Gx-VT}aZvKkMqy6U_F|ezxJu7SuT|&8egiilO<%>(z{-fNj zcU-jB)Gr{x81&Z_eQSVE;QEbDTU+irMsRy;c?C^kdUk_s2^|TXi~%Ru4b2Nb-%E#% zMbIU8hE3&iJUw$?p%_NMX0QY7qjg{#b!z|^**I%_ZlM^7taF^2AKut{}lq^2(pUKhr z9t9q+C%?aMC`hz{*eNehrzqmF-H$^i9ME^M_EQc0tUP|#(3d`BruFoU?u;h6Q&;Cm9uGFaM>7yJ%9Ea)B6Y%3!Qp_^Qm9~Yc(vmhA!*c8I#`g$q5^7VVl}EeCp9lQi zg5RB#=J`YsKwpcpcrw2rG+D%#6%F=b!RU(^wRR6VbcEc)R>}9T8po=bW2K^Di^njt z$3PV~QRLAiQAp)BqN;N>nlupTeCKjoJmBtG3Wv={TC8rF04@H>3C~7i_G>7j7PO7k z94&hk)J4VOX7%ahWIV@p{T6m|! z2cVOKBl2+QHIU#}vi~+bH##Ak-@*%N&XU_~BUWN_}nA3cN>BM&vjU|#Ui~dw6 znnWuqi$DTh;yA{GKaoMx(b0KcU%LWOO!4}8y@6wWyP;{9PSIJrZ-I_&(Rc4?e#{aj zkl}LkZ*uZut6}Fo+&p2jkIl7Mkcin&B`{Cjd2r@o$6&FcK#m2x95#H_+*G1Wl&om} z(*w;!ED(aiJ+=Vc9P|0{)j<;ci#Aj$rdNQQ+ikmb_Vc;-4TtsSUPzojr7zPktbD_# za2`j=rEKGkSS{?F4)Tj6ewfE2c>do$TR+8}0DfTquMD)7hhr*wQ`sFYyDIYR9+5~k zW&c&}E!YMu)c9$U6KI!Z@wvoJ=QAaFWcs}-8EA^IF-38Cc>(ZqscW$@p@yIzy7>z7 zqPWJAX!Hl=gSOrp(XnY74{L2ft5oSlDS$0#JL-M z^^|q0at0L1F(N$Zu*pyq-4!JA0!2{IIqo5@_g|z^)65IFABJ2XYk*aXiz|o_mZMb>LFd~;i^Uxzs&CR~4dBd+ppIoRj^FZ5uQhqH4Fw7(yWH-A zU<9R_4Pbu)hsKSocY~560^|vDBB3}56T9}3xrx*U*JwvH$EpbSBskwskj%V^GHEYL zPX<92xX~#nSSI{BPU^<=cB#gHtYpQedEn%mUB4M+i0|O@Gt{L}25><1p-Yh#`Q1pX ziR<;YP3wj1md%+yR~a`$nW06(%tSL4AM1pP*wBO(UWYE|!#U06B%`R$m(jFPHj+7l zk~AhuisQ89P5#<`{r!%gWfVReJr1GHFxDUw_H@Ye8J-BI_9l;V792l)CR+vi7&IZ zX=X7W{E~}Mp4NYT&0*05Z!t;oY6LB-EnrlSpEF4W$eGClUa)hCodSBqBeB1({|=T# zLMDek^A=r56gE>g{%SocZF&A5D-L+EqpjF4V<7?edy-VZX29p|MS7#o>`Sx<8EZS* zs2q!ttImcYOM-duWRrNP=5H!%RDk&Cr zk95UV7ES#xXZrBbzpzE}??Xs4(WKq5Zh~gDDqd`-LQ@jU>Ivid0Y`sR#*$t#U`GnVPxa@QKeL zv$VXxK?!JouKN|MiVk+F?aZENz@}_Yw_=2a;5E-?E~4Y3{&i-vbmd)!kn_8(qyOkY zZ?B~?6bcZ+6Ai^Km2e5gZ|0LJC<_<8f=!jJ)B25HD=RKUgKYnut7NG}ArVG*CQ77o zDUEu%c#a?SG4;T00M1H2eHgUkb(pPA41gB__dqw+j3kX-I{JI-$-a@RW$!bWn^H zymE;pYF@SRm2+4$WY9L?-$}VP8Off1%W$ndzz_qRh+@d!uBNXcnZIN$s} zzq}3qyv$;IKNoiNw;_+6XAL=03;A4MJMw#oZ+e<*O1S{$j{ctllqt5Am<#zsx4999 zx&ibcB5GLj+ZP-BD`*x;h6gWIxFIBLjbf9~stI1mRJAv9(l8NUc_8;!M;}>`)u$i+ zaoiQQPnY{4@D{(|v0#3zqdz&sWn3CG6^>z-DkbC6dt=Hn3ak5jn(^!H358KKiVI>R ze=Ql3tsHHVf-n8fJWk~<%y1V*%~g$)-F6vlACOGoc-JdU$cN1~$)#XthqMrPwR8k0 z#Q>j6l|)>5N9t%M6y8^CueTJ-JUek@wNBRaxaaY3De}zcfBncd+ah#o5#Mf8VUB?e zu|VSJ)j=#pYhE~RCtK1%3z3RkXf&)@0x+`GbZ;j&xaso6kgDK2XlLRZg!~lFwhD-n zJu^w)6LkO697Dbf!?D$d&UYCx6jRENQPLO~9kC&e_Q`6boKirC>)! z5t!u-QG@o?g;lVqu_81QE5X6->dZ~5Z=OzpWGjl&9X*UM zGt@t_NxSPqz_hGYeVki0Sq7#@Xyxi{0r^dW!Pr_aIrX&6I|$9b>Z= zQIK9znkZMukDpH{bz6X8OJpIRJmBK?zO9g9kXPJS)LON*`mR)&e;itU*IDDin)2{BmXOFtsd#?FKMJ!y7 z-jYfgw33BoNk`mSD*T@seM7zU^o&~?_(yV+Cmy;tFTyQX?ms?RgTcJ`JodM8o%r*6 zbWr5dQ{IteSI}Flf4-0KUrZ+~WO#W62i006w*|C`vEji%h?l$7GH~p?5yo9(EPt*gt7b4IhX25D zg|~HdNFf0~T@X~?mU}2*O;vgE=%g6T_=iPZBjJMmhX*X+!N-v= z9Qqin6Ef{w!a=G@1Vst}^v%dL`#F)pRjc%VS>ow@!KVG_FvW-*Tq3!Cakbf6 zM*+JD8YwR~Jrly>W7WGMYbF~Z=8U?dl3tktp(_NY9-Jel%*+1>_;;Ma7=S=ABwFb~ zndkl2noT|3uaUmNgA98ne66Bs6)k2Jrb#EHz1GSU1LOQ#$ej%=xnS;@+@%PbXd$x? z4O~gIYA}<(+$PqgIxjj4%12X7snc+axRBKOgN}tqc6W3Q>>I&2=~PX)6$T!kBovse z{Ss3&r+8S1=e|dfwGZ>&2j}b@(I4HtEdDl-3&7nEbO>-=f^GN!sa0PN&k?{92BZ>> zSLYseSEs)fHa52;&WM(DbNybXojl#f|M7(N!An*`3wzPA`cK=NGT@0*f6Uoib+z$A zM7Y$xq>p9rypYW+Jo~oN;)hYkkv;#nH%LSNq7-Sa*rCR}pTa&kLMGy2w;&*z{ACC6 z;dWl-I)s4D$YKQ#&{~03OTm4vrVI0*$a_w%u2%KLhZ}Pyw*cf5>>>E7-4lJFUB#e%oVX z7XWbAT@El{ksI(frZQa5Rtd@<@L;uN3C8q|b5WxhZDd-B&-lyLxU(8AjzRNxWe~AI z0M-;+H8k1$&nNf#)O4#VB0%Nsll?p*>rKIe_Y~NfPEW%LTWU?@lHpk(fZUb?qKvKF zLCh)o3>LslwtAk0yV8adwDVXueEoaV@#wpC{%xHiR1x~r1qZ9?-CbvvSi6#u?)^f7 zyQ%Q!T+tbz!-6UMSiiLo5QV7VRb}C%Cxxv(Wk`uVy&|HJ zl!yYRTp-Jg53~W-Z>jB3YOe(rFO}@j!FQ441E4sIhF+Jp143Gcj5vN4WK`HSNh?27XUWa#G1uxbMi=y_wW}!;-Ka4iTFU zh>}qd2$i7MUpU~j6&UWkzd62R1MU<8fU+rE)*s7h3(^GWRCxJbk-qX6HFd#f5mO?N z??56*Nqi~v9UO&H7hcws4%z9Y>We_IPqj1zK~ULc;GqsEMhFP$pnlyRoMvp^Hqm1d zAawIjiu$&h8)0|?kOX0*1NIA~`~Oi7fNU(&mtz@`!IW~#%uh|s6$&g@tJTBR4u7Nm zK4J>@zdt#?qrY86II^zzwD7An-6LGGb?4*#LnkV&8gJsBf> zI|_KMyIKx-U4H1Jo8~B(29^v)EX^N}5fLLI`5@7)9i)fu13A129dns1iYk}M5?-VJ zGQpqKXQ^V;D@URC-lw;6hP2baT6({eO}Ul-|DQDZ`NOEt}CvW zX!P?ugF6=gb&p36lN*jO{dMLFf{t`9#?IVko(aR8b(-F;*SL;FQ#DjMs-ElOwogPApfQQ-`3Gaj+$l<6Km3_nI;;~g^=ZC%ktCvW$XD!2zOCVzD<`syBjvI zqYSCKI!C&>4zsTbcmtVrKez9g_Rx;^dtwO#9^+Jmde{Y>tG^x4DHgUhr1Mwl+K$LF z_(H?9(?jL^**Q8E)KteFsuYk_{hkzP{O|>VYkNjNj0wHuJ&X<4tk!%4Ipk z^|TP_@WV=Gj9C{~5(tCgpkf&!rSi0F!Y$CZn<9~$n`^|KlYC4!omB4DNM|HV+?0zV zNBy;cKvWGWJycfkAZ*@x#0DmUT8D@LG82xL(`hQoh{G;-;z${NPhB!yR}N#vP{k+N zIUK3AIJe4QPjJQs2M1OR8QIiv9HQcK_{uZ0=DnL7rbzu+`b>3g@7zPU*Q4i|Xv_Bo zokY+Jpl{l*Nt(m-(ewgw2T!ly>~JLiScL;GOd#Rprh9uQNLoiz37$dyKnmrei4tVV z!JWlX_&IJ`4T<}0-%N&mb?;9BAqH$z6__bA@nTMM zwhQiY?X~!XBoj<~G_Vn|mqjh;%@!Q5%C@lJ8MzTig{3KaUvy^NjmyQ+viQ}v!QJy% zaikT{rsDnJzbWPK$k3{bpWMA;hds?B9`aFqnp(qXwsymd)I;a`5_YP^>6{u4G+(MvYA!oL=t(n5no?X(as*ZDg4F z{@wIjrzo#eACOrm_A|H@w$$1Xll5d9{;KCqOkE*-QissmZFS$ErpkzvJgO@;~@SpvFtev)9$qsWg=n5usYf zeesz06t8T@|rkBjpe1E?FGjF zxix^8t^3wmGYy7-fkKXW+IF^`k0 zJ&1$oBX+agD%=DraUOx-$IG|+iR2q71blpJ#@*0R8(i8H1~&~ch7h(lVv&%7r$66+ zI`6~lw>5^`wR}R0kZ{p=Dx6hPT&O-pkW22@?e&)K=0H%F1u6B+!wvrQU*eaJ*>cz6XBJwF6d9P+-!h5R#imTq%P@(4scoPxh&`HmsLa zRR}>s42;nU$1&#nTuX<~Rcy%Fw` z2NpMU{G({G5{sI!u)gbS>=l`XZ@w3gDn;9u13JMU_*BPr9{9u`9xELuTnln7W8=!b z2~3Q!Dqef)npiwxf(RzWH1|?|Wi-=d79N zw(qu{w$2aUrA7u=r(=lQnasEErMw&VdJT1e~f%!O2bN@gB-dZGov#U~_O z?@q4&^tcx$6Z8$GQ^B}882gZ$uUv%w2;uqRQ4v;$2PJp&SpU$7RV#@v%|PRcC|>$f zM)z{#T-$|UA4;coKX~?0NNKva&-0lHFDa;H6kZCJ_{{4z{%SOA`g?|4a3gcW=Yxm- zo~OE<(hS4?t&2~wBc|2yBih?5fgA|;m)j!+?~et$KrHD)N5H*E|G3pbrPJNq>->4u zY^U}~`fa8;q5tnM{_p|+ECYg4QZ!1eF>I~7nZqI}8(A4RW375Of_XEd#bIk$<|K

    *-18d`3za-H+r{%|H*T$_=`!46~** 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

    d;hXdM5vb^b(pa) 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/cpq_port_II.png b/src/qt/assets/systemicons/cpq_port_II.png new file mode 100644 index 0000000000000000000000000000000000000000..3254d9b5e114157e664cc7e3c424e4a935aab8de GIT binary patch literal 161871 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 z zyUQ{qyp5edM0x24=brPFC`-nIlD>=pG}wjPf>Y1oqa&Pv^?eegRc=~!1xZC3PU(EM zJ;-@Ge%$P-z4%n$_;DdiG~jE}sSs>RgYV<#uoldk9dARTD3*(s`@E}F(Uw&V@+@4P z+{lX4)p~Ndxpgg_#EZjVu?}bc{14wJpGz5^KT9Sa`1v1IM6;Tv0CkKu=axZ- z*yHNvF(`+hz-`83d8>m z&2e6jbH3Z%Ve(@getTpMbj>Th35Bz3df>n+S++tUIfT-i*6-hiU-)^(k%^d6Wn9*L;GR0f!-JI)z=qMDr|rZjXgY9{l=+Y&AqCkm{m2E(M%|p zFLzpLF`ZF;+ySkzr)Bu7z#sI6z#r|lzC|98T9Lw8;NK8X2Rh?2Tf1VfFzLRBOGn9z zn4}J}AI0k8YdUhOLW1LFptmB4yO~)FujGwFE>5vaaQ7FkeqH6w+q~D-=76@H5gw*; z&0c-xB%3;Ld-38nrX;%L*AWa+!g?tsAu({pGnTd)#Mn0&NL-(oWXm1mRwQOxUO_ z{g%y^W?}Sx-Afq4%kAfsLXNhh7~V8^PQ6}JI9-u$X$gnvgn_SsCjtDJStjd)1U#@Z zP7*Iz%I1{O(9!Y(wF>usnXQ7R#rpy)LX5fpuIGMNzsXnc5*gS&`I9&DX6Mfr8ErC) zqf}0#qMTUP*uxumysw0(m$3|{i@pD@4{XDBf)M1FO+2A9hy`?J;2$Kzb9 zo4>o#w{Io1!CQONT1TrL5v7b0PKwPqF#!>(E|#Kc<`Ptv+})WE#v-7*gxfc4J3DG& z6KwuxLn`m2{nvlBz|U=_XU4q(lvlxqg@tw3KYKrd0rG_DvM-&jRMgxVp+KlmyMhn5 zAThBCWXD^Zo4~-sM6*SgVLL-YT>1C8mc;Ak+|>b>UCh$?Xpuz9YedC>F)8DB<#z{H zT{sW66ASIAn4T)Tx2Nlo+rr=GIx_sc(i>|=pov*>94G%xsSuz3^4C~vUAD=^?(z(q zhiOnIjd6u;Bar6fa$H`P7M5f)y|pyqlYwIB2)0}| zaPGT@KEWHF*1$CQQSvFAI71(m*uY=o;tb-O1&l&o^nA1>m3MIbu(G~xED(M|ovw=X>K5TJ8FbP+=7H ztFv3!;B;=dX0$c=9#u><*6-)*Cc0Il6qxrRN!POeN0c#!V8!SBzS-$aBX3JWg}jRS z3NATx{bWl@Z9Sr>(HZia&e*&jvP*GmUW&%1rosDFJ=Kqp5)|$gkA@MaIp>!+b!cA- z4mezAjnZGMf1;J}eV

    @C>n`VPUzn0RMpP!#u42Do*DJV8iE~Ix1+;EW`W~pYz zVR#tv9TKc;t(y7ysT6zes47lCkOQpelxoZZ8T9+*SK%eB zr?Pshk`)=339<_2{3MQ6BZ9KSrC2cKEVqT9(n$5qqE>@kyp#Hg)Nf176(b^9&&_{*9r`t3h1Gy_~?W7knIBu@8TrrJ+|4#S-M?StCavHp|@lK`S!g+ z1mO|=$;so$J;qfT<0N^RvehU?OMEXYYYi3A_3LP9%I%}>O8coj8`Q8Ih&n=gdV>VBl)8ft4d_4Q4E6>->s?C$Q8rOsY$G@p`(4_e}yiWl%w zTpM_AVj%Wh$A_Z`zVVQ8It)lnYGFR2%B^345qD#&8!NBRZq|-hTU+A8uf8vI80IHeSmPeV3Ptx+);OQQFPExW>3n7IhQ%Ip{pZvAu7qgf%|@bet$| zr1_<~ZFMZ(gcI@qu>eY};q}S-a{_>e-2eG&AfI^(qu~@8XC{tqvjtyaO1Y{u$(Y0+ z)-PV>L-ru4#N~{T?-4FI*AImB0l>&&09AQax_Ol1PZu>(Sc=*E7-<}Wav*nC0DQld zo7Gh~=Oo)?PB&kl@A-LXvdETc?>qxGLoe&7np%#<&7_V7h;*dee)9rYnNom+J^i`%sDv4h`%3n-|zf4T384h z=GBSVrU$*KpI-;d`!cvQN3lSeku6Q)rS5imY?Af~d0N2d)eg z_`M(IOCcu=ml*2Qpcr|tnZ%2I;V<`$G&AH3qei<}FRyPIB(47nz3WY!HHWY5c3|aY z66v-+s#3Z<_LN01E+^(rmEBx*`zMqkLS)(7g&zHni$&PyrO{PVrf;cS9uOwXh+m3C zZ{MrzR%Mst+LgX?PHbYarBYvXAH95MF%N`_e=e`Krq0WdKIR?%;q+>O%k&{gI)3mjyymm45^o|&~MBn(e zZS*ev<4*MSR`TY!M>^rPpWFj4FaMzs>$lf-lo!w0xp4jj8&lBNz36WaXx41C|(an5zKge1gK~X4G`LSVtUd7W%T&S;D`-%lRM&2@_PATh1YYkMN^IR6Ccov zENeQPKmXm{W%xc{Jw$*m)Y0y9RBn*>fCK>Q!sZUQ1R28ADXVAwv+nPhR#zEcB)nE9 z9a9(^JXwjQHcDkYd1W{Z3$R*bOS|YiJs`kD-@g)FJW4NNo$@f%yHPjV^`iyQr-TH2 z21>{I3MXp2cloX^F7x_ag#`tn9!wkS-~$FaB(GRcPrRb}5U**|=g%<~V(oU&1S`k) z7crdh#CGHr+F!U^cbQ^VV<*Dyam%o<)@3{titrxFe(&hu@bzgBeWJMx1Odb?%5`&y z2qvU1nsbr@FY4s%>|+K73k%Cs#U~-5(OW~Vm|enh>YV-OsGTY(_3g0MfU~S8jtl-m zc+DyMxtkOWbZs4YaqyJ6d|X;^plzjDR8@V<5<$pOyIx)GZlwE%@68-Z4L--NT}@~+ zd(4ojCB2Up&sPln6W)mOgJP<*&mvcu_2k`Q_x8AP-4j-l!cHDef9tv5{+IGG3u6M= z&@IGZM*e9xP-iLOv~uQ~MkOctr{n4$X|!5)P6O__HqN;}j@A(L3%JtHNq%#Ze1K#6 z!XD>-KnkpXqss>mRca>x7PQpTB*XAABTnh9|29ibDzBci_t!Gv9PN*BQs=<5$aM@> zK==XCGx~nZdxT6pUABig?cVsWcGc@ob$AKEQS=)81GI5ze@IZTe zr@n!;q2&|z+}bLk!P^oU_;irwL>cLt-L-8RueW~DM=L66bH$gAFTRXqhvSpVQhksk z9Jy8?$v*k&{%-g7t!1M`asA5zXVb@K*26Jo%Jd;dYKT8^mcMVom?`h};bAnuXYKgV zs!mP}_`$dr<8Z@C@i687u-Ykd8olN?y^euA@}z|yIgDO^QEASmhV16QdI3)L2v z+X5=rXZ?>Gj%NeU4uUk<+U!5Kb4`i&&Z@oUd;%dB^nE)@{wGDHHa2coE&0k{P{Yxu()5M+9xb^`T-w zFE1L$aY;%f$4AhAZB{8vhEuK+3Mp2idIc#57~17kxtL|MrULJ8G2=&jPJR-Z+1#NA z621;lZU8H)CbWhaJ&(B+f5tq1-b)xxFm#rCJ=N4r&kJTCA&=8Gg+QebwolB8GHbk|F*zOrBF z4%AQ5sO1sRfS?aCLDsGh%3V@9a1EHK`6>R!F`;b2jsl_BpX*}{z-8%on(xa=o%?Rc zOyCPyK-1j35g#jPIk>ume#}X)8sFzY0i(o=q@me(9m`O{D?nVS^~Y=5=t!BtfP+!i z``N+}ynul0kD|ALezI`Rn}%@}l8qK|79N#}Zh9^=P3-ix`U?vs5i0)Z1bR&h$~Yr7 zE}2=_lpj^0L3(fz2t6d?`V{Pl_WBv~9fRYKtgP84)D04Rt!0tSHbkF5!`sYvD!Ezf z;Tm>rIdEIA8OI+^B%zZQvIYV&W)ATZ&-7WP*DT~2xHLby6Qh6%Uz8P9Jtqv^GW~@- zlROv*D!dmjwj-6H(6Yi^5CB%BOg<~(>)X94@D?^bqoXyO!QQO*^){*=z{gByb$TF#=nyMolnId)_~w<*@~R6Mwlgfp0fn20!WFUo z8SZphj)0LL^$irRn=8$&^>+uH*ulNH8nY&uTn0KWVNNyM%1U89AFHe1V9NoM(&HUl zfpLt=A659M5&&(N1`I>#t>Bh&Z!0nRS2Oarn>;Q7OD&o?1J)NwRK5?`xc{V{sBTm- zsbMT3$2o&q(I4HC8e#0hOMe{<^!FSZwUesZxRh#demgn)Lb;~*S9st?2!O4SJP&8O z{b=3Azxe%Ut>04d$NR;z^ceOao99&rNEzN*j8r%cCx;bFfX7;_gw337DDEcy%h4`n zt%Aq-IPEdgN+$%c-!VGd}G)1&GewVi_Bv!lTpq4TiePg zUei+_QMPRQ%PS-!=_Wp>P#|RM@CZA%F}v~jLqj7)-$KdbRxziFp;e&OBe{}cu(6Nb z`qO|vX;zWuLHEM(Wgq^O^C(hHzKZjYX$yhs>tvg@KR(qj8 zKWo?bBTqh&5h z_M>3V`g@*4_{kvfevp4ynf)-|G;FmT)kR_nkkSVOZ9z+ z!@lU>o$2=VfxQ1bLL>0h-UMMo_$=W*;|w)uoJ;KtQ}ClXhHSCNB6n&QZ{bCC5Yd}? zx6IUbmJ>Dg@MMlY-)FP#p98d>nha#pEp0Qv$1H1cDr{_5d1=FPfrt*IGiKT=m3(=+f%Vs9Y;&Z(Tq%Y= z{B9@s>u+;XSWL;v@fm{kXx`LnF~ByluhnyCMUFHIbpk_i$|7u)B_>%CU-G%?a?1gs zEqrTbJ4qm9dHF{L$O+Z6y!G2M30kqVXSK7VCd#ZGolRNYLLFJ?G-3K4rcEn7uV=Ty zS}JmF3vJB?_v_I{)SOb8EtgWl$DtBZ1>;|RN!My<%;~1Q6uU<2dv^|_4)4r&O&u8h z+!#g-L4vZ+|2tjN^i0~gD7PKAUSD62ANx?h?7RvwqtMD^vdy_9k-A9hy&VK$hXspI z#y6&>Tj(ug`qgQRg*3h>74v@NJM`niIb=qI5W?w3Z_60X^GW8k39kbRR}zJMi|OyV zi21q2@;^}GVb;CQ5__TX9)<8f&$ok0SXn@Q)y!#6;=kLrt(mD_+ZL#d?E+;-16nw6 z%R0})5Kpv55PXrt>&Y3p?~D{Pxu4KQk|uMM{{|!cf}Cr>&?m*$?VB`TN#z9+nj>lV zVrlA^V_%n@4zq8zYUed-j;(aXTFW0;cbDRRCz|lyQgl%opd)!ko1^+=k*aR{d)&+} zgEDinQ9H`-v@}d`r7%@fTif`luCX~Ujms_^z*dPO=xJ#^<_Sf#3YNY5Qz~u(=)jnd zYacKzd}Q>re|v5;D!AsPm$fx&54g--l}7W@5@K3ea7BN4;AM{Xy)z5HMw`qO4(~#- z)Vq@`u=YFGHxM)BZ?2*;C#e0;e9z4&p)Lj?*V@SL(akrgC%jK%dtSDKhHbwQDsh8G zawmx9c>XBlKwUA=-YfBG73XvgZIhYUW^$i=i1l$k1^#kPlBy7mNkEA~(_w3|fCu3- z{U&Jj6B+#Nd6)}=NbAqNWVcqhOJOdk-UT)Zwvg=Opy(hC!e~@ z7R6jhlU__*Oc*mSVg0v01*o~&P`MM$b1KZrq~Ps~)#4?YKpraq0#ho^W^gcMPQ4aS)`ZBxhNvEQ8P^L;9f0_i=t={|$x~L>rZg zTH4ND(a!V6rAo^-0qO&&7D7V87Z1S``oLp!zgIuLmQ?}kEVg&+T8Y$Yh3>YvT{bhS zYo!X%PpU4G&E+U~^KOJTDiSK6@PgxTNgL{bv^&*EaX0!GNxws)1LbX_- zILK!CKh)`O0c`nZf$7Uy5n8vOj19>(KHZPkGDCLH=9K^FpwSVB*ZICeGb2G+?BzX> ze;&dj5vxESP?#_t-cw!tE3*hghOl@pUE8*3_s8A4-wBI39oTW#^W9~d`0PBuLk?J% zj*e_6e|XJ!wXEU=4-d;Rrzt}s$!~naWg1IzK=?@RZ48+?%*mS{-P~fF<^Fj3K?`a~ zI*W5Jl^~-^xdHyV?Q}RdcLisfr5O7+PO^0E2t0q_M1?g3B-fpC-NJ6~Mxl?iz(mft zMf2JkLYV@)zt;AN_po~4ojjvWUGevQIY09H+>)n59Tfgd)wQbg$C_WgsE^<+63 zlP+Bw%8{QZo?1JeD;Ia}g5{^CDcsoR(f#KYv9Kv?);Q8SIp0!LkW=5!ong7q*Ru8@ zgpz@TB^mGih>uKE*27)YGzIgFrtWo}1E}{RuqliBXut3>W54;+Y0dtKB;3L9>=zxv zl@kX~t=N~{=4a!-1n&i{V7)`_+< zvC6ikr$oM_v*46I+eSW>yoe_VQ5Sy@@8ESt*6tb7cVz?cq>Im+?Vb?Uw@@yj{A?4lB) zdv}M~kB%ITa^;D6q4ESy#Hws`Gv`x)2ybz=SvpSE~lYXQL z@-R0KA9m!a2?!r0urMI+u3oJ@^z1e;S$5f!FKMy~X_XZO@38QXM_^fMQ~#1UZu&fB zOBHb-+GD&9^`9suzvDo8j~lDPUuyiaQ4P1bq)hYqY@m>dO8UqDREX|U2Q7ZxA|<`f zHW;F(DDvwC`vQ|nsxBCx6-QO8mXYCM@ii}4upIoBiH}$O(XG4Sf=iMByn8lKINNdUh&i4SudMv`>KN$ z?6gK6Ge#^(ZF;lUZyONPZJvT+M!&}5<=CouLDCu!u*&?R0^iIcQ0(W2^5lB>64eow zkmlP{OvkW+IR%CvpK_$bD)Ifn;i%oUhxlJSy+&#JADJr;K1B+{a7z9Kdd?OmP>Ip+ zAthN|pD-TT>WLy_mkl|Ngo+Aow|XP7ZIggK0018ZdGmFJb+&?$w`QN7^ueEFSv}>mH=@u7#g{Kyx>Ertt@}6Qv(Xs+ajD+``-~ZSd=_8;CGPLL^6pqWU6lU#DrTsZgOy zpy%lLI3G22u7k59Q52DnUN)naFRT3olVLNIGIiUO*EA@o(7FE}KXbDDrPZ;XB+4@x zrNydac1FO@26GJtBIusdo{(V29N*s0oZ1D}Hw}+#PjKJNN-2E2SHEG~gA(cbb!f|c zpEhF~-O*w{`@NUCht8gDn0TUXk!-N8NiR^1d;YuezY;^Yk!)gQAANT3@>v=lVH7C8Flaa$1!CbKl_qnpYk`}+?4i>6ywQ@_If?&9elJ;^t)Hym6Ekq~bR9D)F3_z^Ppr1%1Y&F@I zZo6NxHE<@327~#~T&tw*txtV60BSf0S%_5pKr69*dKIpL{2eqjCV3lHW(%M4o1}lS z>4R|k>ggx|^Xo9F0Tp^rA@%iN#nvwt;;!jsrtFDYnw6E&N%$)j9Q>!POfm8gXWHl; z|H}J1_6u`b(-KVhr!Gr^c;W2$0x1;`gerw;&O-=#N28=3%!YU^n!98Q4u0FJXfK5? zv^Ykno}#YKUq$a`H*@OWI|(x%71XpnZ;<^1BpyXqgjf*lN=h39JbcLR<_S3)_-HcO zd~#rzg#Qfei>Q04$fp?WlY(+@j0g$(9A0wvOxDZ4N{rzlKL`_IVodg*rTkxnx2)mu z?Am*J>{m4FSooTxS~&b$FRFdI_}m%9j)j{VTEO|W7c7$^)JpmGropjP!lrkqbDiUMXS=A929%l+rhs{ln>Q) z)!b1)6$>#IXA*PiMwg|^Ftu!D@}C{+c=s4Kh*FY#G=g#8CV?52+^scbjeFcpAN{7; zQua`hYqkV`>vqN3XJ+P>%!~rqBCu}UdxiFOE+D7E5#w~*)3iMHHY~W?>Fy7xe>E@_ z*z@VyxRPk}<_Lb)mB-(4vt3Q1IFFu8;mN5Lrf2v{1Q9&Q$|RUPz_xPdtM$)scU@zNT} zPyhZ@pgsV6aDLv%J$X5B%KZYkoe>=m!Z9wD4_(kl z@1T&Pdg|ETqFR;KSRy1-*Bs$d#<%-IH3~eey64~4dHCIU5`6Q|&m%yX4I*drApEz9 z33|zd0vvNS3@de*XE$3XEkr06pV1n*?=EXC8f#jf%3%IyE@wsfeP8fFY)GF*Hq2GVozj z@lw7vRA&3Xoi|o21!w>nys1QwDAEi+SEo@y756KO7wH-Dj_uYtFgchDIIzaqDe|R@0C?vT@j5kVA1OUFJ9eKXlFafUGG$ zol<~2VHIU_nN&b`r>W_k#US!q{&6LBVlo&$nh6^FaN9Fiw@R~_%jaAQ z)}3fZsK^*1xeG?cU6jULQsl4(Y3 zJ#5Bn^D3!XwH1%9JeznbMFz$@9ZM2RcXhSqE@AGM=lfGiBo?T_%-M}*e1mvPPV?Eq z0{zQ&{!(sd5>{@ zqjMk>fq^S&44)F85a~Y{0`!j^4#VYA4GJ0IWP796>S?Gm1A20AIMfhQ9{vXfFLLkTQE1y7BBo%nkY21lNybnIT zTIuGiF_p(UJc=}K2m604PW8L*YyI|9_KiAGZ{Jn*+!Xl)Oul#tJJhm{HEh6o31dSr zp>f)NV~sYJWA3P2Bw|Tr#8To-k-7OfEz^|;cNrMraW;la(CE?`_yC2-2o%^segbkU z)7aeym>xDPxmD**hL7KD--Lg#HH}ni3wY}AN`mi;Rl8tKjF`s{+Pa&6xtyH$K{a}h ztR?+b0~4aB{+#3QBs$pnQ5@hBfQ#WJ2n%hx3of*a^c8Qk8#c+D{evthEW#9LL+tmG ztYzu5t5tOn{?z@R93+~o(wdC!GZIc>UT(4f=K|Q^N&*-pdZqe!r_(6wfbS_F|8>Ck z#Ai@7aCnSewnn@(zpekBhB0=wvgea0jT;7yvmtvk2c?t6{wr8!O&lK|FOw3=9t|?j zw$t~CY#t(v2niK4L0Z53v7V8mBO-7+b8<+5gfKC0>hzR6L^PkmYZtwhn+M%zK@<_h z3*9nt&Cv&qXD?o2tfdDf3E?$~c;AosDooJ>W2c>2{lYw-TRW3Cbg2mT%sAYrSo)2OJjc-5=D zc(v)2`LzMp{-0f*hyM9D{^JGfxlRTD+}K_0V29Gpv|+cphY+;sz-i<@AJjho+8f;abh8HQC53%Xy*Lol49W9&(*KPkbQvthB#+;u6nz?i zGML!D2}hJt%w%3egpN=wZ<_zd=T32Xx*Xxd!`r`W@NL=Q8mv^xhHK$dToCa8` zE+;Eo2qB`(=Ihk(*Dv`W%19~5oSmH~{kTUi|APs>2JF&P+GGo$)n)*vj-g}x-~@*R~W}#%oWN6DvMI773Z$$({r_r z*NFy?#5_;=PIt}*0;hBn7YPmsv~LZ)L<1>c-93$w2J27QdJJDSmr*+Sx&`C0NFidYdSe4|0I;>gtL!bvfEpO*irNc%j=~ z1^2{K>!!`AC@7xl%*Z9;+5Gy&!}#&E!Pzv_0bPgnKPw~`AD=Oo2B2LbG_Em7*f#2W zeugQUNt|(#soN}T#$R&RPx%Fy%m0~dfXTGEItTHGrIi)4z!zfBhrro6IB=53Mf$$a z##{vE(`{+(;(CRQHuiqGrukY=^LqV%tL4uE zJ&&a!PB3t-R_VxODtQja+!1cq11{5<2zAI>apQJF_tYE5S1aV{ow6N)3AzbnnAV*tZ`f8j)vC|>HngScsHLY!>6Y zen~}I*&R3gD4g~iJgP}f03h=p5&kJ`}+mm?Y+IwE=GWN z0g$37hXIzIIH7{1NMI|tmr4zhb`*R1@q*$(1(d}zMbdt^gN_9)+B`*!v6Jyv!?RA)BCsES*2O=(pOt^RXizr zaBPp(T`OI%h!Z0}x;M@pOM4DCysLJ>q7Zz8kR@Y@TJCH8V1fgJ0u)dx&LOR;Iwl%2}cZh>6!c9&*1np*TT%VxGQ2B z@#VOrM9kxQPlkudUsGqu1}zkJFE9GO=xg-q;&u>k)?zzl_KKsD;vT;FKM@oJ2JM3rIIe@k=Ep0vClD;S9bG)#0$UC5FvD4mL zN73~8JG*|W58r!*qNSzTb9PARhuD9^fm`7FB@i(($thx6U$2R|KbbY5KZ#iK7!|M~ z&iF8*W=}2!r(~ETjDPG8b7Lmc%12kypT3rD%o*Y|u5Xc4udqBV>Xeo)qOxRQ024GM zSM~YdFtH=1(SrZ^fS%aHNdupl!eG`JPni(Z=(t?S?U-iI0PuT|9+CcNKI8;7Sw)!Z z?_*Tp|Gs|X|GU(f!_djkFM?KOdDiw{Pp6o|y)Em_z?vZ997hm#1NL1D~Ukv{rK!T%gPb z(l5rpIdzYdXHJjjRPaJ|J=at_ycP|gaip+hZ3MY?c*R=R7#f1D_|3#@UvFlB{QbLw ze(D`isDnCh*>22CkP5BnNL}kuND-2%`ZN{ze9042C=-U+`?iGC&G;HG-=;)a4r#t( zEWg#M?uJ=2jED9q;3acDm+Dt_^25THliKabkk^X`QN5b2?$<95=@6MHslri<=y9_Q`GrDdc@0)NSPr+XvnUI45 z9FZYx-;uqqHw^`0wDRow+T|LTa`uXxiz*C1j>3B|B!)avQx0LJ)<9P70-Efg~0$A2S&M?A| zsy<`{HQ@w@er@j&xF@~zSs{`?pKA&Xp)GA@Vt_48_GlD~q?b@#mtXe82^qp548_x- zv^EQV*WG@0tdyzh>iFi$ik+^R!@8~^PAX@64vmojc^|M$ohhP8)%doZCjNM15Bnd_ z^-B24|HZY|Ccdyd?6d=Q#K%xixNJq6;mREcxh8x3>zY#I_8X)!n0lqZN6Fz*MKf~2 zD!7tW(EZQDXVO8BMaoZ|yE{Uirt|_{SKW5ATYdB}-(4G7crcv4Y<@CfyP-o7zxKGf z?ZD+$K{902Lf(zCO@z0#a2*m0$T+Bc2Q%y5{cbWrs<2IWSvZ}xVD)2E3zqEEWnxbR z0X$k8!w=Te1{rK_hR&Zl@3PrMeYRwGMfQ?ah(n>KIjTNLZ^1UB^>zKwR6s`sv-s8D zu6z6uJ70a>zbcexXGy=NaJiWz!yhl9f<=VMCdppwy2E~WctAr4cii#0B?gwfYk;t^ zYx*vnr@NhfRH1juOmP1`E}Qhv88F1?8y=SGq+lf^Cnv9^U2yopS6_D8z{6Nl zLII}~bg7z#zH!HkwSb2{B){lbm=#V8Y!$ap+BWxrw0p2fys{Bm8FDQMVlTz*2htFH z*sKmw-+{lhF5nV^zn_fcoSA&#SxAwh!39oc2g>@{~~fL_bADM947l@$v%1$#&>h6*K(5?pcIH=IXlwNytW1 z))!oS7^~_oYb7L@GyenoRhP2zh>{fdccim z?+=#-Xkr)UzXv$_6b>L_H}dq%xbRxzJdP=3e}DibVuFC@>G^p-TxEv^G!J|)L!f&U z{wFRh(YtBMnaNIy0miPg#FvC+187X$>E(-b6mLp+d3pOT{by;n!R)uFh=yFyt8aUo z=G`>`yq%q0J;;a0b-k05lS-=|PEOB*(g`5n-q`^h9r-nd;1)Rj=#^%52LoZFmn~vM z#0Ow^np;y-;t8(6IFt%1<#TGS}wJR8W=!ty(`2?ygOq z@E2iZp!u=2K-OS?-B+K52^BRJ#%975{QjKzZg0TVDw$!Yt+Hy;<`tFi|4e z@->5^t?GIpXkx9#udg2`N=E4KOajjGx7Kw<|>sskTh zOxTqtl2~?q>Z-ebS49gs3RUeIOm9ARkl<9<@#{>q*;ty)$|=2%0hGGmr`ca@Q(a+> zSsqvopp{=LY>V9^Q)cxJ!Llb@EA$>V4S3EqbZD+Yy&gS2-ucm$2|@@AxF%iqzpLz} zdOJJE!N&l!-4onTrq65{6LiC?P`N?k#8!{sc9qK5Jv{H35@OX%NqJkFa}Vih#L$yv?w6&8;Se5vcSq=V!snuOxZ81rAw zPQvh8_ASh6F)PQdn_Chopw8Vyz!Bbz+7G>jOEB*M!o~YtES>q`wCP$HG5O~7@F^;{ zV*!d04(mp{BwkHDBr4weKaU-?x=eb;Ga+E}0YH$vonBzZ&A<%A&Q9U8o!tePaSR+& z_~bHT99;6L8vaJJufzlUeiQ3?6{OB|Gr$jQx3Dn(XT zZ)#~71Z^shVaLSA1~~}{&MJ2~6Uv~#SWL3#>HDo*&(pt?>z=%PLWK^v0l5Fwm+Q+r zzgFv<9tU>1j+OUxIL=;EZRJKmpfTr zMLcf>cVcTi!e?G3PF1p47*;xAne0g;x0hs2r>@@S1FvEv<)1wChXV3)p&t1tBnJwt zCiZ{Q=GJduzm`sR z>U!mkfS84{+Piu%)d-4`v!;fI8H6WRTyn`7*CEq93;dr?PY>IzHv#Z3waU@r(mTAZ zJsTar;CUnKP*J2}U- zo>5)Tjh*{*{$GvkH0B+<0cHJa`y|4U^`DG%jA0_&SYpaF#0Wv%FKUOsaoFa z?idi23eZO>>u4wVTsBEAUe>bbzQg3+0`@0eC(Ug^f0 z_3Kw_zRw?&#hN;hsJ2C^riB;VVhY1YsYp|dj8&+1i|WMtBg$ON{`mTBi7X~@6bfu` z`@rJXegjovN7X%rkv5mF%y#)rmEW zAqrm)f*0X!-5y^Y$y3Fps-^=$FufN}J-c z$U<^s%-I;ku6Mo>l(EZeEBkx5sRoXb=YoQ4B8)?R93v@UC{^e#u99lssl-M6Nm?6P zEGtU*EhkUU=@O?65R3va;rsLdFCX<8z8nWWmGr*cyqrcY_>@(m!v0cORJR<~Y&lVh zlZ79k9KH;0H8gkItim(SrA<2zKDlr6d}HE%RtC~wT!HCmjCprV{JGMqu#@n259|xs)6^-Usk0A_ zjLnL$PN(6-%Skc|VoUkD-6A1tGAWO?lqhfmyp0{0cUD$RG#&Q30(KKKP|8s0&QW{SHLa(xc%_-$pq zCgWyfvBe1^&=6^MQ=lxK8?T>u*h$}QGhEmytaIQmRw*d(X(}F9Q}iniF~FwZW38;BsUVF4vd_S8-owKqF;6<(0@!9YFMuxJ;AJ`j5OYnzN6XF4)mV09CrqR#l8%t(4mwKv z>fyQm`VViuufBFV@C*Q5Bf#B$dG`J_4{`Al+Pz48dOGg97$*61LIzG&Ho5x!qPjYO z&HrO*NJ}$-wA^!5)5a%|+1SuBv_Fhc7kGFV^9VaHy-d*lGZqHfx*J z(#gyQ>rFVXA3OKn$0=-dEsBr&GrRPZIaJB6JpTj}Dp`)M9=!5^tD=NTyUSz8v1}e# zN`MOLDA2}~vW&N)ySDgK&_g6u2oWkBtp4QGsw^^pZ%kzww{x1RI1XQl{sh<{xRQW# z0BRl$Xs5oD2VOTx7@xp9B^M>cf-1fFnvL}zPMXy1zL#$K2S^;piN}`&PiOJ)1)W~J z)M`~UJ@j9?dX~DB*;X1x(h4ilu_|h-!@s6d;_09kL+cw-g8?k<#7nD)a=+czoUBi{ zSoK4wjLs;&P0ae0VqCfH`BN*(%VaVn0wTCRw=Fr@LbLV$?QO3N?AAsAS%tSK|1gCF z#&qMutCj1t6U(D=S9jSERk6BFQ(nSg3LQW!{hk8sC4P@7d?_y!IxuMz@_0Z_+x>k}xvyf0yN8KC4A0`B%L^IUt*X)hNS9Dug8z0vLa z!}4A8$(6Lqx87&d7X)KmcCb#tF81gK0a|InVfgoO8wf$2Jp#to15k$H#Z9Dk#c0G1!t(x*hp zU^LTM2n;q=eQx&NfGp+hfDGv-ybP<9hzr)}XOZ-`hTmb}iR!7B!Dv*f>7N@xh6SGX zY6bssFWY8Dj3eI*pSq+5kFV6aIDVgTikiDu`U|jz_usHwUXrMqm#Uh_jtiFn-2b`S zqInp}GHPsU^w~*ADK-*zb#)V_0Errn5c5@}0p;HO64I3>!3efXzF8=YXLZ=V_4A!7 znZTcip6>#Y)LN}^yzzz~M-CcbwsHoYNq+<*D=8r$1!smXGAYbW|M3~Y%iQAXWxDwz zA)Yahsw1gV8PledTJ_5BYk9u=d{!M|y0N1>5Tkl|=f9*BL$tz^s|+AxzJ7e1*MGes zUD)E|?nU&4AK!ltry_miB`~AT6fj7c>FeC>9+IZ9v?bm)X;VT*{Dmf|9h5}MJ|Q1^ zXyAZaK#I!7ufVqI<8F-}iWy>L3zG0pDS&jlb6M z8k&VPNa&n1VB3K-h-6Gyv}#iz5rs{f19>IjdlvOgfFe#xTn6cqG!+wop;n^%RU3xC zkd0PZ1s4|w#na7KSfpRwgM#7pgauBn5+XA*v)A3Pj2Sy__qEy`NE)3q?yIHM^%0;h zcRG89BPIW13eD<+GX1`yzkgyixI0<}Q4*-inn5on?ICN_UAAd{zzaICvhqe@P9l9O8|$#17D0nk7NdH_da7<{*{&2Z ziamPz(tsC6xDCCp?&Usk?&W0jx%c%BufgW>azBY<7ptd^o|F#CG7%T8t1!;=i?^x# ze5lFtux5i3GF4>ZVTG~4xTKx-px%3#$_lLvrhxoXgiq?6YiSI@a_iYQDVQvIAJeZ6@zbK=q98%U7DSSt8R^eY9P2x@&J zE+=D(K}UV=6Q%di&+vSvy^QQF;T}B5Co3r-D7F)kz(4{728l2CpNkesw~iK!3?y9n z6JdL8gice`?LUZ0PQhj^jjRP>LfK)nF7Zr7IG1|1xBCQG$+Wi4CuM-kNQ7exBZeu3 z1+mKQHAi+(#+2}CejtpHj#ye>9o)Lr8b>0DLs(c?yeMJwM~f1=d{Vfjb@CXY!^~&qVu|JO zYgMefV0>KQSfJlTj+R{`Tv% z>{M?+=VSC0f6q7fGLYRLJgL6)nhaLqiKX2I@a@bqyad-Zj#QmS9bCY&k_773@S$A_ zLV}8>BMd6Yb}KEE26&5uOjoU1Rwz~L&^bMK%21FgQLrrrn1dijXrX{S1!Iz4kiqEl z!45*}>ociKMWA#g{1-3C=P6A>(M&$z|G5Bt@~f(WKhQ4BFV4U>WC zbh9@hO^IT$Zu1-1qo%gBvNpVOkD_sJYX!AsM2+u~NunpBPa%r-W2ug-_)-!E2{9)+ z_t*TeC03SCt!SDnTNvk53{kGpI$JuKr}OWZ3b_}AnC5RsgkF^pW* zHw$g0$a3m>?Uc{z5lB~EbI|#GNy6~?cXPC%xNKv4t_u)MG3C0&hSpY%ub+uhadNus z!V0rKTaq4DBJOp4>ihce^sCTggUZl-NR{353bTqD_4mR2W$p8N8P>jLpn($PW8Fhx zVdEpYel6Bc2c(j+tPz)%{ugf9UlJ?2&qJ;fZwff=wpB-dAmhC4L_c-3{_&LY)8#xXdr24`w}wb^24HND67t& zs0lE8jf2y0!6kwhDQ}oQuNo!9`^=}P_Vd`CV{~j-9q$K#!ybn`dt*YL;DX*&JK7nU zo4=~-@ga%xL2Z3IiHV0uDyP|VTpWJEAhR#rnS;rFwb-)1*+giBkU!r z&|we6I;_X-;3bPE8x_7=qQgmIPpM=y!YkmUVw-t??aNl4Qu#t4sR9J%%{p&EQR2SY zJ~uil{Oa7Wn=xfd8x9kJsw1~HJQQAcQzDBVwL+Z~n_lmY5`p;~+u&@*Nl==b6(6gX zKXL@8_(2GwXhD(G{HK4kpHHlXU??_mJucAe3c3p!>l+(k=b+9n&u~AFxj<1s*89-e z856s*#kGE?eQV( zC`Kfu=j99v3eSw9qDGi+6g>(1!-#vquzSifu+0BCiO|vR58R`WDso^39SfQ=z`2BU-5}2D}s1b#=!~ z0l=Xsp4#shK~JzoQw6GSQU-{Ib4R!oe&;a20N>fkD-sw4=fq1zTD)ry|1{66dA>a5 zhXCxR`-an)51Uu9)!Erevs1 z@z-Aw;T)@ml~(Nd&JZa}B28AaB8$?$7y9`CRH$fj&hECT>uGp^lv1?ru)X&WUWK&C zppGWqv|i4J!L&q3I?YXohw1M-uP1O&z}0>!7~X1vKIP?567HOo8={@pU-fl`N0-+v z6BV9{b$cQvdc|;|SAO7vte(^bXIKmk+_thy+C0h?4FqfcHFj`VDk&U;4H&-~LH^$iL z1+A}^=##rdlK0D(xo4|Ik_iS-C0xW9zZiwe?wRIoRnP~FG$hfEiqU9R%{Ks9sZUKf zB@*y#jBI4NaPoYeaDB~z3X2w>z`@He)}}GYT-O`VV-QHDt68`6dtqS!TDt%P)CY_x z#yNv3!A*2?4CR|?WysA(7+graYWrHrpzMbq;hKI3|SJ%5_tRBzI- z-}<>*aaQ3?Znr8Wu9NqnObu7EB5wMx33(mbq%kpq-H2$nfi$LwFE`7k`0pvYgU?Eq zjAn0kb5e#n*yQ$HmmsvVvxn2^-*Yi6zF(5I+D~xZtiXp`NgYLm*$4+DURLuwGmJtG zt*1(SBFkf)S6eS`FN6&IPt^Z|6ue%Z$o9PBfjvDyltDAvbvbzeR^0_RvJfP{&X~ue zIBmjoaJG4!LqHu{%p#8&GMO!ML^ox=J9~WN%-N2(V8U*P8aoxI!}#iN@F(K5fe*Y$ zOkoTVHmcTKI$q)Nb>){Q&NR+bQQabA3 zW#TuiWLn9p4XI>$BnuAWTGYX270!6rS7_8*HgK-;4p(OnJqi664fF~8@gY7%@fTj9 zV0I;VyG6C}u-(Z>H0Tsak+=BGwk{A~_~xB3paa)_S$D8)R^a+EU)=pWT7~e0QM*Eh zN$)xL0`~GBA_jGCawJtE>3E|kW7XQo*q>^6Q@u+gC{HxXQNGAW6ikyK>|H&gCSqmy zD4%$zHLgZ}{5q33!3Hb?8?+Ru4MsyLIZr8%GLGL4TWQ z;}cIHBtz3*@E6N}a7r^qn|yO-nJ0kZ&z(f2>$_ZmJnp{SQ6#+FO$EHKo44s0$5W%b zQ+BDOxCzylgj9BY`f#5?O#l;2L}9uC@;RBW&})2;KpM3Rh@p04i5 zs8K!Tu1bV~yJh#EYOk3~sDKrjj<4@zy2%kewccG%4>j)X&#nMp4nE2Xm zW2j`SaaT^bhj$wsiVghUN1#I>V110=W`ubre@~igA%prrWGm7$Evd)vea)#4Cq#Hy z=P3bNnkC6&muszLw>=3nPPE%o_y9cul_kcAGuX3q{&$=$Cge>t$jOzNcjHp*8JUkn z8JOiiybHo%3M8_MWl}zpSEA*pSqr?uh!RWwkyV3lbH)ERx&If03ytFn$5={?X>UWF zGdW7{os2%eG>k)f;k{lx>@6e9a}1Ieh5M^>YvoiH7lt=y;zN12oC(H+2u8#pP)t$Nq>xRv8k(}>7T0$A zT*}o(k-;eD4*Po0=~PkGd90eX34X6`FMhmN{w(tM=6E?nQgme4NJ$o|k(GZSlPmTt zbiPg-&l}5Rzn_yOGb70uN^D(Wf*DST5wR89?@HP%K(^+0M0bn*T$W0W0^4ojN-9l* zC5j2&NWqoBSWuN-m<4CEZ3dgK%FN+<8x+h~fqybyn}XuyHOUz)8;N3z0ik{Dvn{e>TR>0eD0IA|F}y?>%rm>Fv;AWrbrK4|Ox!!{2o_X`!A znz8!n41!u{a%xjYNBGj%*%jcdsjmz2jtkcvOu2Cy>f)_~h(3OB3YY!qLxiA03b}CPNQLn1 z6^Am^LVk`NbdAR!V}6m_6~`y}WGahc;bqO18hF3b*rO3c?V{xTyfxCZ;#k&PQ@lC*#3fS_J$Z_s_g zrq-OVkywdc7K5Ze-&?1IoT0Dw*p3|YAzR~8P?|8jeDV13%I9{WttX5UDRgz?lw5FX zt`soU^<*I#Tq8M`^1VWnU*p$)DRcCbdiN`*>)~1vx=_4vGWjK=g-?ez7kuCimbfyG z!~S#@X`c=$`eC$;(bx$8OM-k9{v*ZDXn01gWr_V!`9hzPNGv0w9{S&B#pZ9eVa2zS zCs^?iKk{vVqzK1;Dk?VFdiX;@56wEyaJGN@oqk@ROoP;~VpX7t_mf8$6j_o<(Vt~C z{KWgarFgL<%G6CF0h3myJOyGOJBx}FGwnw@#kgIqWL+|a5gPl&V{dZeI0OLa9cCPN zKn@s-PaNFu>1}ox;PpCC(#WMZP5WvgR6XM7w_chu> zNzj+#;pW)Cy#?nSyZv;tIRaLMZSBDu6Mk7P-yPeh-|#*ltFEc(Zw~7fWxc~1+*TgE z3%4F9z@^I`Z=LrafP9`kqf%5u8!=5akD|q~GNj51Ux?wn12uZlO!>)!kcP&+*S|w7 z;y7Zo!P##F#*`{H3Dy_K)kjM1uXE)yqml_)b>4zn0;+h$`oX^re9HILt3yt_65R%i z>mFARJG`}m`C@PIC2n$PM`20tidddM*l@E7cvmsWbTfdg7r$#Y@Uz8s@nXU;07qI{ z`u1-|Z|vq>?xrZNWV`z@K3J3$!!kbY;K@#m&V@DI$ReRqJU2U;0$Z`@h!jh%z}NmM zm;+9Gk{#6)UIljK$~Zed=!yt&3Wboep7E18NxO$VnJ>j!*rt7vf_!~!KfB^mb2#T) zW1`@<2I*lQsL%>3+K5JHocB2}1AL5JZj#i+{8v>>-7ADLx9PH`Bm@2ZZ=Cz!3*hO$ z7)d}Wb1;uIWQ>9$3H1Wf1?qEpybOw}h#5H~C$IL$PaWs=uQO{uIYspd-s$k29ZdQ5 z#4?9>`q{nFBS$WyOnx`WizAul?DXax451Nc-#ZowmJriU>Nktfq)#-_aMkW4pW{AY zBH-|@+9HWlMw@!&A=)glBZ*Qy@#1Q;$zr>$*aPsAM)93jUfG$NxsrIr_e>`i#6%*R zRAnMFc(QS{;iLm1xe^~^v{LinG&;sF-<$NhxI<88D<0S2lRkX64RZ;X?S<`EA8phd z#~%uec~@mnH&}P)WGDRq1FDa%n+=R$_C6~?u-H+QRMN?g@IPp?=x0lx1gY)ky*kZm(Y=&58f!4w~ z*+>w@NQYkT$k2Eh-wMqu4|Ve<6m1%+98AM3QC+WboBE2Es{TE}+%oP@=(JUflb=g) z%}JG!S6o*Xv#@Poh#(Nbb0n^1-4h zYSgUoHR`0KB`N$T`qrGtWn^{7}YdI=kiTxrezcI6| z0>oLsx{e0^6I9XEU^8@eZS9W0<{btA1rNRwVjLVN+Ju(-IOai{f4jUXbHGrc{F_5F zL4+b@gasEW-&nA=ixc^;-D8e`2vQAU=9Q6!G5MrgU#7WOZ%V~ko`lH!A|H3M=W#(9j09FWOshiFF@@^f`(50uqD4o zWN6YhJpZ%B_o}m(kyuvQGXyc@a&{icQ+M;&j)_&5#^=yIOvpeDw=otBqHM7QmJ(aHV)b=v^PR^g5#Ky$RNQLt&4RV zgcyI$Vk8L1y2iM1a`FnDo538ML7Lk}y7ED1uCi_SxZ?NQ%n*+_pNuR*Dz*QjQ8(E5 zcE(C`a_H=33o$a8P!_kytkB!KHOuSC)zQRt7loI3`!hbv9K0o(buwj|xMDhTSUQOH z@bC7lQRrt-R$He}-IRk(p=42eiuA&k%L-}Ouc$*QCpaZ!VW%$Hvtpgo>~g>PO9{L1er%{at>h1+$&zY$p zdC{_+34iW@yFRYu7i19f!zTnF*&7YwN{Y4|GD zrPc*tj*~3L7oULG?r{Qaar?alrRo^4e|!_wT^u#1@StnDJqbQy!_1eP705qZ(0G+&U|2yKr3&O!|%-wBF`jW#d&H5JS zSCdyHVnmctfe0myNjQQqBhE%zmt5c7_=n6m`vJ_%f|U}`o1n|%Sh#xJe|Jpf=I#w(;oCXLZzB$JNx)Ho_=qL+>Bh*Y+kRgEeOS*Hs zDlsD$F*=wL7}^B+TwLL-Kp-ON=HD76zC`W9*WfQI`z8^vlZt!Xez@%|#4>XqY2c%ubaN>ykwTIY0#=A2 zEw0t`HdfrapC@1;eJd;cQbky3gCcFKV808;M!lpc`viq2K7>Sm)5D3-XJNR%641}>LhsH=TmUJdOJxXf20|+x0RVp!p;3lFGrK}0A zIWjC<$}+AoVd1<(NHG&($|AdIy<(;3{qKzvH~w>5E(w+D874Ze*g_eao@2*F8QsK(T=3?d@5Af$#%vjP%NUPhV>jtkK z{ZC!B^tEBA3T2gTRo&0ZtfP5jw>rrgA)7ZURf{kX@CG4DzfQ6sx(0ZqA19bYgi%Gn zYj8>!M;@8M)}0PE$G(dTxOyrE!Z9_VodHw|I2GL7ZJh2~pGo2%sAANauao}k-3up} zVaw_+H)AydkGz9|RB9wxXtrXm!LQMHP0`0U^HVqez|!x_+|hSrlNp_lznnDL_HDjL zx}ZKl54FK&%K2{`BhEkye}2BrTF5v6hJPFWHxZy~IX*rH?9@>ERjamDK%jw07PcqL61jbmzL9T$@kr%M;DfZ42qiH~EMz$_s`8^^Bx zcZ7SQBwbC!D-s!cU4oh?_6y$Zq{zV0h&$V+Hd+jVE0*jFDDNlwXDuXE03yUoiW2Aj zWx$%nOdDk`harJ!NeK(Cs@8Oj`s2xf@LSs;n|Fz&6+fO%cfe{qa_|i-EG(Q)I6gCh zAGx`?>ziB&L@|wgeMv(4MJVbAP`jtkM$9|z-fi=tpeII%QjMxa*>??0$q7t1;DKg}C^pS(u={76(XW#c4e$a){v&p5Y*RO%6Z0t{t8a0`f zrVCNwLMRjqcJ41ILzuTpJoxH#jBYju1Fm7)Hg$9uQ`&b}%tsi5#ydGtY8{j`xFCz7 zS~3{*-8zlXRMl_R!O$rq?Rcb(3K%pCQqv(a}1 zzA0Cjw){NmXlh`QRxArU;@$uz4}k7cG-HDT%Ze2lCK?tIE=G$h29WM)o0e%i?t=to z?HA|Nty{042nxTT&a<9~*HUnHJpApKle)Lry?<@3T68E=DaTcRW-I>F)adKS3jY#x zJ&s*0R;s^W_|ZPfa*l|XAkGh0(h5o}#UAsF2PWwfj2yroGUi#Gr`fmsu!LI1R(0E8fPnYqd+-ye7A(J7<$ zWz+wtBm*$ei%ta9-?4vS@9f%h>E{u7_D>?vDIJ=+3-~TR0c8Prpt4+FI}+TE*lmK} zXkrv5_2=gtBy59G(YqM6eNN_}alH?&d?aveL#8g1%(2LL!yoxpzEUc=O!kjshZ`f; zCZt;F#D`=V4q6F{U`j3N9hqP&ggPhCZ(;B8&AG{iLEh~9WR(JV@Oz_zfX5rR8Fzg$ z7a%+Ks|#1{K`<6p55gi4yi8m%@vJvDir4`(~>+{^PQJ8~y}<7lKF8C=)@rYaoh z;uC%0gcPC*PGI`TW9Hbym^j=3nGs&)4u^5aHR*tH3>yH^07%6bjyKgRjdJKs&@}MJ zTUU~<6F{P4SHLMXr;^37S1Mh2)uN-gX=_Zlb9jgZLW7s!@bk0KM&OJ8?DjM4c-0b^@Ql3TD)=i2U_+FR$b&6Q9V9&@E|`7V^1B%) z)`YUQT~9kreiOph%VTek)bn+n|J6<4jiKMux7HK%ppQ#OVj6?IbAQ%i=ymYMZC6{v zcku)rwef=~MXKfpjM)F%j}=RaH0{uKwK45XTH~o{3qRrv6)pLFtJ&SI&hZ4zY%M>i zCVq?OKuwQ@D#|`5C7LoSLGl6!gTNdf9iUfW{A$DXbV)%U6R^xz?<0b1{z;50s8OKW zWJGVji{uCHOHb-*#uhasQgu%fB?MDh3BOcaXIUUHb@?TwzU*Tja^DCSga1E7s?P+z zagchxiUfHx5&!s5W+f4IJu0CO6Qjjy1Toiq(MZwJ4L!XML@c{%Pk;q=oSI#&iyUEnfJ_iX3h_lv-k6?b>COU1l*Bz z2U!=vl}HZV{!a@4b;m`7D-{pKzPiE*hfnc5ju4e9S{MK?dbNYYdI_0;nof&&Uj@`e zu#z+`+{wUNJdg_o(TV8o4=6!ZJ{>i3R*6yPA`6Z*x(5ki`JX5<2iWkW!iKMG9N zD3%WfqnMO>=%_>Z<0HcI%0jQl)4!!ihy&l-j@!Y!zJS{>&iteKDF9Aki zYTWTmQR*n+>}JFxN#tJYJ=gYJ?9~=QnCI_xmEHf~O9u(6G&pz)=X~RVNvl3}@IeCZ z=ex#s!jv4Bf^13KEOuk%$&}!K=K6Ded+(T8%HJX+B-A@MM+gMyz+O@n#W`uMc>uGi zClSuU0`TzN<2#^@`?dF}K|c}%;TiGW>biG*o4Vn`@}xqhgsBq*?0A=&`Iw_RY>lO` z0)3H{{(CS~Y)uhY9~92onG52l_CTI-lRu>&{v(i;I5f!{3R4?H&8bied(rx#sTBN0 zRfN9KSs_TO$jwKF5uHO7vQB?0+w`J8Buwbx-LUj~ZfD3IW` zeY$+d7Vvp@@09NV;5|r!AVBhS^=zRV!^iaZ=Cr~!LEj|GZJx4NEl5OOlirNZC;ck6 z|GX``Pw|Hpv9Q3cCtu1bIOFAGPI$Ey`cmCl>4D9DGNf%8?;e_hx>rcf8x#9Op;WI8;{c3Uq zPy1UrfJF*Pf!MvRQN%A)qC>gaH@b6kzZ@D*W<>An`>4b|#{Q-*@b8-0i{z1f2bdOD z5n?cgn0tChvng-P+vyn__Jb6Osf0?11@k94MC%go*$qJ~z>SofQ%`Dys)z1rCD51E zLqG=}2*2g%x~_7zKwH1MbnJLow7-G+gWaKSI%3ybVrbqj#0_n@NxVYMf?hsaa2z5b zUJe(cW+{y&p`@3JAfdD^9W|;YS5AhBU22tQo0^tHYdkNFFAeglrMuUF=04t}#>uqv zRs!p!qY6Up(Va@)W@&}XT*{9dFglW?o3ekR-G0M`F=f|S%=T;UMVUDCD0;Y5av7e`hrcdNQTPP)n zJ2}X1wfvSVMLkMy6oo7ZSl%AH1sEXYhj~0~5^t69L6YCu({3!!Ca~loqPZ|A_{$Hz zoj@)Af-n^x9qLA$+*5~PDG!f>){mpsblCEPjm!)Y>{;?W|D~49Y?F4y2#%>$3gC)>k`u-EYWHue(=!kQ%UT4I<&Qba_;ZnvL z`B_1t%!qq-{pE0NZr`9?RTx)v=)4?t{;}MmQ%zOP*173T@ahtP#&5c6j#(Q^Be(RD zZb81YQ-|iBd7>pVR(w2I+H3DmXr4C70)mT*2M!OGZvKI5?9gKs&IW_^vCBoifsHp) zc||KdJdSP@XOI~M)ION&5eo9Cjme}2vitNZ&9Pb zgVkYuD2{C8+(@yS>YeWi8RTiB(OzH-gh+tVa#K*Iej#-CHgf9&){gk$&fgNWvc=I# zT1GnYsPIgHoVqoYwA3i_$yH@K0H1uXHi@UHx25Mh#kN!5sInibwp z`#oAC@>M#LvC-!Rb&9EI5RQ4W=m~jD zbQdER+E^zgJ8F3gB?i2UcE|skN=iazO}|xW#})1Rq$>?YZtB^uJsK#t`wY3pb`F0j z86HHGjd+0)0=cxto76!EryZ~@8ibcIJQU&}3CF$y1K3+Srp*->UJ2rGxkSV-9vGhvRcXO#Arn{Dq|_D*lw^l2Unf%?AH=(^Z(ra?$jUx%BfY)v zo*o`4E>KQ}RQ*W0F9ZTe0FyZ>LjmNT-?6D_gX-CmXx_Do;3?oFQFDG&v+H$d$01=F zh}O{ih!>nlu#N}@lrRi9yGF;0WdbR4lwkPmojVQTsg!9>BK*A$yF9tNY6`EK z4g0XfpGXIUR0JyT6J_(U2;4`s%HA{@+!P0BW5#|nf`E^lKWp*d?w`pl6szd}uCDk& zax9EkKJj^(SbO**07gylI58we&0YJGW8zp~WNe!!YZK?3eha|>>e2QYI20UuRJ%rG zwNxfAX3}u_57}dnqDWJ%2QAdS#~o(Wj~?Gfpog2E;B;IrxI4PZ)1}HE1W-hYy1R|i zU(TaEczx)#s)_hgj7S|kPNj`1W%)j$rNM}w7^fc>ztYv#qdQdRJ zI8p~+ZSg9)6jX>qn#{8p#tH*zrjVNOODb<@FEd@5l#&qnnBTh5dGEA=H}nNyYMwB1 zOt5pDh;(a=Lzr)+6c&=0d1&N?ch+5uh`P3WrCei0#<|epm4+<9@{pbymNKhtw6Zz` zI!ib1pCs-mAr$dN(S=u7KY*=ZSE!DcAhq+X_WJtT_4vqm+3)!6_lx_M+YIP>mB(st zz=>iv;tcmx`TUd}e^?s)u3SBaei)*DoUl&Z=S+rjK2qx6fsPBbe+0%8(!xIV5ej~( zQ{{+;w@ocr#aHjmhRA34xX0Zp{LM~Qb{7TF>*QFCiuOSDcugjk1pk19w|)zNma_mg z1(@MlO{4Zy4%y%cUa;s6brM${yEA2Dx9SXj*YVcL3C^RxX*&`NclNWC*9264IR`% z1Vn-Z!Mn3sJ`_#bGnJFpDnLIIjZaLyCpm&^%P8TV2`OY9`;(6`acUT^JX}a%ir6R# zn?%|{3IjwVo@e1`S3Z?Pc;NRdjv{2Dw{z005Czu_X+K*=QRbiy7wwbZpu_xc5VY~h z5{@7p0X-Qf<3i?JxBlr zdGekg6f4QvUm-tR>Au}&UKf(f%=%aoGwA5ft5r7hPE{x4w%8^Hx?(}yrj9<-4F?6g zg^O@<UY(7fh^Q(aNnM3TV(VH!>mPdg;n2kWxdoefG>hoQTa*pxVOG_pZbpZm<3zlwjb>Kl;!00c4IGm~6LNfMk`Y>tQmM~DzN;^KFl0ta z(W2%8H4I`?Eck}fGrS>nQB2Si0WN_jXWc9|EkZOz@?^ChoPhWEOi_ABf0?Y9PiNJ- zB0Bcc_R7ht<|fkT;6 z2?Q9ek<5GDRt0S-sS1Q-j|fKGC^N#17os>>WqWU#ATaoNRH9a&0Vmfnltqn@QP|xv=m{ z8qs=^qqWYMl^lxy8cFAxn|?HQ#zDJIkqsspNH2vKs|X(qltnx;x`-9XjDJcmA9si| zprhzClGM?`X;7=VNvuBJU!N{@Kf3?>f{dQ$*4`8hyAi!L1QpoGY)dkk#Up1%H@tx( zaF~4`g)XG*Sa0yAc%~pRZkHDq_|JmZjg0~Z+fv)BZn%YA2py-wu3J4kL}VUz-Q>7Z z$2P8x$Gi)_|7v^BrG$2q*|;06UOi0ZwMiu=z&!hBD|Ktz+hd+tL1oSVnyTmnzgbj& zo}Kk`<})kyhWHsU1i0&I(SPYQp;~*oY6ctlv#!P2cZ-ah-US^5kAl!08@6&}Ij$Bt$&Uay+E;nLpC;W zy$!QkK0gZkAJxFzKfR&&Uj03vy~?+8H#6~-P8I0lP(@MDflp?`f2^}KD^Z&y{taP- z=ac8|ogY0T2U!FCqW4v662#o!FKf))ED#Q|bQ7$ZBa3N7#2U8Z1s-KK^gS@-rfE#Cj z*e=CzYYBNbM$%77vu)x0MQskrY6Zh;6uxhjv4tpn^2m0L28&dn(Beausdfvog+b-F z3E|YT7^@6DzD~7Ucs8O%Y;36i1uD$eD9XwL-->DT{+;idq<$(XoEnWHO9v1}1IPM0 z@J|S1s@-Pl<k@keL)akcnd1k;UPDU^KCRTx>O$3wcvm=8cS{ zBE$q28;lxE11Ct&M9)=K%_&Lweq1^mZ;B9yqblsRz%DMFAbGMTS6@#?xo2pMh#3MR z1_m-B$V!lrMBY_{#7@8_isvE!Wt&4k!D!J1QgRV}DRsZY4E?_>j`QdzU*`G?-QDz? z*aUj2x^MAcPutW%T(I)#);kbU5NMP<5k}S&Y4ecyF70{B6R=5>dul0q&JxlPZAZ;- z+3AvKhGrlupUDQeh}Mt3!GeS5m1h6|)w8-PS;e7&!9u0{=PnyTC97m{e!YUwx{ zI}JFk^js(y!+mt=8&9ho{LU*qaRBR+3IcbUweA0Cit7CjUTfYN$kfT1tB615QcekGlRqwVB|8J{3 zq>n2Wg~qCW0R;SYC7-mw?#IX&*N3$Iedf-P7X!Iu`*J8Vg59Oz>6!YI&g3 z=NhCLI2PM}L+?sNMHUC$6cHe19;E)+g?H0F?Ge#C575b*Ej6V+fEj|lR(-}j#pk5x z!P|g#gPTm3ocuf=hp*K$HwGYd9cN>#Kv@NhQ^RkLI}rN0et_c(1Z6x_23&$2j{#uY zo+s-;?~GC^hGm`1sO97V=&O&DzxrXsk2!~Dj>JqOS|qNv(;W$x%bjc$u2LDlv4^wF z&15gL31Q$fPZc`jmSk>4MCKD`M?*%y2>Uhw3H^#g1KGmQJ_{?AuwA6Vh2y$~ z1^xX+)423U>MfOe`MJiwSLxY-8NP=~zpB+oltQdb-HlIBW-%dC4*pS$a>0~IW2icO zIKg_ZIPmFEYd9`!o%iG=zImi%8SS9Pl z5G2q5Y$n7M6~)E=W6^LB0Mj9z2+J+52yC2?_kWAu%qHm4JON<1d|n;D!~~9o_5{pm z4#Tqbvog&~y$ao5K%+w7tLRV@Q51MTY+d6=Eja7w`ovun8#tBlvj2QqVsdh>T{^CD zOv)nW*Y3!VIxY#j&UF280n_r=-RH#q9g|dlVhM?!{ytZ}T~djtv-Wu<|3WmQG&7qf zzJ^ZpLAbm-VoEE6`O6|pdT?jeuK+^s;WjUTtQ+>C`-|zVY5+l%4jH}0^EbD$G`P4( zT3Y{_ZAqeYwP$o4rO_L+N{6WTAAZp(%93ug`Si;dviCoj!p!HT9_q|{c-hrv0>zn? z>>^8>m^OSUQC@)g6Im7k$nsSxj#CV;KEh16k!SLMup#iRNu~~u@ZhCdW!ET2s) zR}9rdx`eLP(_i-Xar@hfiod(t4!|lZI9selp~w?pI7`!O_#u6SAaqa142Qu?g2)F% z64Aj0+Yk(Nh;%AZ-D$U8Q$_mqzBiRB11V~QBM3F_LL9yfyEkT#aFa=)=sG*lE!F*2 zfZeag1WHTQ$+seoyJCv^5k%U$Lu3LdvUHnWcP|A_V*)N~fELx_V2nWTW1nuMVI}~+ zh;0*lJVgF0Em6;k!67;|(Y@LuXc0w`*zlB>eg|p!G552cJUi_N1(DU)5Msh$E_j6D zr(QS^gTq6OJV^C8O0{ta?Tl+*TL7-Sz7HY;dwa~)rrq(Koe>(dzXn!|j3GS$9|!qN zz?T;Tj9`@7`kkHbE4AZMZ!Uq3r|iO|j;Q=O6~{ihhSbj=Jw(^%1K@D;xhh~1`tr1?Cv*W`w<|B;@ zOXeCPCLb2ZM@7Ki!4S+*dG@~mYXwlIMY*ylpV%h3&ssO{N0&MMQjJdQu+#b0f$aW+ zS!jEIp9KpW3s{i$_em*5S7p`l^-N8NK@i(XN{uhlr8fmo-n6*w#{blF<|Tzbk-PI~ z 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

    6sj(#Zk>KMfs$k99JT(c$m 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 ~vBo+^o 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 DvS>*I literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/cpq_port_III.png b/src/qt/assets/systemicons/cpq_port_III.png new file mode 100644 index 0000000000000000000000000000000000000000..65d2f714ec6e4124aa4605928d63da6319791ddc GIT binary patch literal 202844 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

    (kmgu)nv5-R7sJd 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

    SfkS%bJ&L@{w2!0ufzQu1xx%r-xGqJ7 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/cpq_portable.png b/src/qt/assets/systemicons/cpq_portable.png new file mode 100644 index 0000000000000000000000000000000000000000..d3dc381e490a0558147dc0cfa4b475590e1a091e GIT binary patch literal 140593 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
    HgThMRW&LPbu%=t`MJVn`GctHG0z_}15B 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 OUiwHQ-4cXd)V~3(ZIjOc literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/cpq_pres_2240.png b/src/qt/assets/systemicons/cpq_pres_2240.png new file mode 100644 index 0000000000000000000000000000000000000000..c50043cdd4b2b55d070da97b1149a17f08920068 GIT binary patch literal 166186 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%0D@EOm$@oE4<%d4(Zq$YGD-)hdgN3%;>dRNF;dW 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/cpq_pres_4500.png b/src/qt/assets/systemicons/cpq_pres_4500.png new file mode 100644 index 0000000000000000000000000000000000000000..edd955b5adc9a5f00b4aa43d3d274fd2a053d4f6 GIT binary patch literal 132431 zcmeEuV|OM&*X|wLnb`JBlF7ujZQHhO+qP{_Y~Qgpv8|KmdC&O==i|G2^{QUA`a|u# zuU&OryQ(`}PDT^~76%pp03e8q2`K;opx=+60BFeX=H6}b6#yW0@K927QqXrLvU9LC zF}E@%a&osbCNg$2Hvs_L)-JL%6Y$s*jKAt5)Iqo8=%8fdSNVVXP6uG z-ly(g9>c{8hF_iB1uR{SAda|;u59n0-EqUmr1EB)MP0$&En}Lz>umL4Lia|ElwP;{ zed+W~U4<*W>#+O!=x(o9Zm#9p>VIL$zZ2BY=$884j+2LG75;2b$*5RTwAFsMp42th zB6p1`c5{=JCeA5hH1|7m6nNT~;6;3Y=4LJN!GugFA%q+2_1!nU7xxv!@%owTi*E}* z_FQ~jiMV=f6vXs84AIl-5%ZPmyP?}d|Hi_y@f5U6csM+h>mwO$vb}#28|EW(PilH< zoBv6GblAFoa%{Z!lhoq)IC(!;v`GcNS1Rb^=4s3NDQ9LgS_{9vd^_{ip7x4zi!EH+ zgRs(zzcqWy+@Sa{HRQX!I? zLE3%%6_)i+s>fOoZ;9}4)X@Ez`XJZMnlpRG{c+CgX)HEu?1!_|w~s#EkJm$?r;4}$ zhl3F<#+ouK6Re1=&qHl+vW=^(6xQB;@1BoVA!R)@6gu0CXk0uW9~nl;XVTXBNXOfu z8{j#wG4k4Hjvw{jT5x}m5V#jYc@U0QWPNZS7tRfK6juozB?|OVavQesB(-vYq5Sd@ zGkw?7Fe+~-zYM6nf^_uk{cmWMk~W$l>!MjZ@?>iKhle3 zj`4FCsJ(goG8JBm0%Tya0Y6Dv7)wMdy;;qsGD@cU}S!*59icGTf z_RN!z&V=3g2QfnkAdbiF&A;j7+Kz10#cv}t#f;;iw$@-DqWV@X!~cO{6(52zUXAA= zEw5-VyYauo(=V>Y28HLgmxo2=$|o=S=zH@Ew-#U7xxQT}$^87HlsWwSK9e=>eR+MA zJN}VY)$2*~G}86et=P^RdVQ5O{*i&;`=NCCH27*+YJsqismHGA3))wYOEw4>xUuD} z0ANebn6poZ?Qo|ntGbvZ50R(#%Dv7_no*LA0^=qVJjBs&2t!2Jna0ymFtHI8w zXw>-JLGLMyM!n0Z5$KdW+|-QrtSB+K4DZNbOm4J1%)6pYS$zwd;cxe1o3%bMqUuOK zgGDr&RW`Z!)c;f9gOw{idyJQPBlj#selcs++=Y{C&Ao!}o!nqu!_^P5{Fo6L4+(z@%-JF;kWSh(1Hd?^O z`iBc79dRZgWq)h5q?|X!5}|v;yZ#qs(g4A8R-J7~(l2uT&EInr#X-|=NrZ-~P<19> zmuLs{+4cnkm+tI6EaE>L7u`!!|785Q)lgj}R3%4@ro+b1K51j<=Rn?8gVTFL9?H0$ z82v~gt6vIT4Z;)u5LT+&H$5J}f4w>N4+;m%{E^A%sbh_@cpSnKm*hUv;6lUVc+xFu zOjFLB@GzPZPekyfXV@I$C8*4X^+ypcgV8~z-F#h-P>RQW?oZX9#%LwMA>K#D0qcr% z+}5vo_mJ~JlEusDz;(JL2Sx3Yu}-RWbx|bCpIsap^-!l3kerzZT&cRjpf6ccLaBwb z@zDo!^Jb=k1Xy!0o(eaXq1VK?jH$cf(+p00bV8PABNKZR7%uNm5 ztN-jNSsi#IFKXeL$NHI#LokG_37_P6PpsgH_?j+424tVGDBbi(X~u2rB+Y$MlU#Ww z?deF3NY1V0qLa?!rf*>(TvDlTLZk;Q$!t6Z&6MI$!@c96pPkFYFf}lK7%JJxI0#r+ z$c}L@DI`{@Q+;6B47WID;ZlC30mq%>wy>#+xFA{GqL~oteT-DqLno`XRjL1xQak~E zcR7Ft-Zur1V}V)n^ZEY}Sm#O}%8onh6lrii5H^6?N{Ou8`HhD0Qx&HkP2&_o z`zgW%Q)q!E@ugc>Zx}sh)t=@+cy3ZQIa^}EU%?LnB>y06aQA^dm}~cbmX9`jhfOpDT7!v!$ZK3P%3L?x)SN9mCJg#3XqW}T2}PX2B_k_P(lK7;Wa@W%a|%2`nNVC( z9vcXYi3)e#Unlr2Q>=FU;Rj=ke}MY-*%uSqSm^-#A`15@T)*?(xGiCQqxnY)ymr4F zDQb7n1IY{dqt0@A7f8NvkfC2qFh}>9LK2gTf&?=>h(&M?L+xdb66T8ec;eQOZm@A3 zKfu?zwnjaf!UGlNie6S1;ED|FerWE2)mF?H0&XvFd*d_)dHyWYlA>`}y4^IfiNThs znq3*Gg`WPER{U@dk)WW1prMIYq-PtH>=$^O#QKdzs;uJo(!=y3=#l%vUkFu8T9Uj` z{icAhp(kWH0CZLC$-rj%;t^3=jhBJs`|SsoMlmyw`UA|5{umLqeW@+HuS#bL=7#9j z`0Dpy-K6)%`sHuE7#J+iK=d%XdkCA=bGeHHRjd&fH$&lRI9Z|jN*tcQg)8<%Zn@f= zhd)S($`Mb=WrzE<>{#Ihw26LUH_8eF^VEeLxK*f$`|2HF0TnX+ib)Kk2Oo0%9+O~X z6)E5)xu*bvRDI-(0dV4w>#eeyS)ASAM;F!40O1lNU$0`ceF=ilQ7b==**{d6AOBc0 zGU&<}_uzU8ltvwV{cLyl2nU1J)eo?ZQ>W8R3p#U*t_9%lL;v!QPXC43sZsNzhF3l% zBSKSLl+R*54h&$F>oCo$WiaO*L^#nc96cp7*@6H_fY%;~y}U|q#n+CKO>6veK24T` z2=U|Z-<>HNAj`}!g%S@V-I0DCL*C|iVyDPAx%69rwSm!5q4g8LLpTB=IJ>J{;z350 z5&GV$7}EV!8j+{Q-{Uw~Rqg?z0XB3BV8uznQOH~9)+ku>7e#y2*m(#vKc)NajI?!65#sF)1!5-g zB?ts#WQ|;GKEf8ex}iar&~%gYOVaKuvGqTZEQ%O}aJ?R=pr)dHh3jrgi0Q#g<9-I& z-mIzR=0S-BsS(g(4~G2CO+|T#knJh|YmD1ertTr3P|ZXM>eBUBig;})ZAavEPwx_Q z5Z=7E6?!EldPX_#FMY1<0jn5DgF@?$FtJ2Xy5P8qoY8XvYDniO4=GU>hw_BAfiC># z3Ovezh*Bsmfnv#vz*;U}8h@ZzIl&T+p(Y=nUVscf75cRi=kI1!Ua%GeST1A-Yq{EB zgP<6zK4-Dni>1nu(GhI_)2w|7Ee;ZRVgk7SU2Ra*@Jd0gXS^dsW6v=pSO@I}^ampy z9!qI#c!7f@$hNv|1(FeIf9yo=QA>0}0?M5(k^+V+b@(p>&ISz1aBtFbNXRogEFf+l{QdCQL{2B4rJ7A{#>9O%I|2QPYWRXI*W%jx z!S1`GOp8=wY#b={Lu7Re2$J=1FH|kF*%aVYIDHG(*Tsk7;DINXgQ9LU=5XwMBYpQ_ zNyL(6p?n1s9{t{Xn3EuNtfdV{+A~Ae?;x<@=og`L!Qn>&pIPZQZ06p^KhW?wO>m3} zN&B&;Zf5*sL`wD$m`5TtuRs)f4`V4|!q`!fnoNh0SF&1vjl3p1*$lRDhy)W2sDaLk znb4Cr!M`^#((!xaGCWhMi{bwDO2M~%F~ZDnDf^9Gnh6q-TsV*f@;iAvEsxOPT{A<% zp^b!JM{I#okogHpz&43^jjPA7CX}5)h{ASUm~pS&k6rZBBYhp_Y3UY#J&5m{9*te{SmTj^qyGEtqRX5u;y zwx7Tl2oF9qG=8gq$39mvpFjL^CM6oV%$PQX!-gD1Ip8`#8Q%u`@q4HcAL=QLFx^&96djn z4(3}ns$u85Xuv%<3~_irI5)3x_VKtmRWE3>G6C8WZ2NaL&%bcdP4txMpOMMc$WYqq09{sW;@2qz!!(9 zI&7qM)$od90cL0%@|za5#+>+v2rsmn8wQkE6G;T7io%T}H62eJ1On+jvA*oX{uuLd zNb+1oTPIrG4lLm<;N13u%%k{&`s@f3ioWV;&@09Vk7%Yrr7_nd<|F0-7N3Tk z_ow^~5t}#$Sr6MUw2tehSfL4;MF#VSr(kb_4I^pQD3nv9Xax$Zkht#Dj(pb8X8=xp zHhccbZ17GSSVcHOV^km6dn&UZ2~TW*X{p|`o!oxh_^QQbvO?1=|GSG;BQXP!`+HL& z6G<_003VoKzb~EPD|Mc1IwKc8s*^p42II@d2hg=(j;gQLBA|9P+ zjWn5!p>BqzCWwcHQE6ExhE73B^LsJKqkqdu6L$5&e z(aikYA}Tk(s7%jKEffWU4CEKuM6%vm8S<_%Jiwr@#hd5kOuG4E3I3$zCM zBcFna$R$T7;n>dZ{9n+I5qjAKq1m~G z=)@C-o52msH;oooi`Op0#c`cY<{|x%O$(EEl1S3&Wr|qqH@prJ4>2v%oZ^3`PrI+7 zgTN#c-o2&wr&7NIt`0kBBop@6B57eiRIwbmR`MYlgD3zjVY>4ujum>5mi^QiYpL^m z`rdo+;)KVyM=<#A{bS@aHM(iT?!#*&!jxr#RVwLg`nBZ~AkvOLpu=#0A#r%@La&}u zBo3H>Nv+__;PSlQq7)LZ2zwww%`ou;{I2E0>1_y5ek`yeQbuwsh*g?C8?c}l8K~jW zUlu2}h83uuf!21F(5+hR=ojdW$db^|QT$9)L700cdE(GGy85niy_g1)W4N1L=1gBN zc#(#^+9ni-=p0TIeEe9)W#OX8-~{HPmP9jCAoA1xmwK45B{j0(iHY>U{rG8(yt#M3wF+}j^IOI_IH`P4+`0J_p%KcK4JlO4v(edF-2m(?3MSZJ5H8 z6X5cQEP&`}FCj;J>y<#pl29*l6c@_qv0w7B(BAjje;e|w>}V$^j$V^yK$$=^oH2J_ zgZ9Xd>=ae^k1N)3z(_StRTA`twHpCMF3rE}*h(lM3^2(&@51n5aU}von&(3s46N`> zss`{Htatl!@4(`Qh{i82;+vG{cSU~kF%~7Hl(&9nZOwu%z7E~xBQ1)!>f}kmQ0i%bK1gB;Yh+Jv0Qg?Wf{Rod&W0tf zc-U_0Pu9epl)L-m=5y+VI(axx;rSL_a4b=1ri|8%=-}hK*)z+b8>}^6Ebz)DM+?K0|OI(b`&=^Haj{>KsBaFdB z#AZGR3vz8Q6sJ2Y#?*K_3)-sB3OO*JgK{n`$PJaM1CA%dQ;tIYJxFUx^htlWOXanV z-sR(e`N_kaO4{=O+#-Aqd}@6C^~504x#5%bT8}|58&YIbsKRHOOk`xy;QboWg~-lq z)hslM62!0?dI_lN5ESzRwnh{}=lUbT{4i_K>LS(u2Oh8bToEIiR6oGESy81Pb-Wg+5=;LN1`c7lA?D z`doNUVESDS8Z01Vwx6U;Cu+pnVov{>S;b`Uu8x@R9~LxsLC8(4hWc@$4^aw2z?vTm zIpdP82&_E!nmky0AdwP}ZE1yST+?8@ytH7oM-89)#X(qe4A4PF zbGJ=dP6UX%+;2%mvjPkO+pwm^sADW51ci@uTIg>Z(wbjwzc5f07pT=?tIe^Dl_`mb z;df?7FPxUFG216<3Z>g&0IRwDEOFr=W>Ri^Pg(M_i^7U{7S$Cj5gnAsrqJ2@OKr-azndegJV+Y;8N4bRbmUaW?Irgwi}i zzcb>+0J>=~f+4cho77?s*#SEI;JB=ZSFn>#9KZTOuawO|MDz0cDU|DP>Xy(?;2Zt5 zi=|~KlYy|jIuz3Q^JUv1IbR1n2%Rqq_j7t>xKN!TUim~-C<~w0Z&(9#RBGJ7N^ky+ zo(#Up=nj^(+yX>s*Nqo(3=~ob`25CZn12>m!9d3HiQpxa8V~Eh0b7Qa0wFvvFxeZ+bCPSK?yhftN)1xYBm+iMR>;}xWW81AU>w0ko^K-q>>2} zjbl1Px(UpIf>{)^-mxjdht#B1*0}mo$1o%wOM!bWoX@?pWC(neb{DbHxax1Z+(6!~>2!}*jdr0A@pX)30AVcIT?Z?*VRqSgLVayiWR*B^)I zhKOM@=+9XdTz7;jA3e+iV>U_{$;Qms59#Ih~|x=VkFNFo*QG_;!aD7f1kpM z6#WAUsGPuKnu@eXJ9M4g1)S4P(Jy9f3F>}Y$%Hd^f(tDn;@>CDMcRQH*6z3!o0@VN zX|6^fJXj|P3KhZ7aiHg9tU;)5!kQ0qJpi3KA8zZ$9fi}Yz|ILymL3-$w=gPkAD6|GzwE6`C%8*#E34epgmLT_SpangZO?|kg&bL~-}dpeG&-}biv0wVFO z!_FM0i^5u9t-yow3N62Qj8L5+E)v=KHZ>l~{3GWd{Nu(U!lCC3(r^?$Og5lLr6C`d zucgMNDCD8@tQC6rrAdAl1KuMTYi-|(Rm2t)2W`Yq1!Dx`Mqcu4glM*~f>a!k>|%C2 zo$K6Z6rNa&CifZ9(H+da9y{7~mo-BlCq*urga1Zngtm(135tQJ>>Mn(5^;+Wfs>x! z1DiWqJUo6RdN>;Ik}<7{`ql6Khz@4J0n~fvVNm@QhTJn;8*?POxp_=5m*+C0FMw}$ zv|Q0RSY}vrTO7-YHHGL3jD(ydHft{vMDqe=?D+l*`OmSXNhC{a>cio zls^M$W$Q0=9#Ot)L^kp%7c+Zj_!P558O?y@cF61|v%W|W7rC|N=4EXfM54@v6Tfjt zHa8R?3MV#{Ukng(eyK6Rs8FdVyA=Yx$2n!uO!lcYwERK*yXOjl{kJ*F`zlK9$-ESDc^FGwyHRa9YLGl&` z`z3-t4H5R*@)|fmb?B5W<$u% zT_i*Zk-oN56y?Y@%D_I8KLf zeYEouH8;$A@V}yxqJCYr4-sok?}WEkUSiu-2*XU0)MeaXXQm;w))v91$8~d0r=d~6 z@>14{9#;5Z5!>@@CbLacTX2@&tTlTC-2(RtZ(;K!kv$hYk}!;$zVN^Dk6oM0deWYW zckV~98>wEZOuyDb6dw3+9mp(~w;1FjLl<53g@P+|&+;8S#5F|hn{&PF#TCHBZUPDUUbo2b;B&si@F7t45MjEP(Z zq-91%Qaqg&cWiKV9ahU&5)`zN-FhD~dc^yq>e-sVQk$T8_fYJX+*y_>JuMJe(j>ew zz{Kj65|+2-f>)}nI1`qxg2tREo|84}KV5ccj1FJHPfrzrS}_E$ko?2r>cpM$Bb|IB z&roQdCfq7=$!kjkYTL-MeyC(az< z@`SU_`FT>Sj78Ldn55tMY;B~(TCpf+1H`5Bw5RFUQPJp5VJns_LLSF29D3JqgeI_N ze(xUPs-bfUp@Od^SL|a`6EoV4v*E?W*Bh(YZtaiH>dCBY0tl{8pPT|f zWMSnRL{0Q2s)*oJeEFtXu4x#TS2hn4^Qn1?t59aV9Dc4TVz25R2ZL`8`(klgeqxl1>(xqdl@0Zf$h|$O9_YUvT$5r;e!Q}0CF4Xr&GV>RN)#77+MFsp2UDK(LKh}5L&X#B?@7t4~Uo+>T zG~~fQyPtjEH$NINKR2(wNM(ggHa9oFz+$Dr6Q!R}djSBDU~@r1IdMV3|9AT4`^-(2 zcRaV)03TM!c1cQv68bsOUR*v$vz*ePe1#e~TygbmMc`Pm@9bb)Q5zd<4Fr@gMkOM{ zbO%QpY`_juSY~EoL1faiwt^YTKK=-I*HiaT*KH7i#$lyKO2o1ZW1|EZMqM?Oz*^{8 zJRx-Z@N^HF&bYwi=Z?_WD_6#xL+z*If2t7_U|u9QbPEWPZrN@g3-jz(Xrb!D3Sl$h zg^=2D&+%ss6Si3sh;UrYRtHRugZc*b8$%A5jS=~%vM8eH%7tFUR}FvNBO5g;8y~q} z-~@%O*(aPe3dIaisEddNMDUdt^@v3}MIyrCvnjdWNn?1W8Pc_se>qGVg3*wTAbmph zdRnGXP;L~-fkJn!JdR)?Z$M}utbg*fTmWHqd?9O^Vtfl>CcP52{+Y#->gnOOwOyLs z64_{YTW5__H z!pQK8(PuUg0RSKZhzs#6xviadn@?J;I^(xIvb$EimasmZQBcdEW+s{;l8{Ff6bZ%u zU<<$-1YrU|-cs^{f%E&Z1sW3Z!GleM4+?OBivvg*1Nu@1M*T@OnaSnRsTGO_#jOxG z&rOhQ-$QUNxsT7^*^W0nFRMK(Pdz^}D2BTIp0=JUPAfZ{&w#6ERo#zUetbm8(BPo{ z|J(ep3;sW#;GaLwQ@ZT9`hPLC^9C;=^FMAC0Q_H!f&35Ju1!(WvjTWK*|@ofWZxHi zZ?#>ua$gp&_$}!PmC0VU{7@VcB@u( z&C(eMSYDQ+Q8lqiAA4v?IST9HFqYc!_d-l^nr4vVAI2vn7r|GQmt`zo#zaxFsPnFJj28g@i$pmKS^bx)Ah>x{ZRFi%hAoQZeF8vU;ymEJ%sD0 zoHBVu#ol+DLe6EM#e1@` z0+%~QkduQ^T59@wevVgKTKYUm_!<9l6Z`%T$wd8gZpq@~z@eQ>i;iK-%ijKG(V{sA zO`czf9pw?4w%K-2lFO^qd~aeCxE zoQ4b3n3`PG+%pmUuz2B0(30ysXU2)dVv3tUDBzsxQi zKiqR#W1}PZ-r2k9U%^TE!)OG^KqRQK4Aaun!>owFv{(_)P|#2~O&q41mq3O!Tqd(j z)0w3WGdpY;k~&~^xF^p6gG5s|ZosLG@US~BS7V*3+b%cunLEOt<9khv!(}D*64WkM z{6gpA$c@dw`bGrKr}@&a9YsQ@>jbUn?<7YD^t-}exo?MFugd!F&1$>}I&1fy7}T@5 zKVRQ#M-J^-S1z5dsAY0mG9PQ{S7);f0x*PwPQA(T1o=QNj-%FbZS8%%i_g$V8?V*3-Lc@08j%A+{6TO;DpYSshW_g_>*m- z!8EeKY`o!MwaUR*on*!_>3c3&#WR*~E1+}Z$;`$lB=mkbaqW4cjlFgEy?ye5Q&t`e z{)r4N1cD4eBH-bgZa4>1R`+>6czy_dv6ae)}6e(CPzj_&L^lGm3q8Th1E$Wn3R-*UpCOf zr7Vp!9MzK_rf^vawK^Xk)+EJ>S^P+SV6!)FZ;I115r; z(M6qj0fw=zAfRCbRY~Ea>JO@nA^X{7X);O>V_muT^S4i!+0T%-JZT}>M!XJPuy)J8MjkS>~Xi+YIsYoxh9Xgz3l<=pR(_u)OReOmWr{s^qB`J@& zm$08zP!M=MRO-I{^}Q$jrvDR@HaxkcGj}TCCtf(P!tsWGD&vel&uW?jRB#qis;0qE zdCtw?@pB64CjNA=JtpV$l>hdiPs2|Gsb-lmVRrpkOV*&(?)?%Z)E5_o{f`r`ZeC`5 zZl_$YHowfYS!Fqo5!2fvI(d@a)gS623ToMZ6XIrK2|lBc|^N@g6FLi<%yz(jG);lGU`zmw^dX; zv*ob)#-wXsleHb#b9q^b$<{FrgR+6xflXdHOuBUIIBGBJAlt`8H#cc9y!o@cQH&SZ zNl=RlNmf6IjyJqhG3SE(Vo*{n;(;fDGK7|1Xu4WWV=zXGWtLur|00atW?x42v;K_h z_m+3JpFD2@A~0`fDj%jc1AW2s;%$5WlU{EG(uOuP1*|l}syo^r*e_bVL%d-7_|~31 zPW*(-uhI~&^*bysnn|1cceZfP1AeHxo{$F@mrin9^N&F(35uHv(T8`7><8dLxLe@?Hpg%ZbS)CsZ2_|>Y zD0hQgxVEPZF>KHdp0-{SH(hW0*r$bSh#_Iws8u7=K$oaa2I`Lt;77$W{NRZ`cxQFl z)XXVu^}9lbV_?ZMjnLxy>$&Ovu6STWUig`t-mP8P5u)ni4tAmlJp5!_}4jO2l@C^pucaF2a5y5FKbz>#IV!7Mg0-SPNM zR#Z3go123YT}PIZK2LWf{kgz~yx!g8Zn=|jJyv9Y)gJHX={Lf>S$XVS*Ku68Rusw; z#fW?N-2oK~@4LndgXWmXi(i96MGD%+i6zk7PSlfUg#>2Qcrm@ARS_F{xtBPmL^GCI z<~Bfg5FO1#Ta@>cntO*zMA# zO#DzegI89rZw7+wl$bkID~Sk6P$&HC{>}$J0HB1??z~`8);z}7f|ASFEOTu&n*Q88 zwAYLX_bvP0UeP?zn%{`d?n)4P-mn85Tc8c$x46RhmnNI5h}=Og976(tzez&d{PsKo z3L*Y~KCP-@mXM>r4A1)t_0|BmpK-Yx|3YH$GR~WsU`#BE+FT zowZ5bkdbldgCig>{@zp`T2zl0%(~~u%cKAO)t{17^4}#juTb;kk3dE*jHfOBaP0p+V&>EghY!B=sdbv2Xg=_kW>wr9S z_*3WTLkE~=l|?C`h-}4(GIEJ;ItJ|rII$zZK^Pw}_cH9|Y=PSz5o@JalZAMg0Poh0 z=wmQo6b5hUPAxawcHwy(>VchDxiO4nn)N=)!97nD(XXL`JW9bEeA6=Ul5%+kYAl}N zIRER_i>i%Mqf2S?d}4?)|64R_Gc34q(#p>Z`T0wLgS_I#9-wvx4|syMRL4-lVB!-0 zFV;A#j8b{Y0QFk5<+iy_GqNAPxtmvV)3U`6-e7OWpeH?8B`huw>yl**v0hSdIf>pe zrp)vpfUd;6V(YZl-jXM#q9RhrlbZa*A&X`ab&O|VYtG2fknmN8WuSM%er&6w0AKpt zpP=yuc=eLEWjd4!3kpZ%|Ar+601xkbg2mw{Uj!Z67i>9TVA7Y>eh%S@u-1ms*l7NuN z#~SVPG(vq4h7sYzGt zfJRARZ`I%WXg#U;zq{??U)?SbusI&5e=aw=138~AiDw#g-i|kq%@@K}zSO_vB^B(= ze@O@U#a`xkyC9mzM*V8hu-Ct}OIN*2hSGJ)QQ5=l5u9-;h?a7`ChL)09-u~Kt@p>- z^B!hzRAXb~Y;cU-8IZo~%lm3*Y;3Gd!9IQSHp$dLRd2H-D2n^4W?gq`zvbe-^@Sy5 zgh1DkC%2GJf{uYfF6B_CcC}ggpDtmbp+PkZ<~NO$Z}2+%uS@cdw_K-*&9CPLsFxD_ z{+&XS2ipkA33)cZWGf&K2Yjs9__pD0{cszWcnnea`t^*0Vzbp1ew_1$akL#syFs>Uso;xqWynYKo}kF$f(kVRqMO4%+CSVw-R*Ee zuso%zq_EC7>uS$@XxK`69i805)?01&@9*KCuC_Sdb;3b~%rI2eULOE|uw-w-+~S$Tx-p@JOIG|@Rpn1toiDk|iX z4M5TVBY*cKBqXTkCFWM@l7CYjv~NRX)-6cP$s)*c{t7j)+d@rig}Cw#nENBFrz*Kt z|L*XfotTKmbu&m0=sEsMPDGP4Gf0ALC}(h0?Dt$pbkEi6KC3_R7OeeSv%jXQyaHVO z*APU?qwDlqI&=5~lW>MLI>wJso)5PdEoU91P9J9{uz{+_!_7|bK=NDFe6P!O)6~_? z6eKKJAaN3VjB%4D%xaePYBdQvd&Pj>t&#>S_)9RRIF~O)aJGBMK{+w%GP0Et3SofV zm|V{9xL6eb`q$Y+p6foYnW+X+2w0q^ib2+@!9!T_aLgzk+OdfzK7q@4JvOzP4tQRJlU8?J zx;eSIym$Uc-Uqp$eZF7Y@6IoKaNiseyo8Zsra_AOhjj8VIaF6_Jv+PSdaJpDfiLr+ZMH7Sq`kT^$kh_AaG-HCtwq>P6`Z7EFe7blFTje&RgliyP^d>8Y+LL)!ll8K1x*vB5tW@$XH*Cw4m!1jRSt(J8HZ|c8a(W!R z%XGWcnX`Hl=FKpzYR%|hlJAf|Uyg+GyeB^2Q~HJiHac9tKBJc`xLv2INk}Z|UxJtZ zYKQ__Np<$IR@8cP@0BPm@fjO+s#RVyx8ILsdF{`DXQs-^$ni3PUn`dlbQMo(AP3)y6G_v?F<`eS$9zuY$EV8YMVtjU*lr+zGeDnGfK1~Wl32X{$Cl2 zIE+QIV{Y;u=6LDstepy6tE#a~mNA#)d>qO-W%NDGl8xjT8Jxu7vx#Eway-67!kav< z?Q}jfLF8j@lo0DPBMN((GGR`W!)eo~7Kt_}Z{k%!_{D;37D4p9*ssmMaIOU)UESpo4ajRQrD&T`EvC|^J67}19|2VS~=;Jq4vlH zzFJGn@h`M(u$M|Nly%g614mG1>rw0Uq%Y_CCy1O-QD(^)5+Wk(v6g=vDA83`f&S+E z%Cw?o^mmb|&e4rrDpV5eb0uw=dWV<(VWz zh}ed6VckqrFPj9UlLIg21*0V$x^?W?kn^&9I%ZwsWf_4)B`P%r0v!TQ@-yHKZAo)tlAK~H-* zpZod9XNfYcpKP`?Q{Zt1AN}T33ZyprV)auoAh!#A$PNhUl(g8Q|6 zj$F7ti{@d6=7J@Q=m(GJ4xNS7RrW)7k?-;#x!<}&vm*OB-GrTkLqG?k+sk2Uy%xjz zMz3#GAfwH1)0~tAYw)QeSUoy7-J@+rgZj#>YSo%H;TFR6c3U3Tr+18%41zSW0L~vV zH-2o&tMQlDt<7izo>z+Wsq2v}*jY_T_4d>K>ToV63>AdWhOefa>RWVg;C=$oeNS8l zV;66{&-83h$2g^|KR)4X?$%@AZV=RrvCn zvw@BpXD2>p=7%>QI|b(kQ>5tlE00q{i5^9LkCuI|pH}h5aMcfuUx&UoxjkPyJ9>DI1&Kr;EJxG%k_0&|c_82SYrn>%oK5L7hG!j`1=KOnq5I7G2s^#8v>NCJ zmS`!TA6t8)O>^HcGD<}LTin-p0ai)S8fgepZ^l?Xe3=w-`W$PSZdj7PUvz#@|BXYW zTQgnmlCEEAzLWX>>w&HoVt~24{7+g&DRHZ;HzHC8Em<~h)(?nKNX;YdL`+v~>;)b8 zPL~IbGjXPtDcv1V{cH-@byv^1w}hNUx2got=gT3FZb;^<>`>FAfm*NK*ey2?7Z>Y# zHG_IBgL<{WyqF;a@yH>8?A&bAuj8)=r0vQi4^P8M@dd1*X=+1wb<5=DlqkkEM%Cdo z%i%OqLn)Ms{6(HY7HJe6k@z%=kRM@)wAIxr6=O|4hB?PqT-=>RQ-;3H$Q{4`S!w7C39tTlT(aVE_pjw^w2A{p~%-XISdfTtzSnq>U)|eB* zcS2vnE02+d?+~zx0px0zE!s7{NyoT!O#_{xS@ao?8@hYU|DoxegX3=7HoS2fvq@t$ zwr$&LoHn*?TaC@eXl$pkZDV668+`k`GvChdzn$ILnHv|*e^M}K<$mc0aY{Sf-hG4wGv zz`Ckm60Fy&{>L76)~-3s{s&(ymP?Ax^y2(u08Xi983`93cVi3Cc8 z-h#Jn%W@GQo*9LKXHOk;V|Upp_M38mf4K8m`gw2|`6(zO*ww2P;|&yW3hLqf?~Eh< zdg=23F0U%1Dj*(H&n?2)18>&=)2&gRbKO+)Md)3pa3T)%KyMB`Q-V296o2@Xx)jze zfrdst^|+=^ge;^m15Jd2w-4GOCo}Rf{GcbSBfJ9M+uVpPIh?6kr(+7>=VH6^tO!GJK^`T6ZwD8A?I>Kz1LH2i6w`c~&B14l>4f;|-9CSBt; zZKHa3 z2XYuUy;LOEGn_84mlS!neb4eP+PJ#U>99^#I(WO>iEk-X)Q=0+IYq= zeto(z5QI1;*cj~R(1Z|-?&S#%qPyX*>J|AE5{GdT#=TUTOpL`N>ZstMueQ5 zoNj-&*IY5CjUT=3?cJ|}qr^d;-;J~3bAfwjnO(5!3U?Ib^`ohKC#xtMaFXpLYHam^c%-{dmOKEG0(V~p+?r}RaPI5mxg4LMPZXpwTInS8&( zmky&%c6O`0C)NNQ6|nXei6uZnD0?zO8{zM{9|sFP&UX19|IPd8LeNKcc zaB5Spe4stpNwaFwJ^TCjZgoWPQE6*Y8&q0qiIVM{8FUw$@!MYB?6+!#!x9nqQB(wL zb(1Wl8(#izXGNN66!mAHaA&bSM#0V95vqM@Bv2aJh2C~E`ilN z?~|NZ@F^07JK6hnTf?5Xsk=U}0Y-gw!|6x6r>B@;@i7*>J@zuOI6PCCj_+QSh=_^( zFa1G=A6s-v{El~h$u0ImcU!1$E62mC&@6G_s%T2tPT9!RtvKgwCQ(RFZ$7)qnK9+~ zwAdW*i156Q6$EeXYbl?y2rLy*TdtdG3QYBK^0nB-_lv_|Z}R;3$iwa2wIF{wvi{eh z*`LZV!@MLT(2WpSj~pc;6XEGzLT)(+PJMajXIOTCgL(NJtkuD&fnKyhON2TnJ_xft zXn7-;;VD?2Uj(y@2*o@amx?$(*L9hc%D+ac3$_K65#7yBa4Du2R`v=J{+AdhbW&_j$e^{d;$}3Qh?bz9RAp36qJzE0^0nc?i$uF8PH6@1KM}RoK%j7W7}|IFghJP<@uw3~U|kmNl$@U2|QthMZo8!M~mjTNkvsC<yc3o`RQdI_U?w{%Yu> zMHf7^+eQ3be*p~F!O8<|9NXvS zR8O<5{ao^NR+`1WGrq4LjZH1#(=tTZL0N2GUDPH8y9)-aqRq3zDa`9RPH_Muvg?7Q!p-8+vJuW0}PzZcU_ zc%kdCWkd*%sy-q82g=eZThrPBJNp%5cB~Cb`7bimG9!FVK0`2=Jrx8_7n|dL8F+>fA3@bzm`#T}57PBxQ zJTgN5qie}Ewv^@KPvCu1vaS3&#PnyLFzuuBNeXl|hdR4M7?y-Ap87pA1;S7rlKn&n z+Vr@(tOWK`jsn z7^9z;r70O}2w3`NS-nqO-K05D<(s{XP++L@+_^SQlCstW+hL)Jl5_u$rw65a*}7pV zp$Wxxe#WZF1hTHinwhW8lwGh(rvA|L>W<7qr*ljsMWVb=-YtJiu; z6nob!9~}89YF(|X4RWaX0v^h5)vvuV5phJ|OXr{q4i(SbR_);B?BL*FfXhzrGivVj zd~fgV&Jdh03BJ33K5oAbqkdj@WTE;Wl;H?{B7Va99p-(o+6g(z!T0V@LZYp-RpS7e zQF)i1e5tcatApK>;ssm~Oc|Dd!*IhEf{4qu>`=o_erJbnZOdWHj-m)j<9X-8b8$a~ zLzg4P1F?j=#id|sAz&KNG(y$wuFBy_n6{}bBc4}Uz2l>V

      IOA?)OsX;N8|>}jf~ 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ǹ_jp+4 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�EN=Kf!Qdz)r@O?NJ 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%0DnY=eKnRrjn=G7l+}K%jz$ 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 z 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

      P!E>FnIzJt2VP??U!}pxLokFGQz+c+$ri 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

      id8)d` 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%0A~GAsyP{Ntlv4kU2Jx|kQhjRQ5FL2y<9go? zvWGJ1bz}PmbT#~bRUmoo@w}wI-es$Bxx4Focv@)

      R4&8UZpxH)K9Yuf8WYsSvBc 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%0D&|2HK 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μ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≫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

      A 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%0A&v7+r_+}*PH{q# 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

      XLql63a65&B|6RJx?asB5=j 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

      |Fa+ch>qrN`%*52*~Jp&_}opyMzhc1!72A$#yC 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 D@g3%h literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_pc_82.png b/src/qt/assets/systemicons/ibm_pc_82.png new file mode 100644 index 0000000000000000000000000000000000000000..4f398d468088aa499996656e04cdf03f946cf5fc GIT binary patch literal 295676 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μ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≫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

      A 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%0A&v7+r_+}*PH{q# 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

      XLql63a65&B|6RJx?asB5=j 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

      |Fa+ch>qrN`%*52*~Jp&_}opyMzhc1!72A$#yC zC*&ZfO&$JmW^_l15Zhv>!Ro?Ji@g<$9NN7LVUqD^CRuVgbMB%(2y04+C~Y)ef-uAo z4_hokwf@oS+wvz#jn8R{7O2Sg+!jz^0+Vql!(Iu(l_LwoZQ*N<5G@d*dOFuSHK}YM zj;y#E)I%1HSiRCA?2bnNvbSmqt z#6#**zcW07D%eG0KCx332IN3tk%-_C3>aScPQ9;A4p$P(g^n1hA{bsZu9QavGVUpy zfT2xRV^rxie6kKm%w)3RYvpp+iJ{Q@qeYiApb7St$$I4z)0wN`KXQ_6;!0GO*TBoC zn4isWuZ~Ha*h%wslfQ;sGzPU9FcYbMM@)6;Pk(Fwx)7r>Y=5|p7AdKf@QhkPf1@8! zdScHPF0A{EWK=CzD=UHXN_0umVz)^-JoheJa44dgPV zFt|Os^EDaEE!LUww@E;g3X%8+uJ1X_v3OBndPBlo7;GvoN>1cv)%?^yn zzIa`EsSR1EyK~~>*QcY0W9{)mG5HKx@D-)03>!O1YH&iT#fw$}yD=)7>sWFbpnaG|86}%VndAq6eJ;fGw^Yu-@YJD`kVB@UFhtyy z8D!?e!HDQL1o(6MSCZh}8f?m;?h}jwG3LiaFM^;6oUD-RB`$~2w($83@Amh<=2N%v z$}G}snL*2dYS3OzIxn?cFATr6zFx6HFydRUUheZHTC?kekb{7uj9KcJ#Bf6)tCS|2 zPbuJzpUAa5HX5AT{B9>hzlGn$g|Aw;rT@{!k{dV8^WsW%_G)=44w{Z>XUy^OAKj-_ zq7lXnqYe{S*3{JbUezlf1yC`{sS-L-3HL6txahN#Mjqq?o5#}BqE6H6=>NE^aA zxS-zs_8-w-CrYj-ebBqcq{=HAh~{Kd!BxrnVkw3~!_%3$G0`wo2tj z?cZ%~*I1B!5(&9NIl}!NTZt({STtzI+n6gGlsz3*ZvQA}snl|;Y$;U;rFGFUIlxV3 z~Bgo7fHqspgyqG@?X-E@W(rfwC9NeUSjO*_IcPmgOT4;0QIBRyQ- zY`@!P6n;FN@!9C{xfz>zQ)f4L`Ys51xs|MGT$+<4wN7qSW%vvqSX}$_e`uiRg~3UM zwC(9)=IwaPbAS5%`T>o|v;24L8J{&=JI5!Y@SiP%MIzjlw*MfRWaDn$(aB?E;NF1f zIFJ2=A`$WF3ywHi>ENae0&mRU$!VH}wZj-{dA8O<&vmgXTAZF1%};HlwXd$BfPqtWi~1mSRA(0)d5XlT=>9< zKFi*Z+f74bkWR4`5mYZt_=Uy_hzwnOi)6L~aNAZ`&FH{~i6@J#wv5ZjXz^(PvPAJh z)HZQ@j1RS3yXUBOsju%}?%Gpo(01y)Z&G5*BxNH~oGlTv{x1SHlX&eepD}3Q6JqMe z)fM6q|8)uD6(t7MBb$ZLrM3>KcFJ(K|N?XLB#g=O8%NSS-ICawzAn}9c5uCi6uMb-fnWjyD%INhnj8@K zZ!&Ur?ltX<2IA`X^oI5>9dh-&ttmOWH7Z2}b0Gd%ilCjMsb2R*Gx^RZSW-=A zsgVq$DzzmoeUT(fhYc;hz#(uwh<(>pSi$hzy*HVz-~E*N0pT?+baK3IkUBF}ImK~4 zLyVH(Q*Tr$nD%OuI_>Q&6Cp=Sjre$+u3)`wv0hDTGM`5xbb&{{nr=W2_rI-ylT2Z3K#x4xTFU=b9!8r zcB;oHO-`xES(Y!Xzfob~{$)#GS!bJ-)eQQw(p%8p&rzhK03^Mxis&VV38<5bdbEQ) z0Om5}OwpmhkZqXi+kK3&{DBc(?=9?aG{pu%{w#^c2rGN*K$`kXtmJ6Gh@|}Z9ZD)% z_8#^!xfdAH6|nX(y75BpzMBhfIEjR6Ac!4VI7l@4Ka4-MyutsHEPG2V{Oq~~c3sXq z>|+`7uWIZUp^A6Zx3dn95(7+Fau~gxlj&u89ygoUclWnirA@`2)Kj@h7BkjftKVti zebmpe82+N8HnHW9;jOf5b9@Qg3lw)iJ-_&OQwotILd?xnvesN&OO^=8kQkI@4u!xu z_+m+AuFUBOeLMduj$~5RWzGSk0n0zejF9P+P2>z&%MD5jQfZHC&<=)H5`G&~qlo3i zG0HS&tK{|c(RZ0{`vPCr&U+*~Krt22bg!OfUUkriKweaVO8>-TtH(}Kb*=R=zO|jM za4Wy`T;!N?Xzcml(>vp*A>w3S7pCNO4%6dsg714_ z(e22g?kTI4%+;j28iCDpw0nY=+@+c_cgWRYG0moHSo}k8X@v2Pl8v?7W$OjnFMgXW zS&4#^R`c&tsg(~X{?H6!F163S&K_>;xoBeOgeUY%d@qoP6#aGkEV5LbZP(}fnaKPyY{=3MB$Gj#O$ zS6Wz#-?9#3*hbM?h$4t3j+&$Aj9ZkNCSV@qDGm-LH(}C&-xY(Px$U|UJGN}{@uL}f z_2L!nj^2-Zt?q0kuU&D0=Lm&__DBuusI>`s%_U``cDue#y;-!8b>9QNSiyV5-;7v) z_QZ=^Ba%>u)wNN8EU?Xqv~8^HG$lc*`9aX(vceX>-00;AAxez5pqiR!s*rC)pZxiX z%O)7alWT&t4{6fV6!V<>;n>EK{;t#S@bhAIr5GNGt;iuCK?^w*z+GW2$R&iw9ZOR6 zjX)D27g6ZoruW+Tgo%c?2uo(&x@n<3;e>Uk3ih}T3XJT>Y}3TiNoP7(^%dBk{V-)9hUH3VWZ+6l`kTR@(?HJ0{ZpLyA zlfNUgXg#0fk8>nLl5p{N3yW0Oo)-)IuF!LW7>;2M4log;HFYKDXin$(U=zc1cyrXm zkd6q~Us?7{MZ%aCw*g||(3NZbADNKCvS!kT_WEJ|t*4%w>#cXhSOJgEX6VXM<)=`E zV|))AuGzQv(~yNzstU(s38^l^ESjEJ?& zU05C*uTRDMCWB#I@kwASWb)DcoCGoAbcVqq#q?Kzw7TLxeJ`ms4KCYo)B{;@d{RGs z&T|qLkb&?LL2Dj4m1b%-AG7dt-2P<>wE+#@7;D@Y^n^Wjmt);kI!G2oVpCDy z{|`oQmhBauJfr(=xxVftGjz&Yb4F<=EAW{?f3*4bD$6ZrdGp#0iu zy1=zefCeralw%`dTjdzogsa1=idI_g43tb_?&mjy?Q2h~>*~-~8bG>?< zQgYbo#wA)))>tPw@k<_KJN;3L`6)j2dd`g zqz_z5-%(aQH*njLJiI0BdCKew2gbKg{{hEcTP7}oIirM(c78j+u#5$@G1QHKo;AmJ zzm3>)Y{QU0QY=?*Y}@)C11>hZB{vxSq2pK9|L*#}H~5AJ2J(OFte>_Jynb=JtE2n- zcU4Ra*PEO|rZ<892qifV`A9Y0E{w>a;HO-*_c*BP(`>msxx`Lx1d*YNaaa>y@y%F} z2ncI`jN%p*_cvB{=9ugf)^yuV296ZK0q4Vuf!=BvLFW5id=kv2oa25Mq~r*JPF<{6 zf?z5AZn9edNX+*WoT$EKFc-1Qc{kaDOos)sAehQu9 zm%Wv_>+!>bJ*}R51=h~p>*d$Ui#C)?;;KsTJ4-%KD_h&F6eYj^`zLcMPVQRaiEM30 z%j8B{guoHx?#mz7%P!nf76rD9cOshivf*hcZN-UjM2+FXnskhfi5WYlVd$8b zAl`AK%S5-~&oD_9$Og;ax{$`SHJS=dG|ga09n(czgVfI7O`SdK?&set{2gN}UCgTU zjZ?_B?7iA6aIPBxkfxi)IRbqkk%G3q&On>ESDMLhWD}xM&OXK{D@F97le@INLS9~J zcIoC|I}aj+l3GBNU}fl<^aU&Z+w2?;u!{z?*t@YG!B9T^o&@$k!`#CRk> z`X@Lt=CpN#(YJsRx}cyXT<;zV+BW6T?eMvU4l-{s=sy7jXkBbiY7S0zQi$m!%)DQ+ zGUuHg8Eoyd6H7$ELA9}G7W7iE%W~VljuU~>c5_?$L7S6gUPEiXPp9BB;kT6<_lcPr zyXqI4MUG%6F8&Wa*)stheVxtw)c@gM&zff+qXbY>oztdP;gQd6m++0;%=O)_cY4ZaVwLQmHgbGnU49iIF)|7`L! zn1!9dR@4qOV6;&gr%&EVYYYrPo6qF0y*0lc?5B@>`_x{$xjQk7K^hRwZGnS1gEHI% z2f2#!AY;>l!TR7fk+zk77`43U(_sz{=P_16BCSoh&FG5pRJdH9EVY^W&`Q1%6d$OM zr;l5&ZtoyxHH`Ce|Kni{+dG{iPI+}VYfv~8W7c%%7C}iK`kO-+2XQrrxDZcgYyw6) z48Yxq$(Kc%@baaeY&7P?MiG^n!Q%NMZj*Ii^nf4Hm>rx?eMbto=RIH{s!EV8&t*1v@#JnU!znQrWa&MPA0hxyWI(5aB|{V$qLx8;fdJ;56k64aQ(xaZDNg!?7Rwdu`%2Hg^!q#d z&1m#*by=W|mgTAx7E*&5NQbpd2kLJBFB<_G#H9_{eDkhRu_fx26`dvrvN1GHOLEq@ zU9!G{6a>Ev_TEn;^LwtDDHxSkNJ0M?hayZi+9b_S?sYJR3_O5B+x?5aNck_nJMR~N z?(`p6r;QiX4prlq|DX$xAgCmqeGo&A5)Ft_B!TB0F&>(L(^m5n)k&SDQUs35BF%^r zhXLafdrzW(39V(OpW_|G3YAr`y`I+TSX2wYha&L!n5ELuqg+ z7Th7l-KDq{2^4pCC{WzJI0PuJ1qwxq1-DXMi+gYj^5mRzzrW$lmwd_?*VvhR?{%#; z1!tGwy7N_vu0$;HoK{A@Ep1s*NgEO>c|H@ek8@Dz-A2~gDP~GNr-61qG0#p-Tde4>pK}VL&%X8wo%SLqpuZcLG=nRKT&)za12=tmSqJ)e|aze z_9CA1%k#OH={$YC3gyXfABqq=hyC#0XAO|gw8q4*s_!%9TujuGEDtMUDCu*5-w*HX z+e%+@()qMdpenc7TD-7b^~3ou?S$|}6;g;~^6lb=L1cYz)`3us4znnY@rZ8XPM6ZoT(;^#5@I<}dDz0r#No27)A@0tP+= zouFAW_2y<42eVLML{LPNw5dv6KgmrnSFbp=FCzcb0eG@RfsnWM0i?190uyzJi$$#a zf!{-QI7PA~W)U;a8Ww*H#9xs&kE`l3G45ea+s)XXpA4a8{PG(UhVocM=wj-5yB_&? z^yemDgSw9-49R#kD4GlIn8#AB>EJjZ<78DSlyH+#yL@~5E$^OGn~%$Tvh{XONPJ`*v|l7Y_YM6Dx)Utq zwbO^^vvZel{;lh;-CdTKKZVx`duA1ujVlAHwsUV39zmK0lQ}{p1B#&)u?iqHMlt>F ze314VP_2dz2KKD3lH>*b)hymR6~zxNoBm{CoNMq0sqMRIXQsy2@anNf;oDPlqaWUR zV`Cn!4el|c#|V4x`T|}MeJYv*mX5w_LqQ68<}h)1V7e6N<-DSOIM74SeA`q`Tz*kp z8OM&7Mi#-@ko2c6bPdNVehUO@4M-81bo`{Z#jLM*ZNBs_Nni# z;a`gCp;&o5&P{gOOkCi5m=_t@fY|NFwYzu)o_klSWm*0q%Qs5D4P?!?cWS8V#&)3W zEPiC)EA6VP?77JWZk=OsappeHlDN|`vSGRyIQl@f`U+H&TFVnJ>E7!y;7rL~!zdHo zO3V2?cy_Wo_p=4P&R(P>#r{SQMb^<@w52ZoHB6+Ar-vw1aa7ofdI@|{8XD&e3NeZ| zj&%{U)^OaQTLHoMS=<2Sd7+a7tv9jHCD?7n&?>`x(rDdJmE(XIEzD>wGJP??<F{XAj8{u1>i~$AEb!v$}t^p5m_GzNJ^6wfW_!>AgoPml=|9#{mcV|?ag1k zuHw6;?h)C29i}jMJ4tBH2;)Ib)$sN&cBWM3c%I){t&%kl-Or%9V%bcpij8 z1rTqj!*Ad^yxi(RjUBAAmCO@F07fCe_k-yen^lq5xw6d64>xpmP1y58Y?+&zTfFbK zcW-%2p4r;(#%e!_iiz9xde=qIV0)~n&lP!!MNN2&L;iFWP<%l}{j&E`r?}^v%?obX znWMGVk%7R&780C@qr3%E!HT_~c{Q(dKrQ|KaQ5@PI9(n<3t(E_H7~m`$=alvo>E|& zx@?)C4$`#su9zHE+Jdy*OC0Z0M{@5H5lud?++Ch&0xENXRzQW6Ix5lEy|_B0)J}nO z-RNTS?h!cuEQY$3XBZ!fd(99qeJ(Llv>>=9f8;<~+nT5o_BuotH6AEKGPWx{OwdF4 zs-FW@EjsUL2jS!zyp94yW1{`_hiz~u-Fj6X_A{qpgpR6O=P@?}M(&i;5qJY-$@5>! z7K5>=!E!Yw%i=i^8CrRhaINky1z7NktYV;iyMG z$zCM@f=64082+?2s;ubnhNf583;{Rp<3$CP>8+P?U?tg~_RY$t7i#V2q`0E~m>SRna4!n+W3&jRaIBaV&qAtG>oY?@Q-W|mk{X-TZywgYXVhPKaJ$UZ|-zIv_$2IWyG`9 zb>7IMn86-f0m3Rgrd+Vs1bRmqre}{)7@~iT5{3)u;0h@9ndtgAsF+unADH}ra@ zqo{2U+WQNUj{+ItJy-PV^7D_y)S0V+s+TwrG>iK`U*4KmhQjXKgbXs5a93`ROne?I zMR!feub-$ou5d-K;2Og%XuW3<8Ea`H2LBPCKO3+v4?-B$Zgih}sFsYYpZure`9oTu zq$(Qtyma(gNSqecnN_uotxdg%RLq&WPu~|OBczfeQVj`YzL#DBRpMC%JX&uU!SZ_3 z!NmB56eO59ZZ5*#4Wz7B%GWvzMh;!J9YE zsJ!QH0-vebDYI_s9V&I`vGq${WKaFboJ#vL+~BuEo^nQf>^yis9_E>uNjb6a`=uPM zj0h?8f>M*jo!|9hLIMXtIAYL)jzaUu!F&kjW+V-dzRlUH%l?CY=Z)VJf7k8nu2Csm zV~Krfo~jSSlkucFP(rQrv@bV_XIreTu<@JiU)UB~mSmw;yreGs=Wh^s$b$%)04FIn z2odw;H-tuQSa`zshK8Q^D}boEf$5D);D_%7n1qUHyheuM4uMusz2q&L0!=S$hEGBm+&y#Z-XS8|wSfg%k`A2oXyMMNpAD9^hX0ZQ{ zH}~?OHQ{M?DQF8Gw7yi618ST*G!=2>;hjwleV6n`x*8A*JvuVBaInj^G@APUW_Fgf zEf3?5qGNT3mj%V7{sWBWQu5`WSLUp7?=(2y@C40Wi z-*tYbXaCq4oItUthoB~GPQ6;R_P<2Uz;s~`CU-b1{N_cWD4~su$UA#6SGzW`vx8=5 zclha5LqRz@fG5~U=gp!y>#d$vz(Rqx_T|gGSTTx@rQuYmR>_Pl$+Jrpr%@HdHdaeT7L^i~_&0{kOhdF}C%3dp-|AOMY{v zV>RcU7cH}keqAkY$D#pkGb_oYQD_RmsL6?miAbO0HkE{>$d@o{=-#NQ#2u6RB@bC_ zkbXM{rhScKQTW8ravsd*0)1QeZ5TR_M}o|jx=vx1h44YVRns)W=RRjsGav`J@H?+0 zd#yAxZjoD)DMi0poccimC3QW)$7Wjb9ur$6m`T)Rrhl(9EY5koQuza1I}*Z&4SIl6 zLk^?-0NrrDim040z{|8Cgebeh^Q8uDsl1CM@syb&2^DRYtYIG1HI8c3dgM^SM_&WU z&G1E<1@#U$(hs`KJ&bx?dgfw#zAwFyO|u3UTaUjRE6=`eZqH{e0lQwek8T2p6qdtj z5Fd+-@4KRyxc;Vlhf1vjBy}I;jmNXfz@1#!L-w@UoweF(QLf;dXoIf8+X)#7v-fM3 zF6XF10>^beU^1!Rq2rXQ43vr}x)RQj9)rN5?XSwq$Lhe2jTI=#XUU@g((5WL$xAQzL zr{m7vg@l)4DC7D^X}zG8bKJZB22bZ^i11{FbSD&;Oa^wu6IwSyqS)kBX26n}HqHH# zQ!lHIEz^|G7>2jshGw1`+;zsw4w_y_&x!65vk_MzA4wsvh;L?@?O#uu71U5Q53Aik zPiVsKW+Y0W_!1sU1#S9b8V9T&0Lug8=|xKFfMLoQm?6oOHls{Jp$*v5#G|ExLw_o}Y;ysLO=0A?^dp$os9|v_^ytxq;#@k(2sl;rn zIhsTcl_799%s$HR`l@NA7MIi}@HZ>H7s6s*WLl2mSzWY{c3?nDy=7sO4V+E;*g+xX zm(1X*f$*C>NMrdPXU3n69Nz3~txYZyxJjz|%wD$N#;nfifHx8h(x>l{P z@96KI(vBU{(|q9`oBnO<(7|VR@tjvgnju9675#TnmQA+w^eZXyU%Vwxf^YruJTOa) z8U-9>SMnMxw#U9 znc&x{?@~OY@udb?W*-S4B)kbBvYKd^F6MMFb)#1xLQOiT-fxnq!F3uIaN25ZG&?nU zsI)8pZJ}JUMC=q1L^WrGK-UZ;9CUnCT`MZ+cZd+AhC4kGQr%a3J&vPy?#ew$8soCe zsiM0mSMg*w`G5O&mHT_nPp#8QRjQlTp0?yf8=k)=1YOn|41oAl?3(zX7DVb0f!`;4 ztUuw5AfJ1z>3y{9pNx9;_EYe8Asp}{0PV{6&u6|u+k7=#f=lUJom_!$htqt2OK-l{ zQYsj$6D@YIaz7@Y8MRn+c6aW>eI86WZJQGveCOmJmeGFsqOm`=mqm$`&*F{IuAUQ;H;2>Y4kRS74p}qd0_IpSs>J+ zfIbXaS^Q6eg#7yhO2rZ5J2xPZ(bX18mME{RRONydKnvwIjZ7zhN+mEw+`Ethc}$Av zJg~>;EzPPP=2oUUT7v~RvOrO_|LH9~^<(gkvSg$Lq7Jw_zj(>_zO0l9Co1#$_D6y) zrO#ph5BHOYFF}`+*`0T~hVKGK$NZcB*33Gom1v*`569%paO&~-x^x)asXZQ=JfEnE z+)Z@}=PIiiv`i(w*(9QX@6x~h>nG#@^4MYh$HiOB3n%{zq2KEoBhg=z$!;$AsrJD} z2iDjE$;e8SqL6pugBDn0Wr?~Eb&}Hhti=745mGPt`7MP8OZwZlI)|^C;AB9554y>GMTPC*di_kM}Dejw306l-jGgr7C zc~vr$k@^B8Qv}0r%?m=35+jlkld6}7#=en?{0w-fC-Eq*nn#U~i8drs{b7i!T&>dD zkkJ3T9OK0D*-8^*b05C8ccoF$BdL_Fti@wqye!m(}J^2i=)@0K!loZj!B z(rah;E1jB>%VLN(uEc=>U}$ip!9Mrgk6vrRh9ZtRgbXny>t1w?!=@78PwNe`cS zL1IWFH~(S3hI%pmovJn`|K?~2T~dyYyjE5-&9~7r?#U(!+thUtuC)A&bAUnWJLW_U zN+%>NSuC#N-*pjq{8EzmtyVxULSP8oZ{7mWx^T#o0M0#gg-l!gOTqCrGAB>0GaF zCzA6Oi^*gD+GCJN;L^A<3?s~^k3{M(3I1Zh)=(nB3&pVS;QeVAMOmmn&xsmDu1gq=Ya1PwU}n)_}bDzDLuFm zjf!U+Sd&|%LF*>N10|K76*P}wpiUE9Z&t<9mv9wqsDMyq}U zxo8>mL~~j26lNH}k(ZbhNP-H?VBXpi0nzhjgmvY}N|+2r0=Pxt@hheFkq4Cy!DaC>S?%pE-z3{ zD8;bK!61}$ll+qg(}zap&z0yIgZ!He*yAcBXbE-{DsQKXO~Jq#iMncYZjU}dBxV)9 zb9hxE_-@F-uFe6}9&2O0jB3v605OlPUS%q@$!gZy&)V=35KJ5bL>*$555%SQjW2+= z?b7Io)6iTfW&zTQqbFBd60iZLO=#?Fe>$K?FmZ6+Co$8>e*KYjC>SG|03_X3!!i`A zKc(e}p=kH_>SKWT2iI^S9$BS|^{a1z-|4Ot*g;raS7p-V@px!jBYzW^MTz>mxcb@F zlO^bBeVA~9|H|j;+dw43w2i7~E5`_1?%Hq-tG^lAW}4qkT-&21NH< z;8=>Zhg1}?^u1L8cSUIxvTMRHR~8m9wb!`Gom6m!E0+VWT`q<8PET9c_K)4tg8T8Q zX@~I_h@Z*xw|pTF@Wn^;iI4YUL3_1N$3hxp0gAo~bRTuxo4Jg{wqK-|?ZFyFgM(^aF&VW_-swL;b&vxov$52>FoeW>_dKVJygUP&<=I*w5| z0ElVCUjHQ?jc@gyQ*zj@YV5m;q2ue(E0iw1t*la@+U~HP(N?65%#yo|6m?)3bU z4SoZ9;G>Z?iI<@?{YE&ug&b3THb+R-zu<+DO#P|t0a1NgS+}k_T4C!EToGMZsQO_! z=vYaU3D4||Ra{ts;tv&Dce|0cT6W1hKVo%yCUMKxTK7*_b{$(!YhbsUPC?0Igk8;z ze7UL&Cq@i?QJ}N^ZYsl+x5R@fJ{{M!{}j;WvHnK_qL({CcXqHlF;6eX-A2b2C<7!* ze5A%uMq#1e<($aRYND>gEo2BBvjC3i_aAoErevNO%!G)M+$?=%#kYHDF6UBcH)O7u z--vUVnu_9J4wyxO>Q&h|>vUt*CxcWEqeA? zaMRP1usDu1b&^u_M`0%$TBelV9$=RFx|SAi|4q!{l8vnA2pTt4dVrOzj)+4i4Aj1k~aF)^+lGY6TsvV$LY1dvs`Ds6+ za^61Rt|u2aXs-~R@^%c}`1#)I82aR7`2nSZXV-Q?wdCAGdDThjAf)SYdB$q( zYI_YXu=aDW)K4O=H}%lo%F5!+qKG6MJ(L9zjM1nMOn)E7} zKJhtsXv{W|Sdou6^_BHyaa9rvSFfG)k{)+w+o(x?9L#*V_unJ(Ih&i9rIGQ<+lnFU5O?p+J z6(KO~oJw2jat;zm5y+(AUm>$C=B*Z=>P+}cXYePGpJrbT)AR`%+ zB6%v8AS2mp)!bsLF!DkNhO+lsD6{kq92y$v-KnRv6pd)8 zRftF!lD3*prvv8Zh2ScLD0uUImS@OL@VZiH9!DVD>@+gCamBmrtrCO_ZC4SP;D)CW zb*%!7M+rqA#umpx!;H43-Nv|WAc!<0N8;|~q-Ora#)&0}EibB7OgNToF8B&mt-A~J z?VUSmJIupf^@2gDx=tH}YHBpw8itQ|8P4{=LQT5&G(Q%;SAJ+uQ=~v*PFtfou+KZr zGwk?_y>?GXb^GNePXL(rCgrDnXcD=Nk+j~Xy!GB5u29xB-9YcFW2}_k!K#%$0t|3n zjf8v|26Vojbzrg$M3ee$HTB&r>7u2?Y0@lLII8|13xZE7ro*a*dT4x~0p#h;D9&3s zL&<}!MprzRsCt@3KANw}hUQC=KMVt={sxrVyjbuHFQkfirIT7WmSGKWdw4_pb)|{qF3p zW6;vys18Fh#1Je_L+p(5;5`$EM?zqbPdfKA_=S-=_F5({Ze}G`D=gOtLn#z96 zb_%#zSYkgCyDDc4at1Gobn}}2N;g=7dKRaGMBBr2-GB7Iuwo?NdBdn`&z)@;4&igK z!;dOMwBTv5^p-fWP@qH$!}jm#r4wkC87L}{>CAH^RAiHZYR9d5yGDoBh7qVFX*Y$% zo1bWG^m!sv8H46LH^;uvLxXXnN`W*&iux~!Sn}i=C!4WFeZvcj5A_Wdy`-DwpBs=} zimOTaStCOcwuON7f|G{kbM3>id^G}inI`ieXwOzWTfM{Qv<2u4WOW2-U-Mw@*@Z1!UzFl?cVmyP8#UnpHm zZOEdxjDBIvrv1vzA>?8ZR~Obd0LLnS!!|qm;gkie*dBgdUr)RPhw!9l4o?S0c1k}P zDCy8EK@A4n-@l6>h{<--H%p|Tp?6i3N#an9Cc&q8ygq^ct*zKHs`4q2e-ZTwN!{i& z@S}7XTDaNETLQ{dadW1Sp41_3*@qo8SIMH(`88*w9%30t1&(el1%=4%UJHd9|$&PWbR;9&k)73>dR;yRvaFe!Z_b$lRs9S^1Ttrc-<`6)H0yk`5-)N zkY&@`W|C$~RSBW$w74cShu*GAFR?~`ICCkmVNFp`x+F2TkAjXN5{Y*jo5M~}yZKIJ zrzWo$13#Dn(5i;9Yej7*w+2D6t;mwYcj0Lq+lQZo6E$d|!aFCgWn-*N2)D1rm1Jro z8I`DIq+$o;V*wtCFMu`bSAglXjeNXG)>m>_za>scvlDPEe9r$Io3z2E21GqCs^11a zXyXcJEjIfxNQ?cD9fMl99N)u#*CsgTjk(- z=Mn|Go9rRWl;UnirMb)v!?&E{F84h?{D|0B2m9ZiJdPcAFKCCmyS0;XEGQI_68Po$ zzvr^_3o+5Wp5@g$v^J0%v66^GLc$GDke1LIwu#-+R_5Q+qt&u^4RJ_?ssMZwlA~qn zg*P(3-KT!w0z}URHIb?#$IyotVj%U}+QSbMkJMQrujQjlcIHWoaBt1TW#oaIQsUA> zt#ZGEdGH`|MN-K$j0roGk_<8QJD)Rs9bz>VxKilR9*5goKY$+*jdG{NdM(vNPZJsgnhFPWke3BTSOKtFhLY^-fR=%U|TL5+5Bb#G` zELkm;(d-A4x!Ae(EwKV*8_2SsUPv-Y{+bGW>rcnn4GOhoMu<1FDM?&)T$!&$heERC z$5DX3bW)KnqYD{i0?0sAIz|m<#iv92Xa|^0Y+t0oUITCjf!jAjTL3kfSQWR`;0+C z7XXu_V0W;M-c8TYV}PexE*Q~sTHOz5^MpQ?^N_P=Ts}pXe%aj48nTcSuu%-9PIQeL zyfQ1`!YO9Dl|i*zVcLi>6{q9b-!bYu7cSTyS_RVJ6l)#0yAi8vqK42~DD+DdaQniy zWv@FiAVFe~gD5lV`&dAv6cbk`4Q(=w+~8-rPuK|6F1krr#0PDSU!0MAT-S({unegs z2a&URfxr<>j(`Q0psUYvlyGZu!6QqC>e+!M-aeU@`kMS^#ebV0uhF^;mWIIW5hIZF zOaUF;Jb1UseQW;HYX8nwsrKFy)I%1C?H4VfHB_|h3m?fuSa&RB)+5-|TdS1O4MxVj zdUC4a`xc6$B@&z^(!>#b)T9zv!1S_@htaiSVZqFsDL?4x)zUlvTvyP`L;_dwU?1nO zit9>`4I~Ev%D_{68my$MR_TN2_`Ao}EyCik60^w8qf3&Trx&0q`QGFz64otFyv+g~ zb-8TK(ZZX7fp3nj7Yhn0h{|N`bgawe`tmDo*8^WIEW>WibNY{|Yi4G(zrX)?1moLa zM$Mq)zoz5_$HSk^=aG`2n+2GIfF)xUX@m;~y`G#3{@R!&g6?))-`F)W9+fgGK%4^# zh_0NgadB_&(TnJ#h4SbOPkVoNPYJJKQ3wLDR48J6CPLrv9&@aVB(2K>(9)n{v2p3e zUeWCnn6^}GU3<#({rza&;?%fEV->jb}+3ZAj$Gh`(Wc)ZkNP7`CU zKr1+xQ(VIh-wN8uf1DTdZ;ClHI+TX`IVy>;Hc>GeW!$MR`^XMupoJm$f;wC7^3Mv zD&7Ovl=S)=8rUp&A`cww#=(IEaqhUm9t5zVf=A4VwUpT8JB z&xi%BZPxG!Fvc75*~We?oCOepE`YTo1T>F0-iHIcKA(_fab z7liDPA;ne7-w1UESZYL{$qi%JaB7Vt7Q_2@h#lsLWAfRU{j7u@@CHFV|KPeYfG=xxQ8|htn_S;%n7<2pqlvYkfe`52-xfyn0kCWP@{_5nf>5`a(#s62^#}N`TcQ~ zzDd%_MK9%nf068Xm`TK#vbbr&>dBdsEtsZy4B9XyVMBr9Dst(?g(kLkMS52@x%p=* zUMJprKi8h(Tb^4-a7El1}J#|$3 zxUKRx6UGj`04R-eVkHgP53{{x=UiE_tgr7KzqX+>?DX8P+#+&52Aro1vy1J9x%Es^ zLG&~@<>Mn$6~Rf$$|}I$B#(C>#t__+EM1yiWNmsh896f3@};XX9QsSf*Faor(z+s2 z+C^m@g`)jAx&70fCF8rJr~T}}3y%cRheAZpq4b6=p#78GqKJokd!CcS=v?K@Z+7DB ztLT3)k6dtmC3Cr2{op)NGU30oB>M1l;~&&m=a)HeYADT0La$f=BYbP@DlmP_#^1s} zM1mE+AUiVkmjM5CHD!ZoblO!rzcCpaOlkMM_>83AAQYEUfkX>)bq(XyxhVD2rV#_G z8b(1wsf)^;Q*k66jSss1n{3XihBQ&~THLv%pKog?Ro38>Qnf)a!>+%Eflh5fjzT^` z)^RnvF?Ul}&o?u+Hb}%VV_8Ecx;yW{@AWnKFQG#}7qA9dkfnRLvpGtBRMa3hxQin*9WEwZ5 zz>$iVpJ(~#%M+wyDPev&3V4d-&KOZ!JY1|Uv$UYU4UuRTzxi5CKAwe|82{Yt6bQKA z_7b~IT5=2=+Vm20enzAvwJ9rYu5_2MPuO>|ivr5ggAnJs0HPo0hhQ6$V9I$tEQ>ud z!l)_o1U#pzQ%I))8Yc?LnaZ9ED`EroqUf5^{))2FcwBu*v}VhjROH_3K%=yLLcJ>2D7=r%XEX|2uti%~=o{9>&4sC**eI${mZ1G|4Z?gtA9&0&G4 z8)$bTJ+QM4;jGQgTn?djWUL`Y#$)_&q`pgKMls7!mp;ssT5$>-lEw z7d&CmYanLaCB#FG_pqLNj=S`#*Hq`&9(LL@a`G7G2kUr#yLztT1V1w1L1P7dbY(dC z9v85ozPuFFJhAdX(j5LXg`3@6}a z2Ew-(oExW~5O40Dp?Z|-x6w0Va@7fYe1gF(1XkK@l`q}|v)b(*wNu{yR~rvgg+Y3E z#~+S1#jf*~Ibe#Vx#blqTt!Tt+@E&0*!9^|8Wl!AuZxJ@k~#Qt$!ajG_$eY`_EX@! zNmEYOI|$_?ypNp=0 zk`{9iQDg;3n9?!u`n8%Uf_VQl)U~RbwWK`l9*BX41t#Nf7I0QkLO7jM&?e#OZW*~g zy0P<%!QRcj0;V4ND@dkq;Hgv7$plQ!V%bI!K&}q8MMd34loDXAu+I}>@X_h#=^#XA z$SG)PET3p>LiOA9^W zn^w%gs!Q{|S>MF}u2RhXxi{hIe)dii=6BqIs}hi(KLYh9-3$kW1Ap1`j|8kOE!gXH zAl}SMR{vQFy*=kG@objPr5sT1)7bM_*L`93c;0;s*V0GKjXE~HUJHJjFl7R3gMq2P zG>?y*h@a)rmtvv7C zj{E^XfBNC(>X^X6bm0Hcm!E4TdX==ahVUhPx&#li{86@)Fx)iK9QH#~8|*BG(_Hoj z!_bvUBY|eeM)VAv3aPO?`spldhAmemekTFzk82OrYxhw?#%C2bUmZQ~?n3Pt)s9b$ z%4@w#H12#$5e;t+Kr{Pt#);oC>@j!ZVLT#;SI|qAl+?U23P|X>erHuv|32Q{epDa+ zZV@_Nr@^`SJ{uB6nLTUFD|)&YRNo0}!VNsigB#y;QC9zUi;G)OGQRWZ`f@OHZ>#$s zia79grk_~WZofS*Pl);LpJ(SiEvKx_uw^-r+BM?Jf~g1cW>w`yZBg{%7Td_-61oGw z$&Ye7@1h)MpDso~b*syuv%Zzu)*JJduFLIwlcS>m>kd*x!Lm`;8G-=MzeCd4I^#Uy z_#J2N+#}he8B0OYi@t%UnZwoR7%@LfkIRQG52w54MqJU`(*e&L4suq0fxK%P&lrW9 ztut4j?C7VTW5?CDbCrl97O^dj?Jq0M1^~G#mSc@H;jKJ5#2zLNOA7KyUu-M@h?=Vr zNP3uOv$T&dz6Q7C&;FD951J4^MLf&@r?0!`^=IUm8_v=A&**wch>wDds&tK{X~_Qp D@g3%h literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_pcjr.png b/src/qt/assets/systemicons/ibm_pcjr.png new file mode 100644 index 0000000000000000000000000000000000000000..1f3014bb4fcff0c9b99bf69defee4a80e35b532d GIT binary patch literal 296020 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°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

      E-Tum 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_ps2_m70.png b/src/qt/assets/systemicons/ibm_ps2_m70.png new file mode 100644 index 0000000000000000000000000000000000000000..af433ebb3628e22c29b68ac63388a8270cc1f784 GIT binary patch literal 219165 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
      1?Tf!1C+r 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 z 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%0AT97n9z>v}Jj4WBt!_wUU{DO?u)5+{%D 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 z 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

      NFZ>MObUcv=OeEb-loZ zWI3GnJq6HY&mlYv%3^on5i@qX9X2_;gQix*L)6~mQc4{Xmt`qDO$QOYpSBlYEsE=3 zm%91)rU5wY?>;{s_Ma`w@zEyHmI*l}N+}a5TLwBPd(sniyB$UcHv04^oyOh1arQlb zbi4&4WW{*`+}^WBwbq2S#*B^VT@9OF9~9W7TLYZb$=qsr(|&W=6LNG&jH_DtC>R~f znK``p8-%8MDtKJybA#w%$S_>bFzNs*^W3MJFalyw4agZOmDF~lXPmV}^<*tMOcT_I zKZ(f0cG&MuGw*;;6E!G?+_}&XfAQ&;eJD?Uo-mV3@|reTtNnp{36MdrbrJ{&)Qh8Z zJJQO279$IqJV`s5SEIn8mph{IRN&KOyl;jk2}nw}hgK*0iT#PFnOJNE;`Y5D0SN<1 z?R{iHrfmLVOm*rvw4p=n{PT!a05fBgrbeIxVJQoiWk$-`(V8@b`tNtK z3(8VF-EXeuKUxIUH;1_;?J#GwBvzj0F=$Bs-NO%qzIpD0OFtiwG6~# zKbtnLQYlq0JR)gz4bXX#j1t(@I?yvuYF^5~_~&6ISFNL0@PGgOQv@+}&&S#b6t(GP z4^G!9<+scv9~*%0lmK}9kN?fT{6D^bINm>9mg9DlbAlA2c%Q39Zll|%G<|RVzyep* zF%irrPt+-(znEfwmwe!60Ty?vQvxz&&w}?NqU_Fd;kDhin>CT{L~q&xNFu5gE6BR} zn4?B}LeZrTHZv7M%Lo`W|LdC*t#Fwvjyu9Y3*w-TY2K^wthh1Q{p_1px?8R$TJ7LU zodQqp5T8h=Y4U?dfX z!b)7`)|enjU}_0wqFxky4-HZm14bniUm}U;9yqCvv`Lm6@##k#<81oROKS$IGn!i( ztM8aZmzr51Msk3_a|O`$(Hs!HJN*S&wytjcGcRmSf)qq@MU9Ap7`Y6IDr24;O(G8Y zr$Q5*VVgS&>*_kdtQe z61fdTylN)wWX<#O_kRK7npo7JL1iU1DiSkcHiN1EA*^f6Y>uDAiX}{Rbd!rm4+N zk5-nu8fc21CGUNR3-jP!omLI8yPW1g5tN&vqh3^0kyVPFt6D?1ZceDn2dFC!R##`} zNm}8$kvxrNc3~IMOhkvA(_Kox9v%RHZyJDC-+cY}`t93KbeS(zO5$v@5Ld-lP}F-u zmhG%8!1lugtp>eIx33+i=lbdPB=B-sAQxfBP-lVK}6@T%|1iB?t@hapY_^a6)*lyQmimDnXPHa6m5#M zpcTPL;IU~~jO$dD4W&!>f~VPyF{A9h27$aRD;KoL9#D_iCC`RsM?@BiouqWBi=Ah` zo-=!Du5$!S&Lb&)Xu^v*)h&O|Hz1A7g3b=O#s+q?HKDCl23Gg>ODcAx;Rwy z!jcxdLySDORyzr$N?R{grpw|xU9#!0e(pW>4V9Q?(bPS~ZuB$gQ|`#QEpeN&*lT8D zP$!j)902%0PYiH!t11<+0-Gt}@uMp|xw^x<_c!)=QoHL&v@#K5oh7zA>*9b>y$UEA zOP}V=%YOk%ssvzQfvOolF&Idu73xi^)>Ccp7|gCa674L0cTvG6GtxBKn&(V$Sr^rK zKMlS&7c=u>trlzkdE#fA#F$+t*J^DHi~?_MQ_`nvC7A7U~fxY9^(k2EVFQhBsI2f9;eP zdpjB>QpqOV;0cU3WxF8KYR^j%W~0pvMLAWZf~r9d27MBfH1i;BtNXBaZ9}5L?zJK5 zQHw6cO6y>$b=Ob*>(>TEvozLwHQdn#3Fd4o79oMUysS67QSD(%*HI?`9kgrff*$g= zX_~@~E#($19F0#WYm2F_A|ImFhM5xA_+V3evajDgXMk-%qp?p!GY9I1@#^Xq?`b^W zAXut6HvY(sKMl2p~~UHoyS6_7)9V z$z=-FgbathWA)MbQ-rY(fqktqx?>v2Eu0p+rkOg4rKtb+RAZvK8Z%kZUZ_+BL!xFK zETkwNx}$EwBguB*lnA_KTs^wNcDu##eh*bk5rnH(l3RF-`pT}9W){;q8*+jxgo;h; zv7V6vQCkC9L!#9(m!h%rRYvcqSlkFmMZwzk>y`{SStIU7I}uB}EHkEQgA^f2{y5bq zVKt31Gg7t&;BYu%e>mX&{vPve*L8iIN==D9{zw=dy*65-FDvw~U-Rhdx(>C9oSBsS zfrObKX3)Elne0Mdcd#FsJ^E)e}TO#9n6tYHV+RBl3p*K&BJ<9D8#_op<`$2t+|B;&rO)yeSNa zC?QW%eI3jU%FSljlITVadwm{axbWgJy!LxjWA#@(u+~GqasrsEcDXk-Qa5A?;$NP! zy+-B6W$3fY2h^hl2xTG&C3`liP+qaCc|;8e53{0e4Iwp+PeD#XbC{KNWmXcr0r<2` z?K4F3JOZr@`e+EMu}ZH<&_*!PV?l8um=^Wvw$%j*R3p|5ol9jj%cd1i02hN%YnRZk zV;ZNR#Nip6yCBjmz(9>wf}Y!Q;!n(4Gu7thP99iBaTf^QE;+f`_>?2XtDv-|do zu44$?e*wPo(dwB$sApD_eRw;qr+ut~Y0L=7KI1Yk&}jpe0^VLAPZQ=vFiXKk;m|#| z>D(vyTJSmps$m_N66SfvvPexM?SF>4;HtGhK(DPAX#-FYZuMNT?uUs7Ou8OQ`}>fF zevKSd2;TD-dPHNmSJ5lHfKnPCCJ-khKzI2X58RjWI~h{_GR|cIto;i*vyTH2y-O** zyx;GC`r@-smyZp=cl7o0<;&;$!{Ph;`S{|n9JiEGHm6dCc8ZS0m^L5=#a0)1jBy8 z*lNJh0$=Z`7r8p=ptu*pDUs49$v&_}>*uvT{-o&?yL3jaUiMsF(d;>~XEummFRU#X zsrycEEVQmAMyh7ZJK$jVE7hPX60MC?=>7+Ie>}OvQyI;iK(Qi;1oYrdSbfLsI>?OT z0XxOl0nE+JNj%R%eCjm-Embnk#qI(xK6!?_+dJIe-a<-o>0T?~byBUm??#{%0;t4i zz(FOlm(?ZuDVbV0cC2Owa|KpMqQne zOpQ|zzVGO`VH{AahsuzXb;!lpiF0+~D{9fJo@fq0Dg&5$1DT--ur?`-W_rjt!foOt zAYX~V30K9#Pg2TQ7SkmI5sk`L1ZqH!uBM05^x)A5bRPbps8AIo%Jr}mReMd${v3*_ zIf#%_HfA*e;``A>6|@-1EGB9Wn_>a9`2H5f<6?dN!1h{1OrE4};~GXYD8WAu#6V;1@N7oKUMP0bErZjjfguG1I;A>8k2h+Gt zU&Z2j{Te2gj$A6^I>Xtc+C%EqCbvt<R|Wrk$n2+hq;Y#6tkF3f4!FC!!}I6Q z!6}UzBz^et`<2FsO2prDbxW*|1wG+Sq2sgkpG6I2Lu_4XQPsVSF_0e{fd3-+f4=+i zzy25h;>X8j{@&eje*D?@f3W@055AvYJbRR;%(UC>tk@91DS0}XO@)czQIB0Qs*GAE zr*X4~Y!R;K&>}+48G?Y<8JV5!uO=D1*k0IFQv~A7=8$bgC=jvM>~PEQHvi~pn%b_H zx#rH7CCos~l}*Iiszp)62t^xr_mi?9r3texc8H-EV>ZF`%^q<|(j<(L9S?SfymV^{ zP>n1lveyrv)B>UpKw70K7n&VxbMF(E&qyU1tx=B#SIfM3)U6S*7MD8d$<6FtyrMgd z)ZR-X9FIpFk4Ma9Y5ITi{b(kXGMh|I1%y=j9jb~lFScFureZ0JORc?hMA9e={5Po>!7B9i>1nCim`X;RDtCgPjtbeQE`oNNVH*c?_|)4MuJ&Qn>*2zCzd!+iHjzZh&N~ zokWDp&LZ#0+Qo`3hdnR>dD@|>ScP zQDmRym&NYQoHy8RcbKMWnEvDWt(5@%+Trfb;^u$+;~&+}Hva6_P3I(XC6FL8`BTkI zs7ak}b6tHwP#fktDpd8-XzhD$#n~$x`e2`U&B>e9e*GA)9j+G; z6C?RlCT@yxHnOt&sCbAnmCnZ3*y;09pb*ST(4v?Ny3QJyOG_q$77rw87o<(disT20 z`T;{E;KN)Qe?5d;Lq*WYbA~JsR2GnOHK&j=Bc%zV1*HP~$zo?IfgzZXjon?~6RRD} zVfEW~X33cQZjNKwN3IAOcpS@RR`zgP%T z7^&>0EfT4z07z=_HB?Bv32Ee_O0w!FB*GvU3;38ivlVv3B8@{V9Nb_U@U}AzEqKA= z6fB-_C$655Vu*p~ZyVVz%#=#R zu9APh)JDm;AqB}Tx+sCx8XdK6#2C z9Dj&ke)TnOZ|`w&ap{elHBpg=Q2nr~mA9<}7X^~bIqkEw>zrX4eob7hWW~w9!lwF} z7eP)mtV`Mi&X^A~QZC>rW16;*qFCkyDuOgkrab73u1-?+R^-xnEt|~-%#7dojql_B z{z?x|9c&ezfXtdi2Z)iWtr)CI5;ys0ltfeAE3=lMXM*k zkQW~ASGDMI$0iluW4rW6mReL*nyS7h1okqOK3K*ksZurJOsTSoG3?p9i#te#-d&ec zpzKBjQ<4PA z(M*(#oQS5f=nS0*P4gXEc?oOactcYLZ#Q+%KM`X?jh7M4hCm0|7=kD&1+2-4tqxO% zOft0L%Q9E1YYjewj#5VjoaM>_z; zg3YwU-Qmt+hbNo(jQF--yDWHrcZcKt28ZK}G;MJC=n?L2@16UTe2Vtx?M0?1ph}+& z)<W+7z_MY~fhpyC7Ijy!?A|T<;!uDx>Rz zwohe${R(1DX6*mn%z03Wqji;9c`;JgN_JgIZA4T9S)h9DwQ#3!H?;TR{(cV;YoHQm z_b#ykC!SNz`Q&vD$jTVJrGY8{kaMxf9~*%GpI_6IFP=U7W8lXL zOhe3XbC7DfKGeuh?X>5jBUD?VG6^QNLy_9{mnqqEQ4-9@#ie0B75mMxh@~8Ec&bG# zj8YUqOw=v`jO&4qATGLFS~&4lC4xg_Ii*&#yLF2aRuc_(1jz7y#}MU8)DqWd*bDMQ zU3mNZE?I3L?zpR8PK+t1`nmD2dkykKgHYMs29ekq7djk-@!0mKz1}|4ofFq-I9~IV zGjf>fS0pNodbnN(F=T~DL5*Q0LSglEYd&!;i>rMJsit2~;X`jI0GzNU!+WccRwxE@ zE$ZZnM$*d6oh>zik|0e2c1U^a%~@m;Fy+R=6NMg+&9XT$65MSMhLV+HoCS81E$!IY zhvN~4Wx+Quzr}z0PyZ2r@zcM=_1!(@ViLP~F+?sU?y|0Il1+ZCwtMA_S|fT4rH z`oOT;?J&$X>p;*)OE05&voo4Y}s>>mBMv-FcyEFa+)&R)K`F%Vd01zHMdSu2&Mcg}KbX?3i zJ8HrwujO30QmT!nh^Q$4dQkxWZZ`nWo;`bVbNlY`n>RPRo12^T_{k&w_SLuPFaP2% z=x0Cs8Sd`(U@)d^e%kD8?V^^q?F&UuA(NVk9*OoR#iM45V}QPFZsay0Qg7Ho!vspb zY^5{m30t5>N!1#X5rnVU!xPi0$Z#b!O*xE1teIGRqEjuH&AQ7?cP#hJa@P&=pS8GK zo!h}8$UeR4hgM`jE1`+2fl19A&^ARAoah8NguFHyadg)w;c8*rkuHgYl(Y17Gm~*? z-^8tz$nEeIM7}x=q#kHz@*@ROmadWGA+*LqKh6Y#aD+J#=4Bbu_yP{q(94H&UsptH zBP5DV&c5Hr;5m`FU1NbL(9lr&$|N)LcGIO-uE=dr>^2+Bz4?o0o|~?naIx9deKq-H z8)^~e)_}G+RIc4f6pyNB;mA~P&z;%W=9NakO%58!&a}ynB87`4LD_AK$<}Xqla16D zPJzh?donRDFEf7g>Ir`9w|@t}{gZ!)KmOx?hJW{O|DQ%a_^0AaJ)bXsy$)M*X*Kg6hC!|40{ z9#5Y>#givbFwZkCE-tE*CNtyq_SRJboAb_l(Ri|*6J{i3sOan*rB+M>7N=;BX;`g?@e->W)d6DHhF_-Ga;wR&q=L(6J4#%4C1%Oq&4>T9PV!K zQADtrHkhUzHk*W;H|@OXo8dFYO#SQh*Fi)iB2se7WxL&eYyiHCuj}`(epF=n;j7pC z7q4Ewy12aDWoD+I{`4>C&wu*oI3ADK2D>*kyPQ#$VgWz(o-UnS(oLYy5V|1sa{OMh7-qK-ff6BAv?fplwBps@b56!A zWdY?0o6QbVfaBo^6(j$yT>#hm^PUjcPsnl3q?8QK_6a)(umEs*d5N4&mGh8-?nxQ| z03ZNKL_t)1uPF?2&CTv}McQ-2kYO>h?Dd4RutrhW1jXLpp!8>RZ}|;FE-NutTUeR| z*T*tCf=V?&8#9F5R_ud%D$i9V$NQh__k$Yk~ z{5shH|DA3CmSy?8$o%>B&HHEHeEG}m@BRMo=6Bcc=oi2EIZ7#b{`|QS(=;Kc$#yx# zy88;{3pos!kusm@NRvZY?2@I^c*uI8Yl|B0htWU)rkqTPP>Y@naNAPUZEL-|^$AHR z)lNd)_OG{rRZkaG--t0hF)vNEFqg&ls+*LJDei$R6rKlNx02A{$A~N)EH*vAJVv)5 z>q+n>dQq)Mt=5}5I%aAd0Hy{VD-$UDL|*rcqp1<2^DcL#LWF-9YU1WT)PI)l76%VI zsU{$8@`wgQo#0k;!BHByON{7=w6Vz|4!5usB`cU0oUM3@dcvp``v~k&H>6T!YeIz} zTAcMypoxaY%&yC&CJr(YHom_NPjT%e%1{C}X&R)G za3{b(OE@Jg^Ne{pBIktdb^`#|Znya4lTYybzxzA5y1Kw${p<@oe*6gk;5UC0|MMUH z5njE0hrj-he}PAjo>ZO24iv6b(U2$&(yCdfhn_@CFU4m>!#*a@eCcbT$SjKTkr@ zQ15$BcocY4vNf{r-@nJ3H}7#g9I)M9V45;YnNN2AYc!z$OiC#wrL-{fZA$!>iEjC0 z1MuB^G4qT2!~DJZczisUWpjCTN#DMHt*X$RGR?;Yi8t76H(<>urG=>5)SCQ&ROHa* z$BoQ2I}aS!|U0-BgCv>!A)yU&{cw7^+BxCxd1Js ze)!!rQu!X8XN2=!I2mVUam7KPLM>>x`OL$87NT73_xCpa7T|t9;;^4h+Bwho*{Rb+@7hhw+d89A-fkXxFh2LRRkrmY_PA*C_@ zaq@S}H2D8pBf!;_G^JesZe4imeTP_&^~Js?N;ib6Z_cVL)KQV(H%Ya!2G&WJ#kmCi zY!*z*drDpX>4 z-^hf@U?BYw9j0k|M}(KlGXMGI)y4d=0r(ESN+~~}BHt@Zc_fN0apJ>aPMggom4&fM zJFsSucs{*ra~BoJY+d;@ZEFrR1Ss>|LU*8c1GB;N;e-WFn5GTp!_oI?c34z+KVZ<< z6FL-IiY3^Yue)jU1f`mTEK$@b2!BmWUi;~oM3}(ru5@l*!4VxV4dyLWD*9}aD|-+L zNK?7pREi3Cj_FwBd*9|7)^i+;&0V@x2vsAPy4%(&fND25b>8!n*k(gM5U)i8^9c@G!J7+)-v8N7$oLDb08z~Avnz&{{gyB;1-)TGsGpvD#Kc1@$ zJRC`tkW&OvX=4xgL}&Y1yC)JXtR=V&94MGPY<^;PvY_`0Tr^zIh%VM_F36(EVQ!-^4if&s2GL~h*@i zD!#xd&G+BeFO|~}xgfeaI;g3jSp8h|7FH^cqP-3QkTcg+f+{MnL|u1*ng!9^K1*VO9f8fbucXknLyqExxpk>HwAM$rYw;~v}X1vXQ{yd04-W1153l#nuYPNmI} zaak73^CCEIt1>d^fF5}!M0Hu&%`5rge9LX*Y41d53xoYzvBs$+n-$ z>W2BOJ6GIBI^1lnA!ydJr#fD$rZFwBsAtW$eY_opr85obtyHB8ylDlacKTYn=Z5b6 zpjIq<|M7TU(9W%}GbZXwd+Gf8wRydDn}-u8F#|k`LylypiSL6SN)W3&4(hv;W}#fY z^CS$C9bPt?{a~ZYT>@fEor*?&>d_=Ktn-WpcAk5DzOhu+##dy7wByufe&__y#U|NM`kMU6}rE|#GOM@!u#))pJyt;#4& zwggyEP=eQ^Y!=(4)CNz)Oqe2yTU>^`XhDv+=aft;DGL&5U2ka(pIXE2+QHdv`sdD) zIFcmMp&PXqC^B5vQ3Sz`W<(+>H)HU)9>~{-a5S;EHa}_hV7vIR&!&1^Yb6ugMa}h0 zZG~C8U@{p)r|LC`#wUuX?Kl?$tn=&qM24qSC;kXWD^g5ZrDiYA$y^&7Ck(3wY*hV7 z5v81zSvBV@s=DW#?o!&&#|Gd#_`1Kl`Hk0azI{9~ZBtHZo{wpsXWC2~Y^N>er1cPr zqLEU<)#VjleEI^PeDaAGe}h|DP0B??xO{Yl7oUBKWm)jmS6||8e+yOM_VyOHx3_rr z_ANxDIe7UEcPatV)ym@3txM{J7KbVg$}hVKI=%s@z8-DSY|a#>y0bTPl`c=ftzn%X z*Zu5yOHT9rY!ST832vp~*Yl2E>*A=|Y*3;xpyB&kVIXRONzuWt8MotOOGRMfF~$Ir zSOqYe763K5uW>4(+0X}yR*MGaJ`J&ZABTfPTbkpknuJb*QcfO-{atDX@Z ztuRs-JGI2Wxb1qzk$1(GZfz4(Rpz6`UVXG8z%K%Cm4g zZK#KaX^U&G=SZZacJCcdrI5kf7?CBMG$i9Xl?KFeEvYPJ!F)W{&r`!Q<_wC}oHF%< z7r@NI<`XW&TKR$k3az4ynTb?d;}-PcDu#Z=nCpT zcTxW$mhv~n&OY1B81=%DxSp<%4#tfvjfsi6!xq|d+*i(OqP!_T5S)NPWA z6inML@vo4pHI4@!$cyjSP3GoEB(1b~M=PDSIzpdRjSQG`hQjXA!{LBsncW*-u)Dm% zGDl`dcRedr_I~wOiq#yUgO9sr#aR)_y(cA{0i&Ueb>OgS>$ok`rV=8dS`++Y^3?}g zsdWy0W5E{y*_#nTOM>9~8OuNb)~?uw`bB$vkpDt%A5Jvtf^J}-pc6|c!|mN2E-x?e^!Xr%(Wg{oX7$bH?4> zoy!Ctny6zPx^}@rw_APK-K!nmc+gL~rsR=!>2fV}rNQesQ-~kBYxK;Yy)Jn@)t(ZG z*3W+^PP8sN-2LxSK6J{wr4xJ9hu-_X$>?AI!;MdTR^xls9>1Iz39S$0hl<|A4NZ5j zbgqEp+ym2-_b{n;kZ+fvfKgMu{=NM~6z}hveI2K|hFvej(_d<59?AFAxP`~5XqIeC-OH#9L!pgEHUI@r%0!MqREEIN0px&lPql~ezF z8`kNmgLOC2y+`r9lZTw0-sc}e)cTcWq=jNYK*vEUdGzu;A8Qs&3t&5qGCqq4v>`x< zsHo~Or&Nqg_^|=_FaEl?y!z!l&o5QwZO&<*Qj){|fJDhJ`XGT2mST37SC?0~xVSJP z;8H-8+$Ivp(*}>9JjFC++~42fI3FPjJbU&DE-o%`eSM8LZ(ae*f~QZPBBg};yF0vn z`_{rpa<2%`v)y@5oLhTptI~tEp6!2&PkMA>xmgd*m_w++dd)qLPax>i!?+Jf)nPh7 zH~G*Y_U#zMG{&L!kX{ctceHya=*iGuoV%I(Kf@@cm-E#9+X|W<3+#Gg=>NW-q+~!3 zdRVhZc+R0JCx^-dQ`_maab}{S@$>3m%SpDoo@%Jia}Q8Sqo+*nE^KD7YVPo1C*cio zuoCjdRe$-=PFP2@<6I+k?(;*JTv?@$(hl#C?p9=^%#|pbm;gaRzP`=2y9n|$A?1ww zyZ5-bciLtl`y$pcy@Q5yVOdp<3}7>DDrpV~ zXT($Q{r(>6RT+WMEK8~6;2_?mlv@K;pO02(o_I|3qi(q#q*+jLxv`8p_-JrAerNvx z_D4~Ha&e!MGfTDLC&c6*XV}R_Ll53d(YUGT8Pp9!#IH#>WiZ*Qrekc^)VwVIn$Qu0 z^-KdmC!YzKeY57Ag_(~;bPwRCmzPhLj}5?gf&kFr-~7qHd?h09Qp$SeoG1T;IAvj2b6`$Wrwt z55<|6rP?sh%Z&Z;IGE@3Br<|l32UNMQxL<;nVi$Zi7Saz<2{N-$eS=xsZzRi>~7C< z$$8^G6mI-Q$&tI5_T}XBuC+P5LZm>QpENm1`EZyqWp)Yc`9L1?bm+M+p#ty#9HwgA z75(vG_SKQ_bhX0Ns=9G5L}lhtC0>T)6WXl5ElOF?F^T)*s5U%3$@t9ZGWHL;CfST< zOWboySuoEta@R;xhpe3+isB(SBcEir_b>Gv(K=Zw&we+!24IP@%G(2{Koe`2eIPj z=Dm^22)MY|;o|BNd75f`@72{6vcvzo-R|VFd+0FkHN18mrRp|y+61)S6M1B6Pjm}M zE9TC{Z1D3=Yh#KJ9{w!?Tuu(2v#>T1;#}$pF;UddO?M+Pjl04swS$j6`ns{`_x$IK zP)>`T4ikIqi~9`wMn-dioJyx4I7JEKv-(h>UaKb7k*g2AhTg%gJ)WFxD0-y?peH-& zwbwa%(w9%7>)+e+CgQQjCZH)1g0XTYCl86 z+Q_IpE{F7xqj|CLAuyY=XTJw?cKS@HCbSha?OTgTUG(J1u!wdBylDIT$ioPG@rWM> z+GiPoO3>t_M)fpJMh*V~fjN5tDyt^EH69&9t_E;zrm0Gl_xnBOG_{5)Tpzn@o3$ZG zwP;sTa`9O6hF12CLL)Xde+SidkuA15a{q{MOjU8ElE8(@I)H(75TSw=0MsFT>7qW4B#Gw0MGqz8m zVVvxBV}iEdK`U5$&8i)dg@T%BOPZ9>zNy>wq7+w{MN`DK8!*M+aW z2XeO1J%m(@4GLC`g@Re?jodWnTn~)C;p$g8Yx3c_iQ=I~;QaGje-?UTr`n?o@g8d@ z8C`$Ar;jx@P2tPXOD6+e8KzZ)FtO>UgREG8rWPhSDgNv0=OGTqaE+nK-P)92y4Ral zKf~TATWobH#gOmfpO;Ei%apQ=(zsrFCW@*-SG9WBMK+6AoNo96fDP&vM+hQZs=-Kt zoHAsYvCIo{;(DEPr$P{SquXpYMrfvyKUD7}pia+y2-5BCE$;8`kf#arJVT10c-BWC zC*f=w_Ts_c3ES_u&noQAG@y53m}7=QV=&Zd2$$OLX7!au@@YTSRSSWu%B4d10W7fk z>Ser6ik_;2sI!NTe-BfhYG>_s%;ETUPJyFAEYU_VT_d%l8PmW|impJJc@dF4Gv9DC z)A-l`d>3ELEUK!^tW!?1%mq0mA~NQG-fb##bv_=E65%&~@O?ab@&woKZ}E$te}St< zkMR7(XHFney!iA*O^YHTyN|Rv+^oAy|L^Lyy_->RS^amGr}A=zoTE)Jc`jKF{-?-9y}s^>b{mmAFeQc-M%r$0I37lh11W&T zteYKmDDG}Zf>uUQ^MuNg@tDv4!F47nIX{rfScde=tae4jv7ZIS0wY%i zkxmLE4GN2tP9vk&&DMurqaEfRReRDXdNbiV{Xl^GVSChuw{^?8Y1^i|kP&K!vNVUZ zD*MAZ-o$v_HV9o$cB~JhPB>{E?dM8I;-ZsPNF#!t51#_iob2qrxae|}5LE7>k&l##p z*1aX{5BHu(mRyn~fbY!@`#r9&uknkYe}P9&9^uiGXZYa{e}Hekd5O1g-{9i%0vFpY z-oJm3|Bt;l>y>27&cnX7_KwIrQw{gt9&XR-W;aEPq(yNs3CL{9Fa&`wf+fSS9{gfI z`9TK!OAPoY7_b2wum!_}4O;>&aIpD6sYTPI)#&MVH+ko(I;ZNKlbI2FujPlm_7oXe zw*~j5*+QL0q3hO}G9z~Ez1FwB;r{jo2#UeEVlf(H!2VuwcXx+rf572zC<_h|jrVgU zW97rTLPkq?R~BTydXQ*m^mFXemta9P6~mg0k5?hp7@<96{mTHy+umP9TkdZ*y^wZp$2N>aS?yAgqz`lkaZIkB|`SL-~uB%!rN zL|sn9N*BB&IQB(CPG(HdZ1OpmQdriFP>b#IvV$i2$T3=KwI~;r+^hv^5pU~~sT4?{ z-r%Jr=dDq(`b>6Ny$FAYtivA0A$6gM2%*N(<^Zc<+#p6REOK9DfGrU>&+2Pop0Cq5j*vKG zI_xmdDZEBS?3s6fBsr(5z{c_L#9+r}2~5qJt0RVVU^j%zqAtJ+?_^EVSsR3CB*k7W zkbDm$M&m_jQAT7>1GXXyx(vvYWT9?cuX&ykECsb)S5ab0>y%!CEFCAyI0z! z7I&Bqc>44SVhnh2{}Ajv9zJ>vXWKIzrWtoHZgHzAB6u?n@WTKV!QpV99#U0YUq36* z(tfwY-R&Kw!&F@N5^_qNVN2VU_V6?eK5h>PUTlh|*!QOx{EBsB8+4HGOGuRqoje_N z@3r$?DKI3vWi2~#>RrQ#u#`crcZ9Us-5-xOXmu8NN{O-dxt3vGyBFgCG&AmXbY%g{ zHv0M{^uOdotR0Y*r;zVwvnG^Il1xwYpI>&btGD_Qf8_|-&`OvCEg01mZJ?t9ah>Dv zBOAJu@r5>qGfO1qSiZWHZBf%j!#eh;$ur+^bDx`7Wpi->h?3mTI(C>tAX`_>S%OP! zj<$@Wp%T89Bux&&_kOs4BR* zeuk${J~VZ~0PxVrI-|j7=}>2O2w^UxJmGz_G(TACduw^O$2y z9^HfMHUj4yLYVOU<{In(=NZqQJjH{nhj{(9*YM=&GrafSyBJ50aU38qU^gGiW+p*! zm=1_xf^#0z;ecn)p5f-%4d!VsHoyc1M9U_!+~iv=v&dRU%SQyVQyTF#vRg(5{uPOo zs|3JS=2kl%DF^?NlwJy6+39qsIqW6Y9D;V!u4F~&NP+D^zg~4?H4b%IX|F-d?LoZs zL`dc`*|dbqn{CmI+HEclWU1DxYa@wMT#jWoQCQ+|{XxdAu<}Jsc4v#N-gz zNDuR2=6NWnPmB@6a0cgmjo~f`V&nLj$$wU=OqN#yC~j`9@%;HU96M~z2E=$Mv<_8) z#8A>M6EC4EH;5Syt~?70wLKM`VNNP~T!G><3RMop!uU@lKX$&c*6k&YObq8eBm#DNlUhe2U4yc#QeN;!C51!M9a+Yx(qgnZVvhqpq2Q8Yb-oTcAghhJH z3DKgh?_BJFh3vG2{Kbf3f@lOcX(Dq)1R;d9o)<I%2Fw-~ph-G7I17z}Mpc zoi1`-+ZdD>5rn8YK~x|y**mK;L>U?#6ayS>0rHT@sc}$%S-MeOR9Wy23>k5*kRr!% z#MRYRl4)yO*lIy>vYb{#FpeWO0@a)+Qm_4@JGcXa} zmw;h#P(u2D0EcNVjNs`oi)e8e?gvxB~+ z;}+BodAaE>M+e8=`+e8RD_v9V#@7J;Zu=vQWsZ%Qj=NyW(Y&f1(w(hbW0aolpMB(;U!4tLI?SW!z*{}CVrlQ% zDipHoA?0Y`^5492{f@^8c~f6QqfRRlj(=WVcY5Nm)&(1aike^@3Bw9sq`#k;eck%h zcif4Rea(w|neRdRib|ZzaJpKDC=2C8^@GoemPyW6uO*p9a`)aeFAn2IFv`D$X-cVo zA>j7z7N7deoA~T!KZ8I1<3E8K>pw_@b3-cnS{a@lJc=5)qtbXQm_|?xJ&PiUG5vY? z@F5;Oz69|Mw+&FbGlqXvB4h;tq2)N3`a#JKa)w4gG=)hM55~2sqo5+;Gt@^0TM?Lwje%(h=WECki)#6`uRV4j!kTcjVaTGkga#`?(RTJ z7{{^3_Qsf86Q#;kopab9_IUC98ZpF#ayXZ+$7-I-k*r#XNSQeh^S$@}*)aI`o<4p0 z{4eb&{U?_MINC;+60lN}DrU=@U8l^2%OGm!J)8n}w|BU?xdpRNau0*lqNJ|C`@t4T zK#tH0VNOVcbvRKK?7T@@lKWQFl%X9-EC|kW#EDO6ywl;KQcXejs~@no7XQ zhhdwpMc~e2GaZNwl~{>f-2j+d{CC@SBdc?fR*)V$KCuy+a*Q zFKMzCNYui8trUE$H4^!#xHwKv%X}SGY2bP7Eto9?sOH3@<6Ru9K}@f1k;&8~={W*i zejnk0qEn}A;A4^8)&a*jC#8U9w9g29oDvho0tuAu7*?0k{FERd_{|1$2$*ETZVGt# z_znE^zwyg>^6U=Zf9t!5BH$6`S)d&Ugfj1e$l`biYD7rMcFr~eN&uvXb0cr8k1cs^AVh0=H-;ruGESj1rH8PnwYbu zr3Dy41l(Bow)Vss?&O$fgIwTh6|F%eB#l{(miLog3scn;8-p4uolnsvBXt-tYUzZt zDgq$HhRK^#$4WxtO6OlYi6jRSRU>=p!m73s1jX{(nVa-Nt%S8?K4WmFXn74x)qJEh z{!)__UA9kcO-DG-)Z_8tSGXTphMA6u?32XA5JdBSuQsMxrBd=Eh`@QoVKA|nro1q) zn?f#HVqHc$asfy=4Uc_Vmx9Kv(7acujzaQIot~p!O;Z&v`F?RN+Hyf9wLsC%D>hv> zr+^?7&Z5R7V;!8wzz*~Dq9QP+{1B32`71GkBn2@s4{&TGKPV&y0IBd#zrR`ni)2SY z2O%Jk0DgmmFz$8%U-}8H6P12E}st)}E)41sf9JhXIFaN>WJk3Gssm z4-6qeh+>9IX<(E0!_31_BQD3NAfF03c0)QxED%bJm`O+lWtuq&ymKmZh{MIj-tq8! zyFGu$doQmFfFJV*QF2@&VhnzhOdE^@=DkM&$u^$3 zlTX!Ra&;X18H5P?>2PG2k%(dGIgK%<4U(zIigM6Ia`dnn7SkdEwP#tkQkyJIi$-R0 z=FBB(U0*T(NeHE5*Knn^bfHO3Gp8bANQg)#2<1adqLxNAKPXH70fEf+6g^R^u*0Q6 z5-KUOlWs}sO0uyCn_kzk2eX6sDcW@oQn>~VKY)~z>zG01(GZ%98&zof%2vuGh_j8bJd{rUeDyPh( zs{MXn;MZxIO_M#Kx1&afh#hfdfKJAmy4zHoc%PoNd72YRuHm2%C)6(q`HjWzybbNG$$G7C?bwYr@62dAqb_l=e&m~QoxLNI6J$*r#}5@TwXoEet&@D0V2ug zLsc>OgiNMqSq%CYNKU5B9u1s|Rbo!X4H}m^0u&J%CrpPu=6R3reD6E(LxA599zTA7 z51%~+k;6PCBj`GC#&1-|{=xABku(SLQjM!XLE7!ssQ*HH~irE&gE8B#3>Y(ZDzwZ{bSlxIfbw+{oD)8 z)oh5>@84#n0Jh^Mb+j4wwbvf=p^(3C>3%6vJDUC&s0%l~ zmcVDv4O2;CtQ)#TtFl9ksUu8T?&-cb=aL1p-gs0R>@Lk~;TSIaor@_7tOJiR zmY?sOIfA)tsv||tscnWi)q|@RV--Fus*hYeG}nmR`Efop<(S-9oz(!+smvYIHPJdE zX=P5LcBncem6547tTSotT-Az)sIZ9abkNncz{M2DnZ0h5h|pLAryERQa;2D*h8&U# zII=<^C2pp18kN^3qQz}9uk&#ni#0Fvki0t%vt4t2se(eg5F0d(gj$Tc((@H<4K&<} z<~ru=dEy40fo9mEoA=5Ia_O3NGALW@2B=1yoo(Sgmz!))%jJvyg{GGr3b^Jen`dvJG_7420_^V(0X?*r`Z(_SWOC!~Iz&Lt9A`bgq zLO_JzhqF{zMn;$khdnS1=XmnL4*%pI|8x9{Z(QR)`Uk&(Pk!>#_`To#ef-?deHG)G zgZG<+zJj3Ypz00zu!1))y%iOZ7PZ%cNUKTGcQ_mnLg>iDZPDJ6fMblNq`;BuVzq0o zxd*fu+aYDI2!H_KUPNy0o;|<+%Y2Uh1gijC05B6#NT@9p`^U}%!pJ5fVlu6D;#J8v zSL!St^VcR%Z8HYqh?|=i`2P2Qh$kOD#ryAn0OA4DAz;oGq@`Phn2086G*KC=%w(xu z9*zm)cGD!VtvK6h)d06d$ZRp3I+o{!Ak%lGwn+%OnJwoH+=x5MntT-&IR>Tc%j)As zE~ZU5I4kwK@(dlb`5YjP8Y)wqIwY?gqFK^u(XKHB5HrScM4Vf9IPN=90)nQEJ!y6U zM4P#59SdZlQs)TP9MTybLQ}-Fmc=5AaGfUeJVN1zvAH+BgIf+K4hKAZ z_zehqJZ@4FaAZ!U~l3g2X1i-sdp<&|m8lD*dmjiD5;%$%I;*ujw^#2L4@*SNeo z!`FY~*C2Yp^@|S>pYeG3=n?+f z&;Att*Z=Lm#XtSu{~7-7-}^fDhx_z=03aG5@Q9L?RRN?9uCd%*C$4JAtIXru7$Xk* zeX?dY4Sy_S&HiUFGp1=O=-$%uw{rnJGP2T+7sKp`h;*K3^~1mb;;RDS$Ik(H0^kLJ zJu`=47*tiwmz#^ec$y~5)@CSI_p&5uliKO!YLZ>u@HG}k!p56EAGWH% zEH{BML``Obap*X_KaBPH74$2UOl@94FVy++Al)bsAe`M8(6o zr4ZQdb_v0-bxES>FtNrw8(?L4o|uyNy>Tnu)+$mbW@@k%CN05A%dWDu`qrJ9gTR1fbDjR!(or@ zcErWSIaCFkanm&}75XMa3+t$isL$xAYh4j#MwAJDU@II`WbyXQt@%rm;K!QVz1I{mAN1O-z&hPwR_}$<6J^a1D`MOurzwf+!m1lF~S5Iv+Re>`@5Gvz} zC|bTY!|s`#Qe|XDP|}{aRx4cY%r;!chYdz8h03BhA~Ve?hk0|zw$5x>B3U1*)`ib3 zTZ_oRu7g%f-sJz`61!Wo%EN(J!Q{;9G|fh{(;{i+05meQPCK3mRHa)cEk#P}Sa>>K zxBq+urI~NmluOJM54&e|)>}#tsTy~M!czm?XA9dr+-ahc^Zn2=Kd$z{QKm{7%t{Uo z>98ch<;BBv-Ll_#6eHuM-#gFg@O5q|8gs!6iP0=lx$5m%G0$RZnSjG#F6hBLhor!< z$(A2Hw%ZL}d+iav@|7>+^Pm4bE-o&x+wCyVQ+ZDzgq#TTQpsW`CA5dQRTZF(me$J2 zNMjx;qpcQEV3Oi^s46w>&=UU2Bu4~;^NRzi<;JAz;k_$AJA1-sR7E7En08jwg>Ruv zK$j(Dmc1(P8&Z&g7y{<$fb&fvAhQFABc4Bh51;+QC-M5HzK#$lY&MMNx7XP1Co>DW zf(Wo3N6cZyICxy&JjLbZ8K%R8hmRiPGCag?cYtcZ+4d5OGlZbH-yHxE?Dr8&Bg7zl ziG+Xt&%TM@`XB#0{0INwAL3_!{ww&WzxUe!MZEULBaFjiJbtvpZ~yim;@|%d|Be+e z4x)^x41u?ifE3~=t))v+<&?C08e8!>&vSiF7Kc8TXi_welI6Q(;;Um<8oJhraJe2; z3g;jYQHU{4G5fE-DgZu?5B)$@ui5cVHO9kXujl9Inj(Q?Wig9(k`!M6c(m=Fbc{`@(nX~y~aS?XG+2(^?ymmyixyNY#iIhUM7SJUc>r7&D~fNImF zCuV9kJOYS(BcqDteO74Osv1rmHAy;*w`lzCNv%_CQTv9tN9KeU zRZ`X7c*3X8C-P%Dz`|md&Rwi|u@ued0uvk$>9uQs;~{Nqt&)PX4QqmJb61a6u+$KM zN)gaPeRf(hfN{{yY-L&Dw=m(+Aw+;!w=EH+t5!si@{x=WU?b0E*E$74lggM0d{VDF z6IY2F2*N09I=|k*pFuPxpL;88HRb{<&FNVICt4u;EMEiC!9NTR&J9qF2tkZz;OubM zCclE=eF}W>Uf_L12y=7o)aKDrcoR>aJi#vh|H9`mY#a{zgYjU1X_|_T`{dKV zL2HobNzTw@h&C^EeXMKn*TG zV0*R!aV4A)F~(tNyzlLMHQo0rpOq%2SWF~{1{q3gD#US_21*K{oHTj z=YQ_YAa)ps5w~~G5at8M%@%+2Z~i9!r~l>m@$dY**EqYlM1V&Sf=KH2nUblGsAB1) zue4qi>H-xAAz-`RCR9xUpG~|(yPzWx#XL>PvC%5t)W}s-b1mAuX`mu$`3L}RMdbSW z$+P)Y0r2r@0bZ!a+hG_cW*0*ULPU|7T#S)2be!SqHJel}(w^jq)yk^!CY%_+Lo)P` z%(^FRw;Rl}BngdG^p3dBn~VSmR6<*8b=#Ba(n5?eHXZ2koU6!MyvJsX1jV6>XQ+aJfrP5VS^<#mhNZ`1&FatYLqS-IL)!sH_su> zoW)E{lKwjx^TePaFZT7vxdEb@4ynfVt5~**Hm-%K;6lsbH*W{+2%OUMFwn;^uQ}Uk z@jmcy10_O}2tur8Ps;$6)&;Rd$ts({i#GG`stgE0n(u8m8AkFeqXK42Cv1(L9BSNd zCg(NiP_}VJLa0JiggHqA3C>V1LZpz~+{A*W>>k9BiXY}Q%Z?HdW3U3j+j?-gxw*l& zzx^GIAqAYh(R4)X3cBos3;f?^mPNCRS+z!c$}#~ZJI3ZMFv!#ENk4qyA)&)|(uT$?f`#hXuuBnAHD zC*Q>V{SMD>?y=v`069$49=ErI>+2ib-QGbpkrgkmUL->uO=F9}1NZkY@U3sZg|~ii zkEhpvfVcmP{~7mtAcApzagMis@cU3bhlIy?`s_n|D^(qWPoSm9BQI4bGS-! z(F%wYAmZR$-NdqES}W;mH^yo-6d`u4wfKPd9kOI{PJ_g>k}@)xS}hQw%`shhz`XbH zLplUw)8Q8{?%bU*!I=hK6o@gDQF2Sfgz+A796?(wEp3RCUOg7*y*-p#^#^CTSLcqE zE^#i!Ti3mEB2N}4NGcXE4OgIQ@$$XTzcb&T5?7kz2r~Lrq)uwS>={MqWt@deB7jIR zZUDg_F8oE+Ke`#WVM*`c972VjLF#G(GuhYfFG#gPiO=+PyH;W5U|jBzsph}a!=I6r?4uf6u!G}_~#T(=OC zTFE(w!(k7oz>P47Uh$6%1p@U|d)X1q%|DD$`{7atj( zcFvWJx(_{}M$26X5zAndzGCe|e<}p7CDt=1_c;(EtrJ)-q!EA+vOAK}^At;BCs zqaaa30_51fSsE=;D=BKbi4sxTTz8E<_n}jINFPgDQdzpuf*e7PEqMvh#y_HepVDj$|1^BauA7DO9dTy62CFMl4N`Sh0%^$hoS4!18H z!o&zcQc|MZV4h}32pIh4B>AuE`4>^r(TvQBO!#z=S{@b5R){U2eIvngM=o6B09bP- zL=;6ddhg>JYWk`G__0X=Sw%!lV;(~Y>YT$c5@4;K001BWNkl13;Ei-vO5`-_ip9Av&2Bk&yUI1$j2IzX?B=c33P&l zdQfl$;};Kgnq}5V+M16ZNsF`+i?q3HluSk4VZ}gu@T19cM@0do%T~}r3hYKNs5ZVJ zqyxT7kZbZFjF8#RB&&=vcP`S9JIsBsJJihhMSADQ>Z+Ha{M?D6xHDE>lobfs$2`N@ zLWK~=g-8l>Ov;hBO@@2SWHdH1VCz&#izLB{xV3JNwODF2*jau^gu~&0oP?KoJ8N>S zwL@TOW!-M@K_cdM)Mn&*0T4wKHJiDjHd5UsHKsAfT8w*JXhjGdv>Y5UM$GdJ9u&jb z7V$8dZ-pTYjxkLEcegv--rhk~adviI(42N3NE{fT1Vgpl83h!zpmWY)^h1(5TKE3` z`|skNcfJXUKLpb~g5?$59}ZBBxO#Ab7ccJNJtKreQr(au&NG}#sLedjI6J?B5CQ5j z4rdts);KAI%{YKPu-Ob4hD^Zra2Vj+2vNmue~Y`_HNYb-&abfF2fX*e_wm8g_b|HG z0lW@RZ^F4ts0`Te_h8y$7|sxtQtUe^^d)qn&Z>UXl)1*y)vc z({>tK>`qY(OF~Hc*UZXxZd{EvUE93cKP9KUk(w?0=Cx?qW5%(`=BVkektzmKMTDO8 z7|0!jXAebey5@!cwF}NkQ1FrL(8x2&y@^q&wzaY9ZBUNo^;xU-GdXjOhFga=)CCR^ z*28FGliH|9>4pk!V8P|}l9f)NiyhA8(n2q+ivXilPKpIXNzD3oMeF(B{z=_s>li8J z09mfXJRi*+&2ny@*TIqZ!-D(JNS*5Dxr`cKyhkyG3ZpU8iHRJSI&7CZQqy5C^W0B$ zT*n-M{yxQdN(zf&22`1=SrL@X{mJ|yv_r&jf@rpkPR^s9%<$jsc6hLTgsaO-On$~; zzsHLg_qe)xh|9|dAfm(xFt~ra-6VIxC@I*CUA<<^)x59?TvFpSILFxd4Q^lD;;`Ri z+V2rV#KYIG@N2*Ns~E?h!e)FAo6Ur~-5%pO0Or8BJM3|BafTQpZk}J`{Ok;Kn6bZ4 zUpGxNqDDX+?sf;vGY}(T+JzK>%#8cpJ$AcWsLr_G-4|ENd5Q?LVw$IfV6b40J3M=O z1Hl1z|MwG&<2iPB9;5#(KL43t!dJigD|r0)4QNyx4pYf_VLw1ZsHo0LTIh1kh)Cg+ zEcst+#NIYeeEHnuXKgtuSbo^P5axM4%=3IVjKglb-Mmr(d~7d%@D}NrL^0F6Uu1miVP$i@5K zs7uxS=9uJ|J?TZIImj9&`x+a#nYE{e$#r9n?i?wdK<>ONqqvwOmvEiR%x*2Ct2vN% zg<`!XsK!mG9`_0$hScRMr;Zm5te&;!0tK;{Db?|&Qv-bR=9F!Ab1B5hlqnzTIo!w4 z8OoVa5Fq9P&>_XLP)Vq33$(UKOPirD>m(nn%+wVH)wWs}Yu30WlAP;ArK}UC#Qp|J zA$C>82rcVgoBK&Y$U1nJDrrjy2$szucF%*PR5)kE+Za>QpKmR#m8%!*;{JEfSGFKm zfdt^eg9iw6#Iq;Y7={7!6flnG7{?Lb4@R6*Y&I8ZzHIYG31>JvA3R>$zway5S58noKE3i?j1O?2A3@AcSakdE?tiCcUUb33Y4AyapeXTaL zd@?e3$qxVs8j`e&n$BDETzIL0ZH#HkOx%nTm1>8#oO3Vv2yOKY)ucMe9s&(}nowhg zlPObUk-O;P+J9fpw1I^eI03!$fOWahlf)qinVLD8hrWrLDidMV4kKh9xaWcqAv(;IT3SyU(JSeDCezsdPo+aYZ=1#QZ zt30*{As`~L&R>7yb^P%k{RzJJ?eF0$U->FR5RBut@O1Y3J?`)CvE6J7&mzV&RvgA5 znLJrMuv#Elk;wLj_@#LWA(SkEVaQte8G}E=x4!jleBp~Y@gn6VSE+a2)s+aKW1e)wky0T_o1oNX@<;sKir59WZ22j{qa@ERUoy$L^fytuhT z*n5yZOgsew?sq##WNbEDd(Np}yNhO|=MOmpTRZ6lbDWp18aT&%pAP; zdm_FWhRyr$y!+?3f9cQApX34{Gj^SKwy8#w&$zxrf_AL*ZsyE+w!9>{rGBaNBDau~ z9EOwso?~;f9-hz!xtI(QYtVf*@}XkvBh8$*g}0W905&U9;zqKl3X+;7uV|d!G|e^J z$yM=z7X=u_9+%1DPc?<>WMG`KWU37$%%`#iDQSK%xMsuW=*}dGvDe#;!KtVT%3%ao z?uAHu2yi+4O9!fG#tPDSC!ojydkbSN*Sm~fO4=V4jWse40b2H5smVs>(^s7x^M6xA zvdbnru<=6cNY=_R^VLd`uT+vKdjcADPXRtl5W0+5TL<*)oKrg@Kt4kskZ>J#uxB^)UsZj6D?@#x{FG3^y` zcKFg4e+m~Dmw5Nx_wnSzxA5ste-7uLe1Pe&!*mE3h7qG5;pratw}KBoc#6$%z?*Ll z*w6QP|E+IAbjE{6U&hye<1-eL7IA*I!9F@nlfyIx5JilB1l)))&0u$Y|J!GyeFmrr zZQE|Q7{?JV%keT=h28^1MbaK^(aTBMEPzw0& zDgZuK6@ar!)x*1_^>jRR(lIU;yjbU@3l$hyZKkT!K)FaGhLo_SmH|&@w2@}!A_9p( z5F_o7OUYSH2N4=i^tRG)U?4`YcPPH{AK6v49tLcOTw=-RaYbQl+diBRCMA?&M2O%( z#s6O%$?CFC)CWKsFNk;&eu`j$ku{UYjCvq;SXxKzmPG zB&bycbi}-T%u33%uR%);-+5Vt^1Y|{G^Y@d?seqn*^o7ANQX%xD~Qp)rl5QIy+kA% z=OMWgQ4ItmF1DIbvrG;lfIS!T;yllI^ym?`+b#C{eJT=S#CE$)siiSux4TCOGp-(7 zB@-o!{zjvCkq{fpZ0=0B^4Ke?BF+&K)4Fuy2#~{JQn24(@NeMa>;Khq;9O8t|GCU}L@t1xRL1sil=R_6LVZ!IXU<`Xwym%h5*<1k#2*E)j z@ZiBEe(9IKjOh?kGQ(%D}Av(p}D@25OF80w`QcI4Dv~!6@krnCDMvnr85QK>4aUA!j zNUX04fFIMxusOqg^8}+N$1-So7{_riQqi3B`VHiJEKnn;qyQFY5O$&intX@J41m&q z4>pr^gHLn2`2ga2(iFhxVYkRqB?z%pY@grYLO$OJFc|QCrwuOxAS;j@ArTrg+uw*><$qa4;IfTy?FdQx16^W2 zDqym_sB9!;QLLq`DA0lyMltLFA;)Qhi7^#^nLW>hfgOTM>L^;Lq;5oGpO;vm=r-{% z9rRR~>Y0JR;z*XTlsOcAdhRAe2&uC*$(GngnGZMDI55g0?;sZ%y_E8p0NFBYa;Q-% zsHqmD%n+s0F{=oM!6AkKmAM#0b#cU?myA5Ps9I2p6-~b*rtuaN;2DWGA7&s%JUC0N z?{uK1^#YCMpchTAk6|)D3z{Nk49)?>m}5*uo8)!kAW?96@c_fHDbRk5g3HUxl5w!x z?I9AAQIQo0-aDM1Z{Y_*h=-Kg$Vt(pQ41;os_PP_>Tw{rK{P@E91dGVcaGh( z!_8f^OY@+aduRTHfarl0lF}7Xhrm$G2pW>xAW~W+`^sGkF=9F-m&e?cj3Z;SAzYl> zgQY--6O;ljE*%_?An}NifWUw_c((;~gBa3CRw58I&`!@xQNw^V!)#{Z3yajO=U+!m%d=J{fCdLf zte*H}vZwYyZRWnUlQNSYa$VBj5&_5?XdAKHeO)VcG&ncI(`q_cHF&FqvBc~}b8)fk z!n^L5D!GcAnADz`tkq(ebM!DZ!7Al=Z`v8P4L8Lh^9tFgWvR0Qv9W9>P46vPF~3}e zaSBn%?}4cnNiSvkTli5S12#G1&ZK=APE;ry2mvc<4!d6frLd}oadH$s(iTRlC)62K z-Uqc%F;T}SSwg1?>oQB(X7sQ`t>}a;>hf!r@dlD~U2)FW7~0u{B3h{BPS@9QUZ1}Bq^wwfeBaP9b)*HZ)-h5_g2=a_?F zo+n70arNLbdH?(KWKKm1v5XRvYhjco^-oHH%;3f**hV&u%(xnN zv9%dBG4%l?J^No5<6AY;r&vugTgA&l!q+8r7Ac>U21t;sh+nquRMX00?+{fI!1*I^ zS6&qW{~tb5#R^GG&7p+Nv>xJmQd-v>M8@71ECV8>u+g1C=91wfbqQYN#ez_Qb_Bj- z=IL?(yg)<0c6w@aZGUc$3Q%X}lApQGDpQY%XiM0vSOJT!ZsMgAYNTOpWGDx1%TI%ZqYrU%k4)|y#;8&+Rgk0p`OvpOso3bzPd#&I3KDGlMV}xR8G@uMmZq!B#4dtI@yeaBEX^Wq{JGU zjM@~^t8m?4N-!CUG1>Z_zF4PJC4k+YqS6$k)Od2}!jZJ`j8I9wBss#HYLs?DL+d$_ z$83Wi5JM2svNgRb06w-6z~Cc*NJMcQlVxd&5*?e!UvzWH<;g=?-qYCkW@27Je48#M z9r|3&WNg!nG5L-Yw9{F)bJ8Wde+ii`UC);6^mbEj=T~JTZ#PCJBLtp4ELNGVOUE_s zRS@|oOPq+s;e?tLoSFV)EasYG*2lY6BOPNjgH|8(QwLuk%ZnQ9^O8fcW&5t2Y$gF) zH~LtccOPky7qjzad}}JC8U+O}@42jc1S}N?$0$+bu4tW(Wd23N$6M3wSL31M^>NB= zZ>@-}--GTMDRcQo9+>_;7EVGnyU7Iw|42p7@|v`VqjNo~#q1igp%n%W9gjqF1aOp8 zycLxWHz)-iJ(Kx&gb=Xb?{Ri^2FC;D`G6oZR3rT0%{L&81}-ixEaE$5C5+=(xB#sj zwck%FF|rA4)dw=UX3jxvF;kXIYRvsQiqQ)5QevwIO{2ar$l%+?$&+d((`7c|!8 zPLdQkG$Ti27gS17yhMummDVv^i*mlq^WhY#H%(LLl-WMa-TGf7d@gN*+X9tVNT|(g zAyU9GOHd6&6zLTL@NpLaV^Gz5B06~QBQs-~Ci33F<@`}l>4I9X{Ux&(y*FK5FG{7& zBmf!}0}r5>4p>5tT1{TwuJylflE@&Yh1Z5Occf?4qlGLhgtU{JZq~sXk;oeis!P~+ zfevIwY@2eIVC~pJ$jgzy5}BZi=+`b!`v8}Sg@c|dSh*bD#I#U7(@PH|)*~q42=;zC z8no!h^K4J6HviOErraBwJe1lU)PsI-OG;URDq*n*I&c}Ol)+r zL?|+sp}C)HW=Bgx;L8r=`u>hbS6Q2%$y!~ZxAKgxAr3El4IQM*iQl793ZJAPBS53t z;SM^}rnAkwd(J$PyhhBdCpV{sPZJf_&z|Ap{2b1CjDv?G!qvqk2InwO6Jm&n(~Pt2 znX%532g2Yti6axFE4f=PL<)sM<3)jD|Lwhp0gB(D)dmq-Ae4Ia{`BN?*%tYAt=6KtZGwXNB6v3>euiyI zS>Tn&Tn=@gVk7lssjO#)cP_0Ak?Jdv)f%AY^(!DMq?jDs&a4N0=~Y<h|1+{eK zJlV>(e3pg1GH`Na_A*6)Xit{Q&Xy_oi;%OEDyfV?v_x!B2(7LBrKZpcd?p6_^#3D9 zJbn5E4<0;#_oML{X1xB!>xeO8nkL-e-6PDCkpffPvWhm!p}Yt2Vm?n@5tHtp9lRiO zB&||r%}!U%lukrjV?k7zrEA8bl}E(p9Hoe+P?4@!t>x>)J(O1kz{mJOMEgJZKY#CiRe46BopUZ84hNi_of{iA`$98122?{3%#gJ-ne=6* zuJ%xnBxs8misW^jtG}Y#W(OCw z!vR|16s#To%a7iQ7~P>o)NG!FCJRAV55J-jcWGAK-P>y8-&x5nAHK zu`EpTJ#_}#XD$mdH5nhq(V|4!Q;4DCh6mVv&xK;*5@>P0Y+dK_Yw_NvZc`cWzyAcE z|NLh$3=a4AcbE=)Y&K(A!_z$D{NfUu%~<4>B7(t>=7dO1;nC3RvIMb^mn$czUZ2V% zN%7yVxrQikd$pLhuU|?}QA5I#bd$^rMavvKYZ40@(d=nr1rsAFv{HIxOBHO5&a^zh zm9vqHGDbJUT8YvwYaym+>Ujznh5@M&G*yUk3aBKO)?y*XXucdsoDX7f=6}#)-8Ey; zNjO7)q6+|f_^*lhxkC5OxgZiFK*a3aNumf^6O;u1 zX;W3h82l(VyFXNOfR5Vc0_Kz;XI)2vTq{i1k*yZ5qlev&jaJq*uj}b#Yo7Xj<^UDf zvNcGx`+9qi9o$O13dyc@Xa&l(E{2-}FOzJrwCG(NAngTO>U?uSAhaOwC{E6(Wns{> zJPd14)XR0|%VftEcK6;FZ7?m|#*PZTyj~JDx^~;<5wO;czf2e3lb(*96O%mBb;)RL z*PX{mDMe5hk->E23$QE*x;0qt;}X8lO!?}Epy=nw1xX=3dHA1lZEHC<>F?DdSfV)q zYBbk8)DfYYTs6<%jlj4>qF%;DNQr!j)9}IjAK-JJ`wZTA;|hS_?EKtJf(C>z;c(bv zw)pbw`p8Te#}UJ@DU#2c7FtoFbZrx<(NgFULw;|y|E|wbPok@9mkQx7N|u-tf-n|WGyB= zDYqywH&Ey{}%s#!s2WS1A}rXtH-L9vV+s02*Ryo)hjkK_2E zh~QNL@E7q0yx+$drp;y(nZ54!6COPpbQrwG7-?usM%wBzRr1^u(@_1)`#E)!DIn&1 zpLNxu@EcbbIVCTCM|DHZ8S@>COZ`JAa{Ay}v$b6#J+U*AED9hwlCq`u1E0Fj1qu&PtLtcDVid?Z%StS1xM0 zPCRoHVCofUmto$bLt+I>astfbpxFJs5{pWNd7fAA|1p88F9O(c*{JIXCc(nol*Y3^kX`00q1^wSldx zd7cZq{qF7#@4WL4{_0PE4bPr^2vD@c-Q(`=4!hkB<7S%*0OA5QhY-yb(Kn8ys5aS6 zHIld#eUY-=o&jcooP(A6JO)9Q{Uy2(m7g662r+=8K-HUlwOLzdK1ZF2SVjWue#VBE zg0g3(wTnE6Y>+54>!3=IAq^qJP%EC zq{S&Puh(Ej4BPq>dwyb!h$0C|VoTC!(!&UC*p-B{v-1Npzu0Ux&wmmKfd5()0K+hd z$eh&xnCDQ!O=`f=s z>MZB;r#jK)9CrP|pw;k)GJ#Oan4Y)k5F(_7&{eY9g@_N zH=6^d%GMf`K@>4o*cp-z7!@i>mX6j5s6{D+k^x_evB4*)-+sTx+i$;Z@Uvj>$()Rk zascLO#&&a73OQAQW8Xva`9)h=Xs?7{-!F23l@7Vwtw&RT9CJ2uv^YD4QkP-qlY zC^O46P1<%Vx_WZ-GbCM`wNlmk<~b&_KuN)#YsHHEfE%eWCL&A<5Nox&M@Rl*W8;@H zpIZofxqu5%%-$3)IRkmL(dgH^1Ir9A93AHmcccYPO*Wa1_dt=f!B}-3@8()X(T#2mk;e07*naRDr)l8ah-Z7x;D zXpP*sRtWUgzx`UMqkzWxIm;5wsS!#gUqUpwZRU-(u&t>kO(z(-l6s{@O7icj_)YO2 zh_Rwu1cpi)0fad*_L=JIjzw<}`Gbf0ssQ*4_;B8-%n3qw&gpKq1G9r4hNcr*tDTQE?Dg=M8kedyxhyY8 zX2Lj(&BK8*4uDo!7&SzqqfV5L5eXbkZP&ZmCFENU#5AyKB5k#jdAO-`n<7F)GB{@i zIxW2Qn;9?`hBrNIQ4Dap*9=t2qb^wGc@t{7*&~g+*5ao{D#*xfWoFKNQVagFy!y4q zU-Es=^0}4nIeYyV=U~wz)Fm#gLrWL$D#`1pIMma;jJ5Z$TnEeycD#rhuISbB^<{fg zws5O8?}Am1$4iKn-8c%`cplWmM|KPnE(G0f)XtHmoS@5U`dnM0EjDjt!(~Hs7y^YJT}&fO|e%C&qNx`ssT~K+4cg?rxeKjVTUQqI6FVb zFboJ`pYjB3Op#wRm03SZN53SDilo%L5a+Hi%U01PEp%mM))tS>Wj<6!NkS^N>UrI0 z^edY+fi_wkFvG01050=$l=rk8#pba@B5f}@9a0F6+z<_yhEEmR@8!&$a;lL_mSWm0 z)?=Iv@g?i%)8S8Mn~h9VRU4hu*Dgd9nJJnS{e`MNIe+l*{wJn^{)tBboX0fhagj#| zvt?QP1p5d9gqON9=A`@OIG}z(-Xs!%h!}8#gJ`tmL2YJ>OZc8%4mU4S2TygT%T4%r zJfPLoW4E$V0$JQr5YqQI2YccOfEiA|$0z&P=ITQXm_x#i2ih?HS;(#$i7If*# zx{joXy-J35+sa3oAFUG^&5^D>a2wMTD*aAVAZ3ktR()835>-mUSR--myXiE9E7@IA zkLTR&_3X6I&G?3w3XetX@X@+j`Z}02N=~Q{S{}>V>p!~AD;jiIa-(ZJ^wR-FokQh% zF2>5}XHhV;&Xf+>kZOryu+5h9$wEEsUDbod;fjo%4{-W-i|J)lYwQq1b*>}8aas$0 zGZwP&{xD$b#0?8QfCSOz?+NwH&B`()2P?=9y0w(f zN^P7d^C%&r3#25i2!Q5d#YmGRHt!bz9;yTpYEZO{uP-@S*?CnvjzbwEMUeMKDx)Jct9d%_y#k;X^T%b^!U$V;yV2Lc^e1fe8bH;Lx!6F5!E-+{V z&7E`rl*&6;gIiC@u)6Ndh)zJ#(yMvq!?|vj*=^{QXWZ0C@s@lDsv`v(BY^9yR@<D?l`QE6J9pEuEm7(^8HpB9U{k zKsjc)*aI7BiYoCB_q(DZgJ|o;(F|tk*yQJY+GzZLD^tgA22-3-h)TvL z?VFdrs5B`pNl)%rMfUV4)_0!gvKN+pxHU@6ila>Qv-{LdNHXz}YFs$+()v7I8%L}} z6aY-yv$N?{0q_^g0VoH4JC|?&UT>N<3;5W6^%N1Tz(w{{GBcd#0@J0@B{$HcbjQY; zjvLLvCD1;3Zl$9-r3$D}I~^S?DeSAQSkYC{bm9u%nU6s&w(hA&pGbPMYR+?w=2->{XvP;k+gsG2l)sN|utqwY39O z8|YjN|OQpuRIdOuGXZ8i888Zu>d%d7>IX9t+}p4l0J(G&!#%><(=M3xYK zCi|t?d|DlxrQAn6uHGywh~RKIz^Z?`PWyU%WAV-U{&v(bHdp+&(IVZ_BzZs zOmJ7#W)Dx_tW@YP&LpZ)ejb%gp(HhNt+KM$e_l840RYEvwh^Y8f8sU7 zIV6-5NArk8a?5$>O)T+}|Iv~Yv4~#I%>F3R4t@&(%Im=DJMD58>b=RXm3pFpt2V>h zAZLruTVbCiY6YpVH9b#a34EzIb=(`{6ci>qU?Mpy5*sm(84(sK%qa{f&e5C}y~SUr zLTa-;13N~D5&QiCa|jqW8*ujJFnL>)bj|X!(=pLe+3s!EKF>)zU)PkZc;~0*P#O*e zH{6Qy)a78F;@Fo^6t%Qel%L%asmZ1kX&C3Sbh4BR+_w~E%p*O*MkphU)=HCzR}?P4O$}NIPb>1#nH06N>m!0+CNidCAjra2IkR_-6VQ?k zPkGue?To4I`aqT{NCieWeM8z@8**EV0u(+(Azt!vHbLW-SV)dq(F2NFMkiEmpe}L= z^d#%PSQK-^HL&Z*pyE@ZcJOHvYn>STwP4FA%^HuRBsFpq{cG1$GFzMM0Joyj5y6AO zcFmjsQ2+!1OPZ}m>qM1OYMfuVG!_z{b?qQsNV|-XW?lwdWN`{Vcyk_1-KkQ3=UJof znt6E*1!9YX&EuOycry}cRx(Hm;DIK)@EDSYoQLH1;D-_8xPe5)VK*U65u0&atbSo* z#*Ao6M1|kAHK)nlG>W@oX6a`MV5ekiY`$~apCVmjF-v5Sf}9!lQX`jyl>ILs#GORe zI0n+hrE5ti%movYb6`g>wd=?kJ*fAt^+Tx!Zs|HCoqjGxVmC%oP47SM_XPoNkuVmi z&l;indc+hb&g_a00EiQZ$J|jV6N5pBF(+0MJh4VX6p=%+|K$(PE-!!hssQ+ld;{Yk zB8t&@cw^ayFxlaoJlp9AV$F_!VqIQ;sHM%cR=8ww!9+C zJ)F#pIR@m!47K17B2J4>2@%Z$i8_B`H0`%2)ryRsDAd`iHZXN-)$6l) zjujM{-~?58_8kr5<}=vj`n($KojeFC3oqfFD;q`6iQy?nK#1C_QB2E%{?NLt$moPE-(uOS!901jqBlVcIGpvyP)I_^kaKIqUc4T|*PHMRoOwfO2SfW63~RU#(!fFMwvf1|I-O$!8y z>%$ExWt6Sp{<@(Q!R`78aR)yuP-+@rJnR*A4tFnr*0I+6n!-3I4!c#wcn6+bJ*L|! zdR(+0uJsu#mCPqy;ZjYK{Q2KYSNpR+8L1iigH4(-78!ENdZg!%cE#4ILy@_T7q#%D zLefSc&3Q3XpSt%qVx+wW-)MSDsaT`YrMF6`$*%W;v@CeAFRRPK#~=i$6^Rn@R*JkZ zr=OYld*bCQ2jE}xgSggpB0^-Hs;C$#j&Z-=0p<{x5huufgPoz|d4WfH7Be?^$)QzF z+;y_po5MiIjZ}${lJUx!fi^-22T`cLy$bHLsi2n*hm0SJGbzkTe}ICc=eNx)+a_yp zyL;{*v9I5#TBtv3}b{wPQigKTjq!YcWTEFll!wT3%t_pKKS0700V zdZCzyzLPV(C`p{50<7yDH3ZT55HlBudYBOiLSjTf>l|sHVAxVW$+}5fkK4B5!-o&` zpci1huYf2XA0M%qhkz&fbs}0|z_%@^BM{Q0klogpf{RaGhiqM|?4BWYm5ONHyD-hy zm77VBD|U)XM=SM+eKV$+lHSKP|u6#re3BT|OSDn*MhvvT5X+qReM z<>AxcT?73)-~gzq7AYb=``%VT;#4dCKv3JQTJ6>FPMD9kUGwUUuiLZcl&cT5L2Vu$ z(%G#cC*2?{7!)~>ZQ{ezV8>vsX@2f~7S%T)@8;&{;5~DDPb7=Puy*){O}~_~BUT>q z0Cq6($^DF>K@ph{JwO!>NM1+sNL8(DcHMV!IJhrIWa7@ZNma`| z&^iw`*qD6WGZ0P#8L-HJR`s!x^!ZZb%y>RM?+T>qA76X-l$MYeKNq$W^=-<-*xe&j zG$cx4UFpE9QLTKC_wU}BNzI1W=NCW(j}MPfk?H{e!m=!#-w^~$ZB!u&<{rQ2h(+W# zj6^=}s`YUK*O+b9LRWXMy&lvSa2!(doH!Tn8%G*oTb~%lf+^+c`S3ZrH8-KSahu{^ zq}OCXqJ%`FrMVk3`TJ7sn6;?@<~`2?xrk|3)DDGoVqBI5OjISBEg-GQ7F&0gQW8}y z%d%`=3xI$90-&hkuAnugEULh|-pOTw`c?+%|D;`Wgh6x8W9Pzk!xHJHLChg)lIe7Q z+h^e6kkYZcjdSu50;3LVF%2@dU3{=bUh-s`-P^n-qe!s1C;jG#0_2WuA19f&KT3@5S3JBEGeG|!BnBH|!&Ui`q_)J)D+ZCHatpBI28n-!B< zCAE2M$ckvshr#`7EorosZZl=-NJf7#hKNWR=HctQj?dfldYO6-MSty+m99g}-18ua z2JLYjqvee2^@>D{PcJXH-|t{zJY24!fKm&i8QnDcc!oOpjl1&JJrjtj73h1O&fJW2 zqa$V-B$tDKgZetwUC37aIqWi3?M{7jEI0)({$q(*c!wqi<2m|2!( z(XR!-zw*bjEdO0pe@x7ubIu!c(%08l%{kYqv&u9k7OBs2q-Rq9PZR)0QJ{4La0|}; zrt2`=pf^UCfj9Y?b@3`80n_YzEg;2BM>HO4L6Lv~w(6g=a2iQ~lY`t~;d%fup9K}Y zDYcsjWW(pi`9@>=PrmgBC__u~Iz((}XCO247Uqp`2x<}yRsMLrLO9Kq7+X{{0#=Lv zMS$8x0=Z9H5KY_ir*5>7@tk-E9J>g{8GH!)!65b8k6s$|?js=tUx0ahb2Jw_tgWjv zoH)TD?Degq4bl>U05*b(Pl!N4r3^U&q^Wi6%`$kZ=ha6aDWhnWheh>5DP?s3R3Fv& zpjd|jygwUsS~NH*t_B|^P)fMVhIbE7SaL>639qlO*tQMV%N3W)(ussN%WtGym%~~S zQ>#esblT?rS?_ThA?(s0MpEO5{!w!o?EAs!d{{X)8wzCSQppxA&M`7O?g#D!>V*ph zs%$F&M%(L(jE*Crlv4087=O)s(YoD@Oqndav=b0J>RA8YJs3dU1yhS4Q7r%xGsMWy zDKm;Gy4XpEwYgIpq3Yj@|Nrl+07$og{y+Z1|NbX_cl{})^pbPl?)Urh@NlE53h0)S zhjzdk<7STyTIPlAn}Mj*&2l(sEd1oez@-1RHYp1Q7JGzXV>d=hHF}e{W)#fED{QH9 z7(K5m@yyVLsoRakOCwC4UiZ0~&OQb1_%J$yqIZ_U!@rIHKHIL&T#Ztskqu{b;w@La zUT~=S@Mt4W5ikV&e6di3Se)!}Kv7o~^toj7YS7U6`8w(Bui?EtLkE1051mFWp%9x7 zbw`k9a~WXo1Q<`-*@t}q*EBfy2L^aem?O)TpAB}pM2jgFM1hp+=$~8KVk{c{{z_4B zs^(y&2sq__Z-DmwRZ4x&S&f)xX@M#zLIWb?F}Y`)AvXs~sUD0kFLyjWJYvZga7uN) ze81yzy;VL!yOxBU7Q|E=G8n!#0R7I!v`U}n6Z_as&8Lf+gJ3_<`OsKwj@lkZK&&R^ zjC2=jjffY|>f;)O@T>s|a29_YcI_jM_SYp1!PvG9x}k9+oToG(nMIIt3Q4Ehe9NS0 zlkWkF)g*&mP7Q1Ta!OSZrGa>@2k2zX7O5(PuL!`e@$ve4{~o{(MD(2VvXxRK=S5RW z6g~O>);U0Y5MoC>c7${Si66tqJ<_#=zwceTn8jp+1dV;3Qfe?*?*glCd~jd$ih6R- zGegd1WOPR0i-+S`0dN-odyWLW(ILi-=q)Wf#o2G~XyZXR=Fs==6Mfpx=JxRr95$4| z!O$I>0jJ!MNRpdJ8Zj}k0#H2`S_kfjcJFoH?73$xd?}Gn!yML?2RJbE8RDOt*FZCe zc+&#dyU;^RVApz=YGd2(A88{Pde}|3-aRM`UG2dYO;9^*I>J9HDsmy)woWvOsKJPfox?#C4$aw(-C|kkn{ocCuI;IgY zXDrLLjz5Y3l;BDu847S|hfxu&?v+|vdsB7oDcqN+v*%%dBHEAj`g<+`oa2Gu-!TT; zH)0{Kx?688RyUu520{kPvp_;H=6^8Kg&|LHkZP6K&GEc{K3Wp?_2`5syeq>z;^*cc69gfhaU?;!f%scVH1|@U%PF^#aex zKS~pO_dHYK2n{&f6c6X!NB6;ir4&eOZmQIXM1*b|>|H+%u*os8@ZdU+I3-HmZk>n# zI-coA^Bx#?1wac4ir@FlEplHFRm4gG6zl#R6%j4f3fKyQWHaQtDf9V=hurGA=LhtA zLM`*F-7l_k*3KKzZV8S`G%N+fLFo#bm^OKISnZ3|_^hCf{J@M-1Pch66BvZ;zM`xf zE*4fMr9g_{a_uJ8MHGp<^{-9}4g?}`M}laFU{?Q*ZtOF!r`b5k$$2BhVha=g+j69<)ApwHg*uLu)g!N znz53R17iWvnuJn-l$&>l1amBA*8BZlsNcM=1;D@N$HT*IeSUr^L{xIlczu1LWm&K+ z%SfW5edq4*5-=VD-gWQv&ux~-$a%rb%L{5`s5GW)MGj#0oH^K9qLF6&fvqY4GJD-l z;F{;xUU($iNCwG_b&}kY#Oi^bs3yam5#T5$5XQq|>WXL8-rRL}30~iL>O-%#Z@7~m zbq06y{?|sVBPOUptm34;*`BmLe9~vF=x}3EIVAn*n#0C@75D(st z54=9ZQuw$hOon-Xkz&kyZjkbkDUvulKO9W#W-|&Tu6t2R37)H1N9O z>D>oIWcuDv!*NivGukk}-dm+gf>R?mW_x|@;8Gyx1^0DD$~+!F@-|r9+T(8&G5V^!z#0nN;k9tJ3k85JX!Zrqo z21CS*V($r=MYx#_X-au3<@ug-{;C4_H9m+~nMjC8a?WzUzv$S(@p%#qMyM0#x*z0Pa z1Klz1Jy7Hb@{flRg&cR90)#xM14lt7Q*|Lyf*h!s2@mnBN5h4=<4?f@{%F>J^d1if zpA|3&?tNn%>iNc~t^ubGWD*|}r4$1QPyye_xCZuW6W!l{;pa;?Cc+7l;fZO@KHE@- zR*an}KKg;I0}MM9LU2dMo-|nv20gRFC2ZV0ftk79^MUu!zjsjq`Fk(aiiv8>JB(oikLX;}Q1=6uL$??o@ImkDIXhF;PbZ|uxzjw_ zELuSkA!kKk0qY@*JrJoH7_oN<{1W{BC7!`yQr%&)oI*@>p^C{p4J{05ckRQPF@lh9 zyguiii^|~lpgIb*Bkw?`L9`9WDc?geE8GYQXC5e0N>MU%Rcz#^yPG2~`A9IR@YN5ZYNcwT^2z$z%) zir3d?q+FdHNquZo9XVa%O^v+9dxR&9QAV}QctEY|ikz!W`BnoT>Z)k8(AGtm>5R=u4 zt*W=T=YeMB2p#Z;XfSPS=q!Z|)PkkoY7l0lrrp7*ifvn) zy>C&$x~{KW1&d$n-Ag{ z6}7?LsSS19zmhC#Apig%07*naREC7X!P`P?@15nxM?YI9baqNcrSa?HSan_3IwDEQ zSsiVhLg2n8q>jOgDFFP(61({mcQh~*bpHKSMO9TrWMk$R06(Ub{(QYY{Pk-A@GE>= zmn)v1Kekz&LqQ(IQ)4iX`bpQpo;U>_R?U&wpT>jQQs5jir@^&K2LvHj;Vpy$I3;`? z$#>=~__GehpG0OFWNCV05;GSZ^9FY~6CVm887yuO@23WUUqk2r1;;vnJsb^FqV)MB z0nky98F|>F0@7^o>7=+QA^-fWgL3D;8DY_ubx7g0SF}JvY?6eaq}a)iUA^uKtobl+ z;{+Myc-yvFWNIyB!BjUzb5qO2!@A$kcy({192_7iK5h~`U{U3J$>4I&osc38+7@&d zMFutB0E%3mAhGoIRA_XSgaV5hbg7xfw1UXGQ$o~vSWr-t+M)UEkB4ZW&IFs-Sd2u% z+tbriizR-&-*JDvV_6o6O3ek3%4JEMz&W)*p?b}BHH0RsBr)lq6v(NBGca?hkEoWE(tTC=ba}Y_ z@^^`z{~ii}+rtgzhdN8^5~oVQW3FD*S*O;Bi^mtex)%OFm!%mv;D% z(E7fUb?^DJ4m)=FM>fAlUE1L6chD`*uzqy7o3jLt4%MSVBF=@yES6^>hRYNAi0Llc zVv6a+w8%T7v%^=XVkFw=9w7`q0~folImUPXnpRYa9`XsCxJZe6=TG&uDFa%L6^`GI;n2HkMlh|Q_FO}cQm}%ll79J z($#^kfLr`;K@x7`BWbg1YA|+(<9m#9x5-urN$(-45;>Vuox891mdfddPkRJ#sy`3L zA4dh@Sda%akLqiDdU|Tsv!9=zv6dCL+s%lVecvi#Gi)1M)`OYa5jJFHg!Qm(TPrXk z5pcG;K107|;_u$oAUxsD;B?9aWE5|?}M~hlFH95|S2$m(=Cb~hj%Lrq9r}>YZ&a2;o zWY0FIsBM=b!v=9Q?>~ak-`enYp-G_Kh$UWsl}gHBqR}4o6SQD&T+&TAjy9|_mT)Yh z=FLtII~)6bB0GNRBcdNE{JidKLoGN)LsuGnZ@M{D^mRByQH~2bc<2(a^Du}imnMa> z^-IZT&(h_1y7!!CW>DbS?CxzKnd)e3)J8+(ISAqXb;h-9#hm=opk&z1xDicpMt993 zrSTcI_0{5l1vh1F(~J(VC9=`8p#3p8Z=SR8j=`VuZDgd^EUxJNLj< zI!xS1{~qHzN)TNN8uyHdrFjNM?Z}Ttgr(Gchli&p8~t)CENTc-@9yW3W8V)uIh&aW zQgr>i1SzE!0wPE`m&^59?&~HW-oM|z768B2i^y4eXV&4S5tfXr_YlO|>EMruYyLf# zoN!r^!I^|@-5_bHA+kNgcQ}aZXkxQbg+bYrpd^(b=G_y;Br+Tl@oH5%lDo#rm%Fo@ zMdnJ|eAOLLYHTd}1ANpO%tb;AtckPcK%&$6u#|meJ@XyLjc0U3Jlvdg^gw7qN@`>t zW4AjBGZ#Y`4kzmX5IXL7&u640LhJ`4o0>pb|GZH}I%XndJJfbdQY!%rKnd&U*oPp5 zuuKzO4*6EQ1VbQbpeL1tXoW`EH1TlR;)pbPri6zi9q|Yn5zNpnG51Rm`#beP2%B|q zLb5;W5jSNHic*;lD<^pQxPXwC9M*4-&Ar{On7pGV?uA$ipj$RjLx=ou(-Y24TO+3B ze|&sIS_s?ghL@L@hR#W;>2*ScB_&+)f}9c(B?}2E%?l$=+En~r+ImT5d#;Xj6^uH1 zdV`a6O#B^Do<@^HNOHg~;0%E!s67hZxgPQBqS|OiUB|tLI^<7#9)TAS>*{0Q6nF?d zLPeSse)PC1}3iGGldOW0h9`jGI5(hde!Z(XOq%4B<2Jr1aI{Es>-%uwTFV4 zfn*s1R;4c~0g0hSnv^L1JV9V*yXzHz%{us6;d3`MX|g##N}m z-JhXIX+cHHva|yo_Otzg7ZvCx?U0wvOpg%M6*dYIpSM$R#q*I3y6mp8tY>nQb?Y*1 zT5NE&+eELW-aoZ2NJXl*_^xve33%wqe^Bb=v?lK)2-&q;5?edSJzv1#V>3M&5(MSI zJ@McWD-uRBW-*=2qriOxlBMrSDK&=GM`JF%rRscFZ2-u|K?{g8Ubhv5N|Iv*E-7Q- zZ1C|`XWIVkZQ9W_>muFex~{X-nENVKeNaT8LP+@nP77d%>gSIiA!Wt;_wVZM6ypNe z*(6dRT6$NgHF>j?ifSw=1J)gG>xyj8!D7fsJwWV$ON__c6_;xUL9v!QKEJ*oU8+&d zvMjh<7JT~jjECzDx4hKCh@>a`q30J2WM5He0m>?nO_5MzYFl?|q(a$BQ=#mmo4cHl zT0FTE0LwJH_rsS5#G@A7Qss6A>kLw9^{!pf8UA}DQv^d%7qD8hkM6|LJvp|*|D{we z1VfRDnk{%D0$U0s0nkmb-q+R?^s#P2&X>yVlCeG9RKd0%u4P3^Ntt*{oL|Z&AK$(E z@cC;2@GE_&auJa&=d}3I_#)}QH|JqyLIFO042oYj-!E74#B~nV~65$sW_94*Xv|4QJ`qqjWQbK zj>&lD1R*&3-JJ+$o`k!KRh==KCxEj%*mwcHmdd)-dp;pW-uR1k-XN2JnZsf0{)lQ( ztKFa9d+KT~R9dIskR!Y$U&O%0KtL&?ypyOB2Ir2KeC$=TQX3hM?J)9FRzkN;Mpkq0 z`c~|UyGlkT`!VleV3l(ML%;;ArJ$f%yDpanq^0S?A0KY`?z?}3ZIfnoJ0NV-JvubJ z?lyzA4)KWCTMv`^+VZmC;o-s1k^+?tNQ}$%iu?U;rbt{ne;aprv0NLFJts-p^H`gV z%jJTUm;U}}cM#OUQBl9hWjOlakXcaQtNEbT;NFKGgym#b5&W&{-6K9pzppxxusMtX zN-MxB8q(o`_<1v*<%n?IiyfIrysh9+5h>fY-Pd*fIp_TS)6>&Gek}lgH3T3%gYk(H zzi>_)7`kp7uGgx+ZRDk0@WcR`){dK!bvz!(VGd^4?0}VKZjw?0Ob2ZFE=T5JtS_$uOoNR$hn{}PX_>b z`_SESa7LeuO6W_C3{dx12?WU4M2Ybc&PR(!O~FVSjwr-Tyshu@a34)MAX@KYuL%ex;A=)4TutAOGWj_}@}W zKc}2uiKx8ZUzf+nhn`l|HVt!>QW_l15F7&sm0MqWBx&N*-E_Ih`sAqI`1^1Hon>KqNl&j z*ELw1+Q+)C!@b`VndsEZp=fDPyAn04;%GOkv?oCh#ew1^9v3^r<;WhjlKZBvd@kU$ zAF{)G#3+Z1D(9JD9j%<(SR|1C1m`45wVVPz$RyBkptHLrx}9@eYm*6+7)%`Rd1qZn zbK&EFF!_Brldksn!DF~FWNa`e5Z8#Sk)pDR`O8W2=~Sf?(YC#_XHY^+^5nS?0YF>6A#_!~V6aN`0{lGatQ%>8<{Z)BMpqwjh#Z5)r6MCp5 zYxcIZCOfccv4we8h2_OEq1zl)fmI5?*%+j`%}}|)^llVnRWoS~{BmD^9LVLGaJBw_ zf!a*lXVl)g2y}|SJ+rID3DL1VWK2UQ`|L0W092%9r|(FLHg|Ui(=OrdXu+@%cosYU zHnW~FU}+Br&nQ9ErWX}+p__kRR#9jDj`1=zNNvK8=cFk=IHDI?mwtMcyR+aQ^*w(Ga^iq9BxAg^5w$911*Oqgt(ZFIJ5tbDqa_&tM59XLt zu=8YigZ+<_!m5#C2l6Z$|7Mop)%)XnY78av&R%g8wl)^g-lC_IJ&T8;!`}-ZMcnUq zJKT%?(xE_9I3lI({g0fAvA8%^8rbJkVn#}r@^E`tQ%d*8hlkg%1;DTVLBAA{UzG5g zb1v(;7Uo1b=fup^S)uy}fx&%d_J-qCn{%0EWD6K^-)`MMu#pfmcZ79=<722lkY3ok z^DsV89#MiLp21s4z^oB|YeR@8Ivg_Cd5#`7M>iah%c8&iQN;2Plyfr1h;#ZwSz6#q z>|6~E`7BaGbg;2|btLl9Q~>Qdfhlk(z6YBs7F$pAd^P$r%ppYWa})0z5t|Eob9(Fq zO8-*{bIqR0IA;WmXwne@ux7iL3hf6Hp-ZIfhWGJ>#>B_^EbWROO9Sj{(&S(eiwnk^ zQr5XRp3$HEGgONZcLW_qK%mw&zkmM@kB^V|;fEifnoT)l->>C$!Ei{Vj#xNkKE%V;8=*|dTGx{LGXF;VC;&ze0gHL?tAnd&G?SjQ;?4i)Y z|3s+g07)7oPD+(TH_T57h4zJ&CkM9P#tXA))(kU~N<{mjDvr2L3cj<*W1+D~XmP@Z z7DyPaIP4@%8K70R7mGN1AwFiQ&w{By&@=6unxmlz1){0R`QL*6=fdjv0Ovp$zhK6A zAO!A?L+6hVkNEc6Z><1`=o+=ptuKeGr<@ZqlzW$KH;YB=c#DR^-$U)bu(9HX9YbVMrkC9;BC_F?0ES4`m!U-HuX(-_9DX{ zZ@hPJa}VUa$kMKcim$sSOx_0sX4|$F1zgdL{<*FgXhB%^no}a{U5;engLGH{Y{c{` zn|!)lE?*IVU%ddRr?n7KVP|u^TnLH>ffa%_u94% z%W@mKWrT-f@4bC={rKX{9;aQYr+(2eFFV^XXCL@6%;b1eojctl=>5pFN7U{wMriVA zvuwrANdYiJz_B79-(xhNf+Oo+GGBx^yC%nKi(qR!jpO&?C}FV~!w>;$*%2G#dlC(z z2xOl0)WcvBzgdJ)C;%|s!^SfZsU*Frb1g*!Xy? zB9}*KpG>;l*Za0@1M23=omdbYrGy$sLje?3y#x5Ai2RUq{`j>3_?17@;u&&IxLmGf z`@E`WJ^OydRAn`Nj@(UBcJL_$S(65qYci&85iH9E%d%iy3)XFIOz-7-LD|O6i9*U7 z&=CSv4C8?aP0g_JeE78rJY?6;e)sWVzTfX{vpI6d8}$D6ck8;gpFfjkW`F(pdsfCf z1)HTBu`(ABty2LvDVQI=QgdA!=b}s@G?}XzQ}dIbC5!~zOSQXAIknEV8YxxHcypt3 zgB3z!H1DKtrZ1iy1-l=CBAW((hHDGPZf)ROc(LG&?l%g+8m+2BoNDaAz3^E}fm(-2 zrd>ZGC(g2{I*BzaW9})2t8A@OwK&v90&E*9q66TFrifd_B06>+7XU+=Cr;8Mbv(#M zE(P%V`iiHgr&h!}(pE`h1=nlBAA=gQDukdZG5nR0vPWD`(Acm@>RI6zH4 z8}l=^c5N@upYVVFr~i!Qa>4)ofBhFo*>Jnvux=~v_qu1Kl)Dm$fMhO(Wi3#Y(ULYi zlYW@RZrq>MnnIXQct8ICsa>yk+R=Ec68m_EFr0Brc0p5(Nk6)+9ew+S`}tK3RVrWbQ%^EHBz3Mj4(Q@c1egoEJX#$9wrPq z0Nr$GNy#K?Wq=o*l*0TrX)i9?Se4>n(>$x{j~or-!#KlwXR*I$jN`dT8Epd6e+sl$hq0E#GAy+Q)vGn9{K3=cCq9KW5Sq5L60O+AuO+o}Zyba9u9QDfJn2TyRVc zZY4MbJrmQo`Tg5d*=DCTN-A}JK-f$>Q=hx87+qReHx;xbz=36N2gas?g8H+H|G!#v zst9x|fYjM#B0iQVP6VYn!#tA0;?G)5CmWprXH%J-fruHnU?S=Hzd7y6yKD`KZu^Q~ zckFpj$%9>QL`fp7-YtIP2)z>JiW@(n>e!XZyvz-!Fn#+Ro^w>3>}KrINzZyWsdn!5 z*Yw)YUU#+6)n+q2UV<}R9*Bd&b&dObdi2YGMnY82Qdr?I()lCXYC#T`5eVxR$8x!`1t)H#?KOQk0Sw&@rXMi zqNk)rpXo={!#Hjj@6(uHVX6Rj1&nL#tHrD%0(H%nR@62#tb;l4Tb<~hvoaGNrC(nw zPz#pjig)kc;r8%QH~nO@crxD)5eSh*6&Hie>+5ng2Pd)vg+V+r<+lR-^{;HdbHCpKcvFye+#FA76v5EM#POHEH#JbsL)xb2tnQtfmQcyEe2i2MOr^6=cU1K%-r^V^%mE{qZ8+1q?Dt92MHz3nI+ z5F;T?u{VR6HS_IW!$;t>`xy~lp9xTYconG|ItRDA2(^n!btJTCS#6R}n_GuM3hkga z^d(B@2!k^qkvq>*yY{XspmyMkyEGatUSk((1?N%Qtj-sijDXyb%6D0@hE6F2?|3n5 z_rY@(BqX0T{)Yq`?6|%>L`ZENtBkaQo%4MT3xRoD)sh7bT4($JI148tT(4Jr^Ub&T>kr=}bMD*<2C6AMLv({EYMe1A zBqn68QbPkRYPeCe^{(COb-7_(U-6f}`~}Q}<#K6O&~B&f*3ktekZ0Sx0x(t5A#a9x zFgx4n+G$P?{97b0d|D9hxfk)zH2mE#j>8_I>{!(svO$gnKnbk=E}>r6H7FA(co8_# z;YFFWdwz5;{NO(___A~uzdo(pGL_5aB3}!D-@wNuWl`0lic$~d>TRExdjzd`XOCgA z5=98kWq)E-znBKpLO!ZzAE0O+-lc}ggUKaXG;s;K%b;R{xTQ1~Ee=6E8ob(uhlZw& zZ%V84EOnG}TFJ*?l?L&NS&AOT^iE`(4k?BN!v@oJbS1cFg#+B#v@@7(%}J>nr%NnZ zF-X;XvuowKUhBi*`_$$rm3)d3(Y7kN^1pR;z8xC|TDPFE1~3@48(244>UD+js%0%>#d)dyD1S zd$jXjo8J%M(cx2f21{rBlrOypO*JtktQ&D*gSJ!6DpzMVaW=32F_xCiR3v%TXoQ~<`l+_DMwWdGd(md7Gj#3N zX|n~Gz=LC?>+J0Y2){kAjw3lr9t`v`Y${ZIJux z(=J^+g1Z}Gv3oxt1R41YH1E4=b`+Ejp1s_a7Gu%a-fN7;15v@!iU}RpEgg{$sK(cJ z)Wq%yI@(o{hhoplXsNA@RCrQ=z0vXad+Qx|C+s>=QJP|*kEbq|3*NtfhiokKg%=Rj zLp9s8&ovx4jOEyT8Mv8X5GGQn-IQfn@Y9b!;BvXNcwj$tQl@qoiE2YV>Y;D@f#{Bt z63tUmPRalPAOJ~3K~%qdMAs~cMNUx?d;wKC;=1g47{`{tRX(GQv`5X+^2jpT4_i6z z{z>*ItxC(6h!lxbaTetxV0BtWJPVsIo)5M@6Qi^ z$1Z@ss{$Y|%kz?#AEDbXM0Dqb!i2mm3zo$!dK0SMW@Dh$lhfyct>UBBTJA}D;V`OZ zI(5UzsoI5BxT-?(bu%^t5`$bfBe#%i#_i|loWVpW@Sv9Q5O4E)%P9w=qZ=$etNh3d zJba&03O3!E2l=23P~cuFu`t;^t8>tC^KTmj#be4~cQpf+=Dw#p*1jKx8lg0|IWyPVyB_+miHu<8qmp%9 zn@LP1m;sl|6}N{go}M1@>G`w8`&KC(T=v(Df>Li9ge`?rpe0om$*?Bs*IlmSi~N)SzaP5e8&M0>8LB_>XRN;`)Yf0{ zzA(Zv5l)Gmam=I^hpiSZJQg*zt54}6Jd+i%tqz7_dp@vvxYMMPsDI`Gg_S)L@(K5&@-bc(`4$B!bFnFmnQ^)ETvK&6bAN!!6aCL$q#!2oPdv z5w-PtA{o&mjkj$xW^kWXc`Rw`sF?<2p>+z70Y$*1*x|K$Z8$7{1NMCf7KriTCUtjUvcmELV%IkhlOjUs;HI`dT-CH;(AhG#!SfS|j9FP?Q2nCEK z!fF9P+vRe7R^=Zz(SLdO;oJY`@A=&P-N*omNEG-HL_aan3lnYY`YHsJoRU&F7~(9m z&Z!YLXN18q?GpK70EmjzF5JmNvNckRh@e0qq!mD9Sgtr%(3$$7L2kAp(yo!1K}}ch z-Clr!15DmzZP6_+%+N6Ca;bOrL9XY-Fp|JJJ|OKxCpeeZZ7OCPEB$)xdYK4`5;E6= zpUomZp@21C~${)@KILI|YA* zo>^Z7gC2dn%OQ1 z{2vX{qTO|kGuFnrnoXYKwlrKr@I@J8qS4qnk^2&%`51`Q{@!v4>IjYM0LRJ0GzOk| z0qpzH$Oj;QzY7r;6>Ly`Ev5X-Y59?ewyy}lZ{$NoUsGOQQAh3i^75EXPDJtXqaETOR2ce=9L_s=o(-#`&MV4!wwLK z-NYAbu#jb<=8Cr?w1k6gkOXot^1+GgT8K|RiU`%=p=Q%u_hKqOa4;+7S}fTt-nyoQ z^JwF7{4iLAclLak1rMi-wbcylh%&Z@`rUq*xDHjc7#3W(NYZezHMMRlI1P z1mo!!H^}lICRnn=UGbskOaYb=xS1ggS8&r*Bpdzwu zr959Rx97k2Gn0Q;1%RTYl!TeevSfXEd8so-&ebNit#55Q`+ctb+z9ftp~$d^XFqbL zxvO+2PJ`AN?I3T)FWwo72C`Sbpf+FC9--@V>$z&5eZh~cf#(AVwC@UzNLS?D&VeyY z?AYBGzeCd6W_w+Z*daZM=*P)xirjzz(u`uH=K8T;9I<0QO8djf-<@TYAAMc11I(H5 z?#GXCokvXTcKFHOWpVCGI>Ah*4p@8Gj;)O^u7RN-K8Bf({(qh`&zo>F)`Ay*Xwujs zHIS-q_MJVTrhz;&n)xz;Efh)B83#oQwzApGS{g^=`yam_h;y76k57+ydiNgdx>Z{u z@zK>7R}C9WCG+l=7@X95*e-W%*#HSoPw&mrb~U~Qw-BwPx%(XU5F#pN+sf^B-TvOs%-!k> zvldnGV4=!kwsdTG!IUgBP8#{e=U^!ja;~tE7H2sdPk?GTPn~Jk@W7&-q|#W`TIYO; zxpj`>gf5?>r^<0Bo8v?4Obbkd^zJOb{w)S|f1TV7d_ZG|tbqtZt#!E_^g?mzil`fSb@C!mHo;cvCN5Mt{U3k+0qa^I z4)G%4db#1lx8L9|fB7?1FI8RAMm(l57aj64imVlz#y(!UuA4qi(aBA` zst{OHN~M&tJv=;=uLZzw>BZy)3e}u4mgShT(A-?9^6|lKD1_!&rWs+;mt=brX6sHIe-gq5t{h=0mWX3FBXxGC)Y}_Ob zP4ehqDpr89p5l{lqXW|9UusfFF=L%N2L@8E!?fp@SG+4?WWO51^WnpX8X6TSA#6oJ z)&vd-EOeS2v(nD^I}MCt>+ zEDJWlV31OutZv-XA<2m)+w|>wau_F*2^IlSL8cradpjgdLgX%QK4KQ#e?N1=ZUAC2 zRs6#Z-3A~9&$a0o=viGJPkRc|x z9zw^PeEZpr@Dz0F-5I|TnmEF?_AmARJJAsX(hyBkIF4tAL&qUjX&sTPHaL**#F_nM zbJ@vrMG3p4yvB{D^P= z@NMG-Ff$$>p78G7H+X*jY$GgtKZ^v)V~@ISxf(_YtTSgr3k~@LdXiu=G$EzR_(+^h z78r@hcJMHpqD04WprVZv2MgpK4=GS4Y4qsud>ul)Cy0)fLj^%QH^9D(;_P2TlHhS6 za^!gWx4RSWpHtO}q}*<|=E%Am7lwP&P?DIWYK>G1U#pWzQkWVGG2c_lA4_@t;pyq= zzke+NeoFQs&7~H*+j^8{MI4Ka zloA%3tIFJ2wLhmp>44}GXos##0;SvE?Yk`MqX;#s5!t&M1I?M1S)b-h}3Z z-iyCYrG3Bo{f^%w)0n=fCnJHw5kwrbQ6!0R8wWWlkm5|(32)5clr0eEZ~us7z{)$N z7HR9h7ZIeK@bLJAUq1d)`2lwS6EC=2u6XzEJwAT?h|7iR$ZxGt)74aL8TbyI#;&s= zik`(`^0sQhT#(Yz4#oApS}~B@h#(eOJabsI=Y2@v(hNmeC|c{Y;oJmi@!T_~k~4Qs z(E(#$q)TV#80>u@*VIX$`2U}AQjW)N9bxFP$foKorP%<_Wjy zL7Np;q}GKb(BaJb2u_ZNNb@A0HuhZyc|^>civq4eJP5X~&HguPly~39h2^Ww5nrdX+|P(ct&0vB^opsaisJ>Go3jj?ZtIA3@2Rhyb??N`WOA=2 z_nUIl-%7(9-ls!SpZ!c*YtAEy4rvH#fp{Pt6^uub(eu}gDwtXbh^#h(sZ(fYg?Ddz z4WTSk_PmXJd`QdoOwad8O2M+^VZQA5?{<5@pa1+P-0ub7yw4~_P^4; z`+^-)AkvU5v@iUjIE?>}VCkW=p!Q}2q4S@H2o-xfiRL~G2s`Qc*R>#Lb4`?O@U+;G zTUA2fn&SESZUxrpvN=D`5y?(;AO=uYq2XIW)f_+2R0VRlskY3(9>p{A6PvqO4573WT5@p*G2>2T9XM>cHNr`GU` z>OW!K6L)0+1)`6~+a^lp>?Tm+H`CJ2)3|~mO?Z8~F8$h~X)7L#A@2DVgGnRfY zwFTVdw&tm!CAC+f}9JiU8|+wF$?>nqZ-G<=T2LF~`rR<_0|7|}LrGD5#kr4(E)OJkibOUC7L8D8VC zhB}9GK*(ybrnp|OLjiC`BxP{77Y7FJf~XuSeg;}!h!P&39bYdI;i8GgV6s+~U6Fhg z4Sc4MA!2OX9k<)EOFE4R$oPzFdoD`Z%pou;YC5{menkSb>Hi2l*LYc$l{vlSoS%OW zXXft<0k~aNwQ72oD-jLV9-5BU|t7bn%(xoz&3lqP|y_Zu7I}C`q!oeXgN%wQ_LYXdKz5Q4jLH` zori}9JU%_)mtTIu%gcAwpWhC!$AQYIb9AC+RLLzFO;s@Ch@fXr1uj*+1I&767b@6g#hGx7v$}0d3beqBRfX zF|l%%CJ7t1gQ4>~e9$YyfIJkNGt> zeY$n#1zoO17!w?iW|L?6=rdY^fHuaNEC}E-jTUr@ex`jeRs7l2*DAav(k#jBnCAj8 zLd=K+x5<=-LdHNGx0F(_t}CwB3%>d08$7>!#=5QGREuy1;dZ^^@#!7@{FgstNvR#U ztz$N4N6(iprPQxy4zRKvHUYgzoRIT^ZCg>c%~T35dGiJ1PJ^A_LKAt^-7RNAugsma z@nw`kLE4OhqPdq0j-k;ct6AY3Rsg^lTCzuo-YN{o^+H1-ceJ+VPXB(tw*p{P6Y#Ep z-%7Q@<^#0ES5M!!TKIN%LscMEovEzrT5h+Sd@TTeYcFQWpG9?B5-T&QO2N9`alKw} zyI%1#e>5{6+bAsB(+OiSD8@Ue8bKLhJqBsQ;BwWBGHQfy?AnUDGh1$*I+ zi7jST0qH?TzpQy+k8SN{I}Q!B=Y`wKcmerBT{`0Sl}Y8@xW?RINtt?U1z5lTiH;y4M_EVvi5c7dzrr%q|}@pqlDOy27P^f zm2bcOwtOuBesizp`d3x`%!$_8lq+8EFL?LvJ(k5{dwU~RiE7#iV;%>M% z$e4=+wy{H$21d)@NOl@Fe(Bewo&nFn3W&LFJH8p`lxhcMtY(5)r>3fJ*GZa3M2%bN zXJb!Oj1FvCXUuf0TyO@y5Q1UQB#jiC!8f-0ezq9Rh}?&P;=ctgyjsSBAG8tXbo2(a zw*{WBYlPIbF~Db&rk1=mje}-)%7&tdHt+Vv!Z(y@cKVyuB5yews&+4VkJawQb%CfD z^c|u3(u=gWR4E4|i~jscx2uM;<=2S^Q^|o(Pmhoy`1tV?{`kiY*X3f;Kf&X}4Y%tR z>n2Fx>0b1;uqF8}QvVnNZ4*J+iiM4t?}Vb}iUb8gygfB1q$7lh7%683(R#nXzTR%PuOoop;KxrQqaw3$nB1x_XecKGAL2kNRbfZNu8bD@26O@pWR%Y*%?pCYe4u$sFme>ZL zx`~f{SF$9zs+FcN8}Axq4p9GScBg}b-M%Xuv+L*CxOa&<5dn#M7c+FEMu;4WA}=5W ztrG){HmY+ZC}Q9bOdfawtWdL_Oj-LhPiY zQbR0p5X`NuYxlj-zzgW+L^Qm%2i6 z-vf10u5)ZR1-e`pESJShhBO$2+Mj2_avQ5v`P#rwiKbVPqd`5yDf*dcOu-BxV-%b8 zFw;Myd=O1VN~|$xw84sV`kBW;v_}U9(SdY(WnYKa>-8|3BCd-~3W|+PQcAT+sSs25 zaR3H?ff%7}@1Zc!nwUS8Qhs@QdV2Xi9GJhWEC3>UDP{eOs{WXAeo4!+)haPzxm^0Z zdU&J};w`0iA&{xF35Q1Tw)ajs=Zpf>xK)X#QQz-9iK^y)m!>@~7N0BOP^hy=FA7jM zCF>+rYP4y!|LkLe`2d*H-ePi?Kc%}6jVPgtxdpUW07$8?WsJ)0?r6oK|EYRUHdFP3 zDft7aeM}Ld-_u!QNX2ucB!!sY0jWUGk<$o;hxf(hf8GtWKpaDD$XxCGn!C?{HuyM( zO|f+i9He6&jMS15-4rQyY}ApG2JasDA`JI?CVmEaQ_qgjAzva+USoEH7csSSmf^sU zzt4Y;N(eW)Ia4k~uL4iKtd{t_0IZkn<2vrYT=F?vSu>BpIZ#|LS6p&JVkh->8{O@` z;(EE@!-sG1(~m!3d%YV+U3@S+>tF z&q68lvRo-KBT=#gy;}P!X`2nY5};e_YwKW~u;!s6k!_lDw$U>8hmQ$L0s(;&HF($? zdLpUPIE-vm|2|z8F1<2!V&cH=?i-&(N3cmM)jC)W4+YP80JRfC(;w3iSvz;3&iaqq zaUWyofTRRSxFw!7pVc6#(`L{!HyhN_!m31#L+mhucK-Bhb)rpc}e$OzaLa?S4kp_>ryv;k-VU)y#F`I@)mqqj9CzG*OeoXb} z5ZREI#RMpVea2=Wi+Q)o9aV9=Y`^N9Q)S>2fk}}d*tCF9$zYeuf_G03`26V;Uhnr| z)VEv~eEWxQk(N~74|e|oY0s&eZFET-6cW5dcEK#>CG#av@NC5)YU=!OmW9G&~a7V(TQrA0B<4;lDBx61X6GL=G zN_AAFg2tOrt!#FsO6F57!6nW&)Y23(F)QB3L}JfXB}$rclLFg%$L)F@+!tFO$8a?C z+zAHP(E&3wAW~KSruFZnKxKpK1}S%J>norI3BbechTH7{&o3{H(0eZ{mb~EM@d4j_ z^9_Fd;jhTKu93~&?`#A~P1L*&h^6Or1j8!k+VwB_0%(TFE6P^Q##9K~W)76g6{Tzg z5w6LLDM8C-VK#&%C0s9;R%8msx;o1D+Te?3x!oK~jjn(qGzG(WAk#4W@8sxtTo<(j z6ySYog@6dath-dfh&tB8xuBHIJQI2#*5}WkLk2*7<|EqV5yRV7P}Z#>9Sz-(`WiU_ zqBT&7Ie~4DhLRFkh)7aO<(e+{g!Jk0@$vKThBo(mD*#gBb-7))tFCgn-theS6LQYD z-mYc}V$51m6kQ=&4^WQtsmRJFKAlNLZ~V&cw$wGU0|_R5a)Ol|s?Mx0uDOkFa26@s zNP|-c6acRFPn97X;8lmc+Z>-y;q)_`&NeQQ5w?v7&`=C~!PFym2s0U|S|r!s$;JUk z!zpT{!cMP0WnfB#m7w z6EdX=l{#@wxiOX-vO|Gw9$v2mav&&;uRACLVvIHH-eZzQU6-ruYY? zHk6{l9+@UGXE2&7io`US8*SURBd)Qjhh}996m2Zo;ch(%`=YTsr_R8qT{>utr0#hD zO_^a=r9myFL0JIEv~Q>BnvO>gUfjRDytEBD=REiW%w*Z>oVXcrMEmSN@nGdFO(JRg zkfe66psGY9udny@-NWPk_i|qH@2vn>mW$?;by*gLz1$yvY|^5$INcB0XWv9@u2FI1&s}L`C=fo?YB#DNV#DqLnKC z2E&#!iQ8GA#{B>Ovu0(%(dQi5*Um+PS{RAaaTfiM(l=l41d-3z60avFhq0 zc>iPaUo1kX<%AOxD0!k?y>@37pR?p;U)1?{qLH}JX0ZJp_W5_TD~|V9jDIoT`UPdL$Mu$eDnxe>7c`_tTuO8Q_DqEgLkhTT%!V4?kgh6hcL#JK~V{yu1 z<@4#9&gSA*L|Rx(WYt$W;1z%T;~(+;_kY3X&!3QTh6ggGlCUmqU^6w#H~&BWLBs`M1Bft=OFi!5T9ryolw_cXGEz4`b>n zh5k&XmRB;rL`P-%bgTPMv^CHdb35!i!hnVd%!E?E2hqc0=DN5CK+d^&I~*yT#zt*? zPB?InDlbdIWW%o^k_%Z%KkRaMV4Y-{YDfX$XR?iAa{LqaAH*cWNAwPRJTUg%0oQ zaq$CSS5*4gNim`(W!owd(6}+8eeTW?7N(d2d1S|mKr8RvybckvE;H?~k53NPqkB3( zo82QmwL`So#};WD{`*(Q${28AM}m(ROd?Qn+?)~@wAk!n^`4}Tu+6Wig_p0z~H&Ndny9inMLvKOO;xv>NF zgghNXbl5(vGzUk2kM?iLC>b1^lWw9m`+LooairLp<%NFlv}1O;UH2r=vu1N8HxLOS>AjN@2v%KFvJK4^)M@!N(_r|z8W!0 z-6_o%E!!N_J75t@K?@9XpS|~h^TR{(E%&ZD4Q@VQ&c61{IZqFQY5?=hKdJz{s}mg^ z>;?p(!s>Hw0Sz;JIUEhlsb)iv6Zha@v<;*C+&80@#=WYW9v^PD)CvYMPj?DyLGArF zAM$=M3z|K&48}rwXrHR0*ktSX)=j7sqo)J9d@gRDWF4*qzy4wD^F}U2-#BNL`gj<) z8Bjfp*N~W(+Uz=xux1o&zve0;5XWKC4*RvkGD0ke7O&ua^tnfB1kOfBX^u z?%(}eq+Gvl$r%F1H{X1N@4x>`EBq5PWUF&|;&HS@5)7FFA0_7+K;*@RDv(ko{W*^$ zBLhw*Wj4N%9mvH0AA9fCBUyHxiG6GBeNIGVWL9QXS2xLKQ_Yq{4WzLkz?#7f^e~2R zBM1XO`fqq(*uTIJ2K+2&jIo~t3@jM72C)4!^25vskR{6)z$C>BD6*TZzOlQjvMMie zJ7@2;{IKsQPE^xx>_#O}QdcoEGUA+l_Fn5--v!2YFusHUS!;`pGJptJ#}Q*i&hzsI zn=Ps`ZFWo{H6~k}2?4OS+%={~NvR!Hwz|MclyEJ3tegPg;lIam#Nlwrxgg0G zU=Ho9QwoDqYhb{n05!uQ%#Bb|EDJ$5jZs;NXk_Ls0k`Y3vlp)lfL~e!pjRS@wO0GZ zBBlaHl8x=)2A9o8s3K_PbTQD$8FCJVj&5f4rqo%68>t$JQPY*D`m^3h!#tNThbJZC zUrxHKs{G`&5mE>_!;&sO1o>cK9L?@)Rlv(;?20Tg%R-R3^ zJM}vY1R9Hz$@`v0gw~^kxz2dnMIPCp#}2;vd^#zV(&4Emu1jSmU=-2YxA-4;rOGC< zIy9qdgeD1#sbeapl3K`&l|DX^_li4S+-9|)9;H}pQLw}Tpp-)p;dE4nNi8x|6-ZRr z+#(v8=#obv>HSPmq*Lo?`h2!7dgXfp;uY` zI)@Cjyec&On}S|yp8s28Gr}_+g&`7pH5Sus!eLL$Ik7dPC8E_VRr48;iV9=cfp8Gj zTW0<_FPHDVDgb_2KalN(**IdjuIn^a+=dNI$JvfFxlW~ddpQ(oGN(#at{yFNiKac- zQqq_(e~s*BsUg=BkhW&V>SUH4+2F)98^>FFSEmk5qQ5Z3_coF=PFLRh(3R+Eo&8+8 z-OKm_r@l@V7^gOzpuYywn(E&LpWh{A!C?)Q6Yk10ZC1(xV z5LM%daLpu}(vY-X1&P#0RFnV#`0`aS53&

      T;)+yT|v8n?t@f3aY*2!?Wq5%btZO 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_psvp_p60.png b/src/qt/assets/systemicons/ibm_psvp_p60.png new file mode 100644 index 0000000000000000000000000000000000000000..af5a95675ffcf1ae77ea8df69c011b61c7e5bf9d GIT binary patch literal 217113 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_xt_82.png b/src/qt/assets/systemicons/ibm_xt_82.png new file mode 100644 index 0000000000000000000000000000000000000000..4f398d468088aa499996656e04cdf03f946cf5fc GIT binary patch literal 295676 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μ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≫s?-nE(Jm5KX2|f#6V;L#x@w=GF!VgC6es@`K1SS^?FX zbPiY}QL81s;Snf`5{xStEx`i7XvZ};D;=7(?rdCbR`2@4r~mrW(G$m4rWV2v0Qj%Z zUFrXW3IG6@>P}?3Pv+P%X@f~k}>u>z*|8}C=?X;zoVtk?Vi2@kj>f*sF9wIW{eOg#>pD8d7qZy|J zQU}kVbm4_E#K1PrtG+oS0T(n0YhZoI2`R}fBiDg*&Wn?t?F%P{KPHDS3jkxZ&qL>U z*-KyQmFyOIHo{I_6=&l>9Rp)a8nH3wk--e1l>SoK8M$kGGU;|Cv9+}4Q%WNUC@C5i;y6ZGR$!bV3M2gC@4p92i;MWdA3h8Qi##vT>2?uCG4ee32T}zvg}H?(oICdn ztgT4FFC$nB96odq>zivhQNJ2lF+`V~{-boj16FC4g^*jZQuN@#SH z;wXfm6ivXNXAIUE1R|UWevQ?WgjgvkEw;Bcz~#%A(eDi~O8by9K(jG}dR;$ zA2!dGCxO93X}oBTaWE$!Sm37y-VZ+Jx?2bB=u&eQ6Me$?J#3F-$M{sW1NF*~jWSpR zgff5=ZaV}9fDj?9tDuddk(~vUEg*PAP6q)fZNOaotRyrzN-xt|gKpfAI7iz>MtXTspD!kI#8vr_8E2hS}U~LT{s5}Mgs&=!kG$rk)z$6LRl5q z+T23DUPmA$0-@0D*3s*4AkP&T0vJm?`m!pKWhI);791?JDY1XwK8(_w((0UsU>4o! zHb$cqSy~{eg;eZBvTHxb1Gd0s#WhMC!ET)cS67bhfeOKLT!iV7a*)MWBQ{w3y{ zRbL!>aaya@M7G<^9W;o1aHnR1h*io)_eOW)``k z_hX#}6M&GkXQlXM>5D<(#cg~?s-S27`w7n2COU@Z5Rw<;q+(wzjMo?Bim~I#gi;Wk zO$3@W@)uq=VJPC2Q}~UPV#hQ{VKC^U$Wm0LgR>mklu)JHP9a3#r%HwUtMy9muZ>;rK zjvaeJ`I494*qfe?|L+@b`IgT!#?}GgLx1(6XPq4}Z=CagyS6RV8%;asHk-|+Bm1*1 zBOZihHoPg#v*F6h)5{Hj=aF$O5 z#%_mona22~FSLBZrQ60$3c+_cG?)kdjKMvQvN0@08XLu+RRt*l=M*>#sQK|&X!t)* z6eKX(;>yYjR#vWHZM6q$E7a;Sk|aQPss<_QXw>Tz$`(3=VMr?+#{sSoh{$sz3}J-F zR8mWy0&Y1NGt6ltGV4Slv#?z>S-~B0*s2Rf{t#(XnvW7J}E!1i?T)221>+37%PBoEb z1vWN%U;qMP`Juyetq=bBe|yPIx88cw($cOk=Xve`*ss_386-3E-@NX-{=;LB-S@u! z+J$At5Ie0I6PR%L>9An{H-5aSecG4%e?_Qr&-~u`-^3(QYgQ<-idF zjzOskVMrr?=NOFD2*VgvW$>|&eiSEeybcEs?)SDvK=9BXKo&A!(2CyYwbz`$+Qud1 zMdmLRhbWHF?RGF2^eOnoFzCu*YKr!LMNwdGZVpARp>2+4tA@3;4U$d!B(^Y?$nq3v znnKD&8Z8$&7Uvgm^2w7vJjO!l3`s3PUZfZdH!;81Bv?<#&}`LE7CDq6uX)=kiILl$VM5`EcMVK<%C5@Rq*fpLMdsvN*;y^dq69Dv;95xDWqI5C{=hp1u5f=RTFaP zcJ>3g9<;U)Jo2GpmTZ3$@Q(HqA`U=%=7IO<`}2b0!#T7eYcChH;u^;)Q)2@JK@7$; zxX^IWFq*n{AwxK8kfj+eoWF$iwJi)rTjV-w)G;;HL>SeP#1W+2rhg_i0UVZ(#8YRUWW(V`@bORnP50Yh^_o|{`OR;>Hwc0}%d%jsuKikHVYAY4 zZQqYd3zg){FKhXq<~{S5|wSI)EOftmo%koVRDeeZFl?50nSQ*8E{S^C&t?qx8qL7 zscLQ#k7_g~ls5-SF{{>5Dk+z+u7D60XP>?RrGO)ck5O@<9gG4#@}ZC8@Ug>_^+#E1 zEbZD2trgZbuHayIFO1Tt$_j^%9K`0`>nMs0wWLAZe=x*xj9#x#U32A7S&K%a0nQoL z*VnOc-#!2wk~c6tHH!-uE}|?8vWW2jVHja{Y8D&o>tII?d&`+33tW~XFLKoC0US4I zw(1yV17z8dltdgcI_BeN z&KF$9C?|Lbr4+&-utHl4liAhPr?ZXCm0r7fc=hxXr|$f-Byv*eoC9Ez;h*Ho$8qeObG19}xa07B_uc!NJMOsS$lB`aRK3wS zGQ0Oc8$}EqLTipr2*n z!@oGjF$kPTzS!3Yf@re-8=pty^LHN16HHcIW5o9ud`6Q?&luUUc45q;mid^j=uC#-&8c%+<48sU%dUMzx~9AtrYgDD6FkKcisOh765sF7!-Ln_^$8y?q7T8 z{)gUp?xP?7HYRx;!ZKwQ(!Rk|X9-cz#rdIRuklrr zu`o9eTN#w8MG^swDO6RC1N--4G};1(hF>OnlxTvYsGt;SB#InpH+LZ~?nJ2uNa6Na}SjY;p)>fKj>yFa>KF%G_Z0(lSn-I)#33 zfGA-o3XNK=2F@LN{S7o)0i4q?RwIf63ObAeMp1EUJiUhsho(ln4rDz zB#;V|Vuf-702fFKy7C$ALXzj2GeAn_CrSx~i!tc+krxB3t*ydT%G2LMUs#gJjJ|FN zSO(=ky9@!Wc4X;-g^a~yH%w!HwqrHnDSQUL!?)0mSOxG}8>=liGtQ{oa+a8MV_;#N zxv+LJWn2sn9=>Ml=+*lk{M_Gv zfGt&}GWaT(T>vPHY~FCLk|0XA`Wx50>m9#S|ATk_&g)K|eqz_IJ-e=--Zj@fc>Hj1 zO>#nlOHpaXIcGc@qzI&7JOIKdrs)QYDf_}%2ri+WkFRDD&QI^Gr3H>wl=;9o;CKb4 zH6qy|s@2CjL`Q}dj&u9#h)gffS<@PI3FlRlfa#mLB<6*NZ1EAj;QcD zBufw>E;xjAkUWG{47I2UE*Z+ALY8mgzqs1@`URkCRV4g(pv)#*H^$k7N2>H(CGy zAOJ~3K~z^ALRJo7n8l-yK7(UNkJCiV8aNh^mL#AiD-LSV%78J>MrA2^qgkJtS=^s( zZvOrkKK17hUOMyWor?#q{LbfX*t5JBM~>}>HW`)=EMWD@8t%Vum6;-tPe1+4 z-2d|9|L*nu-r%F0^C!RFw^EY?*%+3}e#dvd_UBHWeDb}gAARr!9>_X4xMS2!PmsW7 ztfmHet!Sp<$7m$3qol#HFp&GyJp!8m{y=5|oLOjVQRE6t2mk?$<~ybeV-c4Bw)u;N zCKB9>*NC$&gq%dBj=we`P)TgX8LbIq5RgcYQ>OZ8P$3K@!jJ+7KKaSd;42T`gP-}C zpG2hq$s;tA2-8y?ibd7bVUB}$THO`~{XU{FLQ#-%xK@`a>^erH6oQAS)Cdd~L1<7_ z1+pwhce>+s4#3_$d-3?=kD$NRN3GsOrOD$TCkgt4A($W{qOn7?y9tV-z-UmSo=gLr zGT4`v_F!dYZE~qNS0aohR<2xusvKo1fLQg14;{v!Ux2d&&T5pU!NS4<9(wp*C^LdI zge|53D25_05r_mvQ`pbU%rx;4qy$siGv^6~%vk`($D}?3a7P`T3n2ybISb?pf%QB9 zKk?Dt&c^vTM;<#mU!S|+nGZrz(Z?Vuk{0$^JPO7nT_n!>fGajhx&$bYg-j({=6FbIMP{Sy9yp|z|67oatQvoI>~ zg@S|QhMo!kYmIX-UZkMOAMPA=#*TqG@Y0oOX-A`h-dexXD~5Xg`M15S+`GIhpPKrn zcT}pn|F)OBYGi@N|MdO;_HsRxUv(`Q{ddH@Agt>&&1>~~lF<~yan6wd;9vgY7v6mP zXFqQqdf?$(k6e3XX@1Yl?uA|R_2p}qBO!voF(<48GuDAQ%R(;cnGPZnPJ#lZjMd&2 zN1t2 zO!^uU+%XtE=2?VZ)Mq`~nV$7PlJiMxO`HZs8jyNi2T)*C7I@<1NnE;k8H3>_xKL;` z>qHQ3GSnI!1Tp|a03kwzk=&sz3TUJ+Xga~2!I_iKV3ekak_d4uk)|o)r~z9^Jo4z1 zc;b=EIC1?E-2D6-v9Y;^M;ZZ}>9j_-khE4>%(v;~}$_qu1X=k_4Dvj4&Ks!rykD{=4sb@AOo3NI4ULxGj?r{8(fH z7%->dm;l(g^CrO{XMp1*3}c)^Sc*JF95=m^n!&=5sL5*vIFl5M3-RBr4-{P_j%}k> zIVHYP%r5sR*?_`@{5X2tRcUY9H=rGzsx-7^c;w-SaQ}Vxp5o*j#FF`2- zDe4Gi2US*}assF^+3%G+Dm)%XT9FQ^KZQs!@+>|ua0)dLF^E;fX)6o9cGS_ z4{P-VN@XbWlyU}?K~bidTbROQkCNzcTxdxt$sJG@P}=^@KBEis$5;^6@%ewb;I*soW1zPw+&}z zI`4h=JAU_1-}L?8hoIFFIT%N&io7hG2v7#%pOysWdCo!^qcWoz&TR|8nFk)c=as+r zyKld4tKWP1`IU>^qt{-&=jd(MMK{0VB{Iv0k|7t`R2)JwD+CLLfL6xup(Shkj8n|`S%ifL<< zwvJVeMk9Z&0Qmp$iff7L^?FGVh>f%u?ta6Yzjxt}|LEOS7}S$WRm?hzC{EDsMo9A> zhJzBddK0%k{{$B1JIF=@tXy6NE(C0db-8Eno|!kj>HA;*_*WjeaMg9!eqfZ3SR-kC zU1Gp`6gmL7;ntfT|Jk?x(nIh3?YAw)ao7T!7z^x36oW~X4W|8V3{t7G0I(d4Q|u=g zS^FGgD5^fdLNF*W|4MQ6nA|7KK#I&egslFSP*<;dZvR19^AlSw1sA?g-ToG zd5%W2i8LLcQW?0QV3kqY!_-sonv~Yj{cyBt*tF|yImieWU#br7dCpAk(UJcfen!)0T={E=@yh7f(Z>c zfh1|tnxITc)o;jy9>xY)u@2*Qfia1)tgw6cF5G?3J!Dg2236${M+vf#!RAJZnW-j> z830_N-jvwvT|ucv6y@rG>6s}!bN)$Gl>)eg(S!kJ7)KD>2@r^Zg9{*vI06w;SI8Jy z_CQ6Qb#Cl}n}|Ed*wsliY8b%SoH+O*^85)Rw2@$JyI7bM0-(JV zRmuARtGF=P`#$v7_I)3kh10pH$ze~=41J%42SYK$i9lKAkb=U(s;WW| zh{hZ0SMkWiJLMDlW9X>t}4BH9oJnhWQ(B?8Wg2{5T%OJJ==p67VxnP+hB zne!+Lf&~SEM7J|d5VtTu5YjqlK%7W48*TKqQe0WN zh}A2XAf?3W>IDR0fWwD(!(s$$r;w)x*{HzE#WUz<7jgXh!vKpA@E9_%ICbg)?B2Z_ z(^IpE!a8of>G^o#)Wdk{)J5EK%Po+#0FsrkT=To$wHA!nIy{xLQ}E! zUAKSw-3v>5{`{KjZu|pYt6z9-0`M>J>U28eD(aauUH|E)PoKH{uFrj@QJEU&(!i(; z7cUMVrNH!52igwt$b<8Ops_NWJES&5?WDmAROP$z4uxGFpGePa85y)5duNX ze9k1S2_OTBBoX-1m+!^9|KPvikKX+|2pR$+(9n5>ndvzsO`uQ%)RHD(s92brn}u@> zqjZQM;@~VsAR;U-E+7;EHm_`8_r7HmWeTNJEbpJi>gsvo>N^b?SY+t{2M_GSXw(NY z)RA*0(V1>T)EPF1D^NBAoP^RA%}xiJGnR!T^bevJN#7 zq19}m-|s<+0993@sJ5_YZxf&U+!+jeJuEKnL7`~3zP$Swwl;IXMl|Af6{e;;$nz15 zEh%|15NNfhP-GnatrU(Ge&^27Zq2}A2*dh-2vO-FlA46p49tauEfwBrA!&a}s9j9N zRa%!QN(~VQbh!F%Y8*uiODqWj3XMfr22yNWw1~DBL5R>t;7VUS8k)#(6$GI_qCt<^;sw#(aI^zzH! z^2)uBU3cQTpO!&uYx^nvp|3t!eD>u(=7Vrp=NLo4olK%eG)U8p+rIMfeYpSL`>y}P z-+R{!A=}5^`+?u?9=qn6R%dE1dfheOD;+bu$Q&PJIU}-Wz@nt?Bf|_FcTlc`2r0(a zISXYCSRkR{AfZWMY5mlNaWD~46JfOv6=Dd2&|i=a%o%7k^ctA4zGEB(O`i>|9YPV) zC>z`toXY2cjBT14)^bnzl(4RZ3>k`I1R+8qQCbFN6vBX-4p<2(Bp@p=rV&OlvQ*>J z#TBevxj+pUbEws*o3F(Ugps7okuaoO2cPU2#{o4k%z_IG0ZDEVXmH8ktVE~1h^kW9 zSiOKVr=P+@4?KjejRB_TrZ7D{1!KsPSQRNwo?bzBs)bggfwHW?xxnr{O&n{U@Hz($ zV+xFl5{x-Kb@pit(+rCXd%0na}u9A*((L8i)F8OV==|IQ;rOD8qs$p(s5$DdG!?9zB08keD-25!GcF3{{)6q~sTPLm5N5JVr15dH9bq`gk){JAbptLPs#0NTX$ki|@Dz+w2zdmh9MUw$(%exD z2RVg)7!J4)MssX!=17MQRY6mcQVlRO8=+8JP`X4-)L>8{j3k=P28z6Z*4AgwQ!1db z24z(Mj4m>OVQFD6HaA8Hf&h7*q9_%nrrXH!5&FF$YPAL0tuupWTO!TZ{lP0yqz;So z`|!l+y8z4KoWf{OVt#fvib7#+wTJnosqOCD?-a*Y%`uFIaSLqr?F<;Ji0H;SBqSK8qEIV?IHnbYloF|}P$`YI^;Hx_4rd+8 zl6LMgAOhS@0L*xWWG6{@%wu?IWItY0P;|9`l!5ny3phOvhq4}(?L~eLForp+H9|1Q ztICySU+0-BvQ&-IQI$nWeC6=LV^7`q{MY424=vwW?<}3MMw}Kwa5+6Pu>2h-Sv9(O{*JMnpYjWK3Y7oFWFx^EO?}aQJPyDu(GUJ5DJ8moY;72 z8sh_xEZKtjjwtKNn$VDSm^(>L0N3Em5=_S@>p4eG3~M#2Dg|SLyz<_|FZd46y%0X^ z$W2x&6Pqb#;7m;>jf8!sf`op4Kvk+qVH!sr5-u}N)=f!zrCO~9RaqEqu+{5hIO^ft zGiyjkDZ)rXO0wk!fkYTl5i7kLgmXz3J|o9b7)7Y66jfo+Y<3U^F-52Yhyno_#JF%_ z9bfwVr*LuQakLt3?Ag5+x4qytlx2y_S1u#ZNmNYFgM;K8!`=YJsKoN}vVWd(Q&TNOiNKZ1YbbMzBS(%P%{Q@o*B&$*Q#f_%Nqpk3KaB$i58(KT8;}-5 zSYuHZ7MxSl#h63n6EWc&W6a2MI&635=WE&K*1x;+_D{WN_nrgqK6LzfpRLl&nX=%D z86%M*4jcBl3BcF+I(Pc)T|fFGKlIjfPd)Xk4}IybBc7RGERrZGX) zzfy*5dJu5dLR$?X9E9+AUrys$r3eHww%ZsR_?yJ}L&Hu+xkgvykL4kX++k_gtoK<{ z;Zao;7Ut(+EzsNA#NnfdvDq7dGmE*oE=HpYWlmmw=g6wq?X=Q%plD02F}~C7

      A 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%0A&v7+r_+}*PH{q# zbyA|J6TAVk!8#F;lIjmPs0D+XZVNo3z{OXhy&w2C#us|qozpK-b&hmpMI6U%8<-9y zGi@GS2=GpOoIwePHA7d;Ca$RVn_Jr(vuaWoH*Rk3e#^K0CI867kNo`i|AQacK5_Ew zQ^x2EN{Ht=dHj5<%jbF4{}Z?8&8E{%6v^0mzgCvTU|h_q#~%5@y=9Gqez}`NXZ}aM|h{e$8G(r0b%Aw zJ8LY6=q3FHdXCN&Ld>O@7cT+9XcOK`JzwJ=HKAF1bdhjvd53$EwNJ?Vhf7y9?|JY( ze14A_?T*l@b2Rf@<`JzNE zi8atPp0d;!Yp}-PTm#r3PiRY3%_xe3G*!fLLY59m)8HTQEnLW3gEI}<0McSiO_nTh z;`Fg#hHVUKnvrEWh?pcz(Oz?6{ZzO}<8V!A84NYm0__g)w#4eNY0Ww*-aD3-mbi86 z7GM10({wr=*4NirUAcfUp2NdEX2l-U>6oUD*dOiSeZ|@H$2oiU9{Pi2mR35L#!%HI zaUwuuSZf1p$ry~aL^2J{r!x3*nx-L+1G~do6Vg5Hkmh|`2-Xrhr2<6LZiWMqHAG+I z@LU(B^%40On^tXL43uR-97j}j6*dBmMoC3k*LY*+h-zC^*w`Z*%ye_}+FQQv?SJm# z-LH5!`ck|A96NRCbKciK@zfV@Uf$l@{;r2V^?{WrUg}EGNd!^^x3fnI*;0`l2YWNL zmUvOql$w9|BR|A!R`Su``d!qi^NcpHqiln1JV}=M5ll{TBNgz;~UysQ%--f8`y!H=n)`OS;k< z=~ap|A@{F@rPeiwz(Gea=jG2$B2I;Mws8SAV;ytzzhLf=29GrX7<6PJ14Gj^!E`2q z)?by5@j>maF>X2?xrIS$_xCrfsj}H@-0b+;KYQDqm;dvtzvjLdzWy7&>GN7Qm&$TF z>UOf*Rm99h@-Px=o+tfp4}b4{EQI(Y(-Y4<`^@U$`0(t1dEfiqbn)_~Z@G5u+2N(j zmy*|i#cR^R;&LkERPFBU%1Lcy%|0@6BJcI_#Pm8j);0(!P!hZ_As*vhFxd$C;^B$p z$n+O#Kf?`Lsh|-@5$%+$=AGO}3?0K((mfqx418x_q6DIozLcxHn;Uf1A*WQEG zA(LK}CDuVTtFab}qC~}(et&^tY8Z{CbUPX$gIP?em^gMUFRc)%jAx&Hp)JAEq)E)x ztG76F_87-sdzue__#>>XoaM8hdWyHc?aj=JLy{zI8TXFO%?)n9c!s^*5l=kvBn!g@ zoQp{F4x@tusye(^Rb5gyC8<()BJeTz6m3VOxumS1tO^!fmn4C~LX2?@TDvg#x6rMt zFI;DJNN=MZ)5(O%q(*BH%C;uiqmr?}j!06);&6r0=#Ybh zaoF6*fTlj$z-e8hn<;sgu(X&3;-pgKX^hb!%^;Pet{Q~TP_ZY=J)Nk7tpcLiW08@^ zIvosf-lJrKkOtk<_;$!qDyAqZPMtcO4-R+K=D7YV^3q(ORWU0`iX`t%LX3DPKS(;Y_}LoWSy9bq*_hl{vS4c64b9Ow-afiuyX&sG^L>!mtZ98x1FQ3h2FaU#j7`N z?Ysfl0{E3*_?Hj;>`%P&6@_z&Qb}|2^zlbucIO>${Doitwdzm%`p4t($yrsMeDHn0 z`}2=}_5+tX!?>q9E2^KbVxvGxi>1Q&wi!_PFu(f{VG=?iX^V1{Z1JCf(5-`9;)M&m zeiO`L*6Ej&`&2mV!#}=ZJlo)K@4&wB^mCQg&2+GMwixXnJpSF^^L-~DedNg>_{)F! zuRO7SW_?`<@hR{9!p-Y9zU-lgKDjq7$I-%I`D?%Mg-4S|A9>sv)0kN?vr9{h-HnZ{ z>To>O&RWK!L;3cvd)u-1Kk&iLG*A3+p&y+)b3Q#hI4sh<<9(7uuY2YFZyPN4PTh9L z?fv2MN*-ZUQ8`gJm5dXKLWuyTk$9gH#fqjWh!cSqF9MQ+(apAgi4@)Vm&hM2)84nh z8>R5BnHSmUcG?yajHyvk);joG;10og?Xg%_;vFr{H&o>wwfTh`m`3Y{G)dd$!T{@0 zD#j8tV0>8jNoNq)R*E^Q^F3lT2ow@Wg^I$3rmhT!<8jD&Zyhk5PLWcPXB}h|B1|fZ zP|A^IAupdK37(iF$q?SQ?Ro+2oF)-XUC~&Ju@0-lq%r6Z=yV2HBRJR}aX22$Ntzcg zoo9P{mtt0ur5Silr<>xfqSjzs6_O7q(oFIDANe@_?h?K30%?}e?=PT|G!WWMjWwW~ zmWrstVbFe8I6U0N7|+R*XXy14qzW6Aey>BXmj|S8n)BJuJWN>?bh{a8OO9Ju=yUsp z+qn9|b(9SLpghY0p0?c%&1N$qm9n(B#tT=U=eg&eqdypuW)R02%fl74HcVzyygW+P z1a3oBml!Q^b;Qk^FL3O{faB}O>Gua@d5$!SrZ$X5`-~2@LY%AxbUEiaapE|~jxRCV zKMaSz3r08=Q)^qUC3d55~-<6YzN(TMP!yrU@M+gZ_ZLv%u2w+MHM7MUe7@^vK8(5utTWSqGWv z*y=Izv==V_#!}2Gp1*pXTN_)PJUhfXhc*ef-F_$Qr` z*$!KQ0|K%|u2-#pNVT|a-vW;mMq8rz2-M|K993iI)OAH1hb@>8ptVPc7;81w)olda zVqFuW?j}VM<7|VrCC)pfCt#C(iK*KyZ_7+Dx(4CHW!qV_FTALY86@3}ul>ev|FfNy zQ%`+KZUD-%lzE;zqxJsE>gsQP%iF)v(3Rtle&WHO{k`}9*0NMd97l=JjS|B5u)6Ug z(msy8d46-(zV}CeF!}kP`#E*|Wp`4{8cY>#vi-#YciwrYfAo>h_?4_zz3uB>Dc=1% z@28m^s$c!pU-d4s#4-zODZF?Qh5M(d!y$-gn)-it0_R zRNIFWar*3SxF~`MlrzM_;iSjOu)g+AV!fUduw0wV7cyj5jxd}~*zf_7mM9ZcrNLOw z>|lz~HPg{PH*a3$=_`-9um6Vcn)Q~W-+03t-t?dExN!2RSHJ!%S3dojPu;n*_h9*j z#~%4R|MaJSGJn;pU;Eeo{5O5;scyG(`H3eU6MLgk?3_q@-Cm?rD&koAPAB(!dxvsi zVbN#3)MshOM=BP#c1QBU9hcnR-VRZgh=t`LZ~NM>_G>3kv2<)rW|2yasiR^#mDOY- zqO=i84d`};VGZ3nodpu>1CS%l(sm{01MDIc7$8K}J}AOe5Dw=TTeCp6YgzCvX`31w zRNS=2NrfP59sZKCXoysx**ThkRP_#L6HrlGAsV#>9|DKLw;lE7DASD~%~P7DAy_LkHC zNff7nQ6HyRZ&1n-tB9u7D49_;Gm1$8-n6h0MJyvCC8?`|EXnxb2R?`pIqU1kLnEAU zJpSmj+(r`OK#o^aq?je|8?5QzAIZ<0xb8*fQNtkJ)U7k}*m}6lIOnp4oJY z_j<0$OOc^l2$0qd{XxcwleaOO6|AlTgBx}bO*x1-+G#ZiTIZ+Jz zqfK^qH(4C6FjyE+Rb`N8q7)%4nM$atnrl~YQq_knx<*B{}fEj)#oORHaHU^lEdDBJnu0W!V^tvZlT3n=QN@S$a+OV|Pq2FC*da#eNMMz^{5n1p#jVB`_d`xcEcl+zg-x3hiTo;}af(i&0RrK~OG%+N%KZMARc zG?}m4g=u9n+hW*T5SSFLc{rMvwpr`vaqTcvgk1iSXTUoRLQu@Ab{o=w2%sX5!<#?> z^v(s1-_@Zr!aJ}H)<$?ELVbKogKg@XS{&lML^cYm9mZDJx<*<{Q(3Hc7<1^Gswghr z`=<9TA3MGyq$s{5F93O-JAfofJWvBP)$F0~`9Ht!6KSt^@B9A4Z!Pt^X}6M6IVUM= zS5FQn#cSSj-}uM>=}-Je-xPoKGavuRz^IONrbM)`mbjbH=!(so8}@6z=F7K#;a~jo z>fM7yl!_uLMaM}keAGqAw%GZ<wn7QXO%4I7TVOY&vCH9I(B! zg`=TA9CF{6eFgWt>~4-7TM4fDstQJ(re;!WAy6Xk^^hV^5v>cr4eRuL{Vk*v$1zD7fv`l8AeEh9CR71I9A_4(K#3S7yLbvrGh=ZulOV(2MG(F(O<9NMo=aNqK!q~}PD`u{a{_p*}Kk<`4^{)Y%VsieMf8iJY)33k#7cXm;V{4T@wwzq~wO@PJ z+itsj_s#$Qjm9h&QdMb^%7;Gsq3?X)z5o7)oSmH#X`G(F{gS{%G~Oc;K@{bozq|cl zBP6;>h+=^gGlcKreS>pQ7bRfW+Z}OuIA!DJHrK9R=jM$a61Bjc_nbi_FH{717T2 zZgS$p$pJ!j|IK@TOBO}J%kMkMYhL%&yz15WaeRH1!9p)^tF6U5gN#&&)oD*8Vw}`C zFL5~H7^DbIdI*WLp)&V~G#9i;^`i4WR;@!mOpzfwA0ef~*q|5B`Qml!yq&{yS}hlY zQ~{oJ1Rx1Ke%}IZB+l2txaR__C79-9ySir{!3;nZgKv?^LU zh|o>L;o$)r8@Jfo-JvWi>bjxV?SU7hSsK7hQACo)8DZW4mYe8%SH4a%A3!i9_MZg2DClTYwxUVaZmkmvavOPs_ZHs-vg*X#3v2R=xz z+o#*@BBUp6*T|<%pQf%YaTL?&8QK(-<&=YiL&_pdB*r*)cXk0wr`uz3aXF-RTtyN` zriVbiWyB)IoGnpK)wJ}DD4yVr?W4PD@86a5) zhhs3|LYk&Y0CvS0=g*y_EDqTpjZm^f6bt(OJ_6mA^u$!vjB?u0U+B^8bok^aKSd{B zAW|s^%W&8u?<7p7Q)ZJ2DdIMU>Dmoe*oy3r_Q}$eBu(k}`|WE2%6;cEDtEFt4;NiW$?%VVhJ5u%W6d z!xReSc}Ctz==2h*(lDKrco&nVIY|;DMZ&?pWpuF3+S&qZYbyW@heIZl5j*=EXbnna zAUtsltE($?IvG(U31no)Y&NB;Dy*pyD71Fq6t#A&oLFPn3&`f#^l;AWIM|zT^|?nu zOgSt@te&`s*Sz*EoWFP>_yWAgv>u&EDTGg{ng-i`--Ayf2~<>}+RlR`q_=J3x*(Kk z59E;gkw46cB(doNh`5S-Xul=o`79#r6 z;Q;(`KS@5Q0eYRmjjGl+|G|&`_`}U~^q*CtPJ8Y8hWI}@go`3yJpAw@g>X!bF;3Oa zP=OdH@@ZdJAeIqzqj`jKlxJtJodTIzc8K73K`|Tn`IO;EAmdN>blnd zV>TMyBcq&cipjsZbm5ZxjbHu6AGvw;iM1DQ+(?g~zFpxY2@-88RCKiVj7VdJhzzFA zarz`)?Qt+ZU_2?faeaeZw{G#m^S6*HC60SQ%-IW9m@+H-|zKUKe_JT`qi1s z^NzuLueEh$Syg+xyZVtw9{afT%>LkO;ZLyi!H$ggl&|@2$n7f` z3Vu3Sj*1d?cJ|oaxyAneK3A{4KokeKlaiiJp3(1xXjho@6Ksnc^=)HdXzvrGNrc3- zoPDUOlB%|W!lo1qm&j7EjpOie%HgO+D8XZoKgPZHzJer=@mQ2_l(P|WqHsbooy`Ju zEm4&9m~Z>GZ{pqW{>;kuAniH$}i#`w-PrGHfeCQpcjC zz{;9_zel7};v^xC6y1KtaM)DU}yV~vTr%Qew?%uU{<;=@y^p2F^@fZ z7pATg>#LkSx6bzVZji;SM5qWAh0cSfp5m-P$qcOplj)4XphMFblB9zZyR4lUvb5G? z&>yrhtBB!3pM!%DJ3Bk1c^XKNZpyRIKErUK&*@X=s7g&yPHE}}WYd!R4BjiUJV6SW z%?g|qjK?E7oi16H;v7uIHPdMwE{5u;pCcRw#xz8#!@|Jx@>kr&WHMnqp0c^I$?EDc zI(guocyIAGOp;YuQ5Gd0!O2s{sj7Gpi(-r)g^P zEa%|xkg_NPU@CeMT2@svu3o#&!eGGhWigm-g%5RFNx^+Irdq!o~@>;LywDY zu%^L#iD*fQNP}<=V|{CiY`q3ekUG2zuSqv0!UeZ~qYJzSZ#1|H+f*1^`MPX8#x>5E zotM4lZ4dpq@A$5Nr%}8A)60PVv_DxIdjOj*d?JaZ9#2On;VTkrU>e^@UsE`1PK_m*ZhEmlAK z@aLx=`{+a8diC0s|7~OI#v4!HcDnm>zw~q6rN!mW!f;U?9FC|>!QSBnB|S+Tq2egO za75gC7;MnM#E~W+5)4gKwU}5n&%7Ts8G3IJk^m}+!eOtXV5$iuy6`Kp&R}($A(pOn z@*jQCR4{N^J4YRdv;-LIp*89mtJ@mWxRq7JJYE^P5oGJw4bd}e!hZ|yd=TCuBZaj! zN=gJNN_m>PrYH*@f9!EKHn*tCrkw~p%gakR=R(#!7V}OA)uL{d3N3xXd?rY?f7yG_AkD7)KJPi32CaxvRG$J(+ukx)>c>9+}t7rSeRc%>w>au zsH(apPm1T3uace!j=n)>d2-wXKfvWXyQ7Pq*9S z@ZlA9cJ>G%%7EeHD3Kr~)b)g_ZU|oDO>B0##^T%z zT#2h2jBNs^dH2j4>{io7AnG^GK18_>@StnavJ8}-#{#W_=ce~1urjye7^k+ZzgFpOV zKl0==f9uyi`>Bs_TzI*&{>Gc4zj%njpkQnJ27CLvZ0=v-)(zOW;*i?0v^L*2fm2B*t^^!I=Ma^vgj5B;GZxiLS#^y#BVPnN&uhd#M| z*O`;w{JVeWrwAeRt*L9BWT_Bh@{MnP?flmE&XJ$|$)9-i(MKM5234LvbNBhVkA3`^ zd~SY__+aFCJe5r~7W=!62-4E+q<9|#Fg|#K3$0H*5ZX|b6!9$+q9Ql`Qs?bM+O-c& z(;g@?j@H`;lvWbw9oD)wiLVY+!y))skMR;Ev-pM|;^D8PYJ-Hj-Ov3-5t46(MgpCr zaUU0MkL_Y(zz2i#7OgWNZTtD{DA2|Sfb+5E?geNqscXaa^&Ku;xX5HOWmcB-dj(R$ z;{5zU-(Dx0G|A)0RXDONj(_7+BebMIiI$Q?(;lud({N++2CsbUW#;Dk-2cEmNEtm5 zF|}Obq(##31E2U9&wb(RG);*}48{js<+*t23U}XqH+$^y*7NIZZtwDe4?ae~V2nkO zGv2pcy6}1{{jrqgj6AEzvK(LAgWz5`fRBVIJn{l-YrHQxf8SjsN#M%mTU@zx4V@%B z`^-~#Hz6%NO5{`~ehtC#!DpV}rI+7eI2_XHbO=>Mo4)hb70%y#4|&p!kePZyqB~gY zsT-IYgRu=+R*+>~rqc>%$0TV7W8;*`*wC6S170|^OgMUMh2ETEXM2a&Ub@8L!-u%@ z^hy*5c^5~v#xOHAfx!GiA0Z^yH*Q62w~s=a$+$+VJ@PzdJT7S(L+}w)WGj#Lfe@+) zyP;t=tC3Q&Fdsb}S)u6l@)pkH2%%r( zhzMlz)GCE>}>C2>^51h*}8F^^($8y z?d@`S^$?GL*R$Ml;sk3)*4W=4GTa^G5=okLQ9&S*SlUa{qFtlKK%qbqIbJb5DTPL; z7$y#0wwWV|_aX*eTT^G`dPEzj_o8hF#8!q6u7&=Xm>mkTJ=~l2Vx2N8OY+d6sp4Vn ztZQXpo`?)e;uNQKN|bdS5B4?(W$KcquJP95Y=bo;f|=os!P;3c%@|>=$6&qp(`5eW z-hKBz@%#^c@{>Q4b{D_1xw$Tuk#s zjm9HPm`NR6(JA!#(pFz9bYB09d~UXy7D7ry=l(q&ssTADf)#KKB(=*HYPi%4x>dw&Tbhhgdp%m^;pPLYgN`$2DgzW?wz{x*jIpgV5>1@;)2M6 zahvVuppBW``O`o3(<)K=d(R#}H2CzVKmFm=qif55@vr@r-rPbb^Gp+GgleirOqwyy zNTIS0s;w{jAP7O@Z9=BojkmgOy%Sj3kfd?sEJ94md+$-&Mz6Vup}gDGI%{2v<-H9@ zF?gQ>iZn?Ms!mN4|65?=TVaSS?D&T5aNeR+Cr%04FrI85+P6b_?dcVz8alqwD-|$C zAj!~5p|cd7M4*k2zy(ZWv7x~lPhHjAys^*TaEFccYYg|tB)UUUbSR2~ZnsO8$Fz2u zCP*bn(mKD;T%0PE@-hBOS?!W&$KlI7pg>#0cnZ;hVbzHx; z&urGv>Eu}JNYVu7VLBVr>vkiM$9p7E$dY6UX_jz(W0T-hoc9z(&i3{;i;HtS^6)uM zoLJ!Ml?}FcHdtL-p|LeeT9TwgDxzRzV`H6r?>)oouYa4-XrDAK;;2+7TzLBeO5UzY ziB|LLkRoe!$Ofqd-EN;*Ibl4WvAnF2Qqb#X^vKxV9n;iATb&48y?T{iFX8m*Q+O+Q z_nmc$Vvc^lAP5uRs)NL1+PBrfTz{U0bLV;O+i!u7EPkz1$}*15y%CtERX7u?TM^-) zNpwM$jaXY-YT;g%#x(T%y}14m6-lAmHVarg(dc6*pu3n?) zb|r$#^`BmuPD-P09MkE=>~;6qzU*W0*{LnV(Ov-jb&&bM4P)mZk_%lcq7r zzM|K-?}2+UbEfyBx=Jqv|(oAO+li7sfc!aBK9)I#l&Yru6 ztVl79WI7wMv9*l|8r|uFkAH?}K~u3DFWO1o?FNo&L&XBEZ;PWMHk#WPaqo~))6{}A z6{sYVKb?=O0q0CB5{s2PAKI6l5L*qwn>IHP_wtSyDxK}u2vOl}#CaQA6W?i~-^02Y z)-~}WSv$P7n5MzHDz*ShLt`4Oo#AX1TvLK8y%3cv%gP4d9o=*P)4SQi^3VOQ@BYYF zm)6ccH>rF#Q)&oM8Y@a;MUm+6uT2Q>w^YBI&K8SYJn~O|;phLuU;gwjKlrULem=YR zv8Si2M~=Vx$Nu<_{+VMZPc_!sky5Ja_xm28t|oW<{vZ6oU#n&R*rb{0-Q8XP=v^nb ze)50(?|*1+Y4x|Htt}f{B+fo8FbmV9_t{jjmNCr!)4%kW2Je6DyPmrA+FSR1{)@jp zICOO7i5I{Ajky~)cT<<>ba`P>I}-_YJ~(9RNiq>Y1p>j^;3kty~8i@}LTIiNF zkTTqxvAQy#tQu6B#Br?*IDFeX)~#($ptZu-_$DA_B%cZ4;uzAzUpl1%S|@EfyoG19 zY<@x3;%nnR--RgPxoz)C5=mofyo)#am@kOg04eo>I#Y@`Zuh~(Zm(BlS?oLOB*Pii z)(2x4$k-VA+1cIY`nBt9Uf*Q6zmE?Aop|y*j~sI$(Md|0B+y=jvMeD<78<< zpe8FMsQ_s~mcGuhG-O3Wmi2i3+n4ZOk{1bik&vZ1N=hDl=nVV&BSMJPC4t8Knj}dP z(lZ*3utu=7w9MR~!$15#{xM5S%M{(5qUh4=_HZsR9*rZ>&j+OTSQB#|)>T;Rm`uj( z@9(g*xWehvXCkc0Mc#u_n(NnZu)DKIuN!sYQaGgatgarW*PCNF95Nld)_N$g#ve$X zvMi<7>ktTh^BXUbW*VI&q*?qN2?A%!7DN@|y1^#sBp!BkZIIG2H|VmobeOvGj3;B1 zlyMc5#-zPgDOsM=G=`>*?>TulW3afu3oks6^PW8GqIJTNBWq+?f@$L3IpSgs*2VpL zRhK9wxO(jxdDh|N$vc=|oI?mjnikPEr{feyE242R$&ewCXhGiTlSs`k{^HLQT!hUS zW3bj9{1xF^a$SOuicYT}O>`@<;ys0Ui0i%EBAY-U%d*IoXu+mU(=eG#FcZtw^=rKE ziTA}ejx^kH@=n%{9%E@RPd%GanI<0UP9e3A*%MXZg?o>l=|ekZqvd|YRZyCA5JJ<` zO>3#tc&|Xdr~CFk28D$Xc&FQtus^5;%E%mt5c5se8l3g`x)OdSvjlq~1jj19fG+64Y0T*Jn#5B072~}f}e(HlOZ4kB@O*hK5 zlTQsFegB6?$4{L3iPI;~ep_`qSF3t@H^^6m7opSX{4=eq|HfSaZr!@oE3(c?z^JmC zK32{qp)SqqhgXiwf)JZp>(De!xwyFK}WPkCZnNw-?_Uk z{`g<~k3Mks0}t)~3)||dSvSi&)2g2Rn6cZJzV-Zz_v~zLJ^tM1pTFb6+t(H*P2Cf@ zNUbqyG8-mdD5YeEGggS;;|_-=gy2IU^@z+gcGO(Fc%}N-$38Y$US9dk$G_+M-s*OX ze{yJfe)ROyALvS{um47N!f1cEsI^u_w{t5vfA)X=Uw`)O&d#l8KmXa!p8l?ne%GDn z&fj@x`S5%{FN)L&Axdkd#S4re&od$LD6K$eI0N1`NMY#}3FFBS>m0LD!{tj?sp}cj z={_I+$am47J4{*I_H9;xR9N4NZ-_R%Sl7ATnf2`(x9TJ_Aq-k7tNa%Em_U)Utl^|Q}u0%=DDjrt1n*_A~@7`5WQJY5l zUnKPj@;u|l<~Be3_x?BTzyDrVSCBX^Q$5}bN#`^ju`};d|J6-1HyEs3Kh|!=> zi6+fbI^BX#ed<%uOr{eS7nhMj(d+dotEjMzQlGe&wXTd4@F3d8gJLwgNxw5sniO#g zpe<54K+?$v1Y&cglP~i1m%aitbUJ;~q=(XhvKn#U{paxBFq>6)8^2Bn1JaYF9lTX- zo1x^bx87wunvoTnxw%1`nSfY3)vflr!8DMjNsCE^Za1fCYVJ6Bg3)js16=KxHc1qn zZpy8ln{3?}q9_m{kfad=C8XnylSj$34&&*5>lp}SNsiJflktS{c!Jg`ySum8+`P%$ zV4hC5OHuT(#t|H3nI=u+_gIPqV`muSqOXLQdjUzWv%u==8rE8N_x2E?AxqOZjUwQP z7r8X)vADEIZ_wd|7hYgz=N5V1B}r3`9yuD#i6*XILhzANrxZ=?==XD!5-cq)#X~kk za-P;1A|xpN-uf$1?e|0pym2TY5i+AOW0W-f)6aaCEJ=+%(R}~_AOJ~3K~xV8|9HtU zSXW1{M$kx=L|9W2FWTO=G)?N5uOPH}ABT{!P2j9!R+sI*JnDHTqdicP@A~LRIdXIj zB^4sXiUh0V2Zz59w+*0*s;WqIbYFxZX=+2=%wl-bI)e9@5ZNZSX%IkT0xG_ALNHj{ z;96C+uPdx6vDQUtoEgT(N^Phs6GX6qubg`}R{V37>;EQR0K}m~hr)0;OhfRQQeCvJr_PDsoD)fsXd#3v ziugsT>PGl-*7@#_eE9j^%CR#(sPxv2b@R;o9=-4ve*8avcJ1V;om`9m+c4m?Y*MAv z($4yYb8o)$)}Nj1??3Vj|L_<4*EYtob~+WAOuK`QR7%L%w8Tyw#*Rcan_^8Jg77}r z;FOTYS<{sDq*19D{+{3aL$|*1^;iDEU;fK~#hg5Q&o3NVU9-X4Ip^Jaq6=$nEu>V5 zb58gB{b^m*3)ik*edNb~{KuE?zyJOpxw(Gj_|qSGW_k7GYG+~bP%4pnI^9!sW2KZS zX_7^IUQmQQj-l}u-Rf}@nNiLrl;eGNw$>@DA*11x%hzragk*84!|IVaHg4?j2Y>&c zV>l@zn!reePOv6c_hO~dqEmsX-GS;@woYqnZQBB{v5Ty8yo<^Fs2pv*;Z{e5a)2Zi z?QZq_EnqMl`Wl5Me|+S!uiQW-nuUcqjvQUZIm=``jYwMOkV4~~r05i^ ztSoZv+7+%{yGqeX+1lFX>8GEj)9Essl_a_oCk3`XI2>+n%&4XnNgD9JAatyXA5Q4fHbLH{|Ql$*$=a?Jx5i(Gu2}0HgWl=(7jf#OpqnV5w z%4(myBT-UdOgy}Ly&lJppP;TLT)TFK#ie<&EJ1e?<_80U%b83J2+wpnUd$1|=i4E=|&yEz$A!TFO|AO;jiPEAUYpEp$ZL zHjc6ml+`vuOu6*#Rd#Rf9ZcJ38#l&Q)Rn=yKoEhVlar+}lVIyK{`+CfZR@QMJ|1YT z1S^Cv;-QRRxjmN{Z z-ybypR$Ksn%SO6#rnL>{|C7J=*MI88m)?G$v$9rPdGmrBZf$J*+|U2LPd@zcgD;w( zvLyG37M)QWL_GKHSHE+8p+EoN3(voBd^8(=_}YaxAO89`URfHCi-jcb6}<(e=9W^N z3@D|=&dnXJuip&8c#IQ1gxcVobI#XECMHU$n;-hnhqewaAA0VNQ>QjQ@rh4-vD@oU zq;@hAGnj-D)B zVv^ccdRCW0DJ8T@gpeMc6!Bm5dn=u~WU^2PErHfbD-?5DL8;%`c zVqsZg-ITZAT8EHQbW%>JHAq)hp|~d+BXT4vx$w?q64B%S2T#x&D3YXo`?C@u;$HFa z@*1za@+$AXdx0YFlcv$$mlru}t4ka`afIQhq^ct9sBTIolOavxnU1SA$R}98zJU}0 zok$iImgr;yX0r(aPtnN{A|hOOcej8BA)@$bFqot0YR;X#mtXp&&#*YZ$Y5@PvaC6J zY`Im&O8b}}NN+e_(mdIYDbN=IEcEvF&kfYT(tEg2Ws zynX{|Q;JT(i91$fz0!J`re-#qK@wL`{eJwJU0GSB+w1U+uYZj*XYOJB+GSSPmRg2` zqiKly^(0Pc27?7Q)~_?2%v$%lrpODjA}37+v*{$lR%Bd9MF?e}o=pfL91#AT^{lL{ zV2q`lmYh9*l*aB;l?^TgoQXfDd68p{V|RNuB-p+FFt;G;%c0ycOE3Z){r%KIk%IZh%)+D<-v zdkL)%2$r`imcc==kzyLWB{+w-5+`Tax2+ zSn$DG>wG#xr+^Kmlyf*CT*yU|x;#m$w_p9{()!J< zqu+V`wI8^(y?I1w`Q&{M-M@6~)QP#g+f9QMdUrUK)(0_AbCFGwk0P!unX_|xCn>-*L-iG(YakNx%j2Bg+K8~o{ z0FP7=w38(9AT_SSo0znBF75#HPQbbfV=Q|+BX(}>vT^M?H*RhdoTfiFhmtCSRqBr))o#A$>;kmxS>6s09Xj!+5`DXGhb(WEBJ(g=rXAGA%=aP8^_#zra0(W6JW zwtfk`rPnLkoPv+zStQ2BPPq_@xw!$)J@*_{Rim}0-|yqSr`PL}cXI05(3pTT#8EV^ z6_AK_jGS^~>vGHnIKlDb$I0@9rmo0~?0|W&yu8NN))p5pzKxWUEXx=S1}GiB4v)Y8 zF)m)bfHMK-Vm;Ga*S>ki9`g3ih^0dd99ccV&;9Sez~a(8{kdLyFr;)leP**6###am z)qno6*?w#MR8k33fd=Sk9({k?rQw|B{MO{bGZeQ^^nH>XdZVt;>! z$#^d+e_e{s0*#5g)Fern9~`37&AER48ketJL90AwBa~)tFd$7d)9Dx)Vnq!Rs7;AA zhG4~kAZlr8o?frRYp=b<&aHiRZ&l0zPAAY!#vwU-QMG<98KT*OWXQ!|;Acq`}+7P8%Z!5Cm0MC0nL>s4jajmG7jPfGF!N2c(64wNcjTeBn zifnBR(^^->T!oEJ0NZ{ooU@4FFs8!VrrqJkc2IE9JK<~-r9F*~QnI=P+fY?A%4&+K z4R}xRhH^RtZwNjF(ImmTnbld-l+E6x=-si=pI`anhd%WEUwi+Dp8n>nvbI~~SEjR} z0CcxAFu!vF_*eAtomXEv@fZHoANb;aX^%FIP*@ix)3W^VM?P8!Da+Tt{dO}y-%k#$ zEOyg0D@MbS9#2Zq1VmO8LWG)~?Qxinroqb8>BT?thyS2? zcV%v^U71F?>zp| zr9*QIr%oR0^%oXW-RY&n=~UO&Nf}a+Ak|Xj&;eI_f;G%WLq@|bs(Q%P zt5=zo9$N(tEgd4!fsOSyIC}IrhgTNa*w|z=Y#0m{sOuTy>6FuVonrIGbw>MBoY&lQ z?i{yvM||kRzl*fUv2CBb9~n;*6W7I)HC@AMv=igElceEaP52xR!I?p{!;x zfCCYiECotKo+k&w4r}8tdefNJf|oFvPT9J#&y}ke84aiG?++<*jZQRKmXV~2G|@<@ z$+8@+VopKnxVw*geGb_7iOk!OUtm@a2`+&1Gm0Sz&wo7QgZ1;*Elk#?{aHNU!BlP<@o0~WBHo;4eN(6~cQ8J?}Yp!2kXJKK$rOTISnwmW8FgG_~Fu#CzfysCn zr#d1<>NxH$%NeGAPv4v*l36+C^y$0kbUJL^++;c(qjmhADFS-O7b1sn~ z5d&-SXVqh!Zy)iZy=-(S%Mxqa@TINdh}%W}dg0Lj=HwWLEX2@rL`Ik6(>W&!T zOLFoei@I4H)+w3_j4d&BMP(<9W+hcAII_ILWAA&6yYD)UlnKT;rsbG4*Db)ywSp~$ zQZ3s*IFu6Yp&VLco_NpLDdRdWvKeH&@ZGNX{st|$kZt}!MHR8N@&74^l;8w1XuS2% zUX1FxikAlh##A_aoA)o;^#}OcAf%^mCI|_2X%Im~b#v3uG&6#?cpLp9!PW>Lp;RGQ zT%)jN7AF9<3?WqB8EI;}Gwm;&*zI>$zxKW-KJt~Po_gjB`NHDc`?FhFKz0{8i@X1- z&%NKd0JIlaCMhjZu7u(NlAERS*`f=1}jn$uEtcN)I`6F`)Vx5!f+4-6ku^Ogo{qkXbz3~#)42`M9X_~@~C`0ect5BBN7Tcq;nL~#19 zQ*7PX;@dC1$;!$RZtdM-b?q?c?mbC48^&6cjXZ{+;<$D^s+f!`w1^oCrQ*eMFyH0a zv7=1J6_v5ER)uFWs+rD4D4CFF9Y*63ySp1$XPKX0WO;cx!d9FiO+85x^CL-;B7|Z( zov^iai@AOurFCoGG$;iN^IaAf53{v3j2r-K>2&&ZIt5FI257A)Yfn{swzqHawHLn3 zV6edQ(h7^KOLRKjgRh(P4w-0VqUm%BdcAHu)Y?O+(^awE=89I!9Ql+w(y8KfOllC4 zq9~ZnW|U>gc(O}fIh;xHULvJI>(E}ZBd%72lr|3-S2QX*2o4?U@zej)-yzE~?m2sg zPB+C_PgT`z1yQ%PynRNaP42wwPVRr`VOEda$A0H@ zUbWR+*-il>%OwPbX+nERk4b%F3_4NmghIa8FbKY_6UXPn?U1h!p>iN9kk*@4mgx{9=z@KVffoLXmfw8+5Q?hE(yO79vvl0v0JW z)@o3TeCQ(|XMZvx(Fw*lthdmnbF-|72S*45QQ@6LtDL&7|c4f0$?$S=-LDb$x@o@4AC;ee3J=`%4V^b4X>QcDJ>H-M+wBXE<@hdnq~}#LnhNHWoejBE4sauix=NI zsE!Q=1C|f3p=Cl@Hb|wBDveT=YC_Y@sOvIbZqkIqi));`^90w|uk-mY{0jHnbB@Ku zMeaCp2aPGwi8=^k+E$DrMa~Ofd4>Lbtn*0;NgC;mhnJTl5;;hw)7b$W$cs1*jmT!j z#S0fO#-Vk}$&;t)_vbLiGo8e$Qw(!^qzrUAUGBW=7)@<>WI)9K7%jioAw zIA2l}1&a&ID5V(8_bJOsYwC-uDbeNu5}mQNb&KttTjY5TRw7A|+LPufCr{r&uivGq zedGkpDvUKWwvKyl2f+t^{khK}WMFY&g*#54B+m<+v*dY3w@68g9F^#(0&l@I0*Mkj zuAYe1H?94FDtaYUX5%+-)FO5}go&WICM?M2!f7rm}bo-h!zcoS70#N#mv% zYw!k4?c(p186$%Y&Uo*AWo;N4W18~hT~Cb9-}k^f=O23F&B38#|3k0ax%AsPGyY{h z^zR(~?M+Dbs~eZz_`@Ih!9VtQzVxY|dtx!^78BQK?-euW-0sd+DV!VL`_SW)d+s^k zG-dsn@BZk=ZrpSJ+?RW+hwRa{Bkwxn2j1Jgs;Y1PcE6FiWUfx~;+KBzXMbe0d-D%0 zKKjtoWHwQ0mWV|65h6PnMM){ilgOej%M#IQOye(*I!L=pDexh1cy*cQzw#>YfB$Jx z0?W#gqx5?nRO0D$q8P-73h4sEdlW5}m=l1|TFD~Zrsx!e;4zKIi3n(k z!WF~z`jE{V>s-6KK~qI4oz{vpOXzfaZJ#H8?kZ6cd_sYedE5(%fKC*tmUtIOsak7p z?T+bm^0q>z@y4TsVz@tKJesh*waX)qJjs>Im(fW}1`95Z6k88KOdM;jU0dg&NABgu zXV#r}eU_h@Y zN%Mv@hlQm+d%K36ogrz`L8~s4NzLoud57i0hk5MLN4UAQg_KJmJxy7nRWv=Wg>2UpqFw1URn#S?Nlw!=B#GqM(NoMXbb0H|cX;LH zH|TczG-kpFo_>EMOtu6|?>ycrcJ@asA6nz^;Wb`=^9?ecV~s}%NeG(82ySfcktQis zwI30$QsG0iT{_pqmdBB!y!i5q^ye1IvVwkpjwDHtQjjQ*%95zCl1Y1z#Wk6hDN@E= zwpJ<5m90-8{_IuNl+k3D*)&ReVh~cGllU`^@Ca2!Ku+KQGac=B@emf+=)n+C$s4^L zDTh~Au%X1s2_nf@-`J+p8F2ROS^mf$eFmLKCety&1@?xsmcj~3Ih<>ao+y-b?d9Gg zWQ2i5Mn??v-hRG?c4r@dFXI}csV!0nbehI{ONcKO5L*z&G&t90gp@dNj07Lu5J{3o zzJL|@V6ef&)qv4>-wMDS1Q$b$0!LX-scRdjl4ceKR_)<$t;g0C&Xh=RF>XdvH?i&H zRd8;{J2UgCkj-p38|O=hw(q+8!>>I1?DxDq-M#*|ANlYnY*SW=kh1iya{sTNd%tt^ zzxOd3PgV=z?tl5EZ+`UUmtN|oS@F>N=1sS{wmdy|{+?ewf6u+o&o3YO>TqkTFFJ+P zX(}z@M3SWM6ha=1Yszw#6h-H^bpdFm<72kd``}Of2S4)r&cE-ekGZs;r+Fq;*H%gM zJnjJ7J-H`f+ZtV-$A?-`bf{}XmgNZL@Wvy&h=P#>@-*ceU;C$=xoeFJZ(U|%eGh9K z!b^@FKSE=s^yj**l%s0--@fJbw{^#AfULTvsfcqphyh(Bv~A>38As3iR%F)kvJ}2xyt7C8|>`tQ=5ifFOSGy zG+MV~d>sWkN(nlhyal?bcAp<1JOn|S>3FCJC}%UOs$z3;eY3Ot_27^U@>Zg8|g@tA2=jZA6 z64Eq9t4_3@wPWhr0Vdz-K4Vv35~#U$?FyYvhfb%%>e32%CpHu22ZN{!cOh2!WWqPU z`4-(`o?bsAOIyaj@tnHzG)+?<;7M)ULB1Wlw4o+VJFFaDV{dqiUw`g7lu9YGKHXlA zJkKbK0%HtyUAKhBct~g&$E{Kcv{DTE3*>p;1`{2kH7q8HMrR4LY0dij7Ktt*Zq-NH z-&}vd+R-I+BDiw-Ds#Oh>as!Wma&iq2nDycw?I~m#}hU;x5?5DgZTl2g}L^USVe`i zPUF z%a?fl)wdYT&EtZg=yg~*vVzp2ebdl-sgM8wAOJ~3K~(0zMc@y@nE~%DX%hGTd7(*E ztk>PX0I1k#BM3;+IF*v3K*@sOZEQ0L1tFnn;`d=R8c|hs8;Z5!}xjBDbA0fn=zYPTr~&Y)$+bXE~U)a-g^XzDmkvc?jO zML2`ACe-yb5R5ZTRa=H*R6aa=?}ye;p1kW9?|I;fzkm4XN#~6}BoZ0AX>tjmnw4Fk z%sYkuoeRMKhabbTTu}nm%ZuwFgygsKCSO-GC4}&4R{XZ>8QwYFNcrgh`ICR+ziEo% z(V8M%T$mRNhYnHndMqz4ljQ}Csi;gvmUj*w;Kklc-=Lb-6j`imHH}3{XiN=3;e3?ssDze~1;Ix%S6x>mI_?r}0Ov#0=!j?rL*!gt z-{cSfu|LUhS`%anLSxjoZz|&9SooFF1hQ}Uzh~R79dFNebQ^URIA7)nWljU*T=|iA9*P+|( zvcEgxSHJKjARc0iivzm7oZwQ7@mO1Qz-St4d~L zgA}0Cc&J{vyp9lx#ie-$^F7ie#X8&8(gae)6E#hH?C$KxFk-6Oueri`Pq$NW_g$x% zPD_TvakL1k1ZOQ$2a-gvu&_XpcbJr8loEXQGoPcAcS*Yg7M2znEX~CoMC4OVZRyXb+_vDGIcTlb`9dq?{S5vP9{m<=6*= zjBBymfjH6HHg5y9;z4|SG#)2pu_6b-OKc-?7F@8AvC$rwNg7yOIK=AVqxAc8%&IAM zT_RNkR9R=xiKMO!Mb^W6(F&fTTO)08#iHe8L@cmt#aHq2Dn*7;z9n?(xayO-eO5Fr zNi#iI#|0lrgi$OikRr5nON$V3#BXhhL||=PDK@60X=+maf3f!-!IGuvdEWDzW71w* z_tq`fUDbBFd%Pb2he|BXP!Lgw_1Gvy*<)KD**$sbJG!3)%Rwe%sl^R-uHQ- zUnP7ms{%|urvT;@QCSmxU~s1-p9wAr?Josf-;v`IpOy^HqoN|aKAV)IAG#287*;MG zHlz7#ImQ3xFaBqLd4K!bOW!`b$A>;D+nSvHa-yoq^7nM|{qd3iBdABn;puPvw}1WT z9}V60!8EqDwc5LQnXTPjw6@IV>um3CaC~}<59xgW7eX%8v~-|81XNCpnp(syDTC9@ zrxmZh@*Vbe*LZmEF4h{l|K14l)a4Dq9$eq zN|OueF2_vWPUwfgqI3MgpZo^cijWF@D+yR7gd`%xN=AGk2D)y+!NDPSK77o3@4kmp z;#+Q7P1`o5ldnY8ZK@KXTS?WAD4~@WGMG}SOhzKAbXI-0%9Yp%x}~FI?pHAH2n*{rk*j6WVq}WozoXVY%%1i68$GRn_qQ@BcPUGv?a0D}>mI zPq}W{KRn{$qkXh8?C&3Ncz8(8naO0rg$tV~>hliTXu;!VQt4K*aKh1Ce{zql%{AV7 z`%T_`_Z{xv>50+v=l{c>q90B^>hu)2K~nqH*Vp*LE3Z+HMZ_j64Z#oZUEIT1L%(t; zUDC{AV6{3WrbH~CCFcU~zjsUQV=8j}`gPiN#Odit>Gb5<#Uy~A>1@hVPhID|ci-pr z-+7OxpSjM?#W^we<#Q=rUkv(OdvM{xHgCWE2FE8IrfM;IjLr?SdCP1*V!1rQId`s8 zNGcOurmYPj^n~a*JUn2rSg^6a&816M4fV~Ka2B$=p#*A zGoDyR6D5f0U});*T;VRC*?6wf&q)=ua1A6-@;hy%2tl)22D}?st(NCPQ>{(uq{Rgx zP^vQvTs|k>DXj=zQVz8eZ9xpKxC~->&o#kkAhPNgG)=>7He+{ZhpKJ_30{bKTGgC| zawXFF1S7_XQMRDG1-^5Zh$rqIq3C)q`~{;cv`Hlhi-Hg?>o2Mjh7>_LVT53Q$e9o@ zS`rn7YY<7vqm(o=F%9Gx$==|+G#FV$a`J@aiVMIHL&Ar^;09qItd``Ih(TNpVOWx) z+)GtX!mt>8j$YwH&cS!7GO6!}<6{`V{?$M5CmuZc#I^tV3t#^u|0+jL_5TYk}r^3Cc*=hqV^1G+E`c zlh+tyalT~J7hna}5M0J;h1G%Y{`$Y-xu>skw0|ETJ7Opv+3Zkf)xQtiyLUhg25Vc^ z*47wLTUI`UA!!zF5Rf^ z#T&1^iq@IBu`CwLVn1}$RgG4LqoY&d**7DBeYn7dtu5Yq`wdpB6?HA+WNYf8W_G;v z((}}{W^gM~l7nUF1wgY{tPqxXr0W(OpB$gBa4uciqp3$Y-xZ?fE`$24ula(T*w2ahG-C^{-D zKRX1+ji;`obKvCksANJ!w2^})gwcvt zg3`<;Q|d-0Q7EvLL1EFVDZA~n301&YIs8R)U@*GI7=v@3emKR472VR4Vue%t<00=kKc=(6MNo1ZqPz=cwlxJt=#9=*cPJT&8Us+7ayRTx339C#8=x05UC+ zfTWz{+U2C>)ugjX?t~&121QlwYI0~xlQNVdpe{v(=!(v!6Y^)FI2lF^E|FPbtaRWC zd(I8f%Ho477;y2{$LPvLAfi+xI)(2es9K(92$JBJQsMJU4uC@)6)evKm33X zKfKMoJGbe&o~9l%9*Q+&;7Gql!in=KQI!!}LiMp<->$+Hn&HyMLrM)D3 z8F{@;+c2JJa;~_2>!yg*g6G2S1;*nUZ@lpaYts$9Kf(D9Z8DQ?j@`DT24ghGDS$_(OOHgVhhu? zhUvU2ZjK14VQu~dufFmc*4EgnC4@lV2OjS~WN&Yq>rY)g?@muoj|<;iF$_J<$-aC% zUZZU$T)eo$-8&DNP88M(;3yuIp%O*+Y9Tukq;kkQ+B{aOK(){EJ`uWyX_p?y`xw7j}lW3`4+T2uXy3N)!;NWFQA(To7V9FLa%A;zWv> z=p3#)!MUEn^;iYoEy*bpoF&IZjy|u3Rmv&G;8)8yo*Z6$;>Fir{Ol)x^OK+a^!Iiy zz3}rn_cQ4GVaTB-tMPbx{G)!}d|Uwh2t9_CSKj7JN?X6SwO+mb@U}`(v52Rv%|{&X z-=l6cyX|$lE@GQVU3R#YwJ7BU&6-WIO$E?_tQAIEG~iYlqZ=H7%?nq#^}&1Gcw(1- z`ODvCb7PMXdM2|8lkuFz=?VLf9}`^W=-`yue8SrL6qE(6vF)7M+BVH-kB#+hCZk#u zvk{g{M^iUcW<+f@5ANUR=FOYjx%)ngWd|tgy2UnQHYancszw__UDZ^zrLtPs?M9dI zo-t%iBMcruRs-|Rx-8a`6g^diB4P3fYR{cpcer`;5#RaVx4Ck4jg9p!v~D?i^oT20 zuW7 z;usW(P;$l-l$+(oe8zljTE^vy@n|A?hT0NhM^;AShppxL=U?ClufB>k4IwVjw&LVu zh4%v&F6^QzVZ?XKj+`=e(~wXY+hFUOgyq)l2h?`Pa(SDa7AQ31$%y%U&SJ3;v@YPi zT)&tC>l@>;ei$>IPS{u*vA({B52sigsG2c8MBFMd9#8oE=Re0QKX{epaw%3pqsdr~ zPctWr$2|SC#MT-s>!}drbLw5BTSS7Fi9^*I{LzXOB06QFAK_OS?=;59$k`ah=6a@g z3Kuj14tuKl36XB$kWEEV^Sx&AcQ|CbH_WHC(;;EV@}||EMRX zn(nx#8I5o*rtZf-jFHl*{jc1-g>oY24#MGV~B;vNRtym#T z_>}WKwh}zF)|$$W8GL4Ox}xtF41Exmeb%Jx#etA5#9Vaonivzl&;e8KL@k&_b6|`< z7x^ir2x%Z@O6ZLUhJ~?Tvo_meedDUQWQqzuXK_4Kl`cZTVg*!U^UcWs710ZUFa=FW z4priT$*F|r7@QZu=XflFVi6*Wr8M|ZRuzAgj54DH8-g^z^Ha<>C~wJagGw0(K zz>m;lxjel#7FA$mCiyNW=&=Z1} z5nxQ7pZnI&bMw|4eE8uzSkq8dGrsl{pJ6m=X`5Mb4OCp%zJQNCecy@w&UtLgB?PZML_!S*=!dOTi;M-xu*@;^N*8H?Cjjt+(FgyTADg zKlz8g!T0|4clg?meV(?Fh}DcDXGbiPqWNr%ciz0o{{8`NI}(+;7FWi6KBcM+gX_sT z)Av0&DXL1WT;9viFje5a_ue5##eBNP#>Sk@?KQkp*s3Pu$te(nLmN%q)O20X$-$C# z(lQiAfS{o>8yj0(y?l-3vcow^v8(F_Z4j+THY|HtlkGoxz^ku_j$^*Q&hFk;aYzNXJ4VtErgvhF@7>1tJs^j!@Sw`^k z^Q2bHfI;af-uR?Tr%XBM^Z6cJgt{d=!&HTwC)pc0*@Ct0SS~w8qY=Bi+e~L8rqdBA z=yK>Q*`t@$0wgNikl{STLx_Dz5+{-3M7sK7*3(*C2Bnif`~KvdsH=}w01{JN)pDq{2jq16l{-05N#7l4#^Gi0c9ZeSbm> zp6Fq<2t>akXOACx@Bw2Y!S|$~QclaH?8o$b3UE`{9f<;yRg=3XL|3yboAin-kYzy`qjao{M*6k347~0 zKD>=iif(mE+e|q=JY+Uor)~`)NMMF4%JHhI&O3oKE1E+5wnpp1)>c>@aUnw1oSZsd zcRDovH^4TwZ5tkiQipgxu&h}L%?Ji9-q8pAy^ zpu{^2frs~3?Ck7P&l)lgbYOd91L_kFPwz1vuhDmj3zyf6P%7a~FWM+I=5%qwbT+{n zQ5V;BgAXfA5!KzhdzX`wQ@qbut8m`S@6SEm(lVOLcs}P$%&Ck>i+&<{LiEKeDLc&7 zYQ^T(2IEQ1;o&hxjrgtaevhwzXF3vXiuzy4A$k^C6Jsn>z{q4a;`;R)jK^bQ@@1?Z ziyB`5M=3>&)?{R2B|=zLvI8hPe~P8f70a!R^--q4yTmT3$_`%}U5awf*AmuP5nQHN zu-*EHP{u~G4^k9|g4X!pOPG!!rHJ>P6dehIQ^e#XMm$DRVeo?k2Aq!&4E?IZ`+=AS z+^VNvd8~4H*8u}MCsbBxwOnSc+Tem3qKXHfe(5LQdg{qf{!gEK@$>(n+S$JDoZA`I zvFjaSGHEiv@8`q+;|aj;)*-*_^k_0pr*RmeYd2FW=HpxKJ0IM?RFB91<-MD)ed6}} zuWocF_v?0juXSx|;z@0KJE*&NZlTEJWZB%fOkK^eZNu)RtE_FVF`AATjV6*n7Y9+% zX7R-fFErrXAYG$TXfj$!?H4`76q!scFaOqe*w|=T^*vBAS(~%9aRH6R)&er|185tl z>oLnkk1>{q4<7Q~`**o}?`?+FDcUqt?Yex?QB;kht~KNFSb77i3R~ZxwW$A<)>Kw7 zpV~-a(RB-kMTc`soL^zIz>T!3Kt-BXvI2~S`D~Mo%}WJ-RJuIv`RPCR)68Zq$4C2o z`72-K!qy%+8=6Kjp2!V*)q8d>>=woQK#Y;aX-Bu}82X-ERLlbC86;jfi`&8K2^TM4 z6pNXXFdni!k2pRfB&w_!H4R%^TZHJ?+Mck!F=2T+Kx)t?l2}q#BNP=eh=T)_iOF&O z`V;)ifAMP^A1|2CXN)IfATpcHnNDZ)s}=ofMa+u9l?;X`BjOMORijvS10UYH!=+1? zc=E{`j7B4|nH9zOYp=Z_JOv%mx}mOXPEYswu^;;?RRfP79pYWWYE2~K<3J3d1hq&8 z!1{V(|M3am{y)FRXf$KGHlwO7o15#96^o?+eNsyJ*h3K+3bQ_;jb~$XjjhdX9^K#P z?wtoXmsl-3zVekXf{OSs5E57oBu5MbDO;Yr{v5YIe8{akcTqZ0w~_+6y?ue%Y%WDx zh-3rai9OEw6*(KMX~-dQ`_2b^c;`c|UAw`PPd&-{+MKFR!kiC^N;f4RL0m7A2O(W} zQ&j|?G1fr#!n`nuS}bP>d%NrqeOg>4@3dh_-E6b*?l3mb1uel63nqdn!{Cg1~cP6z4%o ziMDO%`<@hypsh*5;l;~S+pPkb3u&0!_XCuM?>_PlzLJQL@&Ch;0LrCaPE|$k0h@MZV+U44wBd5 zK?k2>=*e_B#YIS*^t#?#K5^~o_rCV^Z$7+yW$&-=UViRZ&+g%|UyO#7_d+whKR5s1 zBYHnB0RDgU=vRGXw13X^{WIP1@i*Rm^|!i*k8eNMcl)34-d(7t<58}RT}7i()G9@- zoOhrctIl(Ba!g8&@o2>6`W`-wSlhh7<;$0tOvcphh|TRyR&GHiladH{gj}DCI4EOG zjZ%rKHj+4}G%7*#0i#+@PY)SQYDVLRd-onPpRdz2qyJm9=i^6*+`V^~2M-_f@cuqZ z2~XczgEj>hTWRV>RuQ&p%KlUQymeg_=!YyQ>XC?{>dKynf82ccCPxQHLmCzd7 zVrm7sDlGXRxL#9JRV^D^+f3JHA~HjrA)yfx}ne1^xTo!AVA!mIqK+72_TVbn;wY7D&x3)1=BI`uA3LNb(G1`)| zB1A7Z)tJ~^TVph8(FQ_rY;A2Zn@l)5-lwXeX&T6KbI!@2E#>tYnzrHIog-fU?SD;O z*UV=dw4;jIY{qyz=H%prVd#svX`pGgh$&N5QXn<0rZRKZ*VjRnA`waP3!$f~8*<9L z{r0;IF3EvNqG=S%MaQK}dp!H>Q{20MA0J}rz!X}^q$VaujE==(fl8Y9-?_zVHDGJS z*7iE4on(5kzjrA=y)_3Sv1I9*%6hDfLO(JfKDM|>GRZOQ7 zX0tVh-hs&&8?n}4OhZa%sAwx$8%liXIYXuDAL`6AgIn_W@ng{iC{wq$ZM8qP1Vl_rKnESV9x zOr(A|Xh?}J6h91P70Pr(CK%c%VqW2$M`zjpdlv{!7$3p+C;}n$#HdMwBY9Wc28!ik zL5>k0BQdy~LWj;V`EZ(iZ?aLUzwwFZKYaehFMRjuXTJE0dpB+zEmryEjcIfD--NU2 z;}yW~!XudQwMvD*@+&|051#eiQIo4qrK-~XWL5=?aoH(SRw~!R*bhO*x*=0nV=5c) zuEKkR3mIcG{py&b!v?D*uJ+{Ul+EoKr>Cb9xPitMZ?@JH`d%i+Ty~Nc=lppdcFLad zWQ_Mct1c70=icqxJoWVVO1I4b03ZNKL_t(D+_`_7+qXaD&h7hjOGi7JP}P>%+7zv! zwqp_QRTaisvQlUT+E^-E3*NM@gmPzcVaw~1_-AQasBI?r0h=t}`;G7Nx6)=cPE3+ifx zt;F6a1USe3!3p#E98|;L7qo57lQ*8=<*8@(m`tVwFT3BiZA&PR z<+GpuB(J{qK1YWOQE%(acs%C8g9pUqxqkgRg9~(B&#LQ7P?2MB9XWeqHmIbS&emBj zA21Ao(~~8W@jBzyFr=mImh%WxDeBr_EOZq5A3p*FtTD!vI zNB22h9LwRUE84bYKASU}&#CGur>84&N?f{pg*$g{Gn%#N+Av>}7+Flf#X!nZgj7{c z)fn1QNrbGV!xfD7KvjdOTC|Zh1vz7lE<{Wbs?~KR`*Uj{!{YRmWw(?FV4pCy!IVr0 zZ4xO^)bzRR)6dFP>4Z}j3tvo8gmCerJ-U2L4Joe(!AU64c+BS3oNHH~BxglkH${_> zajvJT%@0isG$}h=kSTX3k}Gr#M4_hbTM?QX=|53>IrFLtnH9c|aM+!LVEi;ZT`DfIoxq z`&0DzVZgaW^c_0MSYb6RQ7JR@eKv8GRCY0hh4X&7eB!xpEI0&MV~9H7guJJq5e1JZ2EWt@VlYz?-rlFfA`(L{q0}-g=a?_>*JHdmA1;EV#Fw; zvJtCK^ah{HQ4}LSbSNs8%M~Zb3rS>a8rIe}Ku1RHge#Y?GhbW7RF;kH4H>5<=`^Cr z=lD_SPDJc#t@z7P8I=Rc4}hX+TD%v)&*O*pc*h*0$JW*wPd@nsN5{w1bwg84Q5bya z@u6ov+axBiwME&4&W4kdMFH#>7Kew-5~@= zRvlmZ@>fYw5)PwZL5i|Fcaiz}8XtUci@SI4$RSuaOvWQJp+wdyhQZ73wuGsDwJ8IR?CZE^wZ!vK9j#?Y zt_p`nv=)WBr$w(Y^Z}(KO#{w(a;#{Yx-edpguzrMGGTC3#^78grYv}J6e&6ew?bu$iZ#wH@bQqCd%|i( z3?7Xl`hbs)98O6t;s&y^Ci%go7^3s;(PC};$)guP`L)-sU47zbKK0V4e`~aJ)h@c# z$kzIiB29AQmhZ;QH-2=%Js(d1ejh$!(;no(|AoAaKQkUTH&S(?o%bptCf$^S#G}?) zf@iec7z`DD2uvm;Nfq-6UD(+AQ~cXogP`0_2k`O4~D*zan$i z?FxpM9MQ&-b70kXCI8(}H)B%HOs6wuvvp#UOm$SCu1Dv-U~4V562OS2##oE85v?ST zyloo>*D>@5{gaNd=4KvNLq9&Iwy=_bZZc;&a>Cip|1dG;F3xMDmTqjN$+xbZH=a_c<|^xM@J{(vrY={5+^4Mx^7_a@+P1A;`0o{3S~UOFVU*P zxqvm&!MVW`Q)CznFTM0U@4WLmZPqkO5kpPW3NXn#;Y);&aKWFWW@D7F8x+_^@rVBC zH#j{!;?|va*?;_y^|ftKhWThLWVF)Vr$a~%%<$PlOZK7iFG=a2|xg& zL>!p~jT?L*CK2dqofy0j|0>(Cx3|mXOIMgorsaKFN#dn$F{TwFV+C0SAflBm&&_Za zk`-K*qTEVOL5_-1+Y+-BRb*X+c%e8D&UXHhVHl)wK*EeN(D$7r6RJ!KPV^xzfEJOS z6nF)pTkM7XumT1Bs;8=IyoW(v*VcaV6QBM3!7}S@qlea~{$Zm? zbv0T5k7ZpO{*7viKb`>mEsA8ivsRMifLQj2DJ6Uu1R&$& z%hWAboSZIEreS+)R}%J2##R-VFJEOgUuQBMF`I3nw8f`^q{I2Bk*sK{MnqJ8ASTXl zfGL5|#n&4p|N7PkA98doG`gy4%Dz$wg)f`)2UtHW zu~s@EZFC8CF{nzhyR*jM`@7%b;oSwFc<~w`AJWz{y3X^3FMJ;F2YeVri=Z`4ExXDy zZ0P#>7N@6yo44*Tp3L}(Kkx_X`co88)fHQtTYU4IKgH&3%I7}w35=1Bw`oMw<-@>o zu^@y5oQ*`q@4dTw5v^;UdFB}o_7_xkLS{wOJ*b*0+Y&tEB-5Ra7@)E(x9{FX8^iwo zAt}M$#odBEHgX-bVbspiO7Up_F7x?JLQ8zad*PfnZ7q5PrBGRO@9tfmefnwP-Pg4c z?JC3C`kaRk4tek052@;wx@iQ@TPeKD>|MObblz}$@`zfG07+ZSK))KO>+0NIW^}{N zo42@o?jEp3bVsU0a(Q-u%3R92<%IjcG=q6WkUm1fsDhw@wbt}QLGi|1xDvWdtP;WdaxFw8Xq3h~M~D$cAjK8I53E)Z zq9#R0PL9|Ig7d`K5$yw_hwMiwJDai(KBh-Qx4eJ!xv%`GTWj+Rf9H?=sh_&*_2}jG z`Q*{ZC(y?efZvnH(a}-cHdVd<;MU*zXaD3MerD~-i(_2{Bcm%{QqtsR3^GoISRySA zk;rIL)Ac8K*O7u$%2q2<=s7riKs&O)h_34xPi8XmkC9aJ*i%lZ91Ac^VbS=IKto$K z68#zF=GS$75i`MLJf?0Ma*68|Ww}f#tTi-+_;ohcuIt48`-i0D>4%P-70abeF*34K zKD!y_40+I;9u9o-n}3@B;qU%^j*m_mPit0v$9O#B``>?=FMs(<93KaC@ndHqO(Ub! zuIu>0tGDPDfe_&SgWLSkf9o5#K}N|rMEb7dFaM>##83U1Kf|@FSD8$$h!m}XGM*L7 zUKTGuiL3^UZOMr6@V$3G;L6oY^u2T^wH-4!g-?OE-h7vXg9Tss{1<7)Qdm`0&3H88 z`1FMFxaH*dlx{gNnM{zvuOZ=xxg#r0)flo8*h$QwjX^7@YQ>}(gI0{2H9qm&^Bf=T zOX`^^>TwcBM@L+{c7>{{`N1o1P*WoNHEH zpznPV26n|=;2|4MPX|V$2~BOOZ9@nHRjX;*3TsAq2S-PT7!%1!i>*yX?mxQ8=H{GF zefBwy4o^ur(XCF1$`idVX>5VfWJEKD&5d1bJ?F{m&+^Of{|iQwF%t{cYhqZ#dkG&h zI-ZY-1v%TCCk2kj6ZS6c64?E~XjKuyK+b1=eJMP&kzwt+r_jd*!0*{(UabY+EZ25+p8NjV+WO;(RToT!cHS!q zrzp0ZVwEw-u042((ag!Abfj%YxZ#MLJ=WHc64qEw4o+yB33W4}suaf7RIQ=56>Zhh zb-jq2QXqO?_K>mQRL_*qJ=z#5t(cjXqXRHDkr;$gu8PRd7}{1wg(-am=`qG)s|srs z@4x>Z7q%~z4%IQ9jBwr)L!_$AdHk%_MqCI(q^cu7{s%tCYd?6MlOxAyVrd&qWozDi z^DQo2x+u(nT(SRXMYlYm>y~7-!h2WJ(4f|qU-_k9;cH*}YQg9BoSpsbxc`_-moIQ~vgGLGkc_3$ zf%VNXyB9a{X`e11CTZ2(7S1Xih$SM*}$Rx(&hG7^8A#!+hz;rs|#TTCE z<(FS(KA)7L%rdN&_+cp&yK2n-{*ef&k~=57NeZ7rt3=ELvo(eH1FQas!8J@VG__?? zS2Uvb;R=2^Wgp|O;ckUMejV14o+Bfj;mLnl$A#A3#G1NG#-hoVLn3> zaf9OC(F1XVRF-b&$Tl$=mkE>?RBkGwIcr-+qnf4>mx;Bu1klKSoouKoU5X`{TA?Ba zQ#yMA&eV;is%wV9Gla;=@jhMW@GcaxA;p{i(ZDo>AkhQHLQ;GZ$&_+N#(y9M& z^l}Iu?>j16bLr|1JG)OaYFk32FzLl3uXKsk4T=ymwjRlKbP0tL8(;34f3ymZ$(1HWl_+q@cPKspLbf*;5!(^M79#e(QMN%KnyH>^nBlY^3}WjxI}r=)Wg z`&Bn6d-rth!t*CT_O(Ct&ePYP`?>2ceev%Mp0=sF6vFWZLUp&EPJGud)oQi0qtPUM zd>Vbc0{Go`0mPL?r?zL@-+$}%zxiwb```a}HlMt@zUUS@2T#%x0G^WqmC6XZq~(RG zgmyTb>v;6=4wK0?^R=x~iOU$VZ5u9L-DZ3D3bvjwnvNwvBPLdztc(#2fsX84xWM1~@BVw*W}O&4^EIIa zw(W$z_jnf=+={jtLlz)S#sMGM!mOz{K3VY1Z~kdEw>QdIHK3G5>&&135B?)|FJ9)E z=dOy#O;1Rnqgx$w{rU|??dY6B=7xxK5P7I6Pil)wQhycmV?6w z936C&yb`9<5p~^C*Ot@8si1|&V`lR;s!G!|Qx>O^Gha2P+*~EMeKuXAZECJQae)vL zzxnGg^Tf65Xah}^xv;Z&4qrKofDJ*>*fGuxeCNBr!Fb$I*CR+4Z8Vdq*xCBkAgJ2f z7OX5EMaW_qh83&fgy4I|<1yP8w$M6@9weso6gol7DxB+?uZ;=b@Xp)sqm9AZ24iKC zQMVP_7lc9=yyQGMKghHtXNHy769uZ2IC%V+*WY-Zx~W;8Z*k-L(^S=n5MeYGdstl( z|D@v;F<}T2j&(LYI}0H?v!F@ADuuPt6|2>PemKRsK(};QBk10$R^<@=f8Hk5`Km-~ z&Vf8BLRL}!EEx$YO0wq2*+_>>I6rWAc6Zs?*6H*+gvPRL`i0+_ZhUI&e2wv=ksDLZi zb?7CO$-7V({k|mXiDn=~NA{vQQaP9D2@FF#7dWN>Zs<@s;)W&BC-L-0M~pq*4G<;h zDaRovXA{vSpAX&2b<5427Y?3z?o+Q;iofyi{<)ui1d|U3QfJc1W@R?+eSG44JOTL8 zy2xgffDYjB;obk#R@1L(Z715;I_0dg(BB1wqZ_h!q#UR;RFgqQv`futH=x3plfwn$ z@eHHE6!P4v>p3~BsH-_!yL0-^F`h`SdRy4-gAat@1q+PER3lOr?zSmDcj2#l_tqhjp>@m7CX7 zPd&}+Z@$JCW}l~SY+pZc?Zf$P_wkVDTzNEJp;x&GucoGy+T`cQ8E z4z0p@T(8!OgZ(AJTeOzq0M+6AilGnmt3-&a^J|z%EW2W-ijK*o=HTF%t^=hl^Vx`G zB!8To8CLOpY)qDQ#Lzq5dh-LGfBqT1`qeMv+I47_bfftpv0-6}%iEG!{+-&*agZrEuCVu1BUgqmR`E{yh zV0&kTcYzoc#?%VOc!^hEeVu;jF~u%ttCrK{F}79&uUT}x(CD;u*C2}i zT&!Yi8=LflM`=sdD%vSDjUarRwmu(0Yh^H|DyfcQ@2l&o1THCzt%xz5|2A0J0OuMVszVMyT zeEMtOefGI$zjfitbN9l^d8L{k?&?22{68)LezYI!7xwnAzwqgQ`N8`?*qdz3s%26t zdtYdOB@n|$g70&1y*l*A3_UDPBd13zMvZ3Kuc)u?p6~a_P+QINXu*6kusl3wG#fMM zj5QXeHJXeYd?A&I5G@xRXbKs$jORm9?8XqO>za!fFEaGvjW<@|oyAs){euVmwg2L; zVO7a4*DcSz@C*@;8zlIqTR2Wn7EDH>Qm&hf^Wuw7F)(UtGMUMEN{o@;`R&&P6`O>O zzFHZY+EZ1bD34u96B8#xjI#GMMq#aH_tGv~+dEXYCaK7sySLcdy1;xs$6Cwr$$~F^ z?MwXBpZ$~k>)-lKzVc%);qw96O&GUZ93Og`c1+NHL8Atufe=F(`)0KEoGyl})Sz+2gIZZ&B4F6f;?CC{Ikn*FQ%hYg5EqGHQPF&3CwR zPw;0PsRdb#XS8lHdgX_nm~K3~U}%+SNpJ~ShP(ju5_nhI4JlFBHX`1I#q;2(eM z=h@xa0X?GYG}HN%Vd%-RB2nQ>I-t_vB-*fy*)<9HV}JaQW2=f$I}*XEk`6eWn8bp{noSutTbGE3W!slE}$a(r8lwEkvgyb=%E{I+6 z<_mTga_&h>|9`H=OXLtQ=C6VDFGl=^%&QeLLr-Tz)w!;Tr(iownQkW zD65Dl9lbObMvA`>L1n6{DZt6{ zrOVf@eM%{H$2CdKmxr?$=uaxjNdxd(>a-!GQ+xaW;8%X>=fAoh4#s^*Mc4GG=+km} z%yO|veb>c)-olQkumPm`*91ubcu_MMZ!*nz%X?*Ya!t>8C91mp=X9tih zWm!@bmZ)t0$DJrjBhjkPVGE5)F?*mbF@oz8%Vop%)*jw1385iI8DaJ=a_#zM&R^Q& z&aESsM?GzO#O2FZiAm8np3)S!zUAI+$LZ7O=m~Va#~4jj7FaE}l*RG^pZfGO+`oTF z*Y*^pW-usNE_z6Yw(Y3v!Fmr#78=>YP!t8z*_iF^Er!EFcAzStwZmk0#bU8wV{?P3 zBDNgy;;jSz@?ZHIe96;qUX&bRh z39?laJoKGIX@#*eh9#Bj-D!%7gch5Yu0@nrYoOp&H*WB$U;7-h$rPpK@2s?aSZKV* z6F53P#1>H4ib1`}v(LQ9-sve9FP-7&-~hsard^V7%pY_TjB|VkThubK84igtiW)l} zGpK9HlhdN%sH%#xDi{oh6h*}g&)=eHkI+gp7z|M=ad>>l;b#sxfBr15d)=G4f9Hr0 zEs35GR4&XBTR=S-tqX9|_MF<^;@*RM4EqT&C5oz~u1kmp7g~I9q$F7Y#wfHA5noZ3 zlvSOP&U!t4F;)a`b-B4-eWc_tM$`9QX3EQCz!*c@N;GocJG#!H$Y7czlY#M^CeKj7B5Qo}V$9RE)+$5%D>3!ASF92{BR@ zT11m{*bK8mMN(YZa$OFwQIzFCie>~`loE=g4L*2`DsvMg`WUShNiB1OV(9yjKORv@ zRy~4Xj<`h5yzsJypuoFcbRj0twSp-QuE#C=9Pe8Ya{~}Vplv(ZHYjQ0WNaVl+K!Nw z{@z1n4BhgGu2~Rbg3v%%(uF=jn~drFylb5Ay5not-~C|!{JZ|umwowLKUUeT_imj! zGjA7N)x}0~KnE%v%^w`krkmlUqMT>|e#@QU+vz8N97ZBp@Q|NNuJPrmW#(Tg{Kd2DW{DfL zH939^*wZ`!03ZNKL_t*6qE*df*RQP=$kW+2zx+#|;7|PVKgts~o??G*#<_EQ6s2W* zYn%PkdpJLrJc2G!7B!2-Vx1)pk|*A_Z7xJ)A9@fAn30`-Sru$=Z-`Y2Ls68Op)Nc4 z2M>5=Q))eK#f*hk*;;gA~eZslOV$svJy`(GV z@6Bqm62fn0yvS=0+T?wHNcnwO;6uCKnM=I0GzqRpM&-d1g2P(P*3Oi@{Rv7#VP<&W zum3G6rE`K_l)|0urfVc|AU7jAuVxG(dLUvfgwUb&N<6D`^P=4LnT&Ix5N#VCn;AraCc$?0{vWCDB$qTbJqdE0iVs37&E z7;(L$ZyNfpMJYqqHMqXX)Y==InB&2RpTf4%?rAN3Y=F)9p@Z<->R=8OA;B>IP#GCMwbwl*drtje5$y}d1b7*UoL-Wd)LT6V8oqW2BX zHJHL?@tLCU7L3Ld9(!zyo6kOnGAax7vTH+mp1paC%a_kn77<+*qzJB$G|P^@pUX{C zX%Yygx2Om%Fh6?0<*R|-b%G_HjZsE++htJ;l9&vc(h88~VpV(vt|R~L`mD&$qwBWm z@UCaM>|s%qq6w`1?xJqbINmJA71)qk6a6GK$K$&pAuTDYV@~a# zVry%cx*AH-T`3_pBykR;sIgY^CTw8{eNXQ*MbYTI&o^k}vnz%?Vo%wsXYnqOQi0JH zl9PC8C19dgx)N4r6)3dUCgjiY-V;_+g($R3*NGEA1x4_ps}ZVWb`Jz6>%i2JyvpHE zK5GUX!TI$KGIa9)-icq|xt6Z!2)!q!B?OnO@~J(ZN3D}v^j$OEKDGSPcl^Gi&5i0G zzV*w0?}uUV*|u$lgTZj_eACXR+s#SEIGF%^(Ve~zMb|Ii61@A&U~0!&*^Az#Wpwp& zIK2A_rS{fQ8wZCk{PmyyiT8Znzx~mFazj^}#S1UoRd0OL(`@aWVlW(wzdw8U!J>?! z={m-fP0n4q$aHgqVlZSfn_`QCX4#>163CF3LalW|8xcMEoGeC4`Josv*5ISY=z@cT zdyIy{0|?Pkmhjp~-_Et`*ZAt+^>&DcvK(NHVmKU7)fLUcaeTaBzBoXmau8AGoMTy~ zhz0K`Ys2pD7CYPfy!`SVKKaRCV`pazZ33?Mj7C$2!x7i6J;Gvnz}-7@tSPaD=EWCp zbL09A$~qBag|^ZRq^K#%F&i5jj7B5Mx}@nE_I7sp+TZ4>-Jki^=9L zli7^rV#)Oz*YUpN!NFbHCi1CI+~nz}-#}TxXk5~}4r46N3EJ4`8W%jL&z$GuzxWA) zk85aCS(c0@Q}*`uL3z5aT@&?!PXvU#Cu(nj+dTKoGaTNZbMew8cK5fLPB*Y-g3$%G zAgA4x5?-YcZ3=n!jRxf)fmRYft8z2YG!4t;67S{jAwoZil@4CkFDW@e*}n3Dr%Y~4 zO`bft%nAr7CBaX!~U&u#$Y50dii&!vnIj5;`1{-(3WcvqWAtc zO&(Ux6{Q?H$Ke8WU0my05`o}*lo5@B)+H&b9L+4R(P{!9dwbAI$qn60Gv;&Q)|uYv zy{C5$MM3nA=sjc%vG=`TdxOpz2QL_77YH%ndPnfR-1I}FT{iTY=BHJ{_le%!!-x9> z-zF7`6oZMu2iJFDNE~wvWE%)vx`@V!ZuE7x;kd)aS}^ciJuL&yOcn zI;j#T6M!#X9l&xP6zU^YRhJ>UV{Ou0nXoKO6MYzo1bOuhn(lp1Ww-2fa_Ukw*qv%U zQIly+N*ys&SuhnLCW^}9LZ8{?J;%rQC@O;~E#5g&G#Fi@lqaMHZL)WnkoUqm@6bh= z8-mB0GRKe_Sr?#KE**n3&DzUS5it%X1x$_dQYfa7m>0O#;!LnJhWHf3Ep{70#~Z*V%-F28<|cm2ltOTJY2B7y(vLK*%}za%34(tyn_g~ zvW$iWpZMjEGaVQAh z29tvA-7!x+^#t$zw;y6-V~8ykI@W|R677SL!Vpsyh?)`?03{jqg&9)V0k3&tpJ81~ zV2%-Cq%l^4ob*ZrXwaozTjZ<}g}RLV4J3tkk*06xI!D`zcYJ-b$DlINGA5zg8EsKI z5d)yq!<%Y|YY31O>cGnH?!70)RnncJ@0W~5L$-Hzm`yhs49A#4ig@3N2B50STqGS` z*JnP4qbNl@*!PXBq?Fk9jMnt7rz`|@EEqkp^Tzx>t12ZC#GwPkp`uiFn532Nz~=WI z>s!7=^Ll)g7~T+52K2B_3~ZL|I@6%@Lh4h|%jahpPzcCPJ~sqnb4+;O&Hb({&mPYFxl8**&g9TD}=xx33XLnNCtgUuMo1y zLs6UqLddga;COLFvy{*jV(UJmq{rU}zDR90a z##YA0s=$X1tqPRs&`Q(y23;s_zj(mwU-x=;cDHab5~5=N+$sL$kNy~c^RN6PzV`Qh z71NE5dQf6?!QSazCX*_wy9-hbq@-CcJ6?YIEG5QLLxy(K{;vswM`TR}TVMTE*IGEqWVS zX^2-}DJk~k2Eh9j;3pD-I17xHf8*#DrB;?y!B0zLAiv@j;N<+LoV)k#ZVpGox0k-V z^#lLxpMTHIPkrpt*8bMOE3J&K7?kx|{Tx&zQAp%(>>x>2`uWRO7*Dns45!%2pmf9s z5#1FZ$7?!>Y#lmIn{+u~;7QrC<7H+3829%9AVp1G)%@^} zd_VP|kRR2E6b(gLasBaE(YD8+SD_;cYYMsjrH;FI@6tAb)_Dwut=Ts3{vGdP-n1fi zG>P4vQ~a%O{oDNVfA}PCecKJn%21X=io&vgdXvd?i0?H=hYgEGN7FPkO)C##}>CH?)*je&+c>Y?jhPF zl+i%VXgs1G7?#V1;3dPsn1X|Y13vZ(zaZoP@qqm^`|RysqU$x$1*$qR99e8(DJp~3 z0i_Bw6~Zw~#yymH&p3Khun~kll z4|QELuByQtpzRl?E=MQo{gVdZTMQ>w70 z7*J+BZ;TPFfJ0(b^r59LH6dAc_s_Gtzt3c22nMFJ9TCU*7Uw!_VIdkRP9f*pdoMoX zQs*71$%$j4hVER$;lUBs46(*Aoeue{f9Y@V+|9du>094G(sKs&fVv#ewo8tVjz}?b z{rY2^+S}#m=vZ#hVL(|Hpj(XbpnX<3*A%u!A*0S)FTcP?fA+&nCPV6aL}3RQUC?!& zC!czP^Ays6e}D`Nlu_%`97w4-l27ED|af{HZ_jr`SI` z;mVau6n02m4M<3gX-pB<$xgQ@ESsB~j7B43a|uw)A*c5*$XcdQ`Gy;Dt`h}!0$WyK zED!G8p|CZ-{_CHkcXMi6()%L@gAvwFIDP&Smo8o*B~M6^-YNP%qHRa-jv;oaM5^7|r$TH#mLzGTM%)28p6{7@IO%qClZVXljZzZz9HrT>O>T&X|XBu^|MS zWy5^Fr0twEqxZX){n8cPTdio{mP@h3ej2pTBSwBAA(~vE|`o) z?Ck6@s3%xkqBSx>(lX+gzk^y&9#%O3D~0`PZy%!r>D# z8SZ0Lo~T7!7m2|UQzvoJK8dBc1@Ao0H}rjrZ z_e)o=-gwWWH=g)6gUR$kSqxrYF53&LatF$d7FzeIss^F&8eLX{c=BXFX#h^ne~xgl zTiBx1J0JPL`~S(W{M^rcd5mi4Q>h1onxfDct%w?YX5wqBNueWP(5B?f`Lk@DnlYSC zsRrZq$W*dTboM{@@?g!BFQpK*enLFoMi}E=#+n`;O5$HtmkdWGhX-@s@$@_S{eR%= zIdg6orF%xBAx*R7{=EYxqfIV9a)sTUO=9xgzkiQ=cY2DV9338Gbj@%u6)Id+WzTfLXYP9RMy3~LmC}|-CJJBQR2V(r>;AwW z#K%D6mZZ?KF`4n%&wP$=`lfH@tG@bO6s2W49Sbu-Yiyy|*w|!qbBn@SlqzVOE(Zy9 z^nFL$I!RVEvhS5BR+&Z-?DXgqc zw6P*U!_vE!swz=Bh=@&9QuI<_K0ju;T+;VF-ia_WM#0buW?$IzDe8RV7QVhhqjP|k z6vC7(n6l$XJ!}Yka8ksR=mCmSvAMCs{{AlYpp-(1$`iE2*Ll=Xc>2ur;0AwqDXVd(n~*R`VXUs|kD zwA};xevv8+J}goQZCosU>y$lw;>j<0Zf6|+;eYk@f9{T&?SJTKad@s84sJ*Kt0euo zfgW~kXcVAob5itA8i14Y|LV+RtcLVo`NQA$J%8uU^EWRBRh3mWRK^O!--U>=rF>hH z{G1O7A0pekr`X)yXJcoda%9=q9OAvBX+6r6q#*w4L_n(&*NZw_QqW#;!$M+%Q_EdGr*475!``zEmdw%G>e8s!pO;U5pfoKbk4h}hY`Vt!(Go0_adi4^0-}0$X zKFjXTHf?`IQ6@&?(OL+mjY2C>CNdh;{Q75~=a+x!6Qp1n4#(@2KuUhC+D<8<5MkEp zVH-jqX(&v=WIC0RdO76Wg$rzMZxek_N{*{nukw$-{X6-=ANrU4ws*W4r2~brXf$0{sjJE4y)%Ts;q5E5Xt;Z;vuVcFd0)~#FYY@fsCHH{?91<7@fo)`?Kgrc-uz4|Es?4N!=t`F3e zMXSjC_>jl0Kf(6iMX_z=TzZLxO(dmUhkS?fSd zP-Nx1G!fZ4s-SCoj^_=B2Xnfv!CI52Cadt7hevCZanIxk-jq?&JEH95S4}_&DO*-qH$5rIpslk;Ch6L9;*TC4a!f5+ed zpMK}&cytb1mPJ*nsKf@PGsj(PBeb@N5a|lT*4`=hPG6!N44BMns>;%I4pUf+8sq&k zKZGpg6f(iH>MXPp)v}KXpQ&I?({ktb1A(DzZ9q(X?eF|LUiai%*xj27CC>$#rsLB2 zi;TvD?0XMfxpIZW!y|gPl+mmAc_*qxo1hIsB5Tl~&1DCHn%Fgxd{7QWZua`+xfthunG$dWmxeMnwf8i?2wjtp2%0i1suNY#jWi%dAl~s;lmfJW= z)Z?#=)fGj#&8TRXLxR*AZ5x7Tu{dUa+~&!`YILpEQN1ht?`kCg4^#D0c0k0e`d{T3 ztXu*TLZj9nlY~Pd@=Ycaws&?IO=`4Og2Gi|pA$i$&TauwyG!JCiR(3r5^cm9hw{V_ zFlGoyK#%}>+*+4VR(6dLUaf*&3FDFJLR>cmqFoTdCrR==R@wkaYf+!~LI{j8;9N)a zN`$*XRw=|)5~f-0~KIlyK%ge*#O{2}->2$O>c`BbY04L|a&{;0KNwVdm z@AnPwHUVNlncJ$sg;`CYsV#1zpctp7aU!=0Cx939VT`v+*9xPSiv z&9ap#L7}M!l09FQ1Ib1J%3@4e3>l9HY;8}eYAd&0AL&|8RSl$Q1y9n6r=EN>Wo2mF z1>VDCIOT0`emC#_>bG&>(iz%zfzmJ<4!Csj5lMa{WL3Aze*Q>^9bMbgbuNeVNJtOp zwP;NcyfvfYh{2$sDr+W_88<)wEO#H=rz|ynALu*B=GKf;r%n-Lpe#nX-m$s0#hEjw znJ*6L+Lqo42Y+j8DpR0d;T?GII66LHI-T(T4}K7<4H_sa!~Xsbm(M-U(s@*284N0_ zs-!3kgV99v2Uf&mTGb@PmtGXPP{km2yBuV*+JoCd3U$+TbgiRpdYX2bQ}cvrF9lUX ziKLijv7Ryy-6w0YpUy>AM3ZDzeoB_$<Mav^2d4Gq*I6L@P$nNT<6v6El%KaosQ(~khUSa+f(Ac?eQMy_s1xA%EiVM}y?b_XE>+)H=^DX=G zJ6}0(lWO3=7e7}6MC<7zpyN1Is~;z4;>nkR_*RsN{)8(W zb3b5)hxX0+6u$d?I=&;H;mFcGeBn-7Jq~%-obeL_S&g~VAt^R#5UL8X;`PhKNj zUnG4cJ+i@bKeN#7ic&$e_U9Udj`0=8R5tToH@=bz+0ogIX;)PE#r865W*1SyAqz@_ zgzUQQpwPJQZ2|?Zq_-xquE4E74bVbup#`mA1)ec&K?x*x*&&Z{8p{KwG6{>dTtg+O zuMs7fl^5T&K?EsTd=S+LUka`qTHCx7wm1#tbKoKkC2gQ893TwZkT@Cp#_RA>&N|<* zKX<7~TXYete)JdI4tA;kbhsygyT#+*SB(6EVT2_Tgk&s0#OT}$+0oc{D!}??TN4V6 zd95-s(iTc3BOLV)-vgxlXg(bmdCTAc)&N=x1hQh_C z-dJznw|Df;j}fwtdhnW9k)}(9!)j<0b)ncvRBANPvq$b;Dc8vHXXMV?2KeRwYXO|Z zIJ1Bmc39p6*VmYgvf0eCVZ~(?iTJb)JNmsD{_BGQwdXxoySM5ZLvEnMC&+A< z`Ekd6v$h51KVIv#F-cr;k{VROOA!_9r4K|eP<2rZa;hKr%)6`g=fNQoz6z2pJK4ZZ z7!B`6PJsI3R1`|aM80pO;l;*AkrG}^nO?SC6KB;-WAs8$!heQdZl34}yWs?{qvHiN zR8`{3LPqS{E9=cs_esrF2)F*;827g%FHf$&{LT?mRRBtJbdKM3Hs2V#x?Iz3Qp?Ve zCBvEFvBs0Amc|JL-~*TX)wm%+PfU-0M|^YYnIQ1T9FzkcQIRsbR!~L(nL<5z80h96 z(5xkGERv>WJ+S>F?p6UJBq;UqRAXz6cxDylBs&nM3hNKYbQvl^A_elMXhas6fgV8 zDQ@I@DL_mNp$!Nrzo|c-tICX30sk=K`vDoaH7WV!&UNLrQi3_!_(mDV;jGZrf|)hB zgsH9kbh{Bi1%_2jSbYy?C03l>hWzMB1^-q#uSz)r5Mt6FSU(khMRotSmDnd=YlBzs zAUfzl>1K?zT^gza&jY4M#wS70>|Y5~{fzHCGO zC#UVgd0lH2CZjf?@ehX{Iyh%naFKc1GTL&-~7H!yShAxjz!>H(4gP=(e{s`!x+DK?AvH z*u@Wrfo;t&^;lB>*Ri1VNkQYYRZ31XnBHtQP2g0svdn2XOz`67AQA#|eyVB}M(r$~ z&D~#AZp2nz8xsTIXKwY>vy7T97Wjp%(@|T0Dx)UR{3duem1yXxvMN{Um;}$T z_8inmP_IZ)y@EKPGS=p3(du?Bu(rmZUYHA_Wvyhnptr4uA27xI4J$E}=LnPFj7*uQ zoRpj#9+J$K)2~Ud0qL`%31b{MteL?o{1o!lgY;`r{jx77tvhX?aL6Z>tj|CmvC(`! zq;v;oX8kn`@m{bXFszF`MBu_zaL(OpYk`xwOK%?R_}okhj;Yq)?tt^=A94Nc-H@j@ zd9udq?HXkrtA-kh)9;;|)-p2jB5ls*c0Ek&`=I1|unYmYcbp$!@{eZeYQd+K?1dxW z?#s5H6RoerThCi3J#Q@^BiO&T@Sk`^p+4}062seaRi6=Z-;-U>H{74teP>tgq^(S@ z6BJ@qZVU=^)$C-N#$sw;N_mgIO4QN9$;nDK z3m_r4G^Sv9z{5-gddi{V&IouW3cp#rqi%r(g(buUCjF_~tCJ)+5Q13{>js`un)SZM zYeyak(2HOBS1_c@mp~#qM5RUn_TV{`JG-$X-@TZ18&wfv!t%`y*Gy4PNG+@5+ptE3 ztiayp#9!WFzs347PFb}d6F0|cka+Hql`j1xz%2a5y0^dZ3;sJn?(=@lO=QoNfKul@ zL*xO_S;yhwf)vt{oedYRx^0Z}7hWKJ#2y*mqf>{M7ocIp^ zYPJRKz50X~wqt-APn6+z)ZHF~v$|83kwbL_&q2 z5?4>}j8AF-iiHfq!-jJSDliH>?mZAI@xvTI^v^EdGhi0esTP9CKQ?)AfrfvSE_j6MkQbYs zqdiCJT33SGYI3e%yo3=sG|-O|?d4h}B8x{gwM&<9#sq z`Afu)Z~!B+nkqzxprXcvH{!IRI{%R{@{+S+Gj7RaWbHX@$x&1*{>*}PqN3|Cb@n4L z_oK~_CMX61Nz5DS1Rj%VTL;@5k06!rP8(QGauLZz6#&Ay1f0mBgu+7F+aYNB$Ar?Y zv5U6bAbb2|fnvgf+SfVZo9NE>=$e8u{t5>X{hzhKOo!7yfT)n}OUn$%X9CwTMyq

      XLql63a65&B|6RJx?asB5=j zdrOH{Jl%+T2siRI<)FTl$<_cLr!{LVM}2@!_=%j?`;a7+ML&=ykG?Q$DuOaF{^0pH zOTCTW^K{tnz9tg#nPooY@TTPaeAS4seF}P;&6yXi*=r1b{mro&_d5oES+}j-thn26 z#PS*W7l{Kb( zR8;&ja`GyVPqJXk#7{jTaQB#ijznv?$@q)XhX`h@WkiN{1 z&o-izSB)*W#$ez`1eVglE7=R`(t2$9b356>xTTl4T~+sub_^bd_0D9*xhUf4(!bh+c*?#3iHx^?)`bN zz;qN0YIYEkzwCPL_kG#>SZ?tha%*?j(Aon53e~4e@neJuu#xI;N5h-srHHeHJaddS zRg+-8Bmzp9t|)f{bz?aq#VA-A>vdIQ#<{(-1M{jKj*d{-AVjVJL0} zWzWZ%FFHbK3!DZCDlzd|=VL$f`(N&Nqwdq+n^K55W0slq1Z-rAv%0@N`s8pplU!&B zk=h5-u!8&lj#_>Lk=U8<y zMnMFGNRms&!FDYW#psQU&ML98?hjqrzf@huu-&qWo})X4D|edK{)-VKs{uQs^$iVE zZlI!Sgre_`pyFvpI3<-drehq+oWF?0D+#Sk+{#g+*1p|pi)QM*cPFz=K-xIx7~M=*p& zPrVkjB&LDQ*{Q#F_Kg*NqOg!UWdhC&6KVSPzQqUE@D{vM~j`6ih#6Xq&~U|KMB1*eEhq-PGR*% z0l>ir0t4IqOw(u3Tb&MYG=K%Rg5E6=ns`M&*O*sU*Uh*x!{_;VvSK-=5=wODo8>C2 zXeNY^ss3sY9S-BMdhZC)k641to9m{WxJ;Ds(XC>Dh%a4i(CudUQ2WJe^B z^q3A$Vh4WO*oMTiC5ud4@OP;N7Kb$XbnmxLvDx9(HO2XWNK@Rh0S~^~XU@$?EyJKJ z)v%84DL@$R+L|6DTPF!`E`P27n{DY3hYxNnPr;uGYd#^FQ{x?#t$otK9TTM*=hYau zam9Um*?1ypo)69KfJd1@7787D1;|x;OFP%WbEMp!s^J%#$FV8y0FSE`-9$Yc6NbR* z%Y7-y7CGPAt>5EQeY;!xD<%w2S!p>;zs5F92&+GVK-Y^L$ve(jyykcVT0QcCWknsH z{Nf=rGWBT9!ob_@Af8U>?RnXEMcVG0F9;`dNccffa2GpN_cycG>*IGe-5dd4rD=$- zMAB*1%tS>O*Nn*Lp~ZXcqpJO2ZNh`?rb0~F#)qut@Z)D}^a}jmb=bgwr`PjBPv6CbmEDF%I3)eO?N;xv z*b#9aBC%u<0fhQ`3^shEm(_t^gxBEh&p=jAG6P&!L0ZK;6n^P-y_v}KR!y;G+tdR$ zhVfFOs{lvSxpXv0%57dJ$XjpvTT`Jvr{do{UqNQ&^b=vS)FQvYt2#-@Zs=3>`0Dl% z1o~m{;xbVG^p&=bl<}EQFN=Elf6)^#?$$*|lX98!(`$T%VIxb#@YFMs`wIFTPeiIc zsdsprQoy0EQHO_t1<6cV-#xaRF7NUl*R28$$r2*#6(pI1s^-i^zIM%?fC602tP}fd zZX$Rh=`~Q=7_@z+($z@!u2In)^jNCS6Jzkr=?&laEL5q;yM%5Ywe#z2 zpG981h)Z&E!FPMo6^A!{3Uj5rMK1dFtD0IOJ+2t1VOB{Zxz8-0x^^^J_^ylo&4j{T zdTmp(IL0o0<$WwaK!Jw5>7Vx+`9moBJS14P=WLm*%VlR|M&IYWi`(EO1>c)I+)S;* z2ZE@_1TRhKBUHXIrMPeq<+$Dd?@$f7U2Ju9HSq9w4fH&Af86pb+R9Hqime=XRYYQ4 z(wL4|tXsY0Cn`g2&-`}sSZxiJ+>p z!4u0HFnx>?@T+Q4ckXinnSjz&mtnl(Xa<}0Yunlef>E>pKNQqs*gY*C<+g6LPTFJs zsc{ZC5LaOfIYBU|!+XEZFHR>&Xg=sNqu7suS;j%3VG>|>Z`5eRfk;%kH@)NYw1T_CBSHadm^XVnjX31KIONUn(sw0e)(xe)fC~TuzFVw zQSh~!7-!kC7+0|~T0wXZz|p`AF{zbZ%wQ_5(hi*$LwcL1toOTmeOD7?-)y3+G$ciY z7e_UWoFz?MN1c$c9fT6-NV*C5if6*v94AFr9QwKU$8N3Im25ogQhCa-WqLKvVZO0p z_}irsd!j>8-4{p!7*tM?K=tLE3Q-0@Jlhv*t2J6AC_#7p@M$xe`Y*K7mqfh>GIBD@ zw1bKGC+#5wRNa@ex^*_GkKG9PurI$;TFqknuwN;sxn+tOiXqV_+5AGM=+lPoH=7U` zzbM_kKXv&$yABq<`TLt(7;sK^B>a-~_ft>UwBh?wk6B6PTCP&}Z#$nuEknbkzzQ}^ z1af*gM(RH#Ru%GJ>QqE3YBg1oX-jGwy(hk_8%Ji?5t^dT{P?JVHBR6F63JMz|LQ8m zhu&eJW!@Igb0yWVYP~s@>^|e~2_31{PtB}TDAL9(G~uWK$b~E6{xTYK(kzgdRvCv` zrH|&K;^Anf2>H6!yx#4d`SNg?*HmDIN3$4tFpEg>m2AD=Rtb>*If_oaq=As1zXL)= zLXwXS@UcxKr|hB*A0Ojz1oiazSAOOIUBbGoBK|F zzbUA_0A@OS6%2j2%3gZMGkIMBR7aN@(3!=fm*bpbdL+7SF}pY43bzaEqKc=s|t;;|CBClXJ_rF7@&rl zURV(*YDt%=H8vq)tF4%u)@=s!cFV!$jzJYfK4M%6VTc>orD2*VDTa4n))ILgopgvO zMs(k{3T?O3s}C9^aCg`#ZaKRx@2y8Yy|Q%Y&dUKN+*|h12iKM3WRGjB8SGI(#IF%UC%~ zPFm#X8RbqX47tr0R2^7)44$qc6BApb!rSVM1z}}+CO}L z)7f3+LzbzWU1Iw9!y@x}L%OL6EQB|@wH-wZNPhA#^xI^ts0fBU?+hy3=_vR!K#~~3 zMrvdAW9a2MxQVmC!g-jyAtFW>5!||D%>AFTw2aV|mc}FHj<5 zbYc5gnCB)E#F8u`<=E2DmYqrkCKQ-zOgp?-v-{rt8Bl!>j~JtHzFt_3)C+7npNl?4 zO2!t59mu!vPz6au2?E6L;z^ERwP64}HLKhC;-$|3arg0nyZW1y@-4q?bfRN}#i>W5w$M{b(>Ew4IW+&Ise;==(T|(e z2cKov*TgP%#^o1DZVrz!_VminNRl!6LBpec*#3))oLn1p zcD!I28tWl)L~)freZP0zgWsfy?%8d(Nt5$-sBLWA|Ne~VL= znaBjC$EIEv^&pv*dL#4gCzH@Cg^L9AikzE@EYXo5a6=Am5~!@BaLFfjj_8e}4O?(b zN9?5?S3e>h8}vY^iV)I#b0ts!e@m@c!?ouYVW26LJOE6%p4QyV{&?% zKv_dYZ*d`e`?KPR{&A;fcon+Y;&{+s!*i@I)SjUcp}b-B=h6PDQE#apN_)w-)?xb8 z@a<06dtib5G5N!ht!#R5TvO9J8T6PGY*39uN%f*dEztu0XS?LmLZ|>~UPjLBICHWa zwpp6{!z{#73qP7XIIP)D)2TD2&gy1}VMNN1pS*MNPB|j&D8ME|ON#jc*lIgXh_2(s`#_G9>o&O5A z-0q;H_AmivF0K!cSE0g_TCdkN2Pi#PQ%-($+bMA7;?H_3v$Va7AYJKB>Z0E_l% z8S_Au(!bhAg0dRw&1O75WB_v<%&Rn~tMwfnBc{&5fdk_58kk+ev}52d>|-^=GUx@& zF8}o~TR7e2AtHJQZgwT9`|?1g8$>D1i;u_`0El1>kl3HU;;?snPRd zC$obel5rWy`fu?7QBqQ2z1r+gQqIT-U20=lq1$;>itbkDN@y~A zvU#EHBh)rE2D8$ZvvS9UF61i&#HRAJswvGqmW+fvH3H_Sb{aF>wVkV9bCI))?7Ca;>-2Wl%Mq5vY zFAKUzsKb`eEDmRfP@7|0?$^8C`&m3WWWTn&E!rHOK)y%%zPXV{HL5KR){{`}c2WzC zLz|jAU9UMngNV8bqGa z_unq(y%$$gGlaudBO?mAkhu4|{0cMF@G*!pjs&^N%==Tx`BSi3z6NuR%1OZGVrkYJ zHdOH^U#}-OI+IuIl7Q|9XU!66zyUS@rq5kv4*#z43dyu-UqAHB^V=n@+sMQW@XLAu zK2yzYQCuy&*w@KYMIxBXtBt5`ewsV~W0JSmIE=$q_wT?=Y<+1o#{glP(gBh^6~!ld zdiH;Z8@C7*wsxm3N0(hEDBb%VxgMuIA9^(({lc%TWS&!JUp7mFFAGT<3uzO5btaH{ z>)#iw`SfgtpXN?uJI_43eXHhc(7vEIRpE?dDBZ6UsA|RuBv;$>HhAwa4KzW%w-!On zNM+5>*$2WSWQP{$D&kH#OVaR@1-nie+XRha>`s~9vaiv=JZ3tq1Oy_LCV+pxc;vNXB>_UvKe0aBnFRtjyR(?Rv zsl45(pHEp1y@aX;_7~@nTw&qI(${~kZxl7|Z=Z(?k$*GVBtu>rdV1Cb3m|@%yZ5*x z&qktpkj?->WK&4{kFP4bait@qJNrT6xD~n3wzDOa77DTfRmm#uv~vSO-&N?TPhSYk z1l5*5>p~tCQQ|;Q2nPOOn)}HR|9ZD`@98N#B-z=hu{ne>z8?TLowH`-=_n7ez))9Fq(EZwvQtLP9hme#lRnt0NoNEXp32mnr3)s9Bx>K2m;S;zLi(4 zJqX{8qi6TrYzzB7h9i7T!JrFX*Uz1@_{HAxZKKXTiVEs5yrhEpb>%R(EiBu7DnNk! zvG(`%(wygaNYSJ4^>JD8BDHNo=&*Va0ULwyCoTV2sK&$lf2k|K8J|nwA(cv5{I34^ zIlkc~gcu2QgCb>V?ZONwKH`EUiEK)W?vu3g-yw6_CjZi0X4yzMIhyh>A=Xw`&OAx}_ z-LD+A`n(Y}te_?wt{mkY%JsZH+}>wF_$>1oKT@cg#b(9|_; z$zjZ~9!COusbu9!=^=yAh}-5$GuY*id?&hqc3KeAVp%wLw_kZ>fOV0iDgk0pVQY4< zCTrqMT*Q5*@GGs(Wfz_KY?D#Dyx8;2|foL$n4lLG)b1ezb9j06BTPb0kq%Pkp*46kY%E_*qXG6`DP9dLs=` zaQck7gvA)&4xXdK@%43D8d}&1M#AtEP6pJ5aZEjBsZ*Tl*E;h?p7ss$a|l&bJRFlkY|B@shTaWtAVy~SIZx=fsx-NHCo8%IvORVM9 z|1uQ`kss1{RE%Hs1};NlDl(by)Ko!E`XTEW4F$FcLykXX;97pGA3nMb@5KuHpBa5j zV~TT%SVxQtV|s00Y;@dt=UpCX{#MFo(fe9S0X>l`71!6rrAhYC199Z92~3i*;>Dz8yTrzaYI9v~bfbltENp>1QAE zD$<5`G;TYAzQxe{zk;4Bqi*WOb+hz896*DXqB`^l4N-GuoF=xCQH*ei8W~t7B4$yF z#Za}{dicGwf}?SjU*-iTYZ7|N!wY4L=sUcMku`aUt~V|G)yMdTaPeiKBLso4#^;EX zIb{2MX94%lkY6haZ^`E_eH&UApc>_*AG(-9(B~YFfwf7R=%jRvt^$nv8b{TQumx9H z?Qj*^Hcna5?V7D5U9r*b{M1MH@o(+@IPubF>d5=OM^zTgo_nfN4AXm9rd!~i3O1}t zA@ZBq*1gM?1rXq$|1|7!c)IWKJuT&4mIkL+D&WpB;MU4d69x|_g*uEo+~Pr{=T}P) zssoAa!h#h<<-K=m=o+iw+!79y>!p%bC}n#ima;&*O_&{9b92Cv5l5kyF|DhMTo3fX z5*E!)+(U~fI$*>Z^rIdc_pMel z2)h0fD)g-~M1l&w;_HVn2tBA%NSD;!vQwIi`3Q z{?f^r}ashN5PeuI3X^v=8`2p47UL)r!B8HD$G5b1bwkC^z|2>{kL! zy3$sMHY+<|$TKcKu68^^fz!O6;W-4A7fw~(p)7T_ouGaYkItR6k4|;8RR|-H4j=ga zDhGq4`u3nnQuXR_bI&6b-QTC~J1`p)PtdL|FLUbZE$i5`Gc(>HRF5R#8DQrlFPwY$ zC-fVpiK6~;+n$x+s)yC(^O+C0!QjE&_x7y&TJL?;qU*lu!|Q0g4PC4KCenwGU`e6J zi;wxtRh*ggQ|`)Vzol>z;~z~Gf2#DzeGg*0&VIhlUZk_*w-Z#16BIW^>8T(^(poF1 zV_~Vam@KupXm3EM<*L~~)Jx0UC+nCxkz1YBx>PFntprxk^ki1d2+|r&clxnSxGWMG z?YjqhtZafp-)+6K*SOK29DVO+t{<^uK?JCTjn<7-ed-RD;4Tvrlk73m{_nH3T@7PX zncV4QtPo`yWG6NE2ZZ-??RjC)*qBxx@aycJ-D`J`)!s`$ynNEsEO=ZKHI#bQ--ydF zFS!yO7Wrsa_6thlSlnV060fHiM!Q}FmWj3e#P>h;;8o|40gX!kyw3RR;7`Jd*gh=%@$poM-4Q=`=WvAz|TD@)}mLUZRQ2 znz$;liHM)rAk`2?sYI@M!8Kb3}&P-ID5C^_0i-)DKPM?V9V;N6BU0B zoC{-5onhD3FST1DKpjC1p^B1K!SpJrz|lcytoph#8pA`UJ|096G-RNz7vYK5VUg<{ zLbCJPHu3uR1MGX-ZTN1+<%+7YSX*CD8JYocv28=#xDHEyWq|}s5Z{x%lM@X>oMM`> zc;nJ~hh*sB^<36k%R}%#GOQV4S2erYadxtry83!WJw37WE0)^sW^w&+z3+2Vb3~eu z(C1_PSt&HZdOZAq@=pqDsI4w

      |Fa+ch>qrN`%*52*~Jp&_}opyMzhc1!72A$#yC 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 D@g3%h literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_xt_86.png b/src/qt/assets/systemicons/ibm_xt_86.png new file mode 100644 index 0000000000000000000000000000000000000000..4f398d468088aa499996656e04cdf03f946cf5fc GIT binary patch literal 295676 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μ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≫s?-nE(Jm5KX2|f#6V;L#x@w=GF!VgC6es@`K1SS^?FX zbPiY}QL81s;Snf`5{xStEx`i7XvZ};D;=7(?rdCbR`2@4r~mrW(G$m4rWV2v0Qj%Z zUFrXW3IG6@>P}?3Pv+P%X@f~k}>u>z*|8}C=?X;zoVtk?Vi2@kj>f*sF9wIW{eOg#>pD8d7qZy|J zQU}kVbm4_E#K1PrtG+oS0T(n0YhZoI2`R}fBiDg*&Wn?t?F%P{KPHDS3jkxZ&qL>U z*-KyQmFyOIHo{I_6=&l>9Rp)a8nH3wk--e1l>SoK8M$kGGU;|Cv9+}4Q%WNUC@C5i;y6ZGR$!bV3M2gC@4p92i;MWdA3h8Qi##vT>2?uCG4ee32T}zvg}H?(oICdn ztgT4FFC$nB96odq>zivhQNJ2lF+`V~{-boj16FC4g^*jZQuN@#SH z;wXfm6ivXNXAIUE1R|UWevQ?WgjgvkEw;Bcz~#%A(eDi~O8by9K(jG}dR;$ zA2!dGCxO93X}oBTaWE$!Sm37y-VZ+Jx?2bB=u&eQ6Me$?J#3F-$M{sW1NF*~jWSpR zgff5=ZaV}9fDj?9tDuddk(~vUEg*PAP6q)fZNOaotRyrzN-xt|gKpfAI7iz>MtXTspD!kI#8vr_8E2hS}U~LT{s5}Mgs&=!kG$rk)z$6LRl5q z+T23DUPmA$0-@0D*3s*4AkP&T0vJm?`m!pKWhI);791?JDY1XwK8(_w((0UsU>4o! zHb$cqSy~{eg;eZBvTHxb1Gd0s#WhMC!ET)cS67bhfeOKLT!iV7a*)MWBQ{w3y{ zRbL!>aaya@M7G<^9W;o1aHnR1h*io)_eOW)``k z_hX#}6M&GkXQlXM>5D<(#cg~?s-S27`w7n2COU@Z5Rw<;q+(wzjMo?Bim~I#gi;Wk zO$3@W@)uq=VJPC2Q}~UPV#hQ{VKC^U$Wm0LgR>mklu)JHP9a3#r%HwUtMy9muZ>;rK zjvaeJ`I494*qfe?|L+@b`IgT!#?}GgLx1(6XPq4}Z=CagyS6RV8%;asHk-|+Bm1*1 zBOZihHoPg#v*F6h)5{Hj=aF$O5 z#%_mona22~FSLBZrQ60$3c+_cG?)kdjKMvQvN0@08XLu+RRt*l=M*>#sQK|&X!t)* z6eKX(;>yYjR#vWHZM6q$E7a;Sk|aQPss<_QXw>Tz$`(3=VMr?+#{sSoh{$sz3}J-F zR8mWy0&Y1NGt6ltGV4Slv#?z>S-~B0*s2Rf{t#(XnvW7J}E!1i?T)221>+37%PBoEb z1vWN%U;qMP`Juyetq=bBe|yPIx88cw($cOk=Xve`*ss_386-3E-@NX-{=;LB-S@u! z+J$At5Ie0I6PR%L>9An{H-5aSecG4%e?_Qr&-~u`-^3(QYgQ<-idF zjzOskVMrr?=NOFD2*VgvW$>|&eiSEeybcEs?)SDvK=9BXKo&A!(2CyYwbz`$+Qud1 zMdmLRhbWHF?RGF2^eOnoFzCu*YKr!LMNwdGZVpARp>2+4tA@3;4U$d!B(^Y?$nq3v znnKD&8Z8$&7Uvgm^2w7vJjO!l3`s3PUZfZdH!;81Bv?<#&}`LE7CDq6uX)=kiILl$VM5`EcMVK<%C5@Rq*fpLMdsvN*;y^dq69Dv;95xDWqI5C{=hp1u5f=RTFaP zcJ>3g9<;U)Jo2GpmTZ3$@Q(HqA`U=%=7IO<`}2b0!#T7eYcChH;u^;)Q)2@JK@7$; zxX^IWFq*n{AwxK8kfj+eoWF$iwJi)rTjV-w)G;;HL>SeP#1W+2rhg_i0UVZ(#8YRUWW(V`@bORnP50Yh^_o|{`OR;>Hwc0}%d%jsuKikHVYAY4 zZQqYd3zg){FKhXq<~{S5|wSI)EOftmo%koVRDeeZFl?50nSQ*8E{S^C&t?qx8qL7 zscLQ#k7_g~ls5-SF{{>5Dk+z+u7D60XP>?RrGO)ck5O@<9gG4#@}ZC8@Ug>_^+#E1 zEbZD2trgZbuHayIFO1Tt$_j^%9K`0`>nMs0wWLAZe=x*xj9#x#U32A7S&K%a0nQoL z*VnOc-#!2wk~c6tHH!-uE}|?8vWW2jVHja{Y8D&o>tII?d&`+33tW~XFLKoC0US4I zw(1yV17z8dltdgcI_BeN z&KF$9C?|Lbr4+&-utHl4liAhPr?ZXCm0r7fc=hxXr|$f-Byv*eoC9Ez;h*Ho$8qeObG19}xa07B_uc!NJMOsS$lB`aRK3wS zGQ0Oc8$}EqLTipr2*n z!@oGjF$kPTzS!3Yf@re-8=pty^LHN16HHcIW5o9ud`6Q?&luUUc45q;mid^j=uC#-&8c%+<48sU%dUMzx~9AtrYgDD6FkKcisOh765sF7!-Ln_^$8y?q7T8 z{)gUp?xP?7HYRx;!ZKwQ(!Rk|X9-cz#rdIRuklrr zu`o9eTN#w8MG^swDO6RC1N--4G};1(hF>OnlxTvYsGt;SB#InpH+LZ~?nJ2uNa6Na}SjY;p)>fKj>yFa>KF%G_Z0(lSn-I)#33 zfGA-o3XNK=2F@LN{S7o)0i4q?RwIf63ObAeMp1EUJiUhsho(ln4rDz zB#;V|Vuf-702fFKy7C$ALXzj2GeAn_CrSx~i!tc+krxB3t*ydT%G2LMUs#gJjJ|FN zSO(=ky9@!Wc4X;-g^a~yH%w!HwqrHnDSQUL!?)0mSOxG}8>=liGtQ{oa+a8MV_;#N zxv+LJWn2sn9=>Ml=+*lk{M_Gv zfGt&}GWaT(T>vPHY~FCLk|0XA`Wx50>m9#S|ATk_&g)K|eqz_IJ-e=--Zj@fc>Hj1 zO>#nlOHpaXIcGc@qzI&7JOIKdrs)QYDf_}%2ri+WkFRDD&QI^Gr3H>wl=;9o;CKb4 zH6qy|s@2CjL`Q}dj&u9#h)gffS<@PI3FlRlfa#mLB<6*NZ1EAj;QcD zBufw>E;xjAkUWG{47I2UE*Z+ALY8mgzqs1@`URkCRV4g(pv)#*H^$k7N2>H(CGy zAOJ~3K~z^ALRJo7n8l-yK7(UNkJCiV8aNh^mL#AiD-LSV%78J>MrA2^qgkJtS=^s( zZvOrkKK17hUOMyWor?#q{LbfX*t5JBM~>}>HW`)=EMWD@8t%Vum6;-tPe1+4 z-2d|9|L*nu-r%F0^C!RFw^EY?*%+3}e#dvd_UBHWeDb}gAARr!9>_X4xMS2!PmsW7 ztfmHet!Sp<$7m$3qol#HFp&GyJp!8m{y=5|oLOjVQRE6t2mk?$<~ybeV-c4Bw)u;N zCKB9>*NC$&gq%dBj=we`P)TgX8LbIq5RgcYQ>OZ8P$3K@!jJ+7KKaSd;42T`gP-}C zpG2hq$s;tA2-8y?ibd7bVUB}$THO`~{XU{FLQ#-%xK@`a>^erH6oQAS)Cdd~L1<7_ z1+pwhce>+s4#3_$d-3?=kD$NRN3GsOrOD$TCkgt4A($W{qOn7?y9tV-z-UmSo=gLr zGT4`v_F!dYZE~qNS0aohR<2xusvKo1fLQg14;{v!Ux2d&&T5pU!NS4<9(wp*C^LdI zge|53D25_05r_mvQ`pbU%rx;4qy$siGv^6~%vk`($D}?3a7P`T3n2ybISb?pf%QB9 zKk?Dt&c^vTM;<#mU!S|+nGZrz(Z?Vuk{0$^JPO7nT_n!>fGajhx&$bYg-j({=6FbIMP{Sy9yp|z|67oatQvoI>~ zg@S|QhMo!kYmIX-UZkMOAMPA=#*TqG@Y0oOX-A`h-dexXD~5Xg`M15S+`GIhpPKrn zcT}pn|F)OBYGi@N|MdO;_HsRxUv(`Q{ddH@Agt>&&1>~~lF<~yan6wd;9vgY7v6mP zXFqQqdf?$(k6e3XX@1Yl?uA|R_2p}qBO!voF(<48GuDAQ%R(;cnGPZnPJ#lZjMd&2 zN1t2 zO!^uU+%XtE=2?VZ)Mq`~nV$7PlJiMxO`HZs8jyNi2T)*C7I@<1NnE;k8H3>_xKL;` z>qHQ3GSnI!1Tp|a03kwzk=&sz3TUJ+Xga~2!I_iKV3ekak_d4uk)|o)r~z9^Jo4z1 zc;b=EIC1?E-2D6-v9Y;^M;ZZ}>9j_-khE4>%(v;~}$_qu1X=k_4Dvj4&Ks!rykD{=4sb@AOo3NI4ULxGj?r{8(fH z7%->dm;l(g^CrO{XMp1*3}c)^Sc*JF95=m^n!&=5sL5*vIFl5M3-RBr4-{P_j%}k> zIVHYP%r5sR*?_`@{5X2tRcUY9H=rGzsx-7^c;w-SaQ}Vxp5o*j#FF`2- zDe4Gi2US*}assF^+3%G+Dm)%XT9FQ^KZQs!@+>|ua0)dLF^E;fX)6o9cGS_ z4{P-VN@XbWlyU}?K~bidTbROQkCNzcTxdxt$sJG@P}=^@KBEis$5;^6@%ewb;I*soW1zPw+&}z zI`4h=JAU_1-}L?8hoIFFIT%N&io7hG2v7#%pOysWdCo!^qcWoz&TR|8nFk)c=as+r zyKld4tKWP1`IU>^qt{-&=jd(MMK{0VB{Iv0k|7t`R2)JwD+CLLfL6xup(Shkj8n|`S%ifL<< zwvJVeMk9Z&0Qmp$iff7L^?FGVh>f%u?ta6Yzjxt}|LEOS7}S$WRm?hzC{EDsMo9A> zhJzBddK0%k{{$B1JIF=@tXy6NE(C0db-8Eno|!kj>HA;*_*WjeaMg9!eqfZ3SR-kC zU1Gp`6gmL7;ntfT|Jk?x(nIh3?YAw)ao7T!7z^x36oW~X4W|8V3{t7G0I(d4Q|u=g zS^FGgD5^fdLNF*W|4MQ6nA|7KK#I&egslFSP*<;dZvR19^AlSw1sA?g-ToG zd5%W2i8LLcQW?0QV3kqY!_-sonv~Yj{cyBt*tF|yImieWU#br7dCpAk(UJcfen!)0T={E=@yh7f(Z>c zfh1|tnxITc)o;jy9>xY)u@2*Qfia1)tgw6cF5G?3J!Dg2236${M+vf#!RAJZnW-j> z830_N-jvwvT|ucv6y@rG>6s}!bN)$Gl>)eg(S!kJ7)KD>2@r^Zg9{*vI06w;SI8Jy z_CQ6Qb#Cl}n}|Ed*wsliY8b%SoH+O*^85)Rw2@$JyI7bM0-(JV zRmuARtGF=P`#$v7_I)3kh10pH$ze~=41J%42SYK$i9lKAkb=U(s;WW| zh{hZ0SMkWiJLMDlW9X>t}4BH9oJnhWQ(B?8Wg2{5T%OJJ==p67VxnP+hB zne!+Lf&~SEM7J|d5VtTu5YjqlK%7W48*TKqQe0WN zh}A2XAf?3W>IDR0fWwD(!(s$$r;w)x*{HzE#WUz<7jgXh!vKpA@E9_%ICbg)?B2Z_ z(^IpE!a8of>G^o#)Wdk{)J5EK%Po+#0FsrkT=To$wHA!nIy{xLQ}E! zUAKSw-3v>5{`{KjZu|pYt6z9-0`M>J>U28eD(aauUH|E)PoKH{uFrj@QJEU&(!i(; z7cUMVrNH!52igwt$b<8Ops_NWJES&5?WDmAROP$z4uxGFpGePa85y)5duNX ze9k1S2_OTBBoX-1m+!^9|KPvikKX+|2pR$+(9n5>ndvzsO`uQ%)RHD(s92brn}u@> zqjZQM;@~VsAR;U-E+7;EHm_`8_r7HmWeTNJEbpJi>gsvo>N^b?SY+t{2M_GSXw(NY z)RA*0(V1>T)EPF1D^NBAoP^RA%}xiJGnR!T^bevJN#7 zq19}m-|s<+0993@sJ5_YZxf&U+!+jeJuEKnL7`~3zP$Swwl;IXMl|Af6{e;;$nz15 zEh%|15NNfhP-GnatrU(Ge&^27Zq2}A2*dh-2vO-FlA46p49tauEfwBrA!&a}s9j9N zRa%!QN(~VQbh!F%Y8*uiODqWj3XMfr22yNWw1~DBL5R>t;7VUS8k)#(6$GI_qCt<^;sw#(aI^zzH! z^2)uBU3cQTpO!&uYx^nvp|3t!eD>u(=7Vrp=NLo4olK%eG)U8p+rIMfeYpSL`>y}P z-+R{!A=}5^`+?u?9=qn6R%dE1dfheOD;+bu$Q&PJIU}-Wz@nt?Bf|_FcTlc`2r0(a zISXYCSRkR{AfZWMY5mlNaWD~46JfOv6=Dd2&|i=a%o%7k^ctA4zGEB(O`i>|9YPV) zC>z`toXY2cjBT14)^bnzl(4RZ3>k`I1R+8qQCbFN6vBX-4p<2(Bp@p=rV&OlvQ*>J z#TBevxj+pUbEws*o3F(Ugps7okuaoO2cPU2#{o4k%z_IG0ZDEVXmH8ktVE~1h^kW9 zSiOKVr=P+@4?KjejRB_TrZ7D{1!KsPSQRNwo?bzBs)bggfwHW?xxnr{O&n{U@Hz($ zV+xFl5{x-Kb@pit(+rCXd%0na}u9A*((L8i)F8OV==|IQ;rOD8qs$p(s5$DdG!?9zB08keD-25!GcF3{{)6q~sTPLm5N5JVr15dH9bq`gk){JAbptLPs#0NTX$ki|@Dz+w2zdmh9MUw$(%exD z2RVg)7!J4)MssX!=17MQRY6mcQVlRO8=+8JP`X4-)L>8{j3k=P28z6Z*4AgwQ!1db z24z(Mj4m>OVQFD6HaA8Hf&h7*q9_%nrrXH!5&FF$YPAL0tuupWTO!TZ{lP0yqz;So z`|!l+y8z4KoWf{OVt#fvib7#+wTJnosqOCD?-a*Y%`uFIaSLqr?F<;Ji0H;SBqSK8qEIV?IHnbYloF|}P$`YI^;Hx_4rd+8 zl6LMgAOhS@0L*xWWG6{@%wu?IWItY0P;|9`l!5ny3phOvhq4}(?L~eLForp+H9|1Q ztICySU+0-BvQ&-IQI$nWeC6=LV^7`q{MY424=vwW?<}3MMw}Kwa5+6Pu>2h-Sv9(O{*JMnpYjWK3Y7oFWFx^EO?}aQJPyDu(GUJ5DJ8moY;72 z8sh_xEZKtjjwtKNn$VDSm^(>L0N3Em5=_S@>p4eG3~M#2Dg|SLyz<_|FZd46y%0X^ z$W2x&6Pqb#;7m;>jf8!sf`op4Kvk+qVH!sr5-u}N)=f!zrCO~9RaqEqu+{5hIO^ft zGiyjkDZ)rXO0wk!fkYTl5i7kLgmXz3J|o9b7)7Y66jfo+Y<3U^F-52Yhyno_#JF%_ z9bfwVr*LuQakLt3?Ag5+x4qytlx2y_S1u#ZNmNYFgM;K8!`=YJsKoN}vVWd(Q&TNOiNKZ1YbbMzBS(%P%{Q@o*B&$*Q#f_%Nqpk3KaB$i58(KT8;}-5 zSYuHZ7MxSl#h63n6EWc&W6a2MI&635=WE&K*1x;+_D{WN_nrgqK6LzfpRLl&nX=%D z86%M*4jcBl3BcF+I(Pc)T|fFGKlIjfPd)Xk4}IybBc7RGERrZGX) zzfy*5dJu5dLR$?X9E9+AUrys$r3eHww%ZsR_?yJ}L&Hu+xkgvykL4kX++k_gtoK<{ z;Zao;7Ut(+EzsNA#NnfdvDq7dGmE*oE=HpYWlmmw=g6wq?X=Q%plD02F}~C7

      A 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%0A&v7+r_+}*PH{q# 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

      XLql63a65&B|6RJx?asB5=j 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

      |Fa+ch>qrN`%*52*~Jp&_}opyMzhc1!72A$#yC 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 D@g3%h literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/olivetti_m19.png b/src/qt/assets/systemicons/olivetti_m19.png new file mode 100644 index 0000000000000000000000000000000000000000..766e335f72d22b07e92f6b6a03e858a340554a1f GIT binary patch literal 262763 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

      IrL@`5;sO<5fny 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%0A#K%sjya=)6S7Ev!4ge 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 AbN~PV literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/olivetti_m21.png b/src/qt/assets/systemicons/olivetti_m21.png new file mode 100644 index 0000000000000000000000000000000000000000..5e0ee4b5207338187ffe344874082a5706c66231 GIT binary patch literal 324694 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/olivetti_m24.png b/src/qt/assets/systemicons/olivetti_m24.png new file mode 100644 index 0000000000000000000000000000000000000000..e48356c32d8dee63dcf41854c7bb447e50da3465 GIT binary patch literal 209215 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�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 (`MmT?$BL0_xEQ`{xv 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 &+L5>%SOVsfw3>fnzBs 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%0ArvwoQ@%ltsMsL1Fu&wEaI1o((D4 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 Y7h<0Yc%(0Y#sB~S07*qoM6N<$f(PcySO5S3 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/olivetti_m24sp.png b/src/qt/assets/systemicons/olivetti_m24sp.png new file mode 100644 index 0000000000000000000000000000000000000000..e48356c32d8dee63dcf41854c7bb447e50da3465 GIT binary patch literal 209215 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%0ArvwoQ@%ltsMsL1Fu&wEaI1o((D4 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 Y7h<0Yc%(0Y#sB~S07*qoM6N<$f(PcySO5S3 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_archlinux_x2.png b/src/qt/assets/systemicons/os_archlinux_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..1b218a76fd19b3ad8d6ab8f4d2d7863e44ceaecd GIT binary patch literal 3833 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_cloud_x2.png b/src/qt/assets/systemicons/os_cloud_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd42f9aca1cfd75a6f6f71947c56b45b7c166ac GIT binary patch literal 1551 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 B@P_~Z literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_debian_x2.png b/src/qt/assets/systemicons/os_debian_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..a6644c33dcdbef1a76cee5eb48f221a04dd4ed51 GIT binary patch literal 5228 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_dos_x2.png b/src/qt/assets/systemicons/os_dos_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..b6df56ef54177932838b17374a6683001ffc6574 GIT binary patch literal 3718 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_fedora_x2.png b/src/qt/assets/systemicons/os_fedora_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..120d247a8ee2cfa298968d87f966355edebd789e GIT binary patch literal 3449 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 bz{&psV8{7Me*}U600000NkvXXu0mjf#>~4Y literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_freebsd_x2.png b/src/qt/assets/systemicons/os_freebsd_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..dd6f88d416986a1a4aec26f952ba04aa2ae0a80f GIT binary patch literal 3969 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 b#@GG>TrMGH%xYCs00000NkvXXu0mjfD;L13 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_gentoo_x2.png b/src/qt/assets/systemicons/os_gentoo_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..f27afa5fc289c6887707b2bdc8feb8d29a453944 GIT binary patch literal 3845 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 Hu0mjf8!S}B literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_jrockitve_x2.png b/src/qt/assets/systemicons/os_jrockitve_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..4283cad5edecdd84807114174a73a86ef1afe86f GIT binary patch literal 3703 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 VU*|QQx3~ZR002ovPDHLkV1j_O{f7Vm literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_l4_x2.png b/src/qt/assets/systemicons/os_l4_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..9fbbaa183f4ac699dd9da4ee584fcfe55c8fe533 GIT binary patch literal 4348 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_linux22_x2.png b/src/qt/assets/systemicons/os_linux22_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..0de56653ae41aeb7943c3ca5b0a6bfe7001d9d4c GIT binary patch literal 5219 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_linux24_x2.png b/src/qt/assets/systemicons/os_linux24_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..b3df83b7f2fa9cac71f541ce5fcdd7b2d7b5937e GIT binary patch literal 5161 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 X`f;a|ml+a800000NkvXXu0mjf<cqv> literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_linux26_x2.png b/src/qt/assets/systemicons/os_linux26_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..8fdf52df7a2705c569158275f91e865fffa352cb GIT binary patch literal 5274 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_linux_x2.png b/src/qt/assets/systemicons/os_linux_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..d4c2eeebe5c10971a95b5215ca9d5b5c1e65964e GIT binary patch literal 4364 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 GLSTa0j!U5c literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_macosx_x2.png b/src/qt/assets/systemicons/os_macosx_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..38eb2e5a7115fe58a71a19a99f87862ecfb39b09 GIT binary patch literal 3783 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_mandriva_x2.png b/src/qt/assets/systemicons/os_mandriva_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..a09e9c1708bbfeb337d8872e1f3ca7d9dc63bb34 GIT binary patch literal 3858 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 UiaZ%6ZvX%Q07*qoM6N<$f-ht^1^@s6 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_netbsd_x2.png b/src/qt/assets/systemicons/os_netbsd_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..9fa38a7a693b238b7f1d9fe1e135d789bfd80bb6 GIT binary patch literal 4123 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 Z{{<4~UT!Z*`6d7W002ovPDHLkV1fj1vBLlW literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_netware_x2.png b/src/qt/assets/systemicons/os_netware_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..4bcc965218472a24e61b9407ad3320ddca34d283 GIT binary patch literal 4623 zcmV+q67cPbP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000rzNkl<ZcwXh3 zd5~Pyb;f^h>7MDCo?Wv@NNBMZuq*@$78o!Q1jJ$-J2u$<0~ZbfIk=qIaU2`FQpTwe z$1I_;;Mjo}IV8AZ659b&U}KDJ6a@)_g8`vsB#oqzX6^3jZF+m}-J7|$=2ktrtLYgU z{pCv?dePHWec$=+Irp4<+q&SA?Eqf|J_mI0n=x|0-N2nTa2IgLLcmKY`FwgmKe^*G z?D_G3u;+(6+4IPK?0MiX*z*rxVb|SX=JD$<=1*t#;dvEA5Fn*I&GXft`@^MCc1Di# z^c|mO*S|l=u7CYUzV!ZW4B>SEe+hii20qJzhSXqImh-f~^BgGTAw3S`!-!+A;2(LF z^1;`McK5TYQa}oUkV1n5d79^|o%`Khit9Qp)<617Ixo76NW6W{+W6fYZ{*Q$+{+nM zwDN5rx-dooBq9*VQW0je$mwys(W6w34O2dLh{^#)#OnxOAcO(0fS&I8YUkcom}1$N z?!k%0ppb>k1WX^tnmU0so8!~lwg9x+EMiCrC#_bpyMKw7&f+CAc+*L|@x&bXWB7Aq z<X?P&5vv6$1xN+{bj;VhQqNnv762EhWfib20E_DJWZMvH{`#w|z4v}(Y8G!Kfq#4y znNA{npXA{aJl?jPI-}Y77O&Jwpq1sHI!ZA28WaL5(?vwoH3YzCi^HrG1q2qy?KYl@ z3~<oy&?Fcl3@I<S_3-0lhV6f}gZ|4drzL6=6pIw5W=Kybc{19=D=i(kmaSQ|Eb5GA z=WDF2wR6hq+;k2ynZch<5{xJC$20haSqiB%(2Wal?brXF*x8%G^Vs;xi=2Dcm-#_C z$K%nZU>ootr2=H}XwM1`=Mr4`<Dap{D<XiSkr+?4ox%ULbz$2MmaU%!YDs8*zPCqN zoOvNGpra&S8N3Qz=U+_QH~*90`@`!Qsm$<7v>V&D0SyS-vXQpKui{I1G1eUlPAD+? zS;uh{3Hn(>Le(%pnwYO?WrbouAq#~Wn9X681FWJ?|3^Q;)ek<v%WkKF4%!3gR~y@4 zz<vV(w)T_;Z(Cr6;!AB@S>$}`eYN+SQ&!v%prd4R6p@-j6a?j*d}IDqo{&a@+ACP- z&q!MmLa4u6HrPjRPbcyAHvKt2TVy7kV|*%Qa(LL24d=7xiGUjKH>E72fVxrA<X=la zEDf^&U~5uB9+tF5qr7AFGS1qtj;pS^ilLz)?ahga37&lNNk)zxXZYwzN@d^Rt2dv) zZ<d~UUzM?%Q<fnBuTGS#&cBuwW;rZ3iDSELShs>}ueqA*uDedHTLoTQUtb?<*RJJ> zC!WBze!;5;Mi4^IgOk+GR}0ROf-AjAwghQbiXs3bb{j9-oje^GAh7I3E6Wf-=`H79 zYn}uc8t7sDy0v`Z10OJxoBDxZz9zW(>Z>_=^e9t_8BR?k_1Xrjn%Jr#84QYivNXcR zcb~_=pZpswXRL(4XZ?vIY`*tPY<=wj-;Aze(uplfS%v`8&pq2j{*~IgyV|+tnrjT` zkT=lFs8XqDyX2BfIC6A^(Xr`yY1;-owL{V-d_FgOh)rL)o1XW76wCK?#v<^D4J~Ko zJrC3I!*A2}&2Ml=Yy(9nx^QI~0{*9o{A+-^j;*AwylsMvGUI&>K9|eU)6+x5bpU}B zHd1@5e*Lk%G{Ne*G}b!@o=OR3Gf>Dtu>hWr?X=Q!`G;Ax>la+P?-c(PTed)Dg$VfC zz`D1be|2n-Qh8Z{H3X>7+C0zG;ETl~rBX@1*Z-D~NLzrkL*A)X*1L;I`v2hb8a%lq zq{d)o0<sAxl@WFqUbKs@E3W0jU){wIT80`atCj%Ab(_k+ffSU=6;7NuL04Coo<|2B zDHQ?Q^Ru(FCL>TPl?eisT^uBmdQ-bX(BqYf_7CZzhSUU19EGXF$mubHLIn}&!Sh>j z1_$Z&E4YD&u&R{RkO0SRI{&89IUaxfan`L{2cUo}Q(jl#wF2VtIL|!uj0%DaD{7<! z0kTq2|AX{2a(o0ac7z}?K`^Tn(2YL}RxS+!w6bJaS&a!$o^F(X8|4BL$qb{TC;9&O zzptXb2A|L8DVNK7o=7C337SqMn3_(ZRR&n~=cZy=B#BTQ-cNk_3Pf&}U}lCOnIcHc zAZI-g9wJ}CPtTB$E@doSs8Uu#0<60E7Z$MfRBJwfBge<_ykGF^U;mnGuf3Mu-d;__ z<m4pJKKm@GRGOp5#|VVPaTU3ZE4;nY9?rb;&sqJq4}gdwd>2u$5VICC6Hq$7AGdc2 zQ-@FT-)<+19WKzg!fH%{UMij+Fnnx`R65Id{^em}t*rnQiY3yS9Mg$3I<`1&D8szD zvYw6)u=Vik#QyH<^nK(8{7eaNEQ>sqMCMXBu1$J6$9U1_C%wH&ZAMuOC!jgAOyI<x zk0Xhh98-z34tn9tVyV>VI5;M_TDFNVb(K|cqTIJ+Ejyn6IUD}>CHl5(!fkCw#^Y3q zWs<1^N2K8Xu9Xy=2#y_ARucp)qDy4H*Ior+K7fk(HdgpMO@cPZ#F&Q4nu@mZSA!e) zoy-Kk_0!#)=@kJu7K!mvOD{idUxIKQO>SdlH70<igT3^0#c6Mg0o1ML%n0wi3^1uc z%IeHw%&rQsjg=)Fm!EVm<*AN=YGo;FtgOZaNLr#%)~;U0isj3A-}~Oj;NT!a2%Wp1 zdg>|qPL0)6b6|x?FjyVrJa`#`Q!Ps=2@x6s-n6n7tpKUnTmOzT*!J6(@}UoXh-frw z_VFxTx|FleK3k_a+uBoI%~h46RV}m-!O=*BWkY@Rc6ShoxByft9?6+3<C7^ozlzxA zl(ldIq=do#ZUzVXx&Hd=Rn9g=jUhn+(`D|VLx&h#Qm>i|TljlPe_szPmk+Rc^JXr* z@IqBL=y|86rg;AO=Xw40*BLo6K_Zm_Yy*4|%Cf4KrUa-H$EvD9Q_X$wgCE3o-MZDB z@B3`uzMaXbM;2Jk8Sq_m>RQ3gH{Z-zXPu=$m|8&-v3~t}O~7}*`&|t%k;-D*VNcdq zR_#)h+JVakdl#TI3p-TJ=`|k&fdXtA3Sk2D&aS(=J5<dzI;fCDqb@6!_4BcheawJY zW)!AK)wX)|YQ1?{edZ9ZV<F7kNNSb!MguEEb~l^fxtc33zm!jX>Nak_{dT_ag)gvU z$E|F;^ddHITti<^CsNL11VDtVIc?h8p67+DIc4E$uHk8olrYfO&AZ<9F1BphV!#{k z8zRiV$A%3XShHpgLj%1?{pZT49u1Xt+ikZgwduIEWXTd``u$Be-K0!Cqe%d;tExE# zT!GYk_(GweEnLlwj*gmY4hcx)n>I?iI@-AS;)@knW2W5JujaEMWYeZi`tJx4Xp+I$ z+pjbLJ6z2@`skwytg7JjYdW1Kkw`EzGowB$H7ur@)4&|ZR?X3{$4#$6nR;)C(euY* zF{0535<?huM)OJou*20{DmB9+k36E*y7qi3l_HbLXyC5v>S`{V%c*K^L3?f~wA{n8 zHy$?x7!MgQY31qXlr>mlO)4#v1>R82`3w&avu)cp`uqD8V|r=q-Mg1;HovH9PDr8W zJ9+XX9UUD2rcDN*09VHwr8d39gpk;dDQg#}G&2l%<NYe783JmnxxRFkMDhnsS91XA zY@R)P_9)qzjAF8i0&mi*T6X$%|Ni~Dnyfz>D=oZ5HY%f5Y1QR$^VM9fS$duqUU-oU zF1SFQ4OB~BnF_F)fCC2(aOB7lCMJ`L*al0id8Glkr?;B3sCYhO6A2!C@Ih|4;Rdz# z3<1jf3b-=eMA@}#7spRdXeBz1tEE|gi8Ze@0QdA%bEXzRla@;7@eUtn=g#lUMe2=g z+_+KYX6=db@o`>$`DIRwjxu_3QUTH6HOZD;AAIvl3ll&Sd+s`B=2LM(+GKM@^7&C6 zOI~^PRb0oJmuH~A8=Fj^1E1{}YtWEwUTI*331Crs?#5QTv_uf-B5HJON`noJH=aW{ z3cQWgKmpAvE#A?M+t7ox7m(f*Z0#Hh9DswRKbwFn!mCRIw)OWKe5e>YZAx2APf)Tx z$a9%D%|?+UCIbM9IP7!cJnJs0xl>e2f`zn9HWAg!%fuBW`;h0Y)1|b96A%>vx0FY? za9Ixnx86y7>m|5d-4F=;RDyMTpW~v3?ql!d6c4nlqGG8aTCZhhV>wcLDtzJ5A{^}( z==tWA)|h}+;d6W8Am{%6EeziBXILTtzYN(lcx7A!J#&O~&soQV_b~9IAMv%;b(EY) zoxWjJtf}9qSg19lwE6^?6moN6gv~d8f}tH>gmMvzIVdR0La6}0hxV!)W7$V;MHY(O z{Iln{KepO1Y=Bl1aT><rl~$hsBxidWwhnbO^vN$mDG#|B$V@|e60(VT5-NZNuIke- zVPN}**}8W(8%kLYMY_PQTFa;17Oyn7UV(90af-nmcVY#e22b)7OpogOwqzz?RuNDF zVIkc%M0^OVZxy{4ZR3h3f64(Tj;*V(x8m`-6<`BG7q2wC-d)>ul^h-CZG~bUG6|SE z0b_??{2-j#4`XvSeh7JL7;$nKdEy}A!~t46I@#do=Zh0zB)DMU9qlpJu3E<Vo7Z!} zma~-2y<ex>^&Rn6gplDmn>M%B`w)=<ZH|T0(FN%#n3;s+Nk|-nsiTmYghC$aOJv|6 zh#~V8f-*=aPHPYl5k7%*0J#tqXtk`F13om+$9v!VUbTraC95u$_U+rp?%lhYm`reZ zWK0ubvP~1C{t`fd<$D?^nIt5~Avpo*X~-q@nZ5Kt1TF#}QF0N!@=yi@p~eJ_!P^#R zuRD`-H*ezOAOAS*?d_(ZF}KWEzI?fEr+@Ez-=ifOVc)@Hh)|{awi4i37Ws03H-3sp zr3m>fGBX3&EX)>>B_Di&2<$nN1VSJvBPrm``pinpoYOawss^}v#SrJ6dk#Bx>`-7# zU0>7MYHMrL1U>xl!xT$p4jnyNooyCvHg(29x1G%1-ALa@R6K;|5mW+#a)9tG0^cDB zY<yuOd<Ws#lqOOX(lZ>eV+&vN@fdx*UEFx%jizN4HbX?XuGi-mOZvKrx5tp?&yjB@ z0Tw@R>u2KI|3u&kgp3jhWe$E2!S`MKKv{&qZy^Yx1Qqb|S+dC-&qRAe9<iwJeN-!3 zwcoUN!)^I+BgPP86w}hu!ujW)&rp94LYP+9+qeWQ3--5mv1fXc_(R`f={4_1w)7yJ zPNbCw5g>yAy#$1V^c@PP#>lztyg)1aqH$cyYS1vz@}@o3qT1NzT%!7>ngOrgn<F~) zobKwz+gs7!*&-BZt>y>_-?o0JdlduEK1YyB(SO1DIPLw2Tp3ve;a4CKl#>~}LY^G0 z94J{l(0hhym({&rXuNOR$}Dwv(0JYyEZSVxHNZ_{!>EAH&dzy)G?Aff)3gHgBpN{3 zjc`~025x#~n63K{(X(a+QAc9uD~N24pyE*~3$o=FUUXypbN3mP^(_sjnuI#dOpNCh zIOAbu;mWQ0oKl;4UW2dBHq9>qBSD8^B+57X*YI>9%Vh^f*;vjKlLCOEW%F7~oS%2} zaG*7Ani<L#)H4)P0STC%o>n<ufeFiA8xW2Q2E016m=B5q*9MTy$AH=<gN=;@Tn@K& zai}$psENAs?PuFI1fW6K3;T6PE??la*IrY3UI9|F52rvwhUw;-{+>F!&|RHohr5s_ zgQfp7st~p9a&4h*@jUp2^bMy|S>2<1&wJjZRG|8ITK3^J4=C`apRbSUUV7;zCZ|&M zvQ6^@ggeDr3G?-J-DYXHTdZwiot)W1iRna2?eNrIKmj*OFq<NC<z9i;C)AHU_L%xR zT0Q1D%X;eyr~uLWBw#XwHmE+gw-$M`v^Lv}o=Omnyvoj<JN5M(qXZxv1IT8x`bQUs zh7U7xVytntX>27I_!jWT)F1Wl-8a!O4rd#I;PA0=it|VGYLlbx9JjXWJg<r&^+O9S z`$Tev<D-*E^s!eB35y(mV}3q=C-4~{{u}i3`TKyc{yzzfbL4=1<0}9F002ovPDHLk FV1k*#>MsBQ literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_openbsd_x2.png b/src/qt/assets/systemicons/os_openbsd_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..13ae3a0db0e60786c5b259b7a5f162a0067396dd GIT binary patch literal 6027 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 FV1h?nZ@d5i literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_opensuse_x2.png b/src/qt/assets/systemicons/os_opensuse_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..4d1696d9b1a809a07472164f2b92a63295f80c02 GIT binary patch literal 7361 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_oracle_x2.png b/src/qt/assets/systemicons/os_oracle_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..545e885cba9b21b9a14daa55e7c4bd4f23eff5be GIT binary patch literal 5728 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 Sp1FVk0000<MNUMnLSTX_?%0z6 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_oraclesolaris_x2.png b/src/qt/assets/systemicons/os_oraclesolaris_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..8db66abe3a5658cf4d95b03ae582792c82672256 GIT binary patch literal 2694 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 A8vp<R literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_os2_other_x2.png b/src/qt/assets/systemicons/os_os2_other_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..2d37846a0ef5eb50cd125e47a837488da666233d GIT binary patch literal 5728 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 Swkl2l0000<MNUMnLSTZHmhvkA literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_os2ecs_x2.png b/src/qt/assets/systemicons/os_os2ecs_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..261f9f56c9d5eb304b42d667b812c39994d689ac GIT binary patch literal 4796 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 WXd4p9soIYK0000<MNUMnLSTZWE+`WK literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_os2warp3_x2.png b/src/qt/assets/systemicons/os_os2warp3_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..1be5a696c05ead9bdba8da3902702a9b5e4b5470 GIT binary patch literal 5940 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 WYD;8&rVgV30000<MNUMnLSTY=Gem3v literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_os2warp45_x2.png b/src/qt/assets/systemicons/os_os2warp45_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..d1a4df0c2361cdc211f85284ce1890f1a7076b85 GIT binary patch literal 4476 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 O0000<MNUMnLSTZG`eR=J literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_os2warp4_x2.png b/src/qt/assets/systemicons/os_os2warp4_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..0a81c875961d620b8d6448ee1b68d1d9de9dd9da GIT binary patch literal 4129 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_other_x2.png b/src/qt/assets/systemicons/os_other_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..9602353c0d9bf0b0dca6e817825fa22b4b5e7f50 GIT binary patch literal 4271 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 RNo4>4002ovPDHLkV1iDP1%3bk literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_qnx_x2.png b/src/qt/assets/systemicons/os_qnx_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..b124cfa6e0e9d92a753d6dfa435c432c18bf3f90 GIT binary patch literal 6414 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_redhat_x2.png b/src/qt/assets/systemicons/os_redhat_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..a756e8aacd339ba1cb6feb3f1d3540b1d4aec9ca GIT binary patch literal 5231 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_solaris_x2.png b/src/qt/assets/systemicons/os_solaris_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..2dfd2ac74f8ae160117ba5e80bf1cdf56644f34e GIT binary patch literal 4358 zcmV+h5&7<kP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000opNkl<ZcwXh3 zd5m3GeaAoN+_%4ZZ#K`^<H<M^Pi)6oh)tZOI7uM^3JH+Xs<c6sy6^{7Knb8iRHZ5^ zhze9FZBs!ZYS>yRTY-dtAdrw0*D;Rm#N%zeud{l#x7_>ga!x(>9?#M6WJs{bQO%LQ zzVD5nH23>G-`{e6_l>yu*4F}j2zVb*;x}VefR6(oNdX@NKEVI`rBO<wqKJPv_ynsT ze2~sNZiDIsG+YP+(27Yn;E^YvFMaNjpMN++1QNK9OJa%ni$WmtIS4)QYEY{{Wg2ED z=?H85$(>j8t~*x6&QAduE|Db!<dj09$#i!?=tIK;w+5b@ya&i+xcj!%eCj6$aw#sU zC1{BflDXa<@Tb7{k`SoZz;6HwQYlKsJOGkQYH7NII_YIgapnjHbqE^?@rDOp9qM(c zRiRn~;F5BH*3jFiP`Y_N=nz6Lv3)QH4;ns%AxHr#y3_>F0Q5B~lsBwT$VWkpM1&B6 zAb}8oy7U|%QLL&@Q(FHr2x>9$7_kr`ga#-OmzV%r!wPqnmW)I3>Z@StuoWN-69JUD zY7K%*&jDA~r)a%p1A-75vk){A%ZGsx!9W9&OQ{NIwANf*o1lF24G_5ydPacQ0Y-!f zA_b9o52Vij7r*c(1q6$=(mG;AqeA;DH-bNFGQV$#`w&G5R0LW>be<tl3L89d@M#>a zFpEe?rczm4ndllwhtW)tli3zd<XX?5gckCG3!*iwtWS|&(m`?63K-v))PCPj5QNwe zFan%!6_|B0e60T#-ZVDE%gb5TKKwOG>u)5So<w;b{>X9s(GluHd#LZ-O>NIEYP+^D zSX{zSI{G=1Z$pR+C4^4m|Mm?KHNdNY?}4A>0F(WV0~BZli1QIZ12B=!^H9%qY@9yM z@4xxgT>0^TqWiA9$&?*3Eh}K4myTE52*Lp=@J<}3_dmYG^<Vu@_D#SKI#+V2&~Y9@ z*f3mGpQQbcS0v>x@XXH7A+RDu%7y^qe3GD8aDBS8oCnJT?0f&a8Gqy(gtZw|brLEQ zFntmx55vS^az(h}-EZfXO`CY#1AoPPX7=;8liMi-9!e#N4D^e(e<AYeZB%Ky@mlaE zZ1OWA*xjFlN)Uw?rVI)p5K^)~-_EDi0Pnp2gA~5-@3dUr3sIQdj0%nIG&mBG&amut zx6%3Ax6ttqpQ88CAM(Xz*KnlJ4oHO1FUk%5?lifs4l+y1FnT;8-ta8>IQtuD4O*Rl zA7Cvjk?}<{ROsN*MwQ|R?&tc4KaEfUGLFNBQCx!*ka8fMCY>*^=7IOJ<j&h^`{3X5 z9k+)kJNl7QV8nevA<*YlXj!)^iT_3oJP#TH_@@1h0%LuZKxu&Ub$~D;0Mdv6{J6c3 z8%}L!>DRu=@_T+KiAT?cz?331I0DissLeuQn$GJ7SpV=plD_Y6STeesZ!BGl5Yme9 zE8@S~uhMeOt>D+eYe2&XKQJK>83)+-x3ybdpb!wCwFDpn9&1~{<zM|Ky>ECmD)5m( z13Y6%W$foj$fUr_fLo*3*~<EV`zZ3A50D<-#aEVH1M-E40Ns9_T;EdgDhc_<S@Jgf zn-<tW%?lv8AWIk_BvMKSTe=ymc#Qwg7C<M;hd%fXb0)7swF0xVFf#+wQ!p`1#tFFg z@9$${-sklb2hd8PwT^MF1c=tOL;=~(GI%vZz5)K(&d-*=1&A)-aoCDLEP&RUtu0*) zJhh3Xx80E37&^Hb-^3(<6wpW+q#<aKFO|6V!|xz??<X0X$@6S$?=N+N2C^!|$)=!D zPx6f)f^C1T0A}}%6E3s>HZe*e*;D9ba`RTgNFg0eV$+~ZVp0k)q2Nmh(k4#?6ua73 z^S-z6mXCfp?j%nX+U9cth$acrS|ydkcTM6;U}N9FkT+P2!;qK{hokvcd<`>u4j{7` zNJ)?YM*T2KglIIt^`KTy##B>NaaeS%U(3q3zKTB^8KgMhCjc~uLqj@5)oQZi(J$`2 zO@K{dU<J6qE)W7O9S&#9Ob_mXLIF}DffR`VN<nDc;0NIOi3l|pre<Jfmi{;0%F3Ho z@~6Xth$t{Qfu`k(6sqnfq{Fi%&k{zPK4bwFMF5)%1cFo97G~!J$mJj{!4V(<sR2`$ zBXiTfZ$$7CCrnPlY@M}le<RoRwQ%p~9)t?fS~VrbsdN_i#E2PqL>9{Kd@~kxA|yb- z@ob6ezC&@%H@k1h8z@_wO;SuqC}*C8)6vHDfBnaBCLd%@4f4gFYtc>`yI?e3z&$<! zH?1(_f03+l92zu4QAijBizk4|*zxf<9CL9;#>l4xI2we_1L%d>naFrjMRtUxBU0^W zM7aN6`1pU(eq?LhBaG%sfB@iVw#>|~!|;0>nr)6E41EIs41$0l^ob&cJKF%3FNy%B zF%nFs3vq&~9y&^XZ8tc^{z3yW@#gHTF!mKDOcEhdZD&OIz`bN2{vq9)e$M9dayGYK z#z>~XzCs7nd$tfvS8<GRVc_G}EBKWff$LK}U86ebQk(K<R09CG>Sc=<0%+8n3o<RN z*?)+x>n{UI0->>lqvj3`4N90M#xWvAq}p1!_FebT^ZMH<{_9uRc<dPt<lESjYiC-f zIrYP5=vvo<U!B35nqg}1IMq`XYNuVa(i}<`8OknUUq^{ksRDA5LtqYZ9;gf*hSZ%V z1WYVqLZI0N0A_Y4Y}XbA5cuF$>0G{qoB#R!9Dn>d+P3au;Mtu39Q(m8oPuC{>oH~y zOfst^&*nPVSMFhdwj58Ygb)T$T>Po9;8?EA%=Ud~snA47K~o4A7c@ITVaNlKW6P%J zB1@B8erq3>-+dF&>7z_;*~ZXUwlehPZJbCK_;GOs+j5;KN6wQ@3HzEkEVckbz=1+L z!RT&kM~5k-V4(xlf<)Nds+!L$VQRdDAZe$STPHX@h8u0AGBU%7@9$@{67j9Jm2As* z#w4W_I5BC7kY?wt2v&f_OoXnJ;Z&x`#HO9}zk03B0h}`tHakJ+M9oOVE(kr1r+n%` zgHzj2GBG&86NN4w>spO39UPgEmNLcy;s^}+MR$Ne2#r9nx6r|wr?%7o`t=|&P&O1$ z)&=Ksf&>)!UO+wYm>iqo#IwU34N`oeb1lP}LQK+;jwL>K6%uUR1HyK!7b6ECV0+6_ zUbSZ{?#OAfgvgjYX4#tEOx^&E3KR{$f$MvmJTT7q!6}}|ck|sPml4Voa*ntY3t)&_ z+k+)<*P;txtHDUNg_D^g#~$6xsyD7PVE_o*1T`O5EtFEYUY%O4&f&pPCMFwvsda$o z^Bu9pQ;vf)J8#L`gV{OO#Yuu%C-!@~+)Ll%I~cfY9SDt-8UzWnZq5akJaxCm%ycy- zf83RPu5)dCOm?J1I*zfuV|H9N+5M#wz#fc*U`J^gubn>1k;k@j#Vgl<!@`89o6qb~ z6yY}NG5Lc#MmZ2=_)O<&YN-rPvg@$`HrdH0;x9-5t@Vqrv?ce#ogh)t;m56gbo}5s zmaXe0?>IQ~A^_+ZmVAioxlB)1IPm-^`&6FKcCMn~Wa1rnoO$w1r44v-0(@lOkFX0O zA>;DpN(Wy^rqem<PA0zAoD9R+5~JA`Lh1afho9!AbZpP9<sQ~m$0&UMXT1E+UjdH7 zi4RHGia<iXUavDfUE$z!W9+2JL!DO=Ice<9o2yN90Kc99uQ@RUTA_T8U}lDJwu*9H zBDY3kWGwz!ZT}&nT8+x?eN^{uM+E_=)A?A8{l!iWoWV>w2Z$y?OfrgH@YSw0EIqY@ zp~rTz=FT-Blyw52=4|iQnVy{Gz|L{Di4vc0A3!@PoY*y~n0%7xnk@h83Bc%6pdzH! zWTiv4oP}}-T0s9YkXOK6F9#<FA`LQ4?Z`>0LkF4JzLSZcZl-o<5965v&y|+)e7T3y z=>pb~n9fWxn<?;6_tm^(+aT$z!xcC5fk>R7LWS$ssZ^>Q92{r6DDiN|0LX>po8z7H z6kvLG;nNdrZ;mpD7O>r$5EN5cir2NVbi-Y&e&-+2m~k2Z=`*Z)><R9Cb`!(d7Iv1F zvZLI?Y$|7bkce<9U*@4DYkAxM?jiDg25#&_OGT&xYMvMG{C<_=3!N)zChs(5`SZct zm!<XQzq=U%Gf32yJSc2WZpxGZ3k6buBVdkXu>)F`(U=W5`TeIEe(XtVM^AAi*UIje zuDK_{aa*jFB2p10-{q|nLu}}ASb0+~I`BEX<rIfT13t0jYU-)%Imlb$7e;{l)`A~E z5MrAVJ3=x$Z<9X?B%m>4F2Fha$jgCT0ZQFazKq!;;|xE(iP4{I#v7d=5;Fe6#IZ~% zKD7-ySvFQi_$_Ca_N4{J4$kmk#~P00TNj<Y72s|C$#^<2^E7=H0Fe~|0OJB|2}5e* z1i(4#2=n}}P=>ZXDECkwuQIl28&l8i#T%c*pPq?Du?zmY+{e=`J@e$9RBAz~yU;5I z5LBx;fkKAL%;FS8c3@$hU|az<EJS>@PLN`u2&pQJ4##2?3I+OaT1NkC)<LcvWCkh| zL_5C6Q=fQ}9Z?}BpOiTRv1sJ20K<Ea(Am>TMuVe3YK@()>V=0D>jvA!2`nVm4XK4< zFk6GMaS%J_r^D6RDn~aR!*xTx-E}!q%EbD%x5sc_JOO_G^(`#xF4Dho4ISO>WQ4%c zn1>g3wvN^oU|U#WUP~*4b%X>5Y_hZ>g;7XQt1&)!nl1SyabFSl_c5IFD0MHk6I`~Q z4Ye`u{?@bft?p*^?N^bTi@)U1VqFmFg+gEeR+MH(U?J^mM-uoh(?_T9Dn3tjFO7*C z`<tCNYO=@<Q0WZMl$WzR-@&~{4pJT8!ZokEj@H&9pcA($Yk3n6&9GI&d=?M_n<vbB z<Brg+GjU*=z1cEj=^~D>6C4A8#TOvuq|j1RlakMNU&B3<hX~HN;br$+PkToTD2;Rg zweYD<GkFVOp%@4d)*+!*1a*(;5tpqk{V`b^^EU1;h5&K7QCb<*72oX~z@18=zrBNX zzk5c6_97Ai5g?k!Ru(k7!HNS2D}di%W~`1I!C<}vOWq!CE|vhX>QW1Ie85nMNbsZf zehQNz^3g$V`os0{@imneW>jtF`${LUq??5R>}Qk_KoI!>(~}-UnKF^%nCY#!n7eNU zu;23$F-+|8Nap};qr1s|Zx=Vd`8tGFIF1AvL4<9W&%OHz)Iv8Xt%!n<*%_aqY}fqQ zTH36C5d~=e)>l%35JbS&=Z>$#J1GC`Fl#sVBSM8t*>FJ790C^2|4%aJ^8JW<J>+m# zX@2Li*1y;SSO}{E5=|qO<;zR1;x7hw(%xI5r>_k{jdTQrMg(nbo`7?R00@Y}kV?hJ z6Aq)9g4uatz)LEC6~Q<GU?gAWJMCAHdHevSKe&#TTnecKgvJRb49+bAHVlM_1*q0T zM$&n-B@gh@JD^zv2|C5L@^X6pD!K3PW5XNPkQ0z{Ot%Nv@isIIz=9T9DNW4{8BVp@ zoyUrBu?6sf%((}k5+On2@M!0i6vy_Ee*7To?zkL;AZ6NIQ{kGDp1s-wl!_wiZp3&t zpOB8hOR>BZ@EPDQf7#<LDFq-=PKvK}T}5GZ5dHXJuDy9V#j`E5B|)<gwpCVuilE^~ zOck?$K$w4Dg7pdW=kt67cn{FRZ^o(sp9DVifB&WT2ZI2*IRF3v07*qoM6N<$g6s_` A9{>OV literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_turbolinux_x2.png b/src/qt/assets/systemicons/os_turbolinux_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..4d5ee4ab1da548ef10bc993675fb29c73610b832 GIT binary patch literal 4018 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 Y01<Zl)|pkqLI3~&07*qoM6N<$g13EQ2><{9 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_ubuntu_x2.png b/src/qt/assets/systemicons/os_ubuntu_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6302b37bda4b3fbb172ec7a9a5ef77ec2b1651 GIT binary patch literal 4050 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 Ef=Lar<NyEw literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win10_x2.png b/src/qt/assets/systemicons/os_win10_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..1d6e81392a56726b3cb3e69a4054a6f84b12b3fa GIT binary patch literal 6135 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 JPDHLkV1i2hn1}!X literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win2k3_x2.png b/src/qt/assets/systemicons/os_win2k3_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..45bec005d0a055df1008ae1ee2234ac3691fa655 GIT binary patch literal 6250 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 UjcZIa3IG5A07*qoM6N<$g7Z6eng9R* literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win2k8_x2.png b/src/qt/assets/systemicons/os_win2k8_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..d97a2789dde0c952b99eda9eb870f0756bd424c5 GIT binary patch literal 6322 zcmV;j7)|GiP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000<yNkl<ZcwXh3 zd3cr8wg12GaL&m*Lnab3oP;ow0YZX6hyr2O7Ep>q^|o5ABkk2{ooa1+YqeMO0kvL- zD`G)pMwt<05QH!jAPFQ)Aqg2zhBLnJzB~J!&f$0p^26u%N7wVLXT2v`C(l`*wf5R; z?<8E|EfWCXWdQR4gyY{sIsm)|;8hX8Uo95P)Av320LD))gE=S&5&<Lt9>wafWz`b( znLrVOn<Je6GdK?TaNRk4u=s0a)Vu>h5Sg|`3`W+(2eEA45D*xjQ)X8EjPRHCmR5Yd zaZ~u`A20f&n~DhF$@7VKpfREVGH+G_2mGz7G6P^(f}1a#mvuR1EZ%YfagEz33?3X$ zl~SpX8ifT@`|6)b@>1DL$yJF8ijKylyY56#cmzK9`<pL|0L<p9Rru@MEttP{Bp#tZ z^v;qba01UNzyqp272x}W34R>mR9(5N4)(@cBzB$#FN)wPg!a&E3>nl9BeEm)%zHFT zd=o{8_UtQprQ>=41c?9;>}f&D<>jzn`5JH3lw!fULOe7r4Kqe3>L82~Q`MX7k5mCf zCRn`wJYs3~dEUr=1I_+RlT#rZLHi_&eO(XUcR3IhEG$9nH3Pt_WfdZ|QV?Ij(X<V3 z){MiuYYOon)6+3&6a%3{FnYj`0l@&UZEpkG>uQnNaT2`9v+Q>Ury(h$A136*>A}0f zl)ZL)Re<abfcPcK0N}91BgoYVfkNPTnSn^972#;!fd#c=@gZFrcTY{jgklARd{v3z zCWGKqU9zDTu}$BA=fT!L*xE0~tJBhq>_Z9KZB&A9L)1a|CW`Y0Fl^4t*!a~(B(&{< z#oY`_K>^`uW+3d%-{Ae4u~__NA!biX!}w820M97^ZYl^P`29z(;Bw7*WVIhrvQH`4 zElCJV9)Rg1dh6MDsTJUoRRG$q<-cq}NB{tDJvaarll$UNpN~WNjx9)}AWWV%9Ym<7 z3Bhz}*l9(4e0Cg`t{;wBlhaXJlz5Xt7y!OlPqW{=(>ME(MR;;jDg=?&%iV22@NL@4 zvjHGL(-xsRS(8KY{*%LSXj(d6T|64K2ft<@M5*&C5KAeDukp#55-eXo0zaW3#uWO4 zzzy^WE%;MatvGwSC;R0}<D-zB<~RuPgE4z-GGr}K9f1Dq55cDw1gHR)SD6gTh{R_v z6k^-qOw3<48Vx75v!x-(c3%+npTpj=oq{OEN?H*!%F-~pC`l_b-_A=^dkql0I{2*K zP(!o73j!yD=S{2v8X}4?_qG&-S_C~<r<VO5m8oiA{Q7}Uh5A>3llbrLqld;}6xG$c z(((SvVmPb6LA-4b1>pqo0@3&K5>^qPR+V5?4+vTj#f3>)$r*YL5S*$PFLvO>k#jWr z2h_obgWD7dN6cW{O94pUWiP81Miux%FnR&;iq9W_td<D};HpM3r8o)WM<ih74l6!f zITFIfofO1(5QxhQ#1-_dUyAOQ9avmlg4LP%m^LL7g~JooEhr!eUjQ8N<@&QM`y$+W z_8Y@SVCL9VM2DM=vX`mqAObD}1HixP0e0E1N$3E0j;g@pr==;FL}4u5nvGA_6d|I1 z2jaR8L6F@#h%iqhLh6@L5Zmz?ZI<h-`ItO01H&l@IUopQ=5K23#^LgFuxi<-L?j^; zEfKkRfbKrB7QCkN_X98>sENJS9N?7H35rv*!zw`uUI0~Uc>orRfct2P-!ZliK3tQD zwOdXhx@jlkx{pv09$yfb|A}t8G?rA2!}_dzl$B*5FE26RL5d^5md!PYYT6BfI4N|I zLhZ?Z0VWsqL1Ju>5}>R?kc{Aspj8lt`hiEF3UCwOWx&A~fZ+8U8e+m@cjaKt#5DY4 zl@(idoJ8-o-H7cv3W0D}RRjgm@->!Ll~NFSD4UdtAwv@s5MEVavpKMTPYp8Kzf&hu z9<mUGD`9zfa9W13_Ko0;WuQYaRPq8qREvNBB$b%gTH#pM4G1EqsL2aPY*Y}Q{rMow zElbCH%dPl!?@1(f>_JTT3HXEfjDh%^R>THtF3KinVc?K>JuN%7)*`%lA4J&>UR1Lm znv3GxWTYj9>1FPesd`s{u>|}lLZ9aT{nB$GLgua5s8Tc545#-1-{3_b)t3j8)3xnb zxa>44j-EzR$8JQ~Pcx!~s!U`MS%yrt%aV-7=n_O_<zjr96&cnT{Q0G=NIm@;EO4;% zK12(SC;SQvpD#sTb~N0?0N{}Qdw>DMfBhRx*H<>(Gf@HX$T9_h#{gh7K>z};W**e? z3IOv}Ab8H$$IC04@y@bSxKLF^LF`1N<7@yBNfbmWxL*BWy0ja~E$dnEJk_SKd_)$^ z#9Pl6vFv$#yT0!vr~~oOzDxoSV%zSUs2+wSt#o{c2400A^bpp9l>svkxV>PQuBwRK zoLId7!YFM0E*&4OO2g^%)eJ<q>%7m>2zS>bw0<$VTa#e&*ue7wQ}7}hLJM&BZ5e2H zD?t*Xz?F#}ywMa@Yixtp%D(>`;QL0+J3t?xzKooSP-Ou8VenK-M<k)7AQ9`n$-pOT z({Z_>3ds~isH;u~!Se*+o(4vm=aseJ64W2T(Y-Kma6BBckqAO`0LDFlciB@b`K|qH z0?-?Z@n&M|&79XZ=utB)$_fw<54d|?Q)`yhrNJ8z1O|e`6gtF=8<~uiThs9Q`gHIu zl}PH`jSzPOI6zM?*Q4MNBsGIHp2WQ8dCZt-MQL##b^rqLf*>mad-P`miWDIGfdP1x zkqkcoMiulZ)Sx*=omr76a7?T^6l+$&2%HL26fk9cCW?ytV)e$p*tE@xkd9MG?%ac5 zsfCf|IK?@PR)n=>IXc^S;PZ1MuyoBZ+)-x5xLZ;onnfLg4DX~FR{o&?+<rYkPl~Y{ z7#*KkRt>6}dI0i_rnVf|Ym=-%gx9*YSVYX8o`VTv(lGBu8IJDb41hBE>GjH9hqxQj zw`DcD+jd}eT@k)mlZ)F*GEq7%1LhDjWEr|jJvIP<Yb*gR`~JHCh%uw{1dxm+;SWPr ztASU0gKYT7@ZKe~BX1K#djrDlRUm>0ju3Q<y&-XCgt;%WYT$WggAI|}(Wm7rxG0F7 z4I{B(Qyz*&Suv)RR#9Xyh><j7>NBj5kbo87T|xm)YQ}J6SmA1wlnM~^?;A}~&@6zp z8>$g!`xb<4k1_~2Tnrw8xQwAVSzC$3u6>Ab)`Ax}9R@Gkk!;%vw`~`Ww+zRwZ$@C~ z@Jtk!SP|JfTnU!I7YG0Z0AT>on}~nufCcUY!T_LUAHEPgvJp6YZ9Fr3w4wp^=guRm zt3q!Qc0L-BDTA>2ZzVWXJrr*)8-fGn$I!d`5MrFCScPyr&t?dYxRKbg3%zW6aj|76 z7Jgfdtf84GEXhKzKGD<{ObK+$6oKvoB*|zd{$+D*5Nv5^0H7=b9x4D{v62cw=7BFa zRw2f=4?JXmV>v*5a6W!BH4|nEWO#NAK7OtUhtBlJ!WF}?dtU|OyZ0l;aZ;%W!h>)! zcp_6k<%sDzgtqoU`0Q{I60)r*D(#2lj5t7B68bjk4}t;k$V>xvPA&il9;)ROm9(mm z1M~)J&zxySP1OaO{iFIlze|XK5I+R7OHx6!r6>af(xUL@QzLNlTn;{1I|yIztU!W& zKVlgO354+A7zlzm`%%PnAE6)yVD+g&M5Se;V00F&gOdSmDG;?M5x*XAjjiL_AlS42 zZlNpd3li1Mn=27*J3yg$U3diN;_eAnh$caA#>}cPGW$f})rSjkmhK)OuN#PMJL&1O z>i}Y%Cn#_a2wNT;c$v^DIfZC@1=`!K*mkxMdy@K55ZTBYmcp*|S$w_#e76w);I9or zX2GkfSAtIyWPls$Y^bW}S^Ec#3lBaR-H}6a_rwgJ;N8Ylr%RuNF#P@(`M7s_e=MdT zw(LBOxQ_1-=R6LcxB-r^W+}@uqTOc^*;I|r_CDBiu^8WO?T@@$vd}-jFL;y4V%1NB z{a@b*axDPYR}ucZg;oJnH-E7o^}AOgiFR^PR1Q7$A%!TLeGi_QI|!0`pm7=ijGn|G z``$J;w%D;~%_(f%bs909htSJ$6e4ka-@%J*u~)*1;EoxDp+%V(RG5k5&rMS*Kn_#^ zHwJ<QjjI6I+PZM+*acWS_vsfNgcH#gHVktoW-8ODden7F`V#QHHoK}3M@I$YiF<P~ zcUlgXeAOSDzZs5*&Lc>$mqR3W-#ZDp2_bE(;po_bQ%xgraMv*80X_f>+W3D1A*)p& zYcQxD+*OH)j$<&(o#509k0#4NOt>W*anZqWse#+6I;gs|ZCQa}0AM?eaZDEgL`MeW zk)I7^AeMfWjg8xfA++Nt5*+0)$z47NuMpXW6x&9)I(Gvh90Q<F3*;t3fLHLHT@F+p zszq9-a^1yqJoCH~OtUvBOF8Sa;0*vywlf(32nTQ~2%gvOCiJ@sX2ZiQ_~q;&xNAxd zR&2__x~)SI+<uILI7q?U6o71?lBsqB2!#kue5WX;xIqw{@xb)tzG?(_R<ctbCy1>1 zwOX=KSkMpYNfAovtAX1+41&@Kubxk|D$s7I)Zk5mVMTUlX~uoG55&xg*;qrH->S{S zU~W}FSmai4g1|r+zaCdg%>Z!Y)nEYN6qqiT8<pkNNb20DjkL@*m~-*s)P9hNQTp8; z1%OjB8liE<_icuPHd|0NOMs;Zf}}#>mG1=ynP@fi$Bgk=SiikLmaQKGvE?}8oktKN zT`>R%N}xXHZE}Ovz`?jwB~;IppMls>i!je6*7aow=rpCG-@qIU$cSNCc6tnTD5^C@ z1_m(t0jEOXy{kX~T-2JW@>GKaz``3##B36A$M|eaDapjfodfU%1>tTwjsC7p3V`Z^ zXJH+d0r-G0=4g0TL-Vn{Xg<0Z9W^K6vb6&0x(ZLrLClbmNGvV`)YGF!l2CP^5>f4Y z(MICocAFuC2V5>hUf7IJKW@a-*|)>RnOV?w6~OitD{%hwNz|XMhO?^+CQA@v(=rif z?T>+Fw?i<QmGg(1>Er9x;QWyTsH;2$RoEYUrRU_JblPML&L7771W~}$QY$8n$-w5_ z190FUo0K`=m@omcIm1yrWjIWs!I1Rd6BsIaBvgL-23ji)K$Ezb2xgmFY|tbka}YA; zJcgi%Xw-aLj!SFbh2Uvte!Zf@VYZmz@knTBYGeMr6XWslbI%|oJ{k25Em-#Ud|ae~ z1o97!i$~!@&mbxx8C^~F*#FUdw46Wd?a%gohtrML_D%*Pf6N%%{rIohIYZ=)N%c?k zRv0}12Im%$gprRB%jBhG>|3?up3Q{ZwULln8wk1MD?(;`Nyvcv-yv~>XOUa)e1;r5 zSwm=ciMOoT^ey?xFJ56j)>(fclUKV*%!o(X>-(O1os=IvO=MYSzB1Lr$E(OI|Gk*` z51ulQEI8sOxwBrnF8{O%^T^#B+$3w-@0tH&&o3YiS6YcG`g;~F-$JaT?q@#t|9u1b zpA#}!bc&EAm4tjzO-N7d48X90(PT(oG0DoGOe|yHCVd~?NoK8bkU12<%=Huk1&~tu z1Owo7xk(_Ys<}uCCM!W_{7eBh_p$$CfdrCyFTcn9rvL7fALO6=sN(;N|NL+AuVmep zeavsj?az_d_dCggqlAJW<dc&M03HAYQKV`@2yDo*Ek*a?<yiZ{m#C}0Xq@T0JCv>| z3Xo(OM=H)@*}9#ub#y}$Yg#g%d-N{$+*Wmj*|-1rYwfO&`Tz3iH?eK^VQBKgQ*)U; zd*b*H@^7s^!R%jtcRw^)_`mCrocA+~o%vh1JxceSa_a~rC&Z%eOcgF)X+^t(pxp_y zyTF81!0_VRNWsWbl2=%wS3_pO3}PO;fTTaVo6KD4A~|>cjgfrqozF?%!h6^=RrV}- zWvu*ImHxf5yMIqKX=&?V{+c=*E}{vonj7)=sYu!<eEh3xF6sXC=Q7`)FRCQZ?v%-k zdkFc{KBEE{abDoT^MX<hf`~BE1gmWcY~?HQ)kj|<u3$PWk+FDf;WBh}J80MM4|7y6 z_Uv|fph+8TJeu55Rt!y!o>Usukil8Zp1aftO(u-V59lA!H=sWg`dOG21RjsvJ56b< zu~A6v6Au8a5)K@xq)j;rBqSOgE-<w@!9)X~4=D_Spg=GSK(ccWdS6<EeQUPCGWbs9 z%zgp|Pt8Z%pklb%u3$iRDl8TgH2LT1?a(AOxi>VqP}ih({RCzkn_8hs-#)zq`kSKz z`ZIa+{gu$<55K(!>leL>gBupWBnr&o<u?{F8=8;;yCkB^33MtDn26AYGp?n3KrkpW z0}~-PAf)3n)E&MBjdde1Sct@>?aP_#dw+cbs<3Tm)rLKgi881}hKE3tZo85xlR1c4 zm)oeC2<G?w{tyHEixF{H_{my?g$3a^56xtsxnO8EG<p1mg)AYaut+2nPltn805=Cw z0z}>q0AN%DK-dY2y;fC1iem>_FV^DJxey4F4KF@97de?J>HtMB>!DZKvqf%)n?f>) z24APst#THakt7*c$@lsb1orpX)T)Y$0tbJ2<E4kt(%wN&hvhiGV-2$Id>XP_y`KmK zz^DeItPq}n_d1Bnu5Jj#gE=!w@Yn-0pvg0T{*dhq65$ZSdEf?M>+CkN7NKO#q4ta5 zATu;+Y3&38_)DIE{!A9V^)$*#3e;uNhIy~Nhd<1_2bpO}Y#Dqq|7jFXeH^tl$IyPM z7U9X+;CT*i6#$QbqV<Iy6~GGunmti)5i_RTR*3npJPb|#_U<x#v~(jRm=G#AL0x`m zY;J=lNxfs4ZELeJ8y6c1O%9!?4(RXc3hbYj60Zf%j@-Eu9%0!YIsHkN3>F~A>05Jq z&2gFlNjY=4uL;1nH#9rK;E+rhQ#cqOy#AEFSAV!<Bik7OK!6(#Ar=mVv)6m}S3r{- zYl;%=zVDb#?~?#cw(mI_(7&@Pu>ZK?VbJ8vxjMK!9`K<Gs5P7RLX(uFUd%dL8{u?I zaIu5ebprqhICQwpFpDDox$s#C>RI~KnF}~@v=XzXj@I?|vSL;x>_cqc3z-o8L(F^d zCjdYJ&eL~}a~B)XX6w8m|GI`IXwu)B!geINs~w>sLAZD3tzKJd4YPcBZ@4|65SSW+ z(6uzTxJ(~YuSdrG^f&rIvf`^<f!x^0JMHH$Dx>q{=YNoY!q}&nrIV<S4;z>aVS|!3 zxMe?gm<)Q$Nrt>b$k2E7LFn3|In_6|;(Dap?t~@}J~N+<vJ?Qkg?>=>y>H7;A}l@? z@x!NIx4#gR3bA)T=3h!Xdqw4WsNOy^$)(Fp7(eHCY*;e&84Nz64`d=h@&F#U*R?pV zL+ZLhVfTo*UNLbl*v)AWopk`f%5qHMAcTbmqv1*$zS(z-`Gv&9Bki^aAoj{a`{f#( zTk*$#>CZ>RBeeJdn0i^!x$_@z)$Y^%hxAWp6QRrH!HLRq#+2AA6XBzO1%WOBP7Kof zSH!Z3*AKug^SELUf`dXJ;1E~{%ry8I(FTE+&@3mRLymw+YJ<0gM#UjKp)XR$%z?)o z4JRKAmn6V;{y5qWt%mdBQQs;Ii=&zEi{Sh@;6tLpnS#M_Jo_7FXVrE{P1PVC7j)rx z@KMPyB@Ke5e;I_JNN}bg_H|97mtQ{sZP-y&)}Q?cDRt*y_jod7S%TZcp-#+&%aVe; zd@E8j(;-GAu*uBH1;H+v;FNecBo0nDp&%r<9bIr=ISW~G1EPgyF9962Gzf6Ki3Org zY#_1+#N&k2b{@pp$^7}So@|@J31;PeyvU$<OYEv22;fFQ$&$owXe4Soxn8(r9)rZp z0Vuk)7(#G3x+$D47hrb-4t0C-$W)~sz+msy$P#eO1`^-<JPx>qf3GzYA>v06&Nx(n z7oh(ERJhy(t79b^PuF0@#YPMsnUB<g1C{u^6a?%^W=2qNtc@503k&*({L9MC2jG9E z5ZJS<Lf|<WN%BENb(}%P_RFZDFb3Q*3Sw9^cz~%6L%RtEvp4t)oBtmG{Ld6@q$Ugk z&p?FAHe|Zipy@(2_O7^$)S>xE7%&V1$5RDJkAkUD0Sw5^fxvqlIsg{{^N$MwdNmN` zh^?xO-f{&Z?6s&XuR}vkEiwv6vx^orK%IglQ*#rmA-H}w060Vd?*e!nKd$(nFxCH2 z<RlKkvIFVvjc94CM#YAD^v=mc;-GwRf{A4Zvaz%!S%u>NCok76;TP8;y6Sy)V%GkB o{#5`^00{dx`uF+219<uW0JfTxf?Ig}kpKVy07*qoM6N<$g5k`+IRF3v literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win2k_x2.png b/src/qt/assets/systemicons/os_win2k_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..a773288edf5492935053784ed3ca44ccd6bc8205 GIT binary patch literal 5948 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win31_x2.png b/src/qt/assets/systemicons/os_win31_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca2005d6acff00e65079e3cdf1e58f190d26876 GIT binary patch literal 6116 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win7_x2.png b/src/qt/assets/systemicons/os_win7_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..c8ce57a2bf5f12c908764c9d33cf676634f7c289 GIT binary patch literal 5835 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 VY~;e>v6BD*002ovPDHLkV1mHO<{|(9 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win81_x2.png b/src/qt/assets/systemicons/os_win81_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..07131ed6c6bdade2c5a6d03c6f19407e19356385 GIT binary patch literal 6134 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 IM6N<$f|K{9Jpcdz literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win8_x2.png b/src/qt/assets/systemicons/os_win8_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..ff94c2dd1176a919d4ea05f3299f511c16364295 GIT binary patch literal 6158 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win95_x2.png b/src/qt/assets/systemicons/os_win95_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..efd62799e7bf62b77da704b48550627f2d45c4e2 GIT binary patch literal 6296 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 O0000<MNUMnLSTY5wan}Q literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win98_x2.png b/src/qt/assets/systemicons/os_win98_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..c8fa4e7bbc69d9553527ea120a03c5c191e0483c GIT binary patch literal 6491 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 BE8GA8 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_win_other_x2.png b/src/qt/assets/systemicons/os_win_other_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..fac95889fef6e6c13865f0dd2f3b0b79eab94649 GIT binary patch literal 5454 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 Ef<{m2kN^Mx literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_winme_x2.png b/src/qt/assets/systemicons/os_winme_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..1c268c84bcb29adbb24f73040f1b99bb8ecea58f GIT binary patch literal 5959 zcmV-N7r5w&P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000*bNkl<ZcwXh3 zd30UXeeXYepQEc;)@WOj2U(NldA5*^!B+9e^hg+zLPDCf6w=oW<Tb2xNa%YcZPEvY zrhz6TKm#TiWAKP=unit$u#NG6@gxuOEZLH*S$90UM|+*CjV9kkasKLWt?%0R>PXk@ z&;I^?d;hkCD8F$5z~jK9Kq~(;q80cB@PrNgJU%}DhYvpVP3A9IgfAh1h=K?Z_QvRY z#~YRRTA>5Q^$F3>Ya!r;wP*O<()TDl{T!BMYc-`!pk(1gEPr$&3iIFTc%uRw`bKl( zRo>h9PU`C~z5M?|ZrH&0&gS05<+SNI(ubZn^c_7pfHI@j^$uZ1f&qu6o6eDac?&{F zgmfhYwdu3@)omk*;7!^H#|YJHp%OAOSp1dyNJvfNcTYY2xDEJx)hqe=FB^Gg%?*6p z{m}d7<{>Pp9T3J<F9(<p*7~D_@buP>i*#PDA-C-q(zcO8(wtn%#POq<SvsiOq2cJL zdM=bw<~2r4t(?~dAi)Mm3^y|T(h54SyvLKLEBV#ha{lu60`8oX+YQ24%u^4te;fxW zN3nGMS+d;Km(r|$oxA!!Suz60Od7LT#t~-nCLNRqmiPn!Yyj!mDk*Z+1@Q*{`Yk+t zdLI9=x}0y_F^a{rH3$zv&l+GLTz>#tKCGkpVhu&DN07GEtKXJbKwjZ!7EI0Vo_q)` z{XS$IfMWod1v4@L{P9Cb2wuh#0wEm@Vub4mf5TRORdX{hxT*2LZ3Qftr9t5IvKZGH zgz)s*h8nW!w;?4u|IxWWizjX`FsqNAv{qQFS3xu&bSMMa0GRyM$JzMyMus-+AU@Op zLZU&08#IW{hHX55`ev4{E9c(D1<aqF2U4H`TxSr%)1HG@xODm~CCvxWt1l&;@p+`= zkL8Y;gS)LC^c)a$JOI&MtDm%0Y5)NL_Rv@kFB!>CU!TX`t((YoLBxfdx<Mp|>q&G| zqtkW7OQ+_sZ2b)GSu%>sirniA!T@+<eGOR++k3A5pbEaXcm$R$yX_t_5PBAE0|Tc| z${N{tl#26{dH#Eo*?0RWo>)4EnvdVpAnZt6FA&RI5byE(lXF?IekNaXLEKc{7X+WX zMwrPTt-i{sV_mDi7hU+IAmGc!8Zv=<Z_dXt6ZHU?*Zn~-wO{}T1dUA?UpR<Y|Dl{M z`-^yH`5fv#eP5@B<#hH0QTsZbjqkf4DtXIw#GQ)@m{XBwwntNWjVoe+kbn@dYQt%= z8g^g_2PxyU1M1Q$xc`>nB*$CblMO^yze|oQ1Ex<sFb?g<0Rh!_Z=W+Mo7t{b?HI-L zZ_OfbVjDwRc49dJlmWrWORs51yiz@vm0ciQN6aeEi(1Yo1_<Hl{P|WsJ#dDS=8wFC zk02B`2!G}TzU~5ueAf1kH)34S6N0G)%FM4H0FGx90rV;qx6aCA{>-7gwY8WR-ns$n z{B{?_ZY&kVfVjfQ+GTV!Ze{6-xvVOh#_hKjQ9dKrY(f2j=nX)?y7i~@>f406SO0R# zOzysU1R1G5V|&My0WnY-7y#F*0i90&MM3~lfV3oEt{l!{7sj&9rM$Abg0$MLWVi3b zazfo8Qo@%>s(sA`@jkD*#d2-&G?pwZWQGgE84!dy^VeVQVE^7T6h~KI2qIQ8jcHT( z=Hdbzv-)T`{Qxi!O#a6@2LvMC2}*c2^_(CDShx}(f%tff2VINbb@MP@SY5=LO-IS7 z-%fVN0W2rn6U3!I(BY=WYt{2uUowqFiwc=KHFv;9N+{U$?rGBNtFTl6Y1s(bwffUp zQZbC&tOUX)*9k_<<jtf#5Jr8#Gmry9s%IJqdIGS_Ym$@V`0KBf@zsR|{AOh_o3<Wd za8ngo?FX@x=;a6(MB{rbtFClGOl8sHA|_56iUwg^Kue3CJv&cR*u2|2nMxchfh#Ff zdFb{+llx}!CJnkF7)1;Kls7UUfQU!T<O)K7G!U?b7I6j!S?LM<=o{m?f6*v@y`q>8 zK0HEh>rOH|KJ5p@s~W`Xt|K-SPhruL62?s&(rtmQn`=mI*oEzMB5iN=lcz9iN<Ia7 zDcv>?IIceH0FwfJPlP>+d;igOA)+3AbE8Mi<cu&iz)ap7jZAs~9II*O+2zMLeDD}~ ztyQFV9@9jXD@Qpf$H8&c9-q(UjJc$jOkw__VhW2h`Pol4Gve4Uh{vz{ee8G+4Skqr z|Gtu`r5S{j0pNG~)&K*eSN``Yx<>DOZ6O-Kx0h=Ggbe^w1OZEWD-Xm;4FF#+5K@?Z zeDC1~o?CvDbJf)@i0usWpBex}o(rN9ku#dO3svMduGf>7uIf{!F=+bT{M(NzP(Zk6 z)$e%{G(h^SzSC#&Mq3_S=ruzTV;ys7@FoOU4g{l<b-*VfWMB~2%Mnw`vUvU<X0v(s zC|+Dyz_GI@G>FvT*&eBp8mc9^b}1cK^N0(#Af=^+w5dy;&I7j;(j3y0L@5myN14f+ zqNqpAHW+jD`<?@g0}M6#uLByE4a6x|LaPr9DWGy@9&@MXvUXb`zh5(oOLf)cyC9N- z7rQ}7sYngifdDCW?$ekshQy2<#!VQ4-!TiJlmTGw0Wh}L&ghf-u>p7m#r&``d$Yjg zd02quxxfO#5<&uO2|mY54QU`)8ie51n@2G3hJ4=IT)^w=M<E-Jlh;;7Qm76A-ODSw zgdic(fVzByNB>@O=fYwtXARR05DEjqfpC}1YjYzMWA*z2FgC)W4*=tWF5yjDXzF^j z6@)z}ggjUHJTR8<VA>Y9&M%^3)<{-u9LYOdib-lcN`Bi;5+jWu&;S5Z!gUlkuAr@X zE3coK$+Fdxxoc4|^KKl0?XywF;%3pzi1T>?g!-!i$^Z}s01`b$-JlicKuCg(Nr#Zs zU)K;Zc}sk}&AoS&vEZfx9{sU{zvECB0Po~y{3?VbDRh~UjjQNr+RCbn6}+)}3b)KH zqH<m#z9b)xLsZ%YPX7R6r+_IUhMo>(&gfD>#H2)D7>?%#>D30u0CVWEOL#4BJ$7du zsh!m*%SI?ghdr2x@R1TauiYS}1R%+2W?19f1YHo@>uzAfJ5#BcUCd3Du8RgGqRgV1 zzQc??LS4fF#zF&hYUXfcMyt0X+5uSRIkqsb^$4ulaDwcX4^Vo0bWjM+C(b0ha1uvq zj+5KIi?l!u(h}V;q|-@$%Vt6?J2=!hgB{yuGHFH;v*s2vXmF|qfTAZ5fB`@l0H%l- z>tG~APY?!xxBB#i5O&PO^?UPLj|UIeQG4brCGCg1i$tf)V9@aKy!$V6*>_?RPcNUy zM|(eEaK}C}14p$(gp~RWAykOm)*a-ue8~C6Nj&?(EJ`L7Q9ieXoM9OVg_gpMsxJrw zAQCafq_1sagV3pAiX^rKi3dRHk%$Muk+5!KHJL5DkT@W00BRGb@q^on@L7TxrJ20+ zw-xL=IfiH7oJ`fO!wl)zL#F=-+7U{kgo9L$3urHy?fYnI9?z@$D;Qc@Ohx5r@(Z)U zqy(b(wx|pM!j9H}l~W7=LgI}=i%8TJ&H%MRz{!&hoUT4cN&CU>d;Xx6hBag&_s$)G zil(9iV++!G`uj6Ea;A*mtr^dI+Yd9ea}QY>L<FTILW59bcOE3O<A4idEUS)|lU`8D z^f@IIPsj()*(k3jsXjFz*47algb@Ah7DjOrA`;$x_c$3XA7P8nTzDi-;eiFk*m0IQ z(K%*UDjJr?6OT;i)E#BKw00a@wjW_|`$uF2K1GT!N~ecFI*LsHQ8GFY)7)IlmQ&^I z%p2{3D5YfbaD*i_V0r;CTS&i?j}5{Rm_lisfGL6+Fm)GOs6O14`yZPN51B~Eph-Ni zun;qOt!P?y$FQL({N0~V<Lh^fVW|sZ)AnOzx9%o8a0sbFAQVzc-DhNkPBEzd1Z~a3 z*m-^yA8a1O)Ei3}Gi@X?&c;!gZg9;1--wD0fY^@cXSawtK)}0i?4h=5C3!8Iv2ES- zP@7cFqI<u_WA~3I;x#k@1HjZI4>G2xak;URmscNU^NwR=w(TRwe-K;w`)j=P7JDV7 zf>7poCRG$MzPyM-e|tMNfD^+3pBID_Kra9-P3;{0<Q&CqySgttl(1<^nauqQi_oW0 zuhk7iObYb4HtSW0Gtv|J?$@Vq|LtYG_VyUw-8O@?wgU|9+>5O`d)`Sn^&~Z|!r!`; zqxCoN@s7z%g&qJ5ZN3-?2N1#>fDpL<;BnGgKf&j;A-oHZ`uK4yxUrP%j6{Oo#5-O2 zT?HM}mnek+AVHco9Sg`9l*qULbdm<K?CnxEzCW4d)`JZ7?<LM@@6mWAIV}ut*+{Uh z3X%jim<xP$9U)*QPg}d6<NInTXw%nSNFf2il|*;-7MGxVeLZ;tAfR_913(E79tbJB z?<UM$g@n|Uc>dzviG1bOGTwZrjJ2C5k=Xo+3*uvZPKyUnA|1z72at?SG<u(+0AhfM z2|;LaWY-B2+m7olPgu4teplm5DW5)?QF&=->qoTc47>7DAk_POV$uNJdV7<Pv&?Ag zJ4+uA{;zS|y|9$kZt+|B?qqydH3;IJs|d@|Ak44FJ*yc2U(5}{qo5Q7gCUOZJwaaE zuIQ0gk9EE&{P?!fM3k|9M_2=J-<v{cdi<Wn(2DjQ5_}Pe?}DI@;ad7xVnUqjhB4eZ zzl8Pgk74=xiP(*Y7!o)@QsjyOU;)YiFt+>rZa`ozRh58~drxAw){qjufQ+ub98SsT zQH(9j)T<l_8?}X?Ie-@)1k<M=JP7i$F0i2PN-dGj4r~iDGt<e*&g@PRU!2Wd^GmsP zZV?-|kL3*)M5z84V}kFXw?W^RpQCtkp?9m&tGE7~ZV<rfRWHzb`Y7!eYjEOHbRkMo zO$13G;KUP+vE$1aJ8?WqzIrcvcJJrosw#GE*-A8q6qPchxQuCEejo~=J1nmVe!6ib z7Y^;`;<3Y+fFUDBP*_&REqC5VZvIegX_~P}*x}u(8b12XBWM7hSPRH1o58GGXAqa1 zNW}b}z$msG5Wtz$FHpC00|Q0=&@6^zr&Cwo#D&@h0LoklM-Ltv@Oh34VdkHGpSaX? zl<=CT`dSVye}US=`vFK#OJQ`;Fnm7Sbwd-!Pn`$A_WAhIpMQ&r%DMO~VL$*s{hD_v zTGX<FD+f-o@?0%9EGlQjn31Sx-Z}K>u2A3%06~CWd4O}fUm+pEM>rB;`r`jh(a1c0 z{qygTojHhTG_|zztsgwawq2iaQ~3m5eCh|Jr6%Ep-aQ`v(KGJ0wwK+nJjawj`yp61 z9d#G@;9nmj5(-i=Z456w`Kb9^Pk}&)-@dki$De$e*PnfkP*_o3IgfZtbk_(ST@IK$ zeU6$qb(SibwnW9>{7W_Rk?rc9m45Zr4NBd;Ua7m*DRswMrEXiJ)RNUoEn212LRSmA zw6dqNC)}g;*?4LBJIZk!)n7y$M?L!Zudn(1Pwsn6f96g9T&2FWI;cieepkPLdBtYs zsB1^no=^4n=9fRHe!TIL`u78l`t7Gm{r-qjU2~TJmTkL=BZ(GDT9(nVe+6rPw~mV^ z&YR0kOpydVqM{Yr@ucWC9=v<LE`I%m6oMyz^3XM(|MQQ&3BZ*j`>0<32Rg1?<lA4r zod>>Di9m<mZMJ@RkS$gF@%w{BW7hPs{PeMJ5a{S&+nUuhcSdxPZ4R174k<0HF4;D= zCCClzCjZj!`C$2KcCFnBfe;p81C|2mfN*903JH|=dVtWWaL>a}kU#ZL+3@~H^bQ65 z<zvtE`+VH!kpQ%wt)|&avA=ob9-<Kpg_*MOuekf6C%EsCpE2Q<hjj`><9-(uz=i5# zG_{9l_Ct%`0MPWMC6OKk%d$yP^%S?fM$6u}c>Be5G@Q9)+<+EBnFhsEzv0@L`yT!o z@9#WFFdXJ<-}!}JF%#%qeRF+Pzt0mA;sFRY)zfj|gwFev<OHJe(ZS<fZfL^PmNwq| z-~iD`PE25MRytQNo}=Mv3#|b~OQ0tJEh#++maXNpAV08^!53bpYS}9GZ`zFrhtVLS z&5i<L)Nfp@ZP0}-FE592<4XZ(xY~*dc=kWn0FYHsY@YY-F~UIr7R{Z32@nXL{n=ml zP)R`^CZMc%H~<Zo>uC!@t1AGz$HxdfEE1`qI2ufvQ%6$kt6bcDmQ6L6n7*Kb^xVNc zFHaOPBQrCDgyhujl;|(4gn^zL4a?2O1lkd?BGubn+B^KT1r%|X=nVjj8$js}O279M zVYq)QO&89vec2U?rcY(`4U-Vk0<T$VH8$*5(y~EX#P}v+MPh=F&k?#P?%8(?0F|6W zdl2pJegPOaC_sW#URNiO!Xd*sL$d3J3m;zK(y8;V8)lQ5lZB(;?7qWXD-_@;!L`D1 zh#3t{Etr6R`uEp(>Njr^D^dz45{XO09~6YI1;9YSbAzQ_;CNq%7a<BdH*)pDNwzI( zpmgRGMwAtC;rMB?VoWX)V}gz%W_)s_hOgXV-sfbc$9B!|u?)WDAwn_{6^5_}T4Evw zh-iWIill9m897C9%TmtmSjVQNYe){9;#%SL8rKXJ8vw7b*@g*NQaOX^lS(nsvp$rJ z%BS<(VOmaqLddZQMg)OyYyd_?cZn`ZENLJlSOG@)*D<7RGlPTsxK@NBT3^TkzT7gs z&As{d4x*7aB#Zxi`fvDf_0w!#_6yd(@&r{Y|CRH5ma_WAf8@9S@_hh0&L1NfhCoPb zpcIJh2BbhLVYW{p$#ISY&_eDt00?mSLNy@1WH!M|M|t%B{)SuTOzrL+24@Y@>M#7k zAOH$MI2h5l!Xmnr^SL8BapMMQ(gG<I0Lplo#->&P5>ryUx54I?c7Pt=E8`N7@dG~> z?sMPp=_HiS)!W&``498rvW+->^2Yq!rMgCb`ph2yurdp9A`l5fIE1+t=f52arJ@s1 zprFp5LPyv~e{u7dAH+&XW6RQC_Ft&-Mw47tN&S}R=r8P{qe+|pL!>W-)@{!csNM>u z&DQ7sINR31+;&>`1<|mw3P`)<{~(hxkX9T3Y0DRWjueQwQwR`{lj!G42lyj44ibPc z38asl#IUmIBo4|VtR#oFt)ub$2>>i#0`WN`$)5cU7&MFw;iL87I>J{@bg#UXIg-Sg z-#`hU-b#~id<0+NZ2X71zOP!}9V}nFogQJuVWkhl9x|HvaZ4aB1%+jHq8JYN0<KUv z;RvBfm`Ef<I3lU_&A^{FjRlJ<C>m2ln?FozN04@Zi1vUYsB8lG2&p(ijvy2c>!Ys< zhfpYxHp23`iUT2|9!IGNM1nY-SBW%VM1=wX2wx&HEf-<O>!0iMvq09$h1VH?$vsaF zP9%ckI7HmBP2_MPelEF1W100Qvyh1?bcE0+v(6Csy?ep1qZPfMG-zY)pZec4e{+P; zuo$4#&RK0z;JV86_7Z6UUeQc->M8DA!R4bTS#hqG2{%k*#JF()2qREhIA)9u0pUr4 zFu+jPCT9R#e+Yd}k-|Gp=Q$sf-g=V5?_c8dvD1vbaW-~JhH0~-@*oKG_(gtU^T!7e ztEZ4spfm)jK_ojZ6a`mPf9?byzIllelcq6r>|`t<U4as2@f?M5#dU%p!~SjnLBPj# ziP$}b5)P)rbQtU$CatrEi+e9pce;kc@;Ug@bNW~~;()r2Zb+=H0`S|we*oX%I!Ejd zQy`>+hzJrLKchk$X}o-b!y9TDTsD>5@zZqG4ubjXZ8Qi_zyN>p5?hdZehnGb&jUOe p{om)G0KN;P@IND3fv14S{|lltfE}`XRqFr%002ovPDHLkV1lB{OdS9K literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_winnt4_x2.png b/src/qt/assets/systemicons/os_winnt4_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..c3352abcd66e1ca76113ed2911e83b976b76cc41 GIT binary patch literal 6045 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 XaG?nWIR&N<00000NkvXXu0mjfi9>$F literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_winvista_x2.png b/src/qt/assets/systemicons/os_winvista_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..7b633b79f29361af3d8ad02ef554251c9de2ee1a GIT binary patch literal 6013 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_winxp_x2.png b/src/qt/assets/systemicons/os_winxp_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..b97e6b51d6dc100dead5a947f6b369d2146c6b3d GIT binary patch literal 6340 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 GLSTZ5z1S20 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/os_xandros_x2.png b/src/qt/assets/systemicons/os_xandros_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..23de5ca91727d727cc8636176d59ec4a03904697 GIT binary patch literal 3209 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/pb_bora_pro.png b/src/qt/assets/systemicons/pb_bora_pro.png new file mode 100644 index 0000000000000000000000000000000000000000..6aaaf9d262a89918320563c5731e7d64bfb1f5e9 GIT binary patch literal 172596 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/pb_pb410.png b/src/qt/assets/systemicons/pb_pb410.png new file mode 100644 index 0000000000000000000000000000000000000000..c78c0496b639e4f468cb157072722bcadf7c1418 GIT binary patch literal 209719 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 NYD!v)H40`y{|7papXmSq literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/pb_pb640.png b/src/qt/assets/systemicons/pb_pb640.png new file mode 100644 index 0000000000000000000000000000000000000000..d0be550f1f1ba2a87be86b9620b316c873e4e848 GIT binary patch literal 177292 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 KT#bxL=>GsyVT~LB literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/pb_pb680.png b/src/qt/assets/systemicons/pb_pb680.png new file mode 100644 index 0000000000000000000000000000000000000000..a697d5dd0be69b1a820dbe287184f144ba7d1e8b GIT binary patch literal 172604 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/tandy_1000.png b/src/qt/assets/systemicons/tandy_1000.png new file mode 100644 index 0000000000000000000000000000000000000000..b50f2c1e60d9a02f75afd5ae010776c403212c34 GIT binary patch literal 160013 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%0A?WDTj9!%8lIxD>2?(1g}0%?hfq7u9bm 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 L2Jjj!`?&uBeoNW8 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/tandy_1000_hx.png b/src/qt/assets/systemicons/tandy_1000_hx.png new file mode 100644 index 0000000000000000000000000000000000000000..b770a6b7caae72ec7f8e75d2b345339c420ea1e8 GIT binary patch literal 179510 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 G?EeFK3Q*Jl literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/tandy_1000_sl2.png b/src/qt/assets/systemicons/tandy_1000_sl2.png new file mode 100644 index 0000000000000000000000000000000000000000..b7feae92a4a7ce728799171d7abe5f7b3b28c1eb GIT binary patch literal 213622 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%0Ae1KcFYFDLdW%B15t81|9 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/toshiba_t1000.png b/src/qt/assets/systemicons/toshiba_t1000.png new file mode 100644 index 0000000000000000000000000000000000000000..a2dbfc382c5b6fe8e0285fe991894b2df99ba8fc GIT binary patch literal 157081 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 PoogH=hmzWfr!M^iIbFqe literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/toshiba_t1200.png b/src/qt/assets/systemicons/toshiba_t1200.png new file mode 100644 index 0000000000000000000000000000000000000000..8c3cf0c37e31c2245e15ec66cdbb341c2bfe1861 GIT binary patch literal 291942 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 literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/toshiba_t1200_hdd.png b/src/qt/assets/systemicons/toshiba_t1200_hdd.png new file mode 100644 index 0000000000000000000000000000000000000000..8c3cf0c37e31c2245e15ec66cdbb341c2bfe1861 GIT binary patch literal 291942 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 literal 0 HcmV?d00001 diff --git a/src/qt/icons/green-square-16.png b/src/qt/icons/green-square-16.png new file mode 100644 index 0000000000000000000000000000000000000000..cb42c38ebbff15c1ca2a3a7289ee07d33323e338 GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|bUj@hLo9le z6BY;<9E$ue`ET-y$%2UtD`!pQNmTMy7LqVcxYBSik>Tjf&LjqgJppV|iMIStfEpP* MUHx3vIVCg!0AmUubN~PV literal 0 HcmV?d00001 diff --git a/src/qt/icons/pause-16.png b/src/qt/icons/pause-16.png new file mode 100644 index 0000000000000000000000000000000000000000..3757802324fb8df5973d732727932094a9ab89d7 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Og&v3Lo9le z6C_F=9PK{vUq6oJpL*CF!B|0~c&8*=WxGN)AW-v)waGfLf-!<|rDx>>Mux(biXx8< Sw`~R*z~JfX=d#Wzp$Py=TOw)z literal 0 HcmV?d00001 diff --git a/src/qt/icons/play-16.png b/src/qt/icons/play-16.png new file mode 100644 index 0000000000000000000000000000000000000000..bde40f503b155bffc67ccfaf035a058548575617 GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|!aQ9ZLo9mF zUOLFjpuoZGV3PM>9?#)<=N7~>3*DOkH%s49<fq!MlGm5ce!Inchuv)L(bp^uPO1Tp z1``}j9xOaJB~CKuU_S%%P3370TaSr2*atCOcw}$+yjT9nDweqQKpPl5UHx3vIVCg! E0DSK@iU0rr literal 0 HcmV?d00001 diff --git a/src/qt/icons/red-power-16.png b/src/qt/icons/red-power-16.png new file mode 100644 index 0000000000000000000000000000000000000000..c90ef491f3b934d49d99ba95a1e74777c5bf8a6a GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|GCW-zLo9le z6Belc5Rv%tKRDq*eNEO3jjb$48Jx_LCZ{`1OG!vbco4mRp5Syw1IrZW6^~hya*jXc z5=#;hE@4z{NMe4_FvF$USN5o$1E)&L<crJ#(`DQ=gg>$EI%u(&^R7bDqA5BI3}!*r V&Z{Hy#ejA)c)I$ztaD0e0swvyH(CGy literal 0 HcmV?d00001 diff --git a/src/qt/icons/red-square-16.png b/src/qt/icons/red-square-16.png new file mode 100644 index 0000000000000000000000000000000000000000..32faa7cdcaaa5a44fa8c83ecab644de555e449ee GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|3_M*NLo9le z6BY;<9Fq7S8S!uOl8@)*-F7f8$#OGm>6Ga`k#MCUkeRKWQ6ychi;+S4BahUYq$`hs PdKo-j{an^LB{Ts54p}2u literal 0 HcmV?d00001 diff --git a/src/qt/icons/stop-16.png b/src/qt/icons/stop-16.png new file mode 100644 index 0000000000000000000000000000000000000000..d73cad140126d6c37246844369798397e90e4722 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|j67W&Lo9le z6C^SYbe#DqBJpFsgm2C3>xaJ{lsuB<X5P{%;(O!33dY531_l9&n*25l455WQVz2bR R_5*b@c)I$ztaD0e0sw<DBy9iy literal 0 HcmV?d00001 diff --git a/src/qt/icons/yellow-square-16.png b/src/qt/icons/yellow-square-16.png new file mode 100644 index 0000000000000000000000000000000000000000..197cf394e92678c329a65c86606958067b76e9c2 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|^gUf1Lo9le z6BY;<9Fq9|-}sNZr?Rq(zOv=4iM)wQ?#f0IrU_RX4kj`jo!Obhz|dmADOHy(>Il@z N;OXk;vd$@?2>@swA6@_e literal 0 HcmV?d00001 diff --git a/src/qt/qt_downloader.cpp b/src/qt/qt_downloader.cpp new file mode 100644 index 000000000..329aeeafb --- /dev/null +++ b/src/qt/qt_downloader.cpp @@ -0,0 +1,95 @@ +/* + * 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. + * + * Downloader module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#include <QDir> +#include <QFile> +#include <QNetworkReply> +#include <QStandardPaths> + +#include "qt_downloader.hpp" + +extern "C" { +#include <86box/plat.h> +} + +Downloader:: +Downloader(const DownloadLocation downloadLocation, QObject *parent) + : QObject(parent) + , file(nullptr) + , reply(nullptr) + , variantData(QVariant::Invalid) +{ + char PATHBUF[256]; + switch (downloadLocation) { + case DownloadLocation::Data: + plat_get_global_data_dir(PATHBUF, 255); + break; + case DownloadLocation::Config: + plat_get_global_config_dir(PATHBUF, 255); + break; + case DownloadLocation::Temp: + plat_get_temp_dir(PATHBUF, 255); + break; + } + downloadDirectory = QDir(PATHBUF); +} + +Downloader::~Downloader() { delete file; } + +void Downloader::download(const QUrl &url, const QString &filepath, const QVariant &varData) { + + variantData = varData; + // temporary until I get the plat stuff fixed + // const auto global_dir = temporaryGetGlobalDataDir(); + // qDebug() << "I was passed filepath " << filepath; + // Join with filename to create final file + // const auto final_path = QDir(global_dir).filePath(filepath); + const auto final_path = downloadDirectory.filePath(filepath); + + file = new QFile(final_path); + if(!file->open(QIODevice::WriteOnly)) { + qWarning() << "Unable to open file " << final_path; + return; + } + + const auto nam = new QNetworkAccessManager(this); + // Create the network request and execute + const auto request = QNetworkRequest(url); + reply = nam->get(request); + // Connect to the finished signal + connect(reply, &QNetworkReply::finished, this, &Downloader::onResult); +} + +void +Downloader::onResult() +{ + if (reply->error()) { + qWarning() << "Error returned from QNetworkRequest: " << reply->errorString(); + emit errorOccurred(reply->errorString()); + reply->deleteLater(); + return; + } + + file->write(reply->readAll()); + file->flush(); + file->close(); + + reply->deleteLater(); + qDebug() << Q_FUNC_INFO << "Downloaded complete: file written to " << file->fileName(); + emit downloadCompleted(file->fileName(), variantData); +} + diff --git a/src/qt/qt_downloader.hpp b/src/qt/qt_downloader.hpp new file mode 100644 index 000000000..0bd3f1fee --- /dev/null +++ b/src/qt/qt_downloader.hpp @@ -0,0 +1,57 @@ +/* + * 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. + * + * Header for the downloader module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#ifndef QT_DOWNLOADER_HPP +#define QT_DOWNLOADER_HPP + +#include <QDir> +#include <QNetworkAccessManager> +#include <QString> +#include <QFile> + + +class Downloader : public QObject { + Q_OBJECT +public: + enum class DownloadLocation { + Data, // AppDataLocation via plat_get_global_data_dir() + Config, // AppConfigLocation via plat_get_global_config_dir() + Temp // TempLocation via plat_get_temp_dir() + }; + explicit Downloader(DownloadLocation downloadLocation = DownloadLocation::Data, QObject *parent = nullptr); + ~Downloader() final; + + void download(const QUrl &url, const QString &filepath, const QVariant &varData = QVariant::Invalid); + +signals: + // Signal emitted when the download is successful + void downloadCompleted(QString filename, QVariant varData); + // Signal emitted when an error occurs + void errorOccurred(const QString&); + +private slots: + void onResult(); + +private: + QFile *file; + QNetworkAccessManager nam; + QNetworkReply *reply; + QVariant variantData; + QDir downloadDirectory; +}; + +#endif diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 3f8476374..4d8a69cc1 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -77,6 +77,8 @@ extern "C" { #include "qt_styleoverride.hpp" #include "qt_unixmanagerfilter.hpp" #include "qt_util.hpp" +#include "qt_vmmanager_clientsocket.hpp" +#include "qt_vmmanager_mainwindow.hpp" // Void Cast #define VC(x) const_cast<wchar_t *>(x) @@ -662,6 +664,19 @@ main(int argc, char *argv[]) return 0; } + if (vmm_enabled) { + // VMManagerMain vmm; + // // Hackish until there is a proper solution + // QApplication::setApplicationName("86Box VM Manager"); + // QApplication::setApplicationDisplayName("86Box VM Manager"); + // vmm.show(); + // vmm.exec(); + const auto vmm_main_window = new VMManagerMainWindow(); + vmm_main_window->show(); + QApplication::exec(); + return 0; + } + #ifdef DISCORD discord_load(); #endif @@ -758,6 +773,36 @@ main(int argc, char *argv[]) socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET")); } + VMManagerClientSocket manager_socket; + if (qgetenv("VMM_86BOX_SOCKET").size()) { + manager_socket.IPCConnect(qgetenv("VMM_86BOX_SOCKET")); + QObject::connect(&manager_socket, &VMManagerClientSocket::pause, main_window, &MainWindow::togglePause); + QObject::connect(&manager_socket, &VMManagerClientSocket::resetVM, main_window, &MainWindow::hardReset); + QObject::connect(&manager_socket, &VMManagerClientSocket::showsettings, main_window, &MainWindow::showSettings); + QObject::connect(&manager_socket, &VMManagerClientSocket::ctrlaltdel, []() { pc_send_cad(); }); + QObject::connect(&manager_socket, &VMManagerClientSocket::request_shutdown, main_window, &MainWindow::close); + QObject::connect(&manager_socket, &VMManagerClientSocket::force_shutdown, []() { + do_stop(); + emit main_window->close(); + }); + QObject::connect(main_window, &MainWindow::vmmRunningStateChanged, &manager_socket, &VMManagerClientSocket::clientRunningStateChanged); + main_window->installEventFilter(&manager_socket); + } + + /* Warn the user about unsupported configs */ + if (cpu_override) { + QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("You are loading an unsupported configuration"), + QObject::tr("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."), + QMessageBox::NoButton, main_window); + warningbox.addButton(QObject::tr("Continue"), QMessageBox::AcceptRole); + warningbox.addButton(QObject::tr("Exit"), QMessageBox::RejectRole); + warningbox.exec(); + if (warningbox.result() == QDialog::Accepted) { + confirm_exit_cmdl = 0; /* skip the confirmation prompt without touching the config */ + emit main_window->close(); + } + } + // pc_reset_hard_init(); QTimer onesec; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 4594ee5be..5c9e10a85 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -2131,6 +2131,7 @@ MainWindow::updateUiPauseState() QString(tr("Pause execution")); ui->actionPause->setIcon(pause_icon); ui->actionPause->setToolTip(tooltip_text); + emit vmmRunningStateChanged(static_cast<VMManagerProtocol::RunningState>(dopause)); } void diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 917fd43f5..54a04a975 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -13,6 +13,8 @@ #include <array> #include <atomic> +#include "qt_vmmanager_protocol.hpp" + class MediaMenu; class RendererStack; @@ -63,6 +65,8 @@ signals: void showMessageForNonQtThread(int flags, const QString &header, const QString &message, bool richText, std::atomic_bool* done); void getTitleForNonQtThread(wchar_t *title); + + void vmmRunningStateChanged(VMManagerProtocol::RunningState state); public slots: void showSettings(); void hardReset(); diff --git a/src/qt/qt_updatecheck.cpp b/src/qt/qt_updatecheck.cpp new file mode 100644 index 000000000..83e2b34d9 --- /dev/null +++ b/src/qt/qt_updatecheck.cpp @@ -0,0 +1,360 @@ +/* + * 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. + * + * Update check module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#include <QDebug> +#include <QJsonArray> +#include <QJsonDocument> +#include <QStandardPaths> +#include <QTimer> + +#include "qt_updatecheck.hpp" +#include "qt_downloader.hpp" +#include "qt_updatedetails.hpp" + +extern "C" { +#include <86box/version.h> +} + +UpdateCheck:: +UpdateCheck(const UpdateChannel channel, QObject *parent) : QObject(parent) +{ + updateChannel = channel; + currentVersion = getCurrentVersion(channel); +} + +UpdateCheck::~ +UpdateCheck() + = default; + +void +UpdateCheck::checkForUpdates() +{ + if (updateChannel == UpdateChannel::Stable) { + const auto githubDownloader = new Downloader(Downloader::DownloadLocation::Temp); + connect(githubDownloader, &Downloader::downloadCompleted, this, &UpdateCheck::githubDownloadComplete); + connect(githubDownloader, &Downloader::errorOccurred, this, &UpdateCheck::generalDownloadError); + githubDownloader->download(QUrl(githubReleaseApi), "github_releases.json"); + } else { + const auto jenkinsDownloader = new Downloader(Downloader::DownloadLocation::Temp); + connect(jenkinsDownloader, &Downloader::downloadCompleted, this, &UpdateCheck::jenkinsDownloadComplete); + connect(jenkinsDownloader, &Downloader::errorOccurred, this, &UpdateCheck::generalDownloadError); + jenkinsDownloader->download(jenkinsLatestNReleasesUrl(10), "jenkins_list.json"); + } +} + +void +UpdateCheck::jenkinsDownloadComplete(const QString &filename, const QVariant &varData) +{ + auto generalError = tr("Unable to determine release information"); + auto jenkinsReleaseListResult = parseJenkinsJson(filename); + auto latestVersion = 0; // NOLINT (Default value as a fallback) + + if(!jenkinsReleaseListResult.has_value() || jenkinsReleaseListResult.value().isEmpty()) { + generalDownloadError(generalError); + return; + } + const auto jenkinsReleaseList = jenkinsReleaseListResult.value(); + latestVersion = jenkinsReleaseListResult->first().buildNumber; + + // If we can't determine the local build (blank current version), always show an update as available. + // Callers can adjust accordingly. + // Otherwise, do a comparison with EMU_BUILD_NUM + bool updateAvailable = false; + bool upToDate = true; + if(currentVersion.isEmpty() || EMU_BUILD_NUM < latestVersion) { + updateAvailable = true; + upToDate = false; + } + + const auto updateResult = UpdateResult { + .channel = updateChannel, + .updateAvailable = updateAvailable, + .upToDate = upToDate, + .currentVersion = currentVersion, + .latestVersion = QString::number(latestVersion), + .githubInfo = {}, + .jenkinsInfo = jenkinsReleaseList, + }; + + emit updateCheckComplete(updateResult); +} + +void +UpdateCheck::generalDownloadError(const QString &error) +{ + emit updateCheckError(error); +} + +void +UpdateCheck::githubDownloadComplete(const QString &filename, const QVariant &varData) +{ + const auto generalError = tr("Unable to determine release information"); + const auto githubReleaseListResult = parseGithubJson(filename); + QString latestVersion = "0.0"; + if(!githubReleaseListResult.has_value() || githubReleaseListResult.value().isEmpty()) { + generalDownloadError(generalError); + } + auto githubReleaseList = githubReleaseListResult.value(); + // Warning: this check (using the tag name) relies on a consistent naming scheme: "v<number>" + // where <number> is the release number. For example, 4.2 from v4.2 as the tag name. + // Another option would be parsing the name field which is generally "86Box <number>" but + // either option requires a consistent naming scheme. + latestVersion = githubReleaseList.first().tag_name.replace("v", ""); + for (const auto &release: githubReleaseList) { + qDebug().noquote().nospace() << release.name << ": " << release.html_url << " (" << release.created_at << ")"; + } + + // const auto updateDetails = new UpdateDetails(githubReleaseList, currentVersion); + bool updateAvailable = false; + bool upToDate = true; + if(currentVersion.isEmpty() || (versionCompare(currentVersion, latestVersion) < 0)) { + updateAvailable = true; + upToDate = false; + } + + const auto updateResult = UpdateResult { + .channel = updateChannel, + .updateAvailable = updateAvailable, + .upToDate = upToDate, + .currentVersion = currentVersion, + .latestVersion = latestVersion, + .githubInfo = githubReleaseList, + .jenkinsInfo = {}, + }; + + emit updateCheckComplete(updateResult); + +} + +QUrl +UpdateCheck::jenkinsLatestNReleasesUrl(const int &count) +{ + const auto urlPath = QString("https://ci.86box.net/job/86box/api/json?tree=builds[number,result,timestamp,changeSets[items[commitId,affectedPaths,author[fullName],msg,id]]]{0,%1}").arg(count); + return { urlPath }; +} + +QString +UpdateCheck::getCurrentVersion(const UpdateChannel &updateChannel) +{ + if (updateChannel == UpdateChannel::Stable) { + return {EMU_VERSION}; + } + // If EMU_BUILD_NUM is anything other than the default of zero it was set by the build process + if constexpr (EMU_BUILD_NUM != 0) { + return QString::number(EMU_BUILD_NUM); // NOLINT because EMU_BUILD_NUM is defined as 0 by default and is set at build time + } + // EMU_BUILD_NUM is not set, most likely a local build + return {}; // NOLINT (Having EMU_BUILD_NUM assigned to a default number throws off the linter) +} + +std::optional<QList<UpdateCheck::JenkinsReleaseInfo>> +UpdateCheck::parseJenkinsJson(const QString &filename) +{ + QList<JenkinsReleaseInfo> releaseInfoList; + QFile json_file(filename); + if (!json_file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Couldn't open the json file: error" << json_file.error(); + return std::nullopt; + } + + const QString read_file = json_file.readAll(); + json_file.close(); + + const auto json_doc = QJsonDocument::fromJson(read_file.toUtf8()); + + if (json_doc.isNull()) { + qWarning("Failed to create QJsonDocument, possibly invalid JSON"); + return std::nullopt; + } + + if (!json_doc.isObject()) { + qWarning("JSON does not have the expected format (object in root), cannot continue"); + return std::nullopt; + } + + auto json_object = json_doc.object(); + + // The json contains multiple release + if(json_object.contains("builds") && json_object["builds"].isArray()) { + + QJsonArray builds = json_object["builds"].toArray(); + for (const auto &each_build: builds) { + if (auto build = parseJenkinsRelease(each_build.toObject()); build.has_value() && build.value().result == "SUCCESS") { + releaseInfoList.append(build.value()); + } + } + } else if(json_object.contains("changeSets") && json_object["changeSets"].isArray()) { + // The json contains only one release, as obtained by the lastSuccessfulBuild api + if (const auto build = parseJenkinsRelease(json_object); build.has_value()) { + releaseInfoList.append(build.value()); + } + } else { + qWarning("JSON is missing data or has invalid data, cannot continue"); + qDebug() << json_object; + return std::nullopt; + } + + return releaseInfoList; +} + +std::optional<UpdateCheck::JenkinsReleaseInfo> +UpdateCheck::parseJenkinsRelease(const QJsonObject &json) +{ + // The root should contain number, result, and timestamp. + if (!json.contains("number") || !json.contains("result") || !json.contains("timestamp")) { + return std::nullopt; + } + + auto releaseInfo = JenkinsReleaseInfo { + .buildNumber = json["number"].toInt(), + .result = json["result"].toString(), + .timestamp = static_cast<qint64>(json["timestamp"].toDouble()) + }; + + // Overview + // Each build should contain a changeSets object with an array. Only the first element is needed. + // The first element should be an object containing an items object with an array. + // Each array element in the items object has information releated to the build. More or less: commit data + // In jq parlance it would be similar to `builds[].changeSets[0].items[]` + + // To break down the somewhat complicated if-init statement below: + // * Get the object for `changeSets` + // * Convert the value to array + // * Grab the first element in the array + // Proceed if + // * the element (first in changeSets) is an object that contains the key `items` + if (const auto changeSet = json["changeSets"].toArray().first(); changeSet.isObject() && changeSet.toObject().contains("items")) { + // Then proceed to process each `items` array element + for (const auto &item : changeSet.toObject()["items"].toArray()) { + auto itemObject = item.toObject(); + // Basic validation + if (!itemObject.contains("commitId") || !itemObject.contains("msg") || !itemObject.contains("affectedPaths")) { + return std::nullopt; + } + // Convert the paths for each commit to a string list + QStringList paths; + for (const auto &each_path : itemObject["affectedPaths"].toArray().toVariantList()) { + if (each_path.type() == QVariant::String) { + paths.append(each_path.toString()); + } + } + // Build the structure + const auto releaseItem = JenkinsChangeSetItem { + .buildId = itemObject["commitId"].toString(), + .author = itemObject["author"].toObject()["fullName"].toString(), + .message = itemObject["msg"].toString(), + .affectedPaths = paths, + }; + releaseInfo.changeSetItems.append(releaseItem); + } + } else { + qWarning("Could not parse release information, possibly invalid JSON"); + } + return releaseInfo; +} + +std::optional<QList<UpdateCheck::GithubReleaseInfo>> +UpdateCheck::parseGithubJson(const QString &filename) +{ + QList<GithubReleaseInfo> releaseInfoList; + QFile json_file(filename); + if (!json_file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning("Couldn't open the json file: error %d", json_file.error()); + return std::nullopt; + } + + const QString read_file = json_file.readAll(); + json_file.close(); + + const auto json_doc = QJsonDocument::fromJson(read_file.toUtf8()); + + if (json_doc.isNull()) { + qWarning("Failed to create QJsonDocument, possibly invalid JSON"); + return std::nullopt; + } + + if (!json_doc.isArray()) { + qWarning("JSON does not have the expected format (array in root), cannot continue"); + return std::nullopt; + } + + auto release_array = json_doc.array(); + + for (const auto &each_release: release_array) { + if (auto release = parseGithubRelease(each_release.toObject()); release.has_value()) { + releaseInfoList.append(release.value()); + } + } + return releaseInfoList; +} +std::optional<UpdateCheck::GithubReleaseInfo> +UpdateCheck::parseGithubRelease(const QJsonObject &json) +{ + // Perform some basic validation + if (!json.contains("name") || !json.contains("tag_name") || !json.contains("html_url")) { + return std::nullopt; + } + + auto githubRelease = GithubReleaseInfo { + .name = json["name"].toString(), + .tag_name = json["tag_name"].toString(), + .html_url = json["html_url"].toString(), + .target_commitish = json["target_commitish"].toString(), + .created_at = json["created_at"].toString(), + .published_at = json["published_at"].toString(), + .body = json["body"].toString(), + }; + + return githubRelease; +} + +// A simple method to compare version numbers +// Should work for comparing x.y.z and x.y. Missing +// values (parts) will be treated as zeroes +int +UpdateCheck::versionCompare(const QString &version1, const QString &version2) +{ + // Split both + QStringList v1List = version1.split('.'); + QStringList v2List = version2.split('.'); + + // Out of the two versions get the maximum amount of "parts" + const int maxParts = std::max(v1List.size(), v2List.size()); + + // Initialize both with zeros + QVector<int> v1Parts(maxParts, 0); + QVector<int> v2Parts(maxParts, 0); + + for (int i = 0; i < v1List.size(); ++i) { + v1Parts[i] = v1List[i].toInt(); + } + + for (int i = 0; i < v2List.size(); ++i) { + v2Parts[i] = v2List[i].toInt(); + } + + for (int i = 0; i < maxParts; ++i) { + // First version is greater + if (v1Parts[i] > v2Parts[i]) + return 1; + // First version is less + if (v1Parts[i] < v2Parts[i]) + return -1; + } + // They are equal + return 0; +} diff --git a/src/qt/qt_updatecheck.hpp b/src/qt/qt_updatecheck.hpp new file mode 100644 index 000000000..2c04993fc --- /dev/null +++ b/src/qt/qt_updatecheck.hpp @@ -0,0 +1,104 @@ +/* + * 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. + * + * Header for the update check module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#ifndef QT_UPDATECHECK_HPP +#define QT_UPDATECHECK_HPP + +#include <QJsonObject> +#include <QObject> +#include <QUrl> +#include <QWidget> + +#include <optional> + +class UpdateCheck final : public QObject { + Q_OBJECT +public: + enum class UpdateChannel { + Stable, + CI, + }; + + struct JenkinsChangeSetItem { + QString buildId; // sha hash + QString author; // github username + QString message; // commit message + QStringList affectedPaths; // list of files in the change + }; + + struct JenkinsReleaseInfo { + int buildNumber = 0; + QString result; + qint64 timestamp = 0; + QList<JenkinsChangeSetItem> changeSetItems; + }; + + struct GithubReleaseInfo { + QString name; + QString tag_name; + QString html_url; + QString target_commitish; + QString created_at; + QString published_at; + QString body; + }; + + struct UpdateResult { + UpdateChannel channel; + bool updateAvailable = false; + bool upToDate = false; + QString currentVersion; + QString latestVersion; + QList<GithubReleaseInfo> githubInfo; + QList<JenkinsReleaseInfo> jenkinsInfo; + }; + + explicit UpdateCheck(UpdateChannel channel, QObject *parent = nullptr); + ~UpdateCheck() override; + void checkForUpdates(); + static int versionCompare(const QString &version1, const QString &version2); + [[nodiscard]] static QString getCurrentVersion(const UpdateChannel &updateChannel = UpdateChannel::Stable); + +signals: + // void updateCheckComplete(const UpdateCheck::UpdateChannel &channel, const QVariant &updateData); + void updateCheckComplete(const UpdateCheck::UpdateResult &result); + void updateCheckError(const QString &errorMsg); + +private: + UpdateChannel updateChannel = UpdateChannel::Stable; + + const QUrl githubReleaseApi = QUrl("https://api.github.com/repos/86box/86Box/releases"); + const QUrl jenkinsLatestApi = QUrl("https://ci.86box.net/job/86box/lastSuccessfulBuild/api/json"); + QString jenkinsLatestVersion; + QString currentVersion; + + static QUrl jenkinsLatestNReleasesUrl(const int &count); + + static std::optional<QList<JenkinsReleaseInfo>> parseJenkinsJson(const QString &filename); + static std::optional<JenkinsReleaseInfo> parseJenkinsRelease(const QJsonObject &json); + + static std::optional<QList<GithubReleaseInfo>> parseGithubJson(const QString &filename); + static std::optional<GithubReleaseInfo> parseGithubRelease(const QJsonObject &json); + + +private slots: + void jenkinsDownloadComplete(const QString &filename, const QVariant& varData); + void githubDownloadComplete(const QString &filename, const QVariant& varData); + void generalDownloadError(const QString &error); +}; + +#endif // QT_UPDATECHECK_HPP diff --git a/src/qt/qt_updatecheckdialog.cpp b/src/qt/qt_updatecheckdialog.cpp new file mode 100644 index 000000000..d0cb6941d --- /dev/null +++ b/src/qt/qt_updatecheckdialog.cpp @@ -0,0 +1,90 @@ +/* + * 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. + * + * Update check dialog module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#include <QDir> +#include <QTimer> + +#include "qt_updatecheckdialog.hpp" +#include "ui_qt_updatecheckdialog.h" +#include "qt_updatedetails.hpp" + +extern "C" { +#include <86box/version.h> +} + +UpdateCheckDialog:: +UpdateCheckDialog(const UpdateCheck::UpdateChannel channel, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateCheckDialog), updateCheck(new UpdateCheck(channel)) +{ + ui->setupUi(this); + setWindowTitle(tr("Update check")); + ui->statusLabel->setHidden(true); + updateChannel = channel; + currentVersion = UpdateCheck::getCurrentVersion(updateChannel); + connect(updateCheck, &UpdateCheck::updateCheckError, [=](const QString &errorMsg) { + generalDownloadError(errorMsg); + }); + connect(updateCheck, &UpdateCheck::updateCheckComplete, this, &UpdateCheckDialog::downloadComplete); + + QTimer::singleShot(0, [this] { + updateCheck->checkForUpdates(); + }); +} + +UpdateCheckDialog::~ +UpdateCheckDialog() + = default; + +void +UpdateCheckDialog::generalDownloadError(const QString &error) const +{ + ui->progressBar->setMaximum(100); + ui->progressBar->setValue(100); + ui->statusLabel->setVisible(true); + const auto statusText = tr("There was an error checking for updates:\n\n%1\n\nPlease try again later.").arg(error); + ui->statusLabel->setText(statusText); + ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok); +} + +void +UpdateCheckDialog::downloadComplete(const UpdateCheck::UpdateResult &result) +{ + if (result.upToDate) { + upToDate(); + return; + } + + const auto updateDetails = new UpdateDetails(result); + connect(updateDetails, &QDialog::accepted, [this] { + accept(); + }); + connect(updateDetails, &QDialog::rejected, [this] { + reject(); + }); + updateDetails->exec(); +} + +void +UpdateCheckDialog::upToDate() +{ + ui->titleLabel->setText(tr("Update check complete")); + ui->progressBar->setMaximum(100); + ui->progressBar->setValue(100); + ui->statusLabel->setVisible(true); + const auto statusText = tr("You are running the latest %1 version of 86Box: %2").arg(updateChannel == UpdateCheck::UpdateChannel::Stable ? "stable" : "beta", currentVersion); + ui->statusLabel->setText(statusText); + ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok); +} diff --git a/src/qt/qt_updatecheckdialog.hpp b/src/qt/qt_updatecheckdialog.hpp new file mode 100644 index 000000000..0f1c0dfa8 --- /dev/null +++ b/src/qt/qt_updatecheckdialog.hpp @@ -0,0 +1,47 @@ +/* + * 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. + * + * Header for the update check dialog module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#ifndef QT_UPDATECHECKDIALOG_HPP +#define QT_UPDATECHECKDIALOG_HPP + +#include <QDialog> + +#include <qt_updatecheck.hpp> + +namespace Ui { +class UpdateCheckDialog; +} + +class UpdateCheckDialog final : public QDialog { + Q_OBJECT +public: + explicit UpdateCheckDialog(UpdateCheck::UpdateChannel channel, QWidget *parent = nullptr); + ~UpdateCheckDialog() override; + +private: + Ui::UpdateCheckDialog *ui; + UpdateCheck::UpdateChannel updateChannel = UpdateCheck::UpdateChannel::Stable; + UpdateCheck *updateCheck; + QString currentVersion; + void upToDate(); + +private slots: + void downloadComplete(const UpdateCheck::UpdateResult &result); + void generalDownloadError(const QString &error) const; +}; + +#endif // QT_UPDATECHECKDIALOG_HPP diff --git a/src/qt/qt_updatecheckdialog.ui b/src/qt/qt_updatecheckdialog.ui new file mode 100644 index 000000000..e50a541bb --- /dev/null +++ b/src/qt/qt_updatecheckdialog.ui @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UpdateCheckDialog</class> + <widget class="QDialog" name="UpdateCheckDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>350</width> + <height>134</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="titleLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Checking for updates..</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="progressBar"> + <property name="maximum"> + <number>0</number> + </property> + <property name="value"> + <number>-1</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="statusLabel"> + <property name="text"> + <string>Status text here</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>UpdateCheckDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>UpdateCheckDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/qt_updatedetails.cpp b/src/qt/qt_updatedetails.cpp new file mode 100644 index 000000000..1328da732 --- /dev/null +++ b/src/qt/qt_updatedetails.cpp @@ -0,0 +1,111 @@ +/* + * 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. + * + * Update details module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#include "qt_updatedetails.hpp" +#include "ui_qt_updatedetails.h" + +#include <QDesktopServices> +#include <QPushButton> + + +UpdateDetails:: +UpdateDetails(const UpdateCheck::UpdateResult &updateResult, QWidget *parent) : ui(new Ui::UpdateDetails) +{ + ui->setupUi(this); + setWindowTitle("86Box Update"); + ui->updateTitle->setText("<b>An update to 86Box is available!</b>"); + QString currentVersionText; + QString releaseType = updateResult.channel == UpdateCheck::UpdateChannel::Stable ? tr("version") : tr("build"); + if(!updateResult.currentVersion.isEmpty()) { + currentVersionText = tr("You are currently running %1 <b>%2</b>. ").arg(releaseType, updateResult.currentVersion); + } + + const auto updateDetailsText = tr("<b>%1 %2</b> is now available. %3Would you like to visit the download page?").arg(releaseType[0].toUpper() + releaseType.mid(1), updateResult.latestVersion, currentVersionText); + ui->updateDetails->setText(updateDetailsText); + + if(updateResult.channel == UpdateCheck::UpdateChannel::Stable) { + ui->updateText->setMarkdown(githubUpdateToMarkdown(updateResult.githubInfo)); + } else { + ui->updateText->setMarkdown(jenkinsUpdateToMarkdown(updateResult.jenkinsInfo)); + } + + const auto downloadButton = new QPushButton(tr("Visit download page")); + ui->buttonBox->addButton(downloadButton, QDialogButtonBox::AcceptRole); + // Override accepted to mean "I want to visit the download page" + connect(ui->buttonBox, &QDialogButtonBox::accepted, [this, updateResult] { + visitDownloadPage(updateResult.channel); + }); + const auto logo = QPixmap(":/assets/86box.png").scaled(QSize(64, 64), Qt::KeepAspectRatio, Qt::SmoothTransformation); + + ui->icon->setPixmap(logo); +} + +UpdateDetails::~ +UpdateDetails() + = default; + +QString +UpdateDetails::jenkinsUpdateToMarkdown(const QList<UpdateCheck::JenkinsReleaseInfo> &releaseInfoList) +{ + QStringList fullText; + for (const auto &update : releaseInfoList) { + fullText.append(QString("### Build %1").arg(update.buildNumber)); + fullText.append("Changes:"); + for (const auto &item : update.changeSetItems) { + fullText.append(QString("* %1").arg(item.message)); + } + fullText.append("\n\n\n---\n\n\n"); + } + // pop off the last hr + fullText.removeLast(); + // return fullText.join("\n\n---\n\n"); + return fullText.join("\n"); +} + +QString +UpdateDetails::githubUpdateToMarkdown(const QList<UpdateCheck::GithubReleaseInfo> &releaseInfoList) +{ + // The github release info can be rather large so we'll only + // display the most recent one + QList<UpdateCheck::GithubReleaseInfo> singleRelease; + if (!releaseInfoList.isEmpty()) { + singleRelease.append(releaseInfoList.first()); + } + QStringList fullText; + for (const auto &release : singleRelease) { + fullText.append(QString("#### %1").arg(release.name)); + // Github body text should already be in markdown and can just + // be placed here as-is + fullText.append(release.body); + fullText.append("\n\n\n---\n\n\n"); + } + // pop off the last hr + fullText.removeLast(); + return fullText.join("\n"); +} +void +UpdateDetails::visitDownloadPage(const UpdateCheck::UpdateChannel &channel) +{ + switch (channel) { + case UpdateCheck::UpdateChannel::Stable: + QDesktopServices::openUrl(QUrl("https://ci.86box.net/job/86Box/lastSuccessfulBuild/artifact/")); + break; + case UpdateCheck::UpdateChannel::CI: + QDesktopServices::openUrl(QUrl("https://github.com/86Box/86Box/releases/latest")); + break; + } +} diff --git a/src/qt/qt_updatedetails.hpp b/src/qt/qt_updatedetails.hpp new file mode 100644 index 000000000..8c3528e11 --- /dev/null +++ b/src/qt/qt_updatedetails.hpp @@ -0,0 +1,43 @@ +/* + * 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. + * + * Header for the update details module + * + * + * + * Authors: cold-brewed + * + * Copyright 2024 cold-brewed + */ + +#ifndef QT_UPDATEDETAILS_HPP +#define QT_UPDATEDETAILS_HPP + +#include <QDialog> +#include <QWidget> +#include "qt_updatecheck.hpp" + +namespace Ui { +class UpdateDetails; +} + +class UpdateDetails final : public QDialog { + Q_OBJECT +public: + explicit UpdateDetails(const UpdateCheck::UpdateResult &updateResult, QWidget *parent = nullptr); + ~UpdateDetails() override; +private: + Ui::UpdateDetails *ui; + static QString jenkinsUpdateToMarkdown(const QList<UpdateCheck::JenkinsReleaseInfo> &releaseInfoList); + static QString githubUpdateToMarkdown(const QList<UpdateCheck::GithubReleaseInfo> &releaseInfoList); +private slots: + static void visitDownloadPage(const UpdateCheck::UpdateChannel &channel); +}; + + +#endif // QT_UPDATEDETAILS_HPP diff --git a/src/qt/qt_updatedetails.ui b/src/qt/qt_updatedetails.ui new file mode 100644 index 000000000..7b9c0aa2a --- /dev/null +++ b/src/qt/qt_updatedetails.ui @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UpdateDetails</class> + <widget class="QDialog" name="UpdateDetails"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>700</width> + <height>500</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>600</width> + <height>400</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="widgetLeft" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>12</number> + </property> + <property name="topMargin"> + <number>12</number> + </property> + <property name="rightMargin"> + <number>12</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="icon"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>64</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="widgetRight" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="updateTitle"> + <property name="text"> + <string>Title</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="updateDetails"> + <property name="text"> + <string>Details</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Release notes:</string> + </property> + </widget> + </item> + <item> + <widget class="QTextBrowser" name="updateText"> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + <property name="openLinks"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>UpdateDetails</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>UpdateDetails</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/qt_vmmanager_addmachine.cpp b/src/qt/qt_vmmanager_addmachine.cpp new file mode 100644 index 000000000..db40972a1 --- /dev/null +++ b/src/qt/qt_vmmanager_addmachine.cpp @@ -0,0 +1,361 @@ +/* +* 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. +* +* 86Box VM manager add machine wizard +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include <QApplication> +#include <QDebug> +#include <QFileDialog> +#include <QMessageBox> +#include <QPushButton> +#include <QStyle> +#include <QVBoxLayout> + +#include "qt_vmmanager_addmachine.hpp" + +extern "C" { +#include <86box/86box.h> +} + +// Implementation note: There are several classes in this file: +// One for the main Wizard class and one for each page of the wizard + +VMManagerAddMachine:: +VMManagerAddMachine(QWidget *parent) : QWizard(parent) +{ + setPage(Page_Intro, new IntroPage); + setPage(Page_WithExistingConfig, new WithExistingConfigPage); + setPage(Page_NameAndLocation, new NameAndLocationPage); + setPage(Page_Conclusion, new ConclusionPage); + + // Need to create a better image + // QPixmap originalPixmap(":/assets/86box.png"); + // QPixmap scaledPixmap = originalPixmap.scaled(150, 150, Qt::KeepAspectRatio); + QPixmap wizardPixmap(":/assets/86box-wizard.png"); + +#ifndef Q_OS_MACOS + setWizardStyle(ModernStyle); + // setPixmap(LogoPixmap, scaledPixmap); + // setPixmap(LogoPixmap, wizardPixmap); + // setPixmap(WatermarkPixmap, scaledPixmap); + setPixmap(WatermarkPixmap, wizardPixmap); +#else + // macos + // setPixmap(BackgroundPixmap, scaledPixmap); + setPixmap(BackgroundPixmap, wizardPixmap); +#endif + + // Wizard wants to resize based on image. This keeps the size + setMinimumSize(size()); + setOption(HaveHelpButton, true); + // setPixmap(LogoPixmap, QPixmap(":/settings/qt/icons/86Box-gray.ico")); + + connect(this, &QWizard::helpRequested, this, &VMManagerAddMachine::showHelp); + + setWindowTitle(tr("Add new system wizard")); +} + +void +VMManagerAddMachine::showHelp() +{ + // TBD + static QString lastHelpMessage; + + QString message; + + // Help will depend on the current page + switch (currentId()) { + case Page_Intro: + message = tr("This is the into page."); + break; + default: + message = tr("No help has been added yet, you're on your own."); + break; + } + + if (lastHelpMessage == message) { + message = tr("Did you click help twice?"); + } + + QMessageBox::information(this, tr("Add new system wizard help"), message); + lastHelpMessage = message; +} + +IntroPage:: +IntroPage(QWidget *parent) +{ + setTitle(tr("Introduction")); + + setPixmap(QWizard::WatermarkPixmap, QPixmap(":/assets/qt/assets/86box.png")); + + topLabel = new QLabel(tr("This will help you add a new system to 86Box.")); + // topLabel = new QLabel(tr("This will help you add a new system to 86Box.\n\n Choose \"New configuration\" if you'd like to create a new machine.\n\nChoose \"Use existing configuration\" if you'd like to paste in an existing configuration from elsewhere.")); + topLabel->setWordWrap(true); + + newConfigRadioButton = new QRadioButton(tr("New configuration")); + // auto newDescription = new QLabel(tr("Choose this option to start with a fresh configuration.")); + existingConfigRadioButton = new QRadioButton(tr("Use existing configuraion")); + // auto existingDescription = new QLabel(tr("Use this option if you'd like to paste in the configuration file from an existing system.")); + newConfigRadioButton->setChecked(true); + + const auto layout = new QVBoxLayout(); + layout->addWidget(topLabel); + layout->addWidget(newConfigRadioButton); + // layout->addWidget(newDescription); + layout->addWidget(existingConfigRadioButton); + // layout->addWidget(existingDescription); + + setLayout(layout); +} + +int +IntroPage::nextId() const +{ + if (newConfigRadioButton->isChecked()) { + return VMManagerAddMachine::Page_NameAndLocation; + } else { + return VMManagerAddMachine::Page_WithExistingConfig; + } +} + +WithExistingConfigPage:: +WithExistingConfigPage(QWidget *parent) +{ + setTitle(tr("Use existing configuration")); + + const auto topLabel = new QLabel(tr("Paste the contents of the existing configuration file into the box below.")); + topLabel->setWordWrap(true); + + existingConfiguration = new QPlainTextEdit(); + connect(existingConfiguration, &QPlainTextEdit::textChanged, this, &WithExistingConfigPage::completeChanged); + registerField("existingConfiguration*", this, "configuration"); + + const auto layout = new QVBoxLayout(); + layout->addWidget(topLabel); + layout->addWidget(existingConfiguration); + const auto loadFileButton = new QPushButton(); + const auto loadFileLabel = new QLabel(tr("Load configuration from file")); + const auto hLayout = new QHBoxLayout(); + loadFileButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_FileIcon)); + loadFileButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + connect(loadFileButton, &QPushButton::clicked, this, &WithExistingConfigPage::chooseExistingConfigFile); + hLayout->addWidget(loadFileButton); + hLayout->addWidget(loadFileLabel); + layout->addLayout(hLayout); + setLayout(layout); +} + +void +WithExistingConfigPage::chooseExistingConfigFile() +{ + // TODO: FIXME: This is using the CLI arg and needs to instead use a proper variable + const auto startDirectory = QString(vmm_path); + const auto selectedConfigFile = QFileDialog::getOpenFileName(this, tr("Choose configuration file"), + startDirectory, + tr("86Box configuration files (86box.cfg)")); + // Empty value means the dialog was canceled + if (!selectedConfigFile.isEmpty()) { + QFile configFile(selectedConfigFile); + if (!configFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(this, tr("Configuration read failed"), tr("Unable to open the selected configuration file for reading: %1").arg(configFile.errorString())); + return; + } + const QString configFileContents = configFile.readAll(); + existingConfiguration->setPlainText(configFileContents); + configFile.close(); + emit completeChanged(); + } +} + +QString +WithExistingConfigPage::configuration() const +{ + return existingConfiguration->toPlainText(); +} +void +WithExistingConfigPage::setConfiguration(const QString &configuration) +{ + if (configuration != existingConfiguration->toPlainText()) { + existingConfiguration->setPlainText(configuration); + emit configurationChanged(configuration); + } +} + +int +WithExistingConfigPage::nextId() const +{ + return VMManagerAddMachine::Page_NameAndLocation; +} + +bool +WithExistingConfigPage::isComplete() const +{ + return !existingConfiguration->toPlainText().isEmpty(); +} + +NameAndLocationPage:: +NameAndLocationPage(QWidget *parent) +{ + setTitle(tr("System name and location")); + + dirValidate = QRegularExpression(R"(^[^\\/:*?"<>|\s]+$)"); + + const auto topLabel = new QLabel(tr("Enter the name of the system and choose the location")); + topLabel->setWordWrap(true); + + const auto chooseDirectoryButton = new QPushButton(); + chooseDirectoryButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirIcon)); + + const auto systemNameLabel = new QLabel(tr("System Name")); + systemName = new QLineEdit(); + // Special event filter to override enter key + systemName->installEventFilter(this); + registerField("systemName*", systemName); + systemNameValidation = new QLabel(); + + const auto systemLocationLabel = new QLabel(tr("System Location")); + systemLocation = new QLineEdit(); + // TODO: FIXME: This is using the CLI arg and needs to instead use a proper variable + systemLocation->setText(QDir::toNativeSeparators(vmm_path)); + registerField("systemLocation*", systemLocation); + systemLocationValidation = new QLabel(); + systemLocationValidation->setWordWrap(true); + + const auto layout = new QGridLayout(); + layout->addWidget(topLabel, 0, 0, 1, -1); + // Spacer row + layout->setRowMinimumHeight(1, 20); + layout->addWidget(systemNameLabel, 2, 0); + layout->addWidget(systemName, 2, 1); + // Validation text, appears only as necessary + layout->addWidget(systemNameValidation, 3, 0, 1, -1); + // Set height on validation because it may not always be present + layout->setRowMinimumHeight(3, 20); + + // Another spacer + layout->setRowMinimumHeight(4, 20); + layout->addWidget(systemLocationLabel, 5, 0); + layout->addWidget(systemLocation, 5, 1); + layout->addWidget(chooseDirectoryButton, 5, 2); + // Validation text + layout->addWidget(systemLocationValidation, 6, 0, 1, -1); + layout->setRowMinimumHeight(6, 20); + + setLayout(layout); + + + connect(chooseDirectoryButton, &QPushButton::clicked, this, &NameAndLocationPage::chooseDirectoryLocation); +} + +int +NameAndLocationPage::nextId() const +{ + return VMManagerAddMachine::Page_Conclusion; +} + +void +NameAndLocationPage::chooseDirectoryLocation() +{ + // TODO: FIXME: This is pulling in the CLI directory! Needs to be set properly elsewhere + const auto directory = QFileDialog::getExistingDirectory(this, "Choose directory", QDir(vmm_path).path()); + systemLocation->setText(QDir::toNativeSeparators(directory)); + emit completeChanged(); +} +bool +NameAndLocationPage::isComplete() const +{ + bool nameValid = false; + bool locationValid = false; + // return true if complete + if (systemName->text().isEmpty()) { + systemNameValidation->setText(tr("Please enter a system name")); + } else if (!systemName->text().contains(dirValidate)) { + systemNameValidation->setText(tr("System name cannot contain a space or certain characters")); + } else if (const QDir newDir = QDir::cleanPath(systemLocation->text() + "/" + systemName->text()); newDir.exists()) { + systemNameValidation->setText(tr("System name already exists")); + } else { + systemNameValidation->clear(); + nameValid = true; + } + + if (systemLocation->text().isEmpty()) { + systemLocationValidation->setText(tr("Please enter a directory for the system")); + } else if (const auto dir = QDir(systemLocation->text()); !dir.exists()) { + systemLocationValidation->setText(tr("Directory does not exist")); + } else { + systemLocationValidation->setText("A new directory for the system will be created in the selected directory above"); + locationValid = true; + } + + return nameValid && locationValid; +} +bool +NameAndLocationPage::eventFilter(QObject *watched, QEvent *event) +{ + // Override the enter key to hit the next wizard button + // if the validator (isComplete) is satisfied + if (event->type() == QEvent::KeyPress) { + const auto keyEvent = dynamic_cast<QKeyEvent*>(event); + if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { + // Only advance if the validator is satisfied (isComplete) + if(const auto wizard = qobject_cast<QWizard*>(this->wizard())) { + if (wizard->currentPage()->isComplete()) { + wizard->next(); + } + } + // Discard the key event + return true; + } + } + return QWizardPage::eventFilter(watched, event); +} + +ConclusionPage:: +ConclusionPage(QWidget *parent) +{ + setTitle(tr("Complete")); + + topLabel = new QLabel(tr("The wizard will now launch the configuration for the new system.")); + topLabel->setWordWrap(true); + + const auto systemNameLabel = new QLabel(tr("System name:")); + systemNameLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + systemName = new QLabel(); + const auto systemLocationLabel = new QLabel(tr("System location:")); + systemLocationLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + systemLocation = new QLabel(); + + const auto layout = new QGridLayout(); + layout->addWidget(topLabel, 0, 0, 1, -1); + layout->setRowMinimumHeight(1, 20); + layout->addWidget(systemNameLabel, 2, 0); + layout->addWidget(systemName, 2, 1); + layout->addWidget(systemLocationLabel, 3, 0); + layout->addWidget(systemLocation, 3, 1); + + setLayout(layout); +} + +// initializePage() runs after the page has been created with the constructor +void +ConclusionPage::initializePage() +{ + const auto finalPath = QDir::cleanPath(field("systemLocation").toString() + "/" + field("systemName").toString()); + const auto nativePath = QDir::toNativeSeparators(finalPath); + const auto systemNameDisplay = field("systemName").toString(); + + systemName->setText(systemNameDisplay); + systemLocation->setText(nativePath); +} diff --git a/src/qt/qt_vmmanager_addmachine.hpp b/src/qt/qt_vmmanager_addmachine.hpp new file mode 100644 index 000000000..c1355b471 --- /dev/null +++ b/src/qt/qt_vmmanager_addmachine.hpp @@ -0,0 +1,115 @@ +/* +* 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. +* +* Header for 86Box VM manager add machine wizard +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_ADDMACHINE_H +#define QT_VMMANAGER_ADDMACHINE_H + +#include <QLabel> +#include <QLineEdit> +#include <QPlainTextEdit> +#include <QRadioButton> +#include <QRegularExpression> +#include <QWizard> + +// Implementation note: There are several classes in this header: +// One for the main Wizard class and one for each page of the wizard + +class VMManagerAddMachine final : public QWizard { + Q_OBJECT + +public: + enum { + Page_Intro, + Page_Fresh, + Page_WithExistingConfig, + Page_NameAndLocation, + Page_Conclusion + }; + + explicit VMManagerAddMachine(QWidget *parent = nullptr); + +private slots: + void showHelp(); +}; + +class IntroPage : public QWizardPage { + Q_OBJECT + +public: + explicit IntroPage(QWidget *parent = nullptr); + [[nodiscard]] int nextId() const override; + +private: + QLabel *topLabel; + QRadioButton *newConfigRadioButton; + QRadioButton *existingConfigRadioButton; +}; + +class WithExistingConfigPage final : public QWizardPage { + Q_OBJECT + Q_PROPERTY(QString configuration READ configuration WRITE setConfiguration NOTIFY configurationChanged) + +public: + explicit WithExistingConfigPage(QWidget *parent = nullptr); + // These extra functions are required to register QPlainTextEdit fields + [[nodiscard]] QString configuration() const; + void setConfiguration(const QString &configuration); +signals: + void configurationChanged(const QString &configuration); +private: + QPlainTextEdit *existingConfiguration; +private slots: + void chooseExistingConfigFile(); +protected: + [[nodiscard]] int nextId() const override; + [[nodiscard]] bool isComplete() const override; + +}; + +class NameAndLocationPage final : public QWizardPage { + Q_OBJECT + +public: + explicit NameAndLocationPage(QWidget *parent = nullptr); + [[nodiscard]] int nextId() const override; +private: + QLineEdit *systemName; + QLineEdit *systemLocation; + QLabel *systemNameValidation; + QLabel *systemLocationValidation; + QRegularExpression dirValidate; +private slots: + void chooseDirectoryLocation(); +protected: + [[nodiscard]] bool isComplete() const override; + bool eventFilter(QObject *watched, QEvent *event) override; + +}; + +class ConclusionPage final : public QWizardPage { + Q_OBJECT +public: + explicit ConclusionPage(QWidget *parent = nullptr); +private: + QLabel *topLabel; + QLabel *systemName; + QLabel *systemLocation; +protected: + void initializePage() override; +}; + +#endif // QT_VMMANAGER_ADDMACHINE_H \ No newline at end of file diff --git a/src/qt/qt_vmmanager_clientsocket.cpp b/src/qt/qt_vmmanager_clientsocket.cpp new file mode 100644 index 000000000..1035a846c --- /dev/null +++ b/src/qt/qt_vmmanager_clientsocket.cpp @@ -0,0 +1,236 @@ +/* +* 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. +* +* 86Box VM manager client socket module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include "qt_vmmanager_clientsocket.hpp" +#include "qt_vmmanager_protocol.hpp" +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> + +extern "C" { +#include "86box/plat.h" +} + +VMManagerClientSocket::VMManagerClientSocket(QObject* obj) : server_connected(false) +{ + socket = new QLocalSocket; + +} + +void +VMManagerClientSocket::dataReady() +{ + // emit signal? + QDataStream stream(socket); + stream.setVersion(QDataStream::Qt_5_7); + QByteArray jsonData; + for (;;) { + // start a transaction + stream.startTransaction(); + // try to read the data + stream >> jsonData; + if (stream.commitTransaction()) { + // first try to successfully read some data + // need to also make sure it's valid json + QJsonParseError parse_error{}; + // try to create a document with the data received + const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parse_error); + if (parse_error.error == QJsonParseError::NoError) { + // the data received was valid json + if (jsonDoc.isObject()) { + // and is a valid json object + // parse the json + jsonReceived(jsonDoc.object()); + } + } + // If the received data isn't valid json, + // loop and try to read more if available + } else { + // read failed, socket is reverted to its previous state (before the transaction) + // Exit the loop and wait for more data to become available + break; + } + } + +} + +bool +VMManagerClientSocket::IPCConnect(const QString &server) +{ + server_name = server; + connect(socket, &QLocalSocket::connected, this, &VMManagerClientSocket::connected); + connect(socket, &QLocalSocket::disconnected, this, &VMManagerClientSocket::disconnected); + connect(socket, &QLocalSocket::errorOccurred, this, &VMManagerClientSocket::connectionError); + connect(socket, &QLocalSocket::readyRead, this, &VMManagerClientSocket::dataReady); + + socket->connectToServer(server_name); + + if(!socket->isValid()) { + qInfo("Could not connect to server: %s", qPrintable(socket->errorString())); + return false; + } + + qInfo("Connection Successful"); + return true; +} + +void +VMManagerClientSocket::connected() const +{ + // TODO: signal + qDebug("Connected to %s", qPrintable(server_name)); +} + +void +VMManagerClientSocket::disconnected() const +{ + // TODO: signal + qDebug("Disconnected from %s", qPrintable(server_name)); +} + +void +VMManagerClientSocket::sendMessage(const VMManagerProtocol::ClientMessage protocol_message) const +{ + sendMessageFull(protocol_message, QStringList(), QJsonObject()); +} + +void +VMManagerClientSocket::sendMessageWithList(const VMManagerProtocol::ClientMessage protocol_message, const QStringList &list) const +{ + sendMessageFull(protocol_message, list, QJsonObject()); +} + +void +VMManagerClientSocket::sendMessageWithObject(const VMManagerProtocol::ClientMessage protocol_message, const QJsonObject &json) const +{ + sendMessageFull(protocol_message, QStringList(), json); +} + +void +VMManagerClientSocket::sendMessageFull(const VMManagerProtocol::ClientMessage protocol_message, const QStringList &list, const QJsonObject &json) const +{ + QDataStream clientStream(socket); + clientStream.setVersion(QDataStream::Qt_5_7); + auto packet = new VMManagerProtocol(VMManagerProtocol::Sender::Client); + auto jsonMessage = packet->protocolClientMessage(protocol_message); + if (!list.isEmpty()) { + jsonMessage["list"] = QJsonArray::fromStringList(list); + } + // TODO: Add the logic for including objects + if(!json.isEmpty()) { + jsonMessage["params"] = json; + } + clientStream << QJsonDocument(jsonMessage).toJson(QJsonDocument::Compact); +} + +void +VMManagerClientSocket::jsonReceived(const QJsonObject &json) +{ + // The serialization portion has already validated the message as json. + // Ensure it has the required fields + if (!VMManagerProtocol::hasRequiredFields(json)) { + // TODO: Error handling of some sort, emit signals + qDebug("Invalid message received from client: required fields missing. Object:"); + qDebug() << json; + return; + } + // qDebug() << Q_FUNC_INFO << json; + + // Parsing happens here. When adding new types, make sure to first add them + // to VMManagerProtocol::ManagerMessage and then add it to the list here. + // If a signal needs to be emitted, add that as well and connect to slots + // as appropriate. + + switch (VMManagerProtocol::getManagerMessageType(json)) { + case VMManagerProtocol::ManagerMessage::Pause: + qDebug("Pause command received from manager"); + emit pause(); + break; + case VMManagerProtocol::ManagerMessage::ResetVM: + qDebug("Reset VM command received from manager"); + emit resetVM(); + break; + case VMManagerProtocol::ManagerMessage::ShowSettings: + qDebug("Show settings command received from manager"); + emit showsettings(); + break; + case VMManagerProtocol::ManagerMessage::CtrlAltDel: + qDebug("CtrlAltDel command received from manager"); + emit ctrlaltdel(); + break; + case VMManagerProtocol::ManagerMessage::RequestShutdown: + qDebug("RequestShutdown command received from manager"); + emit request_shutdown(); + break; + case VMManagerProtocol::ManagerMessage::ForceShutdown: + qDebug("ForceShutdown command received from manager"); + emit force_shutdown(); + break; + case VMManagerProtocol::ManagerMessage::RequestStatus: + qDebug("Status request command received from manager"); + break; + default: + qDebug("Unknown client message type received:"); + qDebug() << json; + break; + } +} + +void +VMManagerClientSocket::connectionError(const QLocalSocket::LocalSocketError socketError) +{ + qInfo("A connection error has occurred: "); + switch (socketError) { + case QLocalSocket::ServerNotFoundError: + qInfo("Server not found"); + break; + case QLocalSocket::ConnectionRefusedError: + qInfo("Connection refused"); + break; + case QLocalSocket::PeerClosedError: + qInfo("Peer closed"); + break; + default: + qInfo() << "QLocalSocket::LocalSocketError " << socketError; + break; + } +} + +bool +VMManagerClientSocket::eventFilter(QObject *obj, QEvent *event) +{ + if (socket->state() == QLocalSocket::ConnectedState) { + VMManagerProtocol::RunningState running_state; + if (event->type() == QEvent::WindowBlocked) { + running_state = dopause ? VMManagerProtocol::RunningState::PausedWaiting : VMManagerProtocol::RunningState::RunningWaiting; + clientRunningStateChanged(running_state); + } else if (event->type() == QEvent::WindowUnblocked) { + running_state = dopause ? VMManagerProtocol::RunningState::Paused : VMManagerProtocol::RunningState::Running; + clientRunningStateChanged(running_state); + } + } + return QObject::eventFilter(obj, event); +} + +void +VMManagerClientSocket::clientRunningStateChanged(VMManagerProtocol::RunningState state) const +{ + QJsonObject extra_object; + extra_object["status"] = static_cast<int>(state); + sendMessageWithObject(VMManagerProtocol::ClientMessage::RunningStateChanged, extra_object); + +} diff --git a/src/qt/qt_vmmanager_clientsocket.hpp b/src/qt/qt_vmmanager_clientsocket.hpp new file mode 100644 index 000000000..10a053347 --- /dev/null +++ b/src/qt/qt_vmmanager_clientsocket.hpp @@ -0,0 +1,71 @@ +/* +* 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. +* +* Header file for 86Box VM manager client socket module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_CLIENTSOCKET_HPP +#define QT_VMMANAGER_CLIENTSOCKET_HPP + +#include "qt_vmmanager_protocol.hpp" +#include <QEvent> +#include <QLocalSocket> +#include <QObject> +#include <QWidget> + +class VMManagerClientSocket final : public QObject { + Q_OBJECT + +public: + explicit VMManagerClientSocket(QObject* object = nullptr); + bool IPCConnect(const QString &server); + +signals: + void pause(); + void ctrlaltdel(); + void showsettings(); + void resetVM(); + void request_shutdown(); + void force_shutdown(); + void dialogstatus(bool open); + +public slots: + void clientRunningStateChanged(VMManagerProtocol::RunningState state) const; + +private: + QString server_name; + QLocalSocket *socket; + bool server_connected; + void connected() const; + void disconnected() const; + static void connectionError(QLocalSocket::LocalSocketError socketError); + + // Main convenience send function + void sendMessage(VMManagerProtocol::ClientMessage protocol_message) const; + // Send message with optional params array convenience function + void sendMessageWithList(VMManagerProtocol::ClientMessage protocol_message, const QStringList &list) const; + // Send message with optional json object convenience function + void sendMessageWithObject(VMManagerProtocol::ClientMessage protocol_message, const QJsonObject &json) const; + // Full send message function called by all convenience functions + void sendMessageFull(VMManagerProtocol::ClientMessage protocol_message, const QStringList &list, const QJsonObject &json) const; + void jsonReceived(const QJsonObject &json); + + void dataReady(); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +}; + +#endif // QT_VMMANAGER_CLIENTSOCKET_HPP diff --git a/src/qt/qt_vmmanager_config.cpp b/src/qt/qt_vmmanager_config.cpp new file mode 100644 index 000000000..08bf4e7c4 --- /dev/null +++ b/src/qt/qt_vmmanager_config.cpp @@ -0,0 +1,76 @@ +/* +* 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. +* +* 86Box VM manager configuration module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include <QDebug> +#include <QDir> +#include "qt_vmmanager_config.hpp" + +extern "C" { +#include <86box/plat.h> +} + +VMManagerConfig::VMManagerConfig(const ConfigType type, const QString& section) +{ + char BUF[256]; + plat_get_global_config_dir(BUF, 255); + const auto configDir = QString(BUF); + const auto configFile = QDir::cleanPath(configDir + "/" + "vmm.ini"); + + config_type = type; + + settings = new QSettings(configFile, QSettings::IniFormat, this); + settings->setFallbacksEnabled(false); + if(type == ConfigType::System && !section.isEmpty()) { + settings->beginGroup(section); + } +} + +VMManagerConfig::~VMManagerConfig() { + settings->endGroup(); +} + +QString +VMManagerConfig::getStringValue(const QString& key) const +{ + const auto value = settings->value(key); + // An invalid QVariant with toString will give a default QString value which is blank. + // Therefore any variables that do not exist will return blank strings + return value.toString(); +} + +void +VMManagerConfig::setStringValue(const QString &key, const QString &value) const +{ + if (value.isEmpty()) { + remove(key); + return; + } + settings->setValue(key, value); +} + +void +VMManagerConfig::remove(const QString &key) const +{ + settings->remove(key); +} + +void +VMManagerConfig::sync() const +{ + settings->sync(); +} + diff --git a/src/qt/qt_vmmanager_config.hpp b/src/qt/qt_vmmanager_config.hpp new file mode 100644 index 000000000..bc63aaa03 --- /dev/null +++ b/src/qt/qt_vmmanager_config.hpp @@ -0,0 +1,46 @@ +/* +* 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. +* +* Header for the 86Box VM manager configuration module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_CONFIG_H +#define QT_VMMANAGER_CONFIG_H + +#include <QSettings> + +class VMManagerConfig : QObject { + Q_OBJECT + +public: + enum class ConfigType { + General, + System, + }; + Q_ENUM(ConfigType); + + explicit VMManagerConfig(ConfigType type, const QString& section = {}); + ~VMManagerConfig() override; + [[nodiscard]] QString getStringValue(const QString& key) const; + void setStringValue(const QString& key, const QString& value) const; + void remove(const QString &key) const; + + void sync() const; + + QSettings *settings; + ConfigType config_type; + QString system_name; +}; + +#endif // QT_VMMANAGER_CONFIG_H \ No newline at end of file diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp new file mode 100644 index 000000000..f72102c25 --- /dev/null +++ b/src/qt/qt_vmmanager_details.cpp @@ -0,0 +1,345 @@ +/* +* 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. +* +* 86Box VM manager system details module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include <QApplication> +#include <QDebug> +#include <QStyle> + +#include "qt_vmmanager_details.hpp" +#include "ui_qt_vmmanager_details.h" + +VMManagerDetails::VMManagerDetails(QWidget *parent) : + QWidget(parent), ui(new Ui::VMManagerDetails) { + ui->setupUi(this); + + const auto leftColumnLayout = qobject_cast<QVBoxLayout*>(ui->leftColumn->layout()); + + // Each section here gets its own VMManagerDetailSection, named in the constructor. + // When a system is selected in the list view it is updated through this object + // See updateData() for the implementation + + systemSection = new VMManagerDetailSection(tr("System", "Header for System section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(systemSection); + // These horizontal lines are used for the alternate layout which may possibly + // be a preference one day. + // ui->leftColumn->layout()->addWidget(createHorizontalLine()); + + videoSection = new VMManagerDetailSection(tr("Display", "Header for Display section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(videoSection); + // ui->leftColumn->layout()->addWidget(createHorizontalLine()); + + storageSection = new VMManagerDetailSection(tr("Storage", "Header for Storage section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(storageSection); + // ui->leftColumn->layout()->addWidget(createHorizontalLine()); + + audioSection = new VMManagerDetailSection(tr("Audio", "Header for Audio section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(audioSection); + // ui->leftColumn->layout()->addWidget(createHorizontalLine()); + + networkSection = new VMManagerDetailSection(tr("Network", "Header for Network section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(networkSection); + // ui->leftColumn->layout()->addWidget(createHorizontalLine()); + + inputSection = new VMManagerDetailSection(tr("Input Devices", "Header for Input section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(inputSection); + // ui->leftColumn->layout()->addWidget(createHorizontalLine()); + + portsSection = new VMManagerDetailSection(tr("Ports", "Header for Input section in VM Manager Details")); + ui->leftColumn->layout()->addWidget(portsSection); + + // This is like adding a spacer + leftColumnLayout->addStretch(); + + // Event filter for the notes to save when it loses focus + ui->notesTextEdit->installEventFilter(this); + + // Default screenshot label and thumbnail (image inside the label) sizes + screenshotThumbnailSize = QSize(240, 160); + + // Set the icons for the screenshot navigation buttons + ui->screenshotNext->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekForward)); + ui->screenshotPrevious->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekBackward)); + ui->screenshotNextTB->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekForward)); + ui->screenshotPreviousTB->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekBackward)); + // Disabled by default + ui->screenshotNext->setEnabled(false); + ui->screenshotPrevious->setEnabled(false); + ui->screenshotNextTB->setEnabled(false); + ui->screenshotPreviousTB->setEnabled(false); + // Connect their signals + connect(ui->screenshotNext, &QPushButton::clicked, this, &VMManagerDetails::nextScreenshot); + connect(ui->screenshotNextTB, &QToolButton::clicked, this, &VMManagerDetails::nextScreenshot); + connect(ui->screenshotPreviousTB, &QToolButton::clicked, this, &VMManagerDetails::previousScreenshot); + connect(ui->screenshotPrevious, &QPushButton::clicked, this, &VMManagerDetails::previousScreenshot); + // These push buttons can be taken out if the tool buttons stay + ui->screenshotNext->setVisible(false); + ui->screenshotPrevious->setVisible(false); + QString toolButtonStyleSheet; + // Simple method to try and determine if light mode is enabled + const bool lightMode = QApplication::palette().window().color().value() > QApplication::palette().windowText().color().value(); + if (lightMode) { + toolButtonStyleSheet = "QToolButton {background: transparent; border: none; padding: 5px} QToolButton:hover {background: palette(midlight)} QToolButton:pressed {background: palette(mid)}"; + } else { + toolButtonStyleSheet = "QToolButton {background: transparent; border: none; padding: 5px} QToolButton:hover {background: palette(dark)} QToolButton:pressed {background: palette(mid)}"; + } + ui->ssNavTBHolder->setStyleSheet(toolButtonStyleSheet); + + // Experimenting + startPauseButton = new QToolButton(); + startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + startPauseButton->setAutoRaise(true); + ui->toolButtonHolder->setStyleSheet(toolButtonStyleSheet); + resetButton = new QToolButton(); + resetButton->setIcon(QIcon(":/menuicons/qt/icons/hard_reset.ico")); + stopButton = new QToolButton(); + stopButton->setIcon(QIcon(":/menuicons/qt/icons/acpi_shutdown.ico")); + configureButton = new QToolButton(); + configureButton->setIcon(QIcon(":/menuicons/qt/icons/settings.ico")); + + ui->toolButtonHolder->layout()->addWidget(configureButton); + ui->toolButtonHolder->layout()->addWidget(resetButton); + ui->toolButtonHolder->layout()->addWidget(stopButton); + ui->toolButtonHolder->layout()->addWidget(startPauseButton); + + sysconfig = new VMManagerSystem(); +} + +VMManagerDetails::~VMManagerDetails() { + delete ui; +} + +void +VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { + + // Set the scrollarea background but also set the scroll bar to none. Otherwise it will also + // set the scrollbar background to the same. + ui->scrollArea->setStyleSheet("QWidget {background-color: palette(light)} QScrollBar{ background-color: none }"); + ui->systemLabel->setStyleSheet("background-color: palette(midlight);"); + // Margins are a little different on macos +#ifdef Q_OS_MACOS + ui->systemLabel->setMargin(15); +#else + ui->systemLabel->setMargin(10); +#endif + + // disconnect old signals before assigning the passed systemconfig object + disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); + disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); + disconnect(resetButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::restartButtonPressed); + disconnect(stopButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::shutdownForceButtonPressed); + disconnect(configureButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::launchSettings); + + sysconfig = passed_sysconfig; + connect(resetButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::restartButtonPressed); + connect(stopButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::shutdownForceButtonPressed); + connect(configureButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::launchSettings); + + bool running = sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::Running || + sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::RunningWaiting; + if(running) { + startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/pause.ico")); + connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); + } else { + startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); + } + + // Each detail section here has its own VMManagerDetailSection. + // When a system is selected in the list view it is updated here, through this object: + // * First you clear it with VMManagerDetailSection::clear() + // * Then you add each line with VMManagerDetailSection::addSection() + + // System + systemSection->clear(); + systemSection->addSection("Machine", passed_sysconfig->getDisplayValue(Display::Name::Machine)); + systemSection->addSection("CPU", passed_sysconfig->getDisplayValue(Display::Name::CPU)); + systemSection->addSection("Memory", passed_sysconfig->getDisplayValue(Display::Name::Memory)); + + // Video + videoSection->clear(); + videoSection->addSection("Video", passed_sysconfig->getDisplayValue(Display::Name::Video)); + if(!passed_sysconfig->getDisplayValue(Display::Name::Voodoo).isEmpty()) { + videoSection->addSection("Voodoo", passed_sysconfig->getDisplayValue(Display::Name::Voodoo)); + } + + // Disks + storageSection->clear(); + storageSection->addSection("Disks", passed_sysconfig->getDisplayValue(Display::Name::Disks)); + storageSection->addSection("Floppy", passed_sysconfig->getDisplayValue(Display::Name::Floppy)); + storageSection->addSection("CD-ROM", passed_sysconfig->getDisplayValue(Display::Name::CD)); + storageSection->addSection("SCSI", passed_sysconfig->getDisplayValue(Display::Name::SCSIController)); + + // Audio + audioSection->clear(); + audioSection->addSection("Audio", passed_sysconfig->getDisplayValue(Display::Name::Audio)); + audioSection->addSection("MIDI Out", passed_sysconfig->getDisplayValue(Display::Name::MidiOut)); + + // Network + networkSection->clear(); + networkSection->addSection("NIC", passed_sysconfig->getDisplayValue(Display::Name::NIC)); + + // Input + inputSection->clear(); + inputSection->addSection(tr("Mouse"), passed_sysconfig->getDisplayValue(Display::Name::Mouse)); + inputSection->addSection(tr("Joystick"), passed_sysconfig->getDisplayValue(Display::Name::Joystick)); + + // Ports + portsSection->clear(); + portsSection->addSection(tr("Serial Ports"), passed_sysconfig->getDisplayValue(Display::Name::Serial)); + portsSection->addSection(tr("Parallel Ports"), passed_sysconfig->getDisplayValue(Display::Name::Parallel)); + + // Disable screenshot navigation buttons by default + ui->screenshotNext->setEnabled(false); + ui->screenshotPrevious->setEnabled(false); + ui->screenshotNextTB->setEnabled(false); + ui->screenshotPreviousTB->setEnabled(false); + + // Different actions are taken depending on the existence and number of screenshots + screenshots = passed_sysconfig->getScreenshots(); + if (!screenshots.empty()) { + ui->screenshot->setFrameStyle(QFrame::NoFrame); + ui->screenshot->setEnabled(true); + if(screenshots.size() > 1) { + ui->screenshotNext->setEnabled(true); + ui->screenshotPrevious->setEnabled(true); + ui->screenshotNextTB->setEnabled(true); + ui->screenshotPreviousTB->setEnabled(true); + } + if(QFileInfo::exists(screenshots.last().filePath())) { + screenshotIndex = screenshots.size() - 1; + const QPixmap pic(screenshots.at(screenshotIndex).filePath()); + ui->screenshot->setPixmap(pic.scaled(240, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + } + } else { + ui->screenshotNext->setEnabled(false); + ui->screenshotPrevious->setEnabled(false); + ui->screenshotNextTB->setEnabled(false); + ui->screenshotPreviousTB->setEnabled(false); + ui->screenshot->setPixmap(QString()); + ui->screenshot->setFixedSize(240, 160); + ui->screenshot->setFrameStyle(QFrame::Box | QFrame::Sunken); + ui->screenshot->setText(tr("No screenshot")); + ui->screenshot->setEnabled(false); + ui->screenshot->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + } + + ui->systemLabel->setText(passed_sysconfig->displayName); + ui->statusLabel->setText(sysconfig->process->processId() == 0 ? + tr("Not running") : + QString("%1: PID %2").arg(tr("Running"), QString::number(sysconfig->process->processId()))); + ui->notesTextEdit->setPlainText(passed_sysconfig->notes); + + disconnect(sysconfig->process, &QProcess::stateChanged, this, &VMManagerDetails::updateProcessStatus); + connect(sysconfig->process, &QProcess::stateChanged, this, &VMManagerDetails::updateProcessStatus); + + disconnect(sysconfig, &VMManagerSystem::windowStatusChanged, this, &VMManagerDetails::updateWindowStatus); + connect(sysconfig, &VMManagerSystem::windowStatusChanged, this, &VMManagerDetails::updateWindowStatus); + + disconnect(sysconfig, &VMManagerSystem::clientProcessStatusChanged, this, &VMManagerDetails::updateProcessStatus); + connect(sysconfig, &VMManagerSystem::clientProcessStatusChanged, this, &VMManagerDetails::updateProcessStatus); + + updateProcessStatus(); +} + +void +VMManagerDetails::updateProcessStatus() { + const bool running = sysconfig->process->state() == QProcess::ProcessState::Running; + QString status_text = running ? + QString("%1: PID %2").arg(tr("Running"), QString::number(sysconfig->process->processId())) : + tr("Not running"); + status_text.append(sysconfig->window_obscured ? QString(" (%1)").arg(tr("waiting")) : ""); + ui->statusLabel->setText(status_text); + resetButton->setEnabled(running); + stopButton->setEnabled(running); + if(running) { + if(sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::Running) { + startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/pause.ico")); + } else { + startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + } + + disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); + disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); + connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); + } else { + startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); + disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); + connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); + } +} + +void +VMManagerDetails::updateWindowStatus() +{ + qInfo("Window status changed: %i", sysconfig->window_obscured); + updateProcessStatus(); +} + +QWidget * +VMManagerDetails::createHorizontalLine(const int leftSpacing, const int rightSpacing) +{ + const auto container = new QWidget; + const auto hLayout = new QHBoxLayout(container); + + hLayout->addSpacing(leftSpacing); + + const auto line = new QFrame(); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + hLayout->addWidget(line); + hLayout->addSpacing(rightSpacing); + hLayout->setContentsMargins(0, 5, 0, 5); + + return container; +} + +void +VMManagerDetails::saveNotes() const +{ + sysconfig->setNotes(ui->notesTextEdit->toPlainText()); +} + +void +VMManagerDetails::nextScreenshot() +{ + screenshotIndex = (screenshotIndex + 1) % screenshots.size(); + const QPixmap pic(screenshots.at(screenshotIndex).filePath()); + ui->screenshot->setPixmap(pic.scaled(240, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation)); +} + +void +VMManagerDetails::previousScreenshot() +{ + screenshotIndex = screenshotIndex == 0 ? screenshots.size() - 1 : screenshotIndex - 1; + const QPixmap pic(screenshots.at(screenshotIndex).filePath()); + ui->screenshot->setPixmap(pic.scaled(240, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation)); +} + +bool +VMManagerDetails::eventFilter(QObject *watched, QEvent *event) +{ + if (watched->isWidgetType() && event->type() == QEvent::FocusOut) { + // Make sure it's the textedit + if (const auto *textEdit = qobject_cast<QPlainTextEdit*>(watched); textEdit) { + saveNotes(); + } + } + return QWidget::eventFilter(watched, event); +} + diff --git a/src/qt/qt_vmmanager_details.hpp b/src/qt/qt_vmmanager_details.hpp new file mode 100644 index 000000000..c6db78127 --- /dev/null +++ b/src/qt/qt_vmmanager_details.hpp @@ -0,0 +1,89 @@ +/* +* 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. +* +* Header for 86Box VM manager system details module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_DETAILS_H +#define QT_VMMANAGER_DETAILS_H + +#include <QWidget> +#include "qt_vmmanager_system.hpp" +// #include "qt_vmmanager_details_section.hpp" +#include "qt_vmmanager_detailsection.hpp" + + +QT_BEGIN_NAMESPACE +//namespace Ui { class VMManagerDetails; class CollapseButton;} +namespace Ui { class VMManagerDetails;} +QT_END_NAMESPACE + +class VMManagerDetails : public QWidget { + Q_OBJECT + +public: + explicit VMManagerDetails(QWidget *parent = nullptr); + + ~VMManagerDetails() override; + + void updateData(VMManagerSystem *passed_sysconfig); + + void updateProcessStatus(); + + void updateWindowStatus(); +// CollapseButton *systemCollapseButton; + +private: + Ui::VMManagerDetails *ui; + VMManagerSystem *sysconfig; + + VMManagerDetailSection *systemSection; + VMManagerDetailSection *videoSection; + VMManagerDetailSection *storageSection; + VMManagerDetailSection *audioSection; + VMManagerDetailSection *networkSection; + VMManagerDetailSection *inputSection; + VMManagerDetailSection *portsSection; + + QFileInfoList screenshots; + int screenshotIndex = 0; + QSize screenshotLabelSize; + QSize screenshotThumbnailSize; + + QToolButton *startPauseButton; + QToolButton *resetButton; + QToolButton *stopButton; + QToolButton *configureButton; + + static QWidget* createHorizontalLine(int leftSpacing = 25, int rightSpacing = 25); + // QVBoxLayout *detailsLayout; +private slots: + void saveNotes() const; + void nextScreenshot(); + void previousScreenshot(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +// CollapseButton *systemCollapseButton; +// QFrame *systemFrame; +// CollapseButton *displayCollapseButton; +// QFrame *displayFrame; +// CollapseButton *storageCollapseButton; +// QFrame *storageFrame; +}; + + + +#endif //QT_VMMANAGER_DETAILS_H diff --git a/src/qt/qt_vmmanager_details.ui b/src/qt/qt_vmmanager_details.ui new file mode 100644 index 000000000..9b4fbbe8b --- /dev/null +++ b/src/qt/qt_vmmanager_details.ui @@ -0,0 +1,293 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VMManagerDetails</class> + <widget class="QWidget" name="VMManagerDetails"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>497</width> + <height>444</height> + </rect> + </property> + <property name="windowTitle"> + <string>VMManagerDetails</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="systemLabel"> + <property name="font"> + <font> + <pointsize>18</pointsize> + </font> + </property> + <property name="text"> + <string>No Machines Found!</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="LeftRight" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="leftColumn"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>139</width> + <height>388</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>12</number> + </property> + <property name="topMargin"> + <number>12</number> + </property> + <property name="rightMargin"> + <number>12</number> + </property> + <property name="bottomMargin"> + <number>12</number> + </property> + </layout> + </widget> + </widget> + </item> + <item alignment="Qt::AlignHCenter"> + <widget class="QWidget" name="rightColumn" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <item alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="screenshot"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>240</width> + <height>160</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>240</width> + <height>160</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="screenshotNavButtons" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="screenshotPrevious"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="ssNavTBHolder" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QToolButton" name="screenshotPreviousTB"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="screenshotNextTB"> + <property name="text"> + <string>...</string> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QPushButton" name="screenshotNext"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="notesTextEdit"> + <property name="placeholderText"> + <string>Type some notes here</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QWidget" name="toolButtonHolder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="statusLabel"> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/qt/qt_vmmanager_detailsection.cpp b/src/qt/qt_vmmanager_detailsection.cpp new file mode 100644 index 000000000..95a600d8f --- /dev/null +++ b/src/qt/qt_vmmanager_detailsection.cpp @@ -0,0 +1,294 @@ +/* +* 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. +* +* 86Box VM manager system details section module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include "qt_vmmanager_detailsection.hpp" +#include "ui_qt_vmmanager_detailsection.h" + +#include <QPushButton> + +const QString VMManagerDetailSection::sectionSeparator = ";"; + +VMManagerDetailSection:: +VMManagerDetailSection(const QString &sectionName) + : mainLayout(new QVBoxLayout()) + , buttonLayout(new QHBoxLayout()) + , frame(new QFrame()) + , ui(new Ui::DetailSection) +{ + ui->setupUi(this); + + frameGridLayout = new QGridLayout(); + // Create the collapse button, set the name and add it to the layout + collapseButton = new CollapseButton(); + setSectionName(sectionName); + ui->collapseButtonHolder->setContentsMargins(getMargins(MarginSection::ToolButton)); + + // Simple method to try and determine if light mode is enabled on the host + const bool lightMode = QApplication::palette().window().color().value() > QApplication::palette().windowText().color().value(); + // Alternate layout + if ( lightMode) { + ui->collapseButtonHolder->setStyleSheet("background-color: palette(midlight);"); + } else { + ui->collapseButtonHolder->setStyleSheet("background-color: palette(mid);"); + } + const auto sectionLabel = new QLabel(sectionName); + sectionLabel->setStyleSheet(sectionLabel->styleSheet().append("font-weight: bold;")); + ui->collapseButtonHolder->setContentsMargins(QMargins(3, 2, 0, 2)); + ui->collapseButtonHolder->layout()->addWidget(sectionLabel); + + // ui->collapseButtonHolder->layout()->addWidget(collapseButton); + collapseButton->setContent(ui->detailFrame); + // Horizontal line added after the section name / button + // const auto hLine = new QFrame(); + // hLine->setFrameShape(QFrame::HLine); + // hLine->setFrameShadow(QFrame::Sunken); + // hLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + // ui->collapseButtonHolder->layout()->addWidget(hLine); + const auto hSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + ui->collapseButtonHolder->layout()->addItem(hSpacer); + // collapseButton->setContent(frame); + // ui->sectionName->setVisible(false); +} + +VMManagerDetailSection:: +VMManagerDetailSection(const QVariant &varSectionName) : ui(new Ui::DetailSection) +{ + const auto sectionName = varSectionName.toString(); + + // Initialize even though they will get wiped out + // (to keep clang-tidy happy) + frameGridLayout = new QGridLayout(); + const auto outerFrame = new QFrame(); + // for the CSS + outerFrame->setObjectName("outer_frame"); + outerFrame->setContentsMargins(QMargins(0, 0, 0, 0)); + const auto innerFrameLayout = new QVBoxLayout(); + + outerFrame->setLayout(innerFrameLayout); + auto *outerFrameLayout = new QVBoxLayout(); + outerFrameLayout->addWidget(outerFrame); + outerFrameLayout->setContentsMargins(QMargins(0, 0, 0, 0)); + + const auto buttonWidget = new QWidget(this); + + mainLayout = new QVBoxLayout(); + buttonLayout = new QHBoxLayout(); + buttonWidget->setLayout(buttonLayout); + + collapseButton = new CollapseButton(); + setSectionName(sectionName); + buttonLayout->setContentsMargins(getMargins(MarginSection::ToolButton)); + buttonLayout->addWidget(collapseButton); + + // buttonLayout->addStretch(); + auto *hLine = new QFrame(); + hLine->setFrameShape(QFrame::HLine); + hLine->setFrameShadow(QFrame::Sunken); + hLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + buttonLayout->addWidget(hLine); + + mainLayout->addLayout(buttonLayout); + + frame = new QFrame(); + frame->setFrameShape(QFrame::Box); + frame->setFrameStyle(QFrame::NoFrame); + collapseButton->setContent(frame); + + mainLayout->addWidget(frame); + innerFrameLayout->addWidget(buttonWidget); + innerFrameLayout->addWidget(frame); + setLayout(outerFrameLayout); +} + +VMManagerDetailSection::~VMManagerDetailSection() += default; + +void +VMManagerDetailSection::setSectionName(const QString &name) +{ + sectionName = name; + collapseButton->setButtonText(" " + sectionName); + // Bold the section headers + collapseButton->setStyleSheet(collapseButton->styleSheet().append("font-weight: bold;")); +} + +void +VMManagerDetailSection::addSection(const QString &name, const QString &value, Display::Name displayField) +{ + const auto new_section = DetailSection { name, value}; + sections.push_back(new_section); + setSections(); +} + +void +VMManagerDetailSection::setupMainLayout() +{ + // clang-tidy says I don't need to check before deleting + delete mainLayout; + mainLayout = new QVBoxLayout; +} +void +VMManagerDetailSection::clearContentsSetupGrid() +{ + // Clear everything out + if(frameGridLayout) { + while(frameGridLayout->count()) { + QLayoutItem * cur_item = frameGridLayout->takeAt(0); + if(cur_item->widget()) + delete cur_item->widget(); + delete cur_item; + } + } + + delete frameGridLayout; + frameGridLayout = new QGridLayout(); + qint32 *left = nullptr, *top = nullptr, *right = nullptr, *bottom = nullptr; + frameGridLayout->getContentsMargins(left, top, right, bottom); + frameGridLayout->setContentsMargins(getMargins(MarginSection::DisplayGrid)); + ui->detailFrame->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + ui->detailFrame->setLayout(frameGridLayout); +} +void +VMManagerDetailSection::setSections() +{ + clearContentsSetupGrid(); + int row = 0; + + + for ( const auto& section : sections) { + // if the string contains the separator (defined elsewhere) then split and + // add each entry on a new line. Otherwise, just add the one. + QStringList sectionsToAdd; + if(section.value.contains(sectionSeparator)) { + sectionsToAdd = section.value.split(sectionSeparator); + } else { + sectionsToAdd.push_back(section.value); + } + bool keyAdded = false; + for(const auto&line : sectionsToAdd) { + if(line.isEmpty()) { + // Don't bother adding entries if the values are blank + continue; + } + const auto labelKey = new QLabel(); + labelKey->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + const auto labelValue = new QLabel(); + labelKey->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + labelValue->setTextInteractionFlags(labelValue->textInteractionFlags() | Qt::TextSelectableByMouse); + labelKey->setTextInteractionFlags(labelValue->textInteractionFlags() | Qt::TextSelectableByMouse); + + // Reduce the text size for the label + // First, get the existing font + auto smaller_font = labelValue->font(); + // Get a smaller size + // Not sure if I like the smaller size, back to regular for now + // auto smaller_size = 0.85 * smaller_font.pointSize(); + const auto smaller_size = 1 * smaller_font.pointSize(); + // Set the font to the smaller size + smaller_font.setPointSizeF(smaller_size); + // Assign that new, smaller font to the label + labelKey->setFont(smaller_font); + labelValue->setFont(smaller_font); + + labelKey->setText(section.name + ":"); + labelValue->setText(line); + if(!keyAdded) { + frameGridLayout->addWidget(labelKey, row, 0, Qt::AlignLeft); + keyAdded = true; + } + frameGridLayout->addWidget(labelValue, row, 1, Qt::AlignLeft); + const auto hSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + frameGridLayout->addItem(hSpacer, row, 2); + row++; + } + } + collapseButton->setContent(ui->detailFrame); +} +void +VMManagerDetailSection::clear() +{ + sections.clear(); +} + +// QT for Linux and Windows doesn't have the same default margins as QT on MacOS. +// For consistency in appearance we'll have to return the margins on a per-OS basis +QMargins +VMManagerDetailSection::getMargins(const MarginSection section) +{ + switch (section) { + case MarginSection::ToolButton: +#if defined(Q_OS_WINDOWS) or defined(Q_OS_LINUX) + return {10, 0, 5, 0}; +#else + return {0, 0, 5, 0}; +#endif + case MarginSection::DisplayGrid: +#if defined(Q_OS_WINDOWS) or defined(Q_OS_LINUX) + return {10, 0, 0, 10}; +#else + return {0, 0, 0, 10}; +#endif + default: + return {}; + } +} + +// CollapseButton Class + +CollapseButton::CollapseButton(QWidget *parent) : QToolButton(parent), content_(nullptr) { + setCheckable(true); + setStyleSheet("background:none; border:none;"); + setIconSize(QSize(8, 8)); + setFont(QApplication::font()); + setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + connect(this, &QToolButton::toggled, [=](const bool checked) { + setArrowType(checked ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow); + content_ != nullptr && checked ? showContent() : hideContent(); + }); + setChecked(true); +} + +void CollapseButton::setButtonText(const QString &text) { + setText(" " + text); +} + +void CollapseButton::setContent(QWidget *content) { + assert(content != nullptr); + content_ = content; + const auto animation_ = new QPropertyAnimation(content_, "maximumHeight"); // QObject with auto delete + animation_->setStartValue(0); + animation_->setEasingCurve(QEasingCurve::InOutQuad); + animation_->setDuration(300); + animation_->setEndValue(content->geometry().height() + 50); + // qDebug() << "section" << text() << "has a height of" << content->geometry().height(); + animator_.clear(); + animator_.addAnimation(animation_); + if (!isChecked()) { + content->setMaximumHeight(0); + } +} + +void CollapseButton::hideContent() { + animator_.setDirection(QAbstractAnimation::Backward); + animator_.start(); +} + +void CollapseButton::showContent() { + animator_.setDirection(QAbstractAnimation::Forward); + animator_.start(); +} + diff --git a/src/qt/qt_vmmanager_detailsection.hpp b/src/qt/qt_vmmanager_detailsection.hpp new file mode 100644 index 000000000..2eb63685a --- /dev/null +++ b/src/qt/qt_vmmanager_detailsection.hpp @@ -0,0 +1,101 @@ +/* +* 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. +* +* 86Box VM manager system details section module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#ifndef QT_VMMANAGER_DETAILSECTION_H +#define QT_VMMANAGER_DETAILSECTION_H + +#include <QLabel> +#include <QToolButton> +#include <QGridLayout> +#include <QPropertyAnimation> +#include <QParallelAnimationGroup> +#include <QApplication> +#include "qt_vmmanager_system.hpp" + +QT_BEGIN_NAMESPACE +namespace Ui { class DetailSection; } +QT_END_NAMESPACE + +class CollapseButton final : public QToolButton { + Q_OBJECT + +public: + explicit CollapseButton(QWidget *parent = nullptr); + + void setButtonText(const QString &text); + + void setContent(QWidget *content); + + void hideContent(); + + void showContent(); + +private: + QWidget *content_; + QString text_; + QParallelAnimationGroup animator_; +}; + +class VMManagerDetailSection final : public QWidget { + Q_OBJECT + +public: + explicit VMManagerDetailSection(const QString &sectionName); + explicit VMManagerDetailSection(const QVariant &varSectionName); + // explicit VMManagerDetailSection(); + + ~VMManagerDetailSection() override; + + void addSection(const QString &name, const QString &value, Display::Name displayField = Display::Name::Unknown); + void clear(); + + CollapseButton *collapseButton; +// QGridLayout *buttonGridLayout; + QGridLayout *frameGridLayout; + QVBoxLayout *mainLayout; + QHBoxLayout *buttonLayout; + QFrame *frame; + + static const QString sectionSeparator; + + +private: + enum class MarginSection { + ToolButton, + DisplayGrid, + }; + + void setSectionName(const QString &name); + void setupMainLayout(); + void clearContentsSetupGrid(); + void setSections(); + + static QMargins getMargins(MarginSection section); + + QString sectionName; + + struct DetailSection { + QString name; + QString value; + }; + + QVector<DetailSection> sections; + Ui::DetailSection *ui; + +}; + +#endif // QT_VMMANAGER_DETAILSECTION_H diff --git a/src/qt/qt_vmmanager_detailsection.ui b/src/qt/qt_vmmanager_detailsection.ui new file mode 100644 index 000000000..18e89ee65 --- /dev/null +++ b/src/qt/qt_vmmanager_detailsection.ui @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DetailSection</class> + <widget class="QWidget" name="DetailSection"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>348</width> + <height>151</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="outerFrame"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="collapseButtonHolder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="detailFrame"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/qt/qt_vmmanager_listviewdelegate.cpp b/src/qt/qt_vmmanager_listviewdelegate.cpp new file mode 100644 index 000000000..167c805ee --- /dev/null +++ b/src/qt/qt_vmmanager_listviewdelegate.cpp @@ -0,0 +1,241 @@ +/* +* 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. +* +* 86Box VM manager list view delegate module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + + +#include <QApplication> + +#include "qt_vmmanager_listviewdelegate.hpp" +#include "qt_vmmanager_model.hpp" + + +// Thanks to scopchanov https://github.com/scopchanov/SO-MessageLog +// from https://stackoverflow.com/questions/53105343/is-it-possible-to-add-a-custom-widget-into-a-qlistview + + +VMManagerListViewDelegate::VMManagerListViewDelegate(QObject *parent) + : QStyledItemDelegate(parent), + m_ptr(new VMManagerListViewDelegateStyle) +{ +} + +VMManagerListViewDelegate::~VMManagerListViewDelegate() += default; + +void VMManagerListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const { + QStyleOptionViewItem opt(option); + initStyleOption(&opt, index); + const QPalette &palette(opt.palette); + // opt.rect = opt.rect.adjusted(0, 0, 0, 20); + const QRect &rect(opt.rect); + const QRect &contentRect(rect.adjusted(m_ptr->margins.left(), + m_ptr->margins.top(), + -m_ptr->margins.right(), + -m_ptr->margins.bottom())); + + // The status icon represents the current state of the vm. Initially set to a default state. + QIcon status_icon = QApplication::style()->standardIcon(QStyle::SP_MediaStop); + auto process_variant = index.data(VMManagerModel::Roles::ProcessStatus); + auto process_status = process_variant.value<VMManagerSystem::ProcessStatus>(); + // The main icon, configurable. Falls back to default if it cannot be loaded. + auto customIcom = index.data(VMManagerModel::Roles::Icon).toString(); + opt.icon = QIcon(":/settings/qt/icons/86Box-gray.ico"); + if(!customIcom.isEmpty()) { + if (const auto customPixmap = QPixmap(customIcom); !customPixmap.isNull()) { + opt.icon = customPixmap; + } + } + // opt.icon = QIcon(":/settings/qt/icons/86Box-gray.ico"); + + // Set the status icon based on the process status + switch(process_status) { + case VMManagerSystem::ProcessStatus::Running: + status_icon = QIcon(":/menuicons/qt/icons/run.ico"); + break; + case VMManagerSystem::ProcessStatus::Stopped: + status_icon = QIcon(":/menuicons/qt/icons/acpi_shutdown.ico"); + break; + case VMManagerSystem::ProcessStatus::PausedWaiting: + case VMManagerSystem::ProcessStatus::RunningWaiting: + case VMManagerSystem::ProcessStatus::Paused: + status_icon = QIcon(":/menuicons/qt/icons/pause.ico"); + break; + default: + status_icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion); + } + + + // Used to determine if the horizontal separator should be drawn + const bool lastIndex = (index.model()->rowCount() - 1) == index.row(); + const bool hasIcon = !opt.icon.isNull(); + const int bottomEdge = rect.bottom(); + QFont f(opt.font); + + f.setPointSizeF(m_ptr->statusFontPointSize(opt.font)); + + painter->save(); + painter->setClipping(true); + painter->setClipRect(rect); + painter->setFont(opt.font); + + // Draw the background + if (opt.state & QStyle::State_Selected) { + // When selected, only draw the highlighted part until the horizontal separator + int offset = 2; + auto highlightRect = rect.adjusted(0, 0, 0, -offset); + painter->fillRect(highlightRect, palette.highlight().color()); + // Then fill the remainder with the normal color + auto regularRect = rect.adjusted(0, rect.height()-offset, 0, 0); + painter->fillRect(regularRect, palette.light().color()); + } else { + // Otherwise just draw the background color as usual + painter->fillRect(rect, palette.light().color()); + } + + // Draw bottom line. Last line gets a different color + painter->setPen(lastIndex ? palette.dark().color() + : palette.mid().color()); + painter->drawLine(lastIndex ? rect.left() : m_ptr->margins.left(), + bottomEdge, rect.right(), bottomEdge); + + // Draw system icon + if (hasIcon) { + painter->drawPixmap(contentRect.left(), contentRect.top(), + opt.icon.pixmap(m_ptr->iconSize)); + } + + // System name + QRect systemNameRect(m_ptr->systemNameBox(opt, index)); + + systemNameRect.moveTo(m_ptr->margins.left() + m_ptr->iconSize.width() + + m_ptr->spacingHorizontal, contentRect.top()); + // If desired, font can be changed here +// painter->setFont(f); + painter->setFont(opt.font); + painter->setPen(palette.text().color()); + painter->drawText(systemNameRect, Qt::TextSingleLine, opt.text); + + // Draw status icon + painter->drawPixmap(systemNameRect.left(), systemNameRect.bottom() + + m_ptr->spacingVertical, + status_icon.pixmap(m_ptr->smallIconSize)); + + // This rectangle is around the status icon + // auto point = QPoint(systemNameRect.left(), systemNameRect.bottom() + // + m_ptr->spacingVertical); + // auto point2 = QPoint(point.x() + m_ptr->smallIconSize.width(), point.y() + m_ptr->smallIconSize.height()); + // auto arect = QRect(point, point2); + // painter->drawRect(arect); + + // Draw status text + QRect statusRect(m_ptr->statusBox(opt, index)); + int extraaa = 2; + statusRect.moveTo(systemNameRect.left() + m_ptr->margins.left() + m_ptr->smallIconSize.width(), + systemNameRect.bottom() + m_ptr->spacingVertical + extraaa + (m_ptr->smallIconSize.height() - systemNameRect.height() )); + +// painter->setFont(opt.font); + painter->setFont(f); + painter->setPen(palette.windowText().color()); + painter->drawText(statusRect, Qt::TextSingleLine, + index.data(VMManagerModel::Roles::ProcessStatusString).toString()); + + painter->restore(); + +} + +QMargins VMManagerListViewDelegate::contentsMargins() const +{ + return m_ptr->margins; +} + +void VMManagerListViewDelegate::setContentsMargins(const int left, const int top, const int right, const int bottom) const +{ + m_ptr->margins = QMargins(left, top, right, bottom); +} + +int VMManagerListViewDelegate::horizontalSpacing() const +{ + return m_ptr->spacingHorizontal; +} + +void VMManagerListViewDelegate::setHorizontalSpacing(const int spacing) const +{ + m_ptr->spacingHorizontal = spacing; +} + +int VMManagerListViewDelegate::verticalSpacing() const +{ + return m_ptr->spacingVertical; +} + +void VMManagerListViewDelegate::setVerticalSpacing(const int spacing) const +{ + m_ptr->spacingVertical = spacing; +} + + +QSize VMManagerListViewDelegate::sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QStyleOptionViewItem opt(option); + initStyleOption(&opt, index); + + const int textHeight = m_ptr->systemNameBox(opt, index).height() + + m_ptr->spacingVertical + m_ptr->statusBox(opt, index).height(); + const int iconHeight = m_ptr->iconSize.height(); + const int h = textHeight > iconHeight ? textHeight : iconHeight; + + // return the same width + // for height, add margins on top and bottom *plus* either the text or icon height, whichever is greater + // Note: text height is the combined value of the system name and the status just below the name + return {opt.rect.width(), m_ptr->margins.top() + h + + m_ptr->margins.bottom()}; +} + +VMManagerListViewDelegateStyle::VMManagerListViewDelegateStyle() : + iconSize(32, 32), + smallIconSize(16, 16), + // bottom gets a little more than the top because of the custom separator + margins(4, 10, 8, 12), + // Spacing between icon and text + spacingHorizontal(8), + spacingVertical(4) +{ + +} + +QRect VMManagerListViewDelegateStyle::statusBox(const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QFont f(option.font); + + f.setPointSizeF(statusFontPointSize(option.font)); + + return QFontMetrics(f).boundingRect(index.data(VMManagerModel::Roles::ProcessStatusString).toString()) + .adjusted(0, 0, 1, 1); +} + +qreal VMManagerListViewDelegateStyle::statusFontPointSize(const QFont &f) const +{ + return 0.75*f.pointSize(); +// return 1*f.pointSize(); +} + +QRect VMManagerListViewDelegateStyle::systemNameBox(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + return option.fontMetrics.boundingRect(option.text).adjusted(0, 0, 1, 1); +} \ No newline at end of file diff --git a/src/qt/qt_vmmanager_listviewdelegate.hpp b/src/qt/qt_vmmanager_listviewdelegate.hpp new file mode 100644 index 000000000..84325086d --- /dev/null +++ b/src/qt/qt_vmmanager_listviewdelegate.hpp @@ -0,0 +1,67 @@ +/* +* 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. +* +* Header for 86Box VM manager list view delegate module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_LISTVIEWDELEGATE_H +#define QT_VMMANAGER_LISTVIEWDELEGATE_H + +#include <QPainter> +#include <QStyledItemDelegate> +#include "qt_vmmanager_system.hpp" + +class VMManagerListViewDelegateStyle +{ + VMManagerListViewDelegateStyle(); + + [[nodiscard]] inline QRect systemNameBox(const QStyleOptionViewItem &option, + const QModelIndex &index) const; + [[nodiscard]] inline qreal statusFontPointSize(const QFont &f) const; + [[nodiscard]] inline QRect statusBox(const QStyleOptionViewItem &option, const QModelIndex &index) const; + + QSize iconSize; + QSize smallIconSize; + QMargins margins; + int spacingHorizontal; + int spacingVertical; + + friend class VMManagerListViewDelegate; +}; + +class VMManagerListViewDelegate final : public QStyledItemDelegate { + Q_OBJECT + +public: + explicit VMManagerListViewDelegate(QObject *parent = nullptr); + ~VMManagerListViewDelegate() override; + using QStyledItemDelegate::QStyledItemDelegate; + + [[nodiscard]] QMargins contentsMargins() const; + void setContentsMargins(int left, int top, int right, int bottom) const; + + [[nodiscard]] int horizontalSpacing() const; + void setHorizontalSpacing(int spacing) const; + + [[nodiscard]] int verticalSpacing() const; + void setVerticalSpacing(int spacing) const; + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override; + [[nodiscard]] QSize sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const override; +private: + VMManagerListViewDelegateStyle *m_ptr; +}; +#endif // QT_VMMANAGER_LISTVIEWDELEGATE_H \ No newline at end of file diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp new file mode 100644 index 000000000..a8480eee7 --- /dev/null +++ b/src/qt/qt_vmmanager_main.cpp @@ -0,0 +1,518 @@ +/* +* 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. +* +* 86Box VM manager main module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include <QAbstractListModel> +#include <QCompleter> +#include <QDebug> +#include <QDesktopServices> +#include <QMenu> +#include <QMessageBox> +#include <QStringListModel> +#include <QTimer> + +#include "qt_vmmanager_main.hpp" +#include "ui_qt_vmmanager_main.h" +#include "qt_vmmanager_model.hpp" +#include "qt_vmmanager_addmachine.hpp" + +VMManagerMain::VMManagerMain(QWidget *parent) : + QWidget(parent), ui(new Ui::VMManagerMain), selected_sysconfig(new VMManagerSystem) { + ui->setupUi(this); + this->setWindowTitle("86Box VM Manager"); + + // Set up the main listView + ui->listView->setItemDelegate(new VMManagerListViewDelegate); + vm_model = new VMManagerModel; + proxy_model = new StringListProxyModel(this); + proxy_model->setSourceModel(vm_model); + ui->listView->setModel(proxy_model); + proxy_model->setSortCaseSensitivity(Qt::CaseInsensitive); + ui->listView->model()->sort(0, Qt::AscendingOrder); + + // Connect the model signal + connect(vm_model, &VMManagerModel::systemDataChanged, this, &VMManagerMain::modelDataChange); + + // Set up the context menu for the list view + ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->listView, &QListView::customContextMenuRequested, [this](const QPoint &pos) { + const auto indexAt = ui->listView->indexAt(pos); + if (indexAt.isValid()) { + QMenu contextMenu(tr("Context Menu"), ui->listView); + + QAction nameChangeAction(tr("Change display name")); + contextMenu.addAction(&nameChangeAction); + // Use a lambda to call a function so indexAt can be passed + connect(&nameChangeAction, &QAction::triggered, ui->listView, [this, indexAt] { + updateDisplayName(indexAt); + }); + + QAction openSystemFolderAction(tr("Open folder")); + contextMenu.addAction(&openSystemFolderAction); + connect(&openSystemFolderAction, &QAction::triggered, [this, indexAt] { + if (const auto configDir = indexAt.data(VMManagerModel::Roles::ConfigDir).toString(); !configDir.isEmpty()) { + QDesktopServices::openUrl(QUrl(QString("file:///") + configDir)); + } + }); + + QAction convertToP3(tr("Convert system to PIII")); + contextMenu.addAction(&convertToP3); + convertToP3.setEnabled(false); + + QAction setSystemIcon(tr("Set icon")); + contextMenu.addAction(&setSystemIcon); + connect(&setSystemIcon, &QAction::triggered, [this, indexAt] { + IconSelectionDialog dialog(":/systemicons/"); + if(dialog.exec() == QDialog::Accepted) { + const QString iconName = dialog.getSelectedIconName(); + // A Blank iconName will cause setIcon to reset to the default + selected_sysconfig->setIcon(iconName); + } + }); + + contextMenu.addSeparator(); + + QAction showRawConfigFile(tr("Show config file")); + contextMenu.addAction(&showRawConfigFile); + connect(&showRawConfigFile, &QAction::triggered, [this, indexAt] { + if (const auto configFile = indexAt.data(VMManagerModel::Roles::ConfigFile).toString(); !configFile.isEmpty()) { + showTextFileContents(indexAt.data(Qt::DisplayRole).toString(), configFile); + } + }); + + contextMenu.exec(ui->listView->viewport()->mapToGlobal(pos)); + } + }); + + // Initial default details view + vm_details = new VMManagerDetails(); + ui->detailsArea->layout()->addWidget(vm_details); + const QItemSelectionModel *selection_model = ui->listView->selectionModel(); + + connect(selection_model, &QItemSelectionModel::currentChanged, this, &VMManagerMain::currentSelectionChanged); + // If there are items in the model, make sure to select the first item by default. + // When settings are loaded, the last selected item will be selected (if available) + if (proxy_model->rowCount(QModelIndex()) > 0) { + const QModelIndex first_index = proxy_model->index(0, 0); + ui->listView->setCurrentIndex(first_index); + } + + // Load and apply settings + loadSettings(); + + // Set up search bar + connect(ui->searchBar, &QLineEdit::textChanged, this, &VMManagerMain::searchSystems); + // Create the completer + auto *completer = new QCompleter(this); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setFilterMode(Qt::MatchContains); + // Get the completer list + const auto allStrings = getSearchCompletionList(); + // Set up the completer + auto *completerModel = new QStringListModel(allStrings, completer); + completer->setModel(completerModel); + ui->searchBar->setCompleter(completer); + + // Set initial status bar after the event loop starts + QTimer::singleShot(0, this, [this] { + emit updateStatusRight(totalCountString()); + }); + + // Start update check after a slight delay + QTimer::singleShot(1000, this, [this] { + if(updateCheck) { + backgroundUpdateCheckStart(); + } + }); +} + +VMManagerMain::~VMManagerMain() { + delete ui; + delete vm_model; +} + +void +VMManagerMain::currentSelectionChanged(const QModelIndex &current, + const QModelIndex &previous) +{ + if(!current.isValid()) { + return; + } + + const auto mapped_index = proxy_model->mapToSource(current); + selected_sysconfig = vm_model->getConfigObjectForIndex(mapped_index); + vm_details->updateData(selected_sysconfig); + + // Emit that the selection changed, include with the process state + emit selectionChanged(current, selected_sysconfig->process->state()); + +} + +void +VMManagerMain::settingsButtonPressed() { + if(!currentSelectionIsValid()) { + return; + } + selected_sysconfig->launchSettings(); + // If the process is already running, the system will be instructed to open its settings window. + // Otherwise the process will be launched and will need to be tracked here. + if (!selected_sysconfig->isProcessRunning()) { + connect(selected_sysconfig->process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), + [=](const int exitCode, const QProcess::ExitStatus exitStatus){ + if (exitCode != 0 || exitStatus != QProcess::NormalExit) { + qInfo().nospace().noquote() << "Abnormal program termination while launching settings: exit code " << exitCode << ", exit status " << exitStatus; + return; + } + selected_sysconfig->reloadConfig(); + vm_details->updateData(selected_sysconfig); + }); + } +} + +void +VMManagerMain::startButtonPressed() const +{ + if(!currentSelectionIsValid()) { + return; + } + selected_sysconfig->startButtonPressed(); +} + +void +VMManagerMain::restartButtonPressed() const +{ + if(!currentSelectionIsValid()) { + return; + } + selected_sysconfig->restartButtonPressed(); + +} + +void +VMManagerMain::pauseButtonPressed() const +{ + if(!currentSelectionIsValid()) { + return; + } + selected_sysconfig->pauseButtonPressed(); +} + +void +VMManagerMain::shutdownRequestButtonPressed() const +{ + if (!currentSelectionIsValid()) { + return; + } + selected_sysconfig->shutdownRequestButtonPressed(); +} + +void +VMManagerMain::shutdownForceButtonPressed() const +{ + if (!currentSelectionIsValid()) { + return; + } + selected_sysconfig->shutdownForceButtonPressed(); +} + +// This function doesn't appear to be needed any longer +void +VMManagerMain::refresh() +{ + bool running = selected_sysconfig->process->state() == QProcess::ProcessState::Running; + const auto current_index = ui->listView->currentIndex(); + emit selectionChanged(current_index, selected_sysconfig->process->state()); + + // if(!selected_sysconfig->config_file.path().isEmpty()) { + if(!selected_sysconfig->isValid()) { + // what was happening here? + } +} + +void +VMManagerMain::updateDisplayName(const QModelIndex &index) +{ + QDialog dialog; + dialog.setMinimumWidth(400); + dialog.setWindowTitle(tr("Set display name")); + const auto layout = new QVBoxLayout(&dialog); + const auto label = new QLabel(tr("Enter the new display name (blank to reset)")); + label->setAlignment(Qt::AlignHCenter); + label->setContentsMargins(QMargins(0, 0, 0, 5)); + layout->addWidget(label); + const auto lineEdit = new QLineEdit(index.data().toString(), &dialog); + layout->addWidget(lineEdit); + lineEdit->selectAll(); + + const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dialog); + layout->addWidget(buttonBox); + + connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + + if (const bool accepted = dialog.exec() == QDialog::Accepted; accepted) { + const auto mapped_index = proxy_model->mapToSource(index); + vm_model->updateDisplayName(mapped_index, lineEdit->text()); + selected_sysconfig = vm_model->getConfigObjectForIndex(mapped_index); + vm_details->updateData(selected_sysconfig); + ui->listView->scrollTo(ui->listView->currentIndex(), QAbstractItemView::PositionAtCenter); + } +} + +void +VMManagerMain::loadSettings() +{ + const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); + const auto lastSelection = config->getStringValue("last_selection"); + updateCheck = config->getStringValue("update_check").toInt(); + regexSearch = config->getStringValue("regex_search").toInt(); + + const auto matches = ui->listView->model()->match(vm_model->index(0, 0), VMManagerModel::Roles::ConfigName, QVariant::fromValue(lastSelection)); + if (!matches.empty()) { + ui->listView->setCurrentIndex(matches.first()); + ui->listView->scrollTo(ui->listView->currentIndex(), QAbstractItemView::PositionAtCenter); + } +} +bool +VMManagerMain::currentSelectionIsValid() const +{ + return ui->listView->currentIndex().isValid() && selected_sysconfig->isValid(); +} + +// Used from MainWindow during app exit to obtain and persist the current selection +QString +VMManagerMain::getCurrentSelection() const +{ + return ui->listView->currentIndex().data(VMManagerModel::Roles::ConfigName).toString(); +} + +void +VMManagerMain::searchSystems(const QString &text) const +{ + // Escape the search text string unless regular expression searching is enabled. + // When escaped, the search string functions as a plain text match. + const auto searchText = regexSearch ? text : QRegularExpression::escape(text); + const QRegularExpression regex(searchText, QRegularExpression::CaseInsensitiveOption); + if (!regex.isValid()) { + qDebug() << "Skipping, invalid regex"; + return; + } + proxy_model->setFilterRegularExpression(regex); + // Searching (filtering) can cause the list view to change. If there is still a valid selection, + // make sure to scroll to it + if (ui->listView->currentIndex().isValid()) { + ui->listView->scrollTo(ui->listView->currentIndex(), QAbstractItemView::PositionAtCenter); + } +} + +void +VMManagerMain::newMachineWizard() +{ + const auto wizard = new VMManagerAddMachine(this); + if (wizard->exec() == QDialog::Accepted) { + const auto newName = wizard->field("systemName").toString(); + const auto systemDir = wizard->field("systemLocation").toString(); + const auto existingConfiguration = wizard->field("existingConfiguration").toString(); + addNewSystem(newName, systemDir, existingConfiguration); + } +} + +void +VMManagerMain::addNewSystem(const QString &name, const QString &dir, const QString &configFile) +{ + const auto newSytemDirectory = QDir(QDir::cleanPath(dir + "/" + name)); + + // qt replaces `/` with native separators + const auto newSystemConfigFile = QFileInfo(newSytemDirectory.path() + "/" + "86box.cfg"); + if (newSystemConfigFile.exists() || newSytemDirectory.exists()) { + QMessageBox::critical(this, tr("Directory in use"), tr("The selected directory is already in use. Please select a different directory.")); + return; + } + // Create the directory + const QDir qmkdir; + if (const bool mkdirResult = qmkdir.mkdir(newSytemDirectory.path()); !mkdirResult) { + QMessageBox::critical(this, tr("Create directory failed"), tr("Unable to create the directory for the new system")); + return; + } + // If specified, write the contents of the configuration file before starting + if (!configFile.isEmpty()) { + const auto configPath = newSystemConfigFile.absoluteFilePath(); + const auto file = new QFile(configPath); + if (!file->open(QIODevice::WriteOnly)) { + qWarning() << "Unable to open file " << configPath; + QMessageBox::critical(this, tr("Configuration write failed"), tr("Unable to open the configuration file at %1 for writing").arg(configPath)); + return; + } + file->write(configFile.toUtf8()); + file->flush(); + file->close(); + } + + const auto new_system = new VMManagerSystem(newSystemConfigFile.absoluteFilePath()); + new_system->launchSettings(); + // Handle this in a closure so we can capture the temporary new_system object + connect(new_system->process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), + [=](const int exitCode, const QProcess::ExitStatus exitStatus) { + if (exitCode != 0 || exitStatus != QProcess::NormalExit) { + qInfo().nospace().noquote() << "Abnormal program termination while creating new system: exit code " << exitCode << ", exit status " << exitStatus; + qInfo() << "Not adding system due to errors"; + QMessageBox::critical(this, tr("Error adding system"), + tr("Abnormal program termination while creating new system: exit code %1, exit status %2.\n\nThe system will not be added.").arg(QString::number(exitCode), exitStatus)); + delete new_system; + return; + } + // Create a new QFileInfo because the info from the old one may be cached + if (const auto fi = QFileInfo(new_system->config_file.absoluteFilePath()); !fi.exists()) { + // No config file which means the cancel button was pressed in the settings dialog + // Attempt to clean up the directory that was created + const QDir qrmdir; + if (const bool result = qrmdir.rmdir(newSytemDirectory.path()); !result) { + qWarning() << "Error cleaning up the old directory for canceled operation. Continuing anyway."; + } + delete new_system; + return; + } + const auto current_index = ui->listView->currentIndex(); + vm_model->reload(); + const auto created_object = vm_model->getIndexForConfigFile(new_system->config_file); + if (created_object.row() < 0) { + // For some reason the index of the new object couldn't be determined. Fall back to the old index. + ui->listView->setCurrentIndex(current_index); + delete new_system; + return; + } + // Get the index of the newly-created system and select it + const QModelIndex mapped_index = proxy_model->mapFromSource(created_object); + ui->listView->setCurrentIndex(mapped_index); + delete new_system; + }); +} + +QStringList +VMManagerMain::getSearchCompletionList() const +{ + QSet<QString> uniqueStrings; + for (int row = 0; row < vm_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = vm_model->index(row, 0); + auto fullList = vm_model->data(index, VMManagerModel::Roles::SearchList).toStringList(); + QSet uniqueSet(fullList.begin(), fullList.end()); + uniqueStrings.unite(uniqueSet); + } + // Convert the set back to a QStringList + QStringList allStrings = uniqueStrings.values(); + return allStrings; +} + +QString +VMManagerMain::totalCountString() const +{ + const auto count = vm_model->rowCount(QModelIndex()); + return QString("%1 %2").arg(QString::number(count), tr("total")); +} + +void +VMManagerMain::modelDataChange() +{ + // Model data has changed. This includes process status. + // Update the counts / totals accordingly + auto modelStats = vm_model->getProcessStats(); + QStringList stats; + for (auto it = modelStats.constBegin(); it != modelStats.constEnd(); ++it) { + const auto &key = it.key(); + stats.append(QString("%1 %2").arg(QString::number(modelStats[key]), key)); + } + auto states = stats.join(", "); + if (!modelStats.isEmpty()) { + states.append(", "); + } + + emit updateStatusRight(states + totalCountString()); +} + +void +VMManagerMain::onPreferencesUpdated() +{ + // Only reload values that we care about + const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); + const auto oldRegexSearch = regexSearch; + regexSearch = config->getStringValue("regex_search").toInt(); + if (oldRegexSearch != regexSearch) { + ui->searchBar->clear(); + } +} + +void +VMManagerMain::backgroundUpdateCheckStart() const +{ + auto updateChannel = UpdateCheck::UpdateChannel::CI; +#ifdef RELEASE_BUILD + updateChannel = UpdateCheck::UpdateChannel::Stable; +#endif + const auto updateCheck = new UpdateCheck(updateChannel); + connect(updateCheck, &UpdateCheck::updateCheckComplete, this, &VMManagerMain::backgroundUpdateCheckComplete); + connect(updateCheck, &UpdateCheck::updateCheckError, this, &VMManagerMain::backgroundUpdateCheckError); + updateCheck->checkForUpdates(); +} + +void +VMManagerMain::backgroundUpdateCheckComplete(const UpdateCheck::UpdateResult &result) +{ + qDebug() << "Check complete: update available?" << result.updateAvailable; + auto type = result.channel == UpdateCheck::UpdateChannel::CI ? tr("Build") : tr("Version"); + const auto updateMessage = QString("%1: %2 %3").arg( tr("An update to 86Box is available"), type, result.latestVersion); + emit updateStatusLeft(updateMessage); +} + +void +VMManagerMain::backgroundUpdateCheckError(const QString &errorMsg) +{ + qDebug() << "Update check failed with the following error:" << errorMsg; + // TODO: Update the status bar +} + +void +VMManagerMain::showTextFileContents(const QString &title, const QString &path) +{ + // Make sure we can open the file + const auto fi = QFileInfo(path); + if(!fi.exists()) { + qWarning("Requested file does not exist: %s", path.toUtf8().constData()); + return; + } + // Read the file + QFile displayFile(path); + if (!displayFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning("Couldn't open the file: error %d", displayFile.error()); + return; + } + const QString configFileContents = displayFile.readAll(); + displayFile.close(); + + const auto textDisplayDialog = new QDialog(this); + textDisplayDialog->setFixedSize(QSize(540, 360)); + textDisplayDialog->setWindowTitle(QString("%1 - %2").arg(title, fi.fileName())); + + const auto textEdit = new QPlainTextEdit(); + textEdit->setReadOnly(true); + textEdit->setPlainText(configFileContents); + const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + connect(buttonBox, &QDialogButtonBox::accepted, textDisplayDialog, &QDialog::accept); + const auto layout = new QVBoxLayout(); + textDisplayDialog->setLayout(layout); + textDisplayDialog->layout()->addWidget(textEdit); + textDisplayDialog->layout()->addWidget(buttonBox); + textDisplayDialog->exec(); +} diff --git a/src/qt/qt_vmmanager_main.hpp b/src/qt/qt_vmmanager_main.hpp new file mode 100644 index 000000000..c3c541b4f --- /dev/null +++ b/src/qt/qt_vmmanager_main.hpp @@ -0,0 +1,167 @@ +/* +* 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. +* +* Header for 86Box VM manager main module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_MAIN_H +#define QT_VMMANAGER_MAIN_H + +#include "qt_updatecheck.hpp" + +#include <QWidget> +#include "qt_vmmanager_model.hpp" +#include "qt_vmmanager_details.hpp" +#include "qt_vmmanager_listviewdelegate.hpp" + +#include <QPushButton> + +extern "C" { +#include <86box/86box.h> // for vmm_path +} + + +QT_BEGIN_NAMESPACE +namespace Ui { class VMManagerMain; } +QT_END_NAMESPACE + +class VMManagerMain final : public QWidget { + Q_OBJECT + +public: + explicit VMManagerMain(QWidget *parent = nullptr); + ~VMManagerMain() override; + // Used to save the current selection + [[nodiscard]] QString getCurrentSelection() const; + + enum class ToolbarButton { + Start, + Pause, + StartPause, + Shutdown, + Reset, + CtrlAltDel, + Settings, + }; +signals: + void selectionChanged(const QModelIndex &currentSelection, QProcess::ProcessState processState); + void updateStatusLeft(const QString &text); + void updateStatusRight(const QString &text); + +public slots: + void startButtonPressed() const; + void settingsButtonPressed(); + void restartButtonPressed() const; + void pauseButtonPressed() const; + void shutdownRequestButtonPressed() const; + void shutdownForceButtonPressed() const; + void searchSystems(const QString &text) const; + void newMachineWizard(); + void addNewSystem(const QString &name, const QString &dir, const QString &configFile = {}); + [[nodiscard]] QStringList getSearchCompletionList() const; + void modelDataChange(); + void onPreferencesUpdated(); + +private: + Ui::VMManagerMain *ui; + + VMManagerModel *vm_model; + VMManagerDetails *vm_details; + VMManagerSystem *selected_sysconfig; + // VMManagerConfig *config; + QSortFilterProxyModel *proxy_model; + bool updateCheck = false; + bool regexSearch = false; + + // void updateSelection(const QItemSelection &selected, + // const QItemSelection &deselected); + void currentSelectionChanged(const QModelIndex &current, + const QModelIndex &previous); + void refresh(); + void updateDisplayName(const QModelIndex &index); + void loadSettings(); + [[nodiscard]] bool currentSelectionIsValid() const; + [[nodiscard]] QString totalCountString() const; + void backgroundUpdateCheckStart() const; + void showTextFileContents(const QString &title, const QString &path); +private slots: + void backgroundUpdateCheckComplete(const UpdateCheck::UpdateResult &result); + void backgroundUpdateCheckError(const QString &errorMsg); +}; + +#include <QDialog> +#include <QListWidget> +#include <QDialogButtonBox> +#include <QDir> + +class IconSelectionDialog final : public QDialog { + Q_OBJECT + +public: + explicit IconSelectionDialog(QString assetPath, QWidget *parent = nullptr) : QDialog(parent), listWidget(new QListWidget) { + // Set the list widget to icon mode + listWidget->setViewMode(QListWidget::IconMode); + setFixedSize(QSize(540, 360)); + listWidget->setGridSize(QSize(96, 96)); + listWidget->setIconSize(QSize(64, 64)); + // Read in all the assets from the given path + const QDir iconsDir(assetPath); + if (!assetPath.endsWith("/")) { + assetPath.append("/"); + } + setWindowTitle(tr("Select an icon")); + + // Loop on all files and add them as items (icons) in QListWidget + for(const QString& iconName : iconsDir.entryList()) { + const auto item = new QListWidgetItem(QIcon(assetPath + iconName), iconName); + // Set the UserRole to the resource bundle path + item->setData(Qt::UserRole, assetPath + iconName); + listWidget->addItem(item); + } + + // Dialog buttons + const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Reset); + // Use the reset button for resetting the icon to the default + const QPushButton* resetButton = buttonBox->button(QDialogButtonBox::Reset); + + // Connect the buttons signals + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(listWidget, &QListWidget::doubleClicked, this, &QDialog::accept); + connect(resetButton, &QPushButton::clicked, [this] { + // For reset, set the index to invalid so the caller will receive a blank string + listWidget->setCurrentIndex(QModelIndex()); + // Then accept + QDialog::accept(); + }); + + const auto layout = new QVBoxLayout(this); + layout->addWidget(listWidget); + layout->addWidget(buttonBox); + } + + public slots: + [[nodiscard]] QString getSelectedIconName() const { + if (listWidget->currentIndex().isValid()) { + return listWidget->currentItem()->data(Qt::UserRole).toString(); + } + // Index is invalid because the reset button was pressed + return {}; + } + +private: + QListWidget* listWidget; +}; + +#endif //QT_VMMANAGER_MAIN_H diff --git a/src/qt/qt_vmmanager_main.ui b/src/qt/qt_vmmanager_main.ui new file mode 100644 index 000000000..c19094345 --- /dev/null +++ b/src/qt/qt_vmmanager_main.ui @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VMManagerMain</class> + <widget class="QWidget" name="VMManagerMain"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>815</width> + <height>472</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>VMManagerMain</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QListView" name="listView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>200</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="searchBar"> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> + </property> + <property name="placeholderText"> + <string> Search</string> + </property> + <property name="clearButtonEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="detailsArea" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp new file mode 100644 index 000000000..767bbcef2 --- /dev/null +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -0,0 +1,178 @@ +/* +* 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. +* +* 86Box VM manager main window +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include "qt_vmmanager_mainwindow.hpp" +#include "qt_vmmanager_main.hpp" +#include "qt_vmmanager_preferences.hpp" +#include "ui_qt_vmmanager_mainwindow.h" +#include "qt_updatecheckdialog.hpp" + +#include <QLineEdit> +#include <QStringListModel> +#include <QCompleter> + +VMManagerMainWindow:: +VMManagerMainWindow(QWidget *parent) + : ui(new Ui::VMManagerMainWindow) + , vmm(new VMManagerMain(this)) + , statusLeft(new QLabel) + , statusRight(new QLabel) +{ + ui->setupUi(this); + + // Connect signals from the VMManagerMain widget + connect(vmm, &VMManagerMain::selectionChanged, this, &VMManagerMainWindow::vmmSelectionChanged); + + setWindowTitle(tr("86Box VM Manager")); + setCentralWidget(vmm); + + // Set up the buttons + connect(ui->actionStartPause, &QAction::triggered, vmm, &VMManagerMain::startButtonPressed); + connect(ui->actionSettings, &QAction::triggered, vmm, &VMManagerMain::settingsButtonPressed); + connect(ui->actionHard_Reset, &QAction::triggered, vmm, &VMManagerMain::restartButtonPressed); + connect(ui->actionForce_Shutdown, &QAction::triggered, vmm, &VMManagerMain::shutdownForceButtonPressed); + connect(ui->actionNew_Machine, &QAction::triggered, vmm, &VMManagerMain::newMachineWizard); + + // Set up menu actions + connect(ui->actionCheck_for_updates, &QAction::triggered, this, &VMManagerMainWindow::checkForUpdatesTriggered); + + // TODO: Remove all of this (all the way to END REMOVE) once certain the search will no longer be in the toolbar. + // BEGIN REMOVE + // Everything is still setup here for it but it is all hidden. None of it will be + // needed if the search stays in VMManagerMain + ui->actionStartPause->setEnabled(true); + ui->actionStartPause->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + ui->actionStartPause->setText(tr("Start")); + ui->actionStartPause->setToolTip(tr("Start")); + ui->actionHard_Reset->setEnabled(false); + ui->actionForce_Shutdown->setEnabled(false); + ui->actionCtrl_Alt_Del->setEnabled(false); + + const auto searchBar = new QLineEdit(); + searchBar->setMinimumWidth(150); + searchBar->setPlaceholderText(" " + tr("Search")); + searchBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + searchBar->setClearButtonEnabled(true); + // Spacer to make the search go all the way to the right + const auto spacer = new QWidget(); + spacer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); + ui->toolBar->addWidget(spacer); + ui->toolBar->addWidget(searchBar); + // Connect signal for search + connect(searchBar, &QLineEdit::textChanged, vmm, &VMManagerMain::searchSystems); + // Preferences + connect(ui->actionPreferences, &QAction::triggered, this, &VMManagerMainWindow::preferencesTriggered); + + // Create a completer for the search bar + auto *completer = new QCompleter(this); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setFilterMode(Qt::MatchContains); + // Get the completer list + const auto allStrings = vmm->getSearchCompletionList(); + // Set up the completer + auto *completerModel = new QStringListModel(allStrings, completer); + completer->setModel(completerModel); + searchBar->setCompleter(completer); + ui->toolBar->setVisible(false); + // END REMOVE + + // Status bar widgets + statusLeft->setAlignment(Qt::AlignLeft); + statusRight->setAlignment(Qt::AlignRight); + ui->statusbar->addPermanentWidget(statusLeft, 1); + ui->statusbar->addPermanentWidget(statusRight, 1); + connect(vmm, &VMManagerMain::updateStatusLeft, this, &VMManagerMainWindow::setStatusLeft); + connect(vmm, &VMManagerMain::updateStatusRight, this, &VMManagerMainWindow::setStatusRight); + + // Inform the main view when preferences are updated + connect(this, &VMManagerMainWindow::preferencesUpdated, vmm, &VMManagerMain::onPreferencesUpdated); + +} + +VMManagerMainWindow::~ +VMManagerMainWindow() + = default; + +void +VMManagerMainWindow::vmmSelectionChanged(const QModelIndex &currentSelection, const QProcess::ProcessState processState) const +{ + if (processState == QProcess::Running) { + ui->actionStartPause->setEnabled(true); + ui->actionStartPause->setIcon(QIcon(":/menuicons/qt/icons/pause.ico")); + ui->actionStartPause->setText(tr("Pause")); + ui->actionStartPause->setToolTip(tr("Pause")); + ui->actionHard_Reset->setEnabled(true); + ui->actionForce_Shutdown->setEnabled(true); + ui->actionCtrl_Alt_Del->setEnabled(true); + } else { + ui->actionStartPause->setEnabled(true); + ui->actionStartPause->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + ui->actionStartPause->setText(tr("Start")); + ui->actionStartPause->setToolTip(tr("Start")); + ui->actionHard_Reset->setEnabled(false); + ui->actionForce_Shutdown->setEnabled(false); + ui->actionCtrl_Alt_Del->setEnabled(false); + } +} +void +VMManagerMainWindow::preferencesTriggered() +{ + const auto prefs = new VMManagerPreferences(); + if (prefs->exec() == QDialog::Accepted) { + emit preferencesUpdated(); + } +} + +void +VMManagerMainWindow::saveSettings() const +{ + const auto currentSelection = vmm->getCurrentSelection(); + const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); + config->setStringValue("last_selection", currentSelection); + // Sometimes required to ensure the settings save before the app exits + config->sync(); +} + +void +VMManagerMainWindow::closeEvent(QCloseEvent *event) +{ + saveSettings(); + QMainWindow::closeEvent(event); +} + +void +VMManagerMainWindow::setStatusLeft(const QString &text) const +{ + statusLeft->setText(text); +} + +void +VMManagerMainWindow::setStatusRight(const QString &text) const +{ + statusRight->setText(text); +} + +void +VMManagerMainWindow::checkForUpdatesTriggered() +{ + auto updateChannel = UpdateCheck::UpdateChannel::CI; +#ifdef RELEASE_BUILD + updateChannel = UpdateCheck::UpdateChannel::Stable; +#endif + const auto updateCheck = new UpdateCheckDialog(updateChannel); + updateCheck->exec(); +} diff --git a/src/qt/qt_vmmanager_mainwindow.hpp b/src/qt/qt_vmmanager_mainwindow.hpp new file mode 100644 index 000000000..764ed5ef8 --- /dev/null +++ b/src/qt/qt_vmmanager_mainwindow.hpp @@ -0,0 +1,59 @@ +/* +* 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. +* +* Header for 86Box VM manager main window +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef VMM_MAINWINDOW_H +#define VMM_MAINWINDOW_H + +#include "qt_vmmanager_main.hpp" + +#include <QObject> +#include <QMainWindow> +#include <QProcess> + +namespace Ui { +class VMManagerMainWindow; +} + +class VMManagerMainWindow final : public QMainWindow +{ + Q_OBJECT +public: + explicit VMManagerMainWindow(QWidget *parent = nullptr); + ~VMManagerMainWindow() override; +signals: + void preferencesUpdated(); + +private: + Ui::VMManagerMainWindow *ui; + VMManagerMain *vmm; + void saveSettings() const; + QLabel *statusLeft; + QLabel *statusRight; +public slots: + void setStatusLeft(const QString &text) const; + void setStatusRight(const QString &text) const; + +private slots: + void vmmSelectionChanged(const QModelIndex &currentSelection, QProcess::ProcessState processState) const; + void preferencesTriggered(); + static void checkForUpdatesTriggered(); + +protected: + void closeEvent(QCloseEvent *event) override; +}; + +#endif // VMM_MAINWINDOW_H diff --git a/src/qt/qt_vmmanager_mainwindow.ui b/src/qt/qt_vmmanager_mainwindow.ui new file mode 100644 index 000000000..b19610593 --- /dev/null +++ b/src/qt/qt_vmmanager_mainwindow.ui @@ -0,0 +1,224 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VMManagerMainWindow</class> + <widget class="QMainWindow" name="VMManagerMainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>900</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"/> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>900</width> + <height>24</height> + </rect> + </property> + <widget class="QMenu" name="menuTools"> + <property name="title"> + <string>Tools</string> + </property> + <addaction name="actionPreferences"/> + <addaction name="actionCheck_for_updates"/> + </widget> + <widget class="QMenu" name="menuMachine"> + <property name="title"> + <string>Machine</string> + </property> + <addaction name="actionStartPause"/> + <addaction name="actionForce_Shutdown"/> + <addaction name="actionHard_Reset"/> + <addaction name="actionCtrl_Alt_Del"/> + <addaction name="separator"/> + <addaction name="actionSettings"/> + </widget> + <widget class="QMenu" name="menuFile"> + <property name="title"> + <string>File</string> + </property> + <addaction name="actionNew_Machine"/> + </widget> + <addaction name="menuFile"/> + <addaction name="menuMachine"/> + <addaction name="menuTools"/> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <widget class="QToolBar" name="toolBar"> + <property name="windowTitle"> + <string>toolBar</string> + </property> + <property name="movable"> + <bool>false</bool> + </property> + <property name="iconSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonIconOnly</enum> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="actionStartPause"/> + <addaction name="actionHard_Reset"/> + <addaction name="actionForce_Shutdown"/> + <addaction name="actionCtrl_Alt_Del"/> + <addaction name="actionSettings"/> + <addaction name="actionNew_Machine"/> + </widget> + <action name="actionDo_something"> + <property name="text"> + <string>Do something</string> + </property> + </action> + <action name="actionStartPause"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/menuicons/qt/icons/run.ico</normaloff>:/menuicons/qt/icons/run.ico</iconset> + </property> + <property name="text"> + <string>Start</string> + </property> + <property name="iconVisibleInMenu"> + <bool>false</bool> + </property> + </action> + <action name="actionHard_Reset"> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/menuicons/qt/icons/hard_reset.ico</normaloff>:/menuicons/qt/icons/hard_reset.ico</iconset> + </property> + <property name="text"> + <string>&amp;Hard Reset...</string> + </property> + <property name="iconVisibleInMenu"> + <bool>false</bool> + </property> + </action> + <action name="actionForce_Shutdown"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/menuicons/qt/icons/acpi_shutdown.ico</normaloff>:/menuicons/qt/icons/acpi_shutdown.ico</iconset> + </property> + <property name="text"> + <string>Force shutdown</string> + </property> + <property name="toolTip"> + <string>Force shutdown</string> + </property> + <property name="visible"> + <bool>true</bool> + </property> + <property name="iconVisibleInMenu"> + <bool>false</bool> + </property> + </action> + <action name="actionCtrl_Alt_Del"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/menuicons/qt/icons/send_cad.ico</normaloff>:/menuicons/qt/icons/send_cad.ico</iconset> + </property> + <property name="text"> + <string>&amp;Ctrl+Alt+Del</string> + </property> + <property name="toolTip"> + <string>Ctrl+Alt+Del</string> + </property> + <property name="visible"> + <bool>false</bool> + </property> + <property name="iconVisibleInMenu"> + <bool>false</bool> + </property> + <property name="shortcutVisibleInContextMenu"> + <bool>false</bool> + </property> + </action> + <action name="actionSettings"> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/menuicons/qt/icons/settings.ico</normaloff>:/menuicons/qt/icons/settings.ico</iconset> + </property> + <property name="text"> + <string>&amp;Settings...</string> + </property> + <property name="menuRole"> + <enum>QAction::NoRole</enum> + </property> + <property name="iconVisibleInMenu"> + <bool>false</bool> + </property> + </action> + <action name="actionNew_Machine"> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/settings/qt/icons/86Box-yellow.ico</normaloff>:/settings/qt/icons/86Box-yellow.ico</iconset> + </property> + <property name="text"> + <string>New Machine</string> + </property> + <property name="toolTip"> + <string>New Machine</string> + </property> + </action> + <action name="actionPreferences"> + <property name="text"> + <string>Preferences</string> + </property> + <property name="toolTip"> + <string>Preferences</string> + </property> + <property name="menuRole"> + <enum>QAction::PreferencesRole</enum> + </property> + </action> + <action name="actionStart"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="../qt_resources.qrc"> + <normaloff>:/menuicons/qt/icons/run.ico</normaloff>:/menuicons/qt/icons/run.ico</iconset> + </property> + <property name="text"> + <string>Start</string> + </property> + <property name="iconVisibleInMenu"> + <bool>false</bool> + </property> + </action> + <action name="actionCheck_for_updates"> + <property name="text"> + <string>Check for updates</string> + </property> + </action> + </widget> + <resources> + <include location="../qt_resources.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/qt/qt_vmmanager_model.cpp b/src/qt/qt_vmmanager_model.cpp new file mode 100644 index 000000000..7dc079df0 --- /dev/null +++ b/src/qt/qt_vmmanager_model.cpp @@ -0,0 +1,163 @@ +/* +* 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. +* +* 86Box VM manager model module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#include <QDebug> +#include "qt_vmmanager_model.hpp" + +VMManagerModel::VMManagerModel() { + auto machines_vec = VMManagerSystem::scanForConfigs(); + for ( const auto& each_config : machines_vec) { + machines.append(each_config); + connect(each_config, &VMManagerSystem::itemDataChanged, this, &VMManagerModel::modelDataChanged); + } +} + +VMManagerModel::~VMManagerModel() { + for ( auto machine : machines) { + delete machine; + } +} + +int +VMManagerModel::rowCount(const QModelIndex &parent) const { + return machines.size(); +} + +QVariant +VMManagerModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) + return {}; + + if (index.row() >= machines.size()) + return {}; + + switch (role) { + case Qt::DisplayRole: + return machines.at(index.row())->displayName; + case ConfigName: + return machines.at(index.row())->config_name; + case ConfigDir: + return machines.at(index.row())->config_dir; + case ConfigFile: + return machines.at(index.row())->config_file.canonicalFilePath(); + case UUID: + return machines.at(index.row())->uuid; + case Notes: + return machines.at(index.row())->notes; + case SearchList: + return machines.at(index.row())->searchTerms; + case LastUsed: + return machines.at(index.row())->timestamp(); + case Icon: + return machines.at(index.row())->icon; + case Qt::ToolTipRole: + return machines.at(index.row())->shortened_dir; + case Qt::UserRole: + return machines.at(index.row())->getAll("General"); + case ProcessStatusString: + return machines.at(index.row())->getProcessStatusString(); + case ProcessStatus: + return QVariant::fromValue(machines.at(index.row())->getProcessStatus()); + default: + return {}; + } +} + +QVariant +VMManagerModel::headerData(int section, Qt::Orientation orientation, int role) const { + + if (role != Qt::DisplayRole) + return {}; + + if (orientation == Qt::Horizontal) + return QStringLiteral("Column %1").arg(section); + else + return QStringLiteral("Row %1").arg(section); +} + +VMManagerSystem * +VMManagerModel::getConfigObjectForIndex(const QModelIndex &index) const +{ + return machines.at(index.row()); +} +void +VMManagerModel::reload() +{ + // Scan for configs + auto machines_vec = VMManagerSystem::scanForConfigs(); + for (const auto &scanned_config : machines_vec) { + int found = 0; + for (const auto &existing_config : machines) { + if (*scanned_config == *existing_config) { + found = 1; + } + } + if (!found) { + addConfigToModel(scanned_config); + } + } + // TODO: Remove missing configs +} + +QModelIndex +VMManagerModel::getIndexForConfigFile(const QFileInfo& config_file) +{ + int object_index = 0; + for (const auto& config_object: machines) { + if (config_object->config_file == config_file) { + return this->index(object_index); + } + object_index++; + } + return {}; +} + +void +VMManagerModel::addConfigToModel(VMManagerSystem *system_config) +{ + beginInsertRows(QModelIndex(), this->rowCount(QModelIndex()), this->rowCount(QModelIndex())); + machines.append(system_config); + connect(system_config, &VMManagerSystem::itemDataChanged, this, &VMManagerModel::modelDataChanged); + endInsertRows(); +} +void +VMManagerModel::modelDataChanged() +{ + // Inform the model + emit dataChanged(this->index(0), this->index(machines.size()-1)); + // Inform any interested observers + emit systemDataChanged(); +} + +void +VMManagerModel::updateDisplayName(const QModelIndex &index, const QString &newDisplayName) +{ + machines.at(index.row())->setDisplayName(newDisplayName); + modelDataChanged(); +} +QHash<QString, int> +VMManagerModel::getProcessStats() +{ + QHash<QString, int> stats; + for (const auto& system: machines) { + if (system->getProcessStatus() != VMManagerSystem::ProcessStatus::Stopped) { + auto statusString = system->getProcessStatusString(); + stats[statusString] += 1; + } + } + return stats; +} \ No newline at end of file diff --git a/src/qt/qt_vmmanager_model.hpp b/src/qt/qt_vmmanager_model.hpp new file mode 100644 index 000000000..858b55d14 --- /dev/null +++ b/src/qt/qt_vmmanager_model.hpp @@ -0,0 +1,91 @@ +/* +* 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. +* +* Header for 86Box VM manager model module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#ifndef QT_VMMANAGER_MODEL_H +#define QT_VMMANAGER_MODEL_H + + +#include "qt_vmmanager_system.hpp" + +#include <QSortFilterProxyModel> + +class VMManagerModel final : public QAbstractListModel { + + Q_OBJECT + +public: + // VMManagerModel(const QStringList &strings, QObject *parent = nullptr) + // : QAbstractListModel(parent), machines(strings) {} + VMManagerModel(); + ~VMManagerModel() override; + enum Roles { + ProcessStatusString = Qt::UserRole + 1, + ProcessStatus, + DisplayName, + ConfigName, + ConfigDir, + ConfigFile, + LastUsed, + UUID, + Notes, + SearchList, + Icon + }; + + [[nodiscard]] int rowCount(const QModelIndex &parent) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, + int role) const override; + void addConfigToModel(VMManagerSystem *system_config); + + [[nodiscard]] VMManagerSystem * getConfigObjectForIndex(const QModelIndex &index) const; + QModelIndex getIndexForConfigFile(const QFileInfo& config_file); + void reload(); + void updateDisplayName(const QModelIndex &index, const QString &newDisplayName); + QHash <QString, int> getProcessStats(); +signals: + void systemDataChanged(); + +private: + QVector<VMManagerSystem *> machines; + void modelDataChanged(); + +}; + +// Note: Custom QSortFilterProxyModel is included here instead of its own file as +// its only use is in this model + +class StringListProxyModel final : public QSortFilterProxyModel { +public: + explicit StringListProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {} + +protected: + [[nodiscard]] bool filterAcceptsRow(const int sourceRow, const QModelIndex &sourceParent) const override { + const QModelIndex index = sourceModel()->index(sourceRow, filterKeyColumn(), sourceParent); + + QStringList stringList = sourceModel()->data(index, VMManagerModel::Roles::SearchList).toStringList(); + + const QRegularExpression regex = filterRegularExpression(); + + const auto result = std::any_of(stringList.begin(), stringList.end(), [&regex](const QString &string) { + return regex.match(string).hasMatch(); + }); + return result; + } +}; + +#endif //QT_VMMANAGER_MODEL_H diff --git a/src/qt/qt_vmmanager_preferences.cpp b/src/qt/qt_vmmanager_preferences.cpp new file mode 100644 index 000000000..0730f875b --- /dev/null +++ b/src/qt/qt_vmmanager_preferences.cpp @@ -0,0 +1,82 @@ +/* +* 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. +* +* 86Box VM manager preferences module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include <QFileDialog> +#include <QStyle> + +#include "qt_vmmanager_preferences.hpp" +#include "qt_vmmanager_config.hpp" +#include "ui_qt_vmmanager_preferences.h" + +extern "C" { +#include <86box/86box.h> +} + +VMManagerPreferences:: +VMManagerPreferences(QWidget *parent) : ui(new Ui::VMManagerPreferences) +{ + ui->setupUi(this); + ui->dirSelectButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirIcon)); + connect(ui->dirSelectButton, &QPushButton::clicked, this, &VMManagerPreferences::chooseDirectoryLocation); + + const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); + const auto configSystemDir = config->getStringValue("system_directory"); + if(!configSystemDir.isEmpty()) { + // Prefer this one + ui->systemDirectory->setText(configSystemDir); + } else if(!QString(vmm_path).isEmpty()) { + // If specified on command line + ui->systemDirectory->setText(QDir(vmm_path).path()); + } + + // TODO: Defaults + const auto configUpdateCheck = config->getStringValue("update_check").toInt(); + ui->updateCheckBox->setChecked(configUpdateCheck); + const auto useRegexSearch = config->getStringValue("regex_search").toInt(); + ui->regexSearchCheckBox->setChecked(useRegexSearch); + + +} + +VMManagerPreferences::~ +VMManagerPreferences() + = default; + +// Bad copy pasta from machine add +void +VMManagerPreferences::chooseDirectoryLocation() +{ + // TODO: FIXME: This is pulling in the CLI directory! Needs to be set properly elsewhere + const auto directory = QFileDialog::getExistingDirectory(this, "Choose directory", QDir(vmm_path).path()); + ui->systemDirectory->setText(QDir::toNativeSeparators(directory)); +} + +void +VMManagerPreferences::accept() +{ + const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); + config->setStringValue("system_directory", ui->systemDirectory->text()); + config->setStringValue("update_check", ui->updateCheckBox->isChecked() ? "1" : "0"); + config->setStringValue("regex_search", ui->regexSearchCheckBox->isChecked() ? "1" : "0"); + QDialog::accept(); +} + +void +VMManagerPreferences::reject() +{ + QDialog::reject(); +} \ No newline at end of file diff --git a/src/qt/qt_vmmanager_preferences.hpp b/src/qt/qt_vmmanager_preferences.hpp new file mode 100644 index 000000000..aedba862a --- /dev/null +++ b/src/qt/qt_vmmanager_preferences.hpp @@ -0,0 +1,46 @@ +/* +* 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. +* +* Header for 86Box VM manager preferences module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef VMMANAGER_PREFERENCES_H +#define VMMANAGER_PREFERENCES_H + +#include <QDialog> + +QT_BEGIN_NAMESPACE +namespace Ui { class VMManagerPreferences; } +QT_END_NAMESPACE + + +class VMManagerPreferences final : public QDialog +{ + Q_OBJECT +public: + explicit VMManagerPreferences(QWidget *parent = nullptr); + ~VMManagerPreferences() override; + +private: + Ui::VMManagerPreferences *ui; + QString settingsFile; +private slots: + void chooseDirectoryLocation(); +protected: + void accept() override; + void reject() override; + +}; + +#endif // VMMANAGER_PREFERENCES_H diff --git a/src/qt/qt_vmmanager_preferences.ui b/src/qt/qt_vmmanager_preferences.ui new file mode 100644 index 000000000..1743a0bfb --- /dev/null +++ b/src/qt/qt_vmmanager_preferences.ui @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VMManagerPreferences</class> + <widget class="QDialog" name="VMManagerPreferences"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Preferences</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>System Directory:</string> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="systemDirectory"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="dirSelectButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QCheckBox" name="updateCheckBox"> + <property name="text"> + <string>Check for updates on startup</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="regexSearchCheckBox"> + <property name="text"> + <string>Use regular expressions in search box</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>VMManagerPreferences</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>VMManagerPreferences</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/qt_vmmanager_protocol.cpp b/src/qt/qt_vmmanager_protocol.cpp new file mode 100644 index 000000000..26f8a1f93 --- /dev/null +++ b/src/qt/qt_vmmanager_protocol.cpp @@ -0,0 +1,131 @@ +/* +* 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. +* +* 86Box VM manager protocol module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#include "qt_vmmanager_protocol.hpp" +#include <QJsonDocument> +#include <QMetaEnum> +VMManagerProtocol::VMManagerProtocol(VMManagerProtocol::Sender sender) +{ + message_class = sender; +} + +VMManagerProtocol::~VMManagerProtocol() += default; + +QJsonObject +VMManagerProtocol::protocolManagerMessage(VMManagerProtocol::ManagerMessage message_type) +{ + auto json_message = constructDefaultObject(VMManagerProtocol::Sender::Manager); + json_message["message"] = managerMessageTypeToString(message_type); + return json_message; +} + +QJsonObject +VMManagerProtocol::protocolClientMessage(VMManagerProtocol::ClientMessage message_type) +{ + auto json_message = constructDefaultObject(VMManagerProtocol::Sender::Client); + json_message["message"] = clientMessageTypeToString(message_type); + return json_message; +} + +QString +VMManagerProtocol::managerMessageTypeToString(VMManagerProtocol::ManagerMessage message) +{ + QMetaEnum qme = QMetaEnum::fromType<VMManagerProtocol::ManagerMessage>(); + return qme.valueToKey(static_cast<int>(message)); +} + +QString +VMManagerProtocol::clientMessageTypeToString(VMManagerProtocol::ClientMessage message) +{ + QMetaEnum qme = QMetaEnum::fromType<VMManagerProtocol::ClientMessage>(); + return qme.valueToKey(static_cast<int>(message)); +} + +QJsonObject +VMManagerProtocol::constructDefaultObject(VMManagerProtocol::Sender type) +{ + QJsonObject json_message; + QString sender_type = ( type == VMManagerProtocol::Sender::Client ) ? "Client" : "VMManager"; + json_message["type"] = QString(sender_type); + json_message["version"] = QStringLiteral(EMU_VERSION); + return json_message; +} +bool +VMManagerProtocol::hasRequiredFields(const QJsonObject& json_document) +{ + for (const auto& field : ProtocolRequiredFields) { + if (!json_document.contains(field)) { + qDebug("Received json missing field \"%s\"", qPrintable(field)); + return false; + } + } + return true; +} +VMManagerProtocol::ClientMessage +VMManagerProtocol::getClientMessageType(const QJsonObject &json_document) +{ + // FIXME: This key ("message") is hardcoded here. Make a hash which maps these + // required values. + QString message_type = json_document.value("message").toString(); + // Can't use switch with strings, manual compare + if (message_type == "Status") { + return VMManagerProtocol::ClientMessage::Status; + } else if (message_type == "WindowBlocked") { + return VMManagerProtocol::ClientMessage::WindowBlocked; + } else if (message_type == "WindowUnblocked") { + return VMManagerProtocol::ClientMessage::WindowUnblocked; + } else if (message_type == "RunningStateChanged") { + return VMManagerProtocol::ClientMessage::RunningStateChanged; + } + return VMManagerProtocol::ClientMessage::UnknownMessage; +} +VMManagerProtocol::ManagerMessage +VMManagerProtocol::getManagerMessageType(const QJsonObject &json_document) +{ + // FIXME: This key ("message") is hardcoded here. Make a hash which maps these + // required values. + QString message_type = json_document.value("message").toString(); + // Can't use switch with strings, manual compare + if (message_type == "RequestStatus") { + return VMManagerProtocol::ManagerMessage::RequestStatus; + } else if (message_type == "Pause") { + return VMManagerProtocol::ManagerMessage::Pause; + } if (message_type == "CtrlAltDel") { + return VMManagerProtocol::ManagerMessage::CtrlAltDel; + } if (message_type == "ShowSettings") { + return VMManagerProtocol::ManagerMessage::ShowSettings; + } if (message_type == "ResetVM") { + return VMManagerProtocol::ManagerMessage::ResetVM; + } if (message_type == "RequestShutdown") { + return VMManagerProtocol::ManagerMessage::RequestShutdown; + } if (message_type == "ForceShutdown") { + return VMManagerProtocol::ManagerMessage::ForceShutdown; + } + return VMManagerProtocol::ManagerMessage::UnknownMessage; +} +QJsonObject +VMManagerProtocol::getParams(const QJsonObject &json_document) +{ + // FIXME: This key ("params") is hardcoded here. Make a hash which maps these + // required values. + auto params_object = json_document.value("params"); + if (params_object.type() != QJsonValue::Object) { + return {}; + } + return params_object.toObject(); +} diff --git a/src/qt/qt_vmmanager_protocol.hpp b/src/qt/qt_vmmanager_protocol.hpp new file mode 100644 index 000000000..48f0a2d8f --- /dev/null +++ b/src/qt/qt_vmmanager_protocol.hpp @@ -0,0 +1,93 @@ +/* +* 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. +* +* Header for 86Box VM manager protocol module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#ifndef QT_VMMANAGER_PROTOCOL_H +#define QT_VMMANAGER_PROTOCOL_H + +#include <QJsonObject> +extern "C" { +#include <86box/version.h> +} + +static QVector<QString> ProtocolRequiredFields = { "type", "message" }; + +class VMManagerProtocol : QObject { + Q_OBJECT + +public: + enum class Sender { + Manager, + Client, + }; + Q_ENUM(Sender); + + enum class ManagerMessage { + RequestStatus, + Pause, + CtrlAltDel, + ShowSettings, + ResetVM, + RequestShutdown, + ForceShutdown, + UnknownMessage, + }; + + // This macro allows us to do a reverse lookup of the enum with `QMetaEnum` + Q_ENUM(ManagerMessage); + + enum class ClientMessage { + Status, + WindowBlocked, + WindowUnblocked, + RunningStateChanged, + UnknownMessage, + }; + Q_ENUM(ClientMessage); + + enum class WindowStatus { + WindowUnblocked = 0, + WindowBlocked, + }; + + enum class RunningState { + Running = 0, + Paused, + RunningWaiting, + PausedWaiting, + Unknown, + }; + Q_ENUM(RunningState); + + explicit VMManagerProtocol(Sender sender); + ~VMManagerProtocol(); + + QJsonObject protocolManagerMessage(ManagerMessage message_type); + QJsonObject protocolClientMessage(ClientMessage message_type); + static QString managerMessageTypeToString(ManagerMessage message); + static QString clientMessageTypeToString(ClientMessage message); + + static bool hasRequiredFields(const QJsonObject &json_document); + static QJsonObject getParams(const QJsonObject &json_document); + static ClientMessage getClientMessageType(const QJsonObject &json_document); + static ManagerMessage getManagerMessageType(const QJsonObject &json_document); + +private: + Sender message_class; + static QJsonObject constructDefaultObject(VMManagerProtocol::Sender type); +}; + +#endif // QT_VMMANAGER_PROTOCOL_H diff --git a/src/qt/qt_vmmanager_serversocket.cpp b/src/qt/qt_vmmanager_serversocket.cpp new file mode 100644 index 000000000..50ff352d6 --- /dev/null +++ b/src/qt/qt_vmmanager_serversocket.cpp @@ -0,0 +1,207 @@ +/* +* 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. +* +* 86Box VM manager server socket module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#include "qt_vmmanager_serversocket.hpp" +#include <QApplication> +#include <QCryptographicHash> +#include <QJsonParseError> +#include <QMetaEnum> +#include <QStandardPaths> +#include <utility> + +VMManagerServerSocket::VMManagerServerSocket(const QFileInfo &config_path, const ServerType type) +{ + server_type = type; + config_file = config_path; + serverIsRunning = false; + socket = nullptr; + server = new QLocalServer; + setupVars(); +} + +VMManagerServerSocket::~VMManagerServerSocket() +{ + delete server; +} + +bool +VMManagerServerSocket::startServer() { + + // Remove socket file (if it exists) in order to start a new one + qInfo("Socket path is %s", qPrintable(socket_path.filePath())); + if (socket_path.exists() and !socket_path.isDir()) { + auto socket_file = new QFile(socket_path.filePath()); + if (!socket_file->remove()) { + qInfo("Failed to remove the old socket file (Error %i): %s", socket_file->error(), qPrintable(socket_file->errorString())); + return false; + } + } + + if (server->listen(socket_path.fileName())) { + serverIsRunning = true; + connect(server, &QLocalServer::newConnection, this, &VMManagerServerSocket::serverConnectionReceived); + return true; + } else { + qInfo("Failed to start server: %s", qPrintable(server->errorString())); + serverIsRunning = false; + return false; + } +} + +void +VMManagerServerSocket::serverConnectionReceived() { + qDebug("Connection received on %s", qPrintable(socket_path.fileName())); + socket = server->nextPendingConnection(); + if(!socket) { + qInfo("Invalid socket when trying to receive the connection"); + return; + } + connect(socket, &QLocalSocket::readyRead, this, &VMManagerServerSocket::serverReceivedMessage); + connect(socket, &QLocalSocket::disconnected, this, &VMManagerServerSocket::serverDisconnected); +} + +void +VMManagerServerSocket::serverReceivedMessage() { + + // Handle legacy socket connections first. These connections only receive + // information on window status + if(server_type == VMManagerServerSocket::ServerType::Legacy) { + QByteArray tempString = socket->read(1); + int window_obscured = tempString.toInt(); + emit windowStatusChanged(window_obscured); + return; + } + + // Normal connections here + QDataStream stream(socket); + stream.setVersion(QDataStream::Qt_5_7); + QByteArray jsonData; + for (;;) { + // Start a transaction + stream.startTransaction(); + // Try to read the data + stream >> jsonData; + if (stream.commitTransaction()) { + QJsonParseError parse_error{}; + // Validate the received data to make sure it's valid json + const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parse_error); + if (parse_error.error == QJsonParseError::NoError) { + // The data received was valid json + if (jsonDoc.isObject()) { + // The data is a valid json object + emit dataReceived(); + jsonReceived(jsonDoc.object()); + } + } + // The data was not valid json. + // Loop and try to read more data + } else { + // read failed, socket is reverted to its previous state (before the transaction) + // exit the loop and wait for more data to become available + break; + } + } +} + +void +VMManagerServerSocket::serverSendMessage(VMManagerProtocol::ManagerMessage protocol_message, const QStringList& arguments) const { + if(!socket) { + qInfo("Cannot send message: Invalid socket"); + return; + } + + // Regular connection + QDataStream stream(socket); + stream.setVersion(QDataStream::Qt_5_7); + auto packet = new VMManagerProtocol(VMManagerProtocol::Sender::Manager); + auto jsonMessage = packet->protocolManagerMessage(protocol_message); + stream << QJsonDocument(jsonMessage).toJson(QJsonDocument::Compact); +} + +void +VMManagerServerSocket::serverDisconnected() +{ + qInfo("Connection disconnected"); +} +void +VMManagerServerSocket::jsonReceived(const QJsonObject &json) +{ + // The serialization portion has already validated the message as json. + // Now ensure it has the required fields. + if (!VMManagerProtocol::hasRequiredFields(json)) { + // TODO: Error handling of some sort, emit signals + qDebug("Invalid message received from client: required fields missing. Object:"); + qDebug() << json; + return; + } +// qDebug().noquote() << Q_FUNC_INFO << json; + QJsonObject params_object; + + auto message_type = VMManagerProtocol::getClientMessageType(json); + switch (message_type) { + case VMManagerProtocol::ClientMessage::Status: + qDebug("Status message received from client"); + break; + case VMManagerProtocol::ClientMessage::WindowBlocked: + qDebug("Window blocked message received from client"); + emit windowStatusChanged(static_cast<int>(VMManagerProtocol::WindowStatus::WindowBlocked)); + break; + case VMManagerProtocol::ClientMessage::WindowUnblocked: + qDebug("Window unblocked received from client"); + emit windowStatusChanged(static_cast<int>(VMManagerProtocol::WindowStatus::WindowUnblocked)); + break; + case VMManagerProtocol::ClientMessage::RunningStateChanged: + qDebug("Running state change received from client"); + params_object = VMManagerProtocol::getParams(json); + if (!params_object.isEmpty()) { + // valid object + if(params_object.value("status").type() == QJsonValue::Double) { + // has status key, value is an int (qt assigns it as Double) + emit runningStatusChanged(static_cast<VMManagerProtocol::RunningState>(params_object.value("status").toInt())); + } + } + break; + default: + qDebug("Unknown client message type received:"); + qDebug() << json; + return; + } +} + +void +VMManagerServerSocket::setupVars() +{ + QString unique_name = QCryptographicHash::hash(config_file.path().toUtf8().constData(), QCryptographicHash::Algorithm::Sha256).toHex().right(6); + socket_path.setFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + QApplication::applicationName() + ".socket." + unique_name); +} + +QString +VMManagerServerSocket::getSocketPath() const +{ + if (server) { + return server->fullServerName(); + } + return {}; +} + +QString +VMManagerServerSocket::serverTypeToString(VMManagerServerSocket::ServerType server_type_lookup) +{ + QMetaEnum qme = QMetaEnum::fromType<VMManagerServerSocket::ServerType>(); + return qme.valueToKey(static_cast<int>(server_type_lookup)); + +} diff --git a/src/qt/qt_vmmanager_serversocket.hpp b/src/qt/qt_vmmanager_serversocket.hpp new file mode 100644 index 000000000..3e6e43a80 --- /dev/null +++ b/src/qt/qt_vmmanager_serversocket.hpp @@ -0,0 +1,82 @@ +/* +* 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. +* +* Header for 86Box VM manager server socket module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed + */ + +#ifndef QT_VMMANAGER_SERVERSOCKET_H +#define QT_VMMANAGER_SERVERSOCKET_H + +#include <QFileInfo> +#include <QLocalServer> +#include <QLocalSocket> +#include <QWidget> +#include <QJsonObject> +#include "qt_vmmanager_protocol.hpp" + +// This macro helps give us the required `qHash()` function in order to use the +// enum as a hash key +#define QHASH_FOR_CLASS_ENUM(T) \ +inline uint qHash(const T &t, uint seed) { \ + return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \ +} + +class VMManagerServerSocket : public QWidget { + + Q_OBJECT + +public: + + enum class ServerType { + Standard, + Legacy, + }; + // This macro allows us to do a reverse lookup of the enum with `QMetaEnum` + Q_ENUM(ServerType) + + QHASH_FOR_CLASS_ENUM(ServerType) + + explicit VMManagerServerSocket(const QFileInfo &config_path, ServerType type = ServerType::Standard); + ~VMManagerServerSocket() override; + + QFileInfo socket_path; + QFileInfo config_file; + + QLocalServer *server; + QLocalSocket *socket; + ServerType server_type; + bool serverIsRunning; + + // Server functions + bool startServer(); + void serverConnectionReceived(); + void serverReceivedMessage(); + void serverSendMessage(VMManagerProtocol::ManagerMessage protocol_message, const QStringList& arguments = QStringList()) const; + static void serverDisconnected(); + void jsonReceived(const QJsonObject &json); + QString getSocketPath() const; + + static QString serverTypeToString(ServerType server_type_lookup); + + void setupVars(); + +signals: + void dataReceived(); + void windowStatusChanged(int status); + void runningStatusChanged(VMManagerProtocol::RunningState state); + + +}; + +#endif // QT_VMMANAGER_SERVERSOCKET_H diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp new file mode 100644 index 000000000..a28e27892 --- /dev/null +++ b/src/qt/qt_vmmanager_system.cpp @@ -0,0 +1,888 @@ +/* +* 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. +* +* 86Box VM manager system module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#include <QString> +#include <QDirIterator> +#include <QDebug> +#include <QTimer> +#include <QSettings> +#include <QApplication> +#include <QStandardPaths> +#include <QCryptographicHash> +#include <QtNetwork> +#include <QElapsedTimer> +#include "qt_vmmanager_system.hpp" +// #include "qt_vmmanager_details_section.hpp" +#include "qt_vmmanager_detailsection.hpp" + + +extern "C" { +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/video.h> +// #include <86box/vid_xga_device.h> +#include <86box/machine.h> +#include <86box/plat.h> +#include <86box/sound.h> +#include <cpu.h> +#include <86box/thread.h> // required for network.h +#include <86box/timer.h> // required for network.h and fdd.h +#include <86box/cdrom.h> +#include <86box/scsi.h> +#include <86box/fdd.h> +#include <86box/gameport.h> +#include <86box/midi.h> +#include <86box/network.h> +#include <86box/mouse.h> +} + +VMManagerSystem::VMManagerSystem(const QString &sysconfig_file) { + + // The 86Box configuration file + config_file = QFileInfo(sysconfig_file); + // The default name of the system. This is the name of the directory + // that contains the 86box configuration file + config_name = config_file.dir().dirName(); + // The full path of the directory that contains the 86box configuration file + config_dir = shortened_dir = config_file.dir().path(); + process_status = ProcessStatus::Stopped; + // Main 86Box uses usr_path for UUID which includes the trailing slash. + // Make sure to append the slash here so the UUIDs will match + auto uuid_path = config_dir; + if (!uuid_path.endsWith("/")) { + uuid_path.append("/"); + } + // In the configuration file the UUID is used as a unique value + uuid = QUuid::createUuidV5(QUuid{}, uuid_path).toString(QUuid::WithoutBraces); + // That unique value is used to map the information to each individual system. + config_settings = new VMManagerConfig(VMManagerConfig::ConfigType::System, uuid); + + // On non-windows platforms, shortened_dir will replace the home directory path with ~ + // and be used as the tool tip in the list view +#if not defined(Q_OS_WINDOWS) + if (config_dir.startsWith(QDir::homePath())) { + shortened_dir.replace(QDir::homePath(), "~"); + } +#endif + loadSettings(); + setupPaths(); + // Paths must be setup before vars! + setupVars(); + + serverIsRunning = false; + window_obscured = false; + + find86BoxBinary(); + platform = QApplication::platformName(); + process = new QProcess(); + connect(process, &QProcess::stateChanged, this, &VMManagerSystem::processStatusChanged); + + // Server type for this instance (Standard should always be used instead of Legacy) + socket_server_type = VMManagerServerSocket::ServerType::Standard; + socket_server = new VMManagerServerSocket(config_file, socket_server_type); + + // NOTE: When unique names or UUIDs are written to the individual VM config file, use that + // here instead of the auto-generated unique_name + // Save settings once everything is initialized + saveSettings(); +} + +VMManagerSystem::~VMManagerSystem() { + delete socket_server; +} + +QVector<VMManagerSystem *> +VMManagerSystem::scanForConfigs(const QString &searchPath) +{ + QElapsedTimer scanTimer; + scanTimer.start(); + QVector<VMManagerSystem *> system_configs; + + const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); + auto systemDirConfig = config->getStringValue("system_directory"); + + const auto config_file_name = QString("86box.cfg"); + const QStringList filters = {config_file_name}; + QStringList matches; + // TODO: Preferences. Once I get the CLI args worked out. + // For now it just takes vmm_path from the CLI + QString search_directory; + // if(searchPath.isEmpty()) { + // // If the location isn't specified in function call, use the one loaded + // // from the config file + // search_directory = systemDirConfig; + // } else { + // search_directory = searchPath; + // } + + search_directory = searchPath.isEmpty()? vmm_path : searchPath; + + if(!QDir(search_directory).exists()) { + qWarning() << "Path" << search_directory << "does not exist. Cannot continue"; + return {}; + } + + QDirIterator dir_iterator(search_directory, filters, QDir::Files, QDirIterator::Subdirectories); + + qInfo("Searching %s for %s", qPrintable(search_directory), qPrintable(config_file_name)); + + QElapsedTimer timer; + timer.start(); + while (dir_iterator.hasNext()) { + QString filename = dir_iterator.next(); + matches.append(filename); + } + + const auto scanElapsed = timer.elapsed(); + qDebug().noquote().nospace() << "Found " << matches.size() << " configs in " << search_directory <<". Scan took " << scanElapsed << " ms"; + + timer.restart(); + // foreach (QFileInfo hit, matches) { + // system_configs.append(new VMManagerSystem(hit)); + // } + for (const auto &filename : matches) { + system_configs.append(new VMManagerSystem(filename)); + } + auto elapsed = timer.elapsed(); + qDebug() << "Load loop took" << elapsed << "ms for" << matches.size() << "loads"; + qDebug() << "Overall scan time was" << scanTimer.elapsed() << "ms, average" << elapsed / matches.size() << "ms / load"; + return system_configs; +} + +QString +VMManagerSystem::generateTemporaryFilename() +{ + QTemporaryFile tempFile; + // File will be closed once the QTemporaryFile object goes out of scope + tempFile.setAutoRemove(true); + tempFile.open(); + return tempFile.fileName(); +} + +QFileInfoList +VMManagerSystem::getScreenshots() { + + // Don't bother unless the directory exists + if(!screenshot_directory.exists()) { + return {}; + } + + auto screen_scan_dir = QDir(screenshot_directory.path(), "Monitor_1*", QDir::SortFlag::LocaleAware | QDir::SortFlag::IgnoreCase, QDir::Files); + auto screenshot_files = screen_scan_dir.entryInfoList(); + return screenshot_files; +} + +void +VMManagerSystem::loadSettings() +{ + // First, load the information from the 86box.cfg + QSettings settings(config_file.filePath(), QSettings::IniFormat); + if (settings.status() != QSettings::NoError) { + qWarning() << "Error loading" << config_file.path() << " status:" << settings.status(); + } + // qInfo() << "Loaded "<< config_file.filePath() << "status:" << settings.status(); + + // Clear out the config hash in case the config is reloaded + for (const auto &outer_key : config_hash.keys()) { + config_hash[outer_key].clear(); + } + + // General + for (const auto &key_name : settings.childKeys()) { + config_hash["General"][key_name] = settings.value(key_name).toString(); + } + + for (auto &group_name : settings.childGroups()) { + settings.beginGroup(group_name); + for (const auto &key_name : settings.allKeys()) { + QString setting_value; + // QSettings will interpret lines with commas as QStringList. + // Check for it and join them back to a string. + if (settings.value(key_name).type() == QVariant::StringList) { + setting_value = settings.value(key_name).toStringList().join(", "); + } else { + setting_value = settings.value(key_name).toString(); + } + config_hash[group_name][key_name] = setting_value; + } + settings.endGroup(); + } + + // Next, load the information from the vmm config for this system + // Display name + auto loadedDisplayName = config_settings->getStringValue("display_name"); + if (!loadedDisplayName.isEmpty()) { + displayName = loadedDisplayName; + } else { + displayName = config_name; + } + // Notes + auto loadedNotes = config_settings->getStringValue("notes"); + if (!loadedNotes.isEmpty()) { + notes = loadedNotes; + } + // Timestamp + auto loadedTimestamp = config_settings->getStringValue("timestamp"); + if (!loadedTimestamp.isEmpty()) { + // Make sure it is valid + if (auto newTimestamp = QDateTime::fromString(loadedTimestamp, Qt::ISODate); newTimestamp.isValid()) { + lastUsedTimestamp = newTimestamp; + } + } + // Icon + auto loadedIcon = config_settings->getStringValue("icon"); + if (!loadedIcon.isEmpty()) { + icon = loadedIcon; + } +} +void +VMManagerSystem::saveSettings() +{ + if(!isValid()) { + return; + } + config_settings->setStringValue("system_name", config_name); + config_settings->setStringValue("config_file", config_file.canonicalFilePath()); + config_settings->setStringValue("config_dir", config_file.canonicalPath()); + if (displayName != config_name) { + config_settings->setStringValue("display_name", displayName); + } else { + config_settings->remove("display_name"); + } + + config_settings->setStringValue("notes", notes); + if(lastUsedTimestamp.isValid()) { + config_settings->setStringValue("timestamp", lastUsedTimestamp.toString(Qt::ISODate)); + } + config_settings->setStringValue("icon", icon); + generateSearchTerms(); +} +void +VMManagerSystem::generateSearchTerms() +{ + searchTerms.clear(); + for (const auto &config_key : config_hash.keys()) { + // searchTerms.append(config_hash[config_key].values()); + // brute force temporarily don't add paths + for(const auto &value: config_hash[config_key].values()) { + if(!value.startsWith("/")) { + searchTerms.append(value); + } + } + } + searchTerms.append(display_table.values()); + searchTerms.append(displayName); + searchTerms.append(config_name); + QRegularExpression whitespaceRegex("\\s+"); + searchTerms.append(notes.split(whitespaceRegex)); +} +void +VMManagerSystem::updateTimestamp() +{ + lastUsedTimestamp = QDateTime::currentDateTimeUtc(); + saveSettings(); +} + +QString +VMManagerSystem::getAll(const QString& category) const { + auto value = config_hash[category].keys().join(", "); + return value; +} + +QHash<QString, QHash<QString, QString>> +VMManagerSystem::getConfigHash() const +{ + return config_hash; +} + +void +VMManagerSystem::setDisplayName(const QString &newDisplayName) +{ + // If blank, reset to the default + if (newDisplayName.isEmpty()) { + displayName = config_name; + } else { + displayName = newDisplayName; + } + saveSettings(); +} +void +VMManagerSystem::setNotes(const QString &newNotes) +{ + notes = newNotes; + saveSettings(); +} +bool +VMManagerSystem::isValid() const +{ + return config_file.exists() && config_file.isFile() && config_file.size() != 0; +} + +bool +VMManagerSystem::isProcessRunning() const +{ + return process->processId() != 0; +} + +qint64 +VMManagerSystem::processId() const +{ + return process->processId(); +} + +QHash<QString, QString> +VMManagerSystem::getCategory(const QString &category) const { + return config_hash[category]; +} + +void +VMManagerSystem::find86BoxBinary() { + // We'll use our own self to launch the VMs + main_binary = QFileInfo(QCoreApplication::applicationFilePath()); +} + +bool +VMManagerSystem::has86BoxBinary() { + return main_binary.exists(); +} + +void +VMManagerSystem::launchMainProcess() { + + if(!has86BoxBinary()) { + qWarning("No binary found! returning"); + return; + } + + // start the server first to get the socket name + if (!serverIsRunning) { + if(!startServer()) { + // FIXME: Better error handling + qInfo("Failed to start VM Manager server"); + return; + } + } + setProcessEnvVars(); + QString program = main_binary.filePath(); + QStringList args; + args << "-P" << config_dir; + args << "--vmname" << displayName; + process->setProgram(program); + process->setArguments(args); + qDebug() << Q_FUNC_INFO << " Full Command:" << process->program() << " " << process->arguments(); + process->start(); + updateTimestamp(); +} + +void +VMManagerSystem::startButtonPressed() { + launchMainProcess(); +} + +void +VMManagerSystem::launchSettings() { + if(!has86BoxBinary()) { + qWarning("No binary found! returning"); + return; + } + + // If the system is already running, instruct it to show settings + if (process->processId() != 0) { + socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::ShowSettings); + return; + } + + // Otherwise, launch the system with the settings parameter + setProcessEnvVars(); + QString program = main_binary.filePath(); + QStringList open_command_args; + QStringList args; + args << "-P" << config_dir << "-S"; + process->setProgram(program); + process->setArguments(args); + qDebug() << Q_FUNC_INFO << " Full Command:" << process->program() << " " << process->arguments(); + process->start(); +} + +void +VMManagerSystem::setupPaths() { + // application_temp_directory.setPath(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + // standard_temp_directory.setPath(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + // QString temp_subdir = QApplication::applicationName(); + // if (!application_temp_directory.exists(temp_subdir)) { + // // FIXME: error checking + // application_temp_directory.mkdir(temp_subdir); + // } + // // QT always replaces `/` with native separators, so it is safe to use here for all platforms + // application_temp_directory.setPath(application_temp_directory.path() + "/" + temp_subdir); + // app_data_directory.setPath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + // // TODO: come back here and update with the new plat_get_global_* + // if (!app_data_directory.exists()) { + // // FIXME: Error checking + // app_data_directory.mkpath(app_data_directory.path()); + // } + screenshot_directory.setPath(config_dir + "/" + "screenshots"); +} + +void +VMManagerSystem::setupVars() { + unique_name = QCryptographicHash::hash(config_file.path().toUtf8().constData(), QCryptographicHash::Algorithm::Sha256).toHex().right(9); + // unique_name = "aaaaaa"; + // Set up the display vars + // This will likely get moved out to its own class + // This will likely get moved out to its own class + auto machine_config = getCategory("Machine"); + auto video_config = getCategory("Video"); + auto disk_config = getCategory("Hard disks"); + auto audio_config = getCategory("Sound"); + auto network_config = getCategory("Network"); + auto input_config = getCategory("Input devices"); + auto floppy_cdrom_config = getCategory("Floppy and CD-ROM drives"); + auto scsi_config = getCategory("Storage controllers"); + auto ports_config = getCategory("Ports (COM & LPT)"); + // auto general_config = getCategory("General"); + // auto config_uuid = QString("Not set"); + // if(!general_config["uuid"].isEmpty()) { + // config_uuid = general_config["uuid"]; + // qDebug() << "btw config dir:" << config_dir; + // } + // qDebug() << "Generated UUID:" << uuid; + // qDebug() << "Config file UUID:" << config_uuid; + auto machine_name = QString(); + int i = 0; + int ram_granularity = 0; + // Machine + for (int ci = 0; ci < machine_count(); ++ci) { + if (machine_available(ci)) { + if (machines[ci].internal_name == machine_config["machine"]) { + machine_name = machines[ci].name; + ram_granularity = machines[ci].ram.step; + } + } + } + display_table[Display::Name::Machine] = machine_name; + + // CPU: Combine name with speed + auto cpu_name = QString(); + while (cpu_families[i].package != 0) { + if (cpu_families[i].internal_name == machine_config["cpu_family"]) { + cpu_name = QString("%1 %2").arg(cpu_families[i].manufacturer, cpu_families[i].name); + } + i++; + } + int speed_display = machine_config["cpu_speed"].toInt() / 1000000; + cpu_name.append(QString::number(speed_display).prepend(" / ")); + cpu_name.append(QCoreApplication::translate("", "MHz").prepend(' ')); + display_table[Display::Name::CPU] = cpu_name; + + // Memory + int divisor = (ram_granularity < 1024) ? 1 : 1024; + QString display_unit = (divisor == 1) ? "KB" : "MB"; + auto mem_display = QString::number(machine_config["mem_size"].toInt() / divisor); + mem_display.append(QCoreApplication::translate("", display_unit.toUtf8().constData()).prepend(' ')); + display_table[Display::Name::Memory] = mem_display; + + // Video card + int video_int = video_get_video_from_internal_name(video_config["gfxcard"].toUtf8().data()); + const device_t* video_dev = video_card_getdevice(video_int); + display_table[Display::Name::Video] = DeviceConfig::DeviceName(video_dev, video_get_internal_name(video_int), 1); + if (!video_config["voodoo"].isEmpty()) { + // FIXME: Come back to this later to add more for secondary video +// display_table[Display::Name::Video].append(" (with voodoo)"); + display_table[Display::Name::Voodoo] = "Voodoo enabled"; + } + + // Drives + // First the number of disks + QMap<QString, int> disks; + for(const auto& key: disk_config.keys()) { + // Assuming the format hdd_NN_* + QStringList pieces = key.split('_'); + QString disk = QString("%1_%2").arg(pieces.at(0), pieces.at(1)); + if(!disk.isEmpty()) { + disks[disk] = 1; + } + } + // Next, the types + QHash<QString, int> bus_types; + for (const auto& key: disks.keys()) { + auto disk_parameter_key = QString("%1_parameters").arg(key); + QStringList pieces = disk_config[disk_parameter_key].split(","); + QString bus_type = pieces.value(pieces.length() - 1).trimmed(); + bus_types[bus_type] = 1; + } + QString disks_display = tr("%n disk(s)", "", disks.count()); + if (disks.count()) { + disks_display.append(" / ").append(bus_types.keys().join(", ").toUpper()); + } +// display_table[Display::Name::Disks] = disks_display; + + // Drives + QString new_disk_display; + for (const auto& key: disks.keys()) { + auto disk_parameter_key = QString("%1_parameters").arg(key); + // Converting a string to an int back to a string to remove the zero (e.g. 01 to 1) + auto disk_number = QString::number(key.split("_").last().toInt()); + QStringList pieces = disk_config[disk_parameter_key].split(","); + QString sectors = pieces.value(0).trimmed(); + QString heads = pieces.value(1).trimmed(); + QString cylinders = pieces.value(2).trimmed(); + QString bus_type = pieces.value(pieces.length() - 1).trimmed(); + // Add separator for each subsequent value, skipping the first + if(!new_disk_display.isEmpty()) { + new_disk_display.append(QString("%1").arg(VMManagerDetailSection::sectionSeparator)); + } + int diskSizeRaw = (cylinders.toInt() * heads.toInt() * sectors.toInt()) >> 11; + QString diskSizeFinal; + QString unit = "MiB"; + if(diskSizeRaw > 1000) { + unit = "GiB"; + diskSizeFinal = QString::number(diskSizeRaw * 1.0 / 1000, 'f', 1); + } else { + diskSizeFinal = QString::number(diskSizeRaw); + } + // Only prefix each disk when there are multiple disks + QString diskNumberDisplay = disks.count() > 1 ? QString("Disk %1: ").arg(disk_number) : ""; + new_disk_display.append(QString("%1%2 %3 (%4)").arg(diskNumberDisplay, diskSizeFinal, unit, bus_type.toUpper())); + } + if(new_disk_display.isEmpty()) { + new_disk_display = "No disks"; + } + display_table[Display::Name::Disks] = new_disk_display; + + // Floppy & CD-ROM + QStringList floppyDevices; + QStringList cdromDevices; + static auto floppy_match = QRegularExpression("fdd_\\d\\d_type", QRegularExpression::CaseInsensitiveOption); + static auto cdrom_match = QRegularExpression("cdrom_\\d\\d_type", QRegularExpression::CaseInsensitiveOption); + for(const auto& key: floppy_cdrom_config.keys()) { + if(key.contains(floppy_match)) { + // auto device_number = key.split("_").at(1); + auto floppy_internal_name = QString(floppy_cdrom_config[key]); + // Not interested in the nones + if(floppy_internal_name == "none") { + continue; + } + auto floppy_type = fdd_get_from_internal_name(floppy_internal_name.toUtf8().data()); + if(auto fddName = QString(fdd_getname(floppy_type)); !fddName.isEmpty()) { + floppyDevices.append(fddName); + } + } + if(key.contains(cdrom_match)) { + auto device_number = key.split("_").at(1); + auto cdrom_internal_name = QString(floppy_cdrom_config[key]); + auto cdrom_type = cdrom_get_from_internal_name(cdrom_internal_name.toUtf8().data()); + + auto cdrom_speed_key = QString("cdrom_%1_speed").arg(device_number); + auto cdrom_parameters_key = QString("cdrom_%1_parameters").arg(device_number); + auto cdrom_speed = QString(floppy_cdrom_config[cdrom_speed_key]); + auto cdrom_parameters = QString(floppy_cdrom_config[cdrom_parameters_key]); + auto cdrom_bus = cdrom_parameters.split(",").at(1).trimmed().toUpper(); + + if(auto cdromName = QString(cdrom_getname(cdrom_type)); !cdromName.isEmpty()) { + if(!cdrom_speed.isEmpty()) { + cdrom_speed = QString("%1x ").arg(cdrom_speed); + } + if(!cdrom_bus.isEmpty()) { + cdrom_bus = QString(" (%1)").arg(cdrom_bus); + } + cdromDevices.append(QString("%1%2%3").arg(cdrom_speed, cdromName, cdrom_bus)); + } + } + } + + display_table[Display::Name::Floppy] = floppyDevices.join(VMManagerDetailSection::sectionSeparator); + display_table[Display::Name::CD] = cdromDevices.join(VMManagerDetailSection::sectionSeparator); + + // SCSI controllers + QStringList scsiControllers; + static auto scsi_match = QRegularExpression("scsicard_\\d", QRegularExpression::CaseInsensitiveOption); + for(const auto& key: scsi_config.keys()) { + if(key.contains(scsi_match)) { + auto device_number = key.split("_").at(1); + auto scsi_internal_name = QString(scsi_config[key]); + auto scsi_id = scsi_card_get_from_internal_name(scsi_internal_name.toUtf8().data()); + auto scsi_device = scsi_card_getdevice(scsi_id); + auto scsi_name = QString(scsi_device->name); + if(!scsi_name.isEmpty()) { + scsiControllers.append(scsi_name); + } + } + } + display_table[Display::Name::SCSIController] = scsiControllers.join(VMManagerDetailSection::sectionSeparator); + + // Audio + int sound_int = sound_card_get_from_internal_name(audio_config["sndcard"].toUtf8().data()); + const device_t* audio_dev = sound_card_getdevice(sound_int); + display_table[Display::Name::Audio] = DeviceConfig::DeviceName(audio_dev, sound_card_get_internal_name(sound_int), 1); + + // MIDI + QString midiOutDev; + if(auto midi_out_device = QString(audio_config["midi_device"]); !midi_out_device.isEmpty()) { + auto midi_device_int = midi_out_device_get_from_internal_name(midi_out_device.toUtf8().data()); + auto midi_out = midi_out_device_getdevice(midi_device_int); + if(auto midiDevName = QString(midi_out->name); !midiDevName.isEmpty()) { + midiOutDev = midiDevName; + } + } + display_table[Display::Name::MidiOut] = midiOutDev; + + // midi_device = mt32 (output) + // mpu401_standalone = 1 + // midi_in_device (input) + + // Network + QString nicList; + static auto nic_match = QRegularExpression("net_\\d\\d_card", QRegularExpression::CaseInsensitiveOption); + for(const auto& key: network_config.keys()) { + if(key.contains(nic_match)) { + auto device_number = key.split("_").at(1); + auto nic_internal_name = QString(network_config[key]); + auto nic_id = network_card_get_from_internal_name(nic_internal_name.toUtf8().data()); + auto nic = network_card_getdevice(nic_id); + auto nic_name = QString(nic->name); + // Add separator for each subsequent value, skipping the first + if(!nicList.isEmpty()) { + nicList.append(QString("%1").arg(VMManagerDetailSection::sectionSeparator)); + } + auto net_type_key = QString("net_%1_net_type").arg(device_number); + auto net_type = network_config[net_type_key]; + if (!net_type.isEmpty()) { + nicList.append(nic_name + " (" + net_type + ")"); + } else { + nicList.append(nic_name); + } + + } + } + if(nicList.isEmpty()) { + nicList = "None"; + } + display_table[Display::Name::NIC] = nicList; + + // Input (Mouse) + auto mouse_internal_name = input_config["mouse_type"]; + auto mouse_dev = mouse_get_from_internal_name(mouse_internal_name.toUtf8().data()); + auto mouse_dev_name = mouse_get_name(mouse_dev); + display_table[Display::Name::Mouse] = mouse_dev_name; + + // Input (joystick) + QString joystickDevice; + if(auto joystick_internal = QString(input_config["joystick_type"]); !joystick_internal.isEmpty()) { + auto joystick_dev = joystick_get_from_internal_name(joystick_internal.toUtf8().data()); + if (auto joystickName = QString(joystick_get_name(joystick_dev)); !joystickName.isEmpty()) { + joystickDevice = joystickName; + } + } + display_table[Display::Name::Joystick] = joystickDevice; + + // # Ports + // Serial + // By default serial 1 and 2 are enabled unless otherwise specified + static auto serial_match = QRegularExpression("serial\\d_enabled", QRegularExpression::CaseInsensitiveOption); + QList<bool> serial_enabled = {true, true, false, false}; + // Parallel + // By default lpt 1 is enabled unless otherwise specified + static auto lpt_match = QRegularExpression("lpt\\d_enabled", QRegularExpression::CaseInsensitiveOption); + QList<bool> lpt_enabled = {true, false, false, false}; + for (const auto &key: ports_config.keys()) { + if (key.contains(serial_match)) { + if (auto serial_dev = key.split("_").at(0); !serial_dev.isEmpty()) { + auto serial_num = serial_dev.at(serial_dev.size() - 1); + // qDebug() << "serial is set" << key << ":" << ports_config[key]; + if(serial_num.isDigit() && serial_num.digitValue() >= 1 && serial_num.digitValue() <= 4) { + // Already verified that it is a digit with isDigit() + serial_enabled[serial_num.digitValue() - 1] = ports_config[key].toInt() == 1; + } + } + } + if (key.contains(lpt_match)) { + if (auto lpt_dev = key.split("_").at(0); !lpt_dev.isEmpty()) { + auto lpt_num = lpt_dev.at(lpt_dev.size() - 1); + // qDebug() << "lpt is set" << key << ":" << ports_config[key]; + if (lpt_num.isDigit() && lpt_num.digitValue() >= 1 && lpt_num.digitValue() <= 4) { + lpt_enabled[lpt_num.digitValue() - 1] = ports_config[key].toInt() == 1; + } + } + } + } + // qDebug() << "ports final" << serial_enabled << lpt_enabled; + QStringList serialFinal; + QStringList lptFinal; + int portIndex = 0; + for(const auto &serialNum: serial_enabled) { + if (serial_enabled[portIndex]) { + serialFinal.append(QString("COM%1").arg(portIndex + 1)); + } + ++portIndex; + } + portIndex = 0; + for (const auto &lptNum: lpt_enabled) { + if (lpt_enabled[portIndex]) { + lptFinal.append(QString("LPT%1").arg(portIndex + 1)); + } + ++portIndex; + } + display_table[Display::Name::Serial] = serialFinal.empty() ? tr("None") : serialFinal.join(", "); + display_table[Display::Name::Parallel] = lptFinal.empty() ? tr("None") : lptFinal.join(", "); + +} + +bool +VMManagerSystem::startServer() { + if (socket_server->startServer()) { + serverIsRunning = true; + connect(socket_server, &VMManagerServerSocket::dataReceived, this, &VMManagerSystem::dataReceived); + connect(socket_server, &VMManagerServerSocket::windowStatusChanged, this, &VMManagerSystem::windowStatusChangeReceived); + connect(socket_server, &VMManagerServerSocket::runningStatusChanged, this, &VMManagerSystem::runningStatusChangeReceived); + return true; + } else { + return false; + } +} + +void +VMManagerSystem::setProcessEnvVars() { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString env_var_name = (socket_server_type == VMManagerServerSocket::ServerType::Standard) ? "VMM_86BOX_SOCKET" : "86BOX_MANAGER_SOCKET"; + env.insert(env_var_name, socket_server->getSocketPath()); + process->setProcessEnvironment(env); +} + +void +VMManagerSystem::restartButtonPressed() { + socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::ResetVM); + +} + +void +VMManagerSystem::pauseButtonPressed() { + socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::Pause); +} +void +VMManagerSystem::dataReceived() +{ + qInfo() << Q_FUNC_INFO << "Note: Respond to data received events here."; +} +void +VMManagerSystem::windowStatusChangeReceived(int status) +{ + window_obscured = status; + emit windowStatusChanged(); + processStatusChanged(); +} +QString +VMManagerSystem::getDisplayValue(Display::Name key) +{ + return (display_table.contains(key)) ? display_table[key] : ""; +} +void +VMManagerSystem::shutdownRequestButtonPressed() +{ + socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::RequestShutdown); +} +void +VMManagerSystem::shutdownForceButtonPressed() +{ + socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::ForceShutdown); +} +void +VMManagerSystem::processStatusChanged() +{ + // set to running if the process is running and the state is stopped + if (process->state() == QProcess::ProcessState::Running) { + if (process_status == VMManagerSystem::ProcessStatus::Stopped) { + process_status = VMManagerSystem::ProcessStatus::Running; + } + } else if (process->state() == QProcess::ProcessState::NotRunning) { + process_status = VMManagerSystem::ProcessStatus::Stopped; + } + emit itemDataChanged(); + emit clientProcessStatusChanged(); +} +void +VMManagerSystem::statusRefresh() +{ + processStatusChanged(); +} +QString +VMManagerSystem::processStatusToString(VMManagerSystem::ProcessStatus status) +{ +// QMetaEnum qme = QMetaEnum::fromType<VMManagerSystem::ProcessStatus>(); +// return qme.valueToKey(static_cast<int>(status)); + switch (status) { + case VMManagerSystem::ProcessStatus::Stopped: + return tr("Powered Off"); + case VMManagerSystem::ProcessStatus::Running: + return tr("Running"); + case VMManagerSystem::ProcessStatus::Paused: + return tr("Paused"); + case VMManagerSystem::ProcessStatus::PausedWaiting: + case VMManagerSystem::ProcessStatus::RunningWaiting: + return tr("Paused (Waiting)"); + default: + return tr("Unknown Status"); + } +} + +QString +VMManagerSystem::getProcessStatusString() const +{ + return processStatusToString(process_status); +} + +VMManagerSystem::ProcessStatus +VMManagerSystem::getProcessStatus() const +{ + return process_status; +} +// Maps VMManagerProtocol::RunningState to VMManagerSystem::ProcessStatus +void +VMManagerSystem::runningStatusChangeReceived(VMManagerProtocol::RunningState state) +{ + if(state == VMManagerProtocol::RunningState::Running) { + process_status = VMManagerSystem::ProcessStatus::Running; + } else if(state == VMManagerProtocol::RunningState::Paused) { + process_status = VMManagerSystem::ProcessStatus::Paused; + } else if(state == VMManagerProtocol::RunningState::RunningWaiting) { + process_status = VMManagerSystem::ProcessStatus::RunningWaiting; + } else if(state == VMManagerProtocol::RunningState::PausedWaiting) { + process_status = VMManagerSystem::ProcessStatus::PausedWaiting; + } else { + process_status = VMManagerSystem::ProcessStatus::Unknown; + } + processStatusChanged(); +} +void +VMManagerSystem::reloadConfig() +{ + loadSettings(); + setupVars(); +} + +QDateTime +VMManagerSystem::timestamp() +{ + return lastUsedTimestamp; +} +void +VMManagerSystem::setIcon(const QString &newIcon) +{ + icon = newIcon; + saveSettings(); + emit itemDataChanged(); +} diff --git a/src/qt/qt_vmmanager_system.hpp b/src/qt/qt_vmmanager_system.hpp new file mode 100644 index 000000000..46fb2a0d9 --- /dev/null +++ b/src/qt/qt_vmmanager_system.hpp @@ -0,0 +1,188 @@ +/* +* 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. +* +* Header for 86Box VM manager system module +* +* +* +* Authors: cold-brewed +* +* Copyright 2024 cold-brewed +*/ + +#ifndef QT_VMMANAGER_SYSTEM_H +#define QT_VMMANAGER_SYSTEM_H + +#include <QFileInfo> +#include <QDir> +#include <QProcess> +#include <QLocalServer> +#include <QWidget> +#include "qt_vmmanager_serversocket.hpp" +#include "qt_vmmanager_config.hpp" +#include "qt_deviceconfig.hpp" + +// This macro helps give us the required `qHash()` function in order to use the +// enum as a hash key +#define QHASH_FOR_CLASS_ENUM(T) \ +inline uint qHash(const T &t, uint seed) { \ + return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \ +} + +namespace Display { +Q_NAMESPACE +enum class Name { + Machine, + CPU, + Memory, + Video, + Disks, + Floppy, + CD, + SCSIController, + MidiOut, + Joystick, + Serial, + Parallel, + Audio, + Voodoo, + NIC, + Mouse, + Unknown +}; +Q_ENUM_NS(Name) +QHASH_FOR_CLASS_ENUM(Name) +} + +class VMManagerSystem : public QWidget { + Q_OBJECT + + typedef QHash<Display::Name, QString> display_table_t; + typedef QHash <QString, QHash <QString, QString>> config_hash_t; + +public: + + enum class ProcessStatus { + Stopped, + Running, + Paused, + PausedWaiting, + RunningWaiting, + Unknown, + }; + Q_ENUM(ProcessStatus); + + explicit VMManagerSystem(const QString &sysconfig_file); + // Default constructor will generate a temporary filename as the config file + // but it will not be valid (isValid() will return false) + VMManagerSystem() : VMManagerSystem(generateTemporaryFilename()) {} + + ~VMManagerSystem() override; + + static QVector<VMManagerSystem *> scanForConfigs(const QString &searchPath = {}); + static QString generateTemporaryFilename(); + + QFileInfo config_file; + QString config_name; + QString config_dir; + QString shortened_dir; + QString uuid; + QString displayName; + QString notes; + QString icon; + QStringList searchTerms; + + config_hash_t config_hash; + + [[nodiscard]] QString getAll(const QString& category) const; + [[nodiscard]] QHash <QString, QString> getCategory(const QString& category) const; + [[nodiscard]] QHash <QString, QHash <QString, QString>> getConfigHash() const; + + void setDisplayName(const QString& newDisplayName); + void setNotes(const QString& newNotes); + + [[nodiscard]] bool isValid() const; + [[nodiscard]] bool isProcessRunning() const; + [[nodiscard]] qint64 processId() const; + void launchMainProcess(); + void launchSettings(); + void startButtonPressed(); + void restartButtonPressed(); + void pauseButtonPressed(); + void shutdownRequestButtonPressed(); + void shutdownForceButtonPressed(); + void reloadConfig(); + QDateTime timestamp(); + void setIcon(const QString &newIcon); + + QProcess *process = new QProcess(); + + bool window_obscured; + + QString getDisplayValue(Display::Name key); + QFileInfoList getScreenshots(); + + inline bool operator==(const VMManagerSystem &rhs) const + { + return config_file.filePath() == rhs.config_file.filePath(); + } + + static QString + processStatusToString(VMManagerSystem::ProcessStatus status) ; + ProcessStatus process_status; + [[nodiscard]] QString getProcessStatusString() const; + [[nodiscard]] ProcessStatus getProcessStatus() const; + +signals: + void windowStatusChanged(); + void itemDataChanged(); + void clientProcessStatusChanged(); + +private: + void loadSettings(); + void saveSettings(); + void generateSearchTerms(); + void updateTimestamp(); + + display_table_t display_table; + + QFileInfo main_binary; + QString platform; + + // QDir application_temp_directory; + // QDir standard_temp_directory; + // QDir app_data_directory; + QDir screenshot_directory; + + QString unique_name; + QDateTime lastUsedTimestamp; + + VMManagerServerSocket *socket_server; + VMManagerServerSocket::ServerType socket_server_type; + + // Configuration file settings + VMManagerConfig *config_settings; + + bool serverIsRunning; + bool startServer(); + + bool has86BoxBinary(); + void find86BoxBinary(); + void setupPaths(); + void setupVars(); + void setProcessEnvVars(); + + void dataReceived(); + void windowStatusChangeReceived(int status); + void runningStatusChangeReceived(VMManagerProtocol::RunningState state); + void processStatusChanged(); + void statusRefresh(); +}; + + +#endif //QT_VMMANAGER_SYSTEM_H diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index a5963c152..51518b8f6 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -59,4 +59,95 @@ <file alias="/texture_vert.spv">qt/texture_vert.spv</file> <file alias="/texture_frag.spv">qt/texture_frag.spv</file> </qresource> + <qresource prefix="/assets"> + <file alias="86Box-green.png">qt/assets/86Box-green.png</file> + <file alias="86box-rb.png">qt/assets/86box-rb.png</file> + <file alias="86box-red.png">qt/assets/86box-red.png</file> + <file alias="86box-yellow.png">qt/assets/86box-yellow.png</file> + <file alias="86box.png">qt/assets/86box.png</file> + <file alias="86box-wizard.png">qt/assets/86box-wizard.png</file> + </qresource> + <qresource prefix="/systemicons"> + <file alias="cpq_deskpro.png">qt/assets/systemicons/cpq_deskpro.png</file> + <file alias="cpq_port_386.png">qt/assets/systemicons/cpq_port_386.png</file> + <file alias="cpq_port_II.png">qt/assets/systemicons/cpq_port_II.png</file> + <file alias="cpq_port_III.png">qt/assets/systemicons/cpq_port_III.png</file> + <file alias="cpq_portable.png">qt/assets/systemicons/cpq_portable.png</file> + <file alias="cpq_pres_2240.png">qt/assets/systemicons/cpq_pres_2240.png</file> + <file alias="cpq_pres_4500.png">qt/assets/systemicons/cpq_pres_4500.png</file> + <file alias="ibm330.png">qt/assets/systemicons/ibm330.png</file> + <file alias="ibm_at.png">qt/assets/systemicons/ibm_at.png</file> + <file alias="ibm_pc_81.png">qt/assets/systemicons/ibm_pc_81.png</file> + <file alias="ibm_pc_82.png">qt/assets/systemicons/ibm_pc_82.png</file> + <file alias="ibm_pcjr.png">qt/assets/systemicons/ibm_pcjr.png</file> + <file alias="ibm_ps2_m70.png">qt/assets/systemicons/ibm_ps2_m70.png</file> + <file alias="ibm_ps2_m80.png">qt/assets/systemicons/ibm_ps2_m80.png</file> + <file alias="ibm_psvp_486.png">qt/assets/systemicons/ibm_psvp_486.png</file> + <file alias="ibm_psvp_p60.png">qt/assets/systemicons/ibm_psvp_p60.png</file> + <file alias="ibm_xt_82.png">qt/assets/systemicons/ibm_xt_82.png</file> + <file alias="ibm_xt_86.png">qt/assets/systemicons/ibm_xt_86.png</file> + <file alias="olivetti_m19.png">qt/assets/systemicons/olivetti_m19.png</file> + <file alias="olivetti_m21.png">qt/assets/systemicons/olivetti_m21.png</file> + <file alias="olivetti_m24.png">qt/assets/systemicons/olivetti_m24.png</file> + <file alias="olivetti_m24sp.png">qt/assets/systemicons/olivetti_m24sp.png</file> + <file alias="os_archlinux_x2.png">qt/assets/systemicons/os_archlinux_x2.png</file> + <file alias="os_cloud_x2.png">qt/assets/systemicons/os_cloud_x2.png</file> + <file alias="os_debian_x2.png">qt/assets/systemicons/os_debian_x2.png</file> + <file alias="os_dos_x2.png">qt/assets/systemicons/os_dos_x2.png</file> + <file alias="os_fedora_x2.png">qt/assets/systemicons/os_fedora_x2.png</file> + <file alias="os_freebsd_x2.png">qt/assets/systemicons/os_freebsd_x2.png</file> + <file alias="os_gentoo_x2.png">qt/assets/systemicons/os_gentoo_x2.png</file> + <file alias="os_jrockitve_x2.png">qt/assets/systemicons/os_jrockitve_x2.png</file> + <file alias="os_l4_x2.png">qt/assets/systemicons/os_l4_x2.png</file> + <file alias="os_linux22_x2.png">qt/assets/systemicons/os_linux22_x2.png</file> + <file alias="os_linux24_x2.png">qt/assets/systemicons/os_linux24_x2.png</file> + <file alias="os_linux26_x2.png">qt/assets/systemicons/os_linux26_x2.png</file> + <file alias="os_linux_x2.png">qt/assets/systemicons/os_linux_x2.png</file> + <file alias="os_macosx_x2.png">qt/assets/systemicons/os_macosx_x2.png</file> + <file alias="os_mandriva_x2.png">qt/assets/systemicons/os_mandriva_x2.png</file> + <file alias="os_netbsd_x2.png">qt/assets/systemicons/os_netbsd_x2.png</file> + <file alias="os_netware_x2.png">qt/assets/systemicons/os_netware_x2.png</file> + <file alias="os_openbsd_x2.png">qt/assets/systemicons/os_openbsd_x2.png</file> + <file alias="os_opensuse_x2.png">qt/assets/systemicons/os_opensuse_x2.png</file> + <file alias="os_oracle_x2.png">qt/assets/systemicons/os_oracle_x2.png</file> + <file alias="os_oraclesolaris_x2.png">qt/assets/systemicons/os_oraclesolaris_x2.png</file> + <file alias="os_os2_other_x2.png">qt/assets/systemicons/os_os2_other_x2.png</file> + <file alias="os_os2ecs_x2.png">qt/assets/systemicons/os_os2ecs_x2.png</file> + <file alias="os_os2warp3_x2.png">qt/assets/systemicons/os_os2warp3_x2.png</file> + <file alias="os_os2warp45_x2.png">qt/assets/systemicons/os_os2warp45_x2.png</file> + <file alias="os_os2warp4_x2.png">qt/assets/systemicons/os_os2warp4_x2.png</file> + <file alias="os_other_x2.png">qt/assets/systemicons/os_other_x2.png</file> + <file alias="os_qnx_x2.png">qt/assets/systemicons/os_qnx_x2.png</file> + <file alias="os_redhat_x2.png">qt/assets/systemicons/os_redhat_x2.png</file> + <file alias="os_solaris_x2.png">qt/assets/systemicons/os_solaris_x2.png</file> + <file alias="os_turbolinux_x2.png">qt/assets/systemicons/os_turbolinux_x2.png</file> + <file alias="os_ubuntu_x2.png">qt/assets/systemicons/os_ubuntu_x2.png</file> + <file alias="os_win10_x2.png">qt/assets/systemicons/os_win10_x2.png</file> + <file alias="os_win2k3_x2.png">qt/assets/systemicons/os_win2k3_x2.png</file> + <file alias="os_win2k8_x2.png">qt/assets/systemicons/os_win2k8_x2.png</file> + <file alias="os_win2k_x2.png">qt/assets/systemicons/os_win2k_x2.png</file> + <file alias="os_win31_x2.png">qt/assets/systemicons/os_win31_x2.png</file> + <file alias="os_win7_x2.png">qt/assets/systemicons/os_win7_x2.png</file> + <file alias="os_win81_x2.png">qt/assets/systemicons/os_win81_x2.png</file> + <file alias="os_win8_x2.png">qt/assets/systemicons/os_win8_x2.png</file> + <file alias="os_win95_x2.png">qt/assets/systemicons/os_win95_x2.png</file> + <file alias="os_win98_x2.png">qt/assets/systemicons/os_win98_x2.png</file> + <file alias="os_win_other_x2.png">qt/assets/systemicons/os_win_other_x2.png</file> + <file alias="os_winme_x2.png">qt/assets/systemicons/os_winme_x2.png</file> + <file alias="os_winnt4_x2.png">qt/assets/systemicons/os_winnt4_x2.png</file> + <file alias="os_winvista_x2.png">qt/assets/systemicons/os_winvista_x2.png</file> + <file alias="os_winxp_x2.png">qt/assets/systemicons/os_winxp_x2.png</file> + <file alias="os_xandros_x2.png">qt/assets/systemicons/os_xandros_x2.png</file> + <file alias="pb_bora_pro.png">qt/assets/systemicons/pb_bora_pro.png</file> + <file alias="pb_pb410.png">qt/assets/systemicons/pb_pb410.png</file> + <file alias="pb_pb640.png">qt/assets/systemicons/pb_pb640.png</file> + <file alias="pb_pb680.png">qt/assets/systemicons/pb_pb680.png</file> + <file alias="tandy_1000.png">qt/assets/systemicons/tandy_1000.png</file> + <file alias="tandy_1000_hx.png">qt/assets/systemicons/tandy_1000_hx.png</file> + <file alias="tandy_1000_sl2.png">qt/assets/systemicons/tandy_1000_sl2.png</file> + <file alias="toshiba_t1000.png">qt/assets/systemicons/toshiba_t1000.png</file> + <file alias="toshiba_t1200.png">qt/assets/systemicons/toshiba_t1200.png</file> + <file alias="toshiba_t1200_hdd.png">qt/assets/systemicons/toshiba_t1200_hdd.png</file> + + </qresource> </RCC> From 5f2df2d7b63b6919df0cd912786dadeb22e12d7b Mon Sep 17 00:00:00 2001 From: Alexander Babikov <lemondrops358@gmail.com> Date: Tue, 11 Mar 2025 10:53:37 +0500 Subject: [PATCH 1024/1190] Update for CD-ROM rewrite --- src/qt/qt_vmmanager_system.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index a28e27892..d8d025dc4 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -593,14 +593,14 @@ VMManagerSystem::setupVars() { auto cdrom_parameters = QString(floppy_cdrom_config[cdrom_parameters_key]); auto cdrom_bus = cdrom_parameters.split(",").at(1).trimmed().toUpper(); - if(auto cdromName = QString(cdrom_getname(cdrom_type)); !cdromName.isEmpty()) { + if(cdrom_type != -1) { if(!cdrom_speed.isEmpty()) { cdrom_speed = QString("%1x ").arg(cdrom_speed); } if(!cdrom_bus.isEmpty()) { cdrom_bus = QString(" (%1)").arg(cdrom_bus); } - cdromDevices.append(QString("%1%2%3").arg(cdrom_speed, cdromName, cdrom_bus)); + cdromDevices.append(QString("%1%2 %3 %4%5").arg(cdrom_speed, cdrom_drive_types[cdrom_type].vendor, cdrom_drive_types[cdrom_type].model, cdrom_drive_types[cdrom_type].revision, cdrom_bus)); } } } From 3ac92ccf4fefe71d415f5dbc5921e5d541534478 Mon Sep 17 00:00:00 2001 From: MaxwellS04 <tongpauz@gmail.com> Date: Fri, 30 May 2025 23:20:50 +0700 Subject: [PATCH 1025/1190] Assorted Cirrus fixes 1. Correct the linear framebuffer setting on VLB Cirrus chips; should fix segfaults when you use them with default configuration 2. Add the "On-Board" name and correct internal_name to the onboard Cirrus Logic GD5420 --- src/video/vid_cl54xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 0d02c10c3..2377e792b 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4796,7 +4796,7 @@ static const device_config_t gd5430_vlb_config[] = { .description = "Linear framebuffer base", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 2, + .default_int = 2048, .file_filter = NULL, .spinner = { 0 }, .selection = { @@ -4871,7 +4871,7 @@ static const device_config_t gd5434_vlb_config[] = { .description = "Linear framebuffer base", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 2, + .default_int = 2048, .file_filter = NULL, .spinner = { 0 }, .selection = { @@ -4982,8 +4982,8 @@ const device_t gd5420_isa_device = { }; const device_t gd5420_onboard_device = { - .name = "Cirrus Logic GD5420 (ISA)", - .internal_name = "cl_gd5420_isa", + .name = "Cirrus Logic GD5420 (ISA) (On-Board)", + .internal_name = "cl_gd5420_onboard", .flags = DEVICE_ISA16, .local = CIRRUS_ID_CLGD5420 | 0x200, .init = gd54xx_init, From e53715bdc53146573565d17cc05b7dec3ad54721 Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Fri, 30 May 2025 23:36:37 +0600 Subject: [PATCH 1026/1190] Dark mode fixes for Windows (#1) --- src/qt/CMakeLists.txt | 5 +++++ src/qt/qt_vmmanager_details.cpp | 10 ++++++++-- src/qt/qt_vmmanager_detailsection.cpp | 10 ++++++++++ src/qt/qt_vmmanager_listviewdelegate.cpp | 16 ++++++++++++---- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index dc430d68c..bed9d27c0 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -193,8 +193,10 @@ add_library(ui STATIC qt_updatecheck.hpp qt_updatecheckdialog.cpp qt_updatecheckdialog.hpp + qt_updatecheckdialog.ui qt_updatedetails.cpp qt_updatedetails.hpp + qt_updatedetails.ui qt_downloader.cpp qt_downloader.hpp @@ -211,10 +213,12 @@ add_library(ui STATIC qt_vmmanager_addmachine.hpp qt_vmmanager_detailsection.cpp qt_vmmanager_detailsection.hpp + qt_vmmanager_detailsection.ui qt_vmmanager_listviewdelegate.hpp qt_vmmanager_listviewdelegate.cpp qt_vmmanager_preferences.cpp qt_vmmanager_preferences.hpp + qt_vmmanager_preferences.ui qt_vmmanager_main.hpp qt_vmmanager_main.cpp qt_vmmanager_main.ui @@ -226,6 +230,7 @@ add_library(ui STATIC qt_vmmanager_config.hpp qt_vmmanager_mainwindow.cpp qt_vmmanager_mainwindow.hpp + qt_vmmanager_mainwindow.ui ../qt_resources.qrc ./qdarkstyle/dark/darkstyle.qrc diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index f72102c25..e427ca140 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -127,8 +127,14 @@ VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { // Set the scrollarea background but also set the scroll bar to none. Otherwise it will also // set the scrollbar background to the same. - ui->scrollArea->setStyleSheet("QWidget {background-color: palette(light)} QScrollBar{ background-color: none }"); - ui->systemLabel->setStyleSheet("background-color: palette(midlight);"); +#ifdef Q_OS_WINDOWS + extern bool windows_is_light_theme(); + if (windows_is_light_theme()) +#endif + { + ui->scrollArea->setStyleSheet("QWidget {background-color: palette(light)} QScrollBar{ background-color: none }"); + ui->systemLabel->setStyleSheet("background-color: palette(midlight);"); + } // Margins are a little different on macos #ifdef Q_OS_MACOS ui->systemLabel->setMargin(15); diff --git a/src/qt/qt_vmmanager_detailsection.cpp b/src/qt/qt_vmmanager_detailsection.cpp index 95a600d8f..f6b77baf9 100644 --- a/src/qt/qt_vmmanager_detailsection.cpp +++ b/src/qt/qt_vmmanager_detailsection.cpp @@ -38,12 +38,22 @@ VMManagerDetailSection(const QString &sectionName) ui->collapseButtonHolder->setContentsMargins(getMargins(MarginSection::ToolButton)); // Simple method to try and determine if light mode is enabled on the host +#ifdef Q_OS_WINDOWS + extern bool windows_is_light_theme(); + const bool lightMode = windows_is_light_theme(); +#else const bool lightMode = QApplication::palette().window().color().value() > QApplication::palette().windowText().color().value(); +#endif // Alternate layout if ( lightMode) { ui->collapseButtonHolder->setStyleSheet("background-color: palette(midlight);"); } else { +#ifdef Q_OS_WINDOWS + ui->outerFrame->setStyleSheet("background-color: #272727;"); + ui->collapseButtonHolder->setStyleSheet("background-color: #616161;"); +#else ui->collapseButtonHolder->setStyleSheet("background-color: palette(mid);"); +#endif } const auto sectionLabel = new QLabel(sectionName); sectionLabel->setStyleSheet(sectionLabel->styleSheet().append("font-weight: bold;")); diff --git a/src/qt/qt_vmmanager_listviewdelegate.cpp b/src/qt/qt_vmmanager_listviewdelegate.cpp index 167c805ee..28820a044 100644 --- a/src/qt/qt_vmmanager_listviewdelegate.cpp +++ b/src/qt/qt_vmmanager_listviewdelegate.cpp @@ -21,6 +21,10 @@ #include "qt_vmmanager_listviewdelegate.hpp" #include "qt_vmmanager_model.hpp" +#ifdef Q_OS_WINDOWS +extern bool windows_is_light_theme(); +#endif + // Thanks to scopchanov https://github.com/scopchanov/SO-MessageLog // from https://stackoverflow.com/questions/53105343/is-it-possible-to-add-a-custom-widget-into-a-qlistview @@ -37,6 +41,10 @@ VMManagerListViewDelegate::~VMManagerListViewDelegate() void VMManagerListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + bool windows_light_mode = true; +#ifdef Q_OS_WINDOWS + windows_light_mode = windows_is_light_theme(); +#endif QStyleOptionViewItem opt(option); initStyleOption(&opt, index); const QPalette &palette(opt.palette); @@ -97,13 +105,13 @@ void VMManagerListViewDelegate::paint(QPainter *painter, const QStyleOptionViewI // When selected, only draw the highlighted part until the horizontal separator int offset = 2; auto highlightRect = rect.adjusted(0, 0, 0, -offset); - painter->fillRect(highlightRect, palette.highlight().color()); + painter->fillRect(highlightRect, windows_light_mode ? palette.highlight().color() : QColor("#616161")); // Then fill the remainder with the normal color auto regularRect = rect.adjusted(0, rect.height()-offset, 0, 0); - painter->fillRect(regularRect, palette.light().color()); + painter->fillRect(regularRect, windows_light_mode ? palette.light().color() : QColor("#272727")); } else { // Otherwise just draw the background color as usual - painter->fillRect(rect, palette.light().color()); + painter->fillRect(rect, windows_light_mode ? palette.light().color() : QColor("#272727")); } // Draw bottom line. Last line gets a different color @@ -238,4 +246,4 @@ qreal VMManagerListViewDelegateStyle::statusFontPointSize(const QFont &f) const QRect VMManagerListViewDelegateStyle::systemNameBox(const QStyleOptionViewItem &option, const QModelIndex &index) const { return option.fontMetrics.boundingRect(option.text).adjusted(0, 0, 1, 1); -} \ No newline at end of file +} From 4a4aa3b0e18fa81c4d8b488c05ff8ec509052d25 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Fri, 30 May 2025 20:45:12 +0200 Subject: [PATCH 1027/1190] Small important change for the 53c400 (May 30th, 2025) Upon an initial POST, the initital status/control 53c400 port should be 0, fixes various versions of the T130B driver on Windows 95 builds. --- src/scsi/scsi_ncr53c400.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 0e04e0b5e..7a87b4ac9 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -759,7 +759,7 @@ ncr53c400_init(const device_t *info) scsi_bus->bus_device = ncr->bus; scsi_bus->timer = ncr->timer; scsi_bus->priv = ncr->priv; - ncr400->status_ctrl = STATUS_BUFFER_NOT_READY; + ncr400->status_ctrl = 0x00; ncr400->buffer_host_pos = 128; timer_add(&ncr400->timer, ncr53c400_callback, ncr400, 0); From cdf742fac3fbf18454e35bae33e1219c89bddb7b Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Sat, 31 May 2025 01:21:17 +0600 Subject: [PATCH 1028/1190] Progress dialog when searching VMs (also a divide-by-zero fix) (#2) --- src/qt/qt_vmmanager_system.cpp | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index d8d025dc4..44c4fd959 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -25,6 +25,7 @@ #include <QCryptographicHash> #include <QtNetwork> #include <QElapsedTimer> +#include <QProgressDialog> #include "qt_vmmanager_system.hpp" // #include "qt_vmmanager_details_section.hpp" #include "qt_vmmanager_detailsection.hpp" @@ -108,6 +109,15 @@ VMManagerSystem::~VMManagerSystem() { QVector<VMManagerSystem *> VMManagerSystem::scanForConfigs(const QString &searchPath) { + QProgressDialog progDialog; + unsigned int found = 0; + progDialog.setCancelButton(nullptr); + progDialog.setWindowTitle(tr("Searching for VMs...")); + progDialog.setMinimumDuration(0); + progDialog.setValue(0); + progDialog.setMinimum(0); + progDialog.setMaximum(0); + progDialog.setWindowFlags(progDialog.windowFlags() & ~Qt::WindowCloseButtonHint); QElapsedTimer scanTimer; scanTimer.start(); QVector<VMManagerSystem *> system_configs; @@ -132,8 +142,9 @@ VMManagerSystem::scanForConfigs(const QString &searchPath) search_directory = searchPath.isEmpty()? vmm_path : searchPath; if(!QDir(search_directory).exists()) { - qWarning() << "Path" << search_directory << "does not exist. Cannot continue"; - return {}; + //qWarning() << "Path" << search_directory << "does not exist. Cannot continue"; + QDir(search_directory).mkpath("."); + //return {}; } QDirIterator dir_iterator(search_directory, filters, QDir::Files, QDirIterator::Subdirectories); @@ -143,6 +154,9 @@ VMManagerSystem::scanForConfigs(const QString &searchPath) QElapsedTimer timer; timer.start(); while (dir_iterator.hasNext()) { + found++; + progDialog.setLabelText(tr("Found %1").arg(QString::number(found))); + QApplication::processEvents(); QString filename = dir_iterator.next(); matches.append(filename); } @@ -154,12 +168,21 @@ VMManagerSystem::scanForConfigs(const QString &searchPath) // foreach (QFileInfo hit, matches) { // system_configs.append(new VMManagerSystem(hit)); // } + progDialog.setMaximum(found); + progDialog.setValue(0); + unsigned int appended = 0; for (const auto &filename : matches) { system_configs.append(new VMManagerSystem(filename)); + appended++; + progDialog.setLabelText(system_configs.last()->displayName); + progDialog.setValue(appended); + QApplication::processEvents(); + } + if (matches.size()) { + auto elapsed = timer.elapsed(); + qDebug() << "Load loop took" << elapsed << "ms for" << matches.size() << "loads"; + qDebug() << "Overall scan time was" << scanTimer.elapsed() << "ms, average" << elapsed / matches.size() << "ms / load"; } - auto elapsed = timer.elapsed(); - qDebug() << "Load loop took" << elapsed << "ms for" << matches.size() << "loads"; - qDebug() << "Overall scan time was" << scanTimer.elapsed() << "ms, average" << elapsed / matches.size() << "ms / load"; return system_configs; } From 3107c1c311638c743504c51fed3fda6f9a67b772 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 31 May 2025 05:35:42 +0200 Subject: [PATCH 1029/1190] Add SNI D858 machine entry. --- src/machine/m_at_socket5.c | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 0d50fead8..47d13d941 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -394,6 +394,84 @@ machine_at_hawk_init(const machine_t *model) return ret; } +int +machine_at_d858_init(const machine_t *model) + +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); + + pci_init(PCI_CONFIG_TYPE_1); + 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(0x11, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */ + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */ + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i430fx_rev02_device); + device_add(&piix_rev02_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&sb_vibra16s_onboard_device); + + return ret; +} + + +static const device_config_t d858_config[] = { + // clang-format off + { + .name = "bios_versions", + .description = "BIOS Versions", + .type = CONFIG_BIOS, + .default_string = "d858", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 4.04 Revision 1.00.858 (04/25/1995)", .internal_name = "d858", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d858/d858.bin", "" } }, + { .name = "Version 4.04 Revision 1.07.858 (08/06/1996)", .internal_name = "d858_aug96", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d858/d858aug96.bin", "" } }, + { .name = "Version 4.05 Revision 2.00.858 (09/24/1997)", .internal_name = "d858_sept97", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d858/d858_sept97.bin", "" } }, + + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + + + +const device_t d858_device = { + .name = "Siemens-Nixdorf D858", + .internal_name = "d858", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = &d858_config[0] +}; + int machine_at_pt2000_init(const machine_t *model) { From 30be3d34b4323be243ef5792d2ce116912799d1a Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 31 May 2025 05:38:05 +0200 Subject: [PATCH 1030/1190] Add SNI D858 machine table entry. --- src/machine/machine_table.c | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a961e9997..8f5c0c3f8 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -66,6 +66,7 @@ extern const device_t vendex_device; extern const device_t c5sbm2_device; extern const device_t sb486pv_device; extern const device_t ap5s_device; +extern const device_t d858_device; extern const device_t d943_device; extern const device_t dells333sl_device; @@ -10751,6 +10752,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, +/* Uses the amstrad_megapc_nvr_device because otherwise the Rev. 2.00.858 BIOS would hang +at soft reset. */ + { + .name = "[i430FX] Siemens-Nixdorf D858", + .internal_name = "d858", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_d858_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_SOUND | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &d858_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &sb_vibra16s_onboard_device, + .net_device = NULL + }, /* KBC On-Chip the VT82C406MV. */ { .name = "[i430FX] FIC PT-2000", From b7ee46eb881ef91c3ba946380272d8d8f3b78fbe Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 31 May 2025 05:38:52 +0200 Subject: [PATCH 1031/1190] Add SNI D858 machine definition. --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c8166a973..1f123e9f5 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -675,6 +675,7 @@ extern int machine_at_optiplexgxl_init(const machine_t *); extern int machine_at_zappa_init(const machine_t *); extern int machine_at_powermatev_init(const machine_t *); extern int machine_at_hawk_init(const machine_t *); +extern int machine_at_d858_init(const machine_t *); extern int machine_at_pt2000_init(const machine_t *); extern int machine_at_pat54pv_init(const machine_t *); From db8de7317d380140d029eeff35565ee14bcb23ee Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Sat, 31 May 2025 16:26:23 +0600 Subject: [PATCH 1032/1190] Make sure to properly open VM folders --- src/qt/qt_vmmanager_main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index a8480eee7..65e126e91 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -64,7 +64,11 @@ VMManagerMain::VMManagerMain(QWidget *parent) : contextMenu.addAction(&openSystemFolderAction); connect(&openSystemFolderAction, &QAction::triggered, [this, indexAt] { if (const auto configDir = indexAt.data(VMManagerModel::Roles::ConfigDir).toString(); !configDir.isEmpty()) { - QDesktopServices::openUrl(QUrl(QString("file:///") + configDir)); + QDir dir(configDir); + if (!dir.exists()) + dir.mkpath("."); + + QDesktopServices::openUrl(QUrl(QString("file:///") + dir.canonicalPath())); } }); From 06e1d0a5ebe208801040afecb2932f3136266a84 Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Sat, 31 May 2025 17:42:46 +0600 Subject: [PATCH 1033/1190] More dark mode fixes for Windows Also enforce modality for progress dialog if possible --- src/qt/qt_vmmanager_details.cpp | 20 ++++++++++++++++---- src/qt/qt_vmmanager_main.cpp | 2 +- src/qt/qt_vmmanager_model.cpp | 4 ++-- src/qt/qt_vmmanager_model.hpp | 2 +- src/qt/qt_vmmanager_system.cpp | 4 ++-- src/qt/qt_vmmanager_system.hpp | 2 +- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index e427ca140..ee8beba30 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -22,6 +22,10 @@ #include "qt_vmmanager_details.hpp" #include "ui_qt_vmmanager_details.h" +#ifdef Q_OS_WINDOWS +extern bool windows_is_light_theme(); +#endif + VMManagerDetails::VMManagerDetails(QWidget *parent) : QWidget(parent), ui(new Ui::VMManagerDetails) { ui->setupUi(this); @@ -71,10 +75,10 @@ VMManagerDetails::VMManagerDetails(QWidget *parent) : screenshotThumbnailSize = QSize(240, 160); // Set the icons for the screenshot navigation buttons - ui->screenshotNext->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekForward)); - ui->screenshotPrevious->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekBackward)); - ui->screenshotNextTB->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekForward)); - ui->screenshotPreviousTB->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSeekBackward)); + ui->screenshotNext->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowRight)); + ui->screenshotPrevious->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowLeft)); + ui->screenshotNextTB->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowRight)); + ui->screenshotPreviousTB->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowLeft)); // Disabled by default ui->screenshotNext->setEnabled(false); ui->screenshotPrevious->setEnabled(false); @@ -90,11 +94,19 @@ VMManagerDetails::VMManagerDetails(QWidget *parent) : ui->screenshotPrevious->setVisible(false); QString toolButtonStyleSheet; // Simple method to try and determine if light mode is enabled +#ifdef Q_OS_WINDOWS + const bool lightMode = windows_is_light_theme(); +#else const bool lightMode = QApplication::palette().window().color().value() > QApplication::palette().windowText().color().value(); +#endif if (lightMode) { toolButtonStyleSheet = "QToolButton {background: transparent; border: none; padding: 5px} QToolButton:hover {background: palette(midlight)} QToolButton:pressed {background: palette(mid)}"; } else { +#ifndef Q_OS_WINDOWS toolButtonStyleSheet = "QToolButton {background: transparent; border: none; padding: 5px} QToolButton:hover {background: palette(dark)} QToolButton:pressed {background: palette(mid)}"; +#else + toolButtonStyleSheet = "QToolButton {padding: 5px}"; +#endif } ui->ssNavTBHolder->setStyleSheet(toolButtonStyleSheet); diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 65e126e91..c49340647 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -390,7 +390,7 @@ VMManagerMain::addNewSystem(const QString &name, const QString &dir, const QStri return; } const auto current_index = ui->listView->currentIndex(); - vm_model->reload(); + vm_model->reload(this); const auto created_object = vm_model->getIndexForConfigFile(new_system->config_file); if (created_object.row() < 0) { // For some reason the index of the new object couldn't be determined. Fall back to the old index. diff --git a/src/qt/qt_vmmanager_model.cpp b/src/qt/qt_vmmanager_model.cpp index 7dc079df0..848970f80 100644 --- a/src/qt/qt_vmmanager_model.cpp +++ b/src/qt/qt_vmmanager_model.cpp @@ -95,10 +95,10 @@ VMManagerModel::getConfigObjectForIndex(const QModelIndex &index) const return machines.at(index.row()); } void -VMManagerModel::reload() +VMManagerModel::reload(QWidget* parent) { // Scan for configs - auto machines_vec = VMManagerSystem::scanForConfigs(); + auto machines_vec = VMManagerSystem::scanForConfigs(parent); for (const auto &scanned_config : machines_vec) { int found = 0; for (const auto &existing_config : machines) { diff --git a/src/qt/qt_vmmanager_model.hpp b/src/qt/qt_vmmanager_model.hpp index 858b55d14..bc13cc16f 100644 --- a/src/qt/qt_vmmanager_model.hpp +++ b/src/qt/qt_vmmanager_model.hpp @@ -54,7 +54,7 @@ public: [[nodiscard]] VMManagerSystem * getConfigObjectForIndex(const QModelIndex &index) const; QModelIndex getIndexForConfigFile(const QFileInfo& config_file); - void reload(); + void reload(QWidget* parent = nullptr); void updateDisplayName(const QModelIndex &index, const QString &newDisplayName); QHash <QString, int> getProcessStats(); signals: diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 44c4fd959..05e595a16 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -107,9 +107,9 @@ VMManagerSystem::~VMManagerSystem() { } QVector<VMManagerSystem *> -VMManagerSystem::scanForConfigs(const QString &searchPath) +VMManagerSystem::scanForConfigs(QWidget* parent, const QString &searchPath) { - QProgressDialog progDialog; + QProgressDialog progDialog(parent); unsigned int found = 0; progDialog.setCancelButton(nullptr); progDialog.setWindowTitle(tr("Searching for VMs...")); diff --git a/src/qt/qt_vmmanager_system.hpp b/src/qt/qt_vmmanager_system.hpp index 46fb2a0d9..d267670e4 100644 --- a/src/qt/qt_vmmanager_system.hpp +++ b/src/qt/qt_vmmanager_system.hpp @@ -84,7 +84,7 @@ public: ~VMManagerSystem() override; - static QVector<VMManagerSystem *> scanForConfigs(const QString &searchPath = {}); + static QVector<VMManagerSystem *> scanForConfigs(QWidget* parent = nullptr, const QString &searchPath = {}); static QString generateTemporaryFilename(); QFileInfo config_file; From 33b511fef8f4740e9acd9788a7354b5266cd3125 Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Sat, 31 May 2025 23:45:43 +0600 Subject: [PATCH 1034/1190] Remove the Machine menu (broken), also make sure buttons are not improperly enabled (#4) --- src/qt/qt_vmmanager_details.cpp | 19 +++++++++++++++++++ src/qt/qt_vmmanager_detailsection.cpp | 4 ++++ src/qt/qt_vmmanager_mainwindow.ui | 20 ++++---------------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index ee8beba30..64b6babec 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -114,19 +114,25 @@ VMManagerDetails::VMManagerDetails(QWidget *parent) : startPauseButton = new QToolButton(); startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); startPauseButton->setAutoRaise(true); + startPauseButton->setEnabled(false); ui->toolButtonHolder->setStyleSheet(toolButtonStyleSheet); resetButton = new QToolButton(); resetButton->setIcon(QIcon(":/menuicons/qt/icons/hard_reset.ico")); + resetButton->setEnabled(false); stopButton = new QToolButton(); stopButton->setIcon(QIcon(":/menuicons/qt/icons/acpi_shutdown.ico")); + stopButton->setEnabled(false); configureButton = new QToolButton(); configureButton->setIcon(QIcon(":/menuicons/qt/icons/settings.ico")); + configureButton->setEnabled(false); ui->toolButtonHolder->layout()->addWidget(configureButton); ui->toolButtonHolder->layout()->addWidget(resetButton); ui->toolButtonHolder->layout()->addWidget(stopButton); ui->toolButtonHolder->layout()->addWidget(startPauseButton); + ui->notesTextEdit->setEnabled(false); + sysconfig = new VMManagerSystem(); } @@ -175,6 +181,8 @@ VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); } + startPauseButton->setEnabled(true); + configureButton->setEnabled(true); // Each detail section here has its own VMManagerDetailSection. // When a system is selected in the list view it is updated here, through this object: @@ -237,6 +245,9 @@ VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { ui->screenshotNextTB->setEnabled(true); ui->screenshotPreviousTB->setEnabled(true); } +#ifdef Q_OS_WINDOWS + ui->screenshot->setStyleSheet(""); +#endif if(QFileInfo::exists(screenshots.last().filePath())) { screenshotIndex = screenshots.size() - 1; const QPixmap pic(screenshots.at(screenshotIndex).filePath()); @@ -253,6 +264,13 @@ VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { ui->screenshot->setText(tr("No screenshot")); ui->screenshot->setEnabled(false); ui->screenshot->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); +#ifdef Q_OS_WINDOWS + if (!windows_is_light_theme()) { + ui->screenshot->setStyleSheet("QLabel { border: 1px solid gray }"); + } else { + ui->screenshot->setStyleSheet(""); + } +#endif } ui->systemLabel->setText(passed_sysconfig->displayName); @@ -260,6 +278,7 @@ VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { tr("Not running") : QString("%1: PID %2").arg(tr("Running"), QString::number(sysconfig->process->processId()))); ui->notesTextEdit->setPlainText(passed_sysconfig->notes); + ui->notesTextEdit->setEnabled(true); disconnect(sysconfig->process, &QProcess::stateChanged, this, &VMManagerDetails::updateProcessStatus); connect(sysconfig->process, &QProcess::stateChanged, this, &VMManagerDetails::updateProcessStatus); diff --git a/src/qt/qt_vmmanager_detailsection.cpp b/src/qt/qt_vmmanager_detailsection.cpp index f6b77baf9..bd080e00c 100644 --- a/src/qt/qt_vmmanager_detailsection.cpp +++ b/src/qt/qt_vmmanager_detailsection.cpp @@ -72,6 +72,7 @@ VMManagerDetailSection(const QString &sectionName) ui->collapseButtonHolder->layout()->addItem(hSpacer); // collapseButton->setContent(frame); // ui->sectionName->setVisible(false); + setVisible(false); } VMManagerDetailSection:: @@ -227,11 +228,14 @@ VMManagerDetailSection::setSections() } } collapseButton->setContent(ui->detailFrame); + if (sections.size()) + setVisible(true); } void VMManagerDetailSection::clear() { sections.clear(); + setVisible(false); } // QT for Linux and Windows doesn't have the same default margins as QT on MacOS. diff --git a/src/qt/qt_vmmanager_mainwindow.ui b/src/qt/qt_vmmanager_mainwindow.ui index b19610593..e3e0a242d 100644 --- a/src/qt/qt_vmmanager_mainwindow.ui +++ b/src/qt/qt_vmmanager_mainwindow.ui @@ -20,7 +20,7 @@ <x>0</x> <y>0</y> <width>900</width> - <height>24</height> + <height>21</height> </rect> </property> <widget class="QMenu" name="menuTools"> @@ -30,17 +30,6 @@ <addaction name="actionPreferences"/> <addaction name="actionCheck_for_updates"/> </widget> - <widget class="QMenu" name="menuMachine"> - <property name="title"> - <string>Machine</string> - </property> - <addaction name="actionStartPause"/> - <addaction name="actionForce_Shutdown"/> - <addaction name="actionHard_Reset"/> - <addaction name="actionCtrl_Alt_Del"/> - <addaction name="separator"/> - <addaction name="actionSettings"/> - </widget> <widget class="QMenu" name="menuFile"> <property name="title"> <string>File</string> @@ -48,7 +37,6 @@ <addaction name="actionNew_Machine"/> </widget> <addaction name="menuFile"/> - <addaction name="menuMachine"/> <addaction name="menuTools"/> </widget> <widget class="QStatusBar" name="statusbar"/> @@ -66,7 +54,7 @@ </size> </property> <property name="toolButtonStyle"> - <enum>Qt::ToolButtonIconOnly</enum> + <enum>Qt::ToolButtonStyle::ToolButtonIconOnly</enum> </property> <attribute name="toolBarArea"> <enum>TopToolBarArea</enum> @@ -167,7 +155,7 @@ <string>&amp;Settings...</string> </property> <property name="menuRole"> - <enum>QAction::NoRole</enum> + <enum>QAction::MenuRole::NoRole</enum> </property> <property name="iconVisibleInMenu"> <bool>false</bool> @@ -193,7 +181,7 @@ <string>Preferences</string> </property> <property name="menuRole"> - <enum>QAction::PreferencesRole</enum> + <enum>QAction::MenuRole::PreferencesRole</enum> </property> </action> <action name="actionStart"> From 34cdfbcc1875c3a7ab6e4a13fdaa120ba03bf385 Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Sun, 1 Jun 2025 01:22:25 +0600 Subject: [PATCH 1035/1190] Tooltips for buttons (#5) --- src/qt/qt_vmmanager_details.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index 64b6babec..c5be7c2cf 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -115,16 +115,20 @@ VMManagerDetails::VMManagerDetails(QWidget *parent) : startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); startPauseButton->setAutoRaise(true); startPauseButton->setEnabled(false); + startPauseButton->setToolTip(tr("Start")); ui->toolButtonHolder->setStyleSheet(toolButtonStyleSheet); resetButton = new QToolButton(); resetButton->setIcon(QIcon(":/menuicons/qt/icons/hard_reset.ico")); resetButton->setEnabled(false); + resetButton->setToolTip(tr("Hard reset")); stopButton = new QToolButton(); stopButton->setIcon(QIcon(":/menuicons/qt/icons/acpi_shutdown.ico")); stopButton->setEnabled(false); + stopButton->setToolTip(tr("Force shutdown")); configureButton = new QToolButton(); configureButton->setIcon(QIcon(":/menuicons/qt/icons/settings.ico")); configureButton->setEnabled(false); + configureButton->setToolTip(tr("Settings...")); ui->toolButtonHolder->layout()->addWidget(configureButton); ui->toolButtonHolder->layout()->addWidget(resetButton); @@ -305,8 +309,10 @@ VMManagerDetails::updateProcessStatus() { if(running) { if(sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::Running) { startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/pause.ico")); + startPauseButton->setToolTip(tr("Pause")); } else { startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/run.ico")); + startPauseButton->setToolTip(tr("Continue")); } disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); @@ -317,6 +323,7 @@ VMManagerDetails::updateProcessStatus() { disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::pauseButtonPressed); disconnect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); + startPauseButton->setToolTip(tr("Start")); } } From e580818ba6d4650a84d9325a177a0167a4ffd970 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sun, 1 Jun 2025 11:58:21 +0200 Subject: [PATCH 1036/1190] Rename the Olivetti M24 and M240 to add the names of their AT&T counterparts --- 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 a961e9997..e54a00bd4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2377,7 +2377,7 @@ const machine_t machines[] = { .net_device = NULL }, { - .name = "[8086] Olivetti M21/24/24SP", + .name = "[8086] Olivetti M21/24/24SP/AT&T PC 6300", .internal_name = "m24", .type = MACHINE_TYPE_8086, .chipset = MACHINE_CHIPSET_PROPRIETARY, @@ -2417,7 +2417,7 @@ const machine_t machines[] = { }, /* Has Olivetti KBC firmware. */ { - .name = "[8086] Olivetti M240", + .name = "[8086] Olivetti M240/AT&T PC 6300 WGS", .internal_name = "m240", .type = MACHINE_TYPE_8086, .chipset = MACHINE_CHIPSET_PROPRIETARY, From 07341003dcc0b0f97f814ef0ecee78c2ca09b4eb Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Sun, 1 Jun 2025 13:21:36 +0200 Subject: [PATCH 1037/1190] C&T 69000 changes of the day (June 1st, 2025) Divide by 3 the destination address on color patterns to make sure the pattern position is perfectly aligned. Fixes color patterns in Win3.1x and Win9x (and possibly NT-based and other stuff). --- src/video/vid_chips_69000.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 8267e271c..170a601fd 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -1268,15 +1268,15 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) 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); + + (3 * ((((chips->bitblt_running.bitblt.destination_addr / 3) & 7) + chips->bitblt_running.x) & 7)), chips); 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; + + (3 * ((((chips->bitblt_running.bitblt.destination_addr / 3) & 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; + + (3 * ((((chips->bitblt_running.bitblt.destination_addr / 3) & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; } } if (chips->bitblt_running.bytes_per_pixel == 2) { @@ -2785,7 +2785,7 @@ chips_69000_disable_handlers(chips_69000_t *chips) mem_mapping_disable(&chips->svga.mapping); if (!chips->on_board) mem_mapping_disable(&chips->bios_rom.mapping); - + chips->linear_mapping.base = 0; /* Save all the mappings and the timers because they are part of linked lists. */ From b5d606f071b8e51f55d06e9d2037fb0ded68bd36 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sun, 1 Jun 2025 16:33:18 +0200 Subject: [PATCH 1038/1190] Add SNI D842 machine entry. --- src/machine/m_at_socket5.c | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 47d13d941..0cd6cb92e 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -80,6 +80,87 @@ machine_at_dellplato_init(const machine_t *model) return ret; } +int +machine_at_d842_init(const machine_t *model) + +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init(model); + + device_add(&ide_pci_2ch_device); + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Onboard */ + pci_register_slot(0x03, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Onboard */ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */ + + device_add(&keyboard_ps2_pci_device); + device_add(&i430nx_device); + device_add(&sio_zb_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + +static const device_config_t d842_config[] = { + // clang-format off + { + .name = "bios_versions", + .description = "BIOS Versions", + .type = CONFIG_BIOS, + .default_string = "d842", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 1.03 Revision 1.03.842 (11/24/1994)", .internal_name = "d842", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842.bin", "" } }, + { .name = "Version 4.04 Revision 1.05.842 (03/15/1996)", .internal_name = "d842_mar96", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_mar96.bin", "" } }, + { .name = "Version 4.04 Revision 1.06.842 (04/03/1998)", .internal_name = "d842_apr98", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_apr98.bin", "" } }, + { .name = "Version 4.04 Revision 1.07.842 (06/02/1998)", .internal_name = "d842_jun98", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98.bin", "" } }, + { .name = "Version 1.03 Revision 1.09.842 (07/08/1996)", .internal_name = "d842_jul96", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jul96.bin", "" } }, + { .name = "Version 1.03 Revision 1.10.842 (06/04/1998)", .internal_name = "d842_jun98_1", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98_1.bin", "" } }, + + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + + + +const device_t d842_device = { + .name = "Siemens-Nixdorf D842", + .internal_name = "d842", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = &d842_config[0] +}; + int machine_at_ambradp90_init(const machine_t *model) { From defcef697404b00229e1cfffcadf98113456ff74 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sun, 1 Jun 2025 16:34:34 +0200 Subject: [PATCH 1039/1190] Add SNI D842 machine table entry. --- src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8f5c0c3f8..91a2fab6a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -66,6 +66,7 @@ extern const device_t vendex_device; extern const device_t c5sbm2_device; extern const device_t sb486pv_device; extern const device_t ap5s_device; +extern const device_t d842_device; extern const device_t d858_device; extern const device_t d943_device; extern const device_t dells333sl_device; @@ -10347,6 +10348,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + + { + .name = "[i430NX] Siemens-Nixdorf D842", + .internal_name = "d842", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_d842_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &d842_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. This is basically an Intel Premiere/PCI II with a fancier POST screen. */ { From 29b9e796df76d2bbbcaa46d4ff03308f426e1692 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sun, 1 Jun 2025 16:35:10 +0200 Subject: [PATCH 1040/1190] Add SNI D842 machine definition. --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 1f123e9f5..dd208b0ce 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -664,6 +664,7 @@ extern int machine_at_p5sp4_init(const machine_t *); /* m_at_socket5.c */ extern int machine_at_plato_init(const machine_t *); extern int machine_at_dellplato_init(const machine_t *); +extern int machine_at_d842_init(const machine_t *); extern int machine_at_ambradp90_init(const machine_t *); extern int machine_at_p54np4_init(const machine_t *); extern int machine_at_586ip_init(const machine_t *); From d8bf4212b78250434bae8efebbc95a261a4dfb58 Mon Sep 17 00:00:00 2001 From: Cacodemon345 <wahil1976@outlook.com> Date: Sun, 1 Jun 2025 23:29:08 +0600 Subject: [PATCH 1041/1190] Add Ctrl+Alt+Del button (#6) --- src/qt/qt_vmmanager_details.cpp | 9 +++++++++ src/qt/qt_vmmanager_details.hpp | 1 + src/qt/qt_vmmanager_system.cpp | 9 +++++++++ src/qt/qt_vmmanager_system.hpp | 3 +++ 4 files changed, 22 insertions(+) diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index c5be7c2cf..23fe5377e 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -129,11 +129,16 @@ VMManagerDetails::VMManagerDetails(QWidget *parent) : configureButton->setIcon(QIcon(":/menuicons/qt/icons/settings.ico")); configureButton->setEnabled(false); configureButton->setToolTip(tr("Settings...")); + cadButton = new QToolButton(); + cadButton->setIcon(QIcon(":menuicons/qt/icons/send_cad.ico")); + cadButton->setEnabled(false); + cadButton->setToolTip(tr("Ctrl+Alt+Del")); ui->toolButtonHolder->layout()->addWidget(configureButton); ui->toolButtonHolder->layout()->addWidget(resetButton); ui->toolButtonHolder->layout()->addWidget(stopButton); ui->toolButtonHolder->layout()->addWidget(startPauseButton); + ui->toolButtonHolder->layout()->addWidget(cadButton); ui->notesTextEdit->setEnabled(false); @@ -170,11 +175,14 @@ VMManagerDetails::updateData(VMManagerSystem *passed_sysconfig) { disconnect(resetButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::restartButtonPressed); disconnect(stopButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::shutdownForceButtonPressed); disconnect(configureButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::launchSettings); + disconnect(cadButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::cadButtonPressed); sysconfig = passed_sysconfig; connect(resetButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::restartButtonPressed); connect(stopButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::shutdownForceButtonPressed); connect(configureButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::launchSettings); + connect(cadButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::cadButtonPressed); + cadButton->setEnabled(true); bool running = sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::Running || sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::RunningWaiting; @@ -306,6 +314,7 @@ VMManagerDetails::updateProcessStatus() { ui->statusLabel->setText(status_text); resetButton->setEnabled(running); stopButton->setEnabled(running); + cadButton->setEnabled(running); if(running) { if(sysconfig->getProcessStatus() == VMManagerSystem::ProcessStatus::Running) { startPauseButton->setIcon(QIcon(":/menuicons/qt/icons/pause.ico")); diff --git a/src/qt/qt_vmmanager_details.hpp b/src/qt/qt_vmmanager_details.hpp index c6db78127..5d3bfa8a4 100644 --- a/src/qt/qt_vmmanager_details.hpp +++ b/src/qt/qt_vmmanager_details.hpp @@ -65,6 +65,7 @@ private: QToolButton *resetButton; QToolButton *stopButton; QToolButton *configureButton; + QToolButton *cadButton; static QWidget* createHorizontalLine(int leftSpacing = 25, int rightSpacing = 25); // QVBoxLayout *detailsLayout; diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 05e595a16..68b83c3a8 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -813,16 +813,25 @@ VMManagerSystem::getDisplayValue(Display::Name key) { return (display_table.contains(key)) ? display_table[key] : ""; } + void VMManagerSystem::shutdownRequestButtonPressed() { socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::RequestShutdown); } + void VMManagerSystem::shutdownForceButtonPressed() { socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::ForceShutdown); } + +void +VMManagerSystem::cadButtonPressed() +{ + socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::CtrlAltDel); +} + void VMManagerSystem::processStatusChanged() { diff --git a/src/qt/qt_vmmanager_system.hpp b/src/qt/qt_vmmanager_system.hpp index d267670e4..ab2069617 100644 --- a/src/qt/qt_vmmanager_system.hpp +++ b/src/qt/qt_vmmanager_system.hpp @@ -109,6 +109,7 @@ public: [[nodiscard]] bool isValid() const; [[nodiscard]] bool isProcessRunning() const; [[nodiscard]] qint64 processId() const; +public slots: void launchMainProcess(); void launchSettings(); void startButtonPressed(); @@ -116,7 +117,9 @@ public: void pauseButtonPressed(); void shutdownRequestButtonPressed(); void shutdownForceButtonPressed(); + void cadButtonPressed(); void reloadConfig(); +public: QDateTime timestamp(); void setIcon(const QString &newIcon); From 111c9d1143681abe9dd7133c44577795d03d4e40 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:42:40 +0200 Subject: [PATCH 1042/1190] Remove SNI D858 machine entry. --- src/machine/m_at_socket5.c | 77 -------------------------------------- 1 file changed, 77 deletions(-) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 0cd6cb92e..3ed2bd2c7 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -475,83 +475,6 @@ machine_at_hawk_init(const machine_t *model) return ret; } -int -machine_at_d858_init(const machine_t *model) - -{ - int ret = 0; - const char* fn; - - /* No ROMs available */ - if (!device_available(model->device)) - return ret; - - device_context(model->device); - fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 0); - ret = bios_load_linear(fn, 0x000e0000, 131072, 0); - device_context_restore(); - - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); - - pci_init(PCI_CONFIG_TYPE_1); - 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(0x11, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */ - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */ - device_add(&keyboard_ps2_ami_pci_device); - device_add(&i430fx_rev02_device); - device_add(&piix_rev02_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); - - - if (sound_card_current[0] == SOUND_INTERNAL) - device_add(&sb_vibra16s_onboard_device); - - return ret; -} - - -static const device_config_t d858_config[] = { - // clang-format off - { - .name = "bios_versions", - .description = "BIOS Versions", - .type = CONFIG_BIOS, - .default_string = "d858", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, /*W1*/ - .bios = { - { .name = "Version 4.04 Revision 1.00.858 (04/25/1995)", .internal_name = "d858", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d858/d858.bin", "" } }, - { .name = "Version 4.04 Revision 1.07.858 (08/06/1996)", .internal_name = "d858_aug96", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d858/d858aug96.bin", "" } }, - { .name = "Version 4.05 Revision 2.00.858 (09/24/1997)", .internal_name = "d858_sept97", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d858/d858_sept97.bin", "" } }, - - }, - }, - { .name = "", .description = "", .type = CONFIG_END } - // clang-format on -}; - - - -const device_t d858_device = { - .name = "Siemens-Nixdorf D858", - .internal_name = "d858", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = &d858_config[0] -}; int machine_at_pt2000_init(const machine_t *model) From 08781dec4192b8ffd31c316d7bd9a62aaedf1bc0 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:43:18 +0200 Subject: [PATCH 1043/1190] Remove SNI D858 machine table entry. --- src/machine/machine_table.c | 42 ------------------------------------- 1 file changed, 42 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 91a2fab6a..5e17a940d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -67,7 +67,6 @@ extern const device_t c5sbm2_device; extern const device_t sb486pv_device; extern const device_t ap5s_device; extern const device_t d842_device; -extern const device_t d858_device; extern const device_t d943_device; extern const device_t dells333sl_device; @@ -10793,47 +10792,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -/* Uses the amstrad_megapc_nvr_device because otherwise the Rev. 2.00.858 BIOS would hang -at soft reset. */ - { - .name = "[i430FX] Siemens-Nixdorf D858", - .internal_name = "d858", - .type = MACHINE_TYPE_SOCKET5, - .chipset = MACHINE_CHIPSET_INTEL_430FX, - .init = machine_at_d858_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 66666667, - .min_voltage = 3380, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 2.0 - }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_SOUND | MACHINE_APM, - .ram = { - .min = 8192, - .max = 131072, - .step = 8192 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = &d858_device, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = &sb_vibra16s_onboard_device, - .net_device = NULL - }, /* KBC On-Chip the VT82C406MV. */ { .name = "[i430FX] FIC PT-2000", From b764ec1e74fd06254f1df21650bf7b5f145af933 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:43:47 +0200 Subject: [PATCH 1044/1190] Remove SNI D858 machine definition. --- src/include/86box/machine.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index dd208b0ce..112d140f8 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -676,7 +676,6 @@ extern int machine_at_optiplexgxl_init(const machine_t *); extern int machine_at_zappa_init(const machine_t *); extern int machine_at_powermatev_init(const machine_t *); extern int machine_at_hawk_init(const machine_t *); -extern int machine_at_d858_init(const machine_t *); extern int machine_at_pt2000_init(const machine_t *); extern int machine_at_pat54pv_init(const machine_t *); From 46c58e547824f6c21d20adfac08dd1150c5a18af Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Mon, 2 Jun 2025 09:00:25 +0200 Subject: [PATCH 1045/1190] Remove video flag from D842. --- 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 5e17a940d..bfaa5fb0f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -10369,7 +10369,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, From 50516eb3d2956dca824b93f9aaffd39e44995d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= <oubattler@gmail.com> Date: Mon, 2 Jun 2025 10:39:33 +0200 Subject: [PATCH 1046/1190] FDC poll: fix VERIFY opcode. --- src/floppy/fdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index ebc16cbfd..0b5391670 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1653,8 +1653,8 @@ fdc_callback(void *priv) case 0x06: /* Read data */ case 0x0c: /* Read deleted data */ case 0x11: /* Scan equal */ + case 0x16: /* Verify */ case 0x19: /* Scan low or equal */ - case 0x1c: /* Verify */ case 0x1d: /* Scan high or equal */ if ((fdc->interrupt == 0x11) || (fdc->interrupt == 0x19) || (fdc->interrupt == 0x1D)) compare = 1; From 3afd6592c5f9372f49e51adf34085da02dcd701b Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Mon, 2 Jun 2025 19:50:05 +0200 Subject: [PATCH 1047/1190] Fix on-board Audio on the SNI D943 TRW had some misinformation. It's NOT using a ViBRA 16S, but a 16C. --- 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 bfaa5fb0f..fdf94a77e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11855,7 +11855,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = &gd5436_onboard_pci_device, - .snd_device = &sb_vibra16s_onboard_device, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, From 479ca3d6b4ba625f05cefe075469cc03f1b95477 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Thu, 5 Jun 2025 13:07:40 +0200 Subject: [PATCH 1048/1190] Small IRQ correction on ad1848/cs4231 (June 5th, 2025) This fixes the the looping wave plays in Win95 using GUS MAX and possibly on WSS derived products. --- src/sound/snd_ad1848.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index 202fd891a..e9a4390c0 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -731,9 +731,11 @@ ad1848_poll(void *priv) if (!(ad1848->status & 0x01)) { ad1848->status |= 0x01; ad1848->regs[24] |= 0x10; - if (ad1848->regs[10] & 2) - picint(1 << ad1848->irq); } + if (ad1848->regs[10] & 2) + picint(1 << ad1848->irq); + else + picintc(1 << ad1848->irq); } if (!(ad1848->adpcm_pos & 7)) /* ADPCM counts down every 4 bytes */ From e3c825fce7489b34fc7396467adababdaa8fcea2 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Fri, 6 Jun 2025 15:54:04 +0200 Subject: [PATCH 1049/1190] (S)VGA: Fix overscan, closes #5651. --- src/video/vid_svga.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 86a57c00e..b4ae192da 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -691,11 +691,11 @@ svga_recalctimings(svga_t *svga) double _dispontime_xga = 0.0; double _dispofftime_xga = 0.0; double disptime_xga = 0.0; + int vblankend; + int hdispend; #ifdef ENABLE_SVGA_LOG int vsyncend; - int vblankend; int hdispstart; - int hdispend; int hsyncstart; int hsyncend; #endif @@ -911,7 +911,19 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); - if (!svga->hoverride) { + vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); + if (vblankend <= svga->vblankstart) + vblankend += 0x00000080; + + hdispend = svga->crtc[1] + 1; + + if (svga->hoverride) { + if (svga->hdisp >= 2048) + svga->monitor->mon_overscan_x = 0; + + svga->y_add = (svga->monitor->mon_overscan_y >> 1); + svga->x_add = (svga->monitor->mon_overscan_x >> 1); + } else { uint32_t dot = svga->hblankstart; uint32_t adj_dot = svga->hblankstart; /* Verified with both the Voodoo 3 and the S3 cards: compare 7 bits if bit 7 is set, @@ -938,6 +950,17 @@ svga_recalctimings(svga_t *svga) } svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + + svga->y_add = svga->vtotal + vblankend + 1; + svga->monitor->mon_overscan_y = svga->y_add + svga->vblankstart - svga->dispend; + + if (svga->hdisp >= 2048) { + svga->x_add = 0; + svga->monitor->mon_overscan_x = 0; + } else { + svga->x_add = (svga->htotal + svga->hblank_end_val - 1) * svga->dots_per_clock; + svga->monitor->mon_overscan_x = svga->x_add + ((svga->hblankstart - hdispend) * svga->dots_per_clock); + } } #ifdef TBD @@ -967,12 +990,6 @@ svga_recalctimings(svga_t *svga) } #endif - if (svga->hdisp >= 2048) - svga->monitor->mon_overscan_x = 0; - - svga->y_add = (svga->monitor->mon_overscan_y >> 1); - svga->x_add = (svga->monitor->mon_overscan_x >> 1); - if (svga->vblankstart < svga->dispend) { svga_log("DISPEND > VBLANKSTART.\n"); svga->dispend = svga->vblankstart; @@ -992,12 +1009,8 @@ svga_recalctimings(svga_t *svga) vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); if (vsyncend <= svga->vsyncstart) vsyncend += 0x00000010; - vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); - if (vblankend <= svga->vblankstart) - vblankend += 0x00000080; hdispstart = ((svga->crtc[3] >> 5) & 3); - hdispend = svga->crtc[1] + 1; hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); if (hsyncend <= hsyncstart) From a1a94076298f52b24be35268bec8e62c4cce97de Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Fri, 6 Jun 2025 20:05:04 +0200 Subject: [PATCH 1050/1190] (S)VGA: Fix overscan. --- src/include/86box/vid_svga.h | 1 + src/video/vid_svga.c | 45 ++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 6de73f9f9..6b817f0ee 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -116,6 +116,7 @@ typedef struct svga_t { int lastline_draw; int displine; int fullchange; + int left_overscan; int x_add; int y_add; int pan; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index b4ae192da..8f5907c3f 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -692,9 +692,9 @@ svga_recalctimings(svga_t *svga) double _dispofftime_xga = 0.0; double disptime_xga = 0.0; int vblankend; - int hdispend; #ifdef ENABLE_SVGA_LOG int vsyncend; + int hdispend; int hdispstart; int hsyncstart; int hsyncend; @@ -915,14 +915,12 @@ svga_recalctimings(svga_t *svga) if (vblankend <= svga->vblankstart) vblankend += 0x00000080; - hdispend = svga->crtc[1] + 1; - if (svga->hoverride) { if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; svga->y_add = (svga->monitor->mon_overscan_y >> 1); - svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga->left_overscan = svga->x_add = (svga->monitor->mon_overscan_x >> 1); } else { uint32_t dot = svga->hblankstart; uint32_t adj_dot = svga->hblankstart; @@ -931,7 +929,9 @@ svga_recalctimings(svga_t *svga) uint32_t eff_mask = (svga->hblank_end_val & ~0x0000003f) ? svga->hblank_end_mask : 0x0000003f; svga->hblank_sub = 0; - svga_log("HDISP=%d, CRTC1+1=%d, Blank: %04i-%04i, Total: %04i, Mask: %02X, ADJ_DOT=%04i.\n", svga->hdisp, svga->crtc[1] + 1, svga->hblankstart, svga->hblank_end_val, + svga_log("HDISP=%d, CRTC1+1=%d, Blank: %04i-%04i, Total: %04i, " + "Mask: %02X, ADJ_DOT=%04i.\n", svga->hdisp, svga->crtc[1] + 1, + svga->hblankstart, svga->hblank_end_val, svga->htotal, eff_mask, adj_dot); while (adj_dot < (svga->htotal << 1)) { @@ -941,7 +941,10 @@ svga_recalctimings(svga_t *svga) if (adj_dot >= svga->htotal) svga->hblank_sub++; - svga_log("Loop: adjdot=%d, htotal=%d, dotmask=%02x, hblankendvalmask=%02x, blankendval=%02x.\n", adj_dot, svga->htotal, dot & eff_mask, svga->hblank_end_val & eff_mask, svga->hblank_end_val); + svga_log("Loop: adjdot=%d, htotal=%d, dotmask=%02x, " + "hblankendvalmask=%02x, blankendval=%02x.\n", adj_dot, + svga->htotal, dot & eff_mask, svga->hblank_end_val & eff_mask, + svga->hblank_end_val); if ((dot & eff_mask) == (svga->hblank_end_val & eff_mask)) break; @@ -949,17 +952,23 @@ svga_recalctimings(svga_t *svga) adj_dot++; } + uint32_t hd = svga->hdisp; svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); - svga->y_add = svga->vtotal + vblankend + 1; - svga->monitor->mon_overscan_y = svga->y_add + svga->vblankstart - svga->dispend; + svga->left_overscan = svga->x_add = (svga->htotal - adj_dot - 1) * svga->dots_per_clock; + svga->monitor->mon_overscan_x = svga->x_add + (svga->hblankstart * svga->dots_per_clock) - hd; - if (svga->hdisp >= 2048) { - svga->x_add = 0; + if ((svga->hdisp >= 2048) || (svga->left_overscan < 0)) { + svga->left_overscan = svga->x_add = 0; svga->monitor->mon_overscan_x = 0; - } else { - svga->x_add = (svga->htotal + svga->hblank_end_val - 1) * svga->dots_per_clock; - svga->monitor->mon_overscan_x = svga->x_add + ((svga->hblankstart - hdispend) * svga->dots_per_clock); + } + + svga->y_add = svga->vtotal - vblankend + 1; + svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend); + + if ((svga->dispend >= 2048) || (svga->y_add < 0)) { + svga->y_add = 0; + svga->monitor->mon_overscan_y = 0; } } @@ -1010,6 +1019,7 @@ svga_recalctimings(svga_t *svga) if (vsyncend <= svga->vsyncstart) vsyncend += 0x00000010; + hdispend = svga->crtc[1] + 1; hdispstart = ((svga->crtc[3] >> 5) & 3); hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); @@ -1191,10 +1201,10 @@ svga_do_render(svga_t *svga) if (!svga->override) { svga->render(svga); - svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga->x_add = svga->left_overscan; svga_render_overscan_left(svga); svga_render_overscan_right(svga); - svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; + svga->x_add = svga->left_overscan - svga->scrollcache; } if (svga->overlay_on) { @@ -1373,7 +1383,7 @@ svga_poll(void *priv) svga->sc = 0; if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; - svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga->x_add = svga->left_overscan; } } } @@ -1479,7 +1489,7 @@ svga_poll(void *priv) if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) svga->scrollcache <<= 1; - svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; + svga->x_add = svga->left_overscan - svga->scrollcache; svga->linecountff = 0; @@ -1529,6 +1539,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->attrregs[0x11] = 0; svga->overscan_color = 0x000000; + svga->left_overscan = 8; svga->monitor->mon_overscan_x = 16; svga->monitor->mon_overscan_y = 32; svga->x_add = 8; From c6e374158b041b50ca2741d37e69fab1fb689179 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Fri, 6 Jun 2025 20:09:36 +0200 Subject: [PATCH 1051/1190] Fix it in svga_doblit() as well. --- src/video/vid_svga.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 8f5907c3f..0c9c24241 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1997,9 +1997,15 @@ svga_doblit(int wx, int wy, svga_t *svga) y_add = enable_overscan ? svga->monitor->mon_overscan_y : 0; x_add = enable_overscan ? svga->monitor->mon_overscan_x : 0; +#ifdef USE_OLD_CALCULATION y_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_y >> 1); x_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_x >> 1); bottom = (svga->monitor->mon_overscan_y >> 1); +#else + y_start = enable_overscan ? 0 : svga->y_add; + x_start = enable_overscan ? 0 : svga->left_overscan; + bottom = svga->monitor->mon_overscan_y - svga->y_add; +#endif if (svga->vertical_linedbl) { y_add <<= 1; From d55f6b28875a7f4ffc94d0303a49835ea13dc9de Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sun, 4 May 2025 18:06:07 -0400 Subject: [PATCH 1052/1190] Some cleanups in isamem and isartc --- src/device/isamem.c | 4 ++-- src/device/isartc.c | 4 ++-- src/include/86box/isamem.h | 8 +------- src/include/86box/isartc.h | 5 +---- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/device/isamem.c b/src/device/isamem.c index 62fb96f5d..b1095da1f 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -2165,12 +2165,12 @@ isamem_get_internal_name(int board) } int -isamem_get_from_internal_name(const char *s) +isamem_get_from_internal_name(const char *str) { int c = 0; while (boards[c].dev != NULL) { - if (!strcmp(boards[c].dev->internal_name, s)) + if (!strcmp(boards[c].dev->internal_name, str)) return c; c++; } diff --git a/src/device/isartc.c b/src/device/isartc.c index 5d6b4aea4..b5bbda7b0 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -919,12 +919,12 @@ isartc_get_internal_name(int board) } int -isartc_get_from_internal_name(char *s) +isartc_get_from_internal_name(const char *str) { int c = 0; while (boards[c].dev != NULL) { - if (!strcmp(boards[c].dev->internal_name, s)) + if (!strcmp(boards[c].dev->internal_name, str)) return c; c++; } diff --git a/src/include/86box/isamem.h b/src/include/86box/isamem.h index 51fe50e33..93f417e3e 100644 --- a/src/include/86box/isamem.h +++ b/src/include/86box/isamem.h @@ -42,7 +42,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #ifndef EMU_ISAMEM_H #define EMU_ISAMEM_H @@ -52,17 +51,12 @@ extern "C" { #endif -/* Global variables. */ -extern const device_t isamem_device; -extern const device_t isamem_brat80_device; -extern const device_t isamem_ev159_device; - /* Functions. */ extern void isamem_reset(void); extern const char *isamem_get_name(int t); extern const char *isamem_get_internal_name(int t); -extern int isamem_get_from_internal_name(const char *s); +extern int isamem_get_from_internal_name(const char *str); extern const device_t *isamem_get_device(int t); extern int isamem_has_config(int board); diff --git a/src/include/86box/isartc.h b/src/include/86box/isartc.h index 0224180b3..815daa5d6 100644 --- a/src/include/86box/isartc.h +++ b/src/include/86box/isartc.h @@ -42,7 +42,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #ifndef EMU_ISARTC_H #define EMU_ISARTC_H @@ -50,13 +49,11 @@ extern "C" { #endif -/* Global variables. */ - /* Functions. */ extern void isartc_reset(void); extern const char *isartc_get_internal_name(int t); -extern int isartc_get_from_internal_name(char *s); +extern int isartc_get_from_internal_name(const char *str); extern const device_t *isartc_get_device(int t); extern int isartc_has_config(int board); From c992a44b44b8a298b3cbbdebf7cb473b8cc4788b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sun, 4 May 2025 19:30:48 -0400 Subject: [PATCH 1053/1190] Clean QT Other Peripherals UI --- src/qt/qt_settingsotherperipherals.cpp | 161 +++++++++++++------------ src/qt/qt_settingsotherperipherals.hpp | 23 ++-- src/qt/qt_settingsotherperipherals.ui | 140 ++++++++++----------- 3 files changed, 164 insertions(+), 160 deletions(-) diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index e1920bf47..b8a347f25 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -11,8 +11,10 @@ * * * Authors: Joakim L. Gilje <jgilje@jgilje.net> + * Jasmine Iwanek <jriwanek@gmail.com> * * Copyright 2021 Joakim L. Gilje + * Copyright 2025 Jasmine Iwanek */ #include "qt_settingsotherperipherals.hpp" #include "ui_qt_settingsotherperipherals.h" @@ -44,84 +46,86 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) this->machineId = machineId; bool machineHasIsa = (machine_has_bus(machineId, MACHINE_BUS_ISA) > 0); + + ui->pushButtonConfigureRTC->setEnabled(machineHasIsa); + ui->comboBoxRTC->setEnabled(machineHasIsa); + ui->checkBoxISABugger->setEnabled(machineHasIsa); + ui->pushButtonConfigureUT->setEnabled(unittester_enabled > 0); + ui->checkBoxKeyCard->setEnabled(machineHasIsa); + ui->pushButtonConfigureKeyCard->setEnabled(novell_keycard_enabled > 0); + ui->checkBoxISABugger->setChecked((machineHasIsa && (bugger_enabled > 0)) ? true : false); ui->checkBoxPOSTCard->setChecked(postcard_enabled > 0 ? true : false); ui->checkBoxUnitTester->setChecked(unittester_enabled > 0 ? true : false); ui->checkBoxKeyCard->setChecked((machineHasIsa && (novell_keycard_enabled > 0)) ? true : false); - ui->checkBoxISABugger->setEnabled(machineHasIsa); - ui->checkBoxKeyCard->setEnabled(machineHasIsa); - ui->pushButtonConfigureKeyCard->setEnabled(novell_keycard_enabled > 0); - ui->pushButtonConfigureUT->setEnabled(unittester_enabled > 0); - ui->comboBoxRTC->setEnabled(machineHasIsa); - ui->pushButtonConfigureRTC->setEnabled(machineHasIsa); - ui->comboBoxCard1->clear(); - ui->comboBoxCard2->clear(); - ui->comboBoxCard3->clear(); - ui->comboBoxCard4->clear(); ui->comboBoxRTC->clear(); - auto *model = ui->comboBoxRTC->model(); - int d = 0; + for (uint8_t i = 0; i < ISAMEM_MAX; ++i) + if (auto *cb = findChild<QComboBox *>(QString("comboBoxIsaMemCard%1").arg(i + 1))) + cb->clear(); + + int c = 0; int selectedRow = 0; + + // ISA RTC Cards + auto *model = ui->comboBoxRTC->model(); while (true) { - QString name = DeviceConfig::DeviceName(isartc_get_device(d), isartc_get_internal_name(d), 0); - if (name.isEmpty()) { + const QString name = DeviceConfig::DeviceName(isartc_get_device(c), isartc_get_internal_name(c), 0); + if (name.isEmpty()) break; - } - if (!device_is_valid(isartc_get_device(d), machineId)) { + if (!device_is_valid(isartc_get_device(c), machineId)) break; - } - int row = Models::AddEntry(model, name, d); - if (d == isartc_type) { + int row = Models::AddEntry(model, name, c); + if (c == isartc_type) selectedRow = row; - } - ++d; + + ++c; } ui->comboBoxRTC->setCurrentIndex(selectedRow); ui->pushButtonConfigureRTC->setEnabled((isartc_type != 0) && isartc_has_config(isartc_type) && machineHasIsa); - // ISA Memory Expansion Card - QComboBox * cbox[ISAMEM_MAX] = { 0 }; - QAbstractItemModel *models[ISAMEM_MAX] = { 0 }; - int removeRows_[ISAMEM_MAX] = { 0 }; - int selectedRows[ISAMEM_MAX] = { 0 }; + // ISA Memory Expansion Cards + QComboBox *isamem_cbox[ISAMEM_MAX] = { 0 }; + QAbstractItemModel *isamem_models[ISAMEM_MAX] = { 0 }; + int isamem_removeRows_[ISAMEM_MAX] = { 0 }; + int isamem_selectedRows[ISAMEM_MAX] = { 0 }; - for (uint8_t c = 0; c < ISAMEM_MAX; ++c) { - cbox[c] = findChild<QComboBox *>(QString("comboBoxCard%1").arg(c + 1)); - models[c] = cbox[c]->model(); - removeRows_[c] = models[c]->rowCount(); + for (uint8_t i = 0; i < ISAMEM_MAX; ++i) { + isamem_cbox[i] = findChild<QComboBox *>(QString("comboBoxIsaMemCard%1").arg(i + 1)); + isamem_models[i] = isamem_cbox[i]->model(); + isamem_removeRows_[i] = isamem_models[i]->rowCount(); } - d = 0; + c = 0; while (true) { - const QString name = DeviceConfig::DeviceName(isamem_get_device(d), - isamem_get_internal_name(d), 0); + const QString name = DeviceConfig::DeviceName(isamem_get_device(c), + isamem_get_internal_name(c), 0); if (name.isEmpty()) break; - if (device_is_valid(isamem_get_device(d), machineId)) { - for (uint8_t c = 0; c < ISAMEM_MAX; ++c) { - int row = Models::AddEntry(models[c], name, d); + if (device_is_valid(isamem_get_device(c), machineId)) { + for (uint8_t i = 0; i < ISAMEM_MAX; ++i) { + int row = Models::AddEntry(isamem_models[i], name, c); - if (d == isamem_type[c]) - selectedRows[c] = row - removeRows_[c]; + if (c == isamem_type[i]) + isamem_selectedRows[i] = row - isamem_removeRows_[i]; } } - d++; + c++; } - for (uint8_t c = 0; c < ISAMEM_MAX; ++c) { - models[c]->removeRows(0, removeRows_[c]); - cbox[c]->setEnabled(models[c]->rowCount() > 1); - cbox[c]->setCurrentIndex(-1); - cbox[c]->setCurrentIndex(selectedRows[c]); - findChild<QPushButton *>(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled((isamem_type[c] != 0) && - isamem_has_config(isamem_type[c]) && machineHasIsa); + for (uint8_t i = 0; i < ISAMEM_MAX; ++i) { + isamem_models[i]->removeRows(0, isamem_removeRows_[i]); + isamem_cbox[i]->setEnabled(isamem_models[i]->rowCount() > 1); + isamem_cbox[i]->setCurrentIndex(-1); + isamem_cbox[i]->setCurrentIndex(isamem_selectedRows[i]); + findChild<QPushButton *>(QString("pushButtonConfigureIsaMemCard%1").arg(i + 1))->setEnabled((isamem_type[i] != 0) && + isamem_has_config(isamem_type[i]) && machineHasIsa); } } @@ -134,15 +138,15 @@ void SettingsOtherPeripherals::save() { /* Other peripherals category */ + isartc_type = ui->comboBoxRTC->currentData().toInt(); bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0; unittester_enabled = ui->checkBoxUnitTester->isChecked() ? 1 : 0; novell_keycard_enabled = ui->checkBoxKeyCard->isChecked() ? 1 : 0; - isartc_type = ui->comboBoxRTC->currentData().toInt(); /* ISA memory boards. */ for (int i = 0; i < ISAMEM_MAX; i++) { - auto *cbox = findChild<QComboBox *>(QString("comboBoxCard%1").arg(i + 1)); + auto *cbox = findChild<QComboBox *>(QString("comboBoxIsaMemCard%1").arg(i + 1)); isamem_type[i] = cbox->currentData().toInt(); } } @@ -150,9 +154,9 @@ SettingsOtherPeripherals::save() void SettingsOtherPeripherals::on_comboBoxRTC_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonConfigureRTC->setEnabled((index != 0) && isartc_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } @@ -163,63 +167,63 @@ SettingsOtherPeripherals::on_pushButtonConfigureRTC_clicked() } void -SettingsOtherPeripherals::on_comboBoxCard1_currentIndexChanged(int index) +SettingsOtherPeripherals::on_comboBoxIsaMemCard1_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } - ui->pushButtonConfigureCard1->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); + + ui->pushButtonConfigureIsaMemCard1->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void -SettingsOtherPeripherals::on_pushButtonConfigureCard1_clicked() +SettingsOtherPeripherals::on_pushButtonConfigureIsaMemCard1_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard1->currentData().toInt()), 1); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxIsaMemCard1->currentData().toInt()), 1); } void -SettingsOtherPeripherals::on_comboBoxCard2_currentIndexChanged(int index) +SettingsOtherPeripherals::on_comboBoxIsaMemCard2_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } - ui->pushButtonConfigureCard2->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); + + ui->pushButtonConfigureIsaMemCard2->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void -SettingsOtherPeripherals::on_pushButtonConfigureCard2_clicked() +SettingsOtherPeripherals::on_pushButtonConfigureIsaMemCard2_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard2->currentData().toInt()), 2); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxIsaMemCard2->currentData().toInt()), 2); } void -SettingsOtherPeripherals::on_comboBoxCard3_currentIndexChanged(int index) +SettingsOtherPeripherals::on_comboBoxIsaMemCard3_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } - ui->pushButtonConfigureCard3->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); + + ui->pushButtonConfigureIsaMemCard3->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void -SettingsOtherPeripherals::on_pushButtonConfigureCard3_clicked() +SettingsOtherPeripherals::on_pushButtonConfigureIsaMemCard3_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard3->currentData().toInt()), 3); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxIsaMemCard3->currentData().toInt()), 3); } void -SettingsOtherPeripherals::on_comboBoxCard4_currentIndexChanged(int index) +SettingsOtherPeripherals::on_comboBoxIsaMemCard4_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } - ui->pushButtonConfigureCard4->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); + + ui->pushButtonConfigureIsaMemCard4->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void -SettingsOtherPeripherals::on_pushButtonConfigureCard4_clicked() +SettingsOtherPeripherals::on_pushButtonConfigureIsaMemCard4_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()), 4); + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxIsaMemCard4->currentData().toInt()), 4); } void @@ -234,13 +238,12 @@ SettingsOtherPeripherals::on_pushButtonConfigureUT_clicked() DeviceConfig::ConfigureDevice(&unittester_device); } -void SettingsOtherPeripherals::on_pushButtonConfigureKeyCard_clicked() -{ - DeviceConfig::ConfigureDevice(&novell_keycard_device); -} - void SettingsOtherPeripherals::on_checkBoxKeyCard_stateChanged(int arg1) { ui->pushButtonConfigureKeyCard->setEnabled(arg1 != 0); } +void SettingsOtherPeripherals::on_pushButtonConfigureKeyCard_clicked() +{ + DeviceConfig::ConfigureDevice(&novell_keycard_device); +} diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index d5804a68b..e87219ab7 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -20,22 +20,23 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonConfigureCard4_clicked(); - void on_comboBoxCard4_currentIndexChanged(int index); - void on_pushButtonConfigureCard3_clicked(); - void on_comboBoxCard3_currentIndexChanged(int index); - void on_pushButtonConfigureCard2_clicked(); - void on_comboBoxCard2_currentIndexChanged(int index); - void on_pushButtonConfigureCard1_clicked(); - void on_comboBoxCard1_currentIndexChanged(int index); - void on_pushButtonConfigureRTC_clicked(); void on_comboBoxRTC_currentIndexChanged(int index); + void on_pushButtonConfigureRTC_clicked(); + + void on_comboBoxIsaMemCard1_currentIndexChanged(int index); + void on_pushButtonConfigureIsaMemCard1_clicked(); + void on_comboBoxIsaMemCard2_currentIndexChanged(int index); + void on_pushButtonConfigureIsaMemCard2_clicked(); + void on_comboBoxIsaMemCard3_currentIndexChanged(int index); + void on_pushButtonConfigureIsaMemCard3_clicked(); + void on_comboBoxIsaMemCard4_currentIndexChanged(int index); + void on_pushButtonConfigureIsaMemCard4_clicked(); + void on_checkBoxUnitTester_stateChanged(int arg1); void on_pushButtonConfigureUT_clicked(); - void on_pushButtonConfigureKeyCard_clicked(); - void on_checkBoxKeyCard_stateChanged(int arg1); + void on_pushButtonConfigureKeyCard_clicked(); private: Ui::SettingsOtherPeripherals *ui; diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index 41df2deac..81b0e0018 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -27,9 +27,9 @@ <number>0</number> </property> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayoutRtc"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelRtc"> <property name="text"> <string>ISA RTC:</string> </property> @@ -58,20 +58,74 @@ </layout> </item> <item> - <widget class="QGroupBox" name="groupBox"> + <widget class="QGroupBox" name="groupBoxMem"> <property name="title"> <string>ISA Memory Expansion</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="2"> - <widget class="QPushButton" name="pushButtonConfigureCard2"> + <layout class="QGridLayout" name="gridLayoutMem"> + <item row="0" column="0"> + <widget class="QLabel" name="labelIsaMemCard1"> + <property name="text"> + <string>Card 1:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxIsaMemCard1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="pushButtonConfigureIsaMemCard1"> <property name="text"> <string>Configure</string> </property> </widget> </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelIsaMemCard2"> + <property name="text"> + <string>Card 2:</string> + </property> + </widget> + </item> <item row="1" column="1"> - <widget class="QComboBox" name="comboBoxCard2"> + <widget class="QComboBox" name="comboBoxIsaMemCard2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButtonConfigureIsaMemCard2"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelIsaMemCard3"> + <property name="text"> + <string>Card 3:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="comboBoxIsaMemCard3"> <property name="sizePolicy"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -84,68 +138,21 @@ </widget> </item> <item row="2" column="2"> - <widget class="QPushButton" name="pushButtonConfigureCard3"> + <widget class="QPushButton" name="pushButtonConfigureIsaMemCard3"> <property name="text"> <string>Configure</string> </property> </widget> </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_3"> + <item row="3" column="0"> + <widget class="QLabel" name="labelIsaMemCard4"> <property name="text"> - <string>Card 2:</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Card 3:</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QPushButton" name="pushButtonConfigureCard1"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBoxCard1"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maxVisibleItems"> - <number>30</number> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Card 1:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="comboBoxCard3"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maxVisibleItems"> - <number>30</number> + <string>Card 4:</string> </property> </widget> </item> <item row="3" column="1"> - <widget class="QComboBox" name="comboBoxCard4"> + <widget class="QComboBox" name="comboBoxIsaMemCard4"> <property name="sizePolicy"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -158,24 +165,17 @@ </widget> </item> <item row="3" column="2"> - <widget class="QPushButton" name="pushButtonConfigureCard4"> + <widget class="QPushButton" name="pushButtonConfigureIsaMemCard4"> <property name="text"> <string>Configure</string> </property> </widget> </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Card 4:</string> - </property> - </widget> - </item> </layout> </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayoutIBPC"> <item> <widget class="QCheckBox" name="checkBoxISABugger"> <property name="text"> @@ -193,7 +193,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> + <layout class="QHBoxLayout" name="horizontalLayoutUT"> <item> <widget class="QCheckBox" name="checkBoxUnitTester"> <property name="sizePolicy"> @@ -217,7 +217,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> + <layout class="QHBoxLayout" name="horizontalLayoutKeyCard"> <property name="topMargin"> <number>0</number> </property> From dee023dc1c2ebb42d55cc488aca1fe5d82e28a33 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Tue, 6 May 2025 00:59:56 -0400 Subject: [PATCH 1054/1190] Segfault fixes in rom.c --- src/mem/rom.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/mem/rom.c b/src/mem/rom.c index 666652d53..d22454983 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -97,7 +97,8 @@ rom_check(const char *fn) else { fp = fopen(fn, "rb"); ret = (fp != NULL); - fclose(fp); + if (fp != NULL) + fclose(fp); } return ret; @@ -134,6 +135,9 @@ rom_fopen(const char *fn, char *mode) char temp[1024]; FILE *fp = NULL; + if ((fn == NULL) || (mode == NULL)) + return NULL; + if (strstr(fn, "roms/") == fn) { /* Relative path */ for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) { @@ -324,7 +328,8 @@ rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t } } - (void) fclose(fp); + if (fp != NULL) + (void) fclose(fp); return 1; } @@ -353,7 +358,8 @@ rom_load_linear(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) fatal("rom_load_linear(): Error reading data\n"); } - (void) fclose(fp); + if (fp != NULL) + (void) fclose(fp); return 1; } @@ -397,7 +403,8 @@ rom_load_linear_inverted(const char *fn, uint32_t addr, int sz, int off, uint8_t } } - (void) fclose(fp); + if (fp != NULL) + (void) fclose(fp); return 1; } @@ -438,8 +445,10 @@ rom_load_interleaved(const char *fnl, const char *fnh, uint32_t addr, int sz, in } } - (void) fclose(fph); - (void) fclose(fpl); + if (fph != NULL) + (void) fclose(fph); + if (fpl != NULL) + (void) fclose(fpl); return 1; } From 577397b40bd0aaaa84d80b8a57e369d2b193c36f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Tue, 6 May 2025 01:00:08 -0400 Subject: [PATCH 1055/1190] Typo fix in rom.c --- src/mem/rom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/rom.c b/src/mem/rom.c index d22454983..f7b2b2b0d 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -324,7 +324,7 @@ rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t } for (int i = 0; i < (sz >> 1); i++) { if (fread(ptr + (addr + (i << 1) + 1), 1, 1, fp) != 1) - fatal("rom_load_linear(): Error reading od data\n"); + fatal("rom_load_linear(): Error reading odd data\n"); } } From af93cd66ec25a895ef715f3ba35bb61aede81390 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Tue, 6 May 2025 02:33:15 -0400 Subject: [PATCH 1056/1190] Clean QT Sound UI --- src/qt/qt_settingssound.cpp | 49 ++++----- src/qt/qt_settingssound.hpp | 26 +++-- src/qt/qt_settingssound.ui | 199 ++++++++++++++++++------------------ 3 files changed, 133 insertions(+), 141 deletions(-) diff --git a/src/qt/qt_settingssound.cpp b/src/qt/qt_settingssound.cpp index e49e1ae27..57e278515 100644 --- a/src/qt/qt_settingssound.cpp +++ b/src/qt/qt_settingssound.cpp @@ -14,7 +14,7 @@ * Jasmine Iwanek <jriwanek@gmail.com> * * Copyright 2021 Joakim L. Gilje - * Copyright 2022-2023 Jasmine Iwanek + * Copyright 2022-2025 Jasmine Iwanek */ #include "qt_settingssound.hpp" #include "ui_qt_settingssound.h" @@ -76,8 +76,8 @@ SettingsSound::onCurrentMachineChanged(const int machineId) int c; int selectedRow; - // Sound Card - QComboBox * cbox[SOUND_CARD_MAX] = { 0 }; + // Sound Cards + QComboBox *cbox[SOUND_CARD_MAX] = { 0 }; QAbstractItemModel *models[SOUND_CARD_MAX] = { 0 }; int removeRows_[SOUND_CARD_MAX] = { 0 }; int selectedRows[SOUND_CARD_MAX] = { 0 }; @@ -89,7 +89,7 @@ SettingsSound::onCurrentMachineChanged(const int machineId) removeRows_[i] = models[i]->rowCount(); } - c = 0; + c = 0; while (true) { const QString name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); @@ -110,7 +110,7 @@ SettingsSound::onCurrentMachineChanged(const int machineId) } } - c++; + c++; } for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { @@ -122,21 +122,19 @@ SettingsSound::onCurrentMachineChanged(const int machineId) // Midi Out c = 0; - auto model = ui->comboBoxMidiOut->model(); + auto *model = ui->comboBoxMidiOut->model(); auto removeRows = model->rowCount(); selectedRow = 0; while (true) { const QString name = DeviceConfig::DeviceName(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0); - if (name.isEmpty()) { + if (name.isEmpty()) break; - } if (midi_out_device_available(c)) { int row = Models::AddEntry(model, name, c); - if (c == midi_output_device_current) { + if (c == midi_output_device_current) selectedRow = row - removeRows; - } } c++; @@ -155,15 +153,13 @@ SettingsSound::onCurrentMachineChanged(const int machineId) while (true) { const QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0); - if (name.isEmpty()) { + if (name.isEmpty()) break; - } if (midi_in_device_available(c)) { int row = Models::AddEntry(model, name, c); - if (c == midi_input_device_current) { + if (c == midi_input_device_current) selectedRow = row - removeRows; - } } c++; @@ -198,13 +194,11 @@ allowMpu401(Ui::SettingsSound *ui) QString midiOut = midi_out_device_get_internal_name(ui->comboBoxMidiOut->currentData().toInt()); QString midiIn = midi_in_device_get_internal_name(ui->comboBoxMidiIn->currentData().toInt()); - if (midiOut.isEmpty()) { + if (midiOut.isEmpty()) return false; - } - if (midiOut == QStringLiteral("none") && midiIn == QStringLiteral("none")) { + if (midiOut == QStringLiteral("none") && midiIn == QStringLiteral("none")) return false; - } return true; } @@ -212,9 +206,9 @@ allowMpu401(Ui::SettingsSound *ui) void SettingsSound::on_comboBoxSoundCard1_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + int sndCard = ui->comboBoxSoundCard1->currentData().toInt(); if (sndCard == SOUND_INTERNAL) @@ -238,9 +232,8 @@ SettingsSound::on_pushButtonConfigureSoundCard1_clicked() void SettingsSound::on_comboBoxSoundCard2_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); @@ -258,9 +251,8 @@ SettingsSound::on_pushButtonConfigureSoundCard2_clicked() void SettingsSound::on_comboBoxSoundCard3_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); @@ -279,9 +271,8 @@ SettingsSound::on_pushButtonConfigureSoundCard3_clicked() void SettingsSound::on_comboBoxSoundCard4_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); @@ -300,9 +291,8 @@ SettingsSound::on_pushButtonConfigureSoundCard4_clicked() void SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } ui->pushButtonConfigureMidiOut->setEnabled(midi_out_device_has_config(ui->comboBoxMidiOut->currentData().toInt())); ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA))); @@ -318,9 +308,8 @@ SettingsSound::on_pushButtonConfigureMidiOut_clicked() void SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } ui->pushButtonConfigureMidiIn->setEnabled(midi_in_device_has_config(ui->comboBoxMidiIn->currentData().toInt())); ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA))); diff --git a/src/qt/qt_settingssound.hpp b/src/qt/qt_settingssound.hpp index 92b700c92..cc2926d5d 100644 --- a/src/qt/qt_settingssound.hpp +++ b/src/qt/qt_settingssound.hpp @@ -20,20 +20,26 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonConfigureMPU401_clicked(); - void on_checkBoxMPU401_stateChanged(int arg1); - void on_pushButtonConfigureMidiIn_clicked(); - void on_pushButtonConfigureMidiOut_clicked(); - void on_comboBoxMidiIn_currentIndexChanged(int index); - void on_comboBoxMidiOut_currentIndexChanged(int index); - void on_pushButtonConfigureSoundCard1_clicked(); void on_comboBoxSoundCard1_currentIndexChanged(int index); - void on_pushButtonConfigureSoundCard2_clicked(); + void on_pushButtonConfigureSoundCard1_clicked(); + void on_comboBoxSoundCard2_currentIndexChanged(int index); - void on_pushButtonConfigureSoundCard3_clicked(); + void on_pushButtonConfigureSoundCard2_clicked(); + void on_comboBoxSoundCard3_currentIndexChanged(int index); - void on_pushButtonConfigureSoundCard4_clicked(); + void on_pushButtonConfigureSoundCard3_clicked(); + void on_comboBoxSoundCard4_currentIndexChanged(int index); + void on_pushButtonConfigureSoundCard4_clicked(); + + void on_comboBoxMidiOut_currentIndexChanged(int index); + void on_pushButtonConfigureMidiOut_clicked(); + + void on_comboBoxMidiIn_currentIndexChanged(int index); + void on_pushButtonConfigureMidiIn_clicked(); + + void on_checkBoxMPU401_stateChanged(int arg1); + void on_pushButtonConfigureMPU401_clicked(); private: Ui::SettingsSound *ui; diff --git a/src/qt/qt_settingssound.ui b/src/qt/qt_settingssound.ui index 1d5ab0050..97ef7c3ff 100644 --- a/src/qt/qt_settingssound.ui +++ b/src/qt/qt_settingssound.ui @@ -26,17 +26,23 @@ <property name="bottomMargin"> <number>0</number> </property> - <item row="5" column="0"> - <widget class="QLabel" name="label_3"> + <item row="0" column="0"> + <widget class="QLabel" name="labelSoundCard1"> <property name="text"> - <string>MIDI In Device:</string> + <string>Sound card #1:</string> </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Sound card #1:</string> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxSoundCard1"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> </widget> </item> @@ -48,12 +54,25 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_4"> + <widget class="QLabel" name="labelSoundCard2"> <property name="text"> <string>Sound card #2:</string> </property> </widget> </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBoxSoundCard2"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> <item row="1" column="3"> <widget class="QPushButton" name="pushButtonConfigureSoundCard2"> <property name="text"> @@ -62,12 +81,25 @@ </widget> </item> <item row="2" column="0"> - <widget class="QLabel" name="label_5"> + <widget class="QLabel" name="labelSoundCard3"> <property name="text"> <string>Sound card #3:</string> </property> </widget> </item> + <item row="2" column="1"> + <widget class="QComboBox" name="comboBoxSoundCard3"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> <item row="2" column="3"> <widget class="QPushButton" name="pushButtonConfigureSoundCard3"> <property name="text"> @@ -75,14 +107,26 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_6"> + <widget class="QLabel" name="labelSoundCard4"> <property name="text"> <string>Sound card #4:</string> </property> </widget> </item> + <item row="3" column="1"> + <widget class="QComboBox" name="comboBoxSoundCard4"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> <item row="3" column="3"> <widget class="QPushButton" name="pushButtonConfigureSoundCard4"> <property name="text"> @@ -90,49 +134,13 @@ </property> </widget> </item> - - - <item row="5" column="1"> - <widget class="QComboBox" name="comboBoxMidiIn"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> <item row="4" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="labelMidiOut"> <property name="text"> <string>MIDI Out Device:</string> </property> </widget> </item> - <item row="6" column="0"> - <widget class="QCheckBox" name="checkBoxMPU401"> - <property name="text"> - <string>Standalone MPU-401</string> - </property> - </widget> - </item> - <item row="6" column="3"> - <widget class="QPushButton" name="pushButtonConfigureMPU401"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="5" column="3"> - <widget class="QPushButton" name="pushButtonConfigureMidiIn"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> <item row="4" column="1"> <widget class="QComboBox" name="comboBoxMidiOut"> <property name="maxVisibleItems"> @@ -153,6 +161,47 @@ </property> </widget> </item> + <item row="5" column="0"> + <widget class="QLabel" name="labelMidiIn"> + <property name="text"> + <string>MIDI In Device:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QComboBox" name="comboBoxMidiIn"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="5" column="3"> + <widget class="QPushButton" name="pushButtonConfigureMidiIn"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QCheckBox" name="checkBoxMPU401"> + <property name="text"> + <string>Standalone MPU-401</string> + </property> + </widget> + </item> + <item row="6" column="3"> + <widget class="QPushButton" name="pushButtonConfigureMPU401"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> <item row="10" column="0"> <widget class="QCheckBox" name="checkBoxFloat32"> <property name="text"> @@ -171,7 +220,7 @@ <property name="title"> <string>FM synth driver</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_1"> + <layout class="QVBoxLayout" name="verticalLayoutFM"> <item> <widget class="QRadioButton" name="radioButtonNuked"> <property name="text"> @@ -202,58 +251,6 @@ </property> </spacer> </item> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBoxSoundCard1"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="comboBoxSoundCard2"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="comboBoxSoundCard3"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QComboBox" name="comboBoxSoundCard4"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> </layout> </widget> <resources/> From 2181ed96ede886ac9eaed94c85e610eea34b3663 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 20:45:24 -0400 Subject: [PATCH 1057/1190] Clean QT Display UI --- src/qt/qt_settingsdisplay.cpp | 42 +++++++++------- src/qt/qt_settingsdisplay.hpp | 23 +++++---- src/qt/qt_settingsdisplay.ui | 94 +++++++++++++++++------------------ 3 files changed, 84 insertions(+), 75 deletions(-) diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index fbe6ab5cc..300dae80e 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -51,22 +51,29 @@ SettingsDisplay::~SettingsDisplay() void SettingsDisplay::save() { - gfxcard[0] = ui->comboBoxVideo->currentData().toInt(); // TODO +#if 0 + for (uint8_t i = 0; i < GFXCARD_MAX; ++i) { + QComboBox *cbox = findChild<QComboBox *>(QString("comboBoxVideo%1").arg(i + 1)); + gfxcard[i] = cbox->currentData().toInt(); + } +#else + gfxcard[0] = ui->comboBoxVideo->currentData().toInt(); for (uint8_t i = 1; i < GFXCARD_MAX; i ++) - gfxcard[i] = ui->comboBoxVideoSecondary->currentData().toInt(); + gfxcard[i] = ui->comboBoxVideoSecondary->currentData().toInt(); +#endif voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; ibm8514_standalone_enabled = ui->checkBox8514->isChecked() ? 1 : 0; xga_standalone_enabled = ui->checkBoxXga->isChecked() ? 1 : 0; - da2_standalone_enabled = ui->checkBoxDa2->isChecked() ? 1 : 0; + da2_standalone_enabled = ui->checkBoxDa2->isChecked() ? 1 : 0; } void SettingsDisplay::onCurrentMachineChanged(int machineId) { // win_settings_video_proc, WM_INITDIALOG - this->machineId = machineId; + this->machineId = machineId; auto curVideoCard = videoCard[0]; auto *model = ui->comboBoxVideo->model(); @@ -98,25 +105,26 @@ SettingsDisplay::onCurrentMachineChanged(int machineId) } model->removeRows(0, removeRows); + // TODO if (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0) { ui->comboBoxVideo->setEnabled(false); ui->comboBoxVideoSecondary->setEnabled(false); - ui->pushButtonConfigureSecondary->setEnabled(false); + ui->pushButtonConfigureVideoSecondary->setEnabled(false); selectedRow = 1; } else { ui->comboBoxVideo->setEnabled(true); ui->comboBoxVideoSecondary->setEnabled(true); - ui->pushButtonConfigureSecondary->setEnabled(true); + ui->pushButtonConfigureVideoSecondary->setEnabled(true); } ui->comboBoxVideo->setCurrentIndex(selectedRow); // TODO for (uint8_t i = 1; i < GFXCARD_MAX; i ++) if (gfxcard[i] == 0) - ui->pushButtonConfigureSecondary->setEnabled(false); + ui->pushButtonConfigureVideoSecondary->setEnabled(false); } void -SettingsDisplay::on_pushButtonConfigure_clicked() +SettingsDisplay::on_pushButtonConfigureVideo_clicked() { int videoCard = ui->comboBoxVideo->currentData().toInt(); auto *device = video_card_getdevice(videoCard); @@ -160,17 +168,17 @@ SettingsDisplay::on_pushButtonConfigureDa2_clicked() void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + static QRegularExpression voodooRegex("3dfx|voodoo|banshee", QRegularExpression::CaseInsensitiveOption); auto curVideoCard_2 = videoCard[1]; videoCard[0] = ui->comboBoxVideo->currentData().toInt(); if (videoCard[0] == VID_INTERNAL) - ui->pushButtonConfigure->setEnabled(machine_has_flags(machineId, MACHINE_VIDEO) && - device_has_config(machine_get_vid_device(machineId))); + ui->pushButtonConfigureVideo->setEnabled(machine_has_flags(machineId, MACHINE_VIDEO) && + device_has_config(machine_get_vid_device(machineId))); else - ui->pushButtonConfigure->setEnabled(video_card_has_config(videoCard[0]) > 0); + ui->pushButtonConfigureVideo->setEnabled(video_card_has_config(videoCard[0]) > 0); bool machineHasPci = machine_has_bus(machineId, MACHINE_BUS_PCI) > 0; ui->pushButtonConfigureVoodoo->setEnabled(machineHasPci && ui->checkBoxVoodoo->isChecked()); @@ -233,7 +241,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) if ((videoCard[1] == 0) || (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0)) { ui->comboBoxVideoSecondary->setCurrentIndex(0); - ui->pushButtonConfigureSecondary->setEnabled(false); + ui->pushButtonConfigureVideoSecondary->setEnabled(false); } // Is the currently selected video card a voodoo? @@ -287,15 +295,15 @@ void SettingsDisplay::on_comboBoxVideoSecondary_currentIndexChanged(int index) { if (index < 0) { - ui->pushButtonConfigureSecondary->setEnabled(false); + ui->pushButtonConfigureVideoSecondary->setEnabled(false); return; } videoCard[1] = ui->comboBoxVideoSecondary->currentData().toInt(); - ui->pushButtonConfigureSecondary->setEnabled(index != 0 && video_card_has_config(videoCard[1]) > 0); + ui->pushButtonConfigureVideoSecondary->setEnabled(index != 0 && video_card_has_config(videoCard[1]) > 0); } void -SettingsDisplay::on_pushButtonConfigureSecondary_clicked() +SettingsDisplay::on_pushButtonConfigureVideoSecondary_clicked() { auto *device = video_card_getdevice(ui->comboBoxVideoSecondary->currentData().toInt()); DeviceConfig::ConfigureDevice(device); diff --git a/src/qt/qt_settingsdisplay.hpp b/src/qt/qt_settingsdisplay.hpp index 854fce658..7eca7cc60 100644 --- a/src/qt/qt_settingsdisplay.hpp +++ b/src/qt/qt_settingsdisplay.hpp @@ -22,22 +22,23 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonConfigureSecondary_clicked(); - -private slots: - void on_comboBoxVideoSecondary_currentIndexChanged(int index); - -private slots: - void on_checkBoxVoodoo_stateChanged(int state); - void on_checkBox8514_stateChanged(int state); - void on_checkBoxXga_stateChanged(int state); - void on_checkBoxDa2_stateChanged(int state); void on_comboBoxVideo_currentIndexChanged(int index); + void on_pushButtonConfigureVideo_clicked(); + + void on_comboBoxVideoSecondary_currentIndexChanged(int index); + void on_pushButtonConfigureVideoSecondary_clicked(); + + void on_checkBoxVoodoo_stateChanged(int state); void on_pushButtonConfigureVoodoo_clicked(); + + void on_checkBox8514_stateChanged(int state); void on_pushButtonConfigure8514_clicked(); + + void on_checkBoxXga_stateChanged(int state); void on_pushButtonConfigureXga_clicked(); + + void on_checkBoxDa2_stateChanged(int state); void on_pushButtonConfigureDa2_clicked(); - void on_pushButtonConfigure_clicked(); private: Ui::SettingsDisplay *ui; diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index a8799204c..c5eba7adf 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -26,28 +26,8 @@ <property name="bottomMargin"> <number>0</number> </property> - <item row="1" column="2"> - <widget class="QPushButton" name="pushButtonConfigure"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="6" column="0" colspan="2"> - <widget class="QCheckBox" name="checkBoxXga"> - <property name="text"> - <string>XGA Graphics</string> - </property> - </widget> - </item> <item row="0" column="0"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelVideo"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -72,15 +52,21 @@ </property> </widget> </item> - <item row="4" column="2"> - <widget class="QPushButton" name="pushButtonConfigureVoodoo"> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButtonConfigureVideo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string>Configure</string> </property> </widget> </item> <item row="2" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="labelVideoSecondary"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -92,10 +78,23 @@ </property> </widget> </item> - <item row="5" column="0" colspan="2"> - <widget class="QCheckBox" name="checkBox8514"> + <item row="3" column="0" colspan="2"> + <widget class="QComboBox" name="comboBoxVideoSecondary"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QPushButton" name="pushButtonConfigureVideoSecondary"> <property name="text"> - <string>IBM 8514/A Graphics</string> + <string>Configure</string> </property> </widget> </item> @@ -106,6 +105,20 @@ </property> </widget> </item> + <item row="4" column="2"> + <widget class="QPushButton" name="pushButtonConfigureVoodoo"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="5" column="0" colspan="2"> + <widget class="QCheckBox" name="checkBox8514"> + <property name="text"> + <string>IBM 8514/A Graphics</string> + </property> + </widget> + </item> <item row="5" column="2"> <widget class="QPushButton" name="pushButtonConfigure8514"> <property name="text"> @@ -113,6 +126,13 @@ </property> </widget> </item> + <item row="6" column="0" colspan="2"> + <widget class="QCheckBox" name="checkBoxXga"> + <property name="text"> + <string>XGA Graphics</string> + </property> + </widget> + </item> <item row="6" column="2"> <widget class="QPushButton" name="pushButtonConfigureXga"> <property name="text"> @@ -134,26 +154,6 @@ </property> </widget> </item> - <item row="3" column="2"> - <widget class="QPushButton" name="pushButtonConfigureSecondary"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QComboBox" name="comboBoxVideoSecondary"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maxVisibleItems"> - <number>30</number> - </property> - </widget> - </item> <item row="8" column="0" colspan="3"> <spacer name="verticalSpacer"> <property name="orientation"> From c999797f501f3a55fca146ba6fa15d931ba63e17 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 20:48:56 -0400 Subject: [PATCH 1058/1190] Clean QT Floppy/CD-ROM UI --- src/qt/qt_settingsfloppycdrom.cpp | 21 +++++++------ src/qt/qt_settingsfloppycdrom.hpp | 19 +++++++----- src/qt/qt_settingsfloppycdrom.ui | 50 +++++++++++++++---------------- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index 5e0ec7bed..bf1499076 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -359,9 +359,9 @@ SettingsFloppyCDROM::on_comboBoxSpeed_activated(int index) void SettingsFloppyCDROM::on_comboBoxBus_activated(int) { - auto i = ui->tableViewCDROM->selectionModel()->currentIndex().siblingAtColumn(0); + auto i = ui->tableViewCDROM->selectionModel()->currentIndex().siblingAtColumn(0); uint8_t bus_type = ui->comboBoxBus->currentData().toUInt(); - int cdromIdx = ui->tableViewCDROM->selectionModel()->currentIndex().data().toInt(); + int cdromIdx = ui->tableViewCDROM->selectionModel()->currentIndex().data().toInt(); Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, @@ -384,9 +384,9 @@ SettingsFloppyCDROM::on_comboBoxBus_activated(int) auto *modelType = ui->comboBoxCDROMType->model(); int removeRows = modelType->rowCount(); - uint32_t j = 0; - int selectedTypeRow = 0; - int eligibleRows = 0; + uint32_t j = 0; + int selectedTypeRow = 0; + int eligibleRows = 0; while (cdrom_drive_types[j].bus_type != BUS_TYPE_NONE) { if (((bus_type == CDROM_BUS_ATAPI) || (bus_type == CDROM_BUS_SCSI)) && ((cdrom_drive_types[j].bus_type == bus_type) || @@ -414,11 +414,10 @@ void SettingsFloppyCDROM::enableCurrentlySelectedChannel() { const auto *item_model = qobject_cast<QStandardItemModel*>(ui->comboBoxChannel->model()); - const auto index = ui->comboBoxChannel->currentIndex(); - auto *item = item_model->item(index); - if(item) { + const auto index = ui->comboBoxChannel->currentIndex(); + auto *item = item_model->item(index); + if(item) item->setEnabled(true); - } } void @@ -449,9 +448,9 @@ SettingsFloppyCDROM::on_comboBoxCDROMType_activated(int) ui->tableViewCDROM->resizeColumnsToContents(); ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - int speed = cdrom_get_speed(type); + int speed = cdrom_get_speed(type); if (speed == -1) { - speed = ui->comboBoxSpeed->currentData().toUInt(); + speed = ui->comboBoxSpeed->currentData().toUInt(); ui->comboBoxSpeed->setEnabled(true); } else ui->comboBoxSpeed->setEnabled(false); diff --git a/src/qt/qt_settingsfloppycdrom.hpp b/src/qt/qt_settingsfloppycdrom.hpp index 0a3424216..063942201 100644 --- a/src/qt/qt_settingsfloppycdrom.hpp +++ b/src/qt/qt_settingsfloppycdrom.hpp @@ -19,17 +19,20 @@ public: signals: void cdromChannelChanged(); + private slots: - void on_comboBoxCDROMType_activated(int index); - void on_comboBoxChannel_activated(int index); - void on_comboBoxBus_activated(int index); - void on_comboBoxSpeed_activated(int index); - void on_comboBoxBus_currentIndexChanged(int index); - void on_comboBoxFloppyType_activated(int index); - void on_checkBoxCheckBPB_stateChanged(int arg1); - void on_checkBoxTurboTimings_stateChanged(int arg1); void onFloppyRowChanged(const QModelIndex &current); + void on_comboBoxFloppyType_activated(int index); + void on_checkBoxTurboTimings_stateChanged(int arg1); + void on_checkBoxCheckBPB_stateChanged(int arg1); + void onCDROMRowChanged(const QModelIndex &current); + void on_comboBoxBus_activated(int index); + void on_comboBoxBus_currentIndexChanged(int index); + void on_comboBoxChannel_activated(int index); + void on_comboBoxSpeed_activated(int index); + void on_comboBoxCDROMType_activated(int index); + private: Ui::SettingsFloppyCDROM *ui; diff --git a/src/qt/qt_settingsfloppycdrom.ui b/src/qt/qt_settingsfloppycdrom.ui index b9a937d8d..7dde46631 100644 --- a/src/qt/qt_settingsfloppycdrom.ui +++ b/src/qt/qt_settingsfloppycdrom.ui @@ -27,7 +27,7 @@ <number>0</number> </property> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelFloppy"> <property name="text"> <string>Floppy drives:</string> </property> @@ -68,7 +68,7 @@ <widget class="QWidget" name="floppyControls" native="true"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="labelFloppyType"> <property name="text"> <string>Type:</string> </property> @@ -99,7 +99,7 @@ </widget> </item> <item> - <widget class="QLabel" name="label_6"> + <widget class="QLabel" name="labelCDROM"> <property name="text"> <string>CD-ROM drives:</string> </property> @@ -140,33 +140,12 @@ <widget class="QWidget" name="cdControls" native="true"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="labelBus"> <property name="text"> <string>Bus:</string> </property> </widget> </item> - <item row="0" column="2"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Channel:</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Speed:</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Type:</string> - </property> - </widget> - </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBoxBus"> <property name="maxVisibleItems"> @@ -174,6 +153,13 @@ </property> </widget> </item> + <item row="0" column="2"> + <widget class="QLabel" name="labelChannel"> + <property name="text"> + <string>Channel:</string> + </property> + </widget> + </item> <item row="0" column="3"> <widget class="QComboBox" name="comboBoxChannel"> <property name="maxVisibleItems"> @@ -181,6 +167,13 @@ </property> </widget> </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelSpeed"> + <property name="text"> + <string>Speed:</string> + </property> + </widget> + </item> <item row="1" column="1"> <widget class="QComboBox" name="comboBoxSpeed"> <property name="maxVisibleItems"> @@ -188,6 +181,13 @@ </property> </widget> </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelCDROMType"> + <property name="text"> + <string>Type:</string> + </property> + </widget> + </item> <item row="2" column="1" colspan="3"> <widget class="QComboBox" name="comboBoxCDROMType"> <property name="maxVisibleItems"> From 8aae02244185decc1c380df7d55a7e087a923c6c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 20:52:03 -0400 Subject: [PATCH 1059/1190] Clean QT HDD UI --- src/qt/qt_settingsharddisks.cpp | 42 +++++++++++++-------------------- src/qt/qt_settingsharddisks.hpp | 7 +++--- src/qt/qt_settingsharddisks.ui | 2 +- 3 files changed, 21 insertions(+), 30 deletions(-) diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index 32b677888..6d82f2b77 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -49,9 +49,8 @@ static void normalize_hd_list() { hard_disk_t ihdd[HDD_NUM]; - int j; + int j = 0; - j = 0; memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); for (uint8_t i = 0; i < HDD_NUM; i++) { @@ -75,8 +74,8 @@ static void addRow(QAbstractItemModel *model, hard_disk_t *hd) { const QString userPath = usr_path; - int row = model->rowCount(); + model->insertRow(row); QString busName = Harddrives::BusChannelName(hd->bus_type, hd->channel); @@ -88,11 +87,11 @@ addRow(QAbstractItemModel *model, hard_disk_t *hd) model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannelPrevious); Harddrives::busTrackClass->device_track(1, DEV_HDD, hd->bus_type, hd->channel); QString fileName = hd->fn; - if (fileName.startsWith(userPath, Qt::CaseInsensitive)) { + if (fileName.startsWith(userPath, Qt::CaseInsensitive)) model->setData(model->index(row, ColumnFilename), fileName.mid(userPath.size())); - } else { + else model->setData(model->index(row, ColumnFilename), fileName); - } + model->setData(model->index(row, ColumnFilename), fileName, Qt::UserRole); model->setData(model->index(row, ColumnCylinders), hd->tracks); @@ -120,9 +119,8 @@ SettingsHarddisks::SettingsHarddisks(QWidget *parent) ui->tableView->setModel(model); for (int i = 0; i < HDD_NUM; i++) { - if (hdd[i].bus_type > 0) { + if (hdd[i].bus_type > 0) addRow(model, &hdd[i]); - } } if (model->rowCount() == HDD_NUM) { ui->pushButtonNew->setEnabled(false); @@ -176,9 +174,8 @@ void SettingsHarddisks::reloadBusChannels() { void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } buschangeinprogress = true; auto idx = ui->tableView->selectionModel()->currentIndex(); @@ -226,9 +223,8 @@ SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) void SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } auto idx = ui->tableView->selectionModel()->currentIndex(); if (idx.isValid()) { @@ -250,17 +246,15 @@ SettingsHarddisks::enableCurrentlySelectedChannel() const auto *item_model = qobject_cast<QStandardItemModel*>(ui->comboBoxChannel->model()); const auto index = ui->comboBoxChannel->currentIndex(); auto *item = item_model->item(index); - if(item) { + if(item) item->setEnabled(true); - } } void SettingsHarddisks::on_comboBoxSpeed_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } auto idx = ui->tableView->selectionModel()->currentIndex(); if (idx.isValid()) { @@ -288,20 +282,19 @@ SettingsHarddisks::onTableRowChanged(const QModelIndex &current) auto *model = ui->comboBoxBus->model(); auto match = model->match(model->index(0, 0), Qt::UserRole, bus); - if (!match.isEmpty()) { + if (!match.isEmpty()) ui->comboBoxBus->setCurrentIndex(match.first().row()); - } + model = ui->comboBoxChannel->model(); match = model->match(model->index(0, 0), Qt::UserRole, busChannel); - if (!match.isEmpty()) { + if (!match.isEmpty()) ui->comboBoxChannel->setCurrentIndex(match.first().row()); - } model = ui->comboBoxSpeed->model(); match = model->match(model->index(0, 0), Qt::UserRole, speed); - if (!match.isEmpty()) { + if (!match.isEmpty()) ui->comboBoxSpeed->setCurrentIndex(match.first().row()); - } + reloadBusChannels(); } @@ -358,11 +351,10 @@ void SettingsHarddisks::on_pushButtonRemove_clicked() { auto idx = ui->tableView->selectionModel()->currentIndex(); - if (!idx.isValid()) { + if (!idx.isValid()) return; - } - auto *model = ui->tableView->model(); + auto *model = ui->tableView->model(); const auto col = idx.siblingAtColumn(ColumnBus); Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannel).toInt()); model->removeRow(idx.row()); diff --git a/src/qt/qt_settingsharddisks.hpp b/src/qt/qt_settingsharddisks.hpp index 4bd287d29..f892a79cd 100644 --- a/src/qt/qt_settingsharddisks.hpp +++ b/src/qt/qt_settingsharddisks.hpp @@ -21,14 +21,13 @@ signals: void driveChannelChanged(); private slots: + void on_comboBoxBus_currentIndexChanged(int index); void on_comboBoxChannel_currentIndexChanged(int index); void on_comboBoxSpeed_currentIndexChanged(int index); -private slots: - void on_pushButtonRemove_clicked(); - void on_pushButtonExisting_clicked(); void on_pushButtonNew_clicked(); - void on_comboBoxBus_currentIndexChanged(int index); + void on_pushButtonExisting_clicked(); + void on_pushButtonRemove_clicked(); void onTableRowChanged(const QModelIndex &current); diff --git a/src/qt/qt_settingsharddisks.ui b/src/qt/qt_settingsharddisks.ui index ea69edc5b..f996c76d1 100644 --- a/src/qt/qt_settingsharddisks.ui +++ b/src/qt/qt_settingsharddisks.ui @@ -46,7 +46,7 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayoutHardDisks"> <item> <widget class="QLabel" name="labelBus"> <property name="text"> From 59c3254daf3e89c2c1d6a44f836da4ee2b16cd8d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 21:01:54 -0400 Subject: [PATCH 1060/1190] Clean QT Input UI --- src/qt/qt_settingsinput.cpp | 236 ++++++++++++++++++------------------ src/qt/qt_settingsinput.hpp | 9 +- src/qt/qt_settingsinput.ui | 140 ++++++++++----------- 3 files changed, 191 insertions(+), 194 deletions(-) diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index a7000414c..6d89c511a 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -38,7 +38,7 @@ extern "C" { #include "qt_keybind.hpp" extern MainWindow *main_window; - + // Temporary working copy of key list accelKey acc_keys_t[NUM_ACCELS]; @@ -48,41 +48,40 @@ SettingsInput::SettingsInput(QWidget *parent) { ui->setupUi(this); - QStringList horizontalHeader; - QStringList verticalHeader; - - horizontalHeader.append(tr("Action")); + QStringList horizontalHeader; + QStringList verticalHeader; + + horizontalHeader.append(tr("Action")); horizontalHeader.append(tr("Keybind")); - QTableWidget *keyTable = ui->tableKeys; - keyTable->setRowCount(10); - keyTable->setColumnCount(3); - keyTable->setColumnHidden(2, true); - keyTable->setColumnWidth(0, 200); - keyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - QStringList headers; - //headers << "Action" << "Bound key"; - keyTable->setHorizontalHeaderLabels(horizontalHeader); - keyTable->verticalHeader()->setVisible(false); - keyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - keyTable->setSelectionBehavior(QAbstractItemView::SelectRows); - keyTable->setSelectionMode(QAbstractItemView::SingleSelection); - keyTable->setShowGrid(true); - - // Make a working copy of acc_keys so we can check for dupes later without getting - // confused - for(int x=0;x<NUM_ACCELS;x++) { - strcpy(acc_keys_t[x].name, acc_keys[x].name); - strcpy(acc_keys_t[x].desc, acc_keys[x].desc); - strcpy(acc_keys_t[x].seq, acc_keys[x].seq); - } + QTableWidget *keyTable = ui->tableKeys; + keyTable->setRowCount(10); + keyTable->setColumnCount(3); + keyTable->setColumnHidden(2, true); + keyTable->setColumnWidth(0, 200); + keyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + QStringList headers; + //headers << "Action" << "Bound key"; + keyTable->setHorizontalHeaderLabels(horizontalHeader); + keyTable->verticalHeader()->setVisible(false); + keyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + keyTable->setSelectionBehavior(QAbstractItemView::SelectRows); + keyTable->setSelectionMode(QAbstractItemView::SingleSelection); + keyTable->setShowGrid(true); - refreshInputList(); + // Make a working copy of acc_keys so we can check for dupes later without getting + // confused + for(int x = 0; x < NUM_ACCELS; x++) { + strcpy(acc_keys_t[x].name, acc_keys[x].name); + strcpy(acc_keys_t[x].desc, acc_keys[x].desc); + strcpy(acc_keys_t[x].seq, acc_keys[x].seq); + } + + refreshInputList(); onCurrentMachineChanged(machine); } - SettingsInput::~SettingsInput() { delete ui; @@ -93,16 +92,16 @@ SettingsInput::save() { mouse_type = ui->comboBoxMouse->currentData().toInt(); joystick_type = ui->comboBoxJoystick->currentData().toInt(); - - // Copy accelerators from working set to global set - for(int x=0;x<NUM_ACCELS;x++) { - strcpy(acc_keys[x].name, acc_keys_t[x].name); - strcpy(acc_keys[x].desc, acc_keys_t[x].desc); - strcpy(acc_keys[x].seq, acc_keys_t[x].seq); - } - ProgSettings::reloadStrings(); + + // Copy accelerators from working set to global set + for(int x = 0; x < NUM_ACCELS; x++) { + strcpy(acc_keys[x].name, acc_keys_t[x].name); + strcpy(acc_keys[x].desc, acc_keys_t[x].desc); + strcpy(acc_keys[x].seq, acc_keys_t[x].seq); + } + ProgSettings::reloadStrings(); } - + void SettingsInput::onCurrentMachineChanged(int machineId) { @@ -115,13 +114,11 @@ SettingsInput::onCurrentMachineChanged(int machineId) int selectedRow = 0; for (int i = 0; i < mouse_get_ndev(); ++i) { const auto *dev = mouse_get_device(i); - if ((i == MOUSE_TYPE_INTERNAL) && (machine_has_flags(machineId, MACHINE_MOUSE) == 0)) { + if ((i == MOUSE_TYPE_INTERNAL) && (machine_has_flags(machineId, MACHINE_MOUSE) == 0)) continue; - } - if (device_is_valid(dev, machineId) == 0) { + if (device_is_valid(dev, machineId) == 0) continue; - } QString name = DeviceConfig::DeviceName(dev, mouse_get_internal_name(i), 0); int row = mouseModel->rowCount(); @@ -131,9 +128,8 @@ SettingsInput::onCurrentMachineChanged(int machineId) mouseModel->setData(idx, name, Qt::DisplayRole); mouseModel->setData(idx, i, Qt::UserRole); - if (i == mouse_type) { + if (i == mouse_type) selectedRow = row - removeRows; - } } mouseModel->removeRows(0, removeRows); ui->comboBoxMouse->setCurrentIndex(selectedRow); @@ -141,13 +137,12 @@ SettingsInput::onCurrentMachineChanged(int machineId) int i = 0; const char *joyName = joystick_get_name(i); auto *joystickModel = ui->comboBoxJoystick->model(); - removeRows = joystickModel->rowCount(); - selectedRow = 0; + removeRows = joystickModel->rowCount(); + selectedRow = 0; while (joyName) { int row = Models::AddEntry(joystickModel, tr(joyName).toUtf8().data(), i); - if (i == joystick_type) { + if (i == joystick_type) selectedRow = row - removeRows; - } ++i; joyName = joystick_get_name(i); @@ -159,95 +154,95 @@ SettingsInput::onCurrentMachineChanged(int machineId) void SettingsInput::refreshInputList() { - - for (int x=0;x<NUM_ACCELS;x++) { - ui->tableKeys->setItem(x, 0, new QTableWidgetItem(tr(acc_keys_t[x].desc))); - ui->tableKeys->setItem(x, 1, new QTableWidgetItem(QKeySequence(acc_keys_t[x].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText))); - ui->tableKeys->setItem(x, 2, new QTableWidgetItem(acc_keys_t[x].name)); - } + for (int x = 0; x < NUM_ACCELS; x++) { + ui->tableKeys->setItem(x, 0, new QTableWidgetItem(tr(acc_keys_t[x].desc))); + ui->tableKeys->setItem(x, 1, new QTableWidgetItem(QKeySequence(acc_keys_t[x].seq, QKeySequence::PortableText).toString(QKeySequence::NativeText))); + ui->tableKeys->setItem(x, 2, new QTableWidgetItem(acc_keys_t[x].name)); + } } void SettingsInput::on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn) { - // Enable/disable bind/clear buttons if user clicked valid row - QTableWidgetItem *cell = ui->tableKeys->item(currentRow,1); - if (!cell) - { - ui->pushButtonBind->setEnabled(false); - ui->pushButtonClearBind->setEnabled(false); - } - else - { - ui->pushButtonBind->setEnabled(true); - ui->pushButtonClearBind->setEnabled(true); - } + // Enable/disable bind/clear buttons if user clicked valid row + QTableWidgetItem *cell = ui->tableKeys->item(currentRow,1); + if (!cell) { + ui->pushButtonBind->setEnabled(false); + ui->pushButtonClearBind->setEnabled(false); + } else { + ui->pushButtonBind->setEnabled(true); + ui->pushButtonClearBind->setEnabled(true); + } } void SettingsInput::on_tableKeys_cellDoubleClicked(int row, int col) { - // Edit bind - QTableWidgetItem *cell = ui->tableKeys->item(row,1); - if (!cell) return; - - QKeySequence keyseq = KeyBinder::BindKey(this, cell->text()); - if (keyseq != false) { - // If no change was made, don't change anything. - if (keyseq.toString(QKeySequence::NativeText) == cell->text()) return; - - // Otherwise, check for conflicts. - // Check against the *working* copy - NOT the one in use by the app, - // so we don't test against shortcuts the user already changed. - for(int x=0;x<NUM_ACCELS;x++) - { - if(QString::fromStdString(acc_keys_t[x].seq) == keyseq.toString(QKeySequence::PortableText)) - { - // That key is already in use - main_window->showMessage(MBX_ANSI & MBX_INFO, "Bind conflict", "This key combo is already in use", false); - return; - } - } - // If we made it here, there were no conflicts. - // Go ahead and apply the bind. - - // Find the correct accelerator key entry - int accKeyID = FindAccelerator(ui->tableKeys->item(row,2)->text().toUtf8().constData()); - if (accKeyID < 0) return; // this should never happen - - // Make the change - cell->setText(keyseq.toString(QKeySequence::NativeText)); - strcpy(acc_keys_t[accKeyID].seq, keyseq.toString(QKeySequence::PortableText).toUtf8().constData()); - - refreshInputList(); - } + // Edit bind + QTableWidgetItem *cell = ui->tableKeys->item(row,1); + if (!cell) + return; + + QKeySequence keyseq = KeyBinder::BindKey(this, cell->text()); + if (keyseq != false) { + // If no change was made, don't change anything. + if (keyseq.toString(QKeySequence::NativeText) == cell->text()) + return; + + // Otherwise, check for conflicts. + // Check against the *working* copy - NOT the one in use by the app, + // so we don't test against shortcuts the user already changed. + for(int x = 0; x < NUM_ACCELS; x++) { + if(QString::fromStdString(acc_keys_t[x].seq) == keyseq.toString(QKeySequence::PortableText)) { + // That key is already in use + main_window->showMessage(MBX_ANSI & MBX_INFO, "Bind conflict", "This key combo is already in use", false); + return; + } + } + // If we made it here, there were no conflicts. + // Go ahead and apply the bind. + + // Find the correct accelerator key entry + int accKeyID = FindAccelerator(ui->tableKeys->item(row,2)->text().toUtf8().constData()); + if (accKeyID < 0) + return; // this should never happen + + // Make the change + cell->setText(keyseq.toString(QKeySequence::NativeText)); + strcpy(acc_keys_t[accKeyID].seq, keyseq.toString(QKeySequence::PortableText).toUtf8().constData()); + + refreshInputList(); + } } void SettingsInput::on_pushButtonBind_clicked() { - // Edit bind - QTableWidgetItem *cell = ui->tableKeys->currentItem(); - if (!cell) return; - - on_tableKeys_cellDoubleClicked(cell->row(), cell->column()); + // Edit bind + QTableWidgetItem *cell = ui->tableKeys->currentItem(); + if (!cell) + return; + + on_tableKeys_cellDoubleClicked(cell->row(), cell->column()); } void SettingsInput::on_pushButtonClearBind_clicked() { - // Wipe bind - QTableWidgetItem *cell = ui->tableKeys->item(ui->tableKeys->currentRow(), 1); - if (!cell) return; - - cell->setText(""); - // Find the correct accelerator key entry - int accKeyID = FindAccelerator(ui->tableKeys->item(cell->row(),2)->text().toUtf8().constData()); - if (accKeyID < 0) return; // this should never happen - - // Make the change - cell->setText(""); - strcpy(acc_keys_t[accKeyID].seq, ""); + // Wipe bind + QTableWidgetItem *cell = ui->tableKeys->item(ui->tableKeys->currentRow(), 1); + if (!cell) + return; + + cell->setText(""); + // Find the correct accelerator key entry + int accKeyID = FindAccelerator(ui->tableKeys->item(cell->row(),2)->text().toUtf8().constData()); + if (accKeyID < 0) + return; // this should never happen + + // Make the change + cell->setText(""); + strcpy(acc_keys_t[accKeyID].seq, ""); } void @@ -263,9 +258,9 @@ SettingsInput::on_comboBoxJoystick_currentIndexChanged(int index) int joystickId = ui->comboBoxJoystick->currentData().toInt(); for (int i = 0; i < MAX_JOYSTICKS; ++i) { auto *btn = findChild<QPushButton *>(QString("pushButtonJoystick%1").arg(i + 1)); - if (btn == nullptr) { + if (btn == nullptr) continue; - } + btn->setEnabled(joystick_get_max_joysticks(joystickId) > i); } } @@ -283,9 +278,8 @@ get_axis(JoystickConfiguration &jc, int axis, int joystick_nr) int axis_sel = jc.selectedAxis(axis); int nr_axes = plat_joystick_state[joystick_state[0][joystick_nr].plat_joystick_nr - 1].nr_axes; - if (axis_sel < nr_axes) { + if (axis_sel < nr_axes) return axis_sel; - } axis_sel -= nr_axes; if (axis_sel & 1) diff --git a/src/qt/qt_settingsinput.hpp b/src/qt/qt_settingsinput.hpp index 742421f64..a51ad2564 100644 --- a/src/qt/qt_settingsinput.hpp +++ b/src/qt/qt_settingsinput.hpp @@ -26,17 +26,20 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonConfigureMouse_clicked(); - void on_comboBoxJoystick_currentIndexChanged(int index); void on_comboBoxMouse_currentIndexChanged(int index); + void on_pushButtonConfigureMouse_clicked(); + + void on_comboBoxJoystick_currentIndexChanged(int index); void on_pushButtonJoystick1_clicked(); void on_pushButtonJoystick2_clicked(); void on_pushButtonJoystick3_clicked(); void on_pushButtonJoystick4_clicked(); + void on_tableKeys_cellDoubleClicked(int row, int col); void on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); - void on_pushButtonBind_clicked(); + void on_pushButtonClearBind_clicked(); + void on_pushButtonBind_clicked(); private: Ui::SettingsInput *ui; diff --git a/src/qt/qt_settingsinput.ui b/src/qt/qt_settingsinput.ui index b7074eeaa..6ac6cf38a 100644 --- a/src/qt/qt_settingsinput.ui +++ b/src/qt/qt_settingsinput.ui @@ -23,6 +23,13 @@ <property name="rightMargin"> <number>0</number> </property> + <item row="0" column="0"> + <widget class="QLabel" name="labelMouse"> + <property name="text"> + <string>Mouse:</string> + </property> + </widget> + </item> <item row="0" column="1" colspan="2"> <widget class="QComboBox" name="comboBoxMouse"> <property name="sizePolicy"> @@ -36,75 +43,6 @@ </property> </widget> </item> - <item row="2" column="3"> - <widget class="QPushButton" name="pushButtonJoystick4"> - <property name="text"> - <string>Joystick 4...</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="pushButtonJoystick3"> - <property name="text"> - <string>Joystick 3...</string> - </property> - </widget> - </item> - <item row="5" column="3"> - <widget class="QPushButton" name="pushButtonBind"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Bind</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QPushButton" name="pushButtonJoystick1"> - <property name="text"> - <string>Joystick 1...</string> - </property> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QComboBox" name="comboBoxJoystick"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Mouse:</string> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="QPushButton" name="pushButtonClearBind"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Clear binding</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Joystick:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="pushButtonJoystick2"> - <property name="text"> - <string>Joystick 2...</string> - </property> - </widget> - </item> <item row="0" column="3"> <widget class="QPushButton" name="pushButtonConfigureMouse"> <property name="sizePolicy"> @@ -118,8 +56,50 @@ </property> </widget> </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelJoystick"> + <property name="text"> + <string>Joystick:</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QComboBox" name="comboBoxJoystick"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QPushButton" name="pushButtonJoystick1"> + <property name="text"> + <string>Joystick 1...</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="pushButtonJoystick2"> + <property name="text"> + <string>Joystick 2...</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="pushButtonJoystick3"> + <property name="text"> + <string>Joystick 3...</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QPushButton" name="pushButtonJoystick4"> + <property name="text"> + <string>Joystick 4...</string> + </property> + </widget> + </item> <item row="3" column="0"> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="labelKeys"> <property name="text"> <string>Key Bindings:</string> </property> @@ -144,6 +124,26 @@ </property> </widget> </item> + <item row="5" column="2"> + <widget class="QPushButton" name="pushButtonClearBind"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Clear binding</string> + </property> + </widget> + </item> + <item row="5" column="3"> + <widget class="QPushButton" name="pushButtonBind"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Bind</string> + </property> + </widget> + </item> </layout> </widget> <resources/> From a83fe67b21274df4423f010da400756f51faded1 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 21:04:00 -0400 Subject: [PATCH 1061/1190] Clean QT Machine UI --- src/qt/qt_settingsmachine.cpp | 2 +- src/qt/qt_settingsmachine.hpp | 11 +---------- src/qt/qt_settingsmachine.ui | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 8548ca8cc..fb5576f69 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -358,4 +358,4 @@ void SettingsMachine::on_checkBoxFPUSoftfloat_stateChanged(int state) { ui->softFloatWarningIcon->setVisible(false); ui->softFloatWarningText->setVisible(false); } -} \ No newline at end of file +} diff --git a/src/qt/qt_settingsmachine.hpp b/src/qt/qt_settingsmachine.hpp index 7e89d7fa4..864894447 100644 --- a/src/qt/qt_settingsmachine.hpp +++ b/src/qt/qt_settingsmachine.hpp @@ -18,22 +18,13 @@ public: signals: void currentMachineChanged(int machineId); + private slots: void on_pushButtonConfigure_clicked(); - -private slots: void on_comboBoxFPU_currentIndexChanged(int index); - -private slots: void on_comboBoxSpeed_currentIndexChanged(int index); - -private slots: void on_comboBoxCPU_currentIndexChanged(int index); - -private slots: void on_comboBoxMachine_currentIndexChanged(int index); - -private slots: void on_comboBoxMachineType_currentIndexChanged(int index); void on_checkBoxFPUSoftfloat_stateChanged(int state); diff --git a/src/qt/qt_settingsmachine.ui b/src/qt/qt_settingsmachine.ui index 0c9c2708e..e3b3cdbde 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -41,6 +41,7 @@ <property name="bottomMargin"> <number>0</number> </property> + <item row="0" column="1"> <widget class="QComboBox" name="comboBoxMachineType"> <property name="maxVisibleItems"> @@ -48,6 +49,7 @@ </property> </widget> </item> + <item row="3" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> @@ -55,6 +57,7 @@ </property> </widget> </item> + <item row="5" column="0"> <widget class="QLabel" name="label_6"> <property name="text"> @@ -62,6 +65,7 @@ </property> </widget> </item> + <item row="3" column="1"> <widget class="QComboBox" name="comboBoxFPU"> <property name="maxVisibleItems"> @@ -69,6 +73,7 @@ </property> </widget> </item> + <item row="5" column="1"> <widget class="QSpinBox" name="spinBoxRAM"> <property name="sizePolicy"> @@ -79,6 +84,7 @@ </property> </widget> </item> + <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="text"> @@ -86,6 +92,7 @@ </property> </widget> </item> + <item row="2" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> @@ -93,6 +100,7 @@ </property> </widget> </item> + <item row="2" column="1"> <widget class="QWidget" name="widget_2" native="true"> <layout class="QHBoxLayout" name="horizontalLayout"> @@ -121,6 +129,7 @@ </property> </widget> </item> + <item> <widget class="QLabel" name="label_7"> <property name="text"> @@ -131,6 +140,7 @@ </property> </widget> </item> + <item> <widget class="QComboBox" name="comboBoxSpeed"> <property name="sizePolicy"> @@ -147,6 +157,7 @@ </layout> </widget> </item> + <item row="4" column="0"> <widget class="QLabel" name="label_5"> <property name="text"> @@ -154,6 +165,7 @@ </property> </widget> </item> + <item row="1" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> @@ -161,6 +173,7 @@ </property> </widget> </item> + <item row="1" column="1"> <widget class="QWidget" name="widget_3" native="true"> <layout class="QHBoxLayout" name="horizontalLayout_2"> @@ -183,6 +196,7 @@ </property> </widget> </item> + <item> <widget class="QPushButton" name="pushButtonConfigure"> <property name="sizePolicy"> @@ -199,6 +213,7 @@ </layout> </widget> </item> + <item row="4" column="1"> <widget class="QWidget" name="widget_4" native="true"> <layout class="QHBoxLayout" name="horizontalLayout_3"> @@ -253,6 +268,7 @@ </layout> </widget> </item> + <item> <layout class="QHBoxLayout" name="dynamicRecompilerLayout"> <item> @@ -270,6 +286,7 @@ </item> </layout> </item> + <item> <layout class="QHBoxLayout" name="softFloatLayout"> <item> @@ -285,6 +302,7 @@ </property> </widget> </item> + <item> <widget class="QLabel" name="softFloatWarningIcon"> <property name="text"> @@ -292,6 +310,7 @@ </property> </widget> </item> + <item> <widget class="QLabel" name="softFloatWarningText"> <property name="text"> @@ -314,6 +333,7 @@ </item> </layout> </item> + <item> <widget class="QGroupBox" name="groupBox"> <property name="sizePolicy"> From 127580b71bbf374c28c8075b1c15e775d16a7fd4 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 21:06:31 -0400 Subject: [PATCH 1062/1190] Clean QT Network UI --- src/qt/qt_settingsnetwork.cpp | 44 +-- src/qt/qt_settingsnetwork.ui | 513 ++++++++++++++++++---------------- 2 files changed, 288 insertions(+), 269 deletions(-) diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 1ea48ee6b..2e64175eb 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -36,17 +36,17 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) auto *nic_cbox = findChild<QComboBox *>(QString("comboBoxNIC%1").arg(i + 1)); auto *net_type_cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1)); - auto *intf_label = findChild<QLabel *>(QString("interfaceLabel%1").arg(i + 1)); + auto *intf_label = findChild<QLabel *>(QString("labelIntf%1").arg(i + 1)); auto *intf_cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1)); auto *conf_btn = findChild<QPushButton *>(QString("pushButtonConf%1").arg(i + 1)); // auto *net_type_conf_btn = findChild<QPushButton *>(QString("pushButtonNetTypeConf%1").arg(i + 1)); - auto *vde_socket_label = findChild<QLabel *>(QString("socketVDELabel%1").arg(i + 1)); + auto *vde_socket_label = findChild<QLabel *>(QString("labelSocketVDENIC%1").arg(i + 1)); auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1)); - auto *option_list_label = findChild<QLabel *>(QString("optionListLabel%1").arg(i + 1)); - auto *option_list_line = findChild<QWidget *>(QString("optionListLine%1").arg(i + 1)); + auto *option_list_label = findChild<QLabel *>(QString("labelOptionList%1").arg(i + 1)); + auto *option_list_line = findChild<QWidget *>(QString("lineOptionList%1").arg(i + 1)); intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP); conf_btn->setEnabled(network_card_has_config(nic_cbox->currentData().toInt())); @@ -56,7 +56,6 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) option_list_label->setVisible(false); option_list_line->setVisible(false); - // VDE vde_socket_label->setVisible(false); socket_line->setVisible(false); @@ -70,21 +69,26 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) // 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->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->setText("PCAP Options"); option_list_label->setVisible(true); option_list_line->setVisible(true); intf_cbox->setVisible(true); intf_label->setVisible(true); break; + + case NET_TYPE_SLIRP: + default: + break; } } } @@ -124,11 +128,10 @@ SettingsNetwork::save() net_cards_conf[i].net_type = cbox->currentData().toInt(); cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1)); memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name)); - if (net_cards_conf[i].net_type == NET_TYPE_PCAP) { + if (net_cards_conf[i].net_type == NET_TYPE_PCAP) strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1); - } else if (net_cards_conf[i].net_type == NET_TYPE_VDE) { + else if (net_cards_conf[i].net_type == NET_TYPE_VDE) strncpy(net_cards_conf[i].host_dev_name, socket_line->text().toUtf8().constData(), sizeof(net_cards_conf[i].host_dev_name)); - } } } @@ -141,7 +144,7 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) int selectedRow = 0; // Network Card - QComboBox * cbox_[NET_CARD_MAX] = { 0 }; + QComboBox *cbox_[NET_CARD_MAX] = { 0 }; QAbstractItemModel *models[NET_CARD_MAX] = { 0 }; int removeRows_[NET_CARD_MAX] = { 0 }; int selectedRows[NET_CARD_MAX] = { 0 }; @@ -226,9 +229,8 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) void SettingsNetwork::on_comboIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } enableElements(ui); } @@ -236,8 +238,8 @@ SettingsNetwork::on_comboIndexChanged(int index) void SettingsNetwork::on_pushButtonConf1_clicked() { - int netCard = ui->comboBoxNIC1->currentData().toInt(); - auto *device = network_card_getdevice(netCard); + int netCard = ui->comboBoxNIC1->currentData().toInt(); + auto *device = network_card_getdevice(netCard); if (netCard == NET_INTERNAL) device = machine_get_net_device(machineId); DeviceConfig::ConfigureDevice(device, 1); @@ -246,23 +248,23 @@ SettingsNetwork::on_pushButtonConf1_clicked() void SettingsNetwork::on_pushButtonConf2_clicked() { - int netCard = ui->comboBoxNIC2->currentData().toInt(); - auto *device = network_card_getdevice(netCard); + int netCard = ui->comboBoxNIC2->currentData().toInt(); + auto *device = network_card_getdevice(netCard); DeviceConfig::ConfigureDevice(device, 2); } void SettingsNetwork::on_pushButtonConf3_clicked() { - int netCard = ui->comboBoxNIC3->currentData().toInt(); - auto *device = network_card_getdevice(netCard); + int netCard = ui->comboBoxNIC3->currentData().toInt(); + auto *device = network_card_getdevice(netCard); DeviceConfig::ConfigureDevice(device, 3); } void SettingsNetwork::on_pushButtonConf4_clicked() { - int netCard = ui->comboBoxNIC4->currentData().toInt(); - auto *device = network_card_getdevice(netCard); + int netCard = ui->comboBoxNIC4->currentData().toInt(); + auto *device = network_card_getdevice(netCard); DeviceConfig::ConfigureDevice(device, 4); } diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index 8fb048f71..0c0979c46 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -27,15 +27,29 @@ <number>0</number> </property> <item> - <widget class="QTabWidget" name="tabWidget"> + <widget class="QTabWidget" name="tabWidgetNet"> <property name="currentIndex"> <number>0</number> </property> - <widget class="QWidget" name="tab_1"> + + <widget class="QWidget" name="tabNet1"> <attribute name="title"> <string>Network Card #1</string> </attribute> - <layout class="QGridLayout" name="gridLayout_3"> + <layout class="QGridLayout" name="gridLayoutNet1"> + <item row="0" column="0"> + <widget class="QLabel" name="labelMode1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Mode:</string> + </property> + </widget> + </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBoxNet1"> <property name="maxVisibleItems"> @@ -50,7 +64,7 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_7"> + <widget class="QLabel" name="labelAdapter1"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -62,79 +76,6 @@ </property> </widget> </item> - <item row="6" column="1"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Mode:</string> - </property> - </widget> - </item> - <item row="2" column="1" colspan="2"> - <widget class="Line" name="optionListLine1"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="pushButtonConf1"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="optionListLabel1"> - <property name="text"> - <string>Options</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="interfaceLabel1"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Interface:</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="socketVDELabel1"> - <property name="text"> - <string>VDE Socket:</string> - </property> - </widget> - </item> <item row="1" column="1"> <widget class="QComboBox" name="comboBoxNIC1"> <property name="sizePolicy"> @@ -151,10 +92,43 @@ </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="socketVDENIC1"> - <property name="maxLength"> - <number>127</number> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButtonConf1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelOptionList1"> + <property name="text"> + <string>Options</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="Line" name="lineOptionList1"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelIntf1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Interface:</string> </property> </widget> </item> @@ -168,15 +142,22 @@ </property> </widget> </item> - </layout> - </widget> - <widget class="QWidget" name="tab_2"> - <attribute name="title"> - <string>Network Card #2</string> - </attribute> - <layout class="QGridLayout" name="gridLayout"> + <item row="5" column="0"> + <widget class="QLabel" name="labelSocketVDENIC1"> + <property name="text"> + <string>VDE Socket:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="socketVDENIC1"> + <property name="maxLength"> + <number>127</number> + </property> + </widget> + </item> <item row="6" column="1"> - <spacer name="verticalSpacer"> + <spacer name="verticalSpacerNIC1"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> @@ -188,28 +169,16 @@ </property> </spacer> </item> - <item row="3" column="0"> - <widget class="QLabel" name="interfaceLabel2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Interface:</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="optionListLabel2"> - <property name="text"> - <string>Options</string> - </property> - </widget> - </item> + </layout> + </widget> + + <widget class="QWidget" name="tabNet2"> + <attribute name="title"> + <string>Network Card #2</string> + </attribute> + <layout class="QGridLayout" name="gridLayoutNet2"> <item row="0" column="0"> - <widget class="QLabel" name="label_8"> + <widget class="QLabel" name="labelMode2"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -234,22 +203,8 @@ </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="socketVDELabel2"> - <property name="text"> - <string>VDE Socket:</string> - </property> - </widget> - </item> - <item row="2" column="1" colspan="2"> - <widget class="Line" name="optionListLine2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> <item row="1" column="0"> - <widget class="QLabel" name="label_10"> + <widget class="QLabel" name="labelAdapter2"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -261,6 +216,22 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBoxNIC2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> <item row="1" column="2"> <widget class="QPushButton" name="pushButtonConf2"> <property name="sizePolicy"> @@ -274,25 +245,33 @@ </property> </widget> </item> - <item row="1" column="1"> - <widget class="QComboBox" name="comboBoxNIC2"> - <property name="maxVisibleItems"> - <number>30</number> + <item row="2" column="0"> + <widget class="QLabel" name="labelOptionList2"> + <property name="text"> + <string>Options</string> </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="Line" name="lineOptionList2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelIntf2"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="sizeAdjustPolicy"> - <enum>QComboBox::AdjustToContents</enum> + <property name="text"> + <string>Interface:</string> </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="socketVDENIC2"/> - </item> <item row="3" column="1"> <widget class="QComboBox" name="comboBoxIntf2"> <property name="sizePolicy"> @@ -303,13 +282,54 @@ </property> </widget> </item> + <item row="5" column="0"> + <widget class="QLabel" name="labelSocketVDENIC2"> + <property name="text"> + <string>VDE Socket:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="socketVDENIC2"> + <property name="maxLength"> + <number>127</number> + </property> + </widget> + </item> + <item row="6" column="1"> + <spacer name="verticalSpacerNIC2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> </layout> </widget> - <widget class="QWidget" name="tab_3"> + + <widget class="QWidget" name="tabNet3"> <attribute name="title"> <string>Network Card #3</string> </attribute> - <layout class="QGridLayout" name="gridLayout_2"> + <layout class="QGridLayout" name="gridLayoutNet3"> + <item row="0" column="0"> + <widget class="QLabel" name="labelMode3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Mode:</string> + </property> + </widget> + </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBoxNet3"> <property name="maxVisibleItems"> @@ -323,17 +343,16 @@ </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="socketVDELabel3"> - <property name="text"> - <string>VDE Socket:</string> + <item row="1" column="0"> + <widget class="QLabel" name="labelAdapter3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="optionListLabel3"> <property name="text"> - <string>Options</string> + <string>Adapter:</string> </property> </widget> </item> @@ -353,39 +372,6 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QLabel" name="interfaceLabel3"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Interface:</string> - </property> - </widget> - </item> - <item row="2" column="1" colspan="2"> - <widget class="Line" name="optionListLine3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_11"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Mode:</string> - </property> - </widget> - </item> <item row="1" column="2"> <widget class="QPushButton" name="pushButtonConf3"> <property name="sizePolicy"> @@ -399,8 +385,22 @@ </property> </widget> </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_13"> + <item row="2" column="0"> + <widget class="QLabel" name="labelOptionList3"> + <property name="text"> + <string>Options</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="Line" name="lineOptionList3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelIntf3"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -408,13 +408,10 @@ </sizepolicy> </property> <property name="text"> - <string>Adapter:</string> + <string>Interface:</string> </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="socketVDENIC3"/> - </item> <item row="3" column="1"> <widget class="QComboBox" name="comboBoxIntf3"> <property name="sizePolicy"> @@ -425,8 +422,22 @@ </property> </widget> </item> + <item row="5" column="0"> + <widget class="QLabel" name="labelSocketVDENIC3"> + <property name="text"> + <string>VDE Socket:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="socketVDENIC3"> + <property name="maxLength"> + <number>127</number> + </property> + </widget> + </item> <item row="6" column="1"> - <spacer name="verticalSpacer_3"> + <spacer name="verticalSpacerNIC3"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> @@ -440,20 +451,14 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab_4"> + + <widget class="QWidget" name="tabNet4"> <attribute name="title"> <string>Network Card #4</string> </attribute> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="2" column="0"> - <widget class="QLabel" name="optionListLabel4"> - <property name="text"> - <string>Options</string> - </property> - </widget> - </item> + <layout class="QGridLayout" name="gridLayoutNet4"> <item row="0" column="0"> - <widget class="QLabel" name="label_14"> + <widget class="QLabel" name="labelMode4"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -465,28 +470,21 @@ </property> </widget> </item> - <item row="6" column="1"> - <spacer name="verticalSpacer_4"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxNet4"> + <property name="maxVisibleItems"> + <number>30</number> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="socketVDELabel4"> - <property name="text"> - <string>VDE Socket:</string> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_16"> + <widget class="QLabel" name="labelAdapter4"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -498,26 +496,6 @@ </property> </widget> </item> - <item row="2" column="1" colspan="2"> - <widget class="Line" name="optionListLine4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="interfaceLabel4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Interface:</string> - </property> - </widget> - </item> <item row="1" column="1"> <widget class="QComboBox" name="comboBoxNIC4"> <property name="sizePolicy"> @@ -534,19 +512,6 @@ </property> </widget> </item> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBoxNet4"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> <item row="1" column="2"> <widget class="QPushButton" name="pushButtonConf4"> <property name="sizePolicy"> @@ -560,8 +525,32 @@ </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="socketVDENIC4"/> + <item row="2" column="0"> + <widget class="QLabel" name="labelOptionList4"> + <property name="text"> + <string>Options</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="Line" name="lineOptionList4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelIntf4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Interface:</string> + </property> + </widget> </item> <item row="3" column="1"> <widget class="QComboBox" name="comboBoxIntf4"> @@ -573,8 +562,36 @@ </property> </widget> </item> + <item row="5" column="0"> + <widget class="QLabel" name="labelSocketVDENIC4"> + <property name="text"> + <string>VDE Socket:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="socketVDENIC4"> + <property name="maxLength"> + <number>127</number> + </property> + </widget> + </item> + <item row="6" column="1"> + <spacer name="verticalSpacerNIC4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> </layout> </widget> + </widget> </item> </layout> From 2641601ea21a52ce31d10c4ec40e5a1f46268d6c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 21:09:53 -0400 Subject: [PATCH 1063/1190] Clean QT Ports UI --- src/qt/qt_settingsports.cpp | 6 +- src/qt/qt_settingsports.hpp | 21 ++-- src/qt/qt_settingsports.ui | 192 ++++++++++++++++++------------------ 3 files changed, 111 insertions(+), 108 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 7e8f2aeda..ddebd28e8 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -51,7 +51,7 @@ SettingsPorts::save() { for (int i = 0; i < PARALLEL_MAX; i++) { auto *cbox = findChild<QComboBox *>(QString("comboBoxLpt%1").arg(i + 1)); - auto *checkBox = findChild<QCheckBox *>(QString("checkBoxParallel%1").arg(i + 1)); + auto *checkBox = findChild<QCheckBox *>(QString("checkBoxParallel%1").arg(i + 1)); if (cbox != NULL) lpt_ports[i].device = cbox->currentData().toInt(); if (checkBox != NULL) @@ -73,7 +73,7 @@ SettingsPorts::onCurrentMachineChanged(int machineId) { this->machineId = machineId; - int c = 0; + int c = 0; // LPT Device QComboBox * cbox[PARALLEL_MAX] = { 0 }; @@ -93,7 +93,7 @@ SettingsPorts::onCurrentMachineChanged(int machineId) if (lptName == nullptr) break; - const QString name = tr(lptName); + const QString name = tr(lptName); for (uint8_t i = 0; i < PARALLEL_MAX; ++i) { int row = Models::AddEntry(models[i], name, c); diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index 83560914f..8be1f0491 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -35,22 +35,25 @@ private slots: void on_checkBoxSerial7_stateChanged(int state); #endif void on_checkBoxSerialPassThru1_stateChanged(int state); + void on_pushButtonSerialPassThru1_clicked(); + void on_checkBoxSerialPassThru2_stateChanged(int state); + void on_pushButtonSerialPassThru2_clicked(); + void on_checkBoxSerialPassThru3_stateChanged(int state); + void on_pushButtonSerialPassThru3_clicked(); + void on_checkBoxSerialPassThru4_stateChanged(int state); + void on_pushButtonSerialPassThru4_clicked(); + #if 0 void on_checkBoxSerialPassThru5_stateChanged(int state); - void on_checkBoxSerialPassThru6_stateChanged(int state); - void on_checkBoxSerialPassThru7_stateChanged(int state); -#endif - - void on_pushButtonSerialPassThru1_clicked(); - void on_pushButtonSerialPassThru2_clicked(); - void on_pushButtonSerialPassThru3_clicked(); - void on_pushButtonSerialPassThru4_clicked(); -#if 0 void on_pushButtonSerialPassThru5_clicked(); + + void on_checkBoxSerialPassThru6_stateChanged(int state); void on_pushButtonSerialPassThru6_clicked(); + + void on_checkBoxSerialPassThru7_stateChanged(int state); void on_pushButtonSerialPassThru7_clicked(); #endif diff --git a/src/qt/qt_settingsports.ui b/src/qt/qt_settingsports.ui index bca870e5d..92420f2df 100644 --- a/src/qt/qt_settingsports.ui +++ b/src/qt/qt_settingsports.ui @@ -29,7 +29,7 @@ <item row="0" column="0"> <layout class="QFormLayout" name="formLayout"> <item row="0" column="0"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelLpt1"> <property name="text"> <string>LPT1 Device:</string> </property> @@ -43,7 +43,7 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="labelLpt2"> <property name="text"> <string>LPT2 Device:</string> </property> @@ -57,7 +57,7 @@ </widget> </item> <item row="2" column="0"> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="labelLpt3"> <property name="text"> <string>LPT3 Device:</string> </property> @@ -71,7 +71,7 @@ </widget> </item> <item row="3" column="0"> - <widget class="QLabel" name="label_4"> + <widget class="QLabel" name="labelLpt4"> <property name="text"> <string>LPT4 Device:</string> </property> @@ -88,27 +88,6 @@ </item> <item row="1" column="0"> <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="1"> - <widget class="QCheckBox" name="checkBoxParallel2"> - <property name="text"> - <string>Parallel port 2</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QCheckBox" name="checkBoxParallel3"> - <property name="text"> - <string>Parallel port 3</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="checkBoxSerial3"> - <property name="text"> - <string>Serial port 3</string> - </property> - </widget> - </item> <item row="0" column="0"> <widget class="QCheckBox" name="checkBoxSerial1"> <property name="text"> @@ -116,20 +95,6 @@ </property> </widget> </item> - <item row="3" column="1"> - <widget class="QCheckBox" name="checkBoxParallel4"> - <property name="text"> - <string>Parallel port 4</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="checkBoxSerial2"> - <property name="text"> - <string>Serial port 2</string> - </property> - </widget> - </item> <item row="0" column="1"> <widget class="QCheckBox" name="checkBoxParallel1"> <property name="text"> @@ -137,6 +102,34 @@ </property> </widget> </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBoxSerial2"> + <property name="text"> + <string>Serial port 2</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="checkBoxParallel2"> + <property name="text"> + <string>Parallel port 2</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBoxSerial3"> + <property name="text"> + <string>Serial port 3</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QCheckBox" name="checkBoxParallel3"> + <property name="text"> + <string>Parallel port 3</string> + </property> + </widget> + </item> <item row="3" column="0"> <widget class="QCheckBox" name="checkBoxSerial4"> <property name="text"> @@ -144,13 +137,76 @@ </property> </widget> </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="checkBoxParallel4"> + <property name="text"> + <string>Parallel port 4</string> + </property> + </widget> + </item> </layout> </item> <item row="3" column="0"> - <layout class="QGridLayout" name="gridLayout_5"> + <layout class="QGridLayout" name="gridLayoutPassThru"> <property name="sizeConstraint"> <enum>QLayout::SetDefaultConstraint</enum> </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBoxSerialPassThru1"> + <property name="text"> + <string>Serial port passthrough 1</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="pushButtonSerialPassThru1"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBoxSerialPassThru2"> + <property name="text"> + <string>Serial port passthrough 2</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButtonSerialPassThru2"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBoxSerialPassThru3"> + <property name="text"> + <string>Serial port passthrough 3</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="pushButtonSerialPassThru3"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBoxSerialPassThru4"> + <property name="text"> + <string>Serial port passthrough 4</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="pushButtonSerialPassThru4"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> <item row="4" column="0"> <spacer name="horizontalSpacer"> <property name="orientation"> @@ -164,13 +220,6 @@ </property> </spacer> </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="checkBoxSerialPassThru3"> - <property name="text"> - <string>Serial port passthrough 3</string> - </property> - </widget> - </item> <item row="5" column="0" colspan="2"> <spacer name="verticalSpacer"> <property name="orientation"> @@ -184,55 +233,6 @@ </property> </spacer> </item> - <item row="0" column="1"> - <widget class="QPushButton" name="pushButtonSerialPassThru1"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QCheckBox" name="checkBoxSerialPassThru1"> - <property name="text"> - <string>Serial port passthrough 1</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="checkBoxSerialPassThru2"> - <property name="text"> - <string>Serial port passthrough 2</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QCheckBox" name="checkBoxSerialPassThru4"> - <property name="text"> - <string>Serial port passthrough 4</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="pushButtonSerialPassThru2"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="pushButtonSerialPassThru3"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="pushButtonSerialPassThru4"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> </layout> </item> </layout> From c0af5cea9983b2df0042d24967e6546347c89655 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Fri, 9 May 2025 21:12:19 -0400 Subject: [PATCH 1064/1190] Clean QT Storage Controllers UI --- src/qt/qt_settingsstoragecontrollers.cpp | 40 +++--- src/qt/qt_settingsstoragecontrollers.hpp | 38 ++--- src/qt/qt_settingsstoragecontrollers.ui | 170 +++++++++++------------ 3 files changed, 125 insertions(+), 123 deletions(-) diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 48fa04892..2af7bd080 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -84,18 +84,16 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) } QString name = DeviceConfig::DeviceName(hdc_get_device(c), hdc_get_internal_name(c), 1); - if (name.isEmpty()) { + if (name.isEmpty()) break; - } if (hdc_available(c)) { const device_t *hdc_dev = hdc_get_device(c); if (device_is_valid(hdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); - if (c == hdc_current[0]) { + if (c == hdc_current[0]) selectedRow = row - removeRows; - } } } c++; @@ -105,7 +103,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->comboBoxHD->setCurrentIndex(-1); ui->comboBoxHD->setCurrentIndex(selectedRow); - /*FD controller config*/ + /* FD controller config */ model = ui->comboBoxFD->model(); removeRows = model->rowCount(); c = 0; @@ -143,11 +141,11 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) /*CD interface controller config*/ #ifdef USE_CDROM_MITSUMI - ui->label_7->setVisible(true); + ui->labelCDInterface->setVisible(true); ui->comboBoxCDInterface->setVisible(true); ui->pushButtonCDInterface->setVisible(true); #else - ui->label_7->setVisible(false); + ui->labelCDInterface->setVisible(false); ui->comboBoxCDInterface->setVisible(false); ui->pushButtonCDInterface->setVisible(false); #endif @@ -242,27 +240,27 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) void SettingsStorageControllers::on_comboBoxHD_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonHD->setEnabled(hdc_has_config(ui->comboBoxHD->currentData().toInt()) > 0); } void SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0); } void SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonCDInterface->setEnabled(cdrom_interface_has_config(ui->comboBoxCDInterface->currentData().toInt()) > 0); } @@ -311,36 +309,36 @@ SettingsStorageControllers::on_pushButtonQuaternaryIDE_clicked() void SettingsStorageControllers::on_comboBoxSCSI1_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonSCSI1->setEnabled(scsi_card_has_config(ui->comboBoxSCSI1->currentData().toInt()) > 0); } void SettingsStorageControllers::on_comboBoxSCSI2_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonSCSI2->setEnabled(scsi_card_has_config(ui->comboBoxSCSI2->currentData().toInt()) > 0); } void SettingsStorageControllers::on_comboBoxSCSI3_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonSCSI3->setEnabled(scsi_card_has_config(ui->comboBoxSCSI3->currentData().toInt()) > 0); } void SettingsStorageControllers::on_comboBoxSCSI4_currentIndexChanged(int index) { - if (index < 0) { + if (index < 0) return; - } + ui->pushButtonSCSI4->setEnabled(scsi_card_has_config(ui->comboBoxSCSI4->currentData().toInt()) > 0); } diff --git a/src/qt/qt_settingsstoragecontrollers.hpp b/src/qt/qt_settingsstoragecontrollers.hpp index c50a94574..6774bb504 100644 --- a/src/qt/qt_settingsstoragecontrollers.hpp +++ b/src/qt/qt_settingsstoragecontrollers.hpp @@ -20,27 +20,31 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonSCSI4_clicked(); - void on_pushButtonSCSI3_clicked(); - void on_pushButtonSCSI2_clicked(); - void on_pushButtonSCSI1_clicked(); - void on_comboBoxSCSI4_currentIndexChanged(int index); - void on_comboBoxSCSI3_currentIndexChanged(int index); - void on_comboBoxSCSI2_currentIndexChanged(int index); - void on_comboBoxSCSI1_currentIndexChanged(int index); - void on_pushButtonQuaternaryIDE_clicked(); - void on_pushButtonTertiaryIDE_clicked(); - void on_pushButtonFD_clicked(); - void on_pushButtonHD_clicked(); - void on_pushButtonCDInterface_clicked(); - void on_checkBoxQuaternaryIDE_stateChanged(int arg1); - void on_checkBoxTertiaryIDE_stateChanged(int arg1); - void on_comboBoxFD_currentIndexChanged(int index); void on_comboBoxHD_currentIndexChanged(int index); + void on_pushButtonHD_clicked(); + + void on_comboBoxFD_currentIndexChanged(int index); + void on_pushButtonFD_clicked(); + void on_comboBoxCDInterface_currentIndexChanged(int index); + void on_pushButtonCDInterface_clicked(); + + void on_checkBoxTertiaryIDE_stateChanged(int arg1); + void on_pushButtonTertiaryIDE_clicked(); + + void on_checkBoxQuaternaryIDE_stateChanged(int arg1); + void on_pushButtonQuaternaryIDE_clicked(); + + void on_comboBoxSCSI1_currentIndexChanged(int index); + void on_pushButtonSCSI1_clicked(); + void on_comboBoxSCSI2_currentIndexChanged(int index); + void on_pushButtonSCSI2_clicked(); + void on_comboBoxSCSI3_currentIndexChanged(int index); + void on_pushButtonSCSI3_clicked(); + void on_comboBoxSCSI4_currentIndexChanged(int index); + void on_pushButtonSCSI4_clicked(); void on_checkBoxLbaEnhancer_stateChanged(int arg1); - void on_pushButtonConfigureLbaEnhancer_clicked(); private: diff --git a/src/qt/qt_settingsstoragecontrollers.ui b/src/qt/qt_settingsstoragecontrollers.ui index a167e5bc1..04a87c1d5 100644 --- a/src/qt/qt_settingsstoragecontrollers.ui +++ b/src/qt/qt_settingsstoragecontrollers.ui @@ -29,47 +29,12 @@ <item> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelHD"> <property name="text"> <string>HD Controller:</string> </property> </widget> </item> - <item row="1" column="2"> - <widget class="QPushButton" name="pushButtonFD"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>FD Controller:</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>CD-ROM Controller:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="comboBoxCDInterface"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="pushButtonCDInterface"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBoxHD"> <property name="sizePolicy"> @@ -90,6 +55,13 @@ </property> </widget> </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelFD"> + <property name="text"> + <string>FD Controller:</string> + </property> + </widget> + </item> <item row="1" column="1"> <widget class="QComboBox" name="comboBoxFD"> <property name="maxVisibleItems"> @@ -97,6 +69,34 @@ </property> </widget> </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButtonFD"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelCDInterface"> + <property name="text"> + <string>CD-ROM Controller:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="comboBoxCDInterface"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="pushButtonCDInterface"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> <item row="3" column="0"> <widget class="QCheckBox" name="checkBoxTertiaryIDE"> <property name="text"> @@ -104,13 +104,6 @@ </property> </widget> </item> - <item row="4" column="0"> - <widget class="QCheckBox" name="checkBoxQuaternaryIDE"> - <property name="text"> - <string>Quaternary IDE Controller</string> - </property> - </widget> - </item> <item row="3" column="2"> <widget class="QPushButton" name="pushButtonTertiaryIDE"> <property name="enabled"> @@ -121,6 +114,13 @@ </property> </widget> </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="checkBoxQuaternaryIDE"> + <property name="text"> + <string>Quaternary IDE Controller</string> + </property> + </widget> + </item> <item row="4" column="2"> <widget class="QPushButton" name="pushButtonQuaternaryIDE"> <property name="enabled"> @@ -134,29 +134,15 @@ </layout> </item> <item> - <widget class="QGroupBox" name="groupBox"> + <widget class="QGroupBox" name="groupBoxSCSI"> <property name="title"> <string>SCSI</string> </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="1" column="3"> - <widget class="QPushButton" name="pushButtonSCSI2"> + <layout class="QGridLayout" name="gridLayoutSCSI"> + <item row="0" column="0"> + <widget class="QLabel" name="labelSCSI1"> <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="3" column="3"> - <widget class="QPushButton" name="pushButtonSCSI4"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>Controller 3:</string> + <string>Controller 1:</string> </property> </widget> </item> @@ -180,6 +166,13 @@ </property> </widget> </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelSCSI2"> + <property name="text"> + <string>Controller 2:</string> + </property> + </widget> + </item> <item row="1" column="2"> <widget class="QComboBox" name="comboBoxSCSI2"> <property name="sizePolicy"> @@ -193,6 +186,20 @@ </property> </widget> </item> + <item row="1" column="3"> + <widget class="QPushButton" name="pushButtonSCSI2"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelSCSI3"> + <property name="text"> + <string>Controller 3:</string> + </property> + </widget> + </item> <item row="2" column="2"> <widget class="QComboBox" name="comboBoxSCSI3"> <property name="sizePolicy"> @@ -206,6 +213,20 @@ </property> </widget> </item> + <item row="2" column="3"> + <widget class="QPushButton" name="pushButtonSCSI3"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelSCSI4"> + <property name="text"> + <string>Controller 4:</string> + </property> + </widget> + </item> <item row="3" column="2"> <widget class="QComboBox" name="comboBoxSCSI4"> <property name="sizePolicy"> @@ -219,29 +240,8 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Controller 1:</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Controller 2:</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Controller 4:</string> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QPushButton" name="pushButtonSCSI3"> + <item row="3" column="3"> + <widget class="QPushButton" name="pushButtonSCSI4"> <property name="text"> <string>Configure</string> </property> From cdfb768ee8cd8e1f7563d3a50490a2559471b701 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 10 May 2025 00:01:36 -0400 Subject: [PATCH 1065/1190] Clean QT Other Removable Devices UI --- src/qt/qt_settingsotherremovable.hpp | 32 ++++++++-------------------- src/qt/qt_settingsotherremovable.ui | 26 +++++++++++----------- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/src/qt/qt_settingsotherremovable.hpp b/src/qt/qt_settingsotherremovable.hpp index cea1d202b..1459ed043 100644 --- a/src/qt/qt_settingsotherremovable.hpp +++ b/src/qt/qt_settingsotherremovable.hpp @@ -21,33 +21,19 @@ public: signals: void moChannelChanged(); void zipChannelChanged(); -private slots: - void on_checkBoxZIP250_stateChanged(int arg1); - -private slots: - void on_comboBoxZIPChannel_activated(int index); - -private slots: - void on_comboBoxZIPBus_activated(int index); - -private slots: - void on_comboBoxZIPBus_currentIndexChanged(int index); - -private slots: - void on_comboBoxMOType_activated(int index); - -private slots: - void on_comboBoxMOChannel_activated(int index); - -private slots: - void on_comboBoxMOBus_activated(int index); - -private slots: - void on_comboBoxMOBus_currentIndexChanged(int index); private slots: void onMORowChanged(const QModelIndex &current); + void on_comboBoxMOBus_currentIndexChanged(int index); + void on_comboBoxMOBus_activated(int index); + void on_comboBoxMOChannel_activated(int index); + void on_comboBoxMOType_activated(int index); + void onZIPRowChanged(const QModelIndex &current); + void on_comboBoxZIPBus_currentIndexChanged(int index); + void on_comboBoxZIPBus_activated(int index); + void on_comboBoxZIPChannel_activated(int index); + void on_checkBoxZIP250_stateChanged(int arg1); private: Ui::SettingsOtherRemovable *ui; diff --git a/src/qt/qt_settingsotherremovable.ui b/src/qt/qt_settingsotherremovable.ui index 8962184fc..ae7839e54 100644 --- a/src/qt/qt_settingsotherremovable.ui +++ b/src/qt/qt_settingsotherremovable.ui @@ -27,7 +27,7 @@ <number>0</number> </property> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelMO"> <property name="text"> <string>MO drives:</string> </property> @@ -68,19 +68,12 @@ <widget class="QWidget" name="moControls" native="true"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="labelMOBus"> <property name="text"> <string>Bus:</string> </property> </widget> </item> - <item row="0" column="2"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Channel:</string> - </property> - </widget> - </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBoxMOBus"> <property name="maxVisibleItems"> @@ -88,6 +81,13 @@ </property> </widget> </item> + <item row="0" column="2"> + <widget class="QLabel" name="labelMOChannel"> + <property name="text"> + <string>Channel:</string> + </property> + </widget> + </item> <item row="0" column="3"> <widget class="QComboBox" name="comboBoxMOChannel"> <property name="maxVisibleItems"> @@ -96,7 +96,7 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_4"> + <widget class="QLabel" name="labelMOType"> <property name="text"> <string>Type:</string> </property> @@ -113,7 +113,7 @@ </widget> </item> <item> - <widget class="QLabel" name="label_6"> + <widget class="QLabel" name="labelZIP"> <property name="text"> <string>ZIP drives:</string> </property> @@ -154,7 +154,7 @@ <widget class="QWidget" name="zipControls" native="true"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="labelZIPBus"> <property name="text"> <string>Bus:</string> </property> @@ -168,7 +168,7 @@ </widget> </item> <item> - <widget class="QLabel" name="label_5"> + <widget class="QLabel" name="labelZIPChannel"> <property name="text"> <string>Channel:</string> </property> From 35c77d798a72dd127d6ae270ce0d7f898572c4c4 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 10 May 2025 02:39:31 -0400 Subject: [PATCH 1066/1190] Move FDC before HDC in settings->storagecontrollers --- src/qt/qt_settingsstoragecontrollers.cpp | 32 ++++++++--------- src/qt/qt_settingsstoragecontrollers.hpp | 6 ++-- src/qt/qt_settingsstoragecontrollers.ui | 46 ++++++++++++------------ 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 2af7bd080..b3d827fa2 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -56,8 +56,8 @@ SettingsStorageControllers::save() QComboBox *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1)); scsi_card_current[i] = cbox->currentData().toInt(); } - hdc_current[0] = ui->comboBoxHD->currentData().toInt(); fdc_current[0] = ui->comboBoxFD->currentData().toInt(); + hdc_current[0] = ui->comboBoxHD->currentData().toInt(); cdrom_interface_current = ui->comboBoxCDInterface->currentData().toInt(); ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; @@ -237,15 +237,6 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->pushButtonConfigureLbaEnhancer->setEnabled(ui->checkBoxLbaEnhancer->isChecked()); } -void -SettingsStorageControllers::on_comboBoxHD_currentIndexChanged(int index) -{ - if (index < 0) - return; - - ui->pushButtonHD->setEnabled(hdc_has_config(ui->comboBoxHD->currentData().toInt()) > 0); -} - void SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) { @@ -255,6 +246,15 @@ SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0); } +void +SettingsStorageControllers::on_comboBoxHD_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonHD->setEnabled(hdc_has_config(ui->comboBoxHD->currentData().toInt()) > 0); +} + void SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index) { @@ -276,18 +276,18 @@ SettingsStorageControllers::on_checkBoxQuaternaryIDE_stateChanged(int arg1) ui->pushButtonQuaternaryIDE->setEnabled(arg1 == Qt::Checked); } -void -SettingsStorageControllers::on_pushButtonHD_clicked() -{ - DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt())); -} - void SettingsStorageControllers::on_pushButtonFD_clicked() { DeviceConfig::ConfigureDevice(fdc_card_getdevice(ui->comboBoxFD->currentData().toInt())); } +void +SettingsStorageControllers::on_pushButtonHD_clicked() +{ + DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt())); +} + void SettingsStorageControllers::on_pushButtonCDInterface_clicked() { diff --git a/src/qt/qt_settingsstoragecontrollers.hpp b/src/qt/qt_settingsstoragecontrollers.hpp index 6774bb504..7c1c56086 100644 --- a/src/qt/qt_settingsstoragecontrollers.hpp +++ b/src/qt/qt_settingsstoragecontrollers.hpp @@ -20,12 +20,12 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_comboBoxHD_currentIndexChanged(int index); - void on_pushButtonHD_clicked(); - void on_comboBoxFD_currentIndexChanged(int index); void on_pushButtonFD_clicked(); + void on_comboBoxHD_currentIndexChanged(int index); + void on_pushButtonHD_clicked(); + void on_comboBoxCDInterface_currentIndexChanged(int index); void on_pushButtonCDInterface_clicked(); diff --git a/src/qt/qt_settingsstoragecontrollers.ui b/src/qt/qt_settingsstoragecontrollers.ui index 04a87c1d5..cd1bf9baf 100644 --- a/src/qt/qt_settingsstoragecontrollers.ui +++ b/src/qt/qt_settingsstoragecontrollers.ui @@ -29,13 +29,34 @@ <item> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> + <widget class="QLabel" name="labelFD"> + <property name="text"> + <string>FD Controller:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxFD"> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="pushButtonFD"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="1" column="0"> <widget class="QLabel" name="labelHD"> <property name="text"> <string>HD Controller:</string> </property> </widget> </item> - <item row="0" column="1"> + <item row="1" column="1"> <widget class="QComboBox" name="comboBoxHD"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> @@ -48,29 +69,8 @@ </property> </widget> </item> - <item row="0" column="2"> - <widget class="QPushButton" name="pushButtonHD"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="labelFD"> - <property name="text"> - <string>FD Controller:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="comboBoxFD"> - <property name="maxVisibleItems"> - <number>30</number> - </property> - </widget> - </item> <item row="1" column="2"> - <widget class="QPushButton" name="pushButtonFD"> + <widget class="QPushButton" name="pushButtonHD"> <property name="text"> <string>Configure</string> </property> From b71e3212366b371f8758aa1a05e5467fff1ae9ee Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Tue, 27 May 2025 22:03:11 -0400 Subject: [PATCH 1067/1190] Assorted cleaning --- src/cdrom/cdrom.c | 24 +- src/floppy/fdd.c | 2 +- src/include/86box/cdrom.h | 16 +- src/include/86box/cdrom_image.h | 2 +- src/include/86box/hdd.h | 4 +- src/include/86box/mo.h | 14 +- src/include/86box/zip.h | 16 +- src/qt/qt_glsl_parser.cpp | 16 +- src/video/vid_ega.c | 125 +++++------ src/video/vid_ps55da2.c | 377 ++++++++++++++++---------------- src/video/video.c | 4 +- 11 files changed, 292 insertions(+), 308 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 44bf2811c..e0fa8b0b6 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -979,28 +979,28 @@ 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); + FILE * fp = fopen(fn2, "wb"); + fwrite(b, 1, len, fp); + fflush(fp); + fclose(fp); 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); + fp = fopen(fn2, "wb"); + fwrite(b, 1, len, fp); + fflush(fp); + fclose(fp); 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); + fp = fopen(fn2, "wb"); + fwrite(b, 1, len, fp); + fflush(fp); + fclose(fp); cdrom_log(dev->log, "Written session TOC of %i bytes to %s\n", len, fn2); } #endif diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index d3d513b9f..31811069f 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -467,7 +467,7 @@ fdd_load(int drive, char *fn) int c = 0; int size; const char *p; - FILE * fp; + FILE *fp; fdd_log("FDD: loading drive %d with '%s'\n", drive, fn); diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 5ff4170a2..a962a8635 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -106,10 +106,10 @@ enum { #define CDV EMU_VERSION_EX static const struct cdrom_drive_types_s { - const char * vendor; - const char * model; - const char * revision; - const char * internal_name; + 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. */ const int scsi_std; @@ -296,7 +296,7 @@ typedef struct cdrom { uint8_t speed; uint8_t cur_speed; - void * priv; + void *priv; char image_path[1024]; char prev_image_path[1280]; @@ -322,10 +322,10 @@ typedef struct cdrom { const cdrom_ops_t *ops; - char * image_history[CD_IMAGE_HISTORY]; + char *image_history[CD_IMAGE_HISTORY]; - void * local; - void * log; + void *local; + void *log; void (*insert)(void *priv); void (*close)(void *priv); diff --git a/src/include/86box/cdrom_image.h b/src/include/86box/cdrom_image.h index 84dd66f37..e0760ff7e 100644 --- a/src/include/86box/cdrom_image.h +++ b/src/include/86box/cdrom_image.h @@ -33,6 +33,6 @@ typedef struct track_file_t { int motorola; } track_file_t; -extern void * image_open(cdrom_t *dev, const char *path); +extern void *image_open(cdrom_t *dev, const char *path); #endif /*CDROM_IMAGE_H*/ diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index eda4396ef..53514740d 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -159,7 +159,7 @@ typedef struct hard_disk_t { uint8_t pad; uint8_t pad0; - void * priv; + void *priv; char fn[1024]; /* Name of current image file */ /* Differential VHD parent file */ @@ -185,7 +185,7 @@ typedef struct hard_disk_t { uint8_t max_multiple_block; uint8_t pad1[3]; - const char * model; + const char *model; hdd_zone_t zones[HDD_MAX_ZONES]; diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index f4e7e9809..fc297ffbb 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -110,13 +110,13 @@ typedef struct mo_drive_t { uint8_t pad; uint8_t pad0; - FILE * fp; - void * priv; + FILE *fp; + void *priv; char image_path[1024]; char prev_image_path[1024]; - char * image_history[MO_IMAGE_HISTORY]; + char *image_history[MO_IMAGE_HISTORY]; uint32_t type; uint32_t medium_size; @@ -129,16 +129,16 @@ typedef struct mo_drive_t { typedef struct mo_t { mode_sense_pages_t ms_pages_saved; - mo_drive_t * drv; + mo_drive_t *drv; #ifdef EMU_IDE_H - ide_tf_t * tf; + ide_tf_t *tf; #else - void * tf; + void *tf; #endif void * log; - uint8_t * buffer; + uint8_t *buffer; uint8_t atapi_cdb[16]; uint8_t current_cdb[16]; uint8_t sense[256]; diff --git a/src/include/86box/zip.h b/src/include/86box/zip.h index 443ab1327..969ce27f5 100644 --- a/src/include/86box/zip.h +++ b/src/include/86box/zip.h @@ -58,13 +58,13 @@ typedef struct zip_drive_t { uint8_t pad; uint8_t pad0; - FILE * fp; - void * priv; + FILE *fp; + void *priv; char image_path[1024]; char prev_image_path[1024]; - char * image_history[ZIP_IMAGE_HISTORY]; + char *image_history[ZIP_IMAGE_HISTORY]; uint32_t is_250; uint32_t medium_size; @@ -74,16 +74,16 @@ typedef struct zip_drive_t { typedef struct zip_t { mode_sense_pages_t ms_pages_saved; - zip_drive_t * drv; + zip_drive_t *drv; #ifdef EMU_IDE_H - ide_tf_t * tf; + ide_tf_t *tf; #else - void * tf; + void *tf; #endif - void * log; + void *log; - uint8_t * buffer; + uint8_t *buffer; uint8_t atapi_cdb[16]; uint8_t current_cdb[16]; uint8_t sense[256]; diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index 6e107bc19..599a95452 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -104,22 +104,22 @@ glsl_detect_bom(const char *fn) static char *load_file(const char *fn) { int bom = glsl_detect_bom(fn); - FILE *f = plat_fopen(fn, "rb"); - if (!f) + FILE *fp = plat_fopen(fn, "rb"); + if (!fp) return 0; - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); + fseek(fp, 0, SEEK_END); + long fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); if (bom) { fsize -= 3; - fseek(f, 3, SEEK_SET); + fseek(fp, 3, SEEK_SET); } char *data = (char*)malloc(fsize + 1); - fread(data, fsize, 1, f); - fclose(f); + (void *) !fread(data, fsize, 1, fp); + fclose(fp); data[fsize] = 0; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index b828239c0..1022bda88 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -47,7 +47,7 @@ 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 int active = 0; uint32_t pallook16[256]; uint32_t pallook64[256]; static int ega_type = EGA_TYPE_IBM; @@ -154,7 +154,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega_recalctimings(ega); if ((type == EGA_TYPE_COMPAQ) && !(val & 0x02)) mem_mapping_disable(&ega->mapping); - else switch (ega->gdcreg[6] & 0xc) { + else switch (ega->gdcreg[6] & 0xc) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); break; @@ -225,7 +225,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) case 6: if ((type == EGA_TYPE_COMPAQ) && !(ega->miscout & 0x02)) mem_mapping_disable(&ega->mapping); - else switch (val & 0xc) { + else switch (val & 0xc) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); break; @@ -289,7 +289,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if ((idx == 7) && (ega->crtc[0x11] & 0x80)) val = (ega->crtc[7] & ~0x10) | (val & 0x10); } - old = ega->crtc[idx]; + old = ega->crtc[idx]; ega->crtc[idx] = val; if (old != val) { if ((idx < 0xe) || (idx > 0x10)) { @@ -305,7 +305,9 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } break; - } default: + } + + default: break; } } @@ -313,7 +315,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) uint8_t ega_in(uint16_t addr, void *priv) { - ega_t *ega = (ega_t *) priv; + ega_t *ega = (ega_t *) priv; uint8_t ret = 0xff; int type = ega_type; int atype = ega->actual_type; @@ -494,7 +496,7 @@ ega_in(uint16_t addr, void *priv) } break; case 0x7c6: - ret = 0xfd; /* EGA mode supported. */ + ret = 0xfd; /* EGA mode supported. */ break; case 0xbc6: /* 0000 = None; @@ -696,7 +698,7 @@ ega_recalctimings(ega_t *ega) timer_disable(&ega->dot_timer); timer_set_delay_u64(&ega->dot_timer, ega->dot_time); ega->cca = 0; - active = 1; + active = 1; ega->dot = 0; } @@ -708,30 +710,30 @@ ega_recalctimings(ega_t *ega) void ega_dot_poll(void *priv) { - ega_t *ega = (ega_t *) priv; - static uint8_t chr; - static uint8_t attr; - 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 crtcreset = ((ega->crtc[0x17] & 0x80) == 0); - const bool seq9dot = ((ega->seqregs[1] & 1) == 0); - const bool blinked = ega->blink & 0x10; - const int dwshift = doublewidth ? 1 : 0; - const int dotwidth = 1 << dwshift; - const int charwidth = dotwidth * (seq9dot ? 9 : 8); - const int cursoron = (ega->sc == (ega->crtc[10] & 31)); - const int cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; - uint32_t addr; - int drawcursor; - uint32_t charaddr; - static int fg = 0; - static int bg = 0; - static uint32_t dat = 0x00000000; - static int cclock = 0; - static int disptime; - static int _dispontime; - static int _dispofftime; + ega_t *ega = (ega_t *) priv; + static uint8_t chr; + static uint8_t attr; + 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 crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seq9dot = ((ega->seqregs[1] & 1) == 0); + const bool blinked = ega->blink & 0x10; + const int dwshift = doublewidth ? 1 : 0; + const int dotwidth = 1 << dwshift; + const int charwidth = dotwidth * (seq9dot ? 9 : 8); + const int cursoron = (ega->sc == (ega->crtc[10] & 31)); + const int cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; + uint32_t addr; + int drawcursor; + uint32_t charaddr; + static int fg = 0; + static int bg = 0; + static uint32_t dat = 0x00000000; + static int cclock = 0; + static int disptime; + static int _dispontime; + static int _dispofftime; if (ega->seqregs[1] & 8) { disptime = ((ega->crtc[0] + 2) << 1); @@ -803,11 +805,9 @@ void ega_poll(void *priv) { ega_t *ega = (ega_t *) priv; - int x, y; int old_ma; int wx = 640; int wy = 350; - uint32_t blink_delay; if (!ega->linepos) { timer_advance_u64(&ega->timer, ega->dispofftime); @@ -826,7 +826,7 @@ ega_poll(void *priv) old_ma = ega->ma; ega->displine *= ega->vres + 1; ega->y_add *= ega->vres + 1; - for (y = 0; y <= ega->vres; y++) { + for (int y = 0; y <= ega->vres; y++) { /* Render scanline */ ega->render(ega); @@ -925,7 +925,7 @@ ega_poll(void *priv) } if (ega->vc == ega->dispend) { ega->dispon = 0; - blink_delay = (ega->crtc[11] & 0x60) >> 5; + uint32_t blink_delay = (ega->crtc[11] & 0x60) >> 5; if (ega->crtc[10] & 0x20) ega->cursoron = 0; else if (blink_delay == 2) @@ -946,14 +946,14 @@ ega_poll(void *priv) #if 0 picint(1 << 2); #endif - x = ega->hdisp; +// x = ega->hdisp; if (ega->interlace && !ega->oddeven) ega->lastline++; if (ega->interlace && ega->oddeven) ega->firstline--; - wx = x; + wx = ega->hdisp; if (ega->vres) { wy = (ega->lastline - ega->firstline) << 1; @@ -1024,9 +1024,6 @@ ega_doblit(int wx, int wy, ega_t *ega) int y_start = enable_overscan ? 0 : (unscaled_overscan_y >> 1); int x_start = enable_overscan ? 0 : (overscan_x >> 1); int bottom = (unscaled_overscan_y >> 1); - uint32_t *p; - int i; - int j; int xs_temp; int ys_temp; @@ -1073,17 +1070,17 @@ ega_doblit(int wx, int wy, ega_t *ega) if ((wx >= 160) && ((wy + 1) >= 120)) { /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ - for (i = 0; i < ega->y_add; i++) { - p = &buffer32->line[i & 0x7ff][0]; + for (int i = 0; i < ega->y_add; i++) { + uint32_t *p = &buffer32->line[i & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) + for (int j = 0; j < (xsize + x_add); j++) p[j] = ega->overscan_color; } - for (i = 0; i < bottom; i++) { - p = &buffer32->line[(ysize + ega->y_add + i) & 0x7ff][0]; + for (int i = 0; i < bottom; i++) { + uint32_t *p = &buffer32->line[(ysize + ega->y_add + i) & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) + for (int j = 0; j < (xsize + x_add); j++) p[j] = ega->overscan_color; } } @@ -1107,12 +1104,11 @@ ega_remap_cpu_addr(uint32_t inaddr, ega_t *ega) // bit 2: 1 = 128K mapping, 0 = other mapping (from memory decode PROM) a0mux = 0; - if (ega->gdcreg[6] & 2) { + if (ega->gdcreg[6] & 2) a0mux |= 2; - } - if (ega->vram_limit <= 64 * 1024) { + + if (ega->vram_limit <= 64 * 1024) a0mux |= 1; - } switch (ega->gdcreg[6] & 0xC) { case 0x0: // 128K A000 @@ -1179,9 +1175,8 @@ ega_write(uint32_t addr, uint8_t val, void *priv) cycles -= video_timing_write_b; - if (ega->chain2_write) { + if (ega->chain2_write) writemask2 &= 0x5 << (addr & 1); - } addr = ega_remap_cpu_addr(addr, ega); @@ -1361,9 +1356,8 @@ ega_read(uint32_t addr, void *priv) cycles -= video_timing_read_b; - if (ega->chain2_read) { + if (ega->chain2_read) readplane = (readplane & 2) | (addr & 1); - } addr = ega_remap_cpu_addr(addr, ega); @@ -1401,23 +1395,19 @@ ega_read(uint32_t addr, void *priv) void ega_init(ega_t *ega, int monitor_type, int is_mono) { - int c; - int d; - int e; - ega->vram = malloc(0x40000); ega->vrammask = 0x3ffff; - for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { + for (uint16_t c = 0; c < 256; c++) { + int e = c; + for (uint8_t d = 0; d < 8; d++) { ega_rotate[d][c] = e; e = (e >> 1) | ((e & 1) ? 0x80 : 0); } } if (is_mono) { - for (c = 0; c < 256; c++) { + for (uint16_t c = 0; c < 256; c++) { if (((c >> 3) & 3) == 0) pallook64[c] = pallook16[c] = makecol32(0, 0, 0); else @@ -1476,7 +1466,7 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); } else { - for (c = 0; c < 256; c++) { + for (uint16_t 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); @@ -1562,11 +1552,9 @@ ega_set_type(void *priv, uint32_t local) static void * ega_standalone_init(const device_t *info) { - ega_t *ega = malloc(sizeof(ega_t)); + ega_t *ega = calloc(1, sizeof(ega_t)); int monitor_type; - memset(ega, 0x00, sizeof(ega_t)); - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); overscan_x = 16; @@ -1635,8 +1623,7 @@ ega_standalone_init(const device_t *info) if (ega->chipset) { io_sethandler(0x01ce, 0x0002, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - ega->eeprom = malloc(sizeof(ati_eeprom_t)); - memset(ega->eeprom, 0, sizeof(ati_eeprom_t)); + ega->eeprom = calloc(1, sizeof(ati_eeprom_t)); ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800p.nvr", 0); } else if (info->local == EGA_COMPAQ) { io_sethandler(0x0084, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 9a95e6ce6..567d60347 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -310,16 +310,16 @@ typedef struct da2_t { uint8_t fctl[32]; uint16_t crtc[32]; uint16_t crtc_vpreg[128]; - uint8_t crtc_vpsel; + uint8_t crtc_vpsel; uint8_t gdcreg[64]; uint8_t reg3ee[16]; int gdcaddr; uint8_t attrc[0x40]; int attraddr, attrff; int attr_palette_enable; - int outflipflop; - int inflipflop; - int iolatch; + int outflipflop; + int inflipflop; + int iolatch; int ioctladdr; int fctladdr; @@ -385,8 +385,7 @@ typedef struct da2_t { card should not attempt to display anything */ int override; - struct - { + struct { int enable; mem_mapping_t mapping; uint8_t ram[DA2_SIZE_GAIJIRAM]; @@ -435,9 +434,9 @@ typedef struct da2_t { uint32_t mmrdbg_vidaddr; #endif - uint8_t pos_regs[8]; - svga_t *mb_vga; - uint8_t monitorid; + uint8_t pos_regs[8]; + svga_t *mb_vga; + uint8_t monitorid; pc_timer_t timer_vidupd; int old_pos2; @@ -520,7 +519,7 @@ da2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; destaddr <<= 3; /* read destination data with big endian order */ - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) writepx[i] = da2_vram_r((destaddr + 24) | i, da2) | (da2_vram_r((destaddr + 16) | i, da2) << 8) | (da2_vram_r((destaddr + 8) | i, da2) << 16) @@ -532,7 +531,7 @@ da2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s mask32.b[3] = mask32in.b[0]; mask32.b[2] = mask32in.b[1]; mask32.d &= 0xffff0000; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { if (da2->bitblt.bitshift_destr > 0) srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; // #ifdef ENABLE_DA2_DEBUGBLT @@ -560,7 +559,7 @@ da2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s break; } } - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { da2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); da2_vram_w((destaddr + 8) | i, (writepx[i] >> 16) & 0xff, da2); } @@ -571,7 +570,7 @@ da2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t { pixel32 srcpx; /* fill data with input color */ - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0; /* read in word */ da2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); @@ -582,7 +581,7 @@ da2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, pixel32 srcpx; srcaddr &= 0xfffffffe; srcaddr <<= 3; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) srcpx.p8[i] = da2_vram_r((srcaddr + 24) | i, da2) | (da2_vram_r((srcaddr + 16) | i, da2) << 8) | (da2_vram_r((srcaddr + 8) | i, da2) << 16) @@ -592,9 +591,9 @@ da2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, } /* get font data for bitblt operation */ static uint32_t -getRAMFont(int32_t code, int line, int x, void *p) +getRAMFont(int32_t code, int line, int x, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint32_t font = 0; #ifdef RESERVED_FOR_FUTURE_USE int fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ @@ -617,8 +616,7 @@ getRAMFont(int32_t code, int line, int x, void *p) font |= da2->mmio.ram[code + 2]; font <<= 8; font |= da2->mmio.ram[code + 3]; - } - else + } else font = 0; return font; } @@ -641,12 +639,12 @@ da2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui uint32_t fontinv; if (width <= 2) { fontinv = ~font; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } da2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } @@ -654,12 +652,12 @@ da2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui } else { font = (font & 0xfff80000) | ((font & 0x0000ffff) << 3); fontinv = ~font; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font >> 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0; } da2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2); - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0; } @@ -667,7 +665,7 @@ da2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, ui da2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2); } else { da2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2); - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { srcpx.p8[i] = (fg & (1 << i)) ? font << 16 : 0; srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0; } @@ -680,8 +678,8 @@ static uint8_t pixel1tohex(uint32_t addr, int index, da2_t *da2) { uint8_t pixeldata = 0; - for (int j = 0; j < 8; j++) { - if (da2_vram_r(((addr << 3) | j) & (1 << (7 - index)), da2)) + for (uint8_t i = 0; i < 8; j++) { + if (da2_vram_r(((addr << 3) | i) & (1 << (7 - index)), da2)) pixeldata++; } return pixeldata; @@ -689,14 +687,14 @@ pixel1tohex(uint32_t addr, int index, da2_t *da2) static void print_pixelbyte(uint32_t addr, da2_t *da2) { - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { pclog("%X", pixel1tohex(addr, i, da2)); } } static void print_bytetobin(uint8_t b) { - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { if (b & 0x80) pclog("1"); else @@ -723,13 +721,13 @@ IBMJtoSJIS(uint16_t knj) knj -= 0x100; if (knj <= 0x1f7d) ; /* do nothing */ - else if (knj >= 0xb700 && knj <= 0xb75f) { + else if (knj >= 0xb700 && knj <= 0xb75f) knj -= 0x90ec; - } else if (knj >= 0xb3f0 && knj <= 0xb67f) { + else if (knj >= 0xb3f0 && knj <= 0xb67f) knj -= 0x906c; - } else if (knj >= 0x8000 && knj <= 0x8183) { + else if (knj >= 0x8000 && knj <= 0x8183) knj -= 0x5524; - } else + else return 0xffff; uint32_t knj1 = knj / 0xBC; uint32_t knj2 = knj - (knj1 * 0xBC); @@ -850,8 +848,7 @@ da2_bitblt_load(da2_t *da2) DOS/V Extension 1040x725 some DBCS uses 0xB0 others 0x90 */ da2->bitblt.destoption = da2->bitblt.reg[0x2F]; - if (da2->bitblt.destoption & 0x10) /* destaddr -= 2, length += 1; */ - { + if (da2->bitblt.destoption & 0x10) { /* destaddr -= 2, length += 1; */ da2->bitblt.destaddr -= 2; da2->bitblt.size_x += 1; da2->bitblt.destpitch -= 2; @@ -892,9 +889,9 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); #endif - } + /* Draw a line */ - else if (da2->bitblt.reg[0x5] == 0x43) { + } else if (da2->bitblt.reg[0x5] == 0x43) { da2->bitblt.exec = DA2_BLT_CLINE; da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0xffff); da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0xffff); @@ -922,17 +919,17 @@ da2_bitblt_load(da2_t *da2) da2_log(" ux1=%d,ux2=%d,uy1=%d,uy2=%d\n", (da2->bitblt.reg[0x32] >> 16) & 0x7ff, (da2->bitblt.reg[0x33] >> 16) & 0x7ff, (da2->bitblt.reg[0x34] >> 16) & 0x7ff, (da2->bitblt.reg[0x35] >> 16) & 0x7ff); - } + /* Fill a rectangle (or draw a horizontal / vertical line) */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { + } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; - } + /* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) { + } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -942,9 +939,9 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); - } + /* Tiling a rectangle (transfer tile data multiple times) */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { + } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -954,9 +951,9 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); - } + /* Block copy */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { + } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; @@ -965,9 +962,9 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); - } + /* Block copy but reversed direction */ - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { + } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; @@ -980,9 +977,9 @@ da2_bitblt_load(da2_t *da2) } } static void -da2_bitblt_exec(void *p) +da2_bitblt_exec(void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); #ifdef ENABLE_DA2_DEBUGBLT_DETAIL if (!(da2->bitblt.debug_exesteps & 0xff)) @@ -1180,9 +1177,9 @@ da2_bitblt_dopayload(void *priv) } } static void -da2_bitblt_addpayload(uint8_t val, void *p) +da2_bitblt_addpayload(uint8_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2->bitblt.indata = 1; if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) da2_log("da2_mmio_write payload overflow! addr %x, val %x\n", da2->bitblt.payload_addr, val); @@ -1222,9 +1219,9 @@ da2_bitblt_addpayload(uint8_t val, void *p) } static void -da2_out(uint16_t addr, uint16_t val, void *p) +da2_out(uint16_t addr, uint16_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; int oldval; /* 3E0 3E1 Sequencer Registers (undoc) @@ -1403,7 +1400,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) if (da2->attraddr < 16) da2->fullchange = changeframecount; if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { - for (int c = 0; c < 16; c++) { + for (uint8_t c = 0; c < 16; c++) { // if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); // else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); if (da2->attrc[LV_MODE_CONTROL] & 0x80) @@ -1486,9 +1483,9 @@ da2_out(uint16_t addr, uint16_t val, void *p) } static uint16_t -da2_in(uint16_t addr, void *p) +da2_in(uint16_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint16_t temp = 0xff; switch (addr) { @@ -1620,9 +1617,9 @@ da2_in(uint16_t addr, void *p) * out b(idx), in w(data) */ static void -da2_outb(uint16_t addr, uint8_t val, void *p) +da2_outb(uint16_t addr, uint8_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; 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) { @@ -1651,10 +1648,10 @@ da2_outb(uint16_t addr, uint8_t val, void *p) da2_out(addr, da2->iolatch, da2); } void -da2_outw(uint16_t addr, uint16_t val, void *p) +da2_outw(uint16_t addr, uint16_t val, void *priv) { da2_iolog("DA2 Outw addr %03X val %04X\n", addr, val); - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2->inflipflop = 0; switch (addr) { case LS_INDEX: @@ -1703,10 +1700,10 @@ da2_outw(uint16_t addr, uint16_t val, void *p) } } static uint8_t -da2_inb(uint16_t addr, void *p) +da2_inb(uint16_t addr, void *priv) { uint8_t temp; - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2->outflipflop = 0; switch (addr) { case LC_DATA: @@ -1736,10 +1733,10 @@ da2_inb(uint16_t addr, void *p) return temp; } static uint16_t -da2_inw(uint16_t addr, void *p) +da2_inw(uint16_t addr, void *priv) { uint16_t temp; - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2->inflipflop = 0; da2->outflipflop = 0; temp = da2_in(addr, da2); @@ -1748,9 +1745,9 @@ da2_inw(uint16_t addr, void *p) } /* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */ static uint8_t -da2_in_ISR(uint16_t addr, void *p) +da2_in_ISR(uint16_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint8_t temp = 0; if (addr == 0x3da) { if (da2->cgastat & 0x01) @@ -1764,9 +1761,9 @@ da2_in_ISR(uint16_t addr, void *p) } static void -da2_out_ISR(uint16_t addr, uint8_t val, void *p) +da2_out_ISR(uint16_t addr, uint8_t val, void *priv) { - // da2_t* da2 = (da2_t*)p; + // da2_t* da2 = (da2_t*) priv; da2_iolog("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); } @@ -1872,9 +1869,9 @@ 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 */ static uint32_t -getfont_ps55dbcs(int32_t code, int32_t line, void *p) +getfont_ps55dbcs(int32_t code, int32_t line, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint32_t font = 0; int32_t fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ if (code >= 0x8000 && code <= 0x8183) @@ -2424,7 +2421,7 @@ da2_mapping_update(da2_t *da2) // da2_recalc_mapping(da2); if (da2->pos_regs[2] & 0x01) { da2_log("DA2 enable registers\n"); - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); @@ -2444,16 +2441,16 @@ da2_mapping_update(da2_t *da2) } static uint8_t -da2_mca_read(int port, void *p) +da2_mca_read(int port, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; return da2->pos_regs[port & 7]; } static void -da2_mca_write(int port, uint8_t val, void *p) +da2_mca_write(int port, uint8_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); @@ -2473,9 +2470,9 @@ da2_mca_feedb(void *priv) } static void -da2_mca_reset(void *p) +da2_mca_reset(void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2_log("da2_mca_reset called.\n"); da2_reset(da2); da2_mca_write(0x102, 0, da2); @@ -2485,7 +2482,7 @@ da2_mca_reset(void *p) static void da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) { - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { if (da2->planemask & (1 << i)) { // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, bitmask); switch (da2->gdcreg[LG_COMMAND] & 0x03) { @@ -2518,7 +2515,7 @@ da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) // if((addr & 8)) bitmask = da2_rightrotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { if (da2->planemask & (1 << i)) { // da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); switch (da2->gdcreg[LG_COMMAND] & 0x03) { @@ -2556,9 +2553,9 @@ da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) } static uint8_t -da2_mmio_read(uint32_t addr, void *p) +da2_mmio_read(uint32_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint32_t index = 0; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { @@ -2604,14 +2601,14 @@ da2_mmio_read(uint32_t addr, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 or 256 color mode */ cycles -= video_timing_read_b; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ #ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); #endif if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); } @@ -2624,9 +2621,9 @@ da2_mmio_read(uint32_t addr, void *p) } } static uint16_t -da2_mmio_readw(uint32_t addr, void *p) +da2_mmio_readw(uint32_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; // da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); // da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); @@ -2635,7 +2632,7 @@ da2_mmio_readw(uint32_t addr, void *p) } else if (!(da2->ioctl[LS_MODE] & 1)) {/* 16 color or 256 color mode */ cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t) (da2->vram[(addr << 3) | i]) | ((uint16_t) (da2->vram[((addr << 3) + 8) | i]) << 8); /* read vram into latch */ #ifdef ENABLE_DA2_DEBUGVRAM @@ -2643,10 +2640,10 @@ da2_mmio_readw(uint32_t addr, void *p) // if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); - // for (int i = 0; i <= 0xb; i++) + // for (uint8_t i = 0; i <= 0xb; i++) // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); // } - // for (int i = 0; i < 16; i++) + // for (uint8_t i = 0; i < 16; i++) //{ // int pixeldata = 0; // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; @@ -2658,7 +2655,7 @@ da2_mmio_readw(uint32_t addr, void *p) if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint16_t ret = 0; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); } @@ -2674,9 +2671,9 @@ da2_mmio_readw(uint32_t addr, void *p) } } static void -da2_mmio_write(uint32_t addr, uint8_t val, void *p) +da2_mmio_write(uint32_t addr, uint8_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint32_t index = 0; // da2_log("da2_mmio_write %x %x\n", addr, val); // if ((addr & ~DA2_MASK_MMIO) != 0xA0000) @@ -2735,10 +2732,10 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) //{ if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { fprintf(da2->mmdbg_fp, "\nB %x %02x ", addr, val); - for (int i = 0; i <= 0xb; i++) + for (uint8_t i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { int pixeldata = 0; if (val & (1 << (7 - i))) pixeldata = (da2->planemask & 0xf); @@ -2751,14 +2748,14 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ addr <<= 3; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcsrc[i] = da2->gdcla[i]; /* use latch */ // da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); // da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) @@ -2771,7 +2768,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) switch (da2->writemode) { case 2: /* equiv to vga write mode 1 */ - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->planemask & (1 << i)) da2_vram_w(addr | i, da2->gdcsrc[i], da2); break; @@ -2779,11 +2776,11 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->planemask & (1 << i)) da2_vram_w(addr | i, val, da2); } else { - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; else @@ -2792,7 +2789,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } break; case 1:/* equiv to vga write mode 2 */ - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); da2_gdcropB(addr, bitmask, da2); break; @@ -2801,7 +2798,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; bitmask &= val; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, bitmask, da2); break; @@ -2818,9 +2815,9 @@ da2_rightrotate(uint16_t data, uint8_t count) return (data >> count) | (data << (sizeof(data) * 8 - count)); } static void -da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) +da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint16_t bitmask; addr &= DA2_MASK_MMIO; bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; @@ -2832,10 +2829,10 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) 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++) + for (uint8_t i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { int pixeldata = 0; if (val & (1 << (15 - i))) pixeldata = (da2->planemask & 0xf); @@ -2851,11 +2848,11 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) da2->changedvram[addr >> 9] = changeframecount; addr <<= 3; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcsrc[i] = da2->gdcla[i]; /* use latch */ if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) @@ -2869,7 +2866,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); switch (da2->writemode) { case 2: - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->planemask & (1 << i)) { da2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); da2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); @@ -2879,13 +2876,13 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) if (da2->gdcreg[LG_DATA_ROTATION] & 15) val = da2_rightrotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->planemask & (1 << i)) { da2_vram_w(addr | i, val & 0xff, da2); da2_vram_w((addr + 8) | i, val >> 8, da2); } } else { - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; else @@ -2895,7 +2892,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) } break; case 1: - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); da2_gdcropW(addr, bitmask, da2); break; @@ -2904,7 +2901,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) val = da2_rightrotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); bitmask &= val; - for (int i = 0; i < 8; i++) + for (uint8_t i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; da2_gdcropW(addr, bitmask, da2); break; @@ -2913,9 +2910,9 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); } static void -da2_mmio_writew(uint32_t addr, uint16_t val, void *p) +da2_mmio_writew(uint32_t addr, uint16_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; // if (da2->bitblt.exec != DA2_BLT_CIDLE) /* Bitblt is in operation. */ // return; // if ((addr & ~0x1ffff) != 0xA0000) return; @@ -2941,52 +2938,52 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) } static void -da2_code_write(uint32_t addr, uint8_t val, void *p) +da2_code_write(uint32_t addr, uint8_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; // if ((addr & ~0xfff) != 0xE0000) return; addr &= DA2_MASK_CRAM; da2->cram[addr] = val; da2->fullchange = 2; } static void -da2_code_writeb(uint32_t addr, uint8_t val, void *p) +da2_code_writeb(uint32_t addr, uint8_t val, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; // da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); cycles -= video_timing_write_b; da2_code_write(addr, val, da2); } static void -da2_code_writew(uint32_t addr, uint16_t val, void *p) +da2_code_writew(uint32_t addr, uint16_t val, void *priv) { // da2_log("DA2_code_writ ew: Write to %x, val %x\n", addr, val); - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; cycles -= video_timing_write_w; da2_code_write(addr, val & 0xff, da2); da2_code_write(addr + 1, val >> 8, da2); } static uint8_t -da2_code_read(uint32_t addr, void *p) +da2_code_read(uint32_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; // if ((addr & ~DA2_MASK_CRAM) != 0xE0000) // return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } static uint8_t -da2_code_readb(uint32_t addr, void *p) +da2_code_readb(uint32_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; cycles -= video_timing_read_b; return da2_code_read(addr, da2); } static uint16_t -da2_code_readw(uint32_t addr, void *p) +da2_code_readw(uint32_t addr, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; cycles -= video_timing_read_w; return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); } @@ -3153,9 +3150,9 @@ da2_poll(void *priv) } static void -da2_loadfont(char *fname, void *p) +da2_loadfont(char *fname, void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; uint8_t buf; uint64_t fsize; if (!fname) @@ -3239,7 +3236,7 @@ da2_reset(void *priv) da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Windows 3.1 display driver won't reset palette) */ - for (int i = 0; i < 256; i++) { + for (uint16_t i = 0; i < 256; i++) { da2->vgapal[i].r = ps55_palette_color[i & 0x3F][0]; da2->vgapal[i].g = ps55_palette_color[i & 0x3F][1]; da2->vgapal[i].b = ps55_palette_color[i & 0x3F][2]; @@ -3320,95 +3317,95 @@ da2_available(void) } static void -da2_close(void *p) +da2_close(void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; /* dump mem for debug */ #ifdef ENABLE_DA2_LOG - FILE *f; - f = fopen("da2_cram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->cram, DA2_SIZE_CRAM, 1, f); - fclose(f); + FILE *fp; + fp = fopen("da2_cram.dmp", "wb"); + if (fp != NULL) { + fwrite(da2->cram, DA2_SIZE_CRAM, 1, fp); + fclose(fp); } - f = fopen("da2_vram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vram, DA2_SIZE_VRAM, 1, f); - fclose(f); + fp = fopen("da2_vram.dmp", "wb"); + if (fp != NULL) { + fwrite(da2->vram, DA2_SIZE_VRAM, 1, fp); + fclose(fp); } - f = fopen("da2_gram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->mmio.ram, DA2_SIZE_GAIJIRAM, 1, f); - fclose(f); + fp = fopen("da2_gram.dmp", "wb"); + if (fp != NULL) { + fwrite(da2->mmio.ram, DA2_SIZE_GAIJIRAM, 1, fp); + fclose(fp); } - f = fopen("da2_attrpal.dmp", "wb"); - if (f != NULL) { - fwrite(da2->attrc, 32, 1, f); - fclose(f); + fp = fopen("da2_attrpal.dmp", "wb"); + if (fp != NULL) { + fwrite(da2->attrc, 32, 1, fp); + fclose(fp); } - f = fopen("da2_dacrgb.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vgapal, 3 * 256, 1, f); - fclose(f); + fp = fopen("da2_dacrgb.dmp", "wb"); + if (fp != NULL) { + fwrite(da2->vgapal, 3 * 256, 1, fp); + fclose(fp); } - f = fopen("da2_daregs.txt", "w"); - if (f != NULL) { - for (int i = 0; i < 0x10; i++) - fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); - for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); - for (int i = 0; i < 0x20; i++) { - fprintf(f, "vp %02X: %4X %4X %4X %4X\n", i, + fp = fopen("da2_daregs.txt", "w"); + if (fp != NULL) { + for (uint8_t i = 0; i < 0x10; i++) + fprintf(fp, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (uint8_t i = 0; i < 0x20; i++) + fprintf(fp, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (uint8_t i = 0; i < 0x20; i++) + fprintf(fp, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (uint8_t i = 0; i < 0x40; i++) + fprintf(fp, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); + for (uint8_t i = 0; i < 0x10; i++) + fprintf(fp, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (uint8_t i = 0; i < 0x10; i++) + fprintf(fp, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + for (uint8_t i = 0; i < 0x20; i++) { + fprintf(fp, "vp %02X: %4X %4X %4X %4X\n", i, da2->crtc_vpreg[0 + i], da2->crtc_vpreg[0x20 + i], da2->crtc_vpreg[0x40 + i], da2->crtc_vpreg[0x60 + i]); } - fclose(f); + fclose(fp); } - f = fopen("ram_low.dmp", "wb"); - if (f != NULL) { - fwrite(&ram[0x0], 0x100000, 1, f); - fclose(f); + fp = fopen("ram_low.dmp", "wb"); + if (fp != NULL) { + fwrite(&ram[0x0], 0x100000, 1, fp); + fclose(fp); } pclog("closed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); #endif #ifdef ENABLE_DA2_DEBUGBLT - f = fopen("da2_bltdump.csv", "w"); - if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + fp = fopen("da2_bltdump.csv", "w"); + if (fp != NULL && da2->bitblt.debug_reg_ip > 0) { /* print header */ for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) - fprintf(f, "\"%02X\"\t", y); + fprintf(fp, "\"%02X\"\t", y); } - fprintf(f, "\n"); + fprintf(fp, "\n"); /* print data */ for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) ; else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) - fprintf(f, "\"\"\t"); + fprintf(fp, "\"\"\t"); else { - fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); + fprintf(fp, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); if (y == 0x12) { int chr = da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + 0x12]; if ((chr >= 0x20) && (chr < 0x7f)) - fprintf(f, "\"%c\"\t", chr); + fprintf(fp, "\"%c\"\t", chr); else - fprintf(f, "\"\"\t"); + fprintf(fp, "\"\"\t"); } } } - fprintf(f, "\n"); + fprintf(fp, "\n"); } - fclose(f); + fclose(fp); } free(da2->bitblt.debug_reg); #endif @@ -3426,28 +3423,28 @@ da2_close(void *p) } static void -da2_speed_changed(void *p) +da2_speed_changed(void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); da2_recalctimings(da2); } static void -da2_force_redraw(void *p) +da2_force_redraw(void *priv) { - da2_t *da2 = (da2_t *) p; + da2_t *da2 = (da2_t *) priv; da2->fullchange = changeframecount; } static const device_config_t da2_configuration[] = { // clang-format off { - .name = "charset", + .name = "charset", .description = "Charset", - .type = CONFIG_SELECTION, + .type = CONFIG_SELECTION, .default_int = DA2_DCONFIG_CHARSET_JPAN, - .selection = { + .selection = { { .description = "932 (Japanese)", .value = DA2_DCONFIG_CHARSET_JPAN @@ -3460,11 +3457,11 @@ static const device_config_t da2_configuration[] = { } }, { - .name = "montype", + .name = "montype", .description = "Monitor type", - .type = CONFIG_SELECTION, + .type = CONFIG_SELECTION, .default_int = DA2_DCONFIG_MONTYPE_COLOR, - .selection = { + .selection = { { .description = "Color", .value = DA2_DCONFIG_MONTYPE_COLOR diff --git a/src/video/video.c b/src/video/video.c index 11edbc3f4..785479e15 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -1017,8 +1017,8 @@ loadfont_common(FILE *fp, int format) for (uint8_t d = 0; d < 8; d++) fontdatm[c][d + 8] = fgetc(fp) & 0xff; (void) fseek(fp, 4096 + 2048, SEEK_SET); - for (uint16_t c = 0; c < 256; c++) - for (uint8_t d = 0; d < 8; d++) /* 8x8 CGA (thick, primary) */ + for (uint16_t c = 0; c < 256; c++) /* 8x8 CGA (thick, primary) */ + for (uint8_t d = 0; d < 8; d++) fontdat[c][d] = fgetc(fp) & 0xff; break; From 6f8571c0262c6ab856c0b7afd6c8ea2433e12d6d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Mon, 26 May 2025 21:27:14 -0400 Subject: [PATCH 1068/1190] Fix a bug in EGA --- src/video/vid_ega.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 1022bda88..b0d58e0f6 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -282,7 +282,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) val = (ega->crtc[7] & ~0x10) | (val & 0x10); } else { idx &= crtcmask; - if ((idx >= 0x19) & (idx <= 0xf6)) + if ((idx >= 0x19) && (idx <= 0xf6)) return; if ((idx < 7) && (ega->crtc[0x11] & 0x80)) return; From 1d23c60daf6cc9346fe04f9ba7aab44d9d0e06cf Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sat, 7 Jun 2025 04:49:38 +0200 Subject: [PATCH 1069/1190] NEAT: Fix register 6Fh readout, fixes #5655. --- src/chipset/neat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 0661f89ee..0aa6fe5b6 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -988,7 +988,7 @@ neat_read(uint16_t port, void *priv) if ((dev->indx >= 0x60) && (dev->indx <= 0x6e)) ret = dev->regs[dev->indx]; else if (dev->indx == 0x6f) - ret = (dev->regs[dev->indx] & 0xfd) | ~(mem_a20_alt & 0x02); + ret = (dev->regs[dev->indx] & 0xfd) | ((~mem_a20_alt) & 0x02); break; default: From 77f1c62aeefdabdef776cd4df20ac5780cd2a757 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Mon, 26 May 2025 18:38:53 -0400 Subject: [PATCH 1070/1190] Support for alternate IBM EGA Address (Disabled behind ifdef because while it's a thing, you need a custom BIOS to use it) --- src/include/86box/vid_ega.h | 2 + src/video/vid_ega.c | 120 +++++++++++++++++++++++++++++++++--- 2 files changed, 115 insertions(+), 7 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 0e28820ff..c4c0ea2d7 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -148,6 +148,8 @@ typedef struct ega_t { card should not attempt to display anything. */ void (*render_override)(void *priv); void * priv_parent; + + uint8_t alt_addr; /* 0 for 0x3XX range, 1 for 0x2XX range */ } ega_t; #endif diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index b0d58e0f6..49b29f369 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -72,7 +72,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) uint8_t gdcmask = (ega_type == EGA_SUPEREGA) ? 0xff : 0x0f; uint8_t crtcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x1f; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) + if (((((addr & 0xfff0) == 0x3d0) || ((addr & 0xfff0) == 0x2d0)) || (((addr & 0xfff0) == 0x3b0) || ((addr & 0xfff0) == 0x2b0))) && !(ega->miscout & 1)) addr ^= 0x60; switch (addr) { @@ -94,7 +94,9 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } break; + case 0x2c0: case 0x3c0: + case 0x2c1: case 0x3c1: if (atype == EGA_SUPEREGA) val &= 0x7f; /* Bit 7 indicates the flipflop status (read only) */ @@ -139,6 +141,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } ega->attrff ^= 1; break; + case 0x2c2: case 0x3c2: o = ega->miscout; egaswitchread = (val & 0xc) >> 2; @@ -148,9 +151,15 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->miscout = val; ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : pallook64[ega->attrregs[0x11] & 0x3f]; - io_removehandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + + uint16_t base_addr = 0x03a0; +#ifdef EGA_ALT_ADDR_SUPPORT + if (ega->alt_addr == 1) + base_addr = 0x02a0; +#endif + io_removehandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); if (!(val & 1)) - io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + io_sethandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); ega_recalctimings(ega); if ((type == EGA_TYPE_COMPAQ) && !(val & 0x02)) mem_mapping_disable(&ega->mapping); @@ -172,9 +181,11 @@ ega_out(uint16_t addr, uint8_t val, void *priv) break; } break; + case 0x2c4: case 0x3c4: ega->seqaddr = val; break; + case 0x2c5: case 0x3c5: o = ega->seqregs[ega->seqaddr & 0xf]; ega->seqregs[ega->seqaddr & 0xf] = val; @@ -201,13 +212,16 @@ ega_out(uint16_t addr, uint8_t val, void *priv) break; } break; + case 0x2c6: case 0x3c6: if (type == EGA_TYPE_COMPAQ) ega->ctl_mode = val; break; + case 0x2ce: case 0x3ce: ega->gdcaddr = val; break; + case 0x2cf: case 0x3cf: ega->gdcreg[ega->gdcaddr & gdcmask] = val; switch (ega->gdcaddr & gdcmask) { @@ -264,14 +278,18 @@ ega_out(uint16_t addr, uint8_t val, void *priv) break; } break; + case 0x2d0: case 0x3d0: + case 0x2d4: case 0x3d4: if (ega->chipset) ega->crtcreg = val & 0x3f; else ega->crtcreg = val; return; + case 0x2d1: case 0x3d1: + case 0x2d5: case 0x3d5: { int idx = ega->crtcreg; @@ -322,7 +340,7 @@ ega_in(uint16_t addr, void *priv) uint8_t gdcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x0f; uint8_t crtcmask = (atype == EGA_SUPEREGA) ? 0xff : 0x1f; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) + if (((((addr & 0xfff0) == 0x3d0) || ((addr & 0xfff0) == 0x2d0)) || (((addr & 0xfff0) == 0x3b0) || ((addr & 0xfff0) == 0x2b0))) && !(ega->miscout & 1)) addr ^= 0x60; switch (addr) { @@ -343,7 +361,9 @@ ega_in(uint16_t addr, void *priv) } break; + case 0x2c0: case 0x3c0: + case 0x2c1: case 0x3c1: if (type == EGA_TYPE_OTHER) { int data = (atype == EGA_SUPEREGA) ? (ega->attrff & 1) : (addr & 1); @@ -356,9 +376,11 @@ ega_in(uint16_t addr, void *priv) ret = (ret & 0x3f) | (ega->attrff ? 0x80 : 0x00); } break; + case 0x2c2: case 0x3c2: ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; break; + case 0x2c4: case 0x3c4: if (type == EGA_TYPE_OTHER) { if (atype == EGA_SUPEREGA) @@ -367,6 +389,7 @@ ega_in(uint16_t addr, void *priv) ret = ega->seqaddr; } break; + case 0x2c5: case 0x3c5: if (type == EGA_TYPE_OTHER) { if ((ega->seqaddr & 0x0f) > 0x04) @@ -375,18 +398,22 @@ ega_in(uint16_t addr, void *priv) ret = ega->seqregs[ega->seqaddr & 0xf]; } break; + case 0x2c6: case 0x3c6: if (type == EGA_TYPE_COMPAQ) ret = ega->ctl_mode; break; + case 0x2c8: case 0x3c8: if (type == EGA_TYPE_OTHER) ret = 2; break; + case 0x2cc: case 0x3cc: if (type == EGA_TYPE_OTHER) ret = ega->miscout; break; + case 0x2ce: case 0x3ce: if (ega_type == EGA_TYPE_OTHER) { ret = ega->gdcaddr; @@ -397,6 +424,7 @@ ega_in(uint16_t addr, void *priv) } } break; + case 0x2cf: case 0x3cf: if (type == EGA_TYPE_OTHER) { switch (ega->gdcaddr & gdcmask) { @@ -421,7 +449,9 @@ ega_in(uint16_t addr, void *priv) } } break; + case 0x2d0: case 0x3d0: + case 0x2d4: case 0x3d4: if (ega_type == EGA_TYPE_OTHER) { ret = ega->crtcreg; @@ -432,7 +462,9 @@ ega_in(uint16_t addr, void *priv) } } break; + case 0x2d1: case 0x3d1: + case 0x2d5: case 0x3d5: switch (ega->crtcreg & crtcmask) { case 0xc: @@ -467,6 +499,7 @@ ega_in(uint16_t addr, void *priv) break; } break; + case 0x2da: case 0x3da: ega->attrff = 0; if (type == EGA_TYPE_COMPAQ) { @@ -1464,7 +1497,12 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) } } - io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + uint16_t base_addr = 0x03a0; +#ifdef EGA_ALT_ADDR_SUPPORT + if (ega->alt_addr == 1) + base_addr = 0x02a0; +#endif + io_sethandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); } else { for (uint16_t c = 0; c < 256; c++) { pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); @@ -1619,7 +1657,15 @@ ega_standalone_init(const device_t *info) mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); if (ega_type == EGA_TYPE_COMPAQ) mem_mapping_disable(&ega->mapping); - io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + uint16_t addr = 0x03c0; +#ifdef EGA_ALT_ADDR_SUPPORT + if (ega_type == EGA_TYPE_IBM) { + addr = device_get_config_hex16("base"); + if (addr == 0x02c0) + ega->alt_addr = 1; + } +#endif + io_sethandler(addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); if (ega->chipset) { io_sethandler(0x01ce, 0x0002, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); @@ -1699,6 +1745,66 @@ ega_speed_changed(void *priv) 0 = Switch closed (ON); 1 = Switch open (OFF). */ +static const device_config_t ega_ibm_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "32 KB", .value = 32 }, + { .description = "64 KB", .value = 64 }, + { .description = "128 KB", .value = 128 }, + { .description = "256 KB", .value = 256 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "monitor_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 9, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Monochrome (5151/MDA) (white)", .value = 0x0B | (DISPLAY_WHITE << 4) }, + { .description = "Monochrome (5151/MDA) (green)", .value = 0x0B | (DISPLAY_GREEN << 4) }, + { .description = "Monochrome (5151/MDA) (amber)", .value = 0x0B | (DISPLAY_AMBER << 4) }, + { .description = "Color 40x25 (5153/CGA)", .value = 0x06 }, + { .description = "Color 80x25 (5153/CGA)", .value = 0x07 }, + { .description = "Enhanced Color - Normal Mode (5154/ECD)", .value = 0x08 }, + { .description = "Enhanced Color - Enhanced Mode (5154/ECD)", .value = 0x09 }, + { .description = "" } + }, + .bios = { { 0 } } + }, +#ifdef EGA_ALT_ADDR_SUPPORT + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x03c0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x3C0", .value = 0x03c0 }, + { .description = "0x2C0", .value = 0x02c0 }, + { .description = "" } + }, + .bios = { { 0 } } + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + static const device_config_t ega_config[] = { // clang-format off { @@ -1753,7 +1859,7 @@ const device_t ega_device = { .available = ega_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, - .config = ega_config + .config = ega_ibm_config }; const device_t cpqega_device = { From ee5508f3062ce5cbc9da4b1e588decc6a0910778 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Mon, 26 May 2025 21:28:20 -0400 Subject: [PATCH 1071/1190] Assorted EGA code optimizations --- src/video/vid_ega.c | 63 ++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 49b29f369..d1e82dfda 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -110,8 +110,9 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } else { if ((ega->attraddr == 0x13) && (ega->attrregs[0x13] != val)) ega->fullchange = changeframecount; - o = ega->attrregs[ega->attraddr & 31]; - ega->attrregs[ega->attraddr & 31] = val; + uint8_t aidx = ega->attraddr & 31; + o = ega->attrregs[aidx]; + ega->attrregs[aidx] = val; if (ega->attraddr < 16) ega->fullchange = changeframecount; int is_attr14 = ega->chipset && (ega->attraddr == 0x14); @@ -222,9 +223,10 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->gdcaddr = val; break; case 0x2cf: - case 0x3cf: - ega->gdcreg[ega->gdcaddr & gdcmask] = val; - switch (ega->gdcaddr & gdcmask) { + case 0x3cf: { + uint8_t reg = ega->gdcaddr & gdcmask; + ega->gdcreg[reg] = val; + switch (reg) { case 2: ega->colourcompare = val; break; @@ -278,14 +280,12 @@ ega_out(uint16_t addr, uint8_t val, void *priv) break; } break; + } case 0x2d0: case 0x3d0: case 0x2d4: case 0x3d4: - if (ega->chipset) - ega->crtcreg = val & 0x3f; - else - ega->crtcreg = val; + ega->crtcreg = ega->chipset ? (val & 0x3f) : val; return; case 0x2d1: case 0x3d1: @@ -294,9 +294,9 @@ ega_out(uint16_t addr, uint8_t val, void *priv) int idx = ega->crtcreg; if (ega->chipset) { - if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) + if ((idx < 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) return; - if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) + if ((idx == 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) val = (ega->crtc[7] & ~0x10) | (val & 0x10); } else { idx &= crtcmask; @@ -392,10 +392,11 @@ ega_in(uint16_t addr, void *priv) case 0x2c5: case 0x3c5: if (type == EGA_TYPE_OTHER) { - if ((ega->seqaddr & 0x0f) > 0x04) - ret = ega->chipset ? ega->seqregs[ega->seqaddr & 0xf] : 0xff; + uint8_t idx = ega->seqaddr & 0xf; + if (idx > 0x04) + ret = ega->chipset ? ega->seqregs[idx] : 0xff; else - ret = ega->seqregs[ega->seqaddr & 0xf]; + ret = ega->seqregs[idx]; } break; case 0x2c6: @@ -415,7 +416,7 @@ ega_in(uint16_t addr, void *priv) break; case 0x2ce: case 0x3ce: - if (ega_type == EGA_TYPE_OTHER) { + if (type == EGA_TYPE_OTHER) { ret = ega->gdcaddr; if (atype == EGA_SUPEREGA) { ret = (ret & 0x0f) | 0xe0; @@ -427,12 +428,13 @@ ega_in(uint16_t addr, void *priv) case 0x2cf: case 0x3cf: if (type == EGA_TYPE_OTHER) { - switch (ega->gdcaddr & gdcmask) { + uint8_t gidx = ega->gdcaddr & gdcmask; + switch (gidx) { default: - ret = ega->gdcreg[ega->gdcaddr & gdcmask]; + ret = ega->gdcreg[gidx]; break; case 0x09 ... 0xf7: - ret = ega->chipset ? ega->gdcreg[ega->gdcaddr & gdcmask] : 0xff; + ret = ega->chipset ? ega->gdcreg[gidx] : 0xff; break; case 0xf8: ret = ega->la; @@ -453,7 +455,7 @@ ega_in(uint16_t addr, void *priv) case 0x3d0: case 0x2d4: case 0x3d4: - if (ega_type == EGA_TYPE_OTHER) { + if (type == EGA_TYPE_OTHER) { ret = ega->crtcreg; if (atype == EGA_SUPEREGA) { ret = (ret & 0x1f) | 0xc0; @@ -560,6 +562,7 @@ ega_recalctimings(ega_t *ega) double _dispofftime; double disptime; double crtcconst; + double mdiv = (ega->seqregs[1] & 1) ? 8.0 : 9.0; ega->vtotal = ega->crtc[6]; ega->dispend = ega->crtc[0x12]; @@ -613,10 +616,7 @@ ega_recalctimings(ega_t *ega) else crtcconst = (cpuclock / 16872000.0 * (double) (1ULL << 32)); } - if (!(ega->seqregs[1] & 1)) - crtcconst *= 9.0; - else - crtcconst *= 8.0; + crtcconst *= mdiv; } else if (ega->eeprom) { clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); @@ -638,20 +638,14 @@ ega_recalctimings(ega_t *ega) crtcconst = (cpuclock / 36000000.0 * (double) (1ULL << 32)); break; } - if (!(ega->seqregs[1] & 1)) - crtcconst *= 9.0; - else - crtcconst *= 8.0; + crtcconst *= mdiv; } else { if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); } - if (!(ega->seqregs[1] & 1)) - ega->dot_clock = crtcconst / 9.0; - else - ega->dot_clock = crtcconst / 8.0; + ega->dot_clock = crtcconst / mdiv; ega->interlace = 0; @@ -664,13 +658,12 @@ ega_recalctimings(ega_t *ega) ega->hdisp *= (ega->seqregs[1] & 1) ? 16 : 18; else ega->hdisp *= (ega->seqregs[1] & 1) ? 8 : 9; - ega->render = ega_render_text; - ega->hdisp_old = ega->hdisp; + ega->render = ega_render_text; } else { ega->hdisp *= (ega->seqregs[1] & 8) ? 16 : 8; - ega->render = ega_render_graphics; - ega->hdisp_old = ega->hdisp; + ega->render = ega_render_graphics; } + ega->hdisp_old = ega->hdisp; } if (ega->chipset) { From a0fda06500f37eb11d66aa7c5d2e5ee9dd5b5111 Mon Sep 17 00:00:00 2001 From: The Dax <thedax@users.noreply.github.com> Date: Sat, 7 Jun 2025 02:04:38 -0400 Subject: [PATCH 1072/1190] Add the Quantum3D Raven to the list of cards recognized as Voodoos/Banshees. This brings it in line with the other Voodoo 3/Banshee cards that don't permit Voodoo 1 or two at the same time without the ini tweak. --- src/qt/qt_settingsdisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 300dae80e..83e19aec7 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -171,7 +171,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) if (index < 0) return; - static QRegularExpression voodooRegex("3dfx|voodoo|banshee", QRegularExpression::CaseInsensitiveOption); + static QRegularExpression voodooRegex("3dfx|voodoo|banshee|raven", QRegularExpression::CaseInsensitiveOption); auto curVideoCard_2 = videoCard[1]; videoCard[0] = ui->comboBoxVideo->currentData().toInt(); if (videoCard[0] == VID_INTERNAL) From d66066fa936fb334e0b39c1ec3342061d546aa16 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sat, 7 Jun 2025 16:51:22 +0200 Subject: [PATCH 1073/1190] QT: Fix a warning. --- src/qt/qt_glsl_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index 599a95452..9efeb430b 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -118,7 +118,7 @@ static char *load_file(const char *fn) { char *data = (char*)malloc(fsize + 1); - (void *) !fread(data, fsize, 1, fp); + (void) fread(data, fsize, 1, fp); fclose(fp); data[fsize] = 0; From 2c0966637399e802a856024a3d753346d226b666 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sat, 7 Jun 2025 17:14:35 +0200 Subject: [PATCH 1074/1190] Added the Tulip AT Compact (TC7). --- src/include/86box/machine.h | 2 ++ src/machine/m_at_286_386sx.c | 33 ++++++++++++++++++++++++----- src/machine/machine_table.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 112d140f8..85b55ae51 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -473,7 +473,9 @@ extern int machine_at_spc4216p_init(const machine_t *); extern int machine_at_spc4620p_init(const machine_t *); extern int machine_at_kmxc02_init(const machine_t *); extern int machine_at_deskmaster286_init(const machine_t *); + extern int machine_at_dells200_init(const machine_t *); +extern int machine_at_tuliptc7_init(const machine_t *); extern int machine_at_pc8_init(const machine_t *); extern int machine_at_3302_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 6ac5b0195..29298510c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -262,6 +262,19 @@ machine_at_px286_init(const machine_t *model) return ret; } +static void +machine_at_ctat_common_init(const machine_t *model) +{ + machine_at_common_init(model); + + device_add(&cs8220_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&keyboard_at_phoenix_device); +} + int machine_at_dells200_init(const machine_t *model) { @@ -274,14 +287,24 @@ machine_at_dells200_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_ctat_common_init(model); - device_add(&cs8220_device); + return ret; +} - if (fdc_current[0] == FDC_INTERNAL) - device_add(&fdc_at_device); +int +machine_at_tuliptc7_init(const machine_t *model) +{ + int ret; - device_add(&keyboard_at_phoenix_device); + ret = bios_load_interleavedr("roms/machines/tuliptc7/tc7be.bin", + "roms/machines/tuliptc7/tc7bo.bin", + 0x000f8000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ctat_common_init(model); return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 611e70c4d..c90cbf0bb 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3415,6 +3415,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC + firmware. */ + { + .name = "[C&T PC/AT] Tulip AT Compact", + .internal_name = "tuliptc7", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_CT_AT, + .init = machine_at_tuliptc7_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 12000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .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 Quadtel KBC firmware. */ { .name = "[GC103] Quadtel 286 clone", From 3101fc496843c85199042218c72f4829b8ae5489 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:27:11 +0200 Subject: [PATCH 1075/1190] Fix unnecessary space in the german translation. --- src/qt/languages/de-DE.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 439346608..267e4b13e 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1834,7 +1834,7 @@ msgid "2 MB" msgstr "2 MB" msgid "8 MB" -msgstr " 8 MB" +msgstr "8 MB" msgid "28 MB" msgstr "28 MB" From 55b4f0bd0d3098a2a0ab597f717d1721187b2bc5 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:28:13 +0200 Subject: [PATCH 1076/1190] Fix unnecessary space in the Czech translation. --- src/qt/languages/cs-CZ.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 593020962..cd726832d 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -1834,7 +1834,7 @@ msgid "2 MB" msgstr "2 MB" msgid "8 MB" -msgstr " 8 MB" +msgstr "8 MB" msgid "28 MB" msgstr "28 MB" From 77195a725da1c51ddca3adb84574918e9bfc76df Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:28:56 +0200 Subject: [PATCH 1077/1190] Fix unnecessary space in the Spanish translation. --- src/qt/languages/es-ES.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 363d56c45..5454ab1de 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -1833,7 +1833,7 @@ msgid "2 MB" msgstr "2 MB" msgid "8 MB" -msgstr " 8 MB" +msgstr "8 MB" msgid "28 MB" msgstr "28 MB" From be0ad9ecde51a51ee3b8dbdbbbce24f91cc34c9e Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:30:16 +0200 Subject: [PATCH 1078/1190] Fix unnecessary space in the Catalonian translation. --- src/qt/languages/ca-ES.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 632af979a..c9fc9bd82 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -1834,7 +1834,7 @@ msgid "2 MB" msgstr "2 MB" msgid "8 MB" -msgstr " 8 MB" +msgstr "8 MB" msgid "28 MB" msgstr "28 MB" From f6e6c11fc498662cd2134cfe5d8b1c7a304fdc05 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:31:47 +0200 Subject: [PATCH 1079/1190] Fix unnecessary space in the Croatian translation. --- src/qt/languages/hr-HR.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 50dd298c2..0330cd59a 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -1834,7 +1834,7 @@ msgid "2 MB" msgstr "2 MB" msgid "8 MB" -msgstr " 8 MB" +msgstr "8 MB" msgid "28 MB" msgstr "28 MB" From cf042e95cbb3cca6b8cf4ce64a4474941e847096 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Sat, 7 Jun 2025 22:50:21 +0200 Subject: [PATCH 1080/1190] ATI EGA Wonder 800 Plus changes (June 7th, 2025) It really comes down to the EEPROM for the monitor settings and fixes for resolutions between hdisp > 640 && hdisp < 800 (like MDA) --- src/video/vid_ega.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index d1e82dfda..c21b7c714 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -667,7 +667,7 @@ ega_recalctimings(ega_t *ega) } if (ega->chipset) { - if (ega->hdisp > 640) { + if (ega->hdisp >= 800) { ega->dispend <<= 1; ega->vtotal <<= 1; ega->split <<= 1; @@ -881,7 +881,7 @@ ega_poll(void *priv) ega->stat &= ~8; ega->vslines++; if (ega->chipset) { - if (ega->hdisp > 640) { + if (ega->hdisp >= 800) { if (ega->displine > 2000) ega->displine = 0; } else { @@ -932,7 +932,7 @@ ega_poll(void *priv) !(ega->real_vc & 1)) ega->vc++; if (ega->chipset) { - if (ega->hdisp > 640) + if (ega->hdisp >= 800) ega->vc &= 1023; else ega->vc &= 511; @@ -1641,7 +1641,7 @@ ega_standalone_init(const device_t *info) } } - monitor_type = device_get_config_int("monitor_type"); + monitor_type = ega->chipset ? 0x09 : device_get_config_int("monitor_type"); ega_init(ega, monitor_type, (monitor_type & 0x0F) == 0x0B); ega->vram_limit = device_get_config_int("memory") * 1024; @@ -1841,6 +1841,29 @@ static const device_config_t ega_config[] = { // clang-format on }; +static const device_config_t atiega800p_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 256, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "32 KB", .value = 32 }, + { .description = "64 KB", .value = 64 }, + { .description = "128 KB", .value = 128 }, + { .description = "256 KB", .value = 256 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t ega_device = { .name = "IBM EGA", .internal_name = "ega", @@ -1894,7 +1917,7 @@ const device_t atiega800p_device = { .available = atiega800p_standalone_available, .speed_changed = ega_speed_changed, .force_redraw = NULL, - .config = ega_config + .config = atiega800p_config }; const device_t iskra_ega_device = { From 16975c374f87269b29ea13eb55920bcce1b31feb Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sun, 4 May 2025 21:44:53 -0400 Subject: [PATCH 1081/1190] ISA ROM Board Support --- src/86box.c | 8 +- src/config.c | 26 + src/device/CMakeLists.txt | 1 + src/device/isarom.c | 643 +++++++++++++++++++++++++ src/include/86box/86box.h | 1 + src/include/86box/config.h | 1 + src/include/86box/isarom.h | 37 ++ src/machine/machine.c | 6 + src/qt/qt_settingsotherperipherals.cpp | 112 +++++ src/qt/qt_settingsotherperipherals.hpp | 9 + src/qt/qt_settingsotherperipherals.ui | 117 +++++ 11 files changed, 960 insertions(+), 1 deletion(-) create mode 100644 src/device/isarom.c create mode 100644 src/include/86box/isarom.h diff --git a/src/86box.c b/src/86box.c index f54a69b79..92e2f0c24 100644 --- a/src/86box.c +++ b/src/86box.c @@ -70,6 +70,7 @@ #include <86box/unittester.h> #include <86box/novell_cardkey.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/isartc.h> #include <86box/lpt.h> #include <86box/serial.h> @@ -181,6 +182,7 @@ int postcard_enabled = 0; /* (C) enable int unittester_enabled = 0; /* (C) enable unit tester device */ int gameport_type[GAMEPORT_MAX] = { 0, 0 }; /* (C) enable gameports */ int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */ +int isarom_type[ISAROM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA ROM cards */ int isartc_type = 0; /* (C) enable ISA RTC card */ int gfxcard[GFXCARD_MAX] = { 0, 0 }; /* (C) graphics/video card */ int show_second_monitors = 1; /* (C) show non-primary monitors */ @@ -1472,6 +1474,10 @@ pc_reset_hard_init(void) zip_hard_reset(); + + /* Reset any ISA ROM cards. */ + isarom_reset(); + /* Reset any ISA RTC cards. */ isartc_reset(); @@ -1901,4 +1907,4 @@ int FindAccelerator(const char *name) { } // No key was found return -1; -} \ No newline at end of file +} diff --git a/src/config.c b/src/config.c index dfe0190ac..8039b9887 100644 --- a/src/config.c +++ b/src/config.c @@ -46,6 +46,7 @@ #include <86box/ini.h> #include <86box/config.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/isartc.h> #include <86box/lpt.h> #include <86box/serial.h> @@ -1699,6 +1700,7 @@ load_other_peripherals(void) if (!novell_keycard_enabled) ini_section_delete_var(cat, "novell_keycard_enabled"); + // ISA RAM Boards for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); @@ -1709,6 +1711,17 @@ load_other_peripherals(void) ini_section_delete_var(cat, temp); } + // ISA ROM Boards + for (uint8_t c = 0; c < ISAROM_MAX; c++) { + sprintf(temp, "isarom%d_type", c); + + p = ini_section_get_string(cat, temp, "none"); + isarom_type[c] = isarom_get_from_internal_name(p); + + if (!strcmp(p, "none")) + ini_section_delete_var(cat, temp); + } + p = ini_section_get_string(cat, "isartc_type", "none"); isartc_type = isartc_get_from_internal_name(p); @@ -1858,6 +1871,8 @@ config_load(void) cdrom[0].sound_on = 1; mem_size = 64; isartc_type = 0; + for (i = 0; i < ISAROM_MAX; i++) + isarom_type[i] = 0; for (i = 0; i < ISAMEM_MAX; i++) isamem_type[i] = 0; @@ -2706,6 +2721,7 @@ save_other_peripherals(void) else ini_section_set_int(cat, "novell_keycard_enabled", novell_keycard_enabled); + // ISA RAM Boards for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); if (isamem_type[c] == 0) @@ -2715,6 +2731,16 @@ save_other_peripherals(void) isamem_get_internal_name(isamem_type[c])); } + // ISA ROM Boards + for (uint8_t c = 0; c < ISAROM_MAX; c++) { + sprintf(temp, "isarom%d_type", c); + if (isarom_type[c] == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + isarom_get_internal_name(isarom_type[c])); + } + if (isartc_type == 0) ini_section_delete_var(cat, "isartc_type"); else diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 486d40b07..ea89f5cd9 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(dev OBJECT i2c_gpio.c ibm_5161.c isamem.c + isarom.c isartc.c isapnp.c kbc_at.c diff --git a/src/device/isarom.c b/src/device/isarom.c new file mode 100644 index 000000000..238314c87 --- /dev/null +++ b/src/device/isarom.c @@ -0,0 +1,643 @@ +/* + * 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. + * + * Implementation of ISA ROM card Expansions. + * + * Authors: Jasmine Iwanek, <jriwanek@gmail.com> + * + * Copyright 2025 Jasmine Iwanek. + */ +#include <stdarg.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/nvr.h> +#include <86box/isarom.h> + +#define ISAROM_CARD 0 +#define ISAROM_CARD_DUAL 1 +#define ISAROM_CARD_QUAD 2 + +#ifdef ENABLE_ISAROM_LOG +int isarom_do_log = ENABLE_ISAROM_LOG; + +static void +isarom_log(const char *fmt, ...) +{ + va_list ap; + + if (isarom_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define isarom_log(fmt, ...) +#endif + +typedef struct isarom_t { + struct { + rom_t rom; + uint32_t addr; + const char *fn; + uint32_t size; + uint32_t len; + char nvr_path[64]; + uint8_t wp; + } socket[4]; + uint8_t inst; + uint8_t type; +} isarom_t; + +static inline uint8_t +get_limit(uint8_t type) +{ + if (type == ISAROM_CARD_DUAL) + return 2; + if (type == ISAROM_CARD_QUAD) + return 4; + return 1; +} + +static inline void +isarom_save_nvr(char *path, uint8_t *data, size_t size) +{ + if (path[0] == 0x00) + return; + + FILE *fp = nvr_fopen(path, "wb"); + if (fp) { + fwrite(data, 1, size, fp); + fclose(fp); + } +} + +void +isarom_close(void *priv) +{ + isarom_t *dev = (isarom_t *) priv; + if (!priv) + return; + + for (uint8_t i = 0; i < get_limit(dev->type); i++) + if (dev->socket[i].rom.rom) { + isarom_log("isarom[%u]: saving NVR for socket %u -> %s (%u bytes)\n", + dev->inst, i, dev->socket[i].nvr_path, dev->socket[i].size); + isarom_save_nvr(dev->socket[i].nvr_path, dev->socket[i].rom.rom, dev->socket[i].size); + } + + free(dev); +} + +static void * +isarom_init(const device_t *info) +{ + isarom_t *dev = (isarom_t *) calloc(1, sizeof(isarom_t)); + if (!dev) + return NULL; + + dev->inst = device_get_instance(); + dev->type = (uint8_t) info->local; + + isarom_log("isarom[%u]: initializing device (type=%u)\n", dev->inst, dev->type); + + for (uint8_t i = 0; i < get_limit(dev->type); i++) { + char key_fn[12]; + char key_addr[14]; + char key_size[14]; + char key_writes[22]; + char suffix[4] = ""; + if (i > 0) + snprintf(suffix, sizeof(suffix), "%d", i + 1); + + snprintf(key_fn, sizeof(key_fn), "bios_fn%s", suffix); + snprintf(key_addr, sizeof(key_addr), "bios_addr%s", suffix); + snprintf(key_size, sizeof(key_size), "bios_size%s", suffix); + snprintf(key_writes, sizeof(key_writes), "rom_writes_enabled%s", suffix); + + dev->socket[i].fn = device_get_config_string(key_fn); + dev->socket[i].addr = device_get_config_hex20(key_addr); + dev->socket[i].size = device_get_config_int(key_size); + // Note: 2K is the smallest ROM I've found, but 86box's memory granularity is 4k, the number below is fine + // as we'll end up allocating no less than 4k due to the device config limits. + dev->socket[i].len = (dev->socket[i].size > 2048) ? dev->socket[i].size - 1 : 0; + dev->socket[i].wp = (uint8_t) device_get_config_int(key_writes) ? 1 : 0; + + isarom_log("isarom[%u]: socket %u: addr=0x%05X size=%u wp=%u fn=%s\n", + dev->inst, i, dev->socket[i].addr, dev->socket[i].size, + dev->socket[i].wp, dev->socket[i].fn ? dev->socket[i].fn : "(null)"); + + if (dev->socket[i].addr != 0 && dev->socket[i].fn != NULL) { + rom_init(&dev->socket[i].rom, + dev->socket[i].fn, + dev->socket[i].addr, + dev->socket[i].size, + dev->socket[i].len, + 0, + MEM_MAPPING_EXTERNAL); + + isarom_log("isarom[%u]: ROM initialized for socket %u\n", dev->inst, i); + + if (dev->socket[i].wp) { + mem_mapping_set_write_handler(&dev->socket[i].rom.mapping, rom_write, rom_writew, rom_writel); + snprintf(dev->socket[i].nvr_path, sizeof(dev->socket[i].nvr_path), "isarom_%i_%i.nvr", dev->inst, i + 1); + FILE *fp = nvr_fopen(dev->socket[i].nvr_path, "rb"); + if (fp != NULL) { + fread(dev->socket[i].rom.rom, 1, dev->socket[i].size, fp); + fclose(fp); + isarom_log("isarom[%u]: loaded %zu bytes from %s\n", dev->inst, read_bytes, dev->socket[i].nvr_path); + } else + isarom_log("isarom[%u]: NVR not found, skipping load (%s)\n", dev->inst, dev->socket[i].nvr_path); + } + } + } + + return dev; +} + +#define BIOS_FILE_FILTER "ROM files (*.bin *.rom)|*.bin,*.rom" + +#define BIOS_ADDR_SELECTION { \ + { "Disabled", 0x00000 }, \ + { "C000H", 0xc0000 }, \ + { "C200H", 0xc2000 }, \ + { "C400H", 0xc4000 }, \ + { "C600H", 0xc6000 }, \ + { "C800H", 0xc8000 }, \ + { "CA00H", 0xca000 }, \ + { "CC00H", 0xcc000 }, \ + { "CE00H", 0xce000 }, \ + { "D000H", 0xd0000 }, \ + { "D200H", 0xd2000 }, \ + { "D400H", 0xd4000 }, \ + { "D600H", 0xd6000 }, \ + { "D800H", 0xd8000 }, \ + { "DA00H", 0xda000 }, \ + { "DC00H", 0xdc000 }, \ + { "DE00H", 0xde000 }, \ + { "E000H", 0xe0000 }, \ + { "E200H", 0xe2000 }, \ + { "E400H", 0xe4000 }, \ + { "E600H", 0xe6000 }, \ + { "E800H", 0xe8000 }, \ + { "EA00H", 0xea000 }, \ + { "EC00H", 0xec000 }, \ + { "EE00H", 0xee000 }, \ + { "", 0 } \ +} + +#define BIOS_SIZE_SELECTION { \ + { "4K", 4096 }, \ + { "8K", 8192 }, \ + { "16K", 16384 }, \ + { "32K", 32768 }, \ + { "64K", 65536 }, \ + { "", 0 } \ +} + +// clang-format off +static const device_config_t isarom_config[] = { + { + .name = "bios_fn", + .description = "BIOS File", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size", + .description = "BIOS Size:", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t isarom_dual_config[] = { + { + .name = "bios_fn", + .description = "BIOS File (ROM #1)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address (ROM #1)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size", + .description = "BIOS Size (ROM #1):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes (ROM #1)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn2", + .description = "BIOS File (ROM #2)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr2", + .description = "BIOS Address (ROM #2)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size2", + .description = "BIOS Size (ROM #2):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled2", + .description = "Enable BIOS extension ROM Writes (ROM #2)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t isarom_quad_config[] = { + { + .name = "bios_fn", + .description = "BIOS File (ROM #1)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address (ROM #1)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size", + .description = "BIOS Size (ROM #1):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes (ROM #1)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn2", + .description = "BIOS File (ROM #2)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr2", + .description = "BIOS Address (ROM #2)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size2", + .description = "BIOS Size (ROM #2):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled2", + .description = "Enable BIOS extension ROM Writes (ROM #2)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn3", + .description = "BIOS File (ROM #3)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = "ROM files (*.bin *.rom)|*.bin,*.rom", + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr3", + .description = "BIOS Address (ROM #3)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size3", + .description = "BIOS Size (ROM #3):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled3", + .description = "Enable BIOS extension ROM Writes (ROM #3)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn4", + .description = "BIOS File (ROM #4)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr4", + .description = "BIOS Address (ROM #4)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size4", + .description = "BIOS Size (ROM #4):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled4", + .description = "Enable BIOS extension ROM Writes (ROM #4)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +static const device_t isarom_device = { + .name = "Generic ISA ROM Board", + .internal_name = "isarom", + .flags = DEVICE_ISA, + .local = ISAROM_CARD, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = isarom_config +}; + +static const device_t isarom_dual_device = { + .name = "Generic Dual ISA ROM Board", + .internal_name = "isarom_dual", + .flags = DEVICE_ISA, + .local = ISAROM_CARD_DUAL, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = isarom_dual_config +}; + +static const device_t isarom_quad_device = { + .name = "Generic Quad ISA ROM Board", + .internal_name = "isarom_quad", + .flags = DEVICE_ISA, + .local = ISAROM_CARD_QUAD, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = isarom_quad_config +}; + +static const struct { + const device_t *dev; +} boards[] = { + // clang-format off + { &device_none }, + { &isarom_device }, + { &isarom_dual_device }, + { &isarom_quad_device }, + { NULL } + // clang-format on +}; + +void +isarom_reset(void) +{ + for (uint8_t i = 0; i < ISAROM_MAX; i++) { + if (isarom_type[i] == 0) + continue; + + /* Add the device instance to the system. */ + device_add_inst(boards[isarom_type[i]].dev, i + 1); + } +} + +const char * +isarom_get_name(int board) +{ + if (boards[board].dev == NULL) + return NULL; + + return (boards[board].dev->name); +} + +const char * +isarom_get_internal_name(int board) +{ + return device_get_internal_name(boards[board].dev); +} + +int +isarom_get_from_internal_name(const char *str) +{ + int c = 0; + + while (boards[c].dev != NULL) { + if (!strcmp(boards[c].dev->internal_name, str)) + return c; + c++; + } + + /* Not found. */ + return 0; +} + +const device_t * +isarom_get_device(int board) +{ + /* Add the device instance to the system. */ + return boards[board].dev; +} + +int +isarom_has_config(int board) +{ + if (boards[board].dev == NULL) + return 0; + + return (boards[board].dev->config ? 1 : 0); +} diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 76f311d17..8bf303961 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -134,6 +134,7 @@ extern int postcard_enabled; /* (C) enable POST card */ extern int unittester_enabled; /* (C) enable unit tester device */ extern int gameport_type[]; /* (C) enable gameports */ extern int isamem_type[]; /* (C) enable ISA mem cards */ +extern int isarom_type[]; /* (C) enable ISA ROM cards */ extern int isartc_type; /* (C) enable ISA RTC card */ extern int sound_is_float; /* (C) sound uses FP values */ extern int voodoo_enabled; /* (C) video option */ diff --git a/src/include/86box/config.h b/src/include/86box/config.h index 693f38ab7..34447266b 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -122,6 +122,7 @@ typedef struct config_t { int ide_qua_enabled; /* Quaternary IDE controller enabled */ int bugger_enabled; /* ISA bugger device enabled */ int isa_rtc_type; /* ISA RTC card */ + int isa_rom_type[ISAROM_MAX]; /* ISA ROM boards */ int isa_mem_type[ISAMEM_MAX]; /* ISA memory boards */ /* Hard disks category */ diff --git a/src/include/86box/isarom.h b/src/include/86box/isarom.h new file mode 100644 index 000000000..91cfa15a9 --- /dev/null +++ b/src/include/86box/isarom.h @@ -0,0 +1,37 @@ +/* + * 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. + * + * Implementation of ISA ROM card Expansions. + * + * Authors: Jasmine Iwanek, <jriwanek@gmail.com> + * + * Copyright 2025 Jasmine Iwanek. + */ +#ifndef EMU_ISAROM_H +#define EMU_ISAROM_H + +#define ISAROM_MAX 4 /* max #cards in system */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions. */ +extern void isarom_reset(void); + +extern const char *isarom_get_name(int t); +extern const char *isarom_get_internal_name(int t); +extern int isarom_get_from_internal_name(const char *str); +extern const device_t *isarom_get_device(int t); +extern int isarom_has_config(int board); + +#ifdef __cplusplus +} +#endif + +#endif /*EMU_ISAROM_H*/ diff --git a/src/machine/machine.c b/src/machine/machine.c index 505674000..6a86b785f 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -39,6 +39,7 @@ #include <86box/video.h> #include <86box/machine.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/pci.h> #include <86box/plat_unused.h> @@ -111,6 +112,11 @@ machine_init_ex(int m) /* Reset any ISA memory cards. */ isamem_reset(); +#if 0 + /* Reset any ISA ROM cards. */ + isarom_reset(); +#endif + /* Reset the fast off stuff. */ cpu_fast_off_reset(); diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index b8a347f25..0ecdc30d3 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -24,6 +24,7 @@ extern "C" { #include <86box/device.h> #include <86box/machine.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/isartc.h> #include <86box/unittester.h> #include <86box/novell_cardkey.h> @@ -65,6 +66,10 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) if (auto *cb = findChild<QComboBox *>(QString("comboBoxIsaMemCard%1").arg(i + 1))) cb->clear(); + for (uint8_t i = 0; i < ISAROM_MAX; ++i) + if (auto *cb = findChild<QComboBox *>(QString("comboBoxIsaRomCard%1").arg(i + 1))) + cb->clear(); + int c = 0; int selectedRow = 0; @@ -127,6 +132,47 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) findChild<QPushButton *>(QString("pushButtonConfigureIsaMemCard%1").arg(i + 1))->setEnabled((isamem_type[i] != 0) && isamem_has_config(isamem_type[i]) && machineHasIsa); } + + // ISA ROM Expansion Cards + QComboBox *isarom_cbox[ISAROM_MAX] = { 0 }; + QAbstractItemModel *isarom_models[ISAROM_MAX] = { 0 }; + int isarom_removeRows_[ISAROM_MAX] = { 0 }; + int isarom_selectedRows[ISAROM_MAX] = { 0 }; + + for (uint8_t i = 0; i < ISAROM_MAX; ++i) { + isarom_cbox[i] = findChild<QComboBox *>(QString("comboBoxIsaRomCard%1").arg(i + 1)); + isarom_models[i] = isarom_cbox[i]->model(); + isarom_removeRows_[i] = isarom_models[i]->rowCount(); + } + + c = 0; + while (true) { + const QString name = DeviceConfig::DeviceName(isarom_get_device(c), + isarom_get_internal_name(c), 0); + + if (name.isEmpty()) + break; + + if (device_is_valid(isarom_get_device(c), machineId)) { + for (uint8_t i = 0; i < ISAROM_MAX; ++i) { + int row = Models::AddEntry(isarom_models[i], name, c); + + if (c == isarom_type[i]) + isarom_selectedRows[i] = row - isarom_removeRows_[i]; + } + } + + c++; + } + + for (uint8_t i = 0; i < ISAROM_MAX; ++i) { + isarom_models[i]->removeRows(0, isarom_removeRows_[i]); + isarom_cbox[i]->setEnabled(isarom_models[i]->rowCount() > 1); + isarom_cbox[i]->setCurrentIndex(-1); + isarom_cbox[i]->setCurrentIndex(isarom_selectedRows[i]); + findChild<QPushButton *>(QString("pushButtonConfigureIsaRomCard%1").arg(i + 1))->setEnabled((isarom_type[i] != 0) && + isarom_has_config(isarom_type[i]) && machineHasIsa); + } } SettingsOtherPeripherals::~SettingsOtherPeripherals() @@ -149,6 +195,12 @@ SettingsOtherPeripherals::save() auto *cbox = findChild<QComboBox *>(QString("comboBoxIsaMemCard%1").arg(i + 1)); isamem_type[i] = cbox->currentData().toInt(); } + + /* ISA ROM boards. */ + for (int i = 0; i < ISAROM_MAX; i++) { + auto *cbox = findChild<QComboBox *>(QString("comboBoxIsaRomCard%1").arg(i + 1)); + isarom_type[i] = cbox->currentData().toInt(); + } } void @@ -226,6 +278,66 @@ SettingsOtherPeripherals::on_pushButtonConfigureIsaMemCard4_clicked() DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxIsaMemCard4->currentData().toInt()), 4); } +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard1_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard1->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard1_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard1->currentData().toInt()), 1); +} + +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard2_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard2->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard2_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard2->currentData().toInt()), 2); +} + +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard3_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard3->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard3_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard3->currentData().toInt()), 3); +} + +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard4_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard4->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard4_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard4->currentData().toInt()), 4); +} + void SettingsOtherPeripherals::on_checkBoxUnitTester_stateChanged(int arg1) { diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index e87219ab7..991759259 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -32,6 +32,15 @@ private slots: void on_comboBoxIsaMemCard4_currentIndexChanged(int index); void on_pushButtonConfigureIsaMemCard4_clicked(); + void on_comboBoxIsaRomCard1_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard1_clicked(); + void on_comboBoxIsaRomCard2_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard2_clicked(); + void on_comboBoxIsaRomCard3_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard3_clicked(); + void on_comboBoxIsaRomCard4_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard4_clicked(); + void on_checkBoxUnitTester_stateChanged(int arg1); void on_pushButtonConfigureUT_clicked(); diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index 81b0e0018..5c6b8fbf0 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -174,6 +174,123 @@ </layout> </widget> </item> + <item> + <widget class="QGroupBox" name="groupBoxRom"> + <property name="title"> + <string>ISA ROM Cards</string> + </property> + <layout class="QGridLayout" name="gridLayoutRom"> + <item row="0" column="0"> + <widget class="QLabel" name="labelIsaRomCard1"> + <property name="text"> + <string>Card 1:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxIsaRomCard1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="pushButtonConfigureIsaRomCard1"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelIsaRomCard2"> + <property name="text"> + <string>Card 2:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBoxIsaRomCard2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButtonConfigureIsaRomCard2"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelIsaRomCard3"> + <property name="text"> + <string>Card 3:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="comboBoxIsaRomCard3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="pushButtonConfigureIsaRomCard3"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelIsaRomCard4"> + <property name="text"> + <string>Card 4:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="comboBoxIsaRomCard4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxVisibleItems"> + <number>30</number> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QPushButton" name="pushButtonConfigureIsaRomCard4"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> <item> <layout class="QHBoxLayout" name="horizontalLayoutIBPC"> <item> From d95420a5e664c85721fc561b68e90daf8498d137 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 7 Jun 2025 20:39:55 -0400 Subject: [PATCH 1082/1190] Fix missing handller for CONFIG_INT in DeviceConfig::ConfigureDevice --- src/qt/qt_deviceconfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index cda52e722..54923be06 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -388,6 +388,7 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se } case CONFIG_MIDI_OUT: case CONFIG_MIDI_IN: + case CONFIG_INT: case CONFIG_SELECTION: { auto *cbox = dc.findChild<QComboBox *>(config->name); From b5708db5b02df7bf786a20b08ce4338f2c1a621a Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 7 Jun 2025 21:33:05 -0400 Subject: [PATCH 1083/1190] Fix bug in generic MM58167 --- src/device/isartc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/device/isartc.c b/src/device/isartc.c index b5bbda7b0..0540dc1f0 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -532,8 +532,8 @@ isartc_init(const device_t *info) switch (dev->board) { case ISARTC_MM58167: /* Generic MM58167 RTC */ { - int rom_addr = device_get_config_hex20("bios_addr"); - if (rom_addr != -1) + uint32_t rom_addr = device_get_config_hex20("bios_addr"); + if (rom_addr != 0) rom_init(&dev->rom, ISARTC_ROM_MM58167_1, rom_addr, 0x0800, 0x7ff, 0, MEM_MAPPING_EXTERNAL); @@ -830,7 +830,7 @@ static const device_config_t mm58167_config[] = { .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "Disabled", .value = -1 }, + { .description = "Disabled", .value = 0x00000 }, { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, { .description = "CC00H", .value = 0xcc000 }, From 1943d6eb522fe5eb1196365179b0d9671658ccce Mon Sep 17 00:00:00 2001 From: Alexander Babikov <lemondrops358@gmail.com> Date: Sun, 8 Jun 2025 12:11:10 +0500 Subject: [PATCH 1084/1190] FluidSynth: Add .sf3 as a recognized extension for SoundFonts --- src/sound/midi_fluidsynth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 027c85b79..48bf825f7 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -324,7 +324,7 @@ static const device_config_t fluidsynth_config[] = { .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, - .file_filter = "SF2 Sound Fonts (*.sf2)|*.sf2", + .file_filter = "SoundFont files (*.sf2 *.sf3)|*.sf2,*.sf3", .spinner = { 0 }, .selection = { { 0 } }, .bios = { { 0 } } From aa9976d5c6a5a994426a484b2f6da7296ed95783 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <lemondrops358@gmail.com> Date: Sat, 7 Jun 2025 20:30:51 +0500 Subject: [PATCH 1085/1190] Fix up file filters for filename fields of device configs for consistency - Filter descriptions are now translatable - Extensions get uppercase and lowercase variations on *nix - Add "All files" option --- src/qt/qt_deviceconfig.cpp | 22 +++++++++++++++++++--- src/qt/qt_util.cpp | 23 +++++++++++++++++++++++ src/qt/qt_util.hpp | 1 + 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index 54923be06..255b3c39f 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -31,6 +31,7 @@ #include <QLabel> #include <QDir> #include <QSettings> +#include <QStringBuilder> extern "C" { #include <86box/86box.h> @@ -45,6 +46,7 @@ extern "C" { #include "qt_filefield.hpp" #include "qt_models_common.hpp" +#include "qt_util.hpp" #ifdef Q_OS_LINUX # include <sys/stat.h> # include <sys/sysmacros.h> @@ -276,11 +278,25 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep) } case CONFIG_FNAME: { - auto *fileField = new FileField(); + auto *fileField = new FileField(this); fileField->setObjectName(config->name); fileField->setFileName(selected); - fileField->setFilter(QString(config->file_filter).left(static_cast<int>(strcspn(config->file_filter, - "|")))); + /* Get the actually used part of the filter */ + QString filter = QString(config->file_filter).left(static_cast<int>(strcspn(config->file_filter, "|"))); + /* Extract the description and the extension list */ + QRegularExpressionMatch match = QRegularExpression("(.+) \\((.+)\\)$").match(filter); + QString description = match.captured(1); + QString extensions = match.captured(2); + QStringList extensionList; + /* Split the extension list up and strip the filename globs */ + QRegularExpression re("\\*\\.(.*)"); + int i = 0; + while (extensions.section(' ', i, i) != "") { + QString extension = re.match(extensions.section(' ', i, i)).captured(1); + extensionList.append(extension); + i++; + } + fileField->setFilter(tr(description.toUtf8().constData()) % util::DlgFilter(extensionList) % tr("All files") % util::DlgFilter({ "*" }, true)); this->ui->formLayout->addRow(tr(config->description), fileField); break; } diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index 0c78c2f5e..5baaaaacf 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -92,6 +92,29 @@ DlgFilter(std::initializer_list<QString> extensions, bool last) return " (" % temp.join(' ') % ")" % (!last ? ";;" : ""); } +QString +DlgFilter(QStringList extensions, bool last) +{ + QStringList temp; + + for (auto ext : extensions) { +#ifdef Q_OS_UNIX + if (ext == "*") { + temp.append("*"); + continue; + } + temp.append("*." % ext.toUpper()); +#endif + temp.append("*." % ext); + } + +#ifdef Q_OS_UNIX + temp.removeDuplicates(); +#endif + return " (" % temp.join(' ') % ")" % (!last ? ";;" : ""); +} + + QString currentUuid() { auto configPath = QFileInfo(cfg_path).dir().canonicalPath(); diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 9432610b6..e0d2648d0 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -11,6 +11,7 @@ namespace util { static constexpr auto UUID_MIN_LENGTH = 36; /* Creates extension list for qt filedialog */ QString DlgFilter(std::initializer_list<QString> extensions, bool last = false); +QString DlgFilter(QStringList extensions, bool last = false); /* Returns screen the widget is on */ QScreen *screenOfWidget(QWidget *widget); #ifdef Q_OS_WINDOWS From c5203c92ca2731b7d94f229d552c0e2b6ba05994 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <lemondrops358@gmail.com> Date: Sun, 8 Jun 2025 13:54:47 +0500 Subject: [PATCH 1086/1190] FluidSynth: Add dynamic sample loading --- src/sound/midi_fluidsynth.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 48bf825f7..1afefd905 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -161,6 +161,7 @@ fluidsynth_init(UNUSED(const device_t *info)) fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain") / 100.0f); + fluid_settings_setint(data->settings, "synth.dynamic-sample-loading", device_get_config_int("dynamic_sample_loading")); data->synth = new_fluid_synth(data->settings); @@ -509,6 +510,17 @@ static const device_config_t fluidsynth_config[] = { }, .bios = { { 0 } } }, + { + .name = "dynamic_sample_loading", + .description = "Dynamic Sample Loading", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; From 5779340e6d0743f50dd5da7cc9277c7814d4421d Mon Sep 17 00:00:00 2001 From: Alexander Babikov <lemondrops358@gmail.com> Date: Sun, 8 Jun 2025 15:37:38 +0500 Subject: [PATCH 1087/1190] ESC/P: Fix a handle leak on reset --- src/printer/prt_escp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index d0836e5f2..f238341c5 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -2053,6 +2053,7 @@ escp_close(void *priv) free(dev->page); } + FT_Done_Face(dev->fontface); free(dev); } From 490e1c5b3e0dd280d3d660026b8c31c1a2744c30 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <lemondrops358@gmail.com> Date: Sun, 8 Jun 2025 16:33:52 +0500 Subject: [PATCH 1088/1190] Update the Russian translation --- src/qt/languages/ru-RU.po | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index af427d670..19975c2c9 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2194,4 +2194,13 @@ msgid "Toggle pause" msgstr "Переключить паузу" msgid "Toggle mute" -msgstr "Переключить беззвучный режим" \ No newline at end of file +msgstr "Переключить беззвучный режим" + +msgid "Text files" +msgstr "Текстовые файлы" + +msgid "ROM files" +msgstr "Файлы ПЗУ" + +msgid "SoundFont files" +msgstr "Файлы SoundFont" From ee91e89aa3c2141e0be3d2597ac88e78ebe10a1b Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sun, 8 Jun 2025 19:14:48 +0200 Subject: [PATCH 1089/1190] EuroPC: Fix the JIM base address. --- src/machine/m_europc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index b98a1f51e..7fc990a45 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -646,6 +646,7 @@ europc_boot(UNUSED(const device_t *info)) * (JS9) can be used to "move" it to 0x0350, to get it out of * the way of other cards that need this range. */ + sys->jim = device_get_config_hex16("js9"); io_sethandler(sys->jim, 16, jim_read, NULL, NULL, jim_write, NULL, NULL, sys); @@ -680,14 +681,14 @@ static const device_config_t europc_config[] = { { .name = "js9", .description = "JS9 Jumper (JIM)", - .type = CONFIG_INT, + .type = CONFIG_HEX16, .default_string = "", - .default_int = 0, + .default_int = 0x0250, .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "Disabled (250h)", .value = 0 }, - { .description = "Enabled (350h)", .value = 1 }, + { .description = "Disabled (250h)", .value = 0x0250 }, + { .description = "Enabled (350h)", .value = 0x0350 }, { .description = "" } }, }, From 494b7536bacea78222b15cbd09f521513ae3fbeb Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sun, 8 Jun 2025 19:53:57 +0200 Subject: [PATCH 1090/1190] AT KBC: Add the Tulip (undocumented VL82C113?) commands and get rid of write_cmd_generic(). --- src/device/kbc_at.c | 946 ++++++++++++++++++++++++-------------------- 1 file changed, 516 insertions(+), 430 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index dd2d5a636..1338b9555 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -952,261 +952,6 @@ pulse_poll(void *priv) write_p2(dev, dev->p2 | dev->old_p2); } -static uint8_t -write_cmd_generic(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *) priv; - uint8_t current_drive; - uint8_t fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - switch (val) { - case 0xa4: /* check if password installed */ - if (dev->misc_flags & FLAG_PS2) { - kbc_at_log("ATkbc: check if password installed\n"); - kbc_delay_to_ob(dev, 0xf1, 0, 0x00); - return 0; - } - break; - - case 0xa5: /* load security */ - kbc_at_log("ATkbc: load security\n"); - dev->wantdata = 1; - dev->state = STATE_KBC_PARAM; - return 0; - - case 0xa7: /* disable auxiliary port */ - if (dev->misc_flags & FLAG_PS2) { - kbc_at_log("ATkbc: disable auxiliary port\n"); - set_enable_aux(dev, 0); - return 0; - } - break; - - case 0xa8: /* Enable auxiliary port */ - if (dev->misc_flags & FLAG_PS2) { - kbc_at_log("ATkbc: enable auxiliary port\n"); - set_enable_aux(dev, 1); - return 0; - } - break; - - case 0xa9: /* Test auxiliary port */ - kbc_at_log("ATkbc: test auxiliary port\n"); - if (dev->misc_flags & FLAG_PS2) { - kbc_delay_to_ob(dev, 0x00, 0, 0x00); /* no error, this is testing the channel 2 interface */ - return 0; - } - break; - - /* TODO: Make this command do nothing on the Regional HT6542, - or else, Efflixi's Award OPTi 495 BIOS gets a stuck key - in Norton Commander 3.0. */ - case 0xaf: /* read keyboard version */ - kbc_at_log("ATkbc: read keyboard version\n"); - kbc_delay_to_ob(dev, kbc_award_revision, 0, 0x00); - return 0; - - /* - P1 bits: 76543210 - ----------------- - IBM PS/1: xxxxxxxx - IBM PS/2 MCA: xxxxx1xx - Intel AMI Pentium BIOS'es with AMI MegaKey KB-5 keyboard controller: x1x1xxxx - Acer: xxxxx0xx - Packard Bell PB450: xxxxx1xx - P6RP4: xx1xx1xx - Epson Action Tower 2600: xxxx01xx - TriGem Hawk: xxxx11xx - - Machine input based on current code: 11111111 - Everything non-Green: Pull down bit 7 if not PS/2 and keyboard is inhibited. - Pull down bit 6 if primary display is CGA. - Xi8088: Pull down bit 6 if primary display is MDA. - Acer: Pull down bit 6 if primary display is MDA. - Pull down bit 2 always (must be so to enable CMOS Setup). - IBM PS/1: Pull down bit 6 if current floppy drive is 3.5". - Epson Action Tower 2600: Pull down bit 3 always (for Epson logo). - NCR: Pull down bit 5 always (power-on default speed = high). - Pull down bit 3 if there is no FPU. - Pull down bits 1 and 0 always? - Compaq: Pull down bit 6 if Compaq dual-scan display is in use. - Pull down bit 5 if system board DIP switch is ON. - Pull down bit 4 if CPU speed selected is auto. - Pull down bit 3 if CPU speed selected is slow (4 MHz). - Pull down bit 2 if FPU is present. - Pull down bits 1 and 0 always? - - Bit 7: AT KBC only - keyboard inhibited (often physical lock): 0 = yes, 1 = no (also Compaq); - Bit 6: Mostly, display: 0 = CGA, 1 = MDA, inverted on Xi8088 and Acer KBC's; - Intel AMI MegaKey KB-5: Used for green features, SMM handler expects it to be set; - IBM PS/1 Model 2011: 0 = current FDD is 3.5", 1 = current FDD is 5.25"; - Compaq: 0 = Compaq dual-scan display, 1 = non-Compaq display. - Bit 5: Mostly, manufacturing jumper: 0 = installed (infinite loop at POST), 1 = not installed; - NCR: power-on default speed: 0 = high, 1 = low; - Compaq: System board DIP switch 5: 0 = ON, 1 = OFF. - Bit 4: (Which board?): RAM on motherboard: 0 = 512 kB, 1 = 256 kB; - NCR: RAM on motherboard: 0 = unsupported, 1 = 512 kB; - Intel AMI MegaKey KB-5: Must be 1; - IBM PS/1: Ignored; - Compaq: 0 = Auto speed selected, 1 = High speed selected. - Bit 3: TriGem AMIKey: most significant bit of 2-bit OEM ID; - NCR: Coprocessor detect (1 = yes, 0 = no); - Compaq: 0 = Slow (4 MHz), 1 = Fast (8 MHz); - Sometimes configured for clock switching; - Bit 2: TriGem AMIKey: least significant bit of 2-bit OEM ID; - Bit 3, 2: - 1, 1: TriGem logo; - 1, 0: Garbled logo; - 0, 1: Epson logo; - 0, 0: Generic AMI logo. - NCR: Unused; - IBM PS/2: Keyboard power: 0 = no power (fuse error), 1 = OK - (for some reason, www.win.tue.nl has this in reverse); - Compaq: FPU: 0 = 80287, 1 = none; - Sometimes configured for clock switching; - Bit 1: PS/2: Auxiliary device data in; - Compaq: Reserved; - NCR: High/auto speed. - Bit 0: PS/2: Keyboard device data in; - Compaq: Reserved; - NCR: DMA mode. - */ - case 0xc0: /* read P1 */ - kbc_at_log("ATkbc: read P1\n"); - fixed_bits = 4; - /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ - if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN)) - fixed_bits |= 0x40; - if (!strcmp(machine_get_internal_name(), "dells333sl")) { - /* - Dell System 333s/L: - - Bit 5: Stuck in reboot loop if clear. - */ - uint8_t p1 = 0x20 | (video_is_mda() ? 0x40 : 0x00); - kbc_delay_to_ob(dev, p1, 0, 0x00); - } else if (kbc_ven == KBC_VEN_IBM_PS1) { - current_drive = fdc_get_current_drive(); - /* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */ - kbc_delay_to_ob(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), - 0, 0x00); - } else if (kbc_ven == KBC_VEN_NCR) { - /* switch settings - * bit 7: keyboard disable - * bit 6: display type (0 color, 1 mono) - * bit 5: power-on default speed (0 high, 1 low) - * bit 4: sense RAM size (0 unsupported, 1 512k on system board) - * bit 3: coprocessor detect - * bit 2: unused - * bit 1: high/auto speed - * bit 0: dma mode - */ - /* (B0 or F0) | 0x04 | (display on bit 6) | (fpu on bit 3) */ - kbc_delay_to_ob(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, - 0, 0x00); - } else if (kbc_ven == KBC_VEN_TRIGEM_AMI) { - /* Bit 3, 2: - 1, 1: TriGem logo; - 1, 0: Garbled logo; - 0, 1: Epson logo; - 0, 0: Generic AMI logo. */ - if (dev->misc_flags & FLAG_PCI) - fixed_bits |= 8; - /* (B0 or F0) | (0x04 or 0x0c) */ - kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00); - } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) { - if (!strcmp(machine_get_internal_name(), "dell466np")) { - /* - Dell 466/NP: - - Bit 2: Keyboard fuse (must be set); - - Bit 4: Password disable jumper (must be clear); - - Bit 5: Manufacturing jumper (must be set). - */ - uint8_t p1 = 0x24; - kbc_delay_to_ob(dev, p1, 0, 0x00); - } else if (!strcmp(machine_get_internal_name(), "optiplex_gxl")) { - /* - Dell OptiPlex GXL/GXM: - - Bit 3: Password disable jumper (must be clear); - - Bit 4: Keyboard fuse (must be set); - - Bit 5: Manufacturing jumper (must be set). - */ - uint8_t p1 = 0x30; - kbc_delay_to_ob(dev, p1, 0, 0x00); - } else if (!strcmp(machine_get_internal_name(), "dellplato") || - !strcmp(machine_get_internal_name(), "dellhannibalp") || - !strcmp(machine_get_internal_name(), "dellxp60")) { - /* - Dell Dimension XPS Pxxx & Pxxxa/Mxxxa: - - Bit 3: Password disable jumper (must be clear); - - Bit 4: Clear CMOS jumper (must be set); - */ - uint8_t p1 = 0x10; - kbc_delay_to_ob(dev, p1, 0, 0x00); - } else { - /* (B0 or F0) | (0x08 or 0x0c) */ - uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) | - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c); - if (!strcmp(machine_get_internal_name(), "alfredo")) - p1_out &= 0xef; - - kbc_delay_to_ob(dev, p1_out, 0, 0x00); - } - } else if (kbc_ven == KBC_VEN_COMPAQ) - kbc_delay_to_ob(dev, dev->p1 | (hasfpu ? 0x00 : 0x04), 0, 0x00); - else - /* (B0 or F0) | (0x04 or 0x44) */ - kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); - return 0; - - case 0xc1: /*Copy bits 0 to 3 of P1 to status bits 4 to 7*/ - if (dev->misc_flags & FLAG_PS2) { - kbc_at_log("ATkbc: copy bits 0 to 3 of P1 to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= (dev->p1 << 4); - return 0; - } - break; - - case 0xc2: /*Copy bits 4 to 7 of P1 to status bits 4 to 7*/ - if (dev->misc_flags & FLAG_PS2) { - kbc_at_log("ATkbc: copy bits 4 to 7 of P1 to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= (dev->p1 & 0xf0); - return 0; - } - break; - - case 0xd3: /* write auxiliary output buffer */ - if (dev->misc_flags & FLAG_PS2) { - kbc_at_log("ATkbc: write auxiliary output buffer\n"); - dev->wantdata = 1; - dev->state = STATE_KBC_PARAM; - return 0; - } - break; - - case 0xd4: /* write to auxiliary port */ - kbc_at_log("ATkbc: write to auxiliary port\n"); - dev->wantdata = 1; - dev->state = STATE_KBC_PARAM; - return 0; - - case 0xf0 ... 0xff: - kbc_at_log("ATkbc: pulse %01X\n", val & 0x0f); - pulse_output(dev, val & 0x0f); - return 0; - - default: - break; - } - - kbc_at_log("ATkbc: bad command %02X\n", val); - return 1; -} - static uint8_t write_cmd_data_ami(void *priv, uint8_t val) { @@ -1282,35 +1027,43 @@ write_cmd_ami(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t ret = 1; switch (val) { + default: + break; + case 0x00 ... 0x1f: kbc_at_log("ATkbc: AMI - alias read from %08X\n", val); kbc_delay_to_ob(dev, dev->mem[val + 0x20], 0, 0x00); - return 0; + ret = 0; + break; case 0x40 ... 0x5f: kbc_at_log("ATkbc: AMI - alias write to %08X\n", dev->command); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xa0: /* copyright message */ kbc_at_queue_add(dev, 0x28); kbc_at_queue_add(dev, 0x00); - return 0; + ret = 0; + break; case 0xa1: /* get controller version */ kbc_at_log("ATkbc: AMI - get controller version\n"); kbc_delay_to_ob(dev, kbc_ami_revision, 0, 0x00); - return 0; + ret = 0; + break; case 0xa2: /* clear keyboard controller lines P22/P23 */ if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); write_p2(dev, dev->p2 & 0xf3); kbc_delay_to_ob(dev, 0x00, 0, 0x00); - return 0; + ret = 0; } break; @@ -1319,7 +1072,7 @@ write_cmd_ami(void *priv, uint8_t val) kbc_at_log("ATkbc: AMI - set KBC lines P22 and P23\n"); write_p2(dev, dev->p2 | 0x0c); kbc_delay_to_ob(dev, 0x00, 0, 0x00); - return 0; + ret = 0; } break; @@ -1327,7 +1080,7 @@ write_cmd_ami(void *priv, uint8_t val) if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - write clock = low\n"); dev->misc_flags &= ~FLAG_CLOCK; - return 0; + ret = 0; } break; @@ -1335,14 +1088,15 @@ write_cmd_ami(void *priv, uint8_t val) if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - write clock = high\n"); dev->misc_flags |= FLAG_CLOCK; - return 0; + ret = 0; } + break; case 0xa6: /* read clock */ if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - read clock\n"); kbc_delay_to_ob(dev, (dev->misc_flags & FLAG_CLOCK) ? 0xff : 0x00, 0, 0x00); - return 0; + ret = 0; } break; @@ -1350,7 +1104,7 @@ write_cmd_ami(void *priv, uint8_t val) if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - write cache bad\n"); dev->misc_flags &= FLAG_CACHE; - return 0; + ret = 0; } break; @@ -1358,7 +1112,7 @@ write_cmd_ami(void *priv, uint8_t val) if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - write cache good\n"); dev->misc_flags |= FLAG_CACHE; - return 0; + ret = 0; } break; @@ -1366,7 +1120,7 @@ write_cmd_ami(void *priv, uint8_t val) if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: AMI - read cache\n"); kbc_delay_to_ob(dev, (dev->misc_flags & FLAG_CACHE) ? 0xff : 0x00, 0, 0x00); - return 0; + ret = 0; } break; @@ -1376,7 +1130,7 @@ write_cmd_ami(void *priv, uint8_t val) dev->wantdata = 1; dev->state = STATE_KBC_PARAM; dev->command_phase = 1; - return 0; + ret = 0; } break; @@ -1387,7 +1141,8 @@ write_cmd_ami(void *priv, uint8_t val) dev->p1 &= ~(1 << (val & 0x03)); kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; /* TODO: The ICS SB486PV sends command B4 but expects to read *TWO* bytes. */ case 0xb4: case 0xb5: @@ -1400,7 +1155,8 @@ write_cmd_ami(void *priv, uint8_t val) else kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; case 0xb8 ... 0xbb: /* set KBC lines P10-P13 (P1 bits 0-3) high */ @@ -1410,7 +1166,8 @@ write_cmd_ami(void *priv, uint8_t val) kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; } - return 0; + ret = 0; + break; case 0xbc: case 0xbd: /* set KBC lines P22-P23 (P2 bits 2-3) high */ @@ -1419,13 +1176,15 @@ write_cmd_ami(void *priv, uint8_t val) write_p2(dev, dev->p2 | (4 << (val & 0x01))); kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; case 0xc1: /* write P1 */ kbc_at_log("ATkbc: AMI MegaKey - write P1\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xc4: /* set KBC line P14 low */ @@ -1433,14 +1192,16 @@ write_cmd_ami(void *priv, uint8_t val) dev->p1 &= 0xef; kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; case 0xc5: /* set KBC line P15 low */ kbc_at_log("ATkbc: set KBC line P15 (P1 bit 5) low\n"); dev->p1 &= 0xdf; kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; case 0xc8: /* @@ -1449,7 +1210,8 @@ write_cmd_ami(void *priv, uint8_t val) */ kbc_at_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); dev->ami_flags &= 0xfb; - return 0; + ret = 0; + break; case 0xc9: /* @@ -1458,7 +1220,15 @@ write_cmd_ami(void *priv, uint8_t val) */ kbc_at_log("ATkbc: AMI - block KBC lines P22 and P23\n"); dev->ami_flags |= 0x04; - return 0; + ret = 0; + break; + + case 0xcb: /* set keyboard mode */ + kbc_at_log("ATkbc: AMI - set keyboard mode\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + ret = 0; + break; case 0xcc: /* set KBC line P14 high */ @@ -1466,32 +1236,36 @@ write_cmd_ami(void *priv, uint8_t val) dev->p1 |= 0x10; kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; case 0xcd: /* set KBC line P15 high */ kbc_at_log("ATkbc: set KBC line P15 (P1 bit 5) high\n"); dev->p1 |= 0x20; kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; - return 0; + ret = 0; + break; case 0xef: /* ??? - sent by AMI486 */ kbc_at_log("ATkbc: ??? - sent by AMI486\n"); - return 0; - - default: + ret = 0; break; } - return write_cmd_generic(dev, val); + return ret; } static uint8_t write_cmd_data_phoenix(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (dev->command) { + default: + break; + /* TODO: Make this actually load the password. */ case 0xa3: /* Load Extended Password */ kbc_at_log("ATkbc: Phoenix - Load Extended Password\n"); @@ -1501,120 +1275,139 @@ write_cmd_data_phoenix(void *priv, uint8_t val) dev->wantdata = 1; dev->state = STATE_KBC_PARAM; } - return 0; + ret = 0; + break; case 0xaf: /* Set Inactivity Timer */ kbc_at_log("ATkbc: Phoenix - Set Inactivity Timer\n"); dev->mem[0x3a] = val; dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xb8: /* Set Extended Memory Access Index */ kbc_at_log("ATkbc: Phoenix - Set Extended Memory Access Index\n"); dev->mem_addr = val; dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xbb: /* Set Extended Memory */ kbc_at_log("ATkbc: Phoenix - Set Extended Memory\n"); dev->mem[dev->mem_addr] = val; dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xbd: /* Set MultiKey Variable */ kbc_at_log("ATkbc: Phoenix - Set MultiKey Variable\n"); if ((dev->mem_addr > 0) && (dev->mem_addr <= multikey_vars[0x00])) dev->mem[multikey_vars[dev->mem_addr]] = val; dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xc7: /* Set Port1 bits */ kbc_at_log("ATkbc: Phoenix - Set Port1 bits\n"); dev->p1 |= val; dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xc8: /* Clear Port1 bits */ kbc_at_log("ATkbc: Phoenix - Clear Port1 bits\n"); dev->p1 &= ~val; dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xc9: /* Set Port2 bits */ kbc_at_log("ATkbc: Phoenix - Set Port2 bits\n"); write_p2(dev, dev->p2 | val); dev->command_phase = 0; - return 0; + ret = 0; + break; case 0xca: /* Clear Port2 bits */ kbc_at_log("ATkbc: Phoenix - Clear Port2 bits\n"); write_p2(dev, dev->p2 & ~val); dev->command_phase = 0; - return 0; - - default: + ret = 0; break; } - return 1; + return ret; } static uint8_t write_cmd_phoenix(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (val) { + default: + break; + case 0x00 ... 0x1f: kbc_at_log("ATkbc: Phoenix - alias read from %08X\n", val); kbc_delay_to_ob(dev, dev->mem[val + 0x20], 0, 0x00); - return 0; + ret = 0; + break; case 0x40 ... 0x5f: kbc_at_log("ATkbc: Phoenix - alias write to %08X\n", dev->command); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xa2: /* Test Extended Password */ kbc_at_log("ATkbc: Phoenix - Test Extended Password\n"); kbc_at_queue_add(dev, 0xf1); /* Extended Password not loaded */ - return 0; + ret = 0; + break; /* TODO: Make this actually load the password. */ case 0xa3: /* Load Extended Password */ kbc_at_log("ATkbc: Phoenix - Load Extended Password\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xaf: /* Set Inactivity Timer */ kbc_at_log("ATkbc: Phoenix - Set Inactivity Timer\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xb8: /* Set Extended Memory Access Index */ kbc_at_log("ATkbc: Phoenix - Set Extended Memory Access Index\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xb9: /* Get Extended Memory Access Index */ kbc_at_log("ATkbc: Phoenix - Get Extended Memory Access Index\n"); kbc_at_queue_add(dev, dev->mem_addr); - return 0; + ret = 0; + break; case 0xba: /* Get Extended Memory */ kbc_at_log("ATkbc: Phoenix - Get Extended Memory\n"); kbc_at_queue_add(dev, dev->mem[dev->mem_addr]); - return 0; + ret = 0; + break; case 0xbb: /* Set Extended Memory */ kbc_at_log("ATkbc: Phoenix - Set Extended Memory\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xbc: /* Get MultiKey Variable */ kbc_at_log("ATkbc: Phoenix - Get MultiKey Variable\n"); @@ -1624,37 +1417,43 @@ write_cmd_phoenix(void *priv, uint8_t val) kbc_at_queue_add(dev, dev->mem[multikey_vars[dev->mem_addr]]); else kbc_at_queue_add(dev, 0xff); - return 0; + ret = 0; + break; case 0xbd: /* Set MultiKey Variable */ kbc_at_log("ATkbc: Phoenix - Set MultiKey Variable\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xc7: /* Set Port1 bits */ kbc_at_log("ATkbc: Phoenix - Set Port1 bits\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xc8: /* Clear Port1 bits */ kbc_at_log("ATkbc: Phoenix - Clear Port1 bits\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xc9: /* Set Port2 bits */ kbc_at_log("ATkbc: Phoenix - Set Port2 bits\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; case 0xca: /* Clear Port2 bits */ kbc_at_log("ATkbc: Phoenix - Clear Port2 bits\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; /* TODO: Handle these three commands properly - configurable revision level and proper CPU bits. */ @@ -1672,7 +1471,8 @@ write_cmd_phoenix(void *priv, uint8_t val) kbc_at_queue_add(dev, 0x01); kbc_at_queue_add(dev, 0x29); } - return 0; + ret = 0; + break; case 0xd6: /* Read Version Information */ kbc_at_log("ATkbc: Phoenix - Read Version Information\n"); @@ -1681,7 +1481,8 @@ write_cmd_phoenix(void *priv, uint8_t val) kbc_at_queue_add(dev, 0xac); else kbc_at_queue_add(dev, 0xaa); - return 0; + ret = 0; + break; case 0xd7: /* Read MultiKey model numbers */ kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n"); @@ -1700,71 +1501,63 @@ write_cmd_phoenix(void *priv, uint8_t val) kbc_at_queue_add(dev, 0x88); kbc_at_queue_add(dev, 0xd0); } - return 0; - - default: + ret = 0; break; } - return write_cmd_generic(dev, val); + return ret; } static uint8_t write_cmd_siemens(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (val) { + default: + ret = write_cmd_ami(dev, val); + break; + case 0x92: /*Siemens Award - 92 sent by PCD-2L BIOS*/ kbc_at_log("Siemens Award - 92 sent by PCD-2L BIOS\n"); - return 0; + ret = 0; + break; case 0x94: /*Siemens Award - 94 sent by PCD-2L BIOS*/ kbc_at_log("Siemens Award - 94 sent by PCD-2L BIOS\n"); - return 0; + ret = 0; + break; case 0x9a: /*Siemens Award - 9A sent by PCD-2L BIOS*/ kbc_at_log("Siemens Award - 9A sent by PCD-2L BIOS\n"); - return 0; + ret = 0; + break; case 0x9c: /*Siemens Award - 9C sent by PCD-2L BIOS*/ kbc_at_log("Siemens Award - 9C sent by PCD-2L BIOS\n"); - return 0; + ret = 0; + break; case 0xa9: /*Siemens Award - A9 sent by PCD-2L BIOS*/ kbc_at_log("Siemens Award - A9 sent by PCD-2L BIOS\n"); - return 0; - - default: + ret = 0; break; } - return write_cmd_ami(dev, val); -} - -static uint8_t -write_cmd_data_quadtel(void *priv, UNUSED(uint8_t val)) -{ - const atkbc_t *dev = (atkbc_t *) priv; - - switch (dev->command) { - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbc_at_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - return 0; - - default: - break; - } - - return 1; + return ret; } static uint8_t write_cmd_olivetti(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (val) { + default: + break; + case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -1775,101 +1568,133 @@ write_cmd_olivetti(void *priv, uint8_t val) */ kbc_delay_to_ob(dev, (0x0c | (is386 ? 0x00 : 0x80)) & 0xdf, 0, 0x00); dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); - return 0; - - default: + ret = 0; break; } - return write_cmd_generic(dev, val); + return ret; +} + +static uint8_t +write_cmd_data_quadtel(void *priv, UNUSED(uint8_t val)) +{ + const atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; + + switch (dev->command) { + default: + break; + + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbc_at_log("ATkbc: ??? - sent by MegaPC BIOS\n"); + ret = 0; + break; + } + + return ret; } static uint8_t write_cmd_quadtel(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (val) { + default: + break; + case 0xaf: kbc_at_log("ATkbc: bad KBC command AF\n"); - return 1; + break; case 0xcf: /*??? - sent by MegaPC BIOS*/ kbc_at_log("ATkbc: ??? - sent by MegaPC BIOS\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; - - default: + ret = 0; break; } - return write_cmd_generic(dev, val); + return ret; } static uint8_t write_cmd_data_toshiba(void *priv, uint8_t val) { const atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (dev->command) { + default: + break; + case 0xb6: /* T3100e - set color/mono switch */ kbc_at_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); - return 0; - - default: + ret = 0; break; } - return 1; + return ret; } static uint8_t write_cmd_toshiba(void *priv, uint8_t val) { atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 1; switch (val) { + default: + break; + case 0xaf: kbc_at_log("ATkbc: bad KBC command AF\n"); - return 1; + break; case 0xb0: /* T3100e: Turbo on */ kbc_at_log("ATkbc: T3100e: Turbo on\n"); t3100e_turbo_set(1); - return 0; + ret = 0; + break; case 0xb1: /* T3100e: Turbo off */ kbc_at_log("ATkbc: T3100e: Turbo off\n"); t3100e_turbo_set(0); - return 0; + ret = 0; + break; case 0xb2: /* T3100e: Select external display */ kbc_at_log("ATkbc: T3100e: Select external display\n"); t3100e_display_set(0x00); - return 0; + ret = 0; + break; case 0xb3: /* T3100e: Select internal display */ kbc_at_log("ATkbc: T3100e: Select internal display\n"); t3100e_display_set(0x01); - return 0; + ret = 0; + break; case 0xb4: /* T3100e: Get configuration / status */ kbc_at_log("ATkbc: T3100e: Get configuration / status\n"); kbc_delay_to_ob(dev, t3100e_config_get(), 0, 0x00); - return 0; + ret = 0; + break; case 0xb5: /* T3100e: Get colour / mono byte */ kbc_at_log("ATkbc: T3100e: Get colour / mono byte\n"); kbc_delay_to_ob(dev, t3100e_mono_get(), 0, 0x00); - return 0; + ret = 0; + break; case 0xb6: /* T3100e: Set colour / mono byte */ kbc_at_log("ATkbc: T3100e: Set colour / mono byte\n"); dev->wantdata = 1; dev->state = STATE_KBC_PARAM; - return 0; + ret = 0; + break; /* TODO: Toshiba KBC mode switching. */ case 0xb7: /* T3100e: Emulate PS/2 keyboard */ @@ -1883,7 +1708,8 @@ write_cmd_toshiba(void *priv, uint8_t val) kbc_at_log("ATkbc: T3100e: Emulate AT keyboard\n"); kbc_at_do_poll = kbc_at_poll_at; } - return 0; + ret = 0; + break; case 0xbb: /* T3100e: Read 'Fn' key. Return it for right Ctrl and right Alt; on the real @@ -1895,12 +1721,14 @@ write_cmd_toshiba(void *priv, uint8_t val) kbc_delay_to_ob(dev, 0x04, 0, 0x00); else kbc_delay_to_ob(dev, 0x00, 0, 0x00); - return 0; + ret = 0; + break; case 0xbc: /* T3100e: Reset Fn+Key notification */ kbc_at_log("ATkbc: T3100e: Reset Fn+Key notification\n"); t3100e_notify_set(0x00); - return 0; + ret = 0; + break; case 0xc0: /* Read P1 */ kbc_at_log("ATkbc: read P1\n"); @@ -1909,13 +1737,176 @@ write_cmd_toshiba(void *priv, uint8_t val) * is set by t3100e_mono_set() */ dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; kbc_delay_to_ob(dev, dev->p1, 0, 0x00); - return 0; - - default: + ret = 0; break; } - return write_cmd_generic(dev, val); + return ret; +} + +static uint8_t +read_p1(atkbc_t *dev) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t ret = 0xff; + uint8_t current_drive; + uint8_t fixed_bits; + + /* + P1 bits: 76543210 + ----------------- + IBM PS/1: xxxxxxxx + IBM PS/2 MCA: xxxxx1xx + Intel AMI Pentium BIOS'es with AMI MegaKey KB-5 keyboard controller: x1x1xxxx + Acer: xxxxx0xx + Packard Bell PB450: xxxxx1xx + P6RP4: xx1xx1xx + Epson Action Tower 2600: xxxx01xx + TriGem Hawk: xxxx11xx + + Machine input based on current code: 11111111 + Everything non-Green: Pull down bit 7 if not PS/2 and keyboard is inhibited. + Pull down bit 6 if primary display is CGA. + Xi8088: Pull down bit 6 if primary display is MDA. + Acer: Pull down bit 6 if primary display is MDA. + Pull down bit 2 always (must be so to enable CMOS Setup). + IBM PS/1: Pull down bit 6 if current floppy drive is 3.5". + Epson Action Tower 2600: Pull down bit 3 always (for Epson logo). + NCR: Pull down bit 5 always (power-on default speed = high). + Pull down bit 3 if there is no FPU. + Pull down bits 1 and 0 always? + Compaq: Pull down bit 6 if Compaq dual-scan display is in use. + Pull down bit 5 if system board DIP switch is ON. + Pull down bit 4 if CPU speed selected is auto. + Pull down bit 3 if CPU speed selected is slow (4 MHz). + Pull down bit 2 if FPU is present. + Pull down bits 1 and 0 always? + + Bit 7: AT KBC only - keyboard inhibited (often physical lock): 0 = yes, 1 = no (also Compaq); + Bit 6: Mostly, display: 0 = CGA, 1 = MDA, inverted on Xi8088 and Acer KBC's; + Intel AMI MegaKey KB-5: Used for green features, SMM handler expects it to be set; + IBM PS/1 Model 2011: 0 = current FDD is 3.5", 1 = current FDD is 5.25"; + Compaq: 0 = Compaq dual-scan display, 1 = non-Compaq display. + Bit 5: Mostly, manufacturing jumper: 0 = installed (infinite loop at POST), 1 = not installed; + NCR: power-on default speed: 0 = high, 1 = low; + Compaq: System board DIP switch 5: 0 = ON, 1 = OFF. + Bit 4: (Which board?): RAM on motherboard: 0 = 512 kB, 1 = 256 kB; + NCR: RAM on motherboard: 0 = unsupported, 1 = 512 kB; + Intel AMI MegaKey KB-5: Must be 1; + IBM PS/1: Ignored; + Compaq: 0 = Auto speed selected, 1 = High speed selected. + Bit 3: TriGem AMIKey: most significant bit of 2-bit OEM ID; + NCR: Coprocessor detect (1 = yes, 0 = no); + Compaq: 0 = Slow (4 MHz), 1 = Fast (8 MHz); + Sometimes configured for clock switching; + Bit 2: TriGem AMIKey: least significant bit of 2-bit OEM ID; + Bit 3, 2: + 1, 1: TriGem logo; + 1, 0: Garbled logo; + 0, 1: Epson logo; + 0, 0: Generic AMI logo. + NCR: Unused; + IBM PS/2: Keyboard power: 0 = no power (fuse error), 1 = OK + (for some reason, www.win.tue.nl has this in reverse); + Compaq: FPU: 0 = 80287, 1 = none; + Sometimes configured for clock switching; + Bit 1: PS/2: Auxiliary device data in; + Compaq: Reserved; + NCR: High/auto speed. + Bit 0: PS/2: Keyboard device data in; + Compaq: Reserved; + NCR: DMA mode. + */ + kbc_at_log("ATkbc: read P1\n"); + + fixed_bits = 4; + + /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ + if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN)) + fixed_bits |= 0x40; + + if (!strcmp(machine_get_internal_name(), "dells333sl")) + /* + Dell System 333s/L: + - Bit 5: Stuck in reboot loop if clear. + */ + ret = 0x20 | (video_is_mda() ? 0x40 : 0x00); + else if (kbc_ven == KBC_VEN_IBM_PS1) { + current_drive = fdc_get_current_drive(); + /* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */ + ret = dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00); + } else if (kbc_ven == KBC_VEN_NCR) { + /* Switch settings: + - Bit 7: Keyboard disable; + - Bit 6: Display type (0 color, 1 mono); + - Bit 5: Power-on default speed (0 high, 1 low); + - Bit 4: Sense RAM size (0 unsupported, 1 512k on system board); + - Bit 3: Coprocessor detect; + - Bit 2: Unused; + - Bit 1: High/Auto speed; + - Bit 0: DMA mode. + + (B0 or F0) | 0x04 | (display on bit 6) | (fpu on bit 3) + */ + ret = (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | + (hasfpu ? 0x08 : 0x00)) & 0xdf; + } else if (kbc_ven == KBC_VEN_TRIGEM_AMI) { + /* Switch settings: + - Bit 3, 2: + - 1, 1: TriGem logo; + - 1, 0: Garbled logo; + - 0, 1: Epson logo; + - 0, 0: Generic AMI logo. + */ + if (dev->misc_flags & FLAG_PCI) + fixed_bits |= 8; + + /* (B0 or F0) | (0x04 or 0x0c) */ + ret = dev->p1 | fixed_bits; + } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && + ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) { + if (!strcmp(machine_get_internal_name(), "dell466np")) + /* + Dell 466/NP: + - Bit 2: Keyboard fuse (must be set); + - Bit 4: Password disable jumper (must be clear); + - Bit 5: Manufacturing jumper (must be set). + */ + ret = 0x24; + else if (!strcmp(machine_get_internal_name(), "optiplex_gxl")) + /* + Dell OptiPlex GXL/GXM: + - Bit 3: Password disable jumper (must be clear); + - Bit 4: Keyboard fuse (must be set); + - Bit 5: Manufacturing jumper (must be set). + */ + ret = 0x30; + else if (!strcmp(machine_get_internal_name(), "dellplato") || + !strcmp(machine_get_internal_name(), "dellhannibalp") || + !strcmp(machine_get_internal_name(), "dellxp60")) + /* + Dell Dimension XPS Pxxx & Pxxxa/Mxxxa: + - Bit 3: Password disable jumper (must be clear); + - Bit 4: Clear CMOS jumper (must be set). + */ + ret = 0x10; + else { + /* (B0 or F0) | (0x08 or 0x0c) */ + ret = ((dev->p1 | fixed_bits) & 0xf0) | + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c); + + if (!strcmp(machine_get_internal_name(), "alfredo")) + ret &= 0xef; + } + } else if (kbc_ven == KBC_VEN_COMPAQ) + ret = dev->p1 | (hasfpu ? 0x00 : 0x04); + else + /* (B0 or F0) | (0x04 or 0x44) */ + ret = dev->p1 | fixed_bits; + + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + + return ret; } static void @@ -1935,7 +1926,18 @@ kbc_at_process_cmd(void *priv) /* Clear the keyboard controller queue. */ kbc_at_queue_reset(dev); - switch (dev->ib) { + /* + If we have a vendor-specific handler, run that. Otherwise, or if + that handler fails, attempt to process it as a generic command. + */ + if (dev->write_cmd_ven) + bad = dev->write_cmd_ven(dev, dev->ib); + + if (bad) switch (dev->ib) { + default: + kbc_at_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib); + break; + /* Read data from KBC memory. */ case 0x20 ... 0x3f: kbc_delay_to_ob(dev, dev->mem[dev->ib], 0, 0x00); @@ -1949,14 +1951,64 @@ kbc_at_process_cmd(void *priv) dev->state = STATE_KBC_PARAM; break; + /* TODO: Are these undocmented VL82C113 commands? */ + case 0x80: /* Tulip command */ + kbc_at_log("ATkbc: Tulip command\n"); + kbc_delay_to_ob(dev, 0xff, 0, 0x00); + break; + + case 0x8c: /* Tulip reset command */ + kbc_at_log("ATkbc: Tulip reset command\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xa4: /* check if password installed */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: check if password installed\n"); + kbc_delay_to_ob(dev, 0xf1, 0, 0x00); + } + break; + + case 0xa5: /* load security */ + kbc_at_log("ATkbc: load security\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xa7: /* disable auxiliary port */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: disable auxiliary port\n"); + set_enable_aux(dev, 0); + } + break; + + case 0xa8: /* Enable auxiliary port */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: enable auxiliary port\n"); + set_enable_aux(dev, 1); + } + break; + + case 0xa9: /* Test auxiliary port */ + kbc_at_log("ATkbc: test auxiliary port\n"); + if (dev->misc_flags & FLAG_PS2) + kbc_delay_to_ob(dev, 0x00, 0, 0x00); /* no error, this is testing the channel 2 interface */ + break; + case 0xaa: /* self-test */ kbc_at_log("ATkbc: self-test\n"); if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { if (dev->state != STATE_RESET) { kbc_at_log("ATkbc: self-test reinitialization\n"); - /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ - /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ + /* + Yes, the firmware has an OR, but we need to make sure + to keep any forcibly lowered bytes lowered. + + TODO: Proper P1 implementation, with OR and AND flags + in the machine table. + */ dev->p1 = dev->p1 & 0xff; write_p2(dev, 0x4b); if (dev->irq[1] != 0xffff) @@ -1977,8 +2029,13 @@ kbc_at_process_cmd(void *priv) } else { if (dev->state != STATE_RESET) { kbc_at_log("ATkbc: self-test reinitialization\n"); - /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ - /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ + /* + Yes, the firmware has an OR, but we need to make sure + to keep any forcibly lowered bytes lowered. + + TODO: Proper P1 implementation, with OR and AND flags + in the machine table. + */ dev->p1 = dev->p1 & 0xff; write_p2(dev, 0xcf); if (dev->irq[0] != 0xffff) @@ -2016,12 +2073,13 @@ kbc_at_process_cmd(void *priv) break; case 0xac: /* diagnostic dump */ - if (dev->misc_flags & FLAG_PS2) { + if (!(dev->misc_flags & FLAG_PS2)) { kbc_at_log("ATkbc: diagnostic dump\n"); dev->mem[0x30] = (dev->p1 & 0xf0) | 0x80; dev->mem[0x31] = dev->p2; dev->mem[0x32] = 0x00; /* T0 and T1. */ - dev->mem[0x33] = 0x00; /* PSW - Program Status Word - always return 0x00 because we do not emulate this byte. */ + /* PSW - Program Status Word - always return 0x00 because we do not emulate this byte. */ + dev->mem[0x33] = 0x00; /* 20 bytes in high nibble in set 1, low nibble in set 1, set 1 space format = 60 bytes. */ for (uint8_t i = 0; i < 20; i++) { kbc_at_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] >> 4]); @@ -2041,10 +2099,33 @@ kbc_at_process_cmd(void *priv) set_enable_kbd(dev, 1); break; - case 0xc7: /* set port1 bits */ - kbc_at_log("ATkbc: Phoenix - set port1 bits\n"); - dev->wantdata = 1; - dev->state = STATE_KBC_PARAM; + /* TODO: Make this command do nothing on the Regional HT6542, + or else, Efflixi's Award OPTi 495 BIOS gets a stuck key + in Norton Commander 3.0. */ + case 0xaf: /* read keyboard version */ + kbc_at_log("ATkbc: read keyboard version\n"); + kbc_delay_to_ob(dev, kbc_award_revision, 0, 0x00); + break; + + case 0xc0: /* read P1 */ + kbc_at_log("ATkbc: read P2\n"); + kbc_delay_to_ob(dev, read_p1(dev), 0, 0x00); + break; + + case 0xc1: /*Copy bits 0 to 3 of P1 to status bits 4 to 7*/ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: copy bits 0 to 3 of P1 to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= (dev->p1 << 4); + } + break; + + case 0xc2: /*Copy bits 4 to 7 of P1 to status bits 4 to 7*/ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: copy bits 4 to 7 of P1 to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= (dev->p1 & 0xf0); + } break; case 0xca: /* read keyboard mode */ @@ -2052,12 +2133,6 @@ kbc_at_process_cmd(void *priv) kbc_delay_to_ob(dev, dev->ami_flags, 0, 0x00); break; - case 0xcb: /* set keyboard mode */ - kbc_at_log("ATkbc: AMI - set keyboard mode\n"); - dev->wantdata = 1; - dev->state = STATE_KBC_PARAM; - break; - case 0xd0: /* read P2 */ kbc_at_log("ATkbc: read P2\n"); mask = 0xff; @@ -2078,6 +2153,22 @@ kbc_at_process_cmd(void *priv) dev->state = STATE_KBC_PARAM; break; + case 0xd3: /* write auxiliary output buffer */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: write auxiliary output buffer\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + } + break; + + case 0xd4: /* write to auxiliary port */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: write to auxiliary port\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + } + break; + case 0xdd: /* disable A20 address line */ case 0xdf: /* enable A20 address line */ kbc_at_log("ATkbc: %sable A20\n", (dev->ib == 0xdd) ? "dis" : "en"); @@ -2089,18 +2180,10 @@ kbc_at_process_cmd(void *priv) kbc_delay_to_ob(dev, 0x00, 0, 0x00); break; - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write_cmd_ven) - bad = dev->write_cmd_ven(dev, dev->ib); - - kbc_at_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib); + case 0xf0 ... 0xff: /* pulse P2 */ + kbc_at_log("ATkbc: pulse %01X\n", dev->ib & 0x0f); + pulse_output(dev, dev->ib & 0x0f); + break; } /* If the command needs data, remember the command. */ @@ -2111,13 +2194,44 @@ kbc_at_process_cmd(void *priv) dev->wantdata = 0; dev->state = STATE_MAIN_IBF; - switch (dev->command) { + /* + Run the vendor-specific handler if we have one. Otherwise, or if it + returns an error, log a bad controller command. + */ + if (dev->write_cmd_data_ven) + bad = dev->write_cmd_data_ven(dev, dev->ib); + + if (bad) switch (dev->command) { + default: + kbc_at_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib); + break; + case 0x60 ... 0x7f: dev->mem[(dev->command & 0x1f) + 0x20] = dev->ib; if (dev->command == 0x60) write_cmd(dev, dev->ib); break; + case 0x8c: /* Tulip reset command */ + kbc_at_log("ATkbc: Tulip rset command\n"); + + dma_reset(); + dma_set_at(1); + + device_reset_all(DEVICE_ALL); + + cpu_alt_reset = 0; + + pci_reset(); + + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); + + resetx86(); + break; + case 0xa5: /* load security */ if (dev->misc_flags & FLAG_PS2) { kbc_at_log("ATkbc: load security (%02X)\n", dev->ib); @@ -2129,11 +2243,6 @@ kbc_at_process_cmd(void *priv) } break; - case 0xc7: /* set port1 bits */ - kbc_at_log("ATkbc: Phoenix - set port1 bits\n"); - dev->p1 |= dev->ib; - break; - case 0xd1: /* write P2 */ kbc_at_log("ATkbc: write P2\n"); /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), @@ -2176,20 +2285,6 @@ kbc_at_process_cmd(void *priv) kbc_delay_to_ob(dev, 0xfe, 2, 0x40); } break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write_cmd_data_ven) - bad = dev->write_cmd_data_ven(dev, dev->ib); - - if (bad) { - kbc_at_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib); - } } } } @@ -2493,6 +2588,9 @@ kbc_at_init(const device_t *info) kbc_award_revision = 0x42; switch (dev->flags & KBC_VEN_MASK) { + default: + break; + case KBC_VEN_SIEMENS: kbc_ami_revision = '8'; kbc_award_revision = 0x42; @@ -2500,15 +2598,6 @@ kbc_at_init(const device_t *info) dev->write_cmd_ven = write_cmd_siemens; break; - case KBC_VEN_ACER: - case KBC_VEN_GENERIC: - case KBC_VEN_NCR: - case KBC_VEN_IBM_PS1: - case KBC_VEN_IBM: - case KBC_VEN_COMPAQ: - dev->write_cmd_ven = write_cmd_generic; - break; - case KBC_VEN_OLIVETTI: dev->write_cmd_ven = write_cmd_olivetti; break; @@ -2564,9 +2653,6 @@ kbc_at_init(const device_t *info) dev->write_cmd_data_ven = write_cmd_data_toshiba; dev->write_cmd_ven = write_cmd_toshiba; break; - - default: - break; } #ifdef OLD_CODE From c135786d0c198d9e4e72867053eab88be675a13e Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 8 Mar 2025 00:04:15 -0500 Subject: [PATCH 1091/1190] Make XT82 diag's and debug roms work --- src/machine/m_xt.c | 127 +++++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 13f9c52ca..3941a39d5 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -282,48 +282,103 @@ machine_pc82_init(const machine_t *model) static const device_config_t ibmxt_config[] = { // clang-format off { - .name = "bios", - .description = "BIOS Version", - .type = CONFIG_BIOS, + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, .default_string = "ibm5160_1501512_5000027", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, - { .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } }, - { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, -#if 0 + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "1501512 (11/08/82)", + .internal_name = "ibm5160_1501512_5000027", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + }, + { + .name = "1501512 (11/08/82) (Alt)", + .internal_name = "ibm5160_1501512_6359116", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } + }, + { + .name = "5000026 (08/16/82)", + .internal_name = "ibm5160_5000026_5000027", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } + }, + // GlaBIOS for IBM XT - { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "" } }, - { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "" } }, + { + .name = "GlaBIOS 0.2.5 (8088)", + .internal_name = "glabios_025_8088", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 1, + .size = 40960, + .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + }, + { + .name = "GlaBIOS 0.2.5 (V20)", + .internal_name = "glabios_025_v20", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 1, + .size = 40960, + .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + }, // The following are Diagnostic ROMs. - { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, - { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, - { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, -#endif + { + .name = "Supersoft Diagnostics", + .internal_name = "diag_supersoft", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/Supersoft_PCXT_32KB.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + }, + { + .name = "Ruud's Diagnostic Rom", + .internal_name = "diag_ruuds", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_32kb.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + }, + { + .name = "XT RAM Test", + .internal_name = "diag_xtramtest", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/xtramtest_32k.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + }, { .files_no = 0 } }, }, { - .name = "enable_5161", + .name = "enable_5161", .description = "IBM 5161 Expansion Unit", - .type = CONFIG_BINARY, + .type = CONFIG_BINARY, .default_int = 1 }, { - .name = "enable_basic", + .name = "enable_basic", .description = "IBM Cassette Basic", - .type = CONFIG_BINARY, + .type = CONFIG_BINARY, .default_int = 1 }, { .name = "", .description = "", .type = CONFIG_END } @@ -351,6 +406,8 @@ machine_xt_init(const machine_t *model) uint8_t enable_5161; uint8_t enable_basic; const char *fn; + uint16_t offset = 0; + uint32_t local = 0; /* No ROMs available. */ if (!device_available(model->device)) @@ -360,11 +417,17 @@ machine_xt_init(const machine_t *model) enable_5161 = machine_get_config_int("enable_5161"); enable_basic = machine_get_config_int("enable_basic"); fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); - ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); + local = device_get_bios_local(model->device, device_get_config_bios("bios")); + + if (local == 0) // Offset for stock roms + offset = 0x6000; + ret = bios_load_linear(fn, 0x000fe000, 65536, offset); if (enable_basic && ret) { - fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); - (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + if (local == 0) { // needed for stock roms + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + } fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); /* On the real machine, the BASIC is repeated. */ (void) bios_load_aux_linear(fn, 0x000f0000, 8192, 0); From f542b5a8af2e79d61cbf4bb73889723838d44df0 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 8 Mar 2025 00:13:47 -0500 Subject: [PATCH 1092/1190] Make XT86 diag's and debug roms work --- src/machine/m_xt.c | 124 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 30 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 3941a39d5..eae32ca7b 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -471,42 +471,98 @@ machine_genxt_init(const machine_t *model) static const device_config_t ibmxt86_config[] = { // clang-format off { - .name = "bios", - .description = "BIOS Version", - .type = CONFIG_BIOS, + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, .default_string = "ibm5160_050986", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "1501512 (05/09/86)", .internal_name = "ibm5160_050986", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } }, - { .name = "5000026 (01/10/86)", .internal_name = "ibm5160_011086", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } }, - { .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } }, -#if 0 + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "1501512 (05/09/86)", + .internal_name = "ibm5160_050986", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + }, + { + .name = "5000026 (01/10/86)", + .internal_name = "ibm5160_011086", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } + }, + { + .name = "1501512 (01/10/86) (Alt)", + .internal_name = "ibm5160_011086_alt", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } + }, + // GlaBIOS for IBM XT - { .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "" } }, - { .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "" } }, + { + .name = "GlaBIOS 0.2.5 (8088)", + .internal_name = "glabios_025_8088", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 1, + .size = 65536, + .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + }, + { + .name = "GlaBIOS 0.2.5 (V20)", + .internal_name = "glabios_025_v20", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 1, + .size = 65536, + .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + }, // The following are Diagnostic ROMs. - { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, - { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, - { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, -#endif + { + .name = "Supersoft Diagnostics", + .internal_name = "diag_supersoft", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/Supersoft_PCXT_32KB.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + }, + { + .name = "Ruud's Diagnostic Rom", + .internal_name = "diag_ruuds", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_32kb.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + }, + { + .name = "XT RAM Test", + .internal_name = "diag_xtramtest", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/xtramtest_32k.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + }, + { .files_no = 0 } }, }, { - .name = "enable_5161", + .name = "enable_5161", .description = "IBM 5161 Expansion Unit", - .type = CONFIG_BINARY, + .type = CONFIG_BINARY, .default_int = 1 }, { .name = "", .description = "", .type = CONFIG_END } @@ -533,6 +589,8 @@ machine_xt86_init(const machine_t *model) int ret = 0; uint8_t enable_5161; const char *fn; + uint16_t offset = 0; + uint32_t local = 0; /* No ROMs available. */ if (!device_available(model->device)) @@ -541,11 +599,17 @@ machine_xt86_init(const machine_t *model) device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); - ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); + local = device_get_bios_local(model->device, device_get_config_bios("bios")); + + if (local == 0) // Offset for stock roms + offset = 0x6000; + ret = bios_load_linear(fn, 0x000fe000, 65536, offset); if (ret) { - fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); - (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + if (local == 0) { // needed for stock roms + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + } fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } From 9f37d0b1d163e08a6cf97380e43d44e82d70c6ef Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sat, 8 Mar 2025 00:14:05 -0500 Subject: [PATCH 1093/1190] Update Ruuds diagnostic rom to 5.4 --- src/machine/m_xt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index eae32ca7b..d71d16c15 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -85,7 +85,7 @@ static const device_config_t ibmpc_config[] = { { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_8kb.bin", "" } }, { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, { .files_no = 0 } @@ -195,7 +195,7 @@ static const device_config_t ibmpc82_config[] = { { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_8kb.bin", "" } }, { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, { .files_no = 0 } @@ -355,7 +355,7 @@ static const device_config_t ibmxt_config[] = { .files_no = 2, .local = 2, .size = 65536, - .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_32kb.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } + .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_32kb.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, { .name = "XT RAM Test", @@ -544,7 +544,7 @@ static const device_config_t ibmxt86_config[] = { .files_no = 2, .local = 2, .size = 65536, - .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_32kb.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } + .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_32kb.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } }, { .name = "XT RAM Test", From 301cd7be7a0a3face438b15b1138479ab9c9918f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Sun, 8 Jun 2025 21:09:05 -0400 Subject: [PATCH 1094/1190] Add Supersoft Diagnostics to IBM 5170 --- src/machine/m_at.c | 74 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 13cd831ba..d2c4b99a2 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -154,32 +154,68 @@ machine_at_ps2_ide_init(const machine_t *model) static const device_config_t ibmat_config[] = { // clang-format off { - .name = "bios", - .description = "BIOS Version", - .type = CONFIG_BIOS, + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, .default_string = "ibm5170_111585", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .bios = { - { .name = "62X082x (11/15/85)", .internal_name = "ibm5170_111585", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47.BIN", "" } }, + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { + .name = "62X082x (11/15/85)", + .internal_name = "ibm5170_111585", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47.BIN", "" } + }, + { + .name = "61X9266 (11/15/85) (Alt)", + .internal_name = "ibm5170_111585_alt", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27_61X9266.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47_61X9265.BIN", "" } + }, + { + .name = "648009x (06/10/85)", + .internal_name = "ibm5170_061085", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmat/BIOS_5170_10JUN85_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JUN85_U47.BIN", "" } + }, + { + .name = "618102x (01/10/84)", + .internal_name = "ibm5170_011084", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/ibmat/BIOS_5170_10JAN84_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JAN84_U47.BIN", "" } + }, + // The following are Diagnostic ROMs. + { + .name = "Supersoft Diagnostics", + .internal_name = "diag_supersoft", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 2, + .size = 65536, + .files = { "roms/machines/diagnostic/5170_EVEN_LOW_U27_27256.bin", "roms/machines/diagnostic/5170_ODD_HIGH_U47_27256.bin", "" } + }, - { .name = "61X9266 (11/15/85) (Alt)", .internal_name = "ibm5170_111585_alt", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27_61X9266.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47_61X9265.BIN", "" } }, - - { .name = "648009x (06/10/85)", .internal_name = "ibm5170_061085", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_10JUN85_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JUN85_U47.BIN", "" } }, - - { .name = "618102x (01/10/84)", .internal_name = "ibm5170_011084", .bios_type = BIOS_NORMAL, - .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_10JAN84_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JAN84_U47.BIN", "" } }, { .files_no = 0 } }, }, { - .name = "enable_5161", + .name = "enable_5161", .description = "IBM 5161 Expansion Unit", - .type = CONFIG_BINARY, + .type = CONFIG_BINARY, .default_int = 0 }, { .name = "", .description = "", .type = CONFIG_END } From 79c408b286f43b36c233a65db7f3d53e10e30813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= <oubattler@gmail.com> Date: Mon, 9 Jun 2025 08:18:16 +0200 Subject: [PATCH 1095/1190] SLiRP: Make sure get_revents() returns SLIRP_POLL_IN set in two cases on Windows, fixes stalls. --- src/network/net_slirp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 92c4c4ddf..e8cfd6cd7 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -291,8 +291,12 @@ net_slirp_get_revents(int idx, void *opaque) WSA_TO_POLL(FD_WRITE, SLIRP_POLL_OUT); WSA_TO_POLL(FD_CONNECT, SLIRP_POLL_OUT); WSA_TO_POLL(FD_OOB, SLIRP_POLL_PRI); + WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_IN); WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_HUP); + if (ret == 0) + ret |= SLIRP_POLL_IN; + return ret; } #else From b639bf18532a696b679cf5246cdb6bf242e698dd Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 14:12:13 +0100 Subject: [PATCH 1096/1190] Enumerate CGA CRTC registers and modes and implement that into the code --- src/include/86box/vid_cga.h | 36 ++++++++++ src/video/vid_cga.c | 135 +++++++++++++++++++----------------- 2 files changed, 107 insertions(+), 64 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index a503d12ba..52e41755c 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -15,11 +15,47 @@ * * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. + * Copyright 2025 starfrost (refactoring) */ #ifndef VIDEO_CGA_H #define VIDEO_CGA_H +// Mode flags for the CGA. +// Set by writing to 3D8 +typedef enum cga_mode_flags_e +{ + CGA_MODE_FLAG_HIGHRES = 1 << 0, // 80-column text mode + CGA_MODE_FLAG_GRAPHICS = 1 << 1, // Graphics mode + CGA_MODE_FLAG_BW = 1 << 2, // Black and white + CGA_MODE_FLAG_VIDEO_ENABLE = 1 << 3, // 0 = no video (as if the video was 0) + CGA_MODE_FLAG_HIGHRES_GRAPHICS = 1 << 4, // 640*200 mode. Corrupts the + CGA_MODE_FLAG_BLINK = 1 << 5, // If this is set, bit 5 of textmode characters blinks. Otherwise it is a high-intensity bg mode. +} cga_mode_flags; + +// Motorola MC6845 CRTC registers +typedef enum cga_crtc_registers_e +{ + CGA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync) + CGA_CRTC_HDISP = 0x1, // Horizontal display + CGA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc + CGA_CRTC_HSYNC_WIDTH = 0x3, // Width of horizontal sync + CGA_CRTC_VTOTAL = 0x4, // Vertical total (total number of scanlines incl. vsync) + CGA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value + CGA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline) + CGA_CRTC_VSYNC = 0x7, // Vertical sync scanline number + CGA_CRTC_INTERLACE = 0x8, // If set, interlacing mode is enabled + CGA_CRTC_MAX_SCANLINE_ADDR = 0x9, + CGA_CRTC_CURSOR_START = 0xA, + CGA_CRTC_CURSOR_END = 0xB, + CGA_CRTC_START_ADDR_HIGH = 0xC, + CGA_CRTC_START_ADDR_LOW = 0xD, + CGA_CRTC_CURSOR_ADDR_HIGH = 0xE, + CGA_CRTC_CURSOR_ADDR_LOW = 0xF, + CGA_CRTC_LIGHT_PEN_ADDR_HIGH = 0x10, + CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, +} cga_crtc_registers; + typedef struct cga_t { mem_mapping_t mapping; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index a24162019..f82d186de 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -16,7 +16,7 @@ * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. - * Copyright 2023 W. M. Martinez + * Copyright 2023 W. M. Martine */ #include <stdio.h> #include <stdint.h> @@ -73,10 +73,10 @@ void cga_recalctimings(cga_t *cga); static void cga_update_latch(cga_t *cga) { - uint32_t lp_latch = cga->displine * cga->crtc[1]; + uint32_t lp_latch = cga->displine * cga->crtc[CGA_CRTC_HDISP]; cga->crtc[0x10] = (lp_latch >> 8) & 0x3f; - cga->crtc[0x11] = lp_latch & 0xff; + cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_LOW] = lp_latch & 0xff; } void @@ -96,6 +96,8 @@ cga_out(uint16_t addr, uint8_t val, void *priv) old = cga->crtc[cga->crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; if (old != val) { + // Update the timings if we are writing any invalid CRTC register or a valid CRTC register + // except the CURSOR and LIGHT PEN registers if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) { cga->fullchange = changeframecount; cga_recalctimings(cga); @@ -235,12 +237,12 @@ cga_recalctimings(cga_t *cga) double _dispontime; double _dispofftime; - if (cga->cgamode & 1) { - disptime = (double) (cga->crtc[0] + 1); - _dispontime = (double) cga->crtc[1]; + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { + disptime = (double) (cga->crtc[CGA_CRTC_HTOTAL] + 1); + _dispontime = (double) cga->crtc[CGA_CRTC_HDISP]; } else { - disptime = (double) ((cga->crtc[0] + 1) << 1); - _dispontime = (double) (cga->crtc[1] << 1); + disptime = (double) ((cga->crtc[CGA_CRTC_HTOTAL] + 1) << 1); + _dispontime = (double) (cga->crtc[CGA_CRTC_HDISP] << 1); } _dispofftime = disptime - _dispontime; _dispontime = _dispontime * CGACONST; @@ -252,7 +254,7 @@ cga_recalctimings(cga_t *cga) static void cga_render(cga_t *cga, int line) { - uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; + uint16_t ca = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -262,33 +264,35 @@ cga_render(cga_t *cga, int line) int cols[4]; int col; - if ((cga->cgamode & 0x12) == 0x12) { + int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); + + if ((cga->cgamode & highres_graphics_flag == highres_graphics_flag)) { for (c = 0; c < 8; ++c) { buffer32->line[line][c] = 0; - if (cga->cgamode & 1) - buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = 0; + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = 0; else - buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = 0; + buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = 0; } } else { for (c = 0; c < 8; ++c) { buffer32->line[line][c] = (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) - buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = (cga->cgacol & 15) + 16; else - buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16; + buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = (cga->cgacol & 15) + 16; } } - if (cga->cgamode & 1) { - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) { + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { + if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { chr = cga->charbuffer[x << 1]; attr = cga->charbuffer[(x << 1) + 1]; } else chr = attr = 0; drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); cols[1] = (attr & 15) + 16; - if (cga->cgamode & 0x20) { + if (cga->cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor) cols[1] = cols[0]; @@ -308,15 +312,15 @@ cga_render(cga_t *cga, int line) cga->ma++; } } else if (!(cga->cgamode & 2)) { - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) { + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { + if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { chr = cga->vram[(cga->ma << 1) & 0x3fff]; attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; } else chr = attr = 0; drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); cols[1] = (attr & 15) + 16; - if (cga->cgamode & 0x20) { + if (cga->cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; if ((cga->cgablink & 8) && (attr & 0x80)) cols[1] = cols[0]; @@ -337,10 +341,10 @@ cga_render(cga_t *cga, int line) } } } - } else if (!(cga->cgamode & 16)) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { cols[0] = (cga->cgacol & 15) | 16; col = (cga->cgacol & 16) ? 24 : 16; - if (cga->cgamode & 4) { + if (cga->cgamode & CGA_MODE_FLAG_BW) { cols[1] = col | 3; /* Cyan */ cols[2] = col | 4; /* Red */ cols[3] = col | 7; /* White */ @@ -353,8 +357,8 @@ cga_render(cga_t *cga, int line) cols[2] = col | 4; /* Red */ cols[3] = col | 6; /* Yellow */ } - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { + if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; else @@ -370,8 +374,8 @@ cga_render(cga_t *cga, int line) } else { cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16; - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { + if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; else @@ -388,12 +392,14 @@ cga_render(cga_t *cga, int line) static void cga_render_blank(cga_t *cga, int line) { - int col = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; + int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); - if (cga->cgamode & 1) - hline(buffer32, 0, line, (cga->crtc[1] << 3) + 16, col); + int col = ((cga->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (cga->cgacol & 15) + 16; + + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + hline(buffer32, 0, line, (cga->crtc[CGA_CRTC_HDISP] << 3) + 16, col); else - hline(buffer32, 0, line, (cga->crtc[1] << 4) + 16, col); + hline(buffer32, 0, line, (cga->crtc[CGA_CRTC_HDISP] << 4) + 16, col); } static void @@ -401,14 +407,15 @@ cga_render_process(cga_t *cga, int line) { int x; uint8_t border; + int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + x = (cga->crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (cga->crtc[1] << 4) + 16; + x = (cga->crtc[CGA_CRTC_HDISP] << 4) + 16; if (cga->composite) { - border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15); + border = ((cga->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (cga->cgacol & 15); Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[line]); } else @@ -524,7 +531,7 @@ cga_poll(void *priv) cga->cgastat |= 1; cga->linepos = 1; oldsc = cga->sc; - if ((cga->crtc[8] & 3) == 3) + if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3) cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; if (cga->cgadispon) { if (cga->displine < cga->firstline) { @@ -573,7 +580,7 @@ cga_poll(void *priv) } cga->sc = oldsc; - if (cga->vc == cga->crtc[7] && !cga->sc) + if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->sc) cga->cgastat |= 8; cga->displine++; if (cga->displine >= 360) @@ -586,12 +593,12 @@ cga_poll(void *priv) if (!cga->vsynctime) cga->cgastat &= ~8; } - if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && - cga->sc == ((cga->crtc[11] & 31) >> 1))) { + if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && + cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { cga->con = 0; cga->coff = 1; } - if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) + if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) cga->maback = cga->ma; if (cga->vadj) { cga->sc++; @@ -600,27 +607,27 @@ cga_poll(void *priv) cga->vadj--; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + cga->ma = cga->maback = (CGA_CRTC_START_ADDR_LOW | (CGA_CRTC_START_ADDR_HIGH << 8)) & 0x3fff; cga->sc = 0; } - } else if (cga->sc == cga->crtc[9]) { + } else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { cga->maback = cga->ma; cga->sc = 0; oldvc = cga->vc; cga->vc++; cga->vc &= 127; - if (cga->vc == cga->crtc[6]) + if (cga->vc == cga->crtc[CGA_CRTC_VDISP]) cga->cgadispon = 0; - if (oldvc == cga->crtc[4]) { + if (oldvc == cga->crtc[CGA_CRTC_VTOTAL]) { cga->vc = 0; - cga->vadj = cga->crtc[5]; + cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + cga->ma = cga->maback = (CGA_CRTC_START_ADDR_LOW | (CGA_CRTC_START_ADDR_HIGH << 8)) & 0x3fff; } - switch (cga->crtc[10] & 0x60) { + switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) { case 0x20: cga->cursoron = 0; break; @@ -633,15 +640,15 @@ cga_poll(void *priv) } } - if (cga->vc == cga->crtc[7]) { + if (cga->vc == cga->crtc[CGA_CRTC_VSYNC]) { cga->cgadispon = 0; cga->displine = 0; cga->vsynctime = 16; - if (cga->crtc[7]) { - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; + if (cga->crtc[CGA_CRTC_VSYNC]) { + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + x = (cga->crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (cga->crtc[1] << 4) + 16; + x = (cga->crtc[CGA_CRTC_HDISP] << 4) + 16; cga->lastline++; xs_temp = x; @@ -657,7 +664,7 @@ cga_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((cga->cgamode & 8) && ((xs_temp != xsize) || + if ((cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; @@ -691,15 +698,15 @@ cga_poll(void *priv) video_res_x = xsize; video_res_y = ysize; - if (cga->cgamode & 1) { + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; - video_res_y /= cga->crtc[9] + 1; + video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(cga->cgamode & 2)) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; - video_res_y /= cga->crtc[9] + 1; + video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(cga->cgamode & 16)) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { video_res_x /= 2; video_bpp = 2; } else @@ -717,11 +724,11 @@ cga_poll(void *priv) } if (cga->cgadispon) cga->cgastat &= ~1; - if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && - cga->sc == ((cga->crtc[10] & 31) >> 1))) + if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && + cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) cga->con = 1; - if (cga->cgadispon && (cga->cgamode & 1)) { - for (x = 0; x < (cga->crtc[1] << 1); x++) + if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) { + for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++) cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; } } From 08e2fd8e17abc954582b942fc621938ed9cd5a1e Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 14:27:41 +0100 Subject: [PATCH 1097/1190] fix rendering but stuck in 640x200 --- src/video/vid_cga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index f82d186de..220c77124 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -607,7 +607,7 @@ cga_poll(void *priv) cga->vadj--; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (CGA_CRTC_START_ADDR_LOW | (CGA_CRTC_START_ADDR_HIGH << 8)) & 0x3fff; + cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; cga->sc = 0; } } else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { @@ -625,7 +625,7 @@ cga_poll(void *priv) cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (CGA_CRTC_START_ADDR_LOW | (CGA_CRTC_START_ADDR_HIGH << 8)) & 0x3fff; + cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; } switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) { case 0x20: From e637f53981ecce39b23c1d5cb0df217e9f34b3ba Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 15:15:53 +0100 Subject: [PATCH 1098/1190] remove cga->coff because it is never used or checked --- src/include/86box/vid_cga.h | 17 ++++++++--------- src/include/86box/vid_hercules.h | 1 - src/include/86box/vid_mda.h | 1 - src/include/86box/vid_pgc.h | 1 - src/machine/m_amstrad.c | 4 ---- src/machine/m_pcjr.c | 2 -- src/machine/m_tandy.c | 2 -- src/video/vid_cga.c | 1 - src/video/vid_colorplus.c | 1 - src/video/vid_compaq_cga.c | 1 - src/video/vid_hercules.c | 1 - src/video/vid_herculesplus.c | 3 +-- src/video/vid_incolor.c | 3 +-- src/video/vid_mda.c | 1 - src/video/vid_nga.c | 1 - src/video/vid_ogc.c | 1 - src/video/vid_sigma.c | 3 +-- 17 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 52e41755c..8ad7b7b98 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -44,14 +44,14 @@ typedef enum cga_crtc_registers_e CGA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value CGA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline) CGA_CRTC_VSYNC = 0x7, // Vertical sync scanline number - CGA_CRTC_INTERLACE = 0x8, // If set, interlacing mode is enabled - CGA_CRTC_MAX_SCANLINE_ADDR = 0x9, - CGA_CRTC_CURSOR_START = 0xA, - CGA_CRTC_CURSOR_END = 0xB, - CGA_CRTC_START_ADDR_HIGH = 0xC, - CGA_CRTC_START_ADDR_LOW = 0xD, - CGA_CRTC_CURSOR_ADDR_HIGH = 0xE, - CGA_CRTC_CURSOR_ADDR_LOW = 0xF, + CGA_CRTC_INTERLACE = 0x8, // Interlacing mode + CGA_CRTC_MAX_SCANLINE_ADDR = 0x9, // Maximum scanline address + CGA_CRTC_CURSOR_START = 0xA, // Cursor start scanline + CGA_CRTC_CURSOR_END = 0xB, // Cursor end scanline + CGA_CRTC_START_ADDR_HIGH = 0xC, // Screen start address high 8 bits + CGA_CRTC_START_ADDR_LOW = 0xD, // Screen start address low 8 bits + CGA_CRTC_CURSOR_ADDR_HIGH = 0xE, // Cursor address high 8 bits + CGA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor addres low 8 bits CGA_CRTC_LIGHT_PEN_ADDR_HIGH = 0x10, CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, } cga_crtc_registers; @@ -76,7 +76,6 @@ typedef struct cga_t { int vc; int cgadispon; int con; - int coff; int cursoron; int cgablink; int vsynctime; diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index c58a50aa3..a468dce55 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -47,7 +47,6 @@ typedef struct { uint16_t ma; uint16_t maback; int con; - int coff; int cursoron; int dispon; int blink; diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index d13c45a28..eeea5a093 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -29,7 +29,6 @@ typedef struct mda_t { uint16_t ma; uint16_t maback; int con; - int coff; int cursoron; int dispon; int blink; diff --git a/src/include/86box/vid_pgc.h b/src/include/86box/vid_pgc.h index 35e2d9e42..43226a0f5 100644 --- a/src/include/86box/vid_pgc.h +++ b/src/include/86box/vid_pgc.h @@ -116,7 +116,6 @@ typedef struct pgc { int vc; int cgadispon; int con; - int coff; int cursoron; int cgablink; int vsynctime; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 814d95ffd..57e8367ff 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -117,7 +117,6 @@ typedef struct amsvid_t { int vc; int cgadispon; int con; - int coff; int cursoron; int cgablink; int vsynctime; @@ -515,7 +514,6 @@ vid_poll_1512(void *priv) } if (vid->sc == (vid->crtc[11] & 31)) { vid->con = 0; - vid->coff = 1; } if (vid->vadj) { vid->sc++; @@ -1319,7 +1317,6 @@ lcdm_poll(amsvid_t *vid) } if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { mda->con = 0; - mda->coff = 1; } if (mda->vadj) { mda->sc++; @@ -1483,7 +1480,6 @@ lcdc_poll(amsvid_t *vid) } if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { cga->con = 0; - cga->coff = 1; } if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) cga->maback = cga->ma; diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index cb69bd9e5..f2da2e2b5 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -82,7 +82,6 @@ typedef struct pcjr_t { int vc; int dispon; int con; - int coff; int cursoron; int blink; int vsynctime; @@ -1167,7 +1166,6 @@ vid_poll(void *priv) } if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { pcjr->con = 0; - pcjr->coff = 1; } if (pcjr->vadj) { pcjr->sc++; diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 7072c5e78..4d0768378 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -92,7 +92,6 @@ typedef struct t1kvid_t { int vc; int dispon; int con; - int coff; int cursoron; int blink; int fullchange; @@ -1212,7 +1211,6 @@ vid_poll(void *priv) } if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { vid->con = 0; - vid->coff = 1; } if (vid->vadj) { vid->sc++; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 220c77124..bb0d04248 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -596,7 +596,6 @@ cga_poll(void *priv) if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { cga->con = 0; - cga->coff = 1; } if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) cga->maback = cga->ma; diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 6c66175c1..a0d5e6de1 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -229,7 +229,6 @@ colorplus_poll(void *priv) } if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) { colorplus->cga.con = 0; - colorplus->cga.coff = 1; } if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1)) colorplus->cga.maback = colorplus->cga.ma; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 13fc399eb..f9fec32d0 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -269,7 +269,6 @@ compaq_cga_poll(void *priv) if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { self->cga.con = 0; - self->cga.coff = 1; } if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) self->cga.maback = self->cga.ma; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index af8ad08f8..cf8ad8cf3 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -399,7 +399,6 @@ hercules_poll(void *priv) if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { dev->con = 0; - dev->coff = 1; } if (dev->vadj) { diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index fb42c3022..42c68bf54 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -77,7 +77,7 @@ typedef struct { int linepos, displine; int vc, sc; uint16_t ma, maback; - int con, coff, cursoron; + int con, cursoron; int dispon, blink; int vsynctime; int vadj; @@ -536,7 +536,6 @@ herculesplus_poll(void *priv) if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { dev->con = 0; - dev->coff = 1; } if (dev->vadj) { dev->sc++; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index d9b48f43a..034d54045 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -167,7 +167,7 @@ typedef struct { int linepos, displine; int vc, sc; uint16_t ma, maback; - int con, coff, cursoron; + int con, cursoron; int dispon, blink; int vsynctime; int vadj; @@ -899,7 +899,6 @@ incolor_poll(void *priv) if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { dev->con = 0; - dev->coff = 1; } if (dev->vadj) { diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 7b6e54806..70ca375fd 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -200,7 +200,6 @@ mda_poll(void *priv) } if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { mda->con = 0; - mda->coff = 1; } if (mda->vadj) { mda->sc++; diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index ef1c6cd40..5fc81109c 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -392,7 +392,6 @@ nga_poll(void *priv) /* cursor stop scanline */ if (nga->cga.sc == (nga->cga.crtc[11] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[11] & 31) >> 1))) { nga->cga.con = 0; - nga->cga.coff = 1; } /* interlaced and max scanline per char reached */ if ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1)) diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index a49cd8a22..162cb9073 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -407,7 +407,6 @@ ogc_poll(void *priv) } if (ogc->cga.sc == (ogc->cga.crtc[11] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[11] & 31) >> 1))) { ogc->cga.con = 0; - ogc->cga.coff = 1; } if ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1)) ogc->cga.maback = ogc->cga.ma; diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index d771260ed..c54af7119 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -158,7 +158,7 @@ typedef struct sigma_t { int linepos, displine; int sc, vc; int cgadispon; - int con, coff, cursoron, cgablink; + int con, cursoron, cgablink; int vsynctime, vadj; int oddeven; @@ -676,7 +676,6 @@ sigma_poll(void *priv) } if (sigma->sc == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1))) { sigma->con = 0; - sigma->coff = 1; } if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1)) sigma->maback = sigma->ma; From d13251c07a98108cb56e7b0148b1fbda49ea8639 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 15:25:28 +0100 Subject: [PATCH 1099/1190] Do the same for the registers. --- src/include/86box/vid_cga.h | 19 +++++++++++++++---- src/video/vid_cga.c | 25 ++++++++++++------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 8ad7b7b98..00016e6c7 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -29,7 +29,7 @@ typedef enum cga_mode_flags_e CGA_MODE_FLAG_GRAPHICS = 1 << 1, // Graphics mode CGA_MODE_FLAG_BW = 1 << 2, // Black and white CGA_MODE_FLAG_VIDEO_ENABLE = 1 << 3, // 0 = no video (as if the video was 0) - CGA_MODE_FLAG_HIGHRES_GRAPHICS = 1 << 4, // 640*200 mode. Corrupts the + CGA_MODE_FLAG_HIGHRES_GRAPHICS = 1 << 4, // 640*200 mode. Corrupts text mode if CGA_MODE_FLAG_GRAPHICS not set. CGA_MODE_FLAG_BLINK = 1 << 5, // If this is set, bit 5 of textmode characters blinks. Otherwise it is a high-intensity bg mode. } cga_mode_flags; @@ -51,11 +51,22 @@ typedef enum cga_crtc_registers_e CGA_CRTC_START_ADDR_HIGH = 0xC, // Screen start address high 8 bits CGA_CRTC_START_ADDR_LOW = 0xD, // Screen start address low 8 bits CGA_CRTC_CURSOR_ADDR_HIGH = 0xE, // Cursor address high 8 bits - CGA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor addres low 8 bits - CGA_CRTC_LIGHT_PEN_ADDR_HIGH = 0x10, - CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, + CGA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor address low 8 bits + CGA_CRTC_LIGHT_PEN_ADDR_HIGH = 0x10, // Light pen address high 8 bits (not currently supported) + CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, // Light pen address low 8 bits (not currently supported) } cga_crtc_registers; +typedef enum cga_registers_e +{ + CGA_REGISTER_CRTC_INDEX = 0x3D4, + CGA_REGISTER_CRTC_DATA = 0x3D5, + CGA_REGISTER_MODE_CONTROL = 0x3D8, + CGA_REGISTER_COLOR_SELECT = 0x3D9, + CGA_REGISTER_STATUS = 0x3DA, + CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH = 0x3DB, + CGA_REGISTER_SET_LIGHT_PEN_LATCH = 0x3DC, +} cga_registers; + typedef struct cga_t { mem_mapping_t mapping; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index bb0d04248..578f7419e 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -89,14 +89,14 @@ cga_out(uint16_t addr, uint8_t val, void *priv) addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x3D4: + case CGA_REGISTER_CRTC_INDEX: cga->crtcreg = val & 31; return; - case 0x3D5: + case CGA_REGISTER_CRTC_DATA: old = cga->crtc[cga->crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; if (old != val) { - // Update the timings if we are writing any invalid CRTC register or a valid CRTC register + // Recalc the timings if we are writing any invalid CRTC register or a valid CRTC register // except the CURSOR and LIGHT PEN registers if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) { cga->fullchange = changeframecount; @@ -104,7 +104,7 @@ cga_out(uint16_t addr, uint8_t val, void *priv) } } return; - case 0x3D8: + case CGA_REGISTER_MODE_CONTROL: old = cga->cgamode; cga->cgamode = val; @@ -115,18 +115,18 @@ cga_out(uint16_t addr, uint8_t val, void *priv) cga_recalctimings(cga); } return; - case 0x3D9: + case CGA_REGISTER_COLOR_SELECT: old = cga->cgacol; cga->cgacol = val; if (old ^ val) cga_recalctimings(cga); return; - case 0x3DB: + case CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH: if (cga->lp_strobe == 1) cga->lp_strobe = 0; return; - case 0x3DC: + case CGA_REGISTER_SET_LIGHT_PEN_LATCH: if (cga->lp_strobe == 0) { cga->lp_strobe = 1; cga_update_latch(cga); @@ -148,21 +148,20 @@ cga_in(uint16_t addr, void *priv) addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x3D4: + case CGA_REGISTER_CRTC_INDEX: ret = cga->crtcreg; break; - case 0x3D5: + case CGA_REGISTER_CRTC_DATA: ret = cga->crtc[cga->crtcreg]; break; - case 0x3DA: + case CGA_REGISTER_STATUS: ret = cga->cgastat; break; - - case 0x3DB: + case CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH: if (cga->lp_strobe == 1) cga->lp_strobe = 0; break; - case 0x3DC: + case CGA_REGISTER_SET_LIGHT_PEN_LATCH: if (cga->lp_strobe == 0) { cga->lp_strobe = 1; cga_update_latch(cga); From 2be1c4960e414dfa6a101e14f14e45f7ef2b5007 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 15:32:32 +0100 Subject: [PATCH 1100/1190] plantronics: don't duplicate code --- src/video/vid_colorplus.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index a0d5e6de1..a0ffd8349 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -42,9 +42,6 @@ #define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */ #define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */ -/* Bits in the CGA graphics mode register */ -#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */ - #define CGA_RGB 0 #define CGA_COMPOSITE 1 @@ -80,7 +77,7 @@ colorplus_write(uint32_t addr, uint8_t val, void *priv) { colorplus_t *colorplus = (colorplus_t *) priv; - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) { + if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) { addr ^= 0x4000; } else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) { addr &= 0x3FFF; @@ -99,7 +96,7 @@ colorplus_read(uint32_t addr, void *priv) { colorplus_t *colorplus = (colorplus_t *) priv; - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) { + if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { addr ^= 0x4000; } else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) { addr &= 0x3FFF; @@ -140,7 +137,7 @@ colorplus_poll(void *priv) /* If one of the extra modes is not selected, drop down to the CGA * drawing code. */ - if (!((colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE))) { + if (!((colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS))) { cga_poll(&colorplus->cga); return; } From 615b296a2a925d3ac7aac86cea96dc64f558087c Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 15:35:58 +0100 Subject: [PATCH 1101/1190] Don't use a magic array size --- src/include/86box/vid_cga.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 00016e6c7..2a36eeade 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -67,11 +67,13 @@ typedef enum cga_registers_e CGA_REGISTER_SET_LIGHT_PEN_LATCH = 0x3DC, } cga_registers; +#define CGA_NUM_CRTC_REGS 32 + typedef struct cga_t { mem_mapping_t mapping; int crtcreg; - uint8_t crtc[32]; + uint8_t crtc[CGA_NUM_CRTC_REGS]; uint8_t cgastat; From b4b1a599ba32bf0fc4266f4510d99b65a9f9681b Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 15:47:49 +0100 Subject: [PATCH 1102/1190] Fix compilation & warnings --- src/video/vid_cga.c | 2 +- src/video/vid_colorplus.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 578f7419e..4a9a032c5 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -265,7 +265,7 @@ cga_render(cga_t *cga, int line) int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); - if ((cga->cgamode & highres_graphics_flag == highres_graphics_flag)) { + if (((cga->cgamode & highres_graphics_flag) == highres_graphics_flag)) { for (c = 0; c < 8; ++c) { buffer32->line[line][c] = 0; if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index a0ffd8349..7daba018e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -77,7 +77,7 @@ colorplus_write(uint32_t addr, uint8_t val, void *priv) { colorplus_t *colorplus = (colorplus_t *) priv; - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) { + if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { addr ^= 0x4000; } else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) { addr &= 0x3FFF; From 4a98cef2bf8fd610edb2a627e02b7b867bf549cb Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Mon, 9 Jun 2025 17:31:56 +0200 Subject: [PATCH 1103/1190] Cleaned up IBM/ATI 8514/A code (June 9th, 2025) Replaced the magic numbers with actual enumerators for ease of understanding. --- src/include/86box/vid_8514a.h | 26 ++++++++++++++++++++------ src/video/vid_8514a.c | 27 ++++++++++++++------------- src/video/vid_ati_mach8.c | 12 ++++++------ 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 696b640bc..92960f912 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -24,6 +24,19 @@ #define INT_FIFO_EMP (1 << 3) #define INT_MASK 0xf +typedef enum { + IBM_8514A_TYPE = 0, + ATI_38800_TYPE, + ATI_68800_TYPE, + TYPE_MAX +} ibm8514_card_type; + +typedef enum { + IBM = 0, + ATI, + EXTENSIONS_MAX +} ibm8514_extensions_t; + typedef struct hwcursor8514_t { int ena; int x; @@ -58,7 +71,7 @@ typedef struct ibm8514_t { int force_old_addr; int type; - int local; + ibm8514_card_type local; int bpp; int on; int accel_bpp; @@ -246,7 +259,8 @@ typedef struct ibm8514_t { int pitch; int ext_pitch; int ext_crt_pitch; - int extensions; + ibm8514_extensions_t extensions; + int onboard; int linear; uint32_t vram_amount; int vram_512k_8514; @@ -263,9 +277,9 @@ typedef struct ibm8514_t { } ibm8514_t; -#define IBM_8514A (((dev->local & 0xff) == 0x00) && (dev->extensions == 0x00)) -#define ATI_8514A_ULTRA (((dev->local & 0xff) == 0x00) && (dev->extensions == 0x01)) -#define ATI_GRAPHICS_ULTRA ((dev->local & 0xff) == 0x01) -#define ATI_MACH32 ((dev->local & 0xff) == 0x02) +#define IBM_8514A (((dev->local & 0xff) == IBM_8514A_TYPE) && (dev->extensions == IBM)) +#define ATI_8514A_ULTRA (((dev->local & 0xff) == IBM_8514A_TYPE) && (dev->extensions == ATI)) +#define ATI_GRAPHICS_ULTRA ((dev->local & 0xff) == ATI_38800_TYPE) +#define ATI_MACH32 ((dev->local & 0xff) == ATI_68800_TYPE) #endif /*VIDEO_8514A_H*/ diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index ba4641259..02f22ed54 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -3693,10 +3693,10 @@ ibm8514_poll(void *priv) svga->render8514(svga); - svga->x_add = (overscan_x >> 1); + svga->x_add = svga->left_overscan; ibm8514_render_overscan_left(dev, svga); ibm8514_render_overscan_right(dev, svga); - svga->x_add = (overscan_x >> 1); + svga->x_add = svga->left_overscan; if (dev->hwcursor_on) { if (svga->hwcursor_draw) @@ -3796,7 +3796,7 @@ ibm8514_poll(void *priv) dev->dispon = 1; dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; - svga->x_add = (overscan_x >> 1); + svga->x_add = svga->left_overscan; dev->hwcursor_on = 0; dev->hwcursor_latch = dev->hwcursor; @@ -3966,7 +3966,7 @@ ibm8514_init(const device_t *info) bios_addr = 0xc6000; switch (dev->extensions) { - case 1: + case ATI: if (rom_present(BIOS_MACH8_ROM_PATH)) { mach_t * mach = (mach_t *) calloc(1, sizeof(mach_t)); svga->ext8514 = mach; @@ -3977,13 +3977,14 @@ ibm8514_init(const device_t *info) 0, MEM_MAPPING_EXTERNAL); ati8514_init(svga, svga->ext8514, svga->dev8514); - mach->accel.scratch0 = ((((bios_addr >> 7) - 0x1000) >> 4)); + mach->accel.scratch0 = ((bios_addr >> 7) - 0x1000) >> 4; bios_rom_eeprom = mach->accel.scratch0; if (dev->type & DEVICE_MCA) { dev->pos_regs[0] = 0x88; dev->pos_regs[1] = 0x80; mach->eeprom.data[0] = 0x0000; mach->eeprom.data[1] = bios_rom_eeprom | ((bios_rom_eeprom | 0x01) << 8); + ibm8514_log("EEPROM Data1=%04x.\n", mach->eeprom.data[1]); mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); ati_eeprom_load_mach8(&mach->eeprom, "ati8514_mca.nvr", 1); mem_mapping_disable(&dev->bios_rom.mapping); @@ -4067,12 +4068,12 @@ static const device_config_t isa_ext8514_config[] = { .description = "Vendor", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 0, + .default_int = IBM, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "IBM", .value = 0 }, - { .description = "ATI", .value = 1 }, + { .description = "IBM", .value = IBM }, + { .description = "ATI", .value = ATI }, { .description = "" } }, .bios = { { 0 } } @@ -4127,12 +4128,12 @@ static const device_config_t mca_ext8514_config[] = { .description = "Vendor", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 0, + .default_int = IBM, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "IBM", .value = 0 }, - { .description = "ATI", .value = 1 }, + { .description = "IBM", .value = IBM }, + { .description = "ATI", .value = ATI }, { .description = "" } }, .bios = { { 0 } } @@ -4145,7 +4146,7 @@ const device_t gen8514_isa_device = { .name = "IBM 8514/A clone (ISA)", .internal_name = "8514_isa", .flags = DEVICE_ISA16, - .local = 0, + .local = IBM_8514A_TYPE, .init = ibm8514_init, .close = ibm8514_close, .reset = NULL, @@ -4159,7 +4160,7 @@ const device_t ibm8514_mca_device = { .name = "IBM 8514/A (MCA)", .internal_name = "8514_mca", .flags = DEVICE_MCA, - .local = 0, + .local = IBM_8514A_TYPE, .init = ibm8514_init, .close = ibm8514_close, .reset = NULL, diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 0b5673d69..f7b5e0915 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -7409,7 +7409,7 @@ const device_t mach8_vga_isa_device = { .name = "ATI Mach8 (ATI Graphics Ultra) (ISA)", .internal_name = "mach8_vga_isa", .flags = DEVICE_ISA, - .local = 1, + .local = ATI_38800_TYPE, .init = mach8_init, .close = mach_close, .reset = mach_reset, @@ -7423,7 +7423,7 @@ const device_t mach32_isa_device = { .name = "ATI Mach32 (ISA)", .internal_name = "mach32_isa", .flags = DEVICE_ISA, - .local = 2, + .local = ATI_68800_TYPE, .init = mach8_init, .close = mach_close, .reset = mach_reset, @@ -7437,7 +7437,7 @@ const device_t mach32_vlb_device = { .name = "ATI Mach32 (VLB)", .internal_name = "mach32_vlb", .flags = DEVICE_VLB, - .local = 2, + .local = ATI_68800_TYPE, .init = mach8_init, .close = mach_close, .reset = mach_reset, @@ -7451,7 +7451,7 @@ const device_t mach32_mca_device = { .name = "ATI Mach32 (MCA)", .internal_name = "mach32_mca", .flags = DEVICE_MCA, - .local = 2, + .local = ATI_68800_TYPE, .init = mach8_init, .close = mach_close, .reset = mach_reset, @@ -7465,7 +7465,7 @@ const device_t mach32_pci_device = { .name = "ATI Mach32 (PCI)", .internal_name = "mach32_pci", .flags = DEVICE_PCI, - .local = 2, + .local = ATI_68800_TYPE, .init = mach8_init, .close = mach_close, .reset = mach_reset, @@ -7479,7 +7479,7 @@ const device_t mach32_onboard_pci_device = { .name = "ATI Mach32 (PCI) On-Board", .internal_name = "mach32_pci_onboard", .flags = DEVICE_PCI, - .local = 2 | 0x100, + .local = ATI_68800_TYPE | 0x100, .init = mach8_init, .close = mach_close, .reset = mach_reset, From 860a9b0163aed2e49208250f2cc2c0ebacee8352 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 17:03:21 +0100 Subject: [PATCH 1104/1190] Apply CGA_CRTC enum to Plantronics Colorplus --- src/video/vid_colorplus.c | 49 ++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 7daba018e..48217765e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -147,7 +147,7 @@ colorplus_poll(void *priv) colorplus->cga.cgastat |= 1; colorplus->cga.linepos = 1; oldsc = colorplus->cga.sc; - if ((colorplus->cga.crtc[8] & 3) == 3) + if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7; if (colorplus->cga.cgadispon) { if (colorplus->cga.displine < colorplus->cga.firstline) { @@ -157,10 +157,10 @@ colorplus_poll(void *priv) colorplus->cga.lastline = colorplus->cga.displine; /* Left / right border */ for (c = 0; c < 8; c++) { - buffer32->line[colorplus->cga.displine][c] = buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16; + buffer32->line[colorplus->cga.displine][c] = buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16; } if (colorplus->control & COLORPLUS_320x200_MODE) { - for (x = 0; x < colorplus->cga.crtc[1]; x++) { + for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; x++) { dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; colorplus->cga.ma++; @@ -186,7 +186,7 @@ colorplus_poll(void *priv) cols[2] = col | 4; cols[3] = col | 6; } - for (x = 0; x < colorplus->cga.crtc[1]; x++) { + for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; x++) { dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; colorplus->cga.ma++; @@ -200,10 +200,10 @@ colorplus_poll(void *priv) } else /* Top / bottom border */ { cols[0] = (colorplus->cga.cgacol & 15) + 16; - hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]); } - x = (colorplus->cga.crtc[1] << 4) + 16; + x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; if (colorplus->cga.composite) Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]); @@ -211,7 +211,7 @@ colorplus_poll(void *priv) video_process_8(x, colorplus->cga.displine); colorplus->cga.sc = oldsc; - if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc) + if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC] && !colorplus->cga.sc) colorplus->cga.cgastat |= 8; colorplus->cga.displine++; if (colorplus->cga.displine >= 360) @@ -224,10 +224,11 @@ colorplus_poll(void *priv) if (!colorplus->cga.vsynctime) colorplus->cga.cgastat &= ~8; } - if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) { + if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) + || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { colorplus->cga.con = 0; } - if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1)) + if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) colorplus->cga.maback = colorplus->cga.ma; if (colorplus->cga.vadj) { colorplus->cga.sc++; @@ -236,41 +237,41 @@ colorplus_poll(void *priv) colorplus->cga.vadj--; if (!colorplus->cga.vadj) { colorplus->cga.cgadispon = 1; - colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; + colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; colorplus->cga.sc = 0; } - } else if (colorplus->cga.sc == colorplus->cga.crtc[9]) { + } else if (colorplus->cga.sc == colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { colorplus->cga.maback = colorplus->cga.ma; colorplus->cga.sc = 0; oldvc = colorplus->cga.vc; colorplus->cga.vc++; colorplus->cga.vc &= 127; - if (colorplus->cga.vc == colorplus->cga.crtc[6]) + if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VDISP]) colorplus->cga.cgadispon = 0; - if (oldvc == colorplus->cga.crtc[4]) { + if (oldvc == colorplus->cga.crtc[CGA_CRTC_VTOTAL]) { colorplus->cga.vc = 0; - colorplus->cga.vadj = colorplus->cga.crtc[5]; + colorplus->cga.vadj = colorplus->cga.crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1; if (!colorplus->cga.vadj) - colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; - if ((colorplus->cga.crtc[10] & 0x60) == 0x20) + colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + if ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) colorplus->cga.cursoron = 0; else colorplus->cga.cursoron = colorplus->cga.cgablink & 8; } - if (colorplus->cga.vc == colorplus->cga.crtc[7]) { + if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC]) { colorplus->cga.cgadispon = 0; colorplus->cga.displine = 0; colorplus->cga.vsynctime = 16; - if (colorplus->cga.crtc[7]) { + if (colorplus->cga.crtc[CGA_CRTC_VSYNC]) { if (colorplus->cga.cgamode & 1) - x = (colorplus->cga.crtc[1] << 3) + 16; + x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (colorplus->cga.crtc[1] << 4) + 16; + x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; colorplus->cga.lastline++; if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize) { xsize = x; @@ -289,11 +290,11 @@ colorplus_poll(void *priv) video_res_y = ysize; if (colorplus->cga.cgamode & 1) { video_res_x /= 8; - video_res_y /= colorplus->cga.crtc[9] + 1; + video_res_y /= colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; } else if (!(colorplus->cga.cgamode & 2)) { video_res_x /= 16; - video_res_y /= colorplus->cga.crtc[9] + 1; + video_res_y /= colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; } else if (!(colorplus->cga.cgamode & 16)) { video_res_x /= 2; @@ -314,10 +315,10 @@ colorplus_poll(void *priv) } if (colorplus->cga.cgadispon) colorplus->cga.cgastat &= ~1; - if (colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1))) + if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) colorplus->cga.con = 1; if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) { - for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++) + for (x = 0; x < (colorplus->cga.crtc[CGA_CRTC_HDISP] << 1); x++) colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.ma << 1) + x) & 0x3fff]; } } From 7bf7a84a83cd9b2dae68cd59eac49501847954ff Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 17:05:49 +0100 Subject: [PATCH 1105/1190] Missed one cga->cgamode --- 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 4a9a032c5..bfd03d03a 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -310,7 +310,7 @@ cga_render(cga_t *cga, int line) } cga->ma++; } - } else if (!(cga->cgamode & 2)) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { chr = cga->vram[(cga->ma << 1) & 0x3fff]; From d32a06d3059813636cdb7824f2bf0341c4fb7c09 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 17:16:01 +0100 Subject: [PATCH 1106/1190] Rename "con" to "cursorvisible" as it determines if the cursor is visible for the current scanline. --- src/include/86box/vid_cga.h | 2 +- src/machine/m_amstrad.c | 8 ++++---- src/video/vid_cga.c | 9 +++++---- src/video/vid_colorplus.c | 4 ++-- src/video/vid_compaq_cga.c | 8 ++++---- src/video/vid_nga.c | 8 ++++---- src/video/vid_ogc.c | 8 ++++---- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 2a36eeade..a84373d84 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -88,7 +88,7 @@ typedef struct cga_t { int sc; int vc; int cgadispon; - int con; + int cursorvisible; // Determines if the cursor is visible FOR THE CURRENT SCANLINE. int cursoron; int cgablink; int vsynctime; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 57e8367ff..b57eac60d 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -1423,7 +1423,7 @@ lcdc_poll(amsvid_t *vid) for (x = 0; x < cga->crtc[1]; x++) { chr = cga->charbuffer[x << 1]; attr = cga->charbuffer[(x << 1) + 1]; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); @@ -1433,7 +1433,7 @@ lcdc_poll(amsvid_t *vid) for (x = 0; x < cga->crtc[1]; x++) { chr = cga->vram[(cga->ma << 1) & 0x3fff]; attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); @@ -1479,7 +1479,7 @@ lcdc_poll(amsvid_t *vid) cga->cgastat &= ~8; } if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { - cga->con = 0; + cga->cursorvisible = 0; } if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) cga->maback = cga->ma; @@ -1580,7 +1580,7 @@ lcdc_poll(amsvid_t *vid) if (cga->cgadispon) cga->cgastat &= ~1; if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))) - cga->con = 1; + cga->cursorvisible = 1; if (cga->cgadispon && (cga->cgamode & 1)) { for (x = 0; x < (cga->crtc[1] << 1); x++) cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index bfd03d03a..0fb1a1402 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -289,7 +289,7 @@ cga_render(cga_t *cga, int line) attr = cga->charbuffer[(x << 1) + 1]; } else chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); cols[1] = (attr & 15) + 16; if (cga->cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; @@ -317,7 +317,7 @@ cga_render(cga_t *cga, int line) attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; } else chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); cols[1] = (attr & 15) + 16; if (cga->cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; @@ -594,7 +594,7 @@ cga_poll(void *priv) } if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { - cga->con = 0; + cga->cursorvisible = 0; } if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) cga->maback = cga->ma; @@ -625,6 +625,7 @@ cga_poll(void *priv) cga->cgadispon = 1; cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; } + switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) { case 0x20: cga->cursoron = 0; @@ -724,7 +725,7 @@ cga_poll(void *priv) cga->cgastat &= ~1; if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) - cga->con = 1; + cga->cursorvisible = 1; if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++) cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 48217765e..d15865c1e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -226,7 +226,7 @@ colorplus_poll(void *priv) } if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { - colorplus->cga.con = 0; + colorplus->cga.cursorvisible = 0; } if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) colorplus->cga.maback = colorplus->cga.ma; @@ -316,7 +316,7 @@ colorplus_poll(void *priv) if (colorplus->cga.cgadispon) colorplus->cga.cgastat &= ~1; if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) - colorplus->cga.con = 1; + colorplus->cga.cursorvisible = 1; if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) { for (x = 0; x < (colorplus->cga.crtc[CGA_CRTC_HDISP] << 1); x++) colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.ma << 1) + x) & 0x3fff]; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index f9fec32d0..80c6ecb9e 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -139,7 +139,7 @@ compaq_cga_poll(void *priv) for (x = 0; x < self->cga.crtc[1]; x++) { chr = self->cga.charbuffer[x << 1]; attr = self->cga.charbuffer[(x << 1) + 1]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); + drawcursor = ((self->cga.ma == ca) && self->cga.cursorvisible && self->cga.cursoron); if (vflags) { underline = 0; @@ -184,7 +184,7 @@ compaq_cga_poll(void *priv) for (x = 0; x < self->cga.crtc[1]; x++) { chr = self->cga.vram[(self->cga.ma << 1) & 0x3fff]; attr = self->cga.vram[((self->cga.ma << 1) + 1) & 0x3fff]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); + drawcursor = ((self->cga.ma == ca) && self->cga.cursorvisible && self->cga.cursoron); if (vflags) { underline = 0; @@ -268,7 +268,7 @@ compaq_cga_poll(void *priv) } if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { - self->cga.con = 0; + self->cga.cursorvisible = 0; } if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) self->cga.maback = self->cga.ma; @@ -386,7 +386,7 @@ compaq_cga_poll(void *priv) self->cga.cgastat &= ~1; if (self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))) - self->cga.con = 1; + self->cga.cursorvisible = 1; if (self->cga.cgadispon && (self->cga.cgamode & 1)) { for (x = 0; x < (self->cga.crtc[1] << 1); x++) diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 5fc81109c..7a30bf173 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -197,7 +197,7 @@ nga_poll(void *priv) } else chr = attr = 0; /* check if cursor has to be drawn */ - drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron); + drawcursor = ((nga->cga.ma == ca) && nga->cga.cursorvisible && nga->cga.cursoron); /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ @@ -233,7 +233,7 @@ nga_poll(void *priv) } else { chr = attr = 0; } - drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron); + drawcursor = ((nga->cga.ma == ca) && nga->cga.cursorvisible && nga->cga.cursoron); /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ @@ -391,7 +391,7 @@ nga_poll(void *priv) } /* cursor stop scanline */ if (nga->cga.sc == (nga->cga.crtc[11] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[11] & 31) >> 1))) { - nga->cga.con = 0; + nga->cga.cursorvisible = 0; } /* interlaced and max scanline per char reached */ if ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1)) @@ -524,7 +524,7 @@ nga_poll(void *priv) /* enable cursor if its scanline was reached */ if (nga->cga.sc == (nga->cga.crtc[10] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[10] & 31) >> 1))) - nga->cga.con = 1; + nga->cga.cursorvisible = 1; } /* 80-columns */ if (nga->cga.cgadispon && (nga->cga.cgamode & 1)) { diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index 162cb9073..afbc778a6 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -252,7 +252,7 @@ ogc_poll(void *priv) } else chr = attr = 0; /* check if cursor has to be drawn */ - drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron); + drawcursor = ((ogc->cga.ma == ca) && ogc->cga.cursorvisible && ogc->cga.cursoron); /* check if character underline mode should be set */ underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); if (underline) { @@ -301,7 +301,7 @@ ogc_poll(void *priv) } else { chr = attr = 0; } - drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron); + drawcursor = ((ogc->cga.ma == ca) && ogc->cga.cursorvisible && ogc->cga.cursoron); /* check if character underline mode should be set */ underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); if (underline) { @@ -406,7 +406,7 @@ ogc_poll(void *priv) ogc->cga.cgastat &= ~8; } if (ogc->cga.sc == (ogc->cga.crtc[11] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[11] & 31) >> 1))) { - ogc->cga.con = 0; + ogc->cga.cursorvisible = 0; } if ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1)) ogc->cga.maback = ogc->cga.ma; @@ -525,7 +525,7 @@ ogc_poll(void *priv) ogc->cga.cgastat &= ~1; if (ogc->cga.sc == (ogc->cga.crtc[10] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[10] & 31) >> 1))) - ogc->cga.con = 1; + ogc->cga.cursorvisible = 1; } /* 80-columns */ if (ogc->cga.cgadispon && (ogc->cga.cgamode & 1)) { From b19240a168b535a7011a6eb72627278aa91c81c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= <oubattler@gmail.com> Date: Mon, 9 Jun 2025 18:22:14 +0200 Subject: [PATCH 1107/1190] Windows hook: do not block anything if keyboard requires capture and it is not captured. --- src/qt/qt_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 3f8476374..72c892af7 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -214,7 +214,7 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) (GetForegroundWindow() == ((HWND) secondaryRenderer->winId()))); } - bool skip = ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window); + bool skip = ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window || (kbd_req_capture && !mouse_capture)); if (skip) return CallNextHookEx(NULL, nCode, wParam, lParam); From a042925efe3e3918b760b0c6a82509af74eeb790 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Mon, 9 Jun 2025 18:30:50 +0200 Subject: [PATCH 1108/1190] Tulip jumper device. --- src/device/CMakeLists.txt | 1 + src/device/tulip_jumper.c | 103 ++++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 2 + 3 files changed, 106 insertions(+) create mode 100644 src/device/tulip_jumper.c diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index ea89f5cd9..29fc0b9b4 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -57,6 +57,7 @@ add_library(dev OBJECT smbus_ali7101.c smbus_piix4.c smbus_sis5595.c + tulip_jumper.c unittester.c ) diff --git a/src/device/tulip_jumper.c b/src/device/tulip_jumper.c new file mode 100644 index 000000000..1974129e3 --- /dev/null +++ b/src/device/tulip_jumper.c @@ -0,0 +1,103 @@ +/* + * 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. + * + * Implementation of the Tulip Jumper Readout. + * + * Bits 7-5 = board number, 0-5 valid, 6, 7 invalid. + * + * Authors: Miran Grca, <mgrca8@gmail.com> + * + * Copyright 2025 Miran Grca. + */ +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/sound.h> +#include <86box/chipset.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> + +typedef struct tulip_jumper_t { + uint8_t jumper; +} tulip_jumper_t; + +#ifdef ENABLE_TULIP_JUMPER_LOG +int tulip_jumper_do_log = ENABLE_TULIP_JUMPER_LOG; + +static void +tulip_jumper_log(const char *fmt, ...) +{ + va_list ap; + + if (tulip_jumper_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define tulip_jumper_log(fmt, ...) +#endif + +static uint8_t +tulip_jumper_read(uint16_t addr, void *priv) +{ + const tulip_jumper_t *dev = (tulip_jumper_t *) priv; + uint8_t ret = 0xff; + + tulip_jumper_log("Tulip Jumper: Read %02x\n", dev->jumper); + + ret = dev->jumper; + + return ret; +} + +static void +tulip_jumper_close(void *priv) +{ + tulip_jumper_t *dev = (tulip_jumper_t *) priv; + + free(dev); +} + +static void * +tulip_jumper_init(const device_t *info) +{ + tulip_jumper_t *dev = (tulip_jumper_t *) calloc(1, sizeof(tulip_jumper_t)); + + /* Return board number 05. */ + dev->jumper = 0xbf; + + io_sethandler(0x0d80, 0x0001, tulip_jumper_read, NULL, NULL, NULL, NULL, NULL, dev); + + return dev; +} + +const device_t tulip_jumper_device = { + .name = "Tulip Jumper Readout", + .internal_name = "tulip_jumper", + .flags = 0, + .local = 0, + .init = tulip_jumper_init, + .close = tulip_jumper_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index e0e775fa1..1b5684414 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -201,6 +201,8 @@ extern const device_t vlsi_scamp_device; extern const device_t wd76c10_device; /* Miscellaneous Hardware */ +extern const device_t tulip_jumper_device; + extern const device_t dell_jumper_device; extern const device_t nec_mate_unk_device; From c3bb3002c1441b5415da93d8b66ee0b1f3d10e64 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Mon, 9 Jun 2025 18:43:52 +0200 Subject: [PATCH 1109/1190] Added the Tulip TC-38. --- src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 39 +++++++++++++++++++++++++++++++++-- src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 85b55ae51..fe109150b 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -548,6 +548,7 @@ extern int machine_at_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); +extern int machine_at_tuliptc38_init(const machine_t *); extern int machine_at_martin_init(const machine_t *); extern int machine_at_403tg_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index b81a6bda7..cc6c9cfc8 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -413,7 +413,7 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems return ret; if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5428_onboard_device); + device_add(machine_get_vid_device(machine)); machine_at_common_init_ex(model, 2); @@ -439,7 +439,7 @@ machine_at_d824_init(const machine_t *model) return ret; if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5428_onboard_device); + device_add(machine_get_vid_device(machine)); machine_at_common_init_ex(model, 2); @@ -457,6 +457,41 @@ machine_at_d824_init(const machine_t *model) return ret; } +int +machine_at_tuliptc38_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tuliptc38/TULIP1.BIN", + 0x000f0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + device_add(&vl82c486_device); + device_add(&tulip_jumper_device); + + device_add(&vl82c113_device); + + device_add(&ide_isa_device); + device_add(&fdc37c651_ide_device); + + if (gfxcard[0] == VID_INTERNAL) { + bios_load_aux_linear("roms/machines/tuliptc38/VBIOS.BIN", + 0x000c0000, 32768, 0); + + device_add(machine_get_vid_device(machine)); + } else for (uint16_t i = 0; i < 32768; i++) + rom[i] = mem_readb_phys(0x000c0000 + i); + + mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000); + mem_mapping_set_exec(&bios_mapping, rom); + + return ret; +} + int machine_at_martin_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c90cbf0bb..ce1e5836a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6646,6 +6646,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ + { + .name = "[VLSI 82C486] Tulip 486 DC/DT", + .internal_name = "tuliptc38", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_VLSI_VL82C486, + .init = machine_at_tuliptc38_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 32768, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ + .vid_device = &gd5426_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ { .name = "[MCA] IBM PS/2 model 70 (type 4)", From 8e72150fa334c6eb8965570246b159598c53b91c Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Mon, 9 Jun 2025 19:26:17 +0200 Subject: [PATCH 1110/1190] Sanitize the Compaq CGA code. --- src/video/vid_compaq_cga.c | 388 +++++++++++++++++++------------------ 1 file changed, 200 insertions(+), 188 deletions(-) diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index f9fec32d0..5b06e23d2 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -44,10 +44,6 @@ static uint32_t vflags; static uint8_t mdaattr[256][2][2]; -typedef struct compaq_cga_t { - cga_t cga; -} compaq_cga_t; - #ifdef ENABLE_COMPAQ_CGA_LOG int compaq_cga_do_log = ENABLE_COMPAQ_CGA_LOG; @@ -66,93 +62,93 @@ compaq_cga_log(const char *fmt, ...) # define compaq_cga_log(fmt, ...) #endif -void -compaq_cga_recalctimings(compaq_cga_t *self) +static void +compaq_cga_recalctimings(cga_t *dev) { double _dispontime; double _dispofftime; double disptime; - disptime = self->cga.crtc[0] + 1; + disptime = dev->crtc[0] + 1; - _dispontime = self->cga.crtc[1]; + _dispontime = dev->crtc[1]; _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - self->cga.dispontime = (uint64_t) (_dispontime); - self->cga.dispofftime = (uint64_t) (_dispofftime); + dev->dispontime = (uint64_t) (_dispontime); + dev->dispofftime = (uint64_t) (_dispofftime); } -void +static void compaq_cga_poll(void *priv) { - compaq_cga_t *self = (compaq_cga_t *) priv; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x; - int c; - int xs_temp; - int ys_temp; - int oldvc; - uint8_t chr; - uint8_t attr; - uint8_t border; - uint8_t cols[4]; - int oldsc; - int underline = 0; - int blink = 0; + cga_t *dev = (cga_t *) priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int underline = 0; + int blink = 0; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint8_t border; + uint8_t cols[4]; + int oldsc; /* If in graphics mode or character height is not 13, behave as CGA */ - if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) { + if ((dev->cgamode & 0x12) || (dev->crtc[9] != 13)) { overscan_x = overscan_y = 16; - cga_poll(&self->cga); + cga_poll(dev); return; } else overscan_x = overscan_y = 0; /* We are in Compaq 350-line CGA territory */ - if (!self->cga.linepos) { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - oldsc = self->cga.sc; - if ((self->cga.crtc[8] & 3) == 3) - self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; - if (self->cga.cgadispon) { - if (self->cga.displine < self->cga.firstline) { - self->cga.firstline = self->cga.displine; + if (!dev->linepos) { + timer_advance_u64(&dev->timer, dev->dispofftime); + dev->cgastat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = ((dev->sc << 1) + dev->oddeven) & 7; + if (dev->cgadispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; video_wait_for_buffer(); - compaq_cga_log("Firstline %i\n", self->cga.firstline); + compaq_cga_log("Firstline %i\n", dev->firstline); } - self->cga.lastline = self->cga.displine; + dev->lastline = dev->displine; - cols[0] = (self->cga.cgacol & 15) + 16; + cols[0] = (dev->cgacol & 15) + 16; for (c = 0; c < 8; c++) { - buffer32->line[self->cga.displine][c] = cols[0]; - if (self->cga.cgamode & 1) - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0]; + buffer32->line[dev->displine][c] = cols[0]; + if (dev->cgamode & 1) + buffer32->line[dev->displine][c + (dev->crtc[1] << 3) + 8] = cols[0]; else - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0]; + buffer32->line[dev->displine][c + (dev->crtc[1] << 4) + 8] = cols[0]; } - if (self->cga.cgamode & 1) { - for (x = 0; x < self->cga.crtc[1]; x++) { - chr = self->cga.charbuffer[x << 1]; - attr = self->cga.charbuffer[(x << 1) + 1]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); + if (dev->cgamode & 1) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->charbuffer[x << 1]; + attr = dev->charbuffer[(x << 1) + 1]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); if (vflags) { underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((dev->cgablink & 8) && (dev->cgamode & 0x20) && (attr & 0x80) && !drawcursor); } - if (vflags && (self->cga.cgamode & 0x80)) { + if (vflags && (dev->cgamode & 0x80)) { cols[0] = mdaattr[attr][blink][0]; cols[1] = mdaattr[attr][blink][1]; - if ((self->cga.sc == 12) && ((attr & 7) == 1)) + if ((dev->sc == 12) && ((attr & 7) == 1)) underline = 1; - } else if (self->cga.cgamode & 0x20) { + } else if (dev->cgamode & 0x20) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -160,7 +156,7 @@ compaq_cga_poll(void *priv) if (blink) cols[1] = cols[0]; } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) + if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor) cols[1] = cols[0]; } } else { @@ -170,33 +166,35 @@ compaq_cga_poll(void *priv) if (vflags && underline) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; + buffer32->line[dev->displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[dev->displine][(x << 3) + c + 8] = + cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[dev->displine][(x << 3) + c + 8] = + cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; } - self->cga.ma++; + dev->ma++; } } else { - for (x = 0; x < self->cga.crtc[1]; x++) { - chr = self->cga.vram[(self->cga.ma << 1) & 0x3fff]; - attr = self->cga.vram[((self->cga.ma << 1) + 1) & 0x3fff]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); if (vflags) { underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((dev->cgablink & 8) && (dev->cgamode & 0x20) && (attr & 0x80) && !drawcursor); } - if (vflags && (self->cga.cgamode & 0x80)) { + if (vflags && (dev->cgamode & 0x80)) { cols[0] = mdaattr[attr][blink][0]; cols[1] = mdaattr[attr][blink][1]; - if (self->cga.sc == 12 && (attr & 7) == 1) + if (dev->sc == 12 && (attr & 7) == 1) underline = 1; - } else if (self->cga.cgamode & 0x20) { + } else if (dev->cgamode & 0x20) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -204,128 +202,134 @@ compaq_cga_poll(void *priv) if (blink) cols[1] = cols[0]; } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) + if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor) cols[1] = cols[0]; } } else { cols[1] = (attr & 15) + 16; cols[0] = (attr >> 4) + 16; } - self->cga.ma++; + dev->ma++; if (vflags && underline) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 9] = mdaattr[attr][blink][1]; + buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] = + buffer32->line[dev->displine][(x << 4) + (c << 1) + 9] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] = + buffer32->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] = + buffer32->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; } } } } else { - cols[0] = (self->cga.cgacol & 15) + 16; + cols[0] = (dev->cgacol & 15) + 16; - if (self->cga.cgamode & 1) - hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); + if (dev->cgamode & 1) + hline(buffer32, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); else - hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); } - if (self->cga.cgamode & 1) - x = (self->cga.crtc[1] << 3) + 16; + if (dev->cgamode & 1) + x = (dev->crtc[1] << 3) + 16; else - x = (self->cga.crtc[1] << 4) + 16; + x = (dev->crtc[1] << 4) + 16; - if (self->cga.composite) { - if (self->cga.cgamode & 0x10) + if (dev->composite) { + if (dev->cgamode & 0x10) border = 0x00; else - border = self->cga.cgacol & 0x0f; + border = dev->cgacol & 0x0f; if (vflags) - Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]); + Composite_Process(dev->cgamode & 0x7f, border, x >> 2, buffer32->line[dev->displine]); else - Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]); + Composite_Process(dev->cgamode, border, x >> 2, buffer32->line[dev->displine]); } else - video_process_8(x, self->cga.displine); + video_process_8(x, dev->displine); - self->cga.sc = oldsc; - if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) - self->cga.cgastat |= 8; - self->cga.displine++; - if (self->cga.displine >= 500) - self->cga.displine = 0; + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->cgastat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; } else { - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - self->cga.linepos = 0; - if (self->cga.vsynctime) { - self->cga.vsynctime--; - if (!self->cga.vsynctime) - self->cga.cgastat &= ~8; + timer_advance_u64(&dev->timer, dev->dispontime); + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) + dev->cgastat &= ~8; } - if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { - self->cga.con = 0; + if (dev->sc == (dev->crtc[11] & 31) || (((dev->crtc[8] & 3) == 3) && + (dev->sc == ((dev->crtc[11] & 31) >> 1)))) { + dev->con = 0; } - if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) - self->cga.maback = self->cga.ma; - if (self->cga.vadj) { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - self->cga.vadj--; - if (!self->cga.vadj) { - self->cga.cgadispon = 1; - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - self->cga.sc = 0; + if ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1)) + dev->maback = dev->ma; + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->cgadispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; } - } else if (self->cga.sc == self->cga.crtc[9]) { - self->cga.maback = self->cga.ma; - self->cga.sc = 0; - oldvc = self->cga.vc; - self->cga.vc++; - self->cga.vc &= 127; + } else if (dev->sc == dev->crtc[9]) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; - if (self->cga.vc == self->cga.crtc[6]) - self->cga.cgadispon = 0; + if (dev->vc == dev->crtc[6]) + dev->cgadispon = 0; - if (oldvc == self->cga.crtc[4]) { - self->cga.vc = 0; - self->cga.vadj = self->cga.crtc[5]; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; - if (!self->cga.vadj) - self->cga.cgadispon = 1; + if (!dev->vadj) + dev->cgadispon = 1; - if (!self->cga.vadj) - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + if (!dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - if ((self->cga.crtc[10] & 0x60) == 0x20) - self->cga.cursoron = 0; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; else - self->cga.cursoron = self->cga.cgablink & 8; + dev->cursoron = dev->cgablink & 8; } - if (self->cga.vc == self->cga.crtc[7]) { - self->cga.cgadispon = 0; - self->cga.displine = 0; - self->cga.vsynctime = 16; + if (dev->vc == dev->crtc[7]) { + dev->cgadispon = 0; + dev->displine = 0; + dev->vsynctime = 16; - if (self->cga.crtc[7]) { - compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline, - self->cga.firstline, self->cga.lastline - self->cga.firstline); + if (dev->crtc[7]) { + compaq_cga_log("Lastline %i Firstline %i %i\n", dev->lastline, + dev->firstline, dev->lastline - dev->firstline); - if (self->cga.cgamode & 1) - x = (self->cga.crtc[1] << 3) + 16; + if (dev->cgamode & 1) + x = (dev->crtc[1] << 3) + 16; else - x = (self->cga.crtc[1] << 4) + 16; + x = (dev->crtc[1] << 4) + 16; - self->cga.lastline++; + dev->lastline++; xs_temp = x; - ys_temp = (self->cga.lastline - self->cga.firstline); + ys_temp = (dev->lastline - dev->firstline); if ((xs_temp > 0) && (ys_temp > 0)) { if (xs_temp < 64) @@ -335,7 +339,8 @@ compaq_cga_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + if ((dev->cgamode & 8) && ((xs_temp != xsize) || + (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); @@ -345,9 +350,9 @@ compaq_cga_poll(void *priv) } if (enable_overscan) - video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); + video_blit_memtoscreen(0, dev->firstline - 8, xsize, (dev->lastline - dev->firstline) + 16); else - video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); + video_blit_memtoscreen(8, dev->firstline, xsize, dev->lastline - dev->firstline); } frames++; @@ -356,63 +361,69 @@ compaq_cga_poll(void *priv) if (enable_overscan) xsize -= 16; video_res_y = ysize; - if (self->cga.cgamode & 1) { + if (dev->cgamode & 1) { video_res_x /= 8; - video_res_y /= self->cga.crtc[9] + 1; + video_res_y /= dev->crtc[9] + 1; video_bpp = 0; - } else if (!(self->cga.cgamode & 2)) { + } else if (!(dev->cgamode & 2)) { video_res_x /= 16; - video_res_y /= self->cga.crtc[9] + 1; + video_res_y /= dev->crtc[9] + 1; video_bpp = 0; - } else if (!(self->cga.cgamode & 16)) { + } else if (!(dev->cgamode & 16)) { video_res_x /= 2; video_bpp = 2; } else video_bpp = 1; } - self->cga.firstline = 1000; - self->cga.lastline = 0; - self->cga.cgablink++; - self->cga.oddeven ^= 1; + dev->firstline = 1000; + dev->lastline = 0; + dev->cgablink++; + dev->oddeven ^= 1; } } else { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; } - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; + if (dev->cgadispon) + dev->cgastat &= ~1; - if (self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))) - self->cga.con = 1; + if (dev->sc == (dev->crtc[10] & 31) || + (((dev->crtc[8] & 3) == 3) && (dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; - if (self->cga.cgadispon && (self->cga.cgamode & 1)) { - for (x = 0; x < (self->cga.crtc[1] << 1); x++) - self->cga.charbuffer[x] = self->cga.vram[((self->cga.ma << 1) + x) & 0x3fff]; + if (dev->cgadispon && (dev->cgamode & 1)) { + for (x = 0; x < (dev->crtc[1] << 1); x++) + dev->charbuffer[x] = dev->vram[((dev->ma << 1) + x) & 0x3fff]; } } } -void * +static void * compaq_cga_init(const device_t *info) { - int display_type; - compaq_cga_t *self = malloc(sizeof(compaq_cga_t)); - memset(self, 0, sizeof(compaq_cga_t)); + int display_type; + cga_t *dev = calloc(1, sizeof(cga_t)); - display_type = device_get_config_int("display_type"); - self->cga.composite = (display_type != CGA_RGB); - self->cga.revision = device_get_config_int("composite_type"); - self->cga.snow_enabled = device_get_config_int("snow_enabled"); + display_type = device_get_config_int("display_type"); + dev->composite = (display_type != CGA_RGB); + dev->revision = device_get_config_int("composite_type"); + dev->snow_enabled = device_get_config_int("snow_enabled"); - self->cga.vram = malloc(0x4000); + dev->vram = malloc(0x4000); - cga_comp_init(self->cga.revision); - timer_add(&self->cga.timer, compaq_cga_poll, self, 1); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); - io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); + cga_comp_init(dev->revision); + timer_add(&dev->timer, compaq_cga_poll, dev, 1); + mem_mapping_add(&dev->mapping, 0xb8000, 0x08000, + cga_read, NULL, NULL, + cga_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + io_sethandler(0x03d0, 0x0010, + cga_in, NULL, NULL, + cga_out, NULL, NULL, + dev); if (info->local) { for (uint16_t c = 0; c < 256; c++) { @@ -441,33 +452,34 @@ compaq_cga_init(const device_t *info) overscan_x = overscan_y = 16; - self->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (self->cga.rgb_type << 1); + dev->rgb_type = device_get_config_int("rgb_type"); + cga_palette = (dev->rgb_type << 1); cgapal_rebuild(); - self->cga.crtc[9] = 13; + dev->crtc[9] = 13; - return self; + return dev; } -void +static void compaq_cga_close(void *priv) { - compaq_cga_t *self = (compaq_cga_t *) priv; + cga_t *dev = (cga_t *) priv; - free(self->cga.vram); - free(self); + free(dev->vram); + free(dev); } -void +static void compaq_cga_speed_changed(void *priv) { - compaq_cga_t *self = (compaq_cga_t *) priv; + cga_t *dev = (cga_t *) priv; - if (self->cga.crtc[9] == 13) /* Character height */ - compaq_cga_recalctimings(self); + if (dev->crtc[9] == 13) + /* Character height */ + compaq_cga_recalctimings(dev); else - cga_recalctimings(&self->cga); + cga_recalctimings(dev); } extern const device_config_t cga_config[]; From 95194556f82ce5d445d8fe15cdb7826460ef5749 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Mon, 9 Jun 2025 19:34:58 +0200 Subject: [PATCH 1111/1190] Added the BIOSTAR MB-84xxUUD-A. --- src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 29 +++++++++++++++++++++++++ src/machine/machine_table.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fe109150b..7aec5db4f 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -613,6 +613,7 @@ extern int machine_at_iach488_init(const machine_t *); extern int machine_at_pcm9340_init(const machine_t *); extern int machine_at_pcm5330_init(const machine_t *); +extern int machine_at_84xxuuda_init(const machine_t *); extern int machine_at_ecs486_init(const machine_t *); extern int machine_at_hot433a_init(const machine_t *); extern int machine_at_pl4600c_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index cc6c9cfc8..a43d5ea63 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2262,6 +2262,35 @@ machine_at_hot433a_init(const machine_t *model) return ret; } +int +machine_at_84xxuuda_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/84xxuuda/uud0520s.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&umc_hb4_device); + device_add(&umc_8886bf_device); + device_add(&um8663bf_device); + device_add(&winbond_flash_w29c010_device); + device_add(&keyboard_ps2_ami_device); + + return ret; +} + int machine_at_pl4600c_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index ce1e5836a..4f907ce10 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9117,6 +9117,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has the UMC 88xx on-chip KBC. All the copies of the BIOS string I can find, end in + in -H, so the UMC on-chip KBC likely emulates the AMI 'H' KBC firmware. */ + { + .name = "[UMC 8881] Biostar MB-84xxUUD-A", + .internal_name = "84xxuuda", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_84xxuuda_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_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .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 + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[UMC 8881] ECS Elite UM8810P-AIO", From b7e6248db9bce8852b1f973635d11a8ea8906965 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 19:26:40 +0100 Subject: [PATCH 1112/1190] Apply CGA_CRTC and CGA_MODE_FLAGS to the rest of the Super CGA crew. --- src/include/86box/vid_cga.h | 1 + src/machine/m_amstrad.c | 110 +++++++++++++++++----------------- src/machine/m_at_compaq.c | 20 +++---- src/machine/m_at_t3100e_vid.c | 44 +++++++------- src/machine/m_elt.c | 6 +- src/machine/m_xt_olivetti.c | 2 +- src/machine/m_xt_t1000_vid.c | 40 ++++++------- src/video/vid_cga.c | 2 +- src/video/vid_cga_comp.c | 4 +- src/video/vid_colorplus.c | 12 ++-- src/video/vid_compaq_cga.c | 96 ++++++++++++++--------------- src/video/vid_f82c425.c | 20 +++---- src/video/vid_nga.c | 106 ++++++++++++++++---------------- src/video/vid_ogc.c | 96 ++++++++++++++--------------- 14 files changed, 280 insertions(+), 279 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index a84373d84..7f68286e5 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -56,6 +56,7 @@ typedef enum cga_crtc_registers_e CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, // Light pen address low 8 bits (not currently supported) } cga_crtc_registers; +// Registers for the CGA typedef enum cga_registers_e { CGA_REGISTER_CRTC_INDEX = 0x3D4, diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index b57eac60d..af6c50bc9 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -369,26 +369,26 @@ vid_poll_1512(void *priv) for (c = 0; c < 8; c++) { if ((vid->cgamode & 0x12) == 0x12) { buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->border & 15) + 16; - if (vid->cgamode & 1) { + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; } else { buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; } } else { buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) { + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16; } else { buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16; } } } - if (vid->cgamode & 1) { + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { for (x = 0; x < 80; x++) { chr = vid->vram[(vid->ma << 1) & 0x3fff]; attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { + if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) @@ -408,12 +408,12 @@ vid_poll_1512(void *priv) } vid->ma++; } - } else if (!(vid->cgamode & 2)) { + } else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) { for (x = 0; x < 40; x++) { chr = vid->vram[(vid->ma << 1) & 0x3fff]; attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { + if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; if ((vid->blink & 16) && (attr & 0x80)) @@ -433,10 +433,10 @@ vid_poll_1512(void *priv) } } } - } else if (!(vid->cgamode & 16)) { + } else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { cols[0] = (vid->cgacol & 15) | 16; col = (vid->cgacol & 16) ? 24 : 16; - if (vid->cgamode & 4) { + if (vid->cgamode & CGA_MODE_FLAG_BW) { cols[1] = col | 3; cols[2] = col | 4; cols[3] = col | 7; @@ -477,7 +477,7 @@ vid_poll_1512(void *priv) } } else { cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) { + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); } else { @@ -486,7 +486,7 @@ vid_poll_1512(void *priv) } } - if (vid->cgamode & 1) + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) x = (vid->crtc[1] << 3) + 16; else x = (vid->crtc[1] << 4) + 16; @@ -545,7 +545,7 @@ vid_poll_1512(void *priv) vid->displine = 0; vid->vsynctime = 46; - if (vid->cgamode & 1) + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) x = (vid->crtc[1] << 3) + 16; else x = (vid->crtc[1] << 4) + 16; @@ -582,15 +582,15 @@ vid_poll_1512(void *priv) video_res_x = xsize; video_res_y = ysize; - if (vid->cgamode & 1) { + if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; video_res_y /= vid->crtc[9] + 1; video_bpp = 0; - } else if (!(vid->cgamode & 2)) { + } else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; video_res_y /= vid->crtc[9] + 1; video_bpp = 0; - } else if (!(vid->cgamode & 16)) { + } else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { video_res_x /= 2; video_bpp = 2; } else { @@ -1403,14 +1403,14 @@ lcdc_poll(amsvid_t *vid) uint16_t ca; int blink; - ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; + ca = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; if (!cga->linepos) { timer_advance_u64(&vid->timer, cga->dispofftime); cga->cgastat |= 1; cga->linepos = 1; oldsc = cga->sc; - if ((cga->crtc[8] & 3) == 3) + if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3) cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; if (cga->cgadispon) { if (cga->displine < cga->firstline) { @@ -1419,28 +1419,28 @@ lcdc_poll(amsvid_t *vid) } cga->lastline = cga->displine; - if (cga->cgamode & 1) { - for (x = 0; x < cga->crtc[1]; x++) { + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { chr = cga->charbuffer[x << 1]; attr = cga->charbuffer[(x << 1) + 1]; drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); - blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); cga->ma++; } - } else if (!(cga->cgamode & 2)) { - for (x = 0; x < cga->crtc[1]; x++) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) { + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { chr = cga->vram[(cga->ma << 1) & 0x3fff]; attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); - blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); cga->ma++; } } else { /* Graphics mode */ - for (x = 0; x < cga->crtc[1]; x++) { + for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; cga->ma++; for (uint8_t c = 0; c < 16; c++) { @@ -1450,22 +1450,22 @@ lcdc_poll(amsvid_t *vid) } } } else { - if (cga->cgamode & 1) { - hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 3), green); - hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 3), green); + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { + hline(buffer32, 0, (cga->displine << 1), (cga->crtc[CGA_CRTC_HDISP] << 3), green); + hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[CGA_CRTC_HDISP] << 3), green); } else { - hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 4), green); - hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 4), green); + hline(buffer32, 0, (cga->displine << 1), (cga->crtc[CGA_CRTC_HDISP] << 4), green); + hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[CGA_CRTC_HDISP] << 4), green); } } - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3); + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + x = (cga->crtc[CGA_CRTC_HDISP] << 3); else - x = (cga->crtc[1] << 4); + x = (cga->crtc[CGA_CRTC_HDISP] << 4); cga->sc = oldsc; - if (cga->vc == cga->crtc[7] && !cga->sc) + if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->sc) cga->cgastat |= 8; cga->displine++; if (cga->displine >= 360) @@ -1478,10 +1478,10 @@ lcdc_poll(amsvid_t *vid) if (!cga->vsynctime) cga->cgastat &= ~8; } - if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { + if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { cga->cursorvisible = 0; } - if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) + if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) cga->maback = cga->ma; if (cga->vadj) { cga->sc++; @@ -1490,41 +1490,41 @@ lcdc_poll(amsvid_t *vid) cga->vadj--; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; cga->sc = 0; } - } else if (cga->sc == cga->crtc[9]) { + } else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { cga->maback = cga->ma; cga->sc = 0; oldvc = cga->vc; cga->vc++; cga->vc &= 127; - if (cga->vc == cga->crtc[6]) + if (cga->vc == cga->crtc[CGA_CRTC_VDISP]) cga->cgadispon = 0; - if (oldvc == cga->crtc[4]) { + if (oldvc == cga->crtc[CGA_CRTC_VTOTAL]) { cga->vc = 0; - cga->vadj = cga->crtc[5]; + cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!cga->vadj) cga->cgadispon = 1; if (!cga->vadj) - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - if ((cga->crtc[10] & 0x60) == 0x20) + cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + if ((cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cga->cursoron = 0; else cga->cursoron = cga->cgablink & 8; } - if (cga->vc == cga->crtc[7]) { + if (cga->vc == cga->crtc[CGA_CRTC_VSYNC]) { cga->cgadispon = 0; cga->displine = 0; cga->vsynctime = 16; - if (cga->crtc[7]) { - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3); + if (cga->crtc[CGA_CRTC_VSYNC]) { + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) + x = (cga->crtc[CGA_CRTC_HDISP] << 3); else - x = (cga->crtc[1] << 4); + x = (cga->crtc[CGA_CRTC_HDISP] << 4); cga->lastline++; xs_temp = x; @@ -1536,7 +1536,7 @@ lcdc_poll(amsvid_t *vid) if (ys_temp < 32) ys_temp = 400; - if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + if ((cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; set_screen_size(xsize, ysize); @@ -1553,15 +1553,15 @@ lcdc_poll(amsvid_t *vid) video_res_x = xsize; video_res_y = ysize; - if (cga->cgamode & 1) { + if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; - video_res_y /= cga->crtc[9] + 1; + video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(cga->cgamode & 2)) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; - video_res_y /= cga->crtc[9] + 1; + video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(cga->cgamode & 16)) { + } else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { video_res_x /= 2; video_bpp = 2; } else @@ -1579,10 +1579,10 @@ lcdc_poll(amsvid_t *vid) } if (cga->cgadispon) cga->cgastat &= ~1; - if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))) + if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) cga->cursorvisible = 1; - if (cga->cgadispon && (cga->cgamode & 1)) { - for (x = 0; x < (cga->crtc[1] << 1); x++) + if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) { + for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++) cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; } } diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 1f5ecdb58..aaa22ffc0 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -276,8 +276,8 @@ compaq_plasma_poll(void *priv) uint8_t chr; uint8_t attr; uint8_t sc; - uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x7fff; + uint16_t ma = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t ca = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; uint16_t addr; int drawcursor; int cursorline; @@ -321,10 +321,10 @@ compaq_plasma_poll(void *priv) addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; ma += (self->cga.displine >> 4) * 80; - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cursorline = 0; else - cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); /* for each text column */ for (x = 0; x < 80; x++) { @@ -352,7 +352,7 @@ compaq_plasma_poll(void *priv) /* set foreground */ cols[1] = blinkcols[attr][1]; /* blink active */ - if (self->cga.cgamode & 0x20) { + if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = blinkcols[attr][0]; /* attribute 7 active and not cursor */ if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { @@ -406,10 +406,10 @@ compaq_plasma_poll(void *priv) addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; ma += (self->cga.displine >> 4) * 40; - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cursorline = 0; else - cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); for (x = 0; x < 40; x++) { /* video output enabled */ @@ -436,7 +436,7 @@ compaq_plasma_poll(void *priv) /* set foreground */ cols[1] = blinkcols[attr][1]; /* blink active */ - if (self->cga.cgamode & 0x20) { + if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = blinkcols[attr][0]; /* attribute 7 active and not cursor */ if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { @@ -485,7 +485,7 @@ compaq_plasma_poll(void *priv) ma++; } } else { - if (self->cga.cgamode & 0x10) { + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { /* 640x400 mode */ if (self->port_23c6 & 0x01) /* 640*400 */ { addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); @@ -589,7 +589,7 @@ compaq_plasma_poll(void *priv) video_res_y = 400; if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) video_bpp = 1; else video_bpp = 2; diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index c827a05e5..0346fccd4 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -255,24 +255,24 @@ t3100e_text_row80(t3100e_t *t3100e) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t ca = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; sc = (t3100e->displine) & 15; addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; ma += (t3100e->displine >> 4) * 80; - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) { + if ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t3100e->cga.crtc[10] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[11] & 0x0F) * 2 >= sc); + cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= sc); } for (uint8_t x = 0; x < 80; x++) { chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); + drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16)); - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); if (t3100e->video_options & 4) bold = boldcols[attr] ? chr + 256 : chr; @@ -280,7 +280,7 @@ t3100e_text_row80(t3100e_t *t3100e) bold = boldcols[attr] ? chr : chr + 256; bold += 512 * (t3100e->video_options & 3); - if (t3100e->cga.cgamode & 0x20) /* Blink */ + if (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */ { cols[1] = blinkcols[attr][1]; cols[0] = blinkcols[attr][0]; @@ -316,24 +316,24 @@ t3100e_text_row40(t3100e_t *t3100e) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t ca = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; sc = (t3100e->displine) & 15; addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; ma += (t3100e->displine >> 4) * 40; - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) { + if ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t3100e->cga.crtc[10] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[11] & 0x0F) * 2 >= sc); + cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= sc); } for (uint8_t x = 0; x < 40; x++) { chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); + drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16)); - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); if (t3100e->video_options & 4) bold = boldcols[attr] ? chr + 256 : chr; @@ -341,7 +341,7 @@ t3100e_text_row40(t3100e_t *t3100e) bold = boldcols[attr] ? chr : chr + 256; bold += 512 * (t3100e->video_options & 3); - if (t3100e->cga.cgamode & 0x20) /* Blink */ + if (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */ { cols[1] = blinkcols[attr][1]; cols[0] = blinkcols[attr][0]; @@ -374,9 +374,9 @@ t3100e_cgaline6(t3100e_t *t3100e) uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; uint32_t bg = black; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; - if (t3100e->cga.crtc[9] == 3) /* 640*400 */ + if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 640*400 */ { addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); } else { @@ -388,7 +388,7 @@ t3100e_cgaline6(t3100e_t *t3100e) for (uint8_t c = 0; c < 8; c++) { ink = (dat & 0x80) ? fg : bg; - if (!(t3100e->cga.cgamode & 8)) + if (!(t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)) ink = black; (buffer32->line[t3100e->displine])[x * 8 + c] = ink; dat = dat << 1; @@ -407,8 +407,8 @@ t3100e_cgaline4(t3100e_t *t3100e) uint32_t ink1 = 0; uint16_t addr; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */ + uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_END] << 8)) & 0x7fff; + if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 320*400 undocumented */ { addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); } else /* 320*200 */ @@ -421,7 +421,7 @@ t3100e_cgaline4(t3100e_t *t3100e) for (uint8_t c = 0; c < 4; c++) { pattern = (dat & 0xC0) >> 6; - if (!(t3100e->cga.cgamode & 8)) + if (!(t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)) pattern = 0; switch (pattern & 3) { @@ -498,7 +498,7 @@ t3100e_poll(void *priv) /* Graphics */ if (t3100e->cga.cgamode & 0x02) { - if (t3100e->cga.cgamode & 0x10) + if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) t3100e_cgaline6(t3100e); else t3100e_cgaline4(t3100e); @@ -551,7 +551,7 @@ t3100e_poll(void *priv) video_res_y = T3100E_YSIZE; if (t3100e->cga.cgamode & 0x02) { - if (t3100e->cga.cgamode & 0x10) + if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) video_bpp = 1; else video_bpp = 2; diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index 812755898..628333aba 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -58,13 +58,13 @@ static void elt_vid_off_poll(void *priv) { cga_t *cga = priv; - uint8_t hdisp = cga->crtc[1]; + uint8_t hdisp = cga->crtc[CGA_CRTC_HDISP]; /* Don't display anything. * TODO: Do something less stupid to emulate backlight off. */ - cga->crtc[1] = 0; + cga->crtc[CGA_CRTC_HDISP] = 0; cga_poll(cga); - cga->crtc[1] = hdisp; + cga->crtc[CGA_CRTC_HDISP] = hdisp; } static void diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index acdb77fd1..8e37dce1f 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -1918,7 +1918,7 @@ m19_vid_out(uint16_t addr, uint8_t val, void *priv) /* activating plantronics mode */ if (addr == 0x3dd) { /* already in graphics mode */ - if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2)) + if ((val & 0x30) && (vid->ogc.cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) vid->mode = PLANTRONICS_MODE; else vid->mode = OLIVETTI_OGC_MODE; diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index efad869e1..8811309a0 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -246,24 +246,24 @@ t1000_text_row80(t1000_t *t1000) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; + uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t ca = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; sc = (t1000->displine) & 7; addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2; ma += (t1000->displine >> 3) * 80; - if ((t1000->cga.crtc[10] & 0x60) == 0x20) { + if ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && ((t1000->cga.crtc[11] & 0x0F) >= sc); + cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= sc) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc); } for (uint8_t x = 0; x < 80; x++) { chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); + drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16)); - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); if (t1000->video_options & 1) bold = boldcols[attr] ? chr : chr + 256; @@ -272,7 +272,7 @@ t1000_text_row80(t1000_t *t1000) if (t1000->video_options & 2) bold += 512; - if (t1000->cga.cgamode & 0x20) /* Blink */ + if (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */ { cols[1] = blinkcols[attr][1]; cols[0] = blinkcols[attr][0]; @@ -307,24 +307,24 @@ t1000_text_row40(t1000_t *t1000) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; + uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t ca = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; sc = (t1000->displine) & 7; addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2; ma += (t1000->displine >> 3) * 40; - if ((t1000->cga.crtc[10] & 0x60) == 0x20) { + if ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && ((t1000->cga.crtc[11] & 0x0F) >= sc); + cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= sc) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc); } for (uint8_t x = 0; x < 40; x++) { chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); + drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16)); - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); if (t1000->video_options & 1) bold = boldcols[attr] ? chr : chr + 256; @@ -333,7 +333,7 @@ t1000_text_row40(t1000_t *t1000) if (t1000->video_options & 2) bold += 512; - if (t1000->cga.cgamode & 0x20) /* Blink */ + if (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */ { cols[1] = blinkcols[attr][1]; cols[0] = blinkcols[attr][0]; @@ -366,7 +366,7 @@ t1000_cgaline6(t1000_t *t1000) uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey; uint32_t bg = grey; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1); @@ -376,7 +376,7 @@ t1000_cgaline6(t1000_t *t1000) for (uint8_t c = 0; c < 8; c++) { ink = (dat & 0x80) ? fg : bg; - if (!(t1000->cga.cgamode & 8)) + if (!(t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)) ink = grey; (buffer32->line[t1000->displine])[x * 8 + c] = ink; dat = dat << 1; @@ -395,7 +395,7 @@ t1000_cgaline4(t1000_t *t1000) uint32_t ink1; uint16_t addr; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { @@ -404,7 +404,7 @@ t1000_cgaline4(t1000_t *t1000) for (uint8_t c = 0; c < 4; c++) { pattern = (dat & 0xC0) >> 6; - if (!(t1000->cga.cgamode & 8)) + if (!(t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)) pattern = 0; switch (pattern & 3) { @@ -479,7 +479,7 @@ t1000_poll(void *priv) /* Graphics */ if (t1000->cga.cgamode & 0x02) { - if (t1000->cga.cgamode & 0x10) + if (t1000->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) t1000_cgaline6(t1000); else t1000_cgaline4(t1000); @@ -532,7 +532,7 @@ t1000_poll(void *priv) video_res_y = T1000_YSIZE; if (t1000->cga.cgamode & 0x02) { - if (t1000->cga.cgamode & 0x10) + if (t1000->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) video_bpp = 1; else video_bpp = 2; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 0fb1a1402..38dac61c7 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -75,7 +75,7 @@ cga_update_latch(cga_t *cga) { uint32_t lp_latch = cga->displine * cga->crtc[CGA_CRTC_HDISP]; - cga->crtc[0x10] = (lp_latch >> 8) & 0x3f; + cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_HIGH] = (lp_latch >> 8) & 0x3f; cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_LOW] = lp_latch & 0xff; } diff --git a/src/video/vid_cga_comp.c b/src/video/vid_cga_comp.c index 6ad6a6b0a..ca9c2c9df 100644 --- a/src/video/vid_cga_comp.c +++ b/src/video/vid_cga_comp.c @@ -135,7 +135,7 @@ update_cga16_color(uint8_t cgamode) int left = (x >> 6) & 15; int rc = right; int lc = left; - if ((cgamode & 4) != 0) { + if ((cgamode & CGA_MODE_FLAG_BW) != 0) { rc = (right & 8) | ((right & 7) != 0 ? 7 : 0); lc = (left & 8) | ((left & 7) != 0 ? 7 : 0); } @@ -240,7 +240,7 @@ Composite_Process(uint8_t cgamode, uint8_t border, uint32_t blocks /*, bool doub for (uint8_t x = 0; x < 5; ++x) OUT(b[x & 3]); - if ((cgamode & 4) != 0) { + if ((cgamode & CGA_MODE_FLAG_BW) != 0) { /* Decode */ i = temp + 5; srgb = TempLine; diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index d15865c1e..716d35b76 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -173,7 +173,7 @@ colorplus_poll(void *priv) } else if (colorplus->control & COLORPLUS_640x200_MODE) { cols[0] = (colorplus->cga.cgacol & 15) | 16; col = (colorplus->cga.cgacol & 16) ? 24 : 16; - if (colorplus->cga.cgamode & 4) { + if (colorplus->cga.cgamode & CGA_MODE_FLAG_BW) { cols[1] = col | 3; cols[2] = col | 4; cols[3] = col | 7; @@ -268,7 +268,7 @@ colorplus_poll(void *priv) colorplus->cga.displine = 0; colorplus->cga.vsynctime = 16; if (colorplus->cga.crtc[CGA_CRTC_VSYNC]) { - if (colorplus->cga.cgamode & 1) + if (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES) x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; @@ -288,15 +288,15 @@ colorplus_poll(void *priv) video_res_x = xsize - 16; video_res_y = ysize; - if (colorplus->cga.cgamode & 1) { + if (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; video_res_y /= colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(colorplus->cga.cgamode & 2)) { + } else if (!(colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; video_res_y /= colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(colorplus->cga.cgamode & 16)) { + } else if (!(colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { video_res_x /= 2; video_bpp = 2; } else { @@ -317,7 +317,7 @@ colorplus_poll(void *priv) colorplus->cga.cgastat &= ~1; if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) colorplus->cga.cursorvisible = 1; - if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) { + if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (colorplus->cga.crtc[CGA_CRTC_HDISP] << 1); x++) colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.ma << 1) + x) & 0x3fff]; } diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 80c6ecb9e..23b7e44df 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -72,9 +72,9 @@ compaq_cga_recalctimings(compaq_cga_t *self) double _dispontime; double _dispofftime; double disptime; - disptime = self->cga.crtc[0] + 1; + disptime = self->cga.crtc[CGA_CRTC_HTOTAL] + 1; - _dispontime = self->cga.crtc[1]; + _dispontime = self->cga.crtc[CGA_CRTC_HDISP]; _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; @@ -86,7 +86,7 @@ void compaq_cga_poll(void *priv) { compaq_cga_t *self = (compaq_cga_t *) priv; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; + uint16_t ca = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -102,7 +102,7 @@ compaq_cga_poll(void *priv) int blink = 0; /* If in graphics mode or character height is not 13, behave as CGA */ - if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) { + if ((self->cga.cgamode & 0x12) || (self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] != 13)) { overscan_x = overscan_y = 16; cga_poll(&self->cga); return; @@ -115,7 +115,7 @@ compaq_cga_poll(void *priv) self->cga.cgastat |= 1; self->cga.linepos = 1; oldsc = self->cga.sc; - if ((self->cga.crtc[8] & 3) == 3) + if ((self->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; if (self->cga.cgadispon) { if (self->cga.displine < self->cga.firstline) { @@ -129,21 +129,21 @@ compaq_cga_poll(void *priv) for (c = 0; c < 8; c++) { buffer32->line[self->cga.displine][c] = cols[0]; - if (self->cga.cgamode & 1) - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0]; + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + buffer32->line[self->cga.displine][c + (self->cga.crtc[CGA_CRTC_HDISP] << 3) + 8] = cols[0]; else - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0]; + buffer32->line[self->cga.displine][c + (self->cga.crtc[CGA_CRTC_HDISP] << 4) + 8] = cols[0]; } - if (self->cga.cgamode & 1) { - for (x = 0; x < self->cga.crtc[1]; x++) { + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { + for (x = 0; x < self->cga.crtc[CGA_CRTC_HDISP]; x++) { chr = self->cga.charbuffer[x << 1]; attr = self->cga.charbuffer[(x << 1) + 1]; drawcursor = ((self->cga.ma == ca) && self->cga.cursorvisible && self->cga.cursoron); if (vflags) { underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); } if (vflags && (self->cga.cgamode & 0x80)) { @@ -152,7 +152,7 @@ compaq_cga_poll(void *priv) if ((self->cga.sc == 12) && ((attr & 7) == 1)) underline = 1; - } else if (self->cga.cgamode & 0x20) { + } else if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -181,14 +181,14 @@ compaq_cga_poll(void *priv) self->cga.ma++; } } else { - for (x = 0; x < self->cga.crtc[1]; x++) { + for (x = 0; x < self->cga.crtc[CGA_CRTC_HDISP]; x++) { chr = self->cga.vram[(self->cga.ma << 1) & 0x3fff]; attr = self->cga.vram[((self->cga.ma << 1) + 1) & 0x3fff]; drawcursor = ((self->cga.ma == ca) && self->cga.cursorvisible && self->cga.cursoron); if (vflags) { underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); } if (vflags && (self->cga.cgamode & 0x80)) { @@ -196,7 +196,7 @@ compaq_cga_poll(void *priv) cols[1] = mdaattr[attr][blink][1]; if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; - } else if (self->cga.cgamode & 0x20) { + } else if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -228,19 +228,19 @@ compaq_cga_poll(void *priv) } else { cols[0] = (self->cga.cgacol & 15) + 16; - if (self->cga.cgamode & 1) - hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + hline(buffer32, 0, self->cga.displine, (self->cga.crtc[CGA_CRTC_HDISP] << 3) + 16, cols[0]); else - hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, self->cga.displine, (self->cga.crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]); } - if (self->cga.cgamode & 1) - x = (self->cga.crtc[1] << 3) + 16; + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + x = (self->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (self->cga.crtc[1] << 4) + 16; + x = (self->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; if (self->cga.composite) { - if (self->cga.cgamode & 0x10) + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) border = 0x00; else border = self->cga.cgacol & 0x0f; @@ -253,7 +253,7 @@ compaq_cga_poll(void *priv) video_process_8(x, self->cga.displine); self->cga.sc = oldsc; - if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) + if (self->cga.vc == self->cga.crtc[CGA_CRTC_VSYNC] && !self->cga.sc) self->cga.cgastat |= 8; self->cga.displine++; if (self->cga.displine >= 500) @@ -267,10 +267,10 @@ compaq_cga_poll(void *priv) self->cga.cgastat &= ~8; } - if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { + if (self->cga.sc == (self->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((self->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && self->cga.sc == ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { self->cga.cursorvisible = 0; } - if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) + if ((self->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && self->cga.sc == (self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) self->cga.maback = self->cga.ma; if (self->cga.vadj) { self->cga.sc++; @@ -279,48 +279,48 @@ compaq_cga_poll(void *priv) self->cga.vadj--; if (!self->cga.vadj) { self->cga.cgadispon = 1; - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + self->cga.ma = self->cga.maback = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; self->cga.sc = 0; } - } else if (self->cga.sc == self->cga.crtc[9]) { + } else if (self->cga.sc == self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { self->cga.maback = self->cga.ma; self->cga.sc = 0; oldvc = self->cga.vc; self->cga.vc++; self->cga.vc &= 127; - if (self->cga.vc == self->cga.crtc[6]) + if (self->cga.vc == self->cga.crtc[CGA_CRTC_VDISP]) self->cga.cgadispon = 0; - if (oldvc == self->cga.crtc[4]) { + if (oldvc == self->cga.crtc[CGA_CRTC_VTOTAL]) { self->cga.vc = 0; - self->cga.vadj = self->cga.crtc[5]; + self->cga.vadj = self->cga.crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!self->cga.vadj) self->cga.cgadispon = 1; if (!self->cga.vadj) - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + self->cga.ma = self->cga.maback = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - if ((self->cga.crtc[10] & 0x60) == 0x20) + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) self->cga.cursoron = 0; else self->cga.cursoron = self->cga.cgablink & 8; } - if (self->cga.vc == self->cga.crtc[7]) { + if (self->cga.vc == self->cga.crtc[CGA_CRTC_VSYNC]) { self->cga.cgadispon = 0; self->cga.displine = 0; self->cga.vsynctime = 16; - if (self->cga.crtc[7]) { + if (self->cga.crtc[CGA_CRTC_VSYNC]) { compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline, self->cga.firstline, self->cga.lastline - self->cga.firstline); - if (self->cga.cgamode & 1) - x = (self->cga.crtc[1] << 3) + 16; + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + x = (self->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (self->cga.crtc[1] << 4) + 16; + x = (self->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; self->cga.lastline++; @@ -335,7 +335,7 @@ compaq_cga_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + if ((self->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); @@ -356,15 +356,15 @@ compaq_cga_poll(void *priv) if (enable_overscan) xsize -= 16; video_res_y = ysize; - if (self->cga.cgamode & 1) { + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; - video_res_y /= self->cga.crtc[9] + 1; + video_res_y /= self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(self->cga.cgamode & 2)) { + } else if (!(self->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; - video_res_y /= self->cga.crtc[9] + 1; + video_res_y /= self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; video_bpp = 0; - } else if (!(self->cga.cgamode & 16)) { + } else if (!(self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { video_res_x /= 2; video_bpp = 2; } else @@ -385,11 +385,11 @@ compaq_cga_poll(void *priv) if (self->cga.cgadispon) self->cga.cgastat &= ~1; - if (self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))) + if (self->cga.sc == (self->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((self->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && self->cga.sc == ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) self->cga.cursorvisible = 1; - if (self->cga.cgadispon && (self->cga.cgamode & 1)) { - for (x = 0; x < (self->cga.crtc[1] << 1); x++) + if (self->cga.cgadispon && (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { + for (x = 0; x < (self->cga.crtc[CGA_CRTC_HDISP] << 1); x++) self->cga.charbuffer[x] = self->cga.vram[((self->cga.ma << 1) + x) & 0x3fff]; } } @@ -445,7 +445,7 @@ compaq_cga_init(const device_t *info) cga_palette = (self->cga.rgb_type << 1); cgapal_rebuild(); - self->cga.crtc[9] = 13; + self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] = 13; return self; } @@ -464,7 +464,7 @@ compaq_cga_speed_changed(void *priv) { compaq_cga_t *self = (compaq_cga_t *) priv; - if (self->cga.crtc[9] == 13) /* Character height */ + if (self->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 13) /* Character height */ compaq_cga_recalctimings(self); else cga_recalctimings(&self->cga); diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index c607cda14..a8fd2227b 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -362,27 +362,27 @@ f82c425_text_row(f82c425_t *f82c425) int blink; uint16_t addr; uint8_t sc; - uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; - uint8_t sl = f82c425->cga.crtc[9] + 1; - int columns = f82c425->cga.crtc[1]; + uint8_t sl = f82c425->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; + int columns = f82c425->cga.crtc[CGA_CRTC_HDISP]; sc = (f82c425->displine) & 7; addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2; ma += (f82c425->displine >> 3) * columns; - if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20) { + if ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) && ((f82c425->cga.crtc[0x0b] & 0x0F) >= sc); + cursorline = ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= sc) && ((f82c425->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc); } for (int x = 0; x < columns; x++) { chr = f82c425->vram[(addr + 2 * x) & 0x3FFF]; attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && (f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10)); + drawcursor = ((ma == ca) && cursorline && (f82c425->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (f82c425->cga.cgablink & 0x10)); - blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); if (drawcursor) { colors[0] = smartmap[~attr & 0xff][0]; @@ -418,7 +418,7 @@ f82c425_cgaline6(f82c425_t *f82c425) uint8_t dat; uint16_t addr; - uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1); @@ -442,7 +442,7 @@ f82c425_cgaline4(f82c425_t *f82c425) uint8_t pattern; uint16_t addr; - uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { @@ -526,7 +526,7 @@ f82c425_poll(void *priv) f82c425->displine = 0; f82c425->cga.cgastat &= ~8; f82c425->dispon = 1; - } else if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6]) { + } else if (f82c425->displine == (f82c425->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * f82c425->cga.crtc[CGA_CRTC_VDISP]) { /* Start of VSYNC */ f82c425->cga.cgastat |= 8; f82c425->dispon = 0; diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 7a30bf173..2eb94220a 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -56,12 +56,12 @@ nga_recalctimings(nga_t *nga) double _dispofftime; double disptime; - if (nga->cga.cgamode & 1) { - disptime = nga->cga.crtc[0] + 1; - _dispontime = nga->cga.crtc[1]; + if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { + disptime = nga->cga.crtc[CGA_CRTC_HTOTAL] + 1; + _dispontime = nga->cga.crtc[CGA_CRTC_HDISP]; } else { - disptime = (nga->cga.crtc[0] + 1) << 1; - _dispontime = nga->cga.crtc[1] << 1; + disptime = (nga->cga.crtc[CGA_CRTC_HTOTAL] + 1) << 1; + _dispontime = nga->cga.crtc[CGA_CRTC_HDISP] << 1; } _dispofftime = disptime - _dispontime; @@ -148,7 +148,7 @@ nga_poll(void *priv) { nga_t *nga = (nga_t *) priv; /* set cursor position in memory */ - uint16_t ca = (nga->cga.crtc[15] | (nga->cga.crtc[14] << 8)) & 0x3fff; + uint16_t ca = (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -164,7 +164,7 @@ nga_poll(void *priv) int oldsc; /* graphic mode and not high-res modes */ - if ((nga->cga.cgamode & 2) && !(nga->cga.cgamode & 0x40)) { + if ((nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) && !(nga->cga.cgamode & 0x40)) { /* standard cga mode */ cga_poll(&nga->cga); return; @@ -176,7 +176,7 @@ nga_poll(void *priv) nga->cga.linepos = 1; oldsc = nga->cga.sc; /* if interlaced */ - if ((nga->cga.crtc[8] & 3) == 3) + if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) nga->cga.sc = ((nga->cga.sc << 1) + nga->cga.oddeven) & 7; if (nga->cga.cgadispon) { if (nga->cga.displine < nga->cga.firstline) { @@ -185,11 +185,11 @@ nga_poll(void *priv) } nga->cga.lastline = nga->cga.displine; /* 80-col */ - if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 2)) { + if ((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && !(nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { /* for each text column */ - for (x = 0; x < nga->cga.crtc[1]; x++) { + for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) { /* video output enabled */ - if (nga->cga.cgamode & 8) { + if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { /* character */ chr = nga->cga.charbuffer[x << 1]; /* text attributes */ @@ -201,7 +201,7 @@ nga_poll(void *priv) /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ - if (nga->cga.cgamode & 0x20) { + if (nga->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; /* attribute 7 active and not cursor */ if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) { @@ -224,10 +224,10 @@ nga_poll(void *priv) } } /* 40-col */ - else if (!(nga->cga.cgamode & 2)) { + else if (!(nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { /* for each text column */ - for (x = 0; x < nga->cga.crtc[1]; x++) { - if (nga->cga.cgamode & 8) { + for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) { + if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { chr = nga->cga.vram[((nga->cga.ma << 1) & 0x3fff) + nga->base]; attr = nga->cga.vram[(((nga->cga.ma << 1) + 1) & 0x3fff) + nga->base]; } else { @@ -237,7 +237,7 @@ nga_poll(void *priv) /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ - if (nga->cga.cgamode & 0x20) { + if (nga->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) { /* set blinking */ @@ -262,7 +262,7 @@ nga_poll(void *priv) /* high res modes */ if (nga->cga.cgamode & 0x40) { /* 640x400x2 mode */ - if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) { + if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { /* * Scanlines are read in the following order: * 0b8000-0b9f3f even scans (0,4,...) @@ -277,7 +277,7 @@ nga_poll(void *priv) } else { cols[0] = (nga->cga.cgacol & 15) | 16; col = (nga->cga.cgacol & 16) ? 24 : 16; - if (nga->cga.cgamode & 4) { + if (nga->cga.cgamode & CGA_MODE_FLAG_BW) { cols[1] = col | 3; /* Cyan */ cols[2] = col | 4; /* Red */ cols[3] = col | 7; /* White */ @@ -306,11 +306,11 @@ nga_poll(void *priv) } /* for each text column */ - for (x = 0; x < nga->cga.crtc[1]; x++) { + for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) { /* video out */ - if (nga->cga.cgamode & 8) { + if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { /* 640x400x2 */ - if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) { + if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { /* read two bytes at a time */ dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2 + 1]; /* each pixel is represented by one bit, so draw 16 pixels at a time */ @@ -347,26 +347,26 @@ nga_poll(void *priv) /* nga specific */ cols[0] = ((nga->cga.cgamode & 0x12) == 0x12) ? 0 : (nga->cga.cgacol & 15) + 16; /* 80-col */ - if (nga->cga.cgamode & 1) { - hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]); - hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]); + if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { + hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16) << 2, cols[0]); + hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16) << 2, cols[0]); } else { - hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]); - hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]); + hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16) << 2, cols[0]); + hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16) << 2, cols[0]); } } - if (nga->cga.cgamode & 1) + if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) /* set screen width */ - x = (nga->cga.crtc[1] << 3) + 16; + x = (nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (nga->cga.crtc[1] << 4) + 16; + x = (nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; video_process_8(x, nga->cga.displine); nga->cga.sc = oldsc; /* vertical sync */ - if (nga->cga.vc == nga->cga.crtc[7] && !nga->cga.sc) + if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VSYNC] && !nga->cga.sc) nga->cga.cgastat |= 8; nga->cga.displine++; if (nga->cga.displine >= 720) @@ -380,7 +380,7 @@ nga_poll(void *priv) nga->lineff ^= 1; /* text mode or 640x400x2 */ - if (nga->lineff && !((nga->cga.cgamode & 1) && (nga->cga.cgamode & 0x40))) { + if (nga->lineff && !((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && (nga->cga.cgamode & 0x40))) { nga->cga.ma = nga->cga.maback; /* 640x400x4 */ } else { @@ -390,11 +390,11 @@ nga_poll(void *priv) nga->cga.cgastat &= ~8; } /* cursor stop scanline */ - if (nga->cga.sc == (nga->cga.crtc[11] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[11] & 31) >> 1))) { + if (nga->cga.sc == (nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { nga->cga.cursorvisible = 0; } /* interlaced and max scanline per char reached */ - if ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1)) + if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) nga->cga.maback = nga->cga.ma; if (nga->cga.vadj) { @@ -405,12 +405,12 @@ nga_poll(void *priv) if (!nga->cga.vadj) { nga->cga.cgadispon = 1; /* change start of displayed page (crtc 12-13) */ - nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff; + nga->cga.ma = nga->cga.maback = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; nga->cga.sc = 0; } /* nga specific */ /* end of character line reached */ - } else if (nga->cga.sc == nga->cga.crtc[9] || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1))) { + } else if (nga->cga.sc == nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { nga->cga.maback = nga->cga.ma; nga->cga.sc = 0; oldvc = nga->cga.vc; @@ -418,21 +418,21 @@ nga_poll(void *priv) nga->cga.vc &= 127; /* lines of character displayed */ - if (nga->cga.vc == nga->cga.crtc[6]) + if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VDISP]) nga->cga.cgadispon = 0; /* total vertical lines */ - if (oldvc == nga->cga.crtc[4]) { + if (oldvc == nga->cga.crtc[CGA_CRTC_VTOTAL]) { nga->cga.vc = 0; /* adjust vertical lines */ - nga->cga.vadj = nga->cga.crtc[5]; + nga->cga.vadj = nga->cga.crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!nga->cga.vadj) { nga->cga.cgadispon = 1; /* change start of displayed page (crtc 12-13) */ - nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff; + nga->cga.ma = nga->cga.maback = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; } /* cursor start */ - switch (nga->cga.crtc[10] & 0x60) { + switch (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) { case 0x20: nga->cga.cursoron = 0; break; @@ -445,18 +445,18 @@ nga_poll(void *priv) } } /* vertical line position */ - if (nga->cga.vc == nga->cga.crtc[7]) { + if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VSYNC]) { nga->cga.cgadispon = 0; nga->cga.displine = 0; /* nga specific */ nga->cga.vsynctime = 16; /* vsync pos */ - if (nga->cga.crtc[7]) { - if (nga->cga.cgamode & 1) + if (nga->cga.crtc[CGA_CRTC_VSYNC]) { + if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) /* set screen width */ - x = (nga->cga.crtc[1] << 3) + 16; + x = (nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (nga->cga.crtc[1] << 4) + 16; + x = (nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; nga->cga.lastline++; xs_temp = x; @@ -471,7 +471,7 @@ nga_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((nga->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + if ((nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); @@ -493,14 +493,14 @@ nga_poll(void *priv) video_res_x = xsize; video_res_y = ysize; /* 80-col */ - if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 0x40)) { + if ((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && !(nga->cga.cgamode & 0x40)) { video_res_x /= 8; - video_res_y /= (nga->cga.crtc[9] + 1) * 2; + video_res_y /= (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2; video_bpp = 0; /* 40-col */ - } else if (!(nga->cga.cgamode & 2)) { + } else if (!(nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; - video_res_y /= (nga->cga.crtc[9] + 1) * 2; + video_res_y /= (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2; video_bpp = 0; } else if (nga->cga.cgamode & 0x40) { video_res_x /= 8; @@ -523,13 +523,13 @@ nga_poll(void *priv) nga->cga.cgastat &= ~1; /* enable cursor if its scanline was reached */ - if (nga->cga.sc == (nga->cga.crtc[10] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[10] & 31) >> 1))) + if (nga->cga.sc == (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) nga->cga.cursorvisible = 1; } /* 80-columns */ - if (nga->cga.cgadispon && (nga->cga.cgamode & 1)) { + if (nga->cga.cgadispon && (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { /* for each character per line */ - for (x = 0; x < (nga->cga.crtc[1] << 1); x++) + for (x = 0; x < (nga->cga.crtc[CGA_CRTC_HDISP] << 1); x++) nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.ma << 1) + x) & 0x3fff) + nga->base]; } } diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index afbc778a6..bc54499b2 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -65,12 +65,12 @@ ogc_recalctimings(ogc_t *ogc) double _dispofftime; double disptime; - if (ogc->cga.cgamode & 1) { - disptime = ogc->cga.crtc[0] + 1; - _dispontime = ogc->cga.crtc[1]; + if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { + disptime = ogc->cga.crtc[CGA_CRTC_HTOTAL] + 1; + _dispontime = ogc->cga.crtc[CGA_CRTC_HDISP]; } else { - disptime = (ogc->cga.crtc[0] + 1) << 1; - _dispontime = ogc->cga.crtc[1] << 1; + disptime = (ogc->cga.crtc[CGA_CRTC_HTOTAL] + 1) << 1; + _dispontime = ogc->cga.crtc[CGA_CRTC_HDISP] << 1; } _dispofftime = disptime - _dispontime; @@ -201,7 +201,7 @@ void ogc_poll(void *priv) { ogc_t *ogc = (ogc_t *) priv; - uint16_t ca = (ogc->cga.crtc[15] | (ogc->cga.crtc[14] << 8)) & 0x3fff; + uint16_t ca = (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -220,7 +220,7 @@ ogc_poll(void *priv) // composito colore appare blu scuro /* graphic mode and not mode 40h */ - if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & 2))) { + if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS))) { /* standard cga mode */ cga_poll(&ogc->cga); return; @@ -231,7 +231,7 @@ ogc_poll(void *priv) ogc->cga.cgastat |= 1; ogc->cga.linepos = 1; oldsc = ogc->cga.sc; - if ((ogc->cga.crtc[8] & 3) == 3) + if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) ogc->cga.sc = ((ogc->cga.sc << 1) + ogc->cga.oddeven) & 7; if (ogc->cga.cgadispon) { if (ogc->cga.displine < ogc->cga.firstline) { @@ -240,11 +240,11 @@ ogc_poll(void *priv) } ogc->cga.lastline = ogc->cga.displine; /* 80-col */ - if (ogc->cga.cgamode & 1) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { /* for each text column */ - for (x = 0; x < ogc->cga.crtc[1]; x++) { + for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) { /* video output enabled */ - if (ogc->cga.cgamode & 8) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { /* character */ chr = ogc->cga.charbuffer[x << 1]; /* text attributes */ @@ -263,7 +263,7 @@ ogc_poll(void *priv) /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ - if (ogc->cga.cgamode & 0x20) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; /* attribute 7 active and not cursor */ if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) { @@ -293,9 +293,9 @@ ogc_poll(void *priv) } } /* 40-col */ - else if (!(ogc->cga.cgamode & 2)) { - for (x = 0; x < ogc->cga.crtc[1]; x++) { - if (ogc->cga.cgamode & 8) { + else if (!(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { + for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { chr = ogc->cga.vram[((ogc->cga.ma << 1) & 0x3fff) + ogc->base]; attr = ogc->cga.vram[(((ogc->cga.ma << 1) + 1) & 0x3fff) + ogc->base]; } else { @@ -312,7 +312,7 @@ ogc_poll(void *priv) /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ - if (ogc->cga.cgamode & 0x20) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) { /* set blinking */ @@ -352,9 +352,9 @@ ogc_poll(void *priv) cols[1] = (ogc->cga.cgacol & 15) + 16; } - for (x = 0; x < ogc->cga.crtc[1]; x++) { + for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) { /* video out */ - if (ogc->cga.cgamode & 8) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { dat = (ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2 + 1]; } else { dat = 0; @@ -370,22 +370,22 @@ ogc_poll(void *priv) } else { /* ogc specific */ cols[0] = ((ogc->cga.cgamode & 0x12) == 0x12) ? 0 : (ogc->cga.cgacol & 15) + 16; - if (ogc->cga.cgamode & 1) - hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[1] << 3) + 16) << 2, cols[0]); + if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[CGA_CRTC_HDISP] << 3) + 16) << 2, cols[0]); else - hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[1] << 4) + 16) << 2, cols[0]); + hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[CGA_CRTC_HDISP] << 4) + 16) << 2, cols[0]); } /* 80 columns */ - if (ogc->cga.cgamode & 1) - x = (ogc->cga.crtc[1] << 3) + 16; + if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (ogc->cga.crtc[1] << 4) + 16; + x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; video_process_8(x, ogc->cga.displine); ogc->cga.sc = oldsc; - if (ogc->cga.vc == ogc->cga.crtc[7] && !ogc->cga.sc) + if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC] && !ogc->cga.sc) ogc->cga.cgastat |= 8; ogc->cga.displine++; if (ogc->cga.displine >= 720) @@ -405,10 +405,10 @@ ogc_poll(void *priv) if (!ogc->cga.vsynctime) ogc->cga.cgastat &= ~8; } - if (ogc->cga.sc == (ogc->cga.crtc[11] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[11] & 31) >> 1))) { + if (ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { ogc->cga.cursorvisible = 0; } - if ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1)) + if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) ogc->cga.maback = ogc->cga.ma; if (ogc->cga.vadj) { ogc->cga.sc++; @@ -417,28 +417,28 @@ ogc_poll(void *priv) ogc->cga.vadj--; if (!ogc->cga.vadj) { ogc->cga.cgadispon = 1; - ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff; + ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; ogc->cga.sc = 0; } // potrebbe dare problemi con composito - } else if (ogc->cga.sc == ogc->cga.crtc[9] || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1))) { + } else if (ogc->cga.sc == ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { ogc->cga.maback = ogc->cga.ma; ogc->cga.sc = 0; oldvc = ogc->cga.vc; ogc->cga.vc++; ogc->cga.vc &= 127; - if (ogc->cga.vc == ogc->cga.crtc[6]) + if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VDISP]) ogc->cga.cgadispon = 0; - if (oldvc == ogc->cga.crtc[4]) { + if (oldvc == ogc->cga.crtc[CGA_CRTC_VTOTAL]) { ogc->cga.vc = 0; - ogc->cga.vadj = ogc->cga.crtc[5]; + ogc->cga.vadj = ogc->cga.crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!ogc->cga.vadj) { ogc->cga.cgadispon = 1; - ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff; + ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; } - switch (ogc->cga.crtc[10] & 0x60) { + switch (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) { case 0x20: ogc->cga.cursoron = 0; break; @@ -450,16 +450,16 @@ ogc_poll(void *priv) break; } } - if (ogc->cga.vc == ogc->cga.crtc[7]) { + if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC]) { ogc->cga.cgadispon = 0; ogc->cga.displine = 0; /* ogc specific */ - ogc->cga.vsynctime = (ogc->cga.crtc[3] >> 4) + 1; - if (ogc->cga.crtc[7]) { - if (ogc->cga.cgamode & 1) - x = (ogc->cga.crtc[1] << 3) + 16; + ogc->cga.vsynctime = (ogc->cga.crtc[CGA_CRTC_HSYNC_WIDTH] >> 4) + 1; + if (ogc->cga.crtc[CGA_CRTC_VSYNC]) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) + x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (ogc->cga.crtc[1] << 4) + 16; + x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 4) + 16; ogc->cga.lastline++; xs_temp = x; @@ -474,7 +474,7 @@ ogc_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((ogc->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + if ((ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); @@ -496,14 +496,14 @@ ogc_poll(void *priv) video_res_x = xsize; video_res_y = ysize; /* 80-col */ - if (ogc->cga.cgamode & 1) { + if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; - video_res_y /= (ogc->cga.crtc[9] + 1) * 2; + video_res_y /= (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2; video_bpp = 0; /* 40-col */ - } else if (!(ogc->cga.cgamode & 2)) { + } else if (!(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { video_res_x /= 16; - video_res_y /= (ogc->cga.crtc[9] + 1) * 2; + video_res_y /= (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2; video_bpp = 0; } else if (!(ogc->ctrl_3de & 1)) { video_res_y /= 2; @@ -524,12 +524,12 @@ ogc_poll(void *priv) if (ogc->cga.cgadispon) ogc->cga.cgastat &= ~1; - if (ogc->cga.sc == (ogc->cga.crtc[10] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[10] & 31) >> 1))) + if (ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) ogc->cga.cursorvisible = 1; } /* 80-columns */ - if (ogc->cga.cgadispon && (ogc->cga.cgamode & 1)) { - for (x = 0; x < (ogc->cga.crtc[1] << 1); x++) + if (ogc->cga.cgadispon && (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { + for (x = 0; x < (ogc->cga.crtc[CGA_CRTC_HDISP] << 1); x++) ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.ma << 1) + x) & 0x3fff) + ogc->base]; } } From a82bb4269f815a5b263cdf2739aa749702208acd Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Mon, 9 Jun 2025 20:36:21 +0200 Subject: [PATCH 1113/1190] Added the Shottle HOT-433A eSupport BIOS. --- src/floppy/fdc.c | 12 ++++++- src/include/86box/pic.h | 2 ++ src/machine/m_at_386dx_486.c | 68 ++++++++++++++++++++++++++++++++---- src/machine/machine_table.c | 5 +-- src/pic.c | 19 ++++++++++ 5 files changed, 97 insertions(+), 9 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 0b5391670..186d4c894 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -187,10 +187,18 @@ fdc_ctrl_reset(void *priv) fdc->stat = 0x80; fdc->pnum = fdc->ptot = 0; fdc->st0 = 0; - fdc->lock = 0; fdc->head = 0; fdc->step = 0; fdc->power_down = 0; + + if (!fdc->lock) { + fdc->fifo = 0; + fdc->tfifo = 1; + + fifo_reset(fdc->fifo_p); + fifo_set_len(fdc->fifo_p, fdc->tfifo + 1); + fifo_set_trigger_len(fdc->fifo_p, fdc->tfifo + 1); + } } sector_id_t @@ -2374,6 +2382,8 @@ fdc_reset(void *priv) fdc->swwp = 0; fdc->disable_write = 0; + fdc->lock = 0; + fdc_ctrl_reset(fdc); if (!(fdc->flags & FDC_FLAG_AT)) diff --git a/src/include/86box/pic.h b/src/include/86box/pic.h index 798cc3357..f6dc9af64 100644 --- a/src/include/86box/pic.h +++ b/src/include/86box/pic.h @@ -102,4 +102,6 @@ extern int picinterrupt(void); extern uint8_t pic_irq_ack(void); +extern void pic_toggle_latch(int is_ps2); + #endif /*EMU_PIC_H*/ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index a43d5ea63..86a1aa087 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2232,18 +2232,66 @@ machine_at_ecs486_init(const machine_t *model) return ret; } +static const device_config_t hot433a_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "hot433a", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "AMI", .internal_name = "hot433a", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/hot433/433AUS33.ROM", "" } }, + { .name = "Award (eSupport update)", .internal_name = "hot433a_award", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/hot433/2A4X5H21.BIN", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t hot433a_device = { + .name = "Shuttle HOT-433A", + .internal_name = "hot433a_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = hot433a_config +}; + int machine_at_hot433a_init(const machine_t *model) { - int ret; + int ret = 0; + const char* fn; - ret = bios_load_linear("roms/machines/hot433/433AUS33.ROM", - 0x000e0000, 131072, 0); + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + int is_award = !strcmp(device_get_config_bios("bios"), "hot433a_award"); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + if (is_award) + device_add(&amstrad_megapc_nvr_device); + else + device_add(&ami_1994_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2255,9 +2303,17 @@ machine_at_hot433a_init(const machine_t *model) device_add(&umc_hb4_device); device_add(&umc_8886bf_device); - device_add(&um8669f_device); + if (is_award) + device_add(&um8663af_device); + else + device_add(&um8669f_device); device_add(&winbond_flash_w29c010_device); - device_add(&keyboard_at_ami_device); + if (is_award) + device_add(&keyboard_ps2_ami_device); + else + device_add(&keyboard_at_ami_device); + + pic_toggle_latch(is_award); return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 4f907ce10..001d9cb8c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -69,6 +69,7 @@ extern const device_t ap5s_device; extern const device_t d842_device; extern const device_t d943_device; extern const device_t dells333sl_device; +extern const device_t hot433a_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -9381,7 +9382,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_APM, .ram = { .min = 1024, @@ -9393,7 +9394,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &hot433a_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, diff --git a/src/pic.c b/src/pic.c index cf17e8205..4b8993322 100644 --- a/src/pic.c +++ b/src/pic.c @@ -638,6 +638,25 @@ pic_reset_hard(void) } } +void +pic_toggle_latch(int is_ps2) +{ + pic_kbd_latch(0x00); + pic_mouse_latch(0x00); + + /* Explicitly reset the latches. */ + kbd_latch = mouse_latch = 0; + latched_irqs = 0x0000; + + /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, + to the point that there's even boards with board-level latched that get used in place of the latches + on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ + if (is_ps2) { + pic_kbd_latch(0x01); + pic_mouse_latch(0x01); + } +} + void pic_init(void) { From ec7e75bb81f395a0b91e6859502b55ee8909b374 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 21:43:32 +0100 Subject: [PATCH 1114/1190] De-magic colorplus_out --- src/video/vid_colorplus.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 716d35b76..efa8ab3a7 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -37,16 +37,19 @@ #include <86box/plat_unused.h> /* Bits in the colorplus control register: */ -#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */ -#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */ -#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */ -#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */ +#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */ +#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */ +#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */ +#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */ -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 +#define CGA_RGB 0 +#define CGA_COMPOSITE 1 -#define COMPOSITE_OLD 0 -#define COMPOSITE_NEW 1 +#define COMPOSITE_OLD 0 +#define COMPOSITE_NEW 1 + +// Plantronics specific registers +#define COLORPLUS_CONTROL 0x3DD video_timings_t timing_colorplus = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; @@ -57,7 +60,7 @@ colorplus_out(uint16_t addr, uint8_t val, void *priv) { colorplus_t *colorplus = (colorplus_t *) priv; - if (addr == 0x3DD) { + if (addr == COLORPLUS_CONTROL) { colorplus->control = val & 0x70; } else { cga_out(addr, val, &colorplus->cga); From 95708eb0d7c2d36b76a73398be5f1934654a777e Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 23:04:13 +0100 Subject: [PATCH 1115/1190] Reorganise and rename the CGA files. Move onboard video to the video folder. Rename "con" to "cursorvisible" across the entire emulator --- src/include/86box/m_pcjr.h | 72 ++ src/include/86box/m_tandy.h | 95 ++ src/include/86box/vid_cga.h | 3 +- src/include/86box/vid_ega.h | 4 +- src/include/86box/vid_hercules.h | 2 +- src/include/86box/vid_mda.h | 2 +- src/include/86box/vid_pgc.h | 2 +- src/include/86box/vid_svga.h | 2 +- src/include/86box/vid_svga_render.h | 2 +- src/include/86box/video.h | 6 + src/machine/CMakeLists.txt | 2 - src/machine/m_amstrad.c | 16 +- src/machine/m_at_compaq.c | 744 --------------- src/machine/m_pcjr.c | 715 +------------- src/machine/m_tandy.c | 873 +----------------- src/machine/machine_table.c | 13 +- src/video/CMakeLists.txt | 22 +- .../{vid_colorplus.c => vid_cga_colorplus.c} | 0 .../{vid_compaq_cga.c => vid_cga_compaq.c} | 0 src/video/vid_cga_compaq_plasma.c | 784 ++++++++++++++++ src/video/{vid_nga.c => vid_cga_ncr.c} | 0 src/video/{vid_ogc.c => vid_cga_olivetti.c} | 4 +- .../vid_cga_toshiba_t1000.c} | 0 .../vid_cga_toshiba_t3100e.c} | 0 src/video/vid_ega.c | 4 +- src/video/vid_ega_render.c | 2 +- src/video/vid_hercules.c | 6 +- .../{vid_incolor.c => vid_hercules_incolor.c} | 8 +- ...vid_herculesplus.c => vid_hercules_plus.c} | 8 +- src/video/vid_jega.c | 2 +- src/video/vid_mda.c | 6 +- src/video/vid_pcjr.c | 703 ++++++++++++++ src/video/vid_ps55da2.c | 10 +- src/video/vid_sigma.c | 10 +- src/video/vid_svga.c | 4 +- src/video/vid_svga_render.c | 6 +- src/video/vid_tandy.c | 827 +++++++++++++++++ 37 files changed, 2581 insertions(+), 2378 deletions(-) create mode 100644 src/include/86box/m_pcjr.h create mode 100644 src/include/86box/m_tandy.h rename src/video/{vid_colorplus.c => vid_cga_colorplus.c} (100%) rename src/video/{vid_compaq_cga.c => vid_cga_compaq.c} (100%) create mode 100644 src/video/vid_cga_compaq_plasma.c rename src/video/{vid_nga.c => vid_cga_ncr.c} (100%) rename src/video/{vid_ogc.c => vid_cga_olivetti.c} (99%) rename src/{machine/m_xt_t1000_vid.c => video/vid_cga_toshiba_t1000.c} (100%) rename src/{machine/m_at_t3100e_vid.c => video/vid_cga_toshiba_t3100e.c} (100%) rename src/video/{vid_incolor.c => vid_hercules_incolor.c} (99%) rename src/video/{vid_herculesplus.c => vid_hercules_plus.c} (99%) create mode 100644 src/video/vid_pcjr.c create mode 100644 src/video/vid_tandy.c diff --git a/src/include/86box/m_pcjr.h b/src/include/86box/m_pcjr.h new file mode 100644 index 000000000..8ba0c4414 --- /dev/null +++ b/src/include/86box/m_pcjr.h @@ -0,0 +1,72 @@ +/* + * 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. + * + * Header files for the PCjr keyboard and video subsystems. + * + * + * + * Authors: Connor Hyde, <mario64crashed@gmail.com> + * + * Copyright 2025 starfrost + */ + +#pragma once + +#define PCJR_RGB 0 +#define PCJR_COMPOSITE 1 + +typedef struct pcjr_s +{ + /* Video Controller stuff. */ + mem_mapping_t mapping; + uint8_t crtc[32]; + int crtcreg; + int array_index; + uint8_t array[32]; + int array_ff; + int memctrl; + uint8_t stat; + int addr_mode; + uint8_t *vram; + uint8_t *b8000; + int linepos; + int displine; + int sc; + int vc; + int dispon; + int cursorvisible; // Is the cursor visible on the current scanline? + int cursoron; + int blink; + int vsynctime; + int fullchange; + int vadj; + uint16_t ma; + uint16_t maback; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + int firstline; + int lastline; + int composite; + int apply_hd; + + /* Keyboard Controller stuff. */ + int latched; + int data; + int serial_data[44]; + int serial_pos; + uint8_t pa; + uint8_t pb; + pc_timer_t send_delay_timer; + +} pcjr_t; + +void pcjr_recalc_timings(pcjr_t *pcjr); + +// Note: This is a temporary solution until the pcjr video is made its own gfx card +void pcjr_vid_init(pcjr_t *pcjr); \ No newline at end of file diff --git a/src/include/86box/m_tandy.h b/src/include/86box/m_tandy.h new file mode 100644 index 000000000..3bafafd46 --- /dev/null +++ b/src/include/86box/m_tandy.h @@ -0,0 +1,95 @@ +/* + * 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. + * + * Header files for the Tandy keyboard and video subsystems. + * + * + * + * Authors: Connor Hyde, <mario64crashed@gmail.com> + * + * Copyright 2025 starfrost + */ + +typedef struct t1kvid_t { + mem_mapping_t mapping; + mem_mapping_t vram_mapping; + + uint8_t crtc[32]; + int crtcreg; + + int array_index; + uint8_t array[256]; + int memctrl; + uint8_t mode; + uint8_t col; + uint8_t stat; + + uint8_t *vram; + uint8_t *b8000; + uint32_t b8000_mask; + uint32_t b8000_limit; + uint8_t planar_ctrl; + uint8_t lp_strobe; + + int linepos; + int displine; + int sc; + int vc; + int dispon; + int cursorvisible; + int cursoron; + int blink; + int fullchange; + int vsynctime; + int vadj; + uint16_t ma; + uint16_t maback; + + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + int firstline; + int lastline; + + int composite; +} t1kvid_t; + +typedef struct t1keep_t { + char *path; + + int state; + int count; + int addr; + int clk; + uint16_t data; + uint16_t store[64]; +} t1keep_t; + +typedef struct tandy_t { + mem_mapping_t ram_mapping; + mem_mapping_t rom_mapping; /* SL2 */ + + uint8_t *rom; /* SL2 */ + uint8_t ram_bank; + uint8_t rom_bank; /* SL2 */ + int rom_offset; /* SL2 */ + + uint32_t base; + uint32_t mask; + int is_hx; + int is_sl2; + + t1kvid_t *vid; +} tandy_t; + +void tandy_vid_init(tandy_t* dev); +uint8_t tandy_vid_in(uint16_t addr, void* priv); +void tandy_vid_out(uint16_t addr, uint8_t val, void *priv); + +void tandy_vid_close(void* priv); +void tandy_recalc_address_sl(tandy_t* dev); //this function is needed by both m_ and vid_tandy.c diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 7f68286e5..add92c708 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -11,7 +11,8 @@ * * * Authors: Sarah Walker, <https://pcem-emulator.co.uk/> - * Miran Grca, <mgrca8@gmail.com> + * Miran Grca, <mgrca8@gmail.com>, + * Connor Hyde / starfrost, <mario64crashed@gmail.com> * * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index c4c0ea2d7..19461ba2b 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -68,7 +68,7 @@ typedef struct ega_t { int chain4; int chain2_read; int chain2_write; - int con; + int cursorvisible; int oddeven_page; int oddeven_chain; int vc; @@ -193,7 +193,7 @@ extern int sc; extern uint32_t ma; extern uint32_t ca; -extern int con; +extern int cursorvisible; extern int cursoron; extern int cgablink; diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index a468dce55..46b0e16a7 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -46,7 +46,7 @@ typedef struct { int sc; uint16_t ma; uint16_t maback; - int con; + int cursorvisible; int cursoron; int dispon; int blink; diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index eeea5a093..15a1cabde 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -28,7 +28,7 @@ typedef struct mda_t { int sc; uint16_t ma; uint16_t maback; - int con; + int cursorvisible; int cursoron; int dispon; int blink; diff --git a/src/include/86box/vid_pgc.h b/src/include/86box/vid_pgc.h index 43226a0f5..d7906f2bc 100644 --- a/src/include/86box/vid_pgc.h +++ b/src/include/86box/vid_pgc.h @@ -115,7 +115,7 @@ typedef struct pgc { int displine; int vc; int cgadispon; - int con; + int cursorvisible; int cursoron; int cgablink; int vsynctime; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 6b817f0ee..aec33d95c 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -105,7 +105,7 @@ typedef struct svga_t { int vslines; int linecountff; int oddeven; - int con; + int cursorvisible; int cursoron; int blink; int scrollcache; diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index babac7592..a96610d4a 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -27,7 +27,7 @@ extern int sc; extern uint32_t ma; extern uint32_t ca; -extern int con; +extern int cursorvisible; extern int cursoron; extern int cgablink; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index bd3101d84..6ab375370 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -395,6 +395,7 @@ extern const device_t gd5480_pci_device; /* Compaq CGA */ extern const device_t compaq_cga_device; extern const device_t compaq_cga_2_device; +extern const device_t compaq_plasma_device; /* Olivetti OGC */ extern const device_t ogc_device; @@ -609,6 +610,11 @@ extern const device_t velocity_200_agp_device; /* Wyse 700 */ extern const device_t wy700_device; +/* Tandy */ +extern const device_t tandy_1000_video_device; +extern const device_t tandy_1000hx_video_device; +extern const device_t tandy_1000sl_video_device; + #endif #endif /*EMU_VIDEO_H*/ diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 8cd54edec..f91eeb17d 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -23,7 +23,6 @@ add_library(mch OBJECT m_xt_laserxt.c m_xt_philips.c m_xt_t1000.c - m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c @@ -37,7 +36,6 @@ add_library(mch OBJECT m_at_commodore.c m_at_grid.c m_at_t3100e.c - m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index af6c50bc9..43800a8bc 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -116,7 +116,7 @@ typedef struct amsvid_t { int sc; int vc; int cgadispon; - int con; + int cursorvisible; int cursoron; int cgablink; int vsynctime; @@ -387,7 +387,7 @@ vid_poll_1512(void *priv) for (x = 0; x < 80; x++) { chr = vid->vram[(vid->ma << 1) & 0x3fff]; attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -412,7 +412,7 @@ vid_poll_1512(void *priv) for (x = 0; x < 40; x++) { chr = vid->vram[(vid->ma << 1) & 0x3fff]; attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -513,7 +513,7 @@ vid_poll_1512(void *priv) vid->stat &= ~8; } if (vid->sc == (vid->crtc[11] & 31)) { - vid->con = 0; + vid->cursorvisible = 0; } if (vid->vadj) { vid->sc++; @@ -607,7 +607,7 @@ vid_poll_1512(void *priv) vid->ma = vid->maback; } if (vid->sc == (vid->crtc[10] & 31)) - vid->con = 1; + vid->cursorvisible = 1; } } @@ -1292,7 +1292,7 @@ lcdm_poll(amsvid_t *vid) for (x = 0; x < mda->crtc[1]; x++) { chr = mda->vram[(mda->ma << 1) & 0xfff]; attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); + drawcursor = ((mda->ma == ca) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl); @@ -1316,7 +1316,7 @@ lcdm_poll(amsvid_t *vid) mda->stat &= ~8; } if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { - mda->con = 0; + mda->cursorvisible = 0; } if (mda->vadj) { mda->sc++; @@ -1383,7 +1383,7 @@ lcdm_poll(amsvid_t *vid) mda->ma = mda->maback; } if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) - mda->con = 1; + mda->cursorvisible = 1; } } diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index aaa22ffc0..2fbfed0ff 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -44,9 +44,6 @@ #include <86box/vid_cga_comp.h> #include <86box/plat_unused.h> - -static video_timings_t timing_compaq_plasma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - enum { COMPAQ_PORTABLEII = 0, COMPAQ_PORTABLEIII, @@ -55,752 +52,11 @@ enum { COMPAQ_DESKPRO386_05_1988 }; -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 - -/*Very rough estimate*/ -#define VID_CLOCK (double) (651 * 416 * 60) - -/* Mapping of attributes to colours */ -static uint32_t amber; -static uint32_t black; -static uint32_t blinkcols[256][2]; -static uint32_t normcols[256][2]; - -/* Video options set by the motherboard; they will be picked up by the card - * on the next poll. - * - * Bit 3: Disable built-in video (for add-on card) - * Bit 2: Thin font - * Bits 0,1: Font set (not currently implemented) - */ -static int8_t cpq_st_display_internal = -1; - -static uint8_t mdaattr[256][2][2]; - -static void -compaq_plasma_display_set(uint8_t internal) -{ - cpq_st_display_internal = internal; -} - -typedef struct compaq_plasma_t { - cga_t cga; - mem_mapping_t font_ram_mapping; - uint8_t *font_ram; - uint8_t port_13c6; - uint8_t port_23c6; - uint8_t port_27c6; - uint8_t internal_monitor; -} compaq_plasma_t; - static int compaq_machine_type = 0; /* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */ static mem_mapping_t ram_mapping; -static void compaq_plasma_recalcattrs(compaq_plasma_t *self); - -static void -compaq_plasma_recalctimings(compaq_plasma_t *self) -{ - double _dispontime; - double _dispofftime; - double disptime; - - if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { - cga_recalctimings(&self->cga); - return; - } - - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); - self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); -} - -static void -compaq_plasma_waitstates(UNUSED(void *priv)) -{ - int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 }; - int ws; - - ws = ws_array[cycles & 0xf]; - sub_cycles(ws); -} - -static void -compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - - if (self->port_23c6 & 0x08) - self->font_ram[addr & 0x1fff] = val; - else - self->cga.vram[addr & 0x7fff] = val; - - compaq_plasma_waitstates(&self->cga); -} -static uint8_t -compaq_plasma_read(uint32_t addr, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t ret; - - compaq_plasma_waitstates(&self->cga); - - if (self->port_23c6 & 0x08) - ret = (self->font_ram[addr & 0x1fff]); - else - ret = (self->cga.vram[addr & 0x7fff]); - - return ret; -} - -static void -compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - - switch (addr) { - /* Emulated CRTC, register select */ - case 0x3d0: - case 0x3d2: - case 0x3d4: - case 0x3d6: - cga_out(addr, val, &self->cga); - break; - - /* Emulated CRTC, value */ - case 0x3d1: - case 0x3d3: - case 0x3d5: - case 0x3d7: - cga_out(addr, val, &self->cga); - compaq_plasma_recalctimings(self); - break; - case 0x3d8: - case 0x3d9: - cga_out(addr, val, &self->cga); - break; - - case 0x13c6: - self->port_13c6 = val; - compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); - /* - For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA; - Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA; - This leads me to believe bit 2 is not relevant to the mode. - */ - if ((val & 0x03) == 0x03) - mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000); - else - mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000); - break; - - case 0x23c6: - self->port_23c6 = val; - compaq_plasma_recalcattrs(self); - break; - - case 0x27c6: - self->port_27c6 = val; - break; - - default: - break; - } -} - -static uint8_t -compaq_plasma_in(uint16_t addr, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x3d4: - case 0x3da: - case 0x3db: - case 0x3dc: - ret = cga_in(addr, &self->cga); - break; - - case 0x3d1: - case 0x3d3: - case 0x3d5: - case 0x3d7: - ret = cga_in(addr, &self->cga); - break; - - case 0x3d8: - ret = self->cga.cgamode; - break; - - case 0x13c6: - ret = self->port_13c6; -#if 0 - if ((self->cga.cgamode & 0x28) == 0x00) - ret |= 0x04; -#endif - break; - - case 0x17c6: - ret = 0xe6; - break; - - case 0x1bc6: - ret = 0x40; - break; - - case 0x23c6: - ret = self->port_23c6; - break; - - case 0x27c6: - ret = self->port_27c6 & 0x3f; - break; - - default: - break; - } - - return ret; -} - -static void -compaq_plasma_poll(void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t chr; - uint8_t attr; - uint8_t sc; - uint16_t ma = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; - uint16_t ca = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; - uint16_t addr; - int drawcursor; - int cursorline; - int blink = 0; - int underline = 0; - int c; - int x; - uint32_t ink = 0; - uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; - uint32_t bg = black; - uint32_t cols[2]; - uint8_t dat; - uint8_t pattern; - uint32_t ink0 = 0; - uint32_t ink1 = 0; - - /* Switch between internal plasma and external CRT display. */ - if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) { - self->internal_monitor = cpq_st_display_internal; - compaq_plasma_recalctimings(self); - } - - /* graphic mode and not mode 40h */ - if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { - /* standard cga mode */ - cga_poll(&self->cga); - return; - } else { - /* mode 40h or text mode */ - if (!self->cga.linepos) { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - if (self->cga.cgadispon) { - if (self->cga.displine == 0) - video_wait_for_buffer(); - - /* 80-col */ - if (self->cga.cgamode & 0x01) { - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; - ma += (self->cga.displine >> 4) * 80; - - if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); - - /* for each text column */ - for (x = 0; x < 80; x++) { - /* video output enabled */ - if (self->cga.cgamode & 0x08) { - /* character */ - chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; - /* text attributes */ - attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; - } else { - chr = 0x00; - attr = 0x00; - } - uint8_t hi_bit = attr & 0x08; - /* check if cursor has to be drawn */ - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); - /* check if character underline mode should be set */ - underline = ((attr & 0x07) == 0x01); - underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); - if (underline) { - /* set forecolor to white */ - attr = attr | 0x7; - } - blink = 0; - /* set foreground */ - cols[1] = blinkcols[attr][1]; - /* blink active */ - if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { - /* set blinking */ - cols[1] = cols[0]; - blink = 1; - } - } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - - /* character address */ - uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && hi_bit) - chr_addr |= 0x1000; - - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; - } - - if (hi_bit) { - if ((self->port_23c6 >> 5) == 1) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); - } else if ((self->port_23c6 >> 5) == 4) { - for (c = 0; c < 8; c++) { - uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f; - uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f; - uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f; - buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16); - } - } - } - ma++; - } - } - /* 40-col */ - else if (!(self->cga.cgamode & 0x02)) { - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; - ma += (self->cga.displine >> 4) * 40; - - if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); - - for (x = 0; x < 40; x++) { - /* video output enabled */ - if (self->cga.cgamode & 0x08) { - /* character */ - chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; - /* text attributes */ - attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; - } else { - chr = 0x00; - attr = 0x00; - } - uint8_t hi_bit = attr & 0x08; - /* check if cursor has to be drawn */ - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); - /* check if character underline mode should be set */ - underline = ((attr & 0x07) == 0x01); - underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); - if (underline) { - /* set forecolor to white */ - attr = attr | 0x7; - } - blink = 0; - /* set foreground */ - cols[1] = blinkcols[attr][1]; - /* blink active */ - if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { - /* set blinking */ - cols[1] = cols[0]; - blink = 1; - } - } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - - /* character address */ - uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && hi_bit) - chr_addr |= 0x1000; - - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; - } - - if (hi_bit) { - if ((self->port_23c6 >> 5) == 1) - for (c = 0; c < 8; c++) { - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black); - } - else if ((self->port_23c6 >> 5) == 4) - for (c = 0; c < 8; c++) { - uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f; - uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f; - uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f; - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); - } - } - ma++; - } - } else { - if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { - /* 640x400 mode */ - if (self->port_23c6 & 0x01) /* 640*400 */ { - addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7fff]; - addr++; - - for (uint8_t c = 0; c < 8; c++) { - ink = (dat & 0x80) ? fg : bg; - if (!(self->cga.cgamode & 0x08)) - ink = black; - buffer32->line[self->cga.displine][(x << 3) + c] = ink; - dat <<= 1; - } - } - } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7fff]; - addr++; - - for (uint8_t c = 0; c < 4; c++) { - pattern = (dat & 0xC0) >> 6; - if (!(self->cga.cgamode & 0x08)) - pattern = 0; - - switch (pattern & 3) { - case 0: - ink0 = ink1 = black; - break; - case 1: - if (self->cga.displine & 0x01) { - ink0 = black; - ink1 = black; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 2: - if (self->cga.displine & 0x01) { - ink0 = black; - ink1 = amber; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 3: - ink0 = ink1 = amber; - break; - - default: - break; - } - buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0; - buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1; - dat <<= 2; - } - } - } - } - } - self->cga.displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (self->cga.displine == 400) { /* Start of VSYNC */ - self->cga.cgastat |= 8; - self->cga.cgadispon = 0; - } - if (self->cga.displine == 416) { /* End of VSYNC */ - self->cga.displine = 0; - self->cga.cgastat &= ~8; - self->cga.cgadispon = 1; - } - } else { - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; - - self->cga.linepos = 0; - - if (self->cga.displine == 400) { - xsize = 640; - ysize = 400; - - if ((self->cga.cgamode & 0x08) || video_force_resize_get()) { - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - /* Plasma specific */ - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; - - /* Fixed 640x400 resolution */ - video_res_x = 640; - video_res_y = 400; - - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) - video_bpp = 1; - else - video_bpp = 2; - } else - video_bpp = 0; - - self->cga.cgablink++; - } - } - } -} - -static void -compaq_plasma_mdaattr_rebuild(void) -{ - for (uint16_t c = 0; c < 256; c++) { - mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16; - if (c & 8) - mdaattr[c][0][1] = 15 + 16; - else - mdaattr[c][0][1] = 7 + 16; - } - - mdaattr[0x70][0][1] = 16; - mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15; - mdaattr[0xF0][0][1] = 16; - mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15; - mdaattr[0x78][0][1] = 16 + 7; - mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15; - mdaattr[0xF8][0][1] = 16 + 7; - mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15; - mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16; - mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16; - mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16; - mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16; -} - -static void -compaq_plasma_recalcattrs(compaq_plasma_t *self) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - amber = makecol(0xff, 0x7d, 0x00); - black = makecol(0x64, 0x19, 0x00); - - /* Initialize the attribute mapping. Start by defaulting everything - * to black on amber, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } - - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always black on - * amber. */ - for (n = 0x11; n <= 0xFF; n++) { - if ((n & 7) == 0) - continue; - if ((self->port_23c6 >> 5) == 1) { /* Inverse */ - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } else { /* Normal */ - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - } - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) { - if (n == 7) - continue; - if ((self->port_23c6 >> 5) == 1) { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n + 128][0] = amber; - blinkcols[n + 128][1] = black; - } else { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n + 128][0] = black; - blinkcols[n + 128][1] = amber; - } - } - /* Colours 07 and 0F are always amber on black. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n + 128][0] = black; - blinkcols[n + 128][1] = amber; - } - /* When not blinking, colours 81-8F are always amber on black. */ - for (n = 0x81; n <= 0x8F; n++) { - normcols[n][0] = black; - normcols[n][1] = amber; - } - - /* Finally do the ones which are solid black. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - normcols[n][0] = normcols[n][1] = black; - - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ - for (n = 0; n <= 0x77; n += 0x11) { - blinkcols[n][0] = blinkcols[n][1] = black; - blinkcols[n + 128][0] = blinkcols[n + 128][1] = black; - } -} - -static void * -compaq_plasma_init(UNUSED(const device_t *info)) -{ - compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); - - cga_init(&self->cga); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); - - self->cga.composite = 0; - self->cga.revision = 0; - - self->cga.vram = malloc(0x8000); - self->internal_monitor = 1; - self->font_ram = malloc(0x2000); - - cga_comp_init(self->cga.revision); - timer_set_callback(&self->cga.timer, compaq_plasma_poll); - timer_set_p(&self->cga.timer, self); - - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, - compaq_plasma_read, NULL, NULL, - compaq_plasma_write, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, self); - for (int i = 1; i <= 2; i++) { - io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - } - io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - - overscan_x = overscan_y = 16; - - self->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (self->cga.rgb_type << 1); - cgapal_rebuild(); - compaq_plasma_mdaattr_rebuild(); - - return self; -} - -static void -compaq_plasma_close(void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - - free(self->cga.vram); - free(self->font_ram); - free(self); -} - -static void -compaq_plasma_speed_changed(void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - - compaq_plasma_recalctimings(self); -} - -const device_config_t compaq_plasma_config[] = { - // clang-format off - { - .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "Color", .value = 0 }, - { .description = "Green Monochrome", .value = 1 }, - { .description = "Amber Monochrome", .value = 2 }, - { .description = "Gray Monochrome", .value = 3 }, - { .description = "" } - } - }, - { .name = "", .description = "", .type = CONFIG_END } - // clang-format on -}; - -const device_t compaq_plasma_device = { - .name = "Compaq Plasma", - .internal_name = "compaq_plasma", - .flags = 0, - .local = 0, - .init = compaq_plasma_init, - .close = compaq_plasma_close, - .reset = NULL, - .available = NULL, - .speed_changed = compaq_plasma_speed_changed, - .force_redraw = NULL, - .config = compaq_plasma_config -}; static uint8_t read_ram(uint32_t addr, UNUSED(void *priv)) diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index f2da2e2b5..e76889d93 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -48,11 +48,10 @@ #include <86box/snd_sn76489.h> #include <86box/video.h> #include <86box/vid_cga_comp.h> +#include <86box/m_pcjr.h> #include <86box/machine.h> #include <86box/plat_unused.h> -#define PCJR_RGB 0 -#define PCJR_COMPOSITE 1 #define STAT_PARITY 0x80 #define STAT_RTIMEOUT 0x40 @@ -63,49 +62,10 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -typedef struct pcjr_t { - /* Video Controller stuff. */ - mem_mapping_t mapping; - uint8_t crtc[32]; - int crtcreg; - int array_index; - uint8_t array[32]; - int array_ff; - int memctrl; - uint8_t stat; - int addr_mode; - uint8_t *vram; - uint8_t *b8000; - int linepos; - int displine; - int sc; - int vc; - int dispon; - int con; - int cursoron; - int blink; - int vsynctime; - int fullchange; - int vadj; - uint16_t ma; - uint16_t maback; - uint64_t dispontime; - uint64_t dispofftime; - pc_timer_t timer; - int firstline; - int lastline; - int composite; - int apply_hd; - /* Keyboard Controller stuff. */ - int latched; - int data; - int serial_data[44]; - int serial_pos; - uint8_t pa; - uint8_t pb; - pc_timer_t send_delay_timer; -} pcjr_t; +static uint8_t key_queue[16]; +static int key_queue_start = 0; +static int key_queue_end = 0; /*PCjr keyboard has no escape scancodes, and no scancodes beyond 54 Map right alt to 54h (FN) */ @@ -626,643 +586,6 @@ const scancode scancode_pcjr[512] = { // clang-format on }; -static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ - -static uint8_t crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static uint8_t key_queue[16]; -static int key_queue_start = 0; -static int key_queue_end = 0; - -static void -recalc_address(pcjr_t *pcjr) -{ - uint8_t masked_memctrl = pcjr->memctrl; - - /* According to the Technical Reference, bits 2 and 5 are - ignored if there is only 64k of RAM and there are only - 4 pages. */ - if (mem_size < 128) - masked_memctrl &= ~0x24; - - if ((pcjr->memctrl & 0xc0) == 0xc0) { - pcjr->vram = &ram[(masked_memctrl & 0x06) << 14]; - pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11]; - } else { - pcjr->vram = &ram[(masked_memctrl & 0x07) << 14]; - pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11]; - } -} - -static void -recalc_timings(pcjr_t *pcjr) -{ - double _dispontime; - double _dispofftime; - double disptime; - - if (pcjr->array[0] & 1) { - disptime = pcjr->crtc[0] + 1; - _dispontime = pcjr->crtc[1]; - } else { - disptime = (pcjr->crtc[0] + 1) << 1; - _dispontime = pcjr->crtc[1] << 1; - } - - _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; - _dispofftime *= CGACONST; - pcjr->dispontime = (uint64_t) (_dispontime); - pcjr->dispofftime = (uint64_t) (_dispofftime); -} - -static int -vid_get_h_overscan_size(pcjr_t *pcjr) -{ - int ret; - - if (pcjr->array[0] & 1) - ret = 128; - else - ret = 256; - - return ret; -} - -static void -vid_out(uint16_t addr, uint8_t val, void *priv) -{ - pcjr_t *pcjr = (pcjr_t *) priv; - uint8_t old; - - switch (addr) { - case 0x3d0: - case 0x3d2: - case 0x3d4: - case 0x3d6: - pcjr->crtcreg = val & 0x1f; - return; - - case 0x3d1: - case 0x3d3: - case 0x3d5: - case 0x3d7: - old = pcjr->crtc[pcjr->crtcreg]; - pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg]; - if (pcjr->crtcreg == 2) - overscan_x = vid_get_h_overscan_size(pcjr); - if (old != val) { - if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) { - pcjr->fullchange = changeframecount; - recalc_timings(pcjr); - } - } - return; - - case 0x3da: - if (!pcjr->array_ff) - pcjr->array_index = val & 0x1f; - else { - if (pcjr->array_index & 0x10) - val &= 0x0f; - pcjr->array[pcjr->array_index & 0x1f] = val; - if (!(pcjr->array_index & 0x1f)) - update_cga16_color(val); - } - pcjr->array_ff = !pcjr->array_ff; - break; - - case 0x3df: - pcjr->memctrl = val; - pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to - then be readable from port 60, others it errors out - with only 64k RAM set (but somehow, still works with - 128k or more RAM). */ - pcjr->addr_mode = val >> 6; - recalc_address(pcjr); - break; - - default: - break; - } -} - -static uint8_t -vid_in(uint16_t addr, void *priv) -{ - pcjr_t *pcjr = (pcjr_t *) priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x3d0: - case 0x3d2: - case 0x3d4: - case 0x3d6: - ret = pcjr->crtcreg; - break; - - case 0x3d1: - case 0x3d3: - case 0x3d5: - case 0x3d7: - ret = pcjr->crtc[pcjr->crtcreg]; - break; - - case 0x3da: - pcjr->array_ff = 0; - pcjr->stat ^= 0x10; - ret = pcjr->stat; - break; - - default: - break; - } - - return ret; -} - -static void -vid_write(uint32_t addr, uint8_t val, void *priv) -{ - pcjr_t *pcjr = (pcjr_t *) priv; - - if (pcjr->memctrl == -1) - return; - - pcjr->b8000[addr & 0x3fff] = val; -} - -static uint8_t -vid_read(uint32_t addr, void *priv) -{ - const pcjr_t *pcjr = (pcjr_t *) priv; - - if (pcjr->memctrl == -1) - return 0xff; - - return (pcjr->b8000[addr & 0x3fff]); -} - -static int -vid_get_h_overscan_delta(pcjr_t *pcjr) -{ - int def; - int coef; - int ret; - - switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { - case 0x13: /*320x200x16*/ - def = 0x56; - coef = 8; - break; - case 0x12: /*160x200x16*/ - def = 0x2c; /* I'm going to assume a datasheet erratum here. */ - coef = 16; - break; - case 0x03: /*640x200x4*/ - def = 0x56; - coef = 8; - break; - case 0x01: /*80 column text*/ - def = 0x5a; - coef = 8; - break; - case 0x00: /*40 column text*/ - default: - def = 0x2c; - coef = 16; - break; - case 0x02: /*320x200x4*/ - def = 0x2b; - coef = 16; - break; - case 0x102: /*640x200x2*/ - def = 0x2b; - coef = 16; - break; - } - - ret = pcjr->crtc[0x02] - def; - - if (ret < -8) - ret = -8; - - if (ret > 8) - ret = 8; - - return ret * coef; -} - -static void -vid_blit_h_overscan(pcjr_t *pcjr) -{ - int cols = (pcjr->array[2] & 0xf) + 16;; - int y0 = pcjr->firstline << 1; - int y = (pcjr->lastline << 1) + 16; - int ho_s = vid_get_h_overscan_size(pcjr); - int i; - int x; - - if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + ho_s; - else - x = (pcjr->crtc[1] << 4) + ho_s; - - for (i = 0; i < 16; i++) { - hline(buffer32, 0, y0 + i, x, cols); - hline(buffer32, 0, y + i, x, cols); - - if (pcjr->composite) { - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y0 + i]); - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y + i]); - } else { - video_process_8(x, y0 + i); - video_process_8(x, y + i); - } - } -} - -static void -vid_poll(void *priv) -{ - pcjr_t *pcjr = (pcjr_t *) priv; - uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x; - int xs_temp; - int ys_temp; - int oldvc; - uint8_t chr; - uint8_t attr; - uint16_t dat; - int cols[4]; - int oldsc; - int l = (pcjr->displine << 1) + 16; - int ho_s = vid_get_h_overscan_size(pcjr); - int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2); - - if (!pcjr->linepos) { - timer_advance_u64(&pcjr->timer, pcjr->dispofftime); - pcjr->stat &= ~1; - pcjr->linepos = 1; - oldsc = pcjr->sc; - if ((pcjr->crtc[8] & 3) == 3) - pcjr->sc = (pcjr->sc << 1) & 7; - if (pcjr->dispon) { - uint16_t offset = 0; - uint16_t mask = 0x1fff; - - if (pcjr->displine < pcjr->firstline) { - pcjr->firstline = pcjr->displine; - video_wait_for_buffer(); - } - pcjr->lastline = pcjr->displine; - cols[0] = (pcjr->array[2] & 0xf) + 16; - - if (pcjr->array[0] & 1) { - hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]); - hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]); - } else { - hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]); - hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]); - } - - switch (pcjr->addr_mode) { - case 0: /*Alpha*/ - offset = 0; - mask = 0x3fff; - break; - case 1: /*Low resolution graphics*/ - offset = (pcjr->sc & 1) * 0x2000; - break; - case 3: /*High resolution graphics*/ - offset = (pcjr->sc & 3) * 0x2000; - break; - default: - break; - } - switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { - case 0x13: /*320x200x16*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 3) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = - buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = - pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; - buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = - buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = - pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16; - buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] = - buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] = - pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; - buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] = - buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] = - pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16; - } - break; - case 0x12: /*160x200x16*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 4) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = - buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = - buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = - buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = - pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; - buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] = - buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] = - buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] = - buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] = - pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16; - buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] = - buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] = - buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] = - buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] = - pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; - buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] = - buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] = - buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] = - buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] = - pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16; - } - break; - case 0x03: /*640x200x4*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 3) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - pcjr->ma++; - for (uint8_t c = 0; c < 8; c++) { - chr = (dat >> 7) & 1; - chr |= ((dat >> 14) & 2); - buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = - pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16; - dat <<= 1; - } - } - break; - case 0x01: /*80 column text*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 3) + ho_d; - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); - if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; - if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; - } - if (pcjr->sc & 8) - for (uint8_t c = 0; c < 8; c++) - buffer32->line[l][ef_x + c] = - buffer32->line[l + 1][ef_x + c] = cols[0]; - else - for (uint8_t c = 0; c < 8; c++) - buffer32->line[l][ef_x + c] = - buffer32->line[l + 1][ef_x + c] = - cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - if (drawcursor) - for (uint8_t c = 0; c < 8; c++) { - buffer32->line[l][ef_x + c] ^= 15; - buffer32->line[l + 1][ef_x + c] ^= 15; - } - pcjr->ma++; - } - break; - case 0x00: /*40 column text*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 4) + ho_d; - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); - if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; - if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; - } - pcjr->ma++; - if (pcjr->sc & 8) - for (uint8_t c = 0; c < 8; c++) - buffer32->line[l][ef_x + (c << 1)] = - buffer32->line[l][ef_x + (c << 1) + 1] = - buffer32->line[l + 1][ef_x + (c << 1)] = - buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0]; - else - for (uint8_t c = 0; c < 8; c++) - buffer32->line[l][ef_x + (c << 1)] = - buffer32->line[l][ef_x + (c << 1) + 1] = - buffer32->line[l + 1][ef_x + (c << 1)] = - buffer32->line[l + 1][ef_x + (c << 1) + 1] = - cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - if (drawcursor) - for (uint8_t c = 0; c < 16; c++) { - buffer32->line[l][ef_x + c] ^= 15; - buffer32->line[l + 1][ef_x + c] ^= 15; - } - } - break; - case 0x02: /*320x200x4*/ - cols[0] = pcjr->array[0 + 16] + 16; - cols[1] = pcjr->array[1 + 16] + 16; - cols[2] = pcjr->array[2 + 16] + 16; - cols[3] = pcjr->array[3 + 16] + 16; - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 4) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - for (uint8_t c = 0; c < 8; c++) { - buffer32->line[l][ef_x + (c << 1)] = - buffer32->line[l][ef_x + (c << 1) + 1] = - buffer32->line[l + 1][ef_x + (c << 1)] = - buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14]; - dat <<= 2; - } - } - break; - case 0x102: /*640x200x2*/ - cols[0] = pcjr->array[0 + 16] + 16; - cols[1] = pcjr->array[1 + 16] + 16; - for (x = 0; x < pcjr->crtc[1]; x++) { - int ef_x = (x << 4) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - for (uint8_t c = 0; c < 16; c++) { - buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = - cols[dat >> 15]; - dat <<= 1; - } - } - break; - - default: - break; - } - } else { - if (pcjr->array[3] & 4) { - if (pcjr->array[0] & 1) { - hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); - hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); - } else { - hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16); - hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16); - } - } else { - cols[0] = pcjr->array[0 + 16] + 16; - if (pcjr->array[0] & 1) { - hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]); - hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]); - } else { - hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]); - hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]); - } - } - } - if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + ho_s; - else - x = (pcjr->crtc[1] << 4) + ho_s; - if (pcjr->composite) { - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]); - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]); - } else { - video_process_8(x, l); - video_process_8(x, l + 1); - } - pcjr->sc = oldsc; - if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { - pcjr->stat |= 8; - } - pcjr->displine++; - if (pcjr->displine >= 360) - pcjr->displine = 0; - } else { - timer_advance_u64(&pcjr->timer, pcjr->dispontime); - if (pcjr->dispon) - pcjr->stat |= 1; - pcjr->linepos = 0; - if (pcjr->vsynctime) { - pcjr->vsynctime--; - if (!pcjr->vsynctime) { - pcjr->stat &= ~8; - } - } - if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { - pcjr->con = 0; - } - if (pcjr->vadj) { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; - pcjr->vadj--; - if (!pcjr->vadj) { - pcjr->dispon = 1; - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - pcjr->sc = 0; - } - } else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) { - pcjr->maback = pcjr->ma; - pcjr->sc = 0; - oldvc = pcjr->vc; - pcjr->vc++; - pcjr->vc &= 127; - if (pcjr->vc == pcjr->crtc[6]) - pcjr->dispon = 0; - if (oldvc == pcjr->crtc[4]) { - pcjr->vc = 0; - pcjr->vadj = pcjr->crtc[5]; - if (!pcjr->vadj) - pcjr->dispon = 1; - if (!pcjr->vadj) - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - if ((pcjr->crtc[10] & 0x60) == 0x20) - pcjr->cursoron = 0; - else - pcjr->cursoron = pcjr->blink & 16; - } - if (pcjr->vc == pcjr->crtc[7]) { - pcjr->dispon = 0; - pcjr->displine = 0; - pcjr->vsynctime = 16; - picint(1 << 5); - if (pcjr->crtc[7]) { - if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + ho_s; - else - x = (pcjr->crtc[1] << 4) + ho_s; - pcjr->lastline++; - - xs_temp = x; - ys_temp = (pcjr->lastline - pcjr->firstline) << 1; - - if ((xs_temp > 0) && (ys_temp > 0)) { - int actual_ys = ys_temp; - - if (xs_temp < 64) - xs_temp = 656; - if (ys_temp < 32) - ys_temp = 400; - if (!enable_overscan) - xs_temp -= ho_s; - - if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { - xsize = xs_temp; - ysize = ys_temp; - - set_screen_size(xsize, ysize + (enable_overscan ? 32 : 0)); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - vid_blit_h_overscan(pcjr); - - if (enable_overscan) { - video_blit_memtoscreen(0, pcjr->firstline << 1, - xsize, actual_ys + 32); - } else if (pcjr->apply_hd) { - video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16, - xsize, actual_ys); - } else { - video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16, - xsize, actual_ys); - } - } - - frames++; - video_res_x = xsize; - video_res_y = ysize; - } - pcjr->firstline = 1000; - pcjr->lastline = 0; - pcjr->blink++; - } - } else { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; - } - if (pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1))) - pcjr->con = 1; - } -} static void kbd_write(uint16_t port, uint8_t val, void *priv) @@ -1433,35 +756,7 @@ speed_changed(void *priv) { pcjr_t *pcjr = (pcjr_t *) priv; - recalc_timings(pcjr); -} - -static void -pcjr_vid_init(pcjr_t *pcjr) -{ - int display_type; - - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); - - pcjr->memctrl = -1; - if (mem_size < 128) - pcjr->memctrl &= ~0x24; - - display_type = device_get_config_int("display_type"); - pcjr->composite = (display_type != PCJR_RGB); - pcjr->apply_hd = device_get_config_int("apply_hd"); - overscan_x = 256; - overscan_y = 32; - - mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, pcjr); - io_sethandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); - timer_add(&pcjr->timer, vid_poll, pcjr, 1); - - cga_palette = 0; - cgapal_rebuild(); + pcjr_recalc_timings(pcjr); } void diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 4d0768378..69200febe 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -44,12 +44,9 @@ #include <86box/video.h> #include <86box/vid_cga_comp.h> #include <86box/machine.h> +#include <86box/m_tandy.h> #include <86box/plat_unused.h> -enum { - TANDY_RGB = 0, - TANDY_COMPOSITE -}; enum { TYPE_TANDY = 0, @@ -65,79 +62,6 @@ enum { EEPROM_WRITE }; -typedef struct t1kvid_t { - mem_mapping_t mapping; - mem_mapping_t vram_mapping; - - uint8_t crtc[32]; - int crtcreg; - - int array_index; - uint8_t array[256]; - int memctrl; - uint8_t mode; - uint8_t col; - uint8_t stat; - - uint8_t *vram; - uint8_t *b8000; - uint32_t b8000_mask; - uint32_t b8000_limit; - uint8_t planar_ctrl; - uint8_t lp_strobe; - - int linepos; - int displine; - int sc; - int vc; - int dispon; - int con; - int cursoron; - int blink; - int fullchange; - int vsynctime; - int vadj; - uint16_t ma; - uint16_t maback; - - uint64_t dispontime; - uint64_t dispofftime; - pc_timer_t timer; - int firstline; - int lastline; - - int composite; -} t1kvid_t; - -typedef struct t1keep_t { - char *path; - - int state; - int count; - int addr; - int clk; - uint16_t data; - uint16_t store[64]; -} t1keep_t; - -typedef struct tandy_t { - mem_mapping_t ram_mapping; - mem_mapping_t rom_mapping; /* SL2 */ - - uint8_t *rom; /* SL2 */ - uint8_t ram_bank; - uint8_t rom_bank; /* SL2 */ - int rom_offset; /* SL2 */ - - uint32_t base; - uint32_t mask; - int is_hx; - int is_sl2; - - t1kvid_t *vid; -} tandy_t; - -static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ static const scancode scancode_tandy[512] = { // clang-format off @@ -655,22 +579,8 @@ static const scancode scancode_tandy[512] = { { .mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; -static uint8_t crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static uint8_t crtcmask_sl[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static int eep_data_out; -static uint8_t vid_in(uint16_t addr, void *priv); -static void vid_out(uint16_t addr, uint8_t val, void *priv); +static int eep_data_out; #ifdef ENABLE_TANDY_LOG int tandy_do_log = ENABLE_TANDY_LOG; @@ -690,762 +600,7 @@ tandy_log(const char *fmt, ...) # define tandy_log(fmt, ...) #endif -static void -recalc_mapping(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - mem_mapping_disable(&vid->mapping); - io_removehandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); - - if (vid->planar_ctrl & 4) { - mem_mapping_enable(&vid->mapping); - if (vid->array[5] & 1) - mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000); - else - mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000); - io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); - } -} - -static void -recalc_timings(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - double _dispontime; - double _dispofftime; - double disptime; - - if (vid->mode & 1) { - disptime = vid->crtc[0] + 1; - _dispontime = vid->crtc[1]; - } else { - disptime = (vid->crtc[0] + 1) << 1; - _dispontime = vid->crtc[1] << 1; - } - - _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; - _dispofftime *= CGACONST; - vid->dispontime = (uint64_t) (_dispontime); - vid->dispofftime = (uint64_t) (_dispofftime); -} - -static void -recalc_address(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - if ((vid->memctrl & 0xc0) == 0xc0) { - vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; - vid->b8000_mask = 0x7fff; - } else { - vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; - vid->b8000_mask = 0x3fff; - } -} - -static void -recalc_address_sl(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - vid->b8000_limit = 0x8000; - - if (vid->array[5] & 1) { - vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base]; - } else if ((vid->memctrl & 0xc0) == 0xc0) { - vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; - } else { - vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; - if ((vid->memctrl & 0x38) == 0x38) - vid->b8000_limit = 0x4000; - } -} - -static void -vid_update_latch(t1kvid_t *vid) -{ - uint32_t lp_latch = vid->displine * vid->crtc[1]; - - vid->crtc[0x10] = (lp_latch >> 8) & 0x3f; - vid->crtc[0x11] = lp_latch & 0xff; -} - -static void -vid_out(uint16_t addr, uint8_t val, void *priv) -{ - tandy_t *dev = (tandy_t *) priv; - t1kvid_t *vid = dev->vid; - uint8_t old; - - if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; - - switch (addr) { - case 0x03d4: - vid->crtcreg = val & 0x1f; - break; - - case 0x03d5: - old = vid->crtc[vid->crtcreg]; - if (dev->is_sl2) - vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; - else - vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; - if (old != val) { - if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { - vid->fullchange = changeframecount; - recalc_timings(dev); - } - } - break; - - case 0x03d8: - old = vid->mode; - vid->mode = val; - if ((old ^ val) & 0x01) - recalc_timings(dev); - if (!dev->is_sl2) - update_cga16_color(vid->mode); - break; - - case 0x03d9: - vid->col = val; - break; - - case 0x03da: - vid->array_index = val & 0x1f; - break; - - case 0x3db: - if (!dev->is_sl2 && (vid->lp_strobe == 1)) - vid->lp_strobe = 0; - break; - - case 0x3dc: - if (!dev->is_sl2 && (vid->lp_strobe == 0)) { - vid->lp_strobe = 1; - vid_update_latch(vid); - } - break; - - case 0x03de: - if (vid->array_index & 16) - val &= 0xf; - vid->array[vid->array_index & 0x1f] = val; - if (dev->is_sl2) { - if ((vid->array_index & 0x1f) == 5) { - recalc_mapping(dev); - recalc_address_sl(dev); - } - } - break; - - case 0x03df: - vid->memctrl = val; - if (dev->is_sl2) - recalc_address_sl(dev); - else - recalc_address(dev); - break; - - case 0x0065: - if (val == 8) - return; /*Hack*/ - vid->planar_ctrl = val; - recalc_mapping(dev); - break; - - default: - break; - } -} - -static uint8_t -vid_in(uint16_t addr, void *priv) -{ - const tandy_t *dev = (tandy_t *) priv; - t1kvid_t *vid = dev->vid; - uint8_t ret = 0xff; - - if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; - - switch (addr) { - case 0x03d4: - ret = vid->crtcreg; - break; - - case 0x03d5: - ret = vid->crtc[vid->crtcreg]; - break; - - case 0x03da: - ret = vid->stat; - break; - - case 0x3db: - if (!dev->is_sl2 && (vid->lp_strobe == 1)) - vid->lp_strobe = 0; - break; - - case 0x3dc: - if (!dev->is_sl2 && (vid->lp_strobe == 0)) { - vid->lp_strobe = 1; - vid_update_latch(vid); - } - break; - - default: - break; - } - - return ret; -} - -static void -vid_write(uint32_t addr, uint8_t val, void *priv) -{ - tandy_t *dev = (tandy_t *) priv; - t1kvid_t *vid = dev->vid; - - if (vid->memctrl == -1) - return; - - if (dev->is_sl2) { - if (vid->array[5] & 1) - vid->b8000[addr & 0xffff] = val; - else { - if ((addr & 0x7fff) < vid->b8000_limit) - vid->b8000[addr & 0x7fff] = val; - } - } else { - vid->b8000[addr & vid->b8000_mask] = val; - } -} - -static uint8_t -vid_read(uint32_t addr, void *priv) -{ - const tandy_t *dev = (tandy_t *) priv; - const t1kvid_t *vid = dev->vid; - - if (vid->memctrl == -1) - return 0xff; - - if (dev->is_sl2) { - if (vid->array[5] & 1) - return (vid->b8000[addr & 0xffff]); - if ((addr & 0x7fff) < vid->b8000_limit) - return (vid->b8000[addr & 0x7fff]); - else - return 0xff; - } else { - return (vid->b8000[addr & vid->b8000_mask]); - } -} - -static void -vid_poll(void *priv) -{ - tandy_t *dev = (tandy_t *) priv; - t1kvid_t *vid = dev->vid; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x; - int c; - int xs_temp; - int ys_temp; - int oldvc; - uint8_t chr; - uint8_t attr; - uint16_t dat; - int cols[4]; - int col; - int oldsc; - - if (!vid->linepos) { - timer_advance_u64(&vid->timer, vid->dispofftime); - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if ((vid->crtc[8] & 3) == 3) - vid->sc = (vid->sc << 1) & 7; - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_wait_for_buffer(); - } - vid->lastline = vid->displine; - cols[0] = (vid->array[2] & 0xf) + 16; - for (c = 0; c < 8; c++) { - if (vid->array[3] & 4) { - buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = cols[0]; - if (vid->mode & 1) { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = cols[0]; - } else { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = cols[0]; - } - } else if ((vid->mode & 0x12) == 0x12) { - buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = 0; - if (vid->mode & 1) { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; - } else { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; - } - } else { - buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->col & 15) + 16; - if (vid->mode & 1) { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16; - } else { - buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16; - } - } - } - if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/ - for (x = 0; x < vid->crtc[1] * 2; x++) { - dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | vid->vram[((vid->ma << 1) + 1) & 0xffff]; - vid->ma++; - buffer32->line[vid->displine << 1][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 2) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 11] = vid->array[(dat & 0xf) + 16] + 16; - } - } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16; - } - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - if (dev->is_sl2) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - } else { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - } - vid->ma++; - buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16; - } - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - chr = (dat >> 6) & 2; - chr |= ((dat >> 15) & 1); - buffer32->line[vid->displine << 1][(x << 3) + 8 + c] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16; - dat <<= 1; - } - } - } else if (vid->mode & 1) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[(vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - if (vid->sc & 8) { - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; - } - } else { - for (c = 0; c < 8; c++) { - if (vid->sc == 8) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; - } else { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] ^= 15; - buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15; - } - } - vid->ma++; - } - } else if (!(vid->mode & 2)) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[(vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - vid->ma++; - if (vid->sc & 8) { - for (c = 0; c < 8; c++) - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; - } else { - for (c = 0; c < 8; c++) { - if (vid->sc == 8) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; - } else { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - if (drawcursor) { - for (c = 0; c < 16; c++) { - buffer32->line[vid->displine << 1][(x << 4) + c + 8] ^= 15; - buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] ^= 15; - } - } - } - } else if (!(vid->mode & 16)) { - cols[0] = (vid->col & 15); - col = (vid->col & 16) ? 8 : 0; - if (vid->mode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->col & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16; - cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16; - cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16; - cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16; - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - cols[0] = 0; - cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - if (vid->array[3] & 4) { - if (vid->mode & 1) { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); - } else { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); - } - } else { - cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; - if (vid->mode & 1) { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); - } else { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, cols[0]); - } - } - } - - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - if (!dev->is_sl2 && vid->composite) { - Composite_Process(vid->mode, 0, x >> 2, buffer32->line[vid->displine << 1]); - Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1) + 1]); - } else { - video_process_8(x, vid->displine << 1); - video_process_8(x, (vid->displine << 1) + 1); - } - vid->sc = oldsc; - if (vid->vc == vid->crtc[7] && !vid->sc) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; - } else { - timer_advance_u64(&vid->timer, vid->dispontime); - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (!vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { - vid->con = 0; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (!vid->vadj) { - vid->dispon = 1; - if (dev->is_sl2 && (vid->array[5] & 1)) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); - else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { - vid->maback = vid->ma; - vid->sc = 0; - oldvc = vid->vc; - vid->vc++; - if (dev->is_sl2) - vid->vc &= 255; - else - vid->vc &= 127; - if (vid->vc == vid->crtc[6]) - vid->dispon = 0; - if (oldvc == vid->crtc[4]) { - vid->vc = 0; - vid->vadj = vid->crtc[5]; - if (!vid->vadj) - vid->dispon = 1; - if (!vid->vadj) { - if (dev->is_sl2 && (vid->array[5] & 1)) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); - else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - } - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } - if (vid->vc == vid->crtc[7]) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 16; - picint(1 << 5); - if (vid->crtc[7]) { - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; - - xs_temp = x; - ys_temp = (vid->lastline - vid->firstline) << 1; - - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) - xs_temp = 656; - if (ys_temp < 32) - ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; - - if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (enable_overscan) { - video_blit_memtoscreen(0, (vid->firstline - 4) << 1, - xsize, ((vid->lastline - vid->firstline) + 8) << 1); - } else { - video_blit_memtoscreen(8, vid->firstline << 1, - xsize, (vid->lastline - vid->firstline) << 1); - } - } - - frames++; - - video_res_x = xsize; - video_res_y = ysize; - if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - video_res_x /= 2; - video_bpp = 4; - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - video_res_x /= 4; - video_bpp = 4; - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - video_bpp = 2; - } else if (vid->mode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (!(vid->mode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (!(vid->mode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 1; - } - } - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if (vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1))) - vid->con = 1; - } -} - -static void -vid_speed_changed(void *priv) -{ - tandy_t *dev = (tandy_t *) priv; - - recalc_timings(dev); -} - -static void -vid_close(void *priv) -{ - tandy_t *dev = (tandy_t *) priv; - - free(dev->vid); - dev->vid = NULL; -} - -static void -vid_init(tandy_t *dev) -{ - int display_type; - t1kvid_t *vid; - - vid = calloc(1, sizeof(t1kvid_t)); - vid->memctrl = -1; - - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); - - display_type = device_get_config_int("display_type"); - vid->composite = (display_type != TANDY_RGB); - - cga_comp_init(1); - - if (dev->is_sl2) { - vid->b8000_limit = 0x8000; - vid->planar_ctrl = 4; - overscan_x = overscan_y = 16; - - io_sethandler(0x0065, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); - } else - vid->b8000_mask = 0x3fff; - - timer_add(&vid->timer, vid_poll, dev, 1); - mem_mapping_add(&vid->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev); - io_sethandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); - - dev->vid = vid; -} - -const device_config_t vid_config[] = { - // clang-format off - { - .name = "display_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = TANDY_RGB, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "RGB", .value = TANDY_RGB }, - { .description = "Composite", .value = TANDY_COMPOSITE }, - { .description = "" } - } - }, - { .name = "", .description = "", .type = CONFIG_END } - // clang-format on -}; - -const device_t vid_device = { - .name = "Tandy 1000", - .internal_name = "tandy1000_video", - .flags = 0, - .local = 0, - .init = NULL, - .close = vid_close, - .reset = NULL, - .available = NULL, - .speed_changed = vid_speed_changed, - .force_redraw = NULL, - .config = vid_config -}; - -const device_t vid_device_hx = { - .name = "Tandy 1000 HX", - .internal_name = "tandy1000_hx_video", - .flags = 0, - .local = 0, - .init = NULL, - .close = vid_close, - .reset = NULL, - .available = NULL, - .speed_changed = vid_speed_changed, - .force_redraw = NULL, - .config = vid_config -}; - -const device_t vid_device_sl = { - .name = "Tandy 1000SL2", - .internal_name = "tandy1000_sl_video", - .flags = 0, - .local = 1, - .init = NULL, - .close = vid_close, - .reset = NULL, - .available = NULL, - .speed_changed = vid_speed_changed, - .force_redraw = NULL, - .config = NULL -}; static void eep_write(UNUSED(uint16_t addr), uint8_t val, void *priv) @@ -1630,12 +785,12 @@ tandy_write(uint16_t addr, uint8_t val, void *priv) } if (dev->is_hx) { io_removehandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev); if (val & 0x01) mem_mapping_disable(&dev->vid->mapping); else { io_sethandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev); mem_mapping_set_addr(&dev->vid->mapping, 0xb8000, 0x8000); } } else { @@ -1654,7 +809,7 @@ tandy_write(uint16_t addr, uint8_t val, void *priv) mem_mapping_set_addr(&dev->ram_mapping, ((val >> 1) & 7) * 128 * 1024, 0x20000); - recalc_address_sl(dev); + tandy_recalc_address_sl(dev); dev->ram_bank = val; break; @@ -1803,10 +958,10 @@ machine_tandy1k_init(const machine_t *model, int type) keyboard_set_table(scancode_tandy); io_sethandler(0x00a0, 1, tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); - device_context(&vid_device); - vid_init(dev); + device_context(&tandy_1000_video_device); + tandy_vid_init(dev); device_context_restore(); - device_add_ex(&vid_device, dev); + device_add_ex(&tandy_1000_video_device, dev); device_add((type == TYPE_TANDY1000SX) ? &ncr8496_device : &sn76489_device); break; @@ -1815,10 +970,10 @@ machine_tandy1k_init(const machine_t *model, int type) keyboard_set_table(scancode_tandy); io_sethandler(0x00a0, 1, tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); - device_context(&vid_device_hx); - vid_init(dev); + device_context(&tandy_1000hx_video_device); + tandy_vid_init(dev); device_context_restore(); - device_add_ex(&vid_device_hx, dev); + device_add_ex(&tandy_1000hx_video_device, dev); device_add(&ncr8496_device); device_add(&eep_1000hx_device); break; @@ -1828,10 +983,10 @@ machine_tandy1k_init(const machine_t *model, int type) init_rom(dev); io_sethandler(0xffe8, 8, tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); - device_context(&vid_device_sl); - vid_init(dev); + device_context(&tandy_1000sl_video_device); + tandy_vid_init(dev); device_context_restore(); - device_add_ex(&vid_device_sl, dev); + device_add_ex(&tandy_1000sl_video_device, dev); device_add(&pssj_device); device_add(&eep_1000sl2_device); break; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 611e70c4d..3e1e00b2f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -39,8 +39,10 @@ // Temporarily here till we move everything out into the right files extern const device_t pcjr_device; extern const device_t m19_vid_device; -extern const device_t vid_device; -extern const device_t vid_device_hx; +extern const device_t tandy_1000_video_device; +extern const device_t tandy_1000hx_video_device; +extern const device_t tandy_1000sl_video_device; + extern const device_t t1000_video_device; extern const device_t xi8088_device; extern const device_t cga_device; @@ -50,7 +52,6 @@ extern const device_t vid_pc2086_device; extern const device_t vid_pc3086_device; extern const device_t vid_200_device; extern const device_t vid_ppc512_device; -extern const device_t vid_device_sl; extern const device_t t1200_video_device; extern const device_t compaq_plasma_device; extern const device_t ps1_2011_device; @@ -1590,7 +1591,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &vid_device, + .vid_device = &tandy_1000_video_device, .snd_device = NULL, .net_device = NULL }, @@ -1629,7 +1630,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &vid_device_hx, + .vid_device = &tandy_1000hx_video_device, .snd_device = NULL, .net_device = NULL }, @@ -2530,7 +2531,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &vid_device_sl, + .vid_device = &tandy_1000sl_video_device, .snd_device = NULL, .net_device = NULL }, diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 062fc272a..09c49dabe 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -11,20 +11,32 @@ # Authors: David Hrdlička, <hrdlickadavid@outlook.com> # # Copyright 2020-2021 David Hrdlička. +# Copyright 2025 starfrost # add_library(vid OBJECT agpgart.c video.c vid_table.c + # CGA vid_cga.c vid_cga_comp.c - vid_compaq_cga.c + vid_cga_compaq.c + vid_cga_compaq_plasma.c + vid_cga_colorplus.c + vid_cga_ncr.c + vid_cga_olivetti.c + vid_cga_toshiba_t1000.c + vid_cga_toshiba_t3100e.c + + # PCJr/Tandy + vid_pcjr.c + vid_tandy.c + vid_mda.c vid_hercules.c - vid_herculesplus.c - vid_incolor.c - vid_colorplus.c + vid_hercules_plus.c + vid_hercules_incolor.c vid_genius.c vid_pgc.c vid_im1024.c @@ -70,9 +82,7 @@ add_library(vid OBJECT vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c - vid_ogc.c vid_mga.c - vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c diff --git a/src/video/vid_colorplus.c b/src/video/vid_cga_colorplus.c similarity index 100% rename from src/video/vid_colorplus.c rename to src/video/vid_cga_colorplus.c diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_cga_compaq.c similarity index 100% rename from src/video/vid_compaq_cga.c rename to src/video/vid_cga_compaq.c diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c new file mode 100644 index 000000000..feb9a12c8 --- /dev/null +++ b/src/video/vid_cga_compaq_plasma.c @@ -0,0 +1,784 @@ +/* + * 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 plasma displays on early Compaq Portables and laptops. + * + * + * + * Authors: Sarah Walker, <https://pcem-emulator.co.uk/> + * Miran Grca, <mgrca8@gmail.com> + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2025 starfrost + */ +#include <stdarg.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <wchar.h> +#include <math.h> +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/video.h> +#include <86box/vid_cga.h> +#include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> + +static video_timings_t timing_compaq_plasma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; + +#define CGA_RGB 0 +#define CGA_COMPOSITE 1 + +/*Very rough estimate*/ +#define VID_CLOCK (double) (651 * 416 * 60) + +/* Mapping of attributes to colours */ +static uint32_t amber; +static uint32_t black; +static uint32_t blinkcols[256][2]; +static uint32_t normcols[256][2]; + +/* Video options set by the motherboard; they will be picked up by the card + * on the next poll. + * + * Bit 3: Disable built-in video (for add-on card) + * Bit 2: Thin font + * Bits 0,1: Font set (not currently implemented) + */ +static int8_t cpq_st_display_internal = -1; + +static uint8_t mdaattr[256][2][2]; + +static void +compaq_plasma_display_set(uint8_t internal) +{ + cpq_st_display_internal = internal; +} + +typedef struct compaq_plasma_t { + cga_t cga; + mem_mapping_t font_ram_mapping; + uint8_t *font_ram; + uint8_t port_13c6; + uint8_t port_23c6; + uint8_t port_27c6; + uint8_t internal_monitor; +} compaq_plasma_t; + + +static void compaq_plasma_recalcattrs(compaq_plasma_t *self); + +static void +compaq_plasma_recalctimings(compaq_plasma_t *self) +{ + double _dispontime; + double _dispofftime; + double disptime; + + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { + cga_recalctimings(&self->cga); + return; + } + + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); +} + +static void +compaq_plasma_waitstates(UNUSED(void *priv)) +{ + int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 }; + int ws; + + ws = ws_array[cycles & 0xf]; + sub_cycles(ws); +} + +static void +compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + + if (self->port_23c6 & 0x08) + self->font_ram[addr & 0x1fff] = val; + else + self->cga.vram[addr & 0x7fff] = val; + + compaq_plasma_waitstates(&self->cga); +} +static uint8_t +compaq_plasma_read(uint32_t addr, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t ret; + + compaq_plasma_waitstates(&self->cga); + + if (self->port_23c6 & 0x08) + ret = (self->font_ram[addr & 0x1fff]); + else + ret = (self->cga.vram[addr & 0x7fff]); + + return ret; +} + +static void +compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + + switch (addr) { + /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + cga_out(addr, val, &self->cga); + break; + + /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + cga_out(addr, val, &self->cga); + compaq_plasma_recalctimings(self); + break; + case 0x3d8: + case 0x3d9: + cga_out(addr, val, &self->cga); + break; + + case 0x13c6: + self->port_13c6 = val; + compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); + /* + For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA; + Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA; + This leads me to believe bit 2 is not relevant to the mode. + */ + if ((val & 0x03) == 0x03) + mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000); + else + mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000); + break; + + case 0x23c6: + self->port_23c6 = val; + compaq_plasma_recalcattrs(self); + break; + + case 0x27c6: + self->port_27c6 = val; + break; + + default: + break; + } +} + +static uint8_t +compaq_plasma_in(uint16_t addr, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x3d4: + case 0x3da: + case 0x3db: + case 0x3dc: + ret = cga_in(addr, &self->cga); + break; + + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + ret = cga_in(addr, &self->cga); + break; + + case 0x3d8: + ret = self->cga.cgamode; + break; + + case 0x13c6: + ret = self->port_13c6; +#if 0 + if ((self->cga.cgamode & 0x28) == 0x00) + ret |= 0x04; +#endif + break; + + case 0x17c6: + ret = 0xe6; + break; + + case 0x1bc6: + ret = 0x40; + break; + + case 0x23c6: + ret = self->port_23c6; + break; + + case 0x27c6: + ret = self->port_27c6 & 0x3f; + break; + + default: + break; + } + + return ret; +} + +static void +compaq_plasma_poll(void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t chr; + uint8_t attr; + uint8_t sc; + uint16_t ma = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t ca = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t addr; + int drawcursor; + int cursorline; + int blink = 0; + int underline = 0; + int c; + int x; + uint32_t ink = 0; + uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; + uint32_t bg = black; + uint32_t cols[2]; + uint8_t dat; + uint8_t pattern; + uint32_t ink0 = 0; + uint32_t ink1 = 0; + + /* Switch between internal plasma and external CRT display. */ + if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) { + self->internal_monitor = cpq_st_display_internal; + compaq_plasma_recalctimings(self); + } + + /* graphic mode and not mode 40h */ + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { + /* standard cga mode */ + cga_poll(&self->cga); + return; + } else { + /* mode 40h or text mode */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + self->cga.linepos = 1; + if (self->cga.cgadispon) { + if (self->cga.displine == 0) + video_wait_for_buffer(); + + /* 80-col */ + if (self->cga.cgamode & 0x01) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; + ma += (self->cga.displine >> 4) * 80; + + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); + + /* for each text column */ + for (x = 0; x < 80; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else { + chr = 0x00; + attr = 0x00; + } + uint8_t hi_bit = attr & 0x08; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = ((attr & 0x07) == 0x01); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + } + + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && hi_bit) + chr_addr |= 0x1000; + + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + + if (hi_bit) { + if ((self->port_23c6 >> 5) == 1) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); + } else if ((self->port_23c6 >> 5) == 4) { + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16); + } + } + } + ma++; + } + } + /* 40-col */ + else if (!(self->cga.cgamode & 0x02)) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; + ma += (self->cga.displine >> 4) * 40; + + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); + + for (x = 0; x < 40; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else { + chr = 0x00; + attr = 0x00; + } + uint8_t hi_bit = attr & 0x08; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = ((attr & 0x07) == 0x01); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + } + + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && hi_bit) + chr_addr |= 0x1000; + + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + + if (hi_bit) { + if ((self->port_23c6 >> 5) == 1) + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black); + } + else if ((self->port_23c6 >> 5) == 4) + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); + } + } + ma++; + } + } else { + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { + /* 640x400 mode */ + if (self->port_23c6 & 0x01) /* 640*400 */ { + addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; + + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(self->cga.cgamode & 0x08)) + ink = black; + buffer32->line[self->cga.displine][(x << 3) + c] = ink; + dat <<= 1; + } + } + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; + + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(self->cga.cgamode & 0x08)) + pattern = 0; + + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; + break; + case 1: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = black; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 2: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = amber; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 3: + ink0 = ink1 = amber; + break; + + default: + break; + } + buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0; + buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1; + dat <<= 2; + } + } + } + } + } + self->cga.displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (self->cga.displine == 400) { /* Start of VSYNC */ + self->cga.cgastat |= 8; + self->cga.cgadispon = 0; + } + if (self->cga.displine == 416) { /* End of VSYNC */ + self->cga.displine = 0; + self->cga.cgastat &= ~8; + self->cga.cgadispon = 1; + } + } else { + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; + + self->cga.linepos = 0; + + if (self->cga.displine == 400) { + xsize = 640; + ysize = 400; + + if ((self->cga.cgamode & 0x08) || video_force_resize_get()) { + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + /* Plasma specific */ + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; + + /* Fixed 640x400 resolution */ + video_res_x = 640; + video_res_y = 400; + + if (self->cga.cgamode & 0x02) { + if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + self->cga.cgablink++; + } + } + } +} + +static void +compaq_plasma_mdaattr_rebuild(void) +{ + for (uint16_t c = 0; c < 256; c++) { + mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16; + if (c & 8) + mdaattr[c][0][1] = 15 + 16; + else + mdaattr[c][0][1] = 7 + 16; + } + + mdaattr[0x70][0][1] = 16; + mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15; + mdaattr[0xF0][0][1] = 16; + mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15; + mdaattr[0x78][0][1] = 16 + 7; + mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15; + mdaattr[0xF8][0][1] = 16 + 7; + mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15; + mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16; + mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16; + mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16; + mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16; +} + +static void +compaq_plasma_recalcattrs(compaq_plasma_t *self) +{ + int n; + + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold */ + + /* Set up colours */ + amber = makecol(0xff, 0x7d, 0x00); + black = makecol(0x64, 0x19, 0x00); + + /* Initialize the attribute mapping. Start by defaulting everything + * to black on amber, and with bold set by bit 3 */ + for (n = 0; n < 256; n++) { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + } + + /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always black on + * amber. */ + for (n = 0x11; n <= 0xFF; n++) { + if ((n & 7) == 0) + continue; + if ((self->port_23c6 >> 5) == 1) { /* Inverse */ + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + } else { /* Normal */ + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + } + } + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8E. */ + for (n = 0x01; n <= 0x0E; n++) { + if (n == 7) + continue; + if ((self->port_23c6 >> 5) == 1) { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + blinkcols[n + 128][0] = amber; + blinkcols[n + 128][1] = black; + } else { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; + } + } + /* Colours 07 and 0F are always amber on black. If blinking is + * enabled so are 87 and 8F. */ + for (n = 0x07; n <= 0x0F; n += 8) { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; + } + /* When not blinking, colours 81-8F are always amber on black. */ + for (n = 0x81; n <= 0x8F; n++) { + normcols[n][0] = black; + normcols[n][1] = amber; + } + + /* Finally do the ones which are solid black. These differ between + * the normal and blinking mappings */ + for (n = 0; n <= 0xFF; n += 0x11) + normcols[n][0] = normcols[n][1] = black; + + /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ + for (n = 0; n <= 0x77; n += 0x11) { + blinkcols[n][0] = blinkcols[n][1] = black; + blinkcols[n + 128][0] = blinkcols[n + 128][1] = black; + } +} + +static void * +compaq_plasma_init(UNUSED(const device_t *info)) +{ + compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); + + cga_init(&self->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); + + self->cga.composite = 0; + self->cga.revision = 0; + + self->cga.vram = malloc(0x8000); + self->internal_monitor = 1; + self->font_ram = malloc(0x2000); + + cga_comp_init(self->cga.revision); + timer_set_callback(&self->cga.timer, compaq_plasma_poll); + timer_set_p(&self->cga.timer, self); + + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, + compaq_plasma_read, NULL, NULL, + compaq_plasma_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, self); + for (int i = 1; i <= 2; i++) { + io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + } + io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + + overscan_x = overscan_y = 16; + + self->cga.rgb_type = device_get_config_int("rgb_type"); + cga_palette = (self->cga.rgb_type << 1); + cgapal_rebuild(); + compaq_plasma_mdaattr_rebuild(); + + return self; +} + +static void +compaq_plasma_close(void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + + free(self->cga.vram); + free(self->font_ram); + free(self); +} + +static void +compaq_plasma_speed_changed(void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + + compaq_plasma_recalctimings(self); +} + +const device_config_t compaq_plasma_config[] = { + // clang-format off + { + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Color", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t compaq_plasma_device = { + .name = "Compaq Plasma", + .internal_name = "compaq_plasma", + .flags = 0, + .local = 0, + .init = compaq_plasma_init, + .close = compaq_plasma_close, + .reset = NULL, + .available = NULL, + .speed_changed = compaq_plasma_speed_changed, + .force_redraw = NULL, + .config = compaq_plasma_config +}; diff --git a/src/video/vid_nga.c b/src/video/vid_cga_ncr.c similarity index 100% rename from src/video/vid_nga.c rename to src/video/vid_cga_ncr.c diff --git a/src/video/vid_ogc.c b/src/video/vid_cga_olivetti.c similarity index 99% rename from src/video/vid_ogc.c rename to src/video/vid_cga_olivetti.c index bc54499b2..71073d464 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_cga_olivetti.c @@ -217,7 +217,7 @@ ogc_poll(void *priv) int blink = 0; int underline = 0; - // composito colore appare blu scuro + // Composite color appears dark blue /* graphic mode and not mode 40h */ if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS))) { @@ -420,7 +420,7 @@ ogc_poll(void *priv) ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; ogc->cga.sc = 0; } - // potrebbe dare problemi con composito + // may cause problems with composite } else if (ogc->cga.sc == ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { ogc->cga.maback = ogc->cga.ma; ogc->cga.sc = 0; diff --git a/src/machine/m_xt_t1000_vid.c b/src/video/vid_cga_toshiba_t1000.c similarity index 100% rename from src/machine/m_xt_t1000_vid.c rename to src/video/vid_cga_toshiba_t1000.c diff --git a/src/machine/m_at_t3100e_vid.c b/src/video/vid_cga_toshiba_t3100e.c similarity index 100% rename from src/machine/m_at_t3100e_vid.c rename to src/video/vid_cga_toshiba_t3100e.c diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index c21b7c714..6000a2f30 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -901,7 +901,7 @@ ega_poll(void *priv) ega->linepos = 0; if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount)) - ega->con = 0; + ega->cursorvisible = 0; if (ega->dispon) { /* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll */ if (ega->linedbl && !ega->linecountff) { @@ -1037,7 +1037,7 @@ ega_poll(void *priv) ega->linecountff = 0; } if (ega->sc == (ega->crtc[10] & 31)) - ega->con = 1; + ega->cursorvisible = 1; } } diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 8a73ffbbb..b383e96b0 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -143,7 +143,7 @@ ega_render_text(ega_t *ega) for (int x = 0; x < (ega->hdisp + ega->scrollcache); x += charwidth) { uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; - int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); + int drawcursor = ((ega->ma == ega->ca) && ega->cursorvisible && ega->cursoron); uint32_t chr; uint32_t attr; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index cf8ad8cf3..48037b3f4 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -341,7 +341,7 @@ hercules_poll(void *priv) attr = dev->charbuffer[(x << 1) + 1]; } else chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); if (dev->sc == 12 && ((attr & 7) == 1)) { @@ -398,7 +398,7 @@ hercules_poll(void *priv) } if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { - dev->con = 0; + dev->cursorvisible = 0; } if (dev->vadj) { @@ -517,7 +517,7 @@ hercules_poll(void *priv) } if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) - dev->con = 1; + dev->cursorvisible = 1; if (dev->dispon && !(dev->ctrl & 0x02)) { for (x = 0; x < (dev->crtc[1] << 1); x++) { pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000; diff --git a/src/video/vid_incolor.c b/src/video/vid_hercules_incolor.c similarity index 99% rename from src/video/vid_incolor.c rename to src/video/vid_hercules_incolor.c index 034d54045..1d5e9d2aa 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_hercules_incolor.c @@ -167,7 +167,7 @@ typedef struct { int linepos, displine; int vc, sc; uint16_t ma, maback; - int con, cursoron; + int cursorvisible, cursoron; int dispon, blink; int vsynctime; int vadj; @@ -760,7 +760,7 @@ text_line(incolor_t *dev, uint16_t ca) } else chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) { case 0: @@ -898,7 +898,7 @@ incolor_poll(void *priv) } if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { - dev->con = 0; + dev->cursorvisible = 0; } if (dev->vadj) { @@ -977,7 +977,7 @@ incolor_poll(void *priv) } if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) - dev->con = 1; + dev->cursorvisible = 1; } } diff --git a/src/video/vid_herculesplus.c b/src/video/vid_hercules_plus.c similarity index 99% rename from src/video/vid_herculesplus.c rename to src/video/vid_hercules_plus.c index 42c68bf54..4c3f7867c 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_hercules_plus.c @@ -77,7 +77,7 @@ typedef struct { int linepos, displine; int vc, sc; uint16_t ma, maback; - int con, cursoron; + int cursorvisible, cursoron; int dispon, blink; int vsynctime; int vadj; @@ -418,7 +418,7 @@ text_line(herculesplus_t *dev, uint16_t ca) } else chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) { case 0: @@ -535,7 +535,7 @@ herculesplus_poll(void *priv) } if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { - dev->con = 0; + dev->cursorvisible = 0; } if (dev->vadj) { dev->sc++; @@ -612,7 +612,7 @@ herculesplus_poll(void *priv) } if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) - dev->con = 1; + dev->cursorvisible = 1; } VIDEO_MONITOR_EPILOGUE(); diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 4240f5e98..053ef0030 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -113,7 +113,7 @@ typedef struct jega_t { uint8_t attr_palette_enable; uint32_t *pallook; int is_vga; - int con; + int cursorvisible; int cursoron; int cursorblink_disable; int ca; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 70ca375fd..12f8a93ac 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -158,7 +158,7 @@ mda_poll(void *priv) for (x = 0; x < mda->crtc[1]; x++) { chr = mda->vram[(mda->ma << 1) & 0xfff]; attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); + drawcursor = ((mda->ma == ca) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); if (mda->sc == 12 && ((attr & 7) == 1)) { for (c = 0; c < 9; c++) @@ -199,7 +199,7 @@ mda_poll(void *priv) } } if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { - mda->con = 0; + mda->cursorvisible = 0; } if (mda->vadj) { mda->sc++; @@ -266,7 +266,7 @@ mda_poll(void *priv) mda->ma = mda->maback; } if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) { - mda->con = 1; + mda->cursorvisible = 1; } } VIDEO_MONITOR_EPILOGUE(); diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c new file mode 100644 index 000000000..9d1e3453e --- /dev/null +++ b/src/video/vid_pcjr.c @@ -0,0 +1,703 @@ +/* + * 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. + * + * IBM PCjr video subsystem emulation + * + * + * Authors: Sarah Walker, <https://pcem-emulator.co.uk/> + * Miran Grca, <mgrca8@gmail.com> + * Connor Hyde / starfrost <mario64crashed@gmail.com> + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2025 starfrost + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <wchar.h> +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/mem.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/video.h> +#include <86box/vid_cga.h> +#include <86box/vid_cga_comp.h> + +#include <86box/m_pcjr.h> + +static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ + +static uint8_t crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void +recalc_address(pcjr_t *pcjr) +{ + uint8_t masked_memctrl = pcjr->memctrl; + + /* According to the Technical Reference, bits 2 and 5 are + ignored if there is only 64k of RAM and there are only + 4 pages. */ + if (mem_size < 128) + masked_memctrl &= ~0x24; + + if ((pcjr->memctrl & 0xc0) == 0xc0) { + pcjr->vram = &ram[(masked_memctrl & 0x06) << 14]; + pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11]; + } else { + pcjr->vram = &ram[(masked_memctrl & 0x07) << 14]; + pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11]; + } +} + +void +pcjr_recalc_timings(pcjr_t *pcjr) +{ + double _dispontime; + double _dispofftime; + double disptime; + + if (pcjr->array[0] & 1) { + disptime = pcjr->crtc[0] + 1; + _dispontime = pcjr->crtc[1]; + } else { + disptime = (pcjr->crtc[0] + 1) << 1; + _dispontime = pcjr->crtc[1] << 1; + } + + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST; + _dispofftime *= CGACONST; + pcjr->dispontime = (uint64_t) (_dispontime); + pcjr->dispofftime = (uint64_t) (_dispofftime); +} + +static int +vid_get_h_overscan_size(pcjr_t *pcjr) +{ + int ret; + + if (pcjr->array[0] & 1) + ret = 128; + else + ret = 256; + + return ret; +} + +static void +vid_out(uint16_t addr, uint8_t val, void *priv) +{ + pcjr_t *pcjr = (pcjr_t *) priv; + uint8_t old; + + switch (addr) { + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + pcjr->crtcreg = val & 0x1f; + return; + + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + old = pcjr->crtc[pcjr->crtcreg]; + pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg]; + if (pcjr->crtcreg == 2) + overscan_x = vid_get_h_overscan_size(pcjr); + if (old != val) { + if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) { + pcjr->fullchange = changeframecount; + pcjr_recalc_timings(pcjr); + } + } + return; + + case 0x3da: + if (!pcjr->array_ff) + pcjr->array_index = val & 0x1f; + else { + if (pcjr->array_index & 0x10) + val &= 0x0f; + pcjr->array[pcjr->array_index & 0x1f] = val; + if (!(pcjr->array_index & 0x1f)) + update_cga16_color(val); + } + pcjr->array_ff = !pcjr->array_ff; + break; + + case 0x3df: + pcjr->memctrl = val; + pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to + then be readable from port 60, others it errors out + with only 64k RAM set (but somehow, still works with + 128k or more RAM). */ + pcjr->addr_mode = val >> 6; + recalc_address(pcjr); + break; + + default: + break; + } +} + +static uint8_t +vid_in(uint16_t addr, void *priv) +{ + pcjr_t *pcjr = (pcjr_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + ret = pcjr->crtcreg; + break; + + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + ret = pcjr->crtc[pcjr->crtcreg]; + break; + + case 0x3da: + pcjr->array_ff = 0; + pcjr->stat ^= 0x10; + ret = pcjr->stat; + break; + + default: + break; + } + + return ret; +} + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + pcjr_t *pcjr = (pcjr_t *) priv; + + if (pcjr->memctrl == -1) + return; + + pcjr->b8000[addr & 0x3fff] = val; +} + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + const pcjr_t *pcjr = (pcjr_t *) priv; + + if (pcjr->memctrl == -1) + return 0xff; + + return (pcjr->b8000[addr & 0x3fff]); +} + +static int +vid_get_h_overscan_delta(pcjr_t *pcjr) +{ + int def; + int coef; + int ret; + + switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { + case 0x13: /*320x200x16*/ + def = 0x56; + coef = 8; + break; + case 0x12: /*160x200x16*/ + def = 0x2c; /* I'm going to assume a datasheet erratum here. */ + coef = 16; + break; + case 0x03: /*640x200x4*/ + def = 0x56; + coef = 8; + break; + case 0x01: /*80 column text*/ + def = 0x5a; + coef = 8; + break; + case 0x00: /*40 column text*/ + default: + def = 0x2c; + coef = 16; + break; + case 0x02: /*320x200x4*/ + def = 0x2b; + coef = 16; + break; + case 0x102: /*640x200x2*/ + def = 0x2b; + coef = 16; + break; + } + + ret = pcjr->crtc[0x02] - def; + + if (ret < -8) + ret = -8; + + if (ret > 8) + ret = 8; + + return ret * coef; +} + +static void +vid_blit_h_overscan(pcjr_t *pcjr) +{ + int cols = (pcjr->array[2] & 0xf) + 16;; + int y0 = pcjr->firstline << 1; + int y = (pcjr->lastline << 1) + 16; + int ho_s = vid_get_h_overscan_size(pcjr); + int i; + int x; + + if (pcjr->array[0] & 1) + x = (pcjr->crtc[1] << 3) + ho_s; + else + x = (pcjr->crtc[1] << 4) + ho_s; + + for (i = 0; i < 16; i++) { + hline(buffer32, 0, y0 + i, x, cols); + hline(buffer32, 0, y + i, x, cols); + + if (pcjr->composite) { + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y0 + i]); + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y + i]); + } else { + video_process_8(x, y0 + i); + video_process_8(x, y + i); + } + } +} + +static void +vid_poll(void *priv) +{ + pcjr_t *pcjr = (pcjr_t *) priv; + uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint16_t dat; + int cols[4]; + int oldsc; + int l = (pcjr->displine << 1) + 16; + int ho_s = vid_get_h_overscan_size(pcjr); + int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2); + + if (!pcjr->linepos) { + timer_advance_u64(&pcjr->timer, pcjr->dispofftime); + pcjr->stat &= ~1; + pcjr->linepos = 1; + oldsc = pcjr->sc; + if ((pcjr->crtc[8] & 3) == 3) + pcjr->sc = (pcjr->sc << 1) & 7; + if (pcjr->dispon) { + uint16_t offset = 0; + uint16_t mask = 0x1fff; + + if (pcjr->displine < pcjr->firstline) { + pcjr->firstline = pcjr->displine; + video_wait_for_buffer(); + } + pcjr->lastline = pcjr->displine; + cols[0] = (pcjr->array[2] & 0xf) + 16; + + if (pcjr->array[0] & 1) { + hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + } else { + hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]); + } + + switch (pcjr->addr_mode) { + case 0: /*Alpha*/ + offset = 0; + mask = 0x3fff; + break; + case 1: /*Low resolution graphics*/ + offset = (pcjr->sc & 1) * 0x2000; + break; + case 3: /*High resolution graphics*/ + offset = (pcjr->sc & 3) * 0x2000; + break; + default: + break; + } + switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { + case 0x13: /*320x200x16*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 3) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = + buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = + pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = + buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = + pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] = + buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] = + pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] = + buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] = + pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16; + } + break; + case 0x12: /*160x200x16*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 4) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = + buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = + buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = + buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = + pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] = + buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] = + buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] = + buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] = + pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] = + buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] = + buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] = + buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] = + pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] = + buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] = + buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] = + buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] = + pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16; + } + break; + case 0x03: /*640x200x4*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 3) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset]; + pcjr->ma++; + for (uint8_t c = 0; c < 8; c++) { + chr = (dat >> 7) & 1; + chr |= ((dat >> 14) & 2); + buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = + pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16; + dat <<= 1; + } + } + break; + case 0x01: /*80 column text*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 3) + ho_d; + chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; + attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + drawcursor = ((pcjr->ma == ca) && pcjr->cursorvisible && pcjr->cursoron); + if (pcjr->array[3] & 4) { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; + if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; + } + if (pcjr->sc & 8) + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + c] = + buffer32->line[l + 1][ef_x + c] = cols[0]; + else + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + c] = + buffer32->line[l + 1][ef_x + c] = + cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + if (drawcursor) + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[l][ef_x + c] ^= 15; + buffer32->line[l + 1][ef_x + c] ^= 15; + } + pcjr->ma++; + } + break; + case 0x00: /*40 column text*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 4) + ho_d; + chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; + attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + drawcursor = ((pcjr->ma == ca) && pcjr->cursorvisible && pcjr->cursoron); + if (pcjr->array[3] & 4) { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; + if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; + } + pcjr->ma++; + if (pcjr->sc & 8) + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + (c << 1)] = + buffer32->line[l][ef_x + (c << 1) + 1] = + buffer32->line[l + 1][ef_x + (c << 1)] = + buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0]; + else + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + (c << 1)] = + buffer32->line[l][ef_x + (c << 1) + 1] = + buffer32->line[l + 1][ef_x + (c << 1)] = + buffer32->line[l + 1][ef_x + (c << 1) + 1] = + cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + if (drawcursor) + for (uint8_t c = 0; c < 16; c++) { + buffer32->line[l][ef_x + c] ^= 15; + buffer32->line[l + 1][ef_x + c] ^= 15; + } + } + break; + case 0x02: /*320x200x4*/ + cols[0] = pcjr->array[0 + 16] + 16; + cols[1] = pcjr->array[1 + 16] + 16; + cols[2] = pcjr->array[2 + 16] + 16; + cols[3] = pcjr->array[3 + 16] + 16; + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 4) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[l][ef_x + (c << 1)] = + buffer32->line[l][ef_x + (c << 1) + 1] = + buffer32->line[l + 1][ef_x + (c << 1)] = + buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14]; + dat <<= 2; + } + } + break; + case 0x102: /*640x200x2*/ + cols[0] = pcjr->array[0 + 16] + 16; + cols[1] = pcjr->array[1 + 16] + 16; + for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 4) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + for (uint8_t c = 0; c < 16; c++) { + buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = + cols[dat >> 15]; + dat <<= 1; + } + } + break; + + default: + break; + } + } else { + if (pcjr->array[3] & 4) { + if (pcjr->array[0] & 1) { + hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); + } else { + hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16); + } + } else { + cols[0] = pcjr->array[0 + 16] + 16; + if (pcjr->array[0] & 1) { + hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + } else { + hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]); + } + } + } + if (pcjr->array[0] & 1) + x = (pcjr->crtc[1] << 3) + ho_s; + else + x = (pcjr->crtc[1] << 4) + ho_s; + if (pcjr->composite) { + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]); + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]); + } else { + video_process_8(x, l); + video_process_8(x, l + 1); + } + pcjr->sc = oldsc; + if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { + pcjr->stat |= 8; + } + pcjr->displine++; + if (pcjr->displine >= 360) + pcjr->displine = 0; + } else { + timer_advance_u64(&pcjr->timer, pcjr->dispontime); + if (pcjr->dispon) + pcjr->stat |= 1; + pcjr->linepos = 0; + if (pcjr->vsynctime) { + pcjr->vsynctime--; + if (!pcjr->vsynctime) { + pcjr->stat &= ~8; + } + } + if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { + pcjr->cursorvisible = 0; + } + if (pcjr->vadj) { + pcjr->sc++; + pcjr->sc &= 31; + pcjr->ma = pcjr->maback; + pcjr->vadj--; + if (!pcjr->vadj) { + pcjr->dispon = 1; + pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; + pcjr->sc = 0; + } + } else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) { + pcjr->maback = pcjr->ma; + pcjr->sc = 0; + oldvc = pcjr->vc; + pcjr->vc++; + pcjr->vc &= 127; + if (pcjr->vc == pcjr->crtc[6]) + pcjr->dispon = 0; + if (oldvc == pcjr->crtc[4]) { + pcjr->vc = 0; + pcjr->vadj = pcjr->crtc[5]; + if (!pcjr->vadj) + pcjr->dispon = 1; + if (!pcjr->vadj) + pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; + if ((pcjr->crtc[10] & 0x60) == 0x20) + pcjr->cursoron = 0; + else + pcjr->cursoron = pcjr->blink & 16; + } + if (pcjr->vc == pcjr->crtc[7]) { + pcjr->dispon = 0; + pcjr->displine = 0; + pcjr->vsynctime = 16; + picint(1 << 5); + if (pcjr->crtc[7]) { + if (pcjr->array[0] & 1) + x = (pcjr->crtc[1] << 3) + ho_s; + else + x = (pcjr->crtc[1] << 4) + ho_s; + pcjr->lastline++; + + xs_temp = x; + ys_temp = (pcjr->lastline - pcjr->firstline) << 1; + + if ((xs_temp > 0) && (ys_temp > 0)) { + int actual_ys = ys_temp; + + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= ho_s; + + if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { + xsize = xs_temp; + ysize = ys_temp; + + set_screen_size(xsize, ysize + (enable_overscan ? 32 : 0)); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + vid_blit_h_overscan(pcjr); + + if (enable_overscan) { + video_blit_memtoscreen(0, pcjr->firstline << 1, + xsize, actual_ys + 32); + } else if (pcjr->apply_hd) { + video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16, + xsize, actual_ys); + } else { + video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16, + xsize, actual_ys); + } + } + + frames++; + video_res_x = xsize; + video_res_y = ysize; + } + pcjr->firstline = 1000; + pcjr->lastline = 0; + pcjr->blink++; + } + } else { + pcjr->sc++; + pcjr->sc &= 31; + pcjr->ma = pcjr->maback; + } + if (pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1))) + pcjr->cursorvisible = 1; + } +} + + +void +pcjr_vid_init(pcjr_t *pcjr) +{ + int display_type; + + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); + + pcjr->memctrl = -1; + if (mem_size < 128) + pcjr->memctrl &= ~0x24; + + display_type = device_get_config_int("display_type"); + pcjr->composite = (display_type != PCJR_RGB); + pcjr->apply_hd = device_get_config_int("apply_hd"); + overscan_x = 256; + overscan_y = 32; + + mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, + vid_read, NULL, NULL, + vid_write, NULL, NULL, NULL, 0, pcjr); + io_sethandler(0x03d0, 16, + vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); + timer_add(&pcjr->timer, vid_poll, pcjr, 1); + + cga_palette = 0; + cgapal_rebuild(); +} diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 567d60347..4b9c8064a 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -362,7 +362,7 @@ typedef struct da2_t { int vc; int sc; int linepos, vslines, linecountff; - int con, cursoron, blink, blinkconf; + int cursorvisible, cursoron, blink, blinkconf; int scrollcache; int char_width; @@ -2055,7 +2055,7 @@ da2_render_text(da2_t *da2) 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); + drawcursor = ((da2->ma == da2->ca) && da2->cursorvisible && 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 = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ @@ -2155,7 +2155,7 @@ da2_render_textm3(da2_t *da2) } chr_wide = 0; } - drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); + drawcursor = ((da2->ma == da2->ca) && da2->cursorvisible && 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 = (colormode) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ @@ -3056,7 +3056,7 @@ da2_poll(void *priv) da2->linepos = 0; if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) - da2->con = 0; + da2->cursorvisible = 0; if (da2->dispon) { if (da2->sc == da2->rowcount) { da2->linecountff = 0; @@ -3145,7 +3145,7 @@ da2_poll(void *priv) da2->scrollcache = da2->attrc[LV_PANNING] & 7; } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) - da2->con = 1; + da2->cursorvisible = 1; } } diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index c54af7119..9a5d184f9 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -158,7 +158,7 @@ typedef struct sigma_t { int linepos, displine; int sc, vc; int cgadispon; - int con, cursoron, cgablink; + int cursorvisible, cursoron, cgablink; int vsynctime, vadj; int oddeven; @@ -430,7 +430,7 @@ sigma_text80(sigma_t *sigma) for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { chr = vram[x << 1]; attr = vram[(x << 1) + 1]; - drawcursor = ((ma == ca) && sigma->con && sigma->cursoron); + drawcursor = ((ma == ca) && sigma->cursorvisible && sigma->cursoron); if (!(sigma->sigmamode & MODE_NOBLINK)) { cols[1] = (attr & 15) | 16; @@ -485,7 +485,7 @@ sigma_text40(sigma_t *sigma) for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { chr = vram[x << 1]; attr = vram[(x << 1) + 1]; - drawcursor = ((ma == ca) && sigma->con && sigma->cursoron); + drawcursor = ((ma == ca) && sigma->cursorvisible && sigma->cursoron); if (!(sigma->sigmamode & MODE_NOBLINK)) { cols[1] = (attr & 15) | 16; @@ -675,7 +675,7 @@ sigma_poll(void *priv) sigma->sigmastat &= ~STATUS_RETR_V; } if (sigma->sc == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1))) { - sigma->con = 0; + sigma->cursorvisible = 0; } if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1)) sigma->maback = sigma->ma; @@ -775,7 +775,7 @@ sigma_poll(void *priv) if (sigma->cgadispon) sigma->sigmastat &= ~STATUS_RETR_H; if (sigma->sc == (sigma->crtc[10] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[10] & 31) >> 1))) - sigma->con = 1; + sigma->cursorvisible = 1; } } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 0c9c24241..6290832df 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1332,7 +1332,7 @@ svga_poll(void *priv) svga->linepos = 0; if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount)) - svga->con = 0; + svga->cursorvisible = 0; if (svga->dispon) { /* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll - S3 Trio64V2/DX: sc == rowcount, wrapping 5-bit counter. */ @@ -1503,7 +1503,7 @@ svga_poll(void *priv) svga->overlay_latch = svga->overlay; } if (svga->sc == (svga->crtc[10] & 31)) - svga->con = 1; + svga->cursorvisible = 1; } } diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index d47697a7e..348506e56 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -158,7 +158,7 @@ svga_render_text_40(svga_t *svga) if (!svga->force_old_addr) addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron); if (svga->force_old_addr) { chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; @@ -241,7 +241,7 @@ svga_render_text_80(svga_t *svga) if (!svga->force_old_addr) addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron); if (svga->force_old_addr) { chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; @@ -318,7 +318,7 @@ svga_render_text_80_ksc5601(svga_t *svga) for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron); chr = svga->vram[addr]; nextchr = svga->vram[addr + 8]; attr = svga->vram[addr + 1]; diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c new file mode 100644 index 000000000..13d46a239 --- /dev/null +++ b/src/video/vid_tandy.c @@ -0,0 +1,827 @@ +/* + * 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. + * + * Tandy 1000 video emulation + * + * + * + * Authors: Sarah Walker, <https://pcem-emulator.co.uk/> + * Miran Grca, <mgrca8@gmail.com> + * Connor Hyde / starfrost, <mario64crashed@gmail.com> + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2025 starfrost + */ +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> +#include <math.h> +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/nmi.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/nvr.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/gameport.h> +#include <86box/keyboard.h> +#include <86box/sound.h> +#include <86box/snd_sn76489.h> +#include <86box/video.h> +#include <86box/vid_cga_comp.h> +#include <86box/m_tandy.h> +#include <86box/machine.h> +#include <86box/plat_unused.h> + +static uint8_t crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t crtcmask_sl[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +enum { + TANDY_RGB = 0, + TANDY_COMPOSITE +}; + +static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ + +static void +recalc_mapping(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + mem_mapping_disable(&vid->mapping); + io_removehandler(0x03d0, 16, + tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev); + + if (vid->planar_ctrl & 4) { + mem_mapping_enable(&vid->mapping); + if (vid->array[5] & 1) + mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000); + else + mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000); + io_sethandler(0x03d0, 16, tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev); + } +} + +static void +recalc_timings(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + double _dispontime; + double _dispofftime; + double disptime; + + if (vid->mode & 1) { + disptime = vid->crtc[0] + 1; + _dispontime = vid->crtc[1]; + } else { + disptime = (vid->crtc[0] + 1) << 1; + _dispontime = vid->crtc[1] << 1; + } + + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST; + _dispofftime *= CGACONST; + vid->dispontime = (uint64_t) (_dispontime); + vid->dispofftime = (uint64_t) (_dispofftime); +} + +static void +recalc_address(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + if ((vid->memctrl & 0xc0) == 0xc0) { + vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; + vid->b8000_mask = 0x7fff; + } else { + vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; + vid->b8000_mask = 0x3fff; + } +} + +void +tandy_recalc_address_sl(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + vid->b8000_limit = 0x8000; + + if (vid->array[5] & 1) { + vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base]; + } else if ((vid->memctrl & 0xc0) == 0xc0) { + vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; + } else { + vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; + if ((vid->memctrl & 0x38) == 0x38) + vid->b8000_limit = 0x4000; + } +} + +static void +vid_update_latch(t1kvid_t *vid) +{ + uint32_t lp_latch = vid->displine * vid->crtc[1]; + + vid->crtc[0x10] = (lp_latch >> 8) & 0x3f; + vid->crtc[0x11] = lp_latch & 0xff; +} + +void +tandy_vid_out(uint16_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *) priv; + t1kvid_t *vid = dev->vid; + uint8_t old; + + if ((addr >= 0x3d0) && (addr <= 0x3d7)) + addr = (addr & 0xff9) | 0x004; + + switch (addr) { + case 0x03d4: + vid->crtcreg = val & 0x1f; + break; + + case 0x03d5: + old = vid->crtc[vid->crtcreg]; + if (dev->is_sl2) + vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; + else + vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; + if (old != val) { + if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { + vid->fullchange = changeframecount; + recalc_timings(dev); + } + } + break; + + case 0x03d8: + old = vid->mode; + vid->mode = val; + if ((old ^ val) & 0x01) + recalc_timings(dev); + if (!dev->is_sl2) + update_cga16_color(vid->mode); + break; + + case 0x03d9: + vid->col = val; + break; + + case 0x03da: + vid->array_index = val & 0x1f; + break; + + case 0x3db: + if (!dev->is_sl2 && (vid->lp_strobe == 1)) + vid->lp_strobe = 0; + break; + + case 0x3dc: + if (!dev->is_sl2 && (vid->lp_strobe == 0)) { + vid->lp_strobe = 1; + vid_update_latch(vid); + } + break; + + case 0x03de: + if (vid->array_index & 16) + val &= 0xf; + vid->array[vid->array_index & 0x1f] = val; + if (dev->is_sl2) { + if ((vid->array_index & 0x1f) == 5) { + recalc_mapping(dev); + tandy_recalc_address_sl(dev); + } + } + break; + + case 0x03df: + vid->memctrl = val; + if (dev->is_sl2) + tandy_recalc_address_sl(dev); + else + recalc_address(dev); + break; + + case 0x0065: + if (val == 8) + return; /*Hack*/ + vid->planar_ctrl = val; + recalc_mapping(dev); + break; + + default: + break; + } +} + +uint8_t +tandy_vid_in(uint16_t addr, void *priv) +{ + const tandy_t *dev = (tandy_t *) priv; + t1kvid_t *vid = dev->vid; + uint8_t ret = 0xff; + + if ((addr >= 0x3d0) && (addr <= 0x3d7)) + addr = (addr & 0xff9) | 0x004; + + switch (addr) { + case 0x03d4: + ret = vid->crtcreg; + break; + + case 0x03d5: + ret = vid->crtc[vid->crtcreg]; + break; + + case 0x03da: + ret = vid->stat; + break; + + case 0x3db: + if (!dev->is_sl2 && (vid->lp_strobe == 1)) + vid->lp_strobe = 0; + break; + + case 0x3dc: + if (!dev->is_sl2 && (vid->lp_strobe == 0)) { + vid->lp_strobe = 1; + vid_update_latch(vid); + } + break; + + default: + break; + } + + return ret; +} + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *) priv; + t1kvid_t *vid = dev->vid; + + if (vid->memctrl == -1) + return; + + if (dev->is_sl2) { + if (vid->array[5] & 1) + vid->b8000[addr & 0xffff] = val; + else { + if ((addr & 0x7fff) < vid->b8000_limit) + vid->b8000[addr & 0x7fff] = val; + } + } else { + vid->b8000[addr & vid->b8000_mask] = val; + } +} + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + const tandy_t *dev = (tandy_t *) priv; + const t1kvid_t *vid = dev->vid; + + if (vid->memctrl == -1) + return 0xff; + + if (dev->is_sl2) { + if (vid->array[5] & 1) + return (vid->b8000[addr & 0xffff]); + if ((addr & 0x7fff) < vid->b8000_limit) + return (vid->b8000[addr & 0x7fff]); + else + return 0xff; + } else { + return (vid->b8000[addr & vid->b8000_mask]); + } +} + +static void +vid_poll(void *priv) +{ + tandy_t *dev = (tandy_t *) priv; + t1kvid_t *vid = dev->vid; + uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; + + if (!vid->linepos) { + timer_advance_u64(&vid->timer, vid->dispofftime); + vid->stat |= 1; + vid->linepos = 1; + oldsc = vid->sc; + if ((vid->crtc[8] & 3) == 3) + vid->sc = (vid->sc << 1) & 7; + if (vid->dispon) { + if (vid->displine < vid->firstline) { + vid->firstline = vid->displine; + video_wait_for_buffer(); + } + vid->lastline = vid->displine; + cols[0] = (vid->array[2] & 0xf) + 16; + for (c = 0; c < 8; c++) { + if (vid->array[3] & 4) { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = cols[0]; + if (vid->mode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = cols[0]; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = cols[0]; + } + } else if ((vid->mode & 0x12) == 0x12) { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = 0; + if (vid->mode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; + } + } else { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->col & 15) + 16; + if (vid->mode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16; + } + } + } + if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/ + for (x = 0; x < vid->crtc[1] * 2; x++) { + dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | vid->vram[((vid->ma << 1) + 1) & 0xffff]; + vid->ma++; + buffer32->line[vid->displine << 1][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 2) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 11] = vid->array[(dat & 0xf) + 16] + 16; + } + } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16; + } + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + if (dev->is_sl2) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + } else { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + } + vid->ma++; + buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16; + } + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + chr = (dat >> 6) & 2; + chr |= ((dat >> 15) & 1); + buffer32->line[vid->displine << 1][(x << 3) + 8 + c] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16; + dat <<= 1; + } + } + } else if (vid->mode & 1) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[(vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + if (vid->sc & 8) { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; + } + } else { + for (c = 0; c < 8; c++) { + if (vid->sc == 8) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + } else { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] ^= 15; + buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15; + } + } + vid->ma++; + } + } else if (!(vid->mode & 2)) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[(vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + vid->ma++; + if (vid->sc & 8) { + for (c = 0; c < 8; c++) + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + } else { + for (c = 0; c < 8; c++) { + if (vid->sc == 8) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + } else { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + if (drawcursor) { + for (c = 0; c < 16; c++) { + buffer32->line[vid->displine << 1][(x << 4) + c + 8] ^= 15; + buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] ^= 15; + } + } + } + } else if (!(vid->mode & 16)) { + cols[0] = (vid->col & 15); + col = (vid->col & 16) ? 8 : 0; + if (vid->mode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (vid->col & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16; + cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16; + cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16; + cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16; + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 16; c++) { + buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + if (vid->array[3] & 4) { + if (vid->mode & 1) { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + } else { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + } + } else { + cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; + if (vid->mode & 1) { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); + } else { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, cols[0]); + } + } + } + + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + if (!dev->is_sl2 && vid->composite) { + Composite_Process(vid->mode, 0, x >> 2, buffer32->line[vid->displine << 1]); + Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1) + 1]); + } else { + video_process_8(x, vid->displine << 1); + video_process_8(x, (vid->displine << 1) + 1); + } + vid->sc = oldsc; + if (vid->vc == vid->crtc[7] && !vid->sc) + vid->stat |= 8; + vid->displine++; + if (vid->displine >= 360) + vid->displine = 0; + } else { + timer_advance_u64(&vid->timer, vid->dispontime); + if (vid->dispon) + vid->stat &= ~1; + vid->linepos = 0; + if (vid->vsynctime) { + vid->vsynctime--; + if (!vid->vsynctime) + vid->stat &= ~8; + } + if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { + vid->cursorvisible = 0; + } + if (vid->vadj) { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + vid->vadj--; + if (!vid->vadj) { + vid->dispon = 1; + if (dev->is_sl2 && (vid->array[5] & 1)) + vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + else + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->sc = 0; + } + } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { + vid->maback = vid->ma; + vid->sc = 0; + oldvc = vid->vc; + vid->vc++; + if (dev->is_sl2) + vid->vc &= 255; + else + vid->vc &= 127; + if (vid->vc == vid->crtc[6]) + vid->dispon = 0; + if (oldvc == vid->crtc[4]) { + vid->vc = 0; + vid->vadj = vid->crtc[5]; + if (!vid->vadj) + vid->dispon = 1; + if (!vid->vadj) { + if (dev->is_sl2 && (vid->array[5] & 1)) + vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + else + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + } + if ((vid->crtc[10] & 0x60) == 0x20) + vid->cursoron = 0; + else + vid->cursoron = vid->blink & 16; + } + if (vid->vc == vid->crtc[7]) { + vid->dispon = 0; + vid->displine = 0; + vid->vsynctime = 16; + picint(1 << 5); + if (vid->crtc[7]) { + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + vid->lastline++; + + xs_temp = x; + ys_temp = (vid->lastline - vid->firstline) << 1; + + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; + + if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if (enable_overscan) { + video_blit_memtoscreen(0, (vid->firstline - 4) << 1, + xsize, ((vid->lastline - vid->firstline) + 8) << 1); + } else { + video_blit_memtoscreen(8, vid->firstline << 1, + xsize, (vid->lastline - vid->firstline) << 1); + } + } + + frames++; + + video_res_x = xsize; + video_res_y = ysize; + if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + video_res_x /= 2; + video_bpp = 4; + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + video_res_x /= 4; + video_bpp = 4; + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + video_bpp = 2; + } else if (vid->mode & 1) { + video_res_x /= 8; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (!(vid->mode & 2)) { + video_res_x /= 16; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (!(vid->mode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + vid->firstline = 1000; + vid->lastline = 0; + vid->blink++; + } + } else { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + } + if (vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1))) + vid->cursorvisible = 1; + } +} + +void +tandy_vid_speed_changed(void *priv) +{ + tandy_t *dev = (tandy_t *) priv; + + recalc_timings(dev); +} + +void +tandy_vid_close(void *priv) +{ + tandy_t *dev = (tandy_t *) priv; + + free(dev->vid); + dev->vid = NULL; +} + +void +tandy_vid_init(tandy_t *dev) +{ + int display_type; + t1kvid_t *vid; + + vid = calloc(1, sizeof(t1kvid_t)); + vid->memctrl = -1; + + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); + + display_type = device_get_config_int("display_type"); + vid->composite = (display_type != TANDY_RGB); + + cga_comp_init(1); + + if (dev->is_sl2) { + vid->b8000_limit = 0x8000; + vid->planar_ctrl = 4; + overscan_x = overscan_y = 16; + + io_sethandler(0x0065, 1, tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev); + } else + vid->b8000_mask = 0x3fff; + + timer_add(&vid->timer, vid_poll, dev, 1); + mem_mapping_add(&vid->mapping, 0xb8000, 0x08000, + vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev); + io_sethandler(0x03d0, 16, + tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev); + + dev->vid = vid; +} + +const device_config_t vid_config[] = { + // clang-format off + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = TANDY_RGB, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = TANDY_RGB }, + { .description = "Composite", .value = TANDY_COMPOSITE }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t tandy_1000_video_device = { + .name = "Tandy 1000", + .internal_name = "tandy1000_video", + .flags = 0, + .local = 0, + .init = NULL, + .close = tandy_vid_close, + .reset = NULL, + .available = NULL, + .speed_changed = tandy_vid_speed_changed, + .force_redraw = NULL, + .config = vid_config +}; + +const device_t tandy_1000hx_video_device = { + .name = "Tandy 1000 HX", + .internal_name = "tandy1000_hx_video", + .flags = 0, + .local = 0, + .init = NULL, + .close = tandy_vid_close, + .reset = NULL, + .available = NULL, + .speed_changed = tandy_vid_speed_changed, + .force_redraw = NULL, + .config = vid_config +}; + +const device_t tandy_1000sl_video_device = { + .name = "Tandy 1000SL2", + .internal_name = "tandy1000_sl_video", + .flags = 0, + .local = 1, + .init = NULL, + .close = tandy_vid_close, + .reset = NULL, + .available = NULL, + .speed_changed = tandy_vid_speed_changed, + .force_redraw = NULL, + .config = NULL +}; \ No newline at end of file From 40f8affdda07ec3d958f3570806ec75e338ba3ef Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 23:18:59 +0100 Subject: [PATCH 1116/1190] CGACompq merge --- src/video/vid_cga_compaq.c | 168 +++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 83 deletions(-) diff --git a/src/video/vid_cga_compaq.c b/src/video/vid_cga_compaq.c index e5c78c665..1ed739ed8 100644 --- a/src/video/vid_cga_compaq.c +++ b/src/video/vid_cga_compaq.c @@ -68,9 +68,9 @@ compaq_cga_recalctimings(cga_t *dev) double _dispontime; double _dispofftime; double disptime; - disptime = dev.crtc[0] + 1; + disptime = dev->crtc[CGA_CRTC_HTOTAL] + 1; - _dispontime = dev.crtc[CGA_CRTC_HDISP]; + _dispontime = dev->crtc[CGA_CRTC_HDISP]; _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; @@ -81,8 +81,8 @@ compaq_cga_recalctimings(cga_t *dev) static void compaq_cga_poll(void *priv) { - cga_t *dev = (cga_t *) priv; - uint16_t ca = (dev.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (dev.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + cga_t *dev = (cga_t *) priv; + uint16_t ca = (dev->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (dev->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -97,8 +97,10 @@ compaq_cga_poll(void *priv) int underline = 0; int blink = 0; + int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); + /* If in graphics mode or character height is not 13, behave as CGA */ - if ((dev.cgamode & 0x12) || (dev.crtc[9] != 13)) { + if ((dev->cgamode & highres_graphics_flag) || (dev->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] != 13)) { overscan_x = overscan_y = 16; cga_poll(dev); return; @@ -124,22 +126,22 @@ compaq_cga_poll(void *priv) cols[0] = (dev->cgacol & 15) + 16; for (c = 0; c < 8; c++) { - buffer32->line[dev.displine][c] = cols[0]; - if (dev.cgamode & CGA_MODE_FLAG_HIGHRES) - buffer32->line[dev.displine][c + (dev.crtc[CGA_CRTC_HDISP] << 3) + 8] = cols[0]; + buffer32->line[dev->displine][c] = cols[0]; + if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) + buffer32->line[dev->displine][c + (dev->crtc[CGA_CRTC_HDISP] << 3) + 8] = cols[0]; else - buffer32->line[dev.displine][c + (dev.crtc[CGA_CRTC_HDISP] << 4) + 8] = cols[0]; + buffer32->line[dev->displine][c + (dev->crtc[CGA_CRTC_HDISP] << 4) + 8] = cols[0]; } - if (dev.cgamode & CGA_MODE_FLAG_HIGHRES) { - for (x = 0; x < dev.crtc[CGA_CRTC_HDISP]; x++) { - chr = dev.charbuffer[x << 1]; - attr = dev.charbuffer[(x << 1) + 1]; - drawcursor = ((dev.ma == ca) && dev.con && dev.cursoron); + if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) { + for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) { + chr = dev->charbuffer[x << 1]; + attr = dev->charbuffer[(x << 1) + 1]; + drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); if (vflags) { underline = 0; - blink = ((dev.cgablink & 8) && (dev.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((dev->cgablink & 8) && (dev->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); } if (vflags && (dev->cgamode & 0x80)) { @@ -148,7 +150,7 @@ compaq_cga_poll(void *priv) if ((dev->sc == 12) && ((attr & 7) == 1)) underline = 1; - } else if (dev.cgamode & 0x20) { + } else if (dev->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -179,14 +181,14 @@ compaq_cga_poll(void *priv) dev->ma++; } } else { - for (x = 0; x < dev.crtc[CGA_CRTC_HDISP]; x++) { - chr = dev.vram[(dev.ma << 1) & 0x3fff]; - attr = dev.vram[((dev.ma << 1) + 1) & 0x3fff]; - drawcursor = ((dev.ma == ca) && dev.con && dev.cursoron); + for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) { + chr = dev->vram[(dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); if (vflags) { underline = 0; - blink = ((dev.cgablink & 8) && (dev.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); + blink = ((dev->cgablink & 8) && (dev->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); } if (vflags && (dev->cgamode & 0x80)) { @@ -194,7 +196,7 @@ compaq_cga_poll(void *priv) cols[1] = mdaattr[attr][blink][1]; if (dev->sc == 12 && (attr & 7) == 1) underline = 1; - } else if (dev.cgamode & CGA_MODE_FLAG_BLINK)) { + } else if (dev->cgamode & CGA_MODE_FLAG_BLINK)) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -232,9 +234,9 @@ compaq_cga_poll(void *priv) cols[0] = (dev->cgacol & 15) + 16; if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) - hline(buffer32, 0, dev.displine, (dev.crtc[CGA_CRTC_HDISP] << 3) + 16, cols[0]); + hline(buffer32, 0, dev->displine, (dev->crtc[CGA_CRTC_HDISP] << 3) + 16, cols[0]); else - hline(buffer32, 0, dev.displine, (dev.crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]); + hline(buffer32, 0, dev->displine, (dev->crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]); } if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) @@ -242,8 +244,8 @@ compaq_cga_poll(void *priv) else x = (dev->crtc[CGA_CRTC_HDISP] << 4) + 16; - if (dev.composite) { - if (dev.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) + if (dev->composite) { + if (dev->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) border = 0x00; else border = dev->cgacol & 0x0f; @@ -255,12 +257,12 @@ compaq_cga_poll(void *priv) } else video_process_8(x, dev->displine); - dev.sc = oldsc; - if (dev.vc == dev.crtc[CGA_CRTC_VSYNC] && !dev.sc) - dev.cgastat |= 8; - dev.displine++; - if (dev.displine >= 500) - dev.displine = 0; + dev->sc = oldsc; + if (dev->vc == dev->crtc[CGA_CRTC_VSYNC] && !dev->sc) + dev->cgastat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; } else { timer_advance_u64(&dev->timer, dev->dispontime); dev->linepos = 0; @@ -270,60 +272,60 @@ compaq_cga_poll(void *priv) dev->cgastat &= ~8; } - if (dev.sc == (dev.crtc[11] & 31) || ((dev.crtc[8] & 3) == 3 && dev.sc == ((dev.crtc[11] & 31) >> 1))) { - dev.con = 0; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->cursorvisible = 0; } - if ((dev.crtc[8] & 3) == 3 && dev.sc == (dev.crtc[9] >> 1)) - dev.maback = dev.ma; - if (dev.vadj) { - dev.sc++; - dev.sc &= 31; - dev.ma = dev.maback; - dev.vadj--; - if (!dev.vadj) { - dev.cgadispon = 1; - dev.ma = dev.maback = (dev.crtc[13] | (dev.crtc[12] << 8)) & 0x3fff; - dev.sc = 0; + if ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1)) + dev->maback = dev->ma; + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->cgadispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; } - } else if (dev.sc == dev.crtc[9]) { - dev.maback = dev.ma; - dev.sc = 0; - oldvc = dev.vc; - dev.vc++; - dev.vc &= 127; + } else if (dev->sc == dev->crtc[9]) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; - if (dev.vc == dev.crtc[6]) - dev.cgadispon = 0; + if (dev->vc == dev->crtc[6]) + dev->cgadispon = 0; - if (oldvc == dev.crtc[4]) { - dev.vc = 0; - dev.vadj = dev.crtc[5]; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; if (!dev->vadj) dev->cgadispon = 1; - if (!dev.vadj) - dev.ma = dev.maback = (dev.crtc[13] | (dev.crtc[12] << 8)) & 0x3fff; + if (!dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - if ((dev.crtc[10] & 0x60) == 0x20) - dev.cursoron = 0; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; else dev->cursoron = dev->cgablink & 8; } - if (dev.vc == dev.crtc[7]) { - dev.cgadispon = 0; - dev.displine = 0; - dev.vsynctime = 16; + if (dev->vc == dev->crtc[7]) { + dev->cgadispon = 0; + dev->displine = 0; + dev->vsynctime = 16; - if (dev.crtc[7]) { - compaq_cga_log("Lastline %i Firstline %i %i\n", dev.lastline, - dev.firstline, dev.lastline - dev.firstline); + if (dev->crtc[7]) { + compaq_cga_log("Lastline %i Firstline %i %i\n", dev->lastline, + dev->firstline, dev->lastline - dev->firstline); - if (dev.cgamode & CGA_MODE_FLAG_HIGHRES) - x = (dev.crtc[CGA_CRTC_HDISP] << 3) + 16; + if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) + x = (dev->crtc[CGA_CRTC_HDISP] << 3) + 16; else - x = (dev.crtc[CGA_CRTC_HDISP] << 4) + 16; + x = (dev->crtc[CGA_CRTC_HDISP] << 4) + 16; dev->lastline++; @@ -338,7 +340,7 @@ compaq_cga_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((dev.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + if ((dev->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { xsize = xs_temp; ysize = ys_temp; set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); @@ -359,15 +361,15 @@ compaq_cga_poll(void *priv) if (enable_overscan) xsize -= 16; video_res_y = ysize; - if (dev.cgamode & CGA_MODE_FLAG_HIGHRES) { + if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) { video_res_x /= 8; - video_res_y /= dev.crtc[9] + 1; + video_res_y /= dev->crtc[9] + 1; video_bpp = 0; - } else if (!(dev.cgamode & 2)) { + } else if (!(dev->cgamode & 2)) { video_res_x /= 16; - video_res_y /= dev.crtc[9] + 1; + video_res_y /= dev->crtc[9] + 1; video_bpp = 0; - } else if (!(dev.cgamode & 16)) { + } else if (!(dev->cgamode & 16)) { video_res_x /= 2; video_bpp = 2; } else @@ -388,12 +390,12 @@ compaq_cga_poll(void *priv) if (dev->cgadispon) dev->cgastat &= ~1; - if (dev.sc == (dev.crtc[10] & 31) || ((dev.crtc[8] & 3) == 3 && dev.sc == ((dev.crtc[10] & 31) >> 1))) - dev.con = 1; + if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + dev->cursorvisible = 1; - if (dev.cgadispon && (dev.cgamode & CGA_MODE_FLAG_HIGHRES)) { - for (x = 0; x < (dev.crtc[CGA_CRTC_HDISP] << 1); x++) - dev.charbuffer[x] = dev.vram[((dev.ma << 1) + x) & 0x3fff]; + if (dev->cgadispon && (dev->cgamode & CGA_MODE_FLAG_HIGHRES)) { + for (x = 0; x < (dev->crtc[CGA_CRTC_HDISP] << 1); x++) + dev->charbuffer[x] = dev->vram[((dev->ma << 1) + x) & 0x3fff]; } } } @@ -453,7 +455,7 @@ compaq_cga_init(const device_t *info) cga_palette = (dev->rgb_type << 1); cgapal_rebuild(); - dev.crtc[9] = 13; + dev->crtc[9] = 13; return dev; } @@ -472,7 +474,7 @@ compaq_cga_speed_changed(void *priv) { cga_t *dev = (cga_t *) priv; - if (dev.crtc[9] == 13) /* Character height */ + if (dev->crtc[9] == 13) /* Character height */ compaq_cga_recalctimings(self); else cga_recalctimings(dev); From 386c346ee1a5f57267f618a826ecb83bbdcbd06c Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 9 Jun 2025 23:19:45 +0100 Subject: [PATCH 1117/1190] Fix compile --- src/video/vid_cga_compaq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_cga_compaq.c b/src/video/vid_cga_compaq.c index 1ed739ed8..c36af38b1 100644 --- a/src/video/vid_cga_compaq.c +++ b/src/video/vid_cga_compaq.c @@ -196,7 +196,7 @@ compaq_cga_poll(void *priv) cols[1] = mdaattr[attr][blink][1]; if (dev->sc == 12 && (attr & 7) == 1) underline = 1; - } else if (dev->cgamode & CGA_MODE_FLAG_BLINK)) { + } else if (dev->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -475,7 +475,7 @@ compaq_cga_speed_changed(void *priv) cga_t *dev = (cga_t *) priv; if (dev->crtc[9] == 13) /* Character height */ - compaq_cga_recalctimings(self); + compaq_cga_recalctimings(dev); else cga_recalctimings(dev); } From 4a971a7fbc4319233ae6423f4e94dd0efe9a785b Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Tue, 10 Jun 2025 01:34:15 +0200 Subject: [PATCH 1118/1190] Added the AMD Am28F010 Flash chip. --- src/include/86box/flash.h | 1 + src/mem/catalyst_flash.c | 54 +++++++++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/include/86box/flash.h b/src/include/86box/flash.h index 6f0e1ff15..bd9b7e505 100644 --- a/src/include/86box/flash.h +++ b/src/include/86box/flash.h @@ -20,6 +20,7 @@ #ifndef EMU_FLASH_H #define EMU_FLASH_H +extern const device_t amd_am28f010_flash_device; extern const device_t catalyst_flash_device; extern const device_t intel_flash_bxt_ami_device; diff --git a/src/mem/catalyst_flash.c b/src/mem/catalyst_flash.c index 00e2422a3..5c8812464 100644 --- a/src/mem/catalyst_flash.c +++ b/src/mem/catalyst_flash.c @@ -29,6 +29,7 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/plat.h> +#include <86box/plat_fallthrough.h> #define FLAG_WORD 4 #define FLAG_BXB 2 @@ -44,21 +45,22 @@ enum { }; enum { - CMD_SET_READ = 0x00, - CMD_READ_SIGNATURE = 0x90, - CMD_ERASE = 0x20, - CMD_ERASE_CONFIRM = 0x20, - CMD_ERASE_VERIFY = 0xA0, - CMD_PROGRAM = 0x40, - CMD_PROGRAM_VERIFY = 0xC0, - CMD_RESET = 0xFF + CMD_SET_READ = 0x00, + CMD_READ_AUTO_SELECT = 0x80, + CMD_READ_SIGNATURE = 0x90, + CMD_ERASE = 0x20, + CMD_ERASE_CONFIRM = 0x20, + CMD_ERASE_VERIFY = 0xA0, + CMD_PROGRAM = 0x40, + CMD_PROGRAM_VERIFY = 0xC0, + CMD_RESET = 0xFF }; typedef struct flash_t { uint8_t command; + uint8_t is_amd; uint8_t pad; uint8_t pad0; - uint8_t pad1; uint8_t *array; mem_mapping_t mapping; @@ -83,11 +85,22 @@ flash_read(uint32_t addr, void *priv) ret = dev->array[addr]; break; + case CMD_READ_AUTO_SELECT: + if (!dev->is_amd) + break; + fallthrough; case CMD_READ_SIGNATURE: - if (addr == 0x00000) - ret = 0x31; /* CATALYST */ - else if (addr == 0x00001) - ret = 0xB4; /* 28F010 */ + if (dev->is_amd) { + if (addr == 0x00000) + ret = 0x01; /* AMD */ + else if (addr == 0x00001) + ret = 0xa7; /* Am28F010 */ + } else { + if (addr == 0x00000) + ret = 0x31; /* CATALYST */ + else if (addr == 0x00001) + ret = 0xb4; /* 28F010 */ + } break; default: @@ -205,6 +218,7 @@ catalyst_flash_init(UNUSED(const device_t *info)) catalyst_flash_add_mappings(dev); dev->command = CMD_RESET; + dev->is_amd = info->local; fp = nvr_fopen(flash_path, "rb"); if (fp) { @@ -244,3 +258,17 @@ const device_t catalyst_flash_device = { .force_redraw = NULL, .config = NULL }; + +const device_t amd_am28f010_flash_device = { + .name = "AMD Am28F010-D Flash BIOS", + .internal_name = "amd_am28f010_flash", + .flags = DEVICE_PCI, + .local = 1, + .init = catalyst_flash_init, + .close = catalyst_flash_close, + .reset = catalyst_flash_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; From fe78720d420a39a62d269d30491fe605c9109f84 Mon Sep 17 00:00:00 2001 From: MaxwellS04 <tongpauz@gmail.com> Date: Tue, 10 Jun 2025 15:30:06 +0700 Subject: [PATCH 1119/1190] Assorted device fixes (Jun 30) -Make the internal video for 3302, ActionPC and ActionTower configurable - --- src/machine/m_at_286_386sx.c | 2 +- src/machine/m_at_386dx_486.c | 4 ++-- src/machine/machine_table.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 29298510c..a295f305a 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -1128,7 +1128,7 @@ machine_at_3302_init(const machine_t *model) device_add(&fdc_at_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&paradise_pvga1a_ncr3302_device); + device_add(machine_get_vid_device(machine)); device_add(&keyboard_at_ncr_device); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 86a1aa087..0becae2b8 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2447,7 +2447,7 @@ machine_at_actionpc2600_init(const machine_t *model) device_add(&keyboard_ps2_tg_ami_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&tgui9440_onboard_pci_device); + device_add(machine_get_vid_device(machine)); return ret; } @@ -2479,7 +2479,7 @@ machine_at_actiontower8400_init(const machine_t *model) device_add(&intel_flash_bxt_device); // The ActionPC 2600 has this so I'm gonna assume this does too. device_add(&keyboard_ps2_ami_pci_device); if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5430_onboard_pci_device); + device_add(machine_get_vid_device(machine)); return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 001d9cb8c..13ac1bee1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3692,7 +3692,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &paradise_pvga1a_ncr3302_device, .snd_device = NULL, .net_device = NULL }, @@ -9235,7 +9235,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &tgui9440_onboard_pci_device, .snd_device = NULL, .net_device = NULL }, @@ -9276,7 +9276,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &gd5430_onboard_pci_device, .snd_device = NULL, .net_device = NULL }, From a28d3e53200355b99feb92cc7d31ae2748fc343e Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Tue, 10 Jun 2025 13:58:09 +0300 Subject: [PATCH 1120/1190] Fixes for broken translation Fixes for broken translation --- src/device/isarom.c | 40 ++++++++++++++++++------------------- src/device/novell_cardkey.c | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/device/isarom.c b/src/device/isarom.c index 238314c87..f742a9eae 100644 --- a/src/device/isarom.c +++ b/src/device/isarom.c @@ -212,7 +212,7 @@ isarom_init(const device_t *info) static const device_config_t isarom_config[] = { { .name = "bios_fn", - .description = "BIOS File", + .description = "BIOS file", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -234,7 +234,7 @@ static const device_config_t isarom_config[] = { }, { .name = "bios_size", - .description = "BIOS Size:", + .description = "BIOS size", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, @@ -260,7 +260,7 @@ static const device_config_t isarom_config[] = { static const device_config_t isarom_dual_config[] = { { .name = "bios_fn", - .description = "BIOS File (ROM #1)", + .description = "BIOS file (ROM #1)", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -271,7 +271,7 @@ static const device_config_t isarom_dual_config[] = { }, { .name = "bios_addr", - .description = "BIOS Address (ROM #1)", + .description = "BIOS address (ROM #1)", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 0x00000, @@ -282,7 +282,7 @@ static const device_config_t isarom_dual_config[] = { }, { .name = "bios_size", - .description = "BIOS Size (ROM #1):", + .description = "BIOS size (ROM #1)", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, @@ -304,7 +304,7 @@ static const device_config_t isarom_dual_config[] = { }, { .name = "bios_fn2", - .description = "BIOS File (ROM #2)", + .description = "BIOS file (ROM #2)", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -315,7 +315,7 @@ static const device_config_t isarom_dual_config[] = { }, { .name = "bios_addr2", - .description = "BIOS Address (ROM #2)", + .description = "BIOS address (ROM #2)", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 0x00000, @@ -326,7 +326,7 @@ static const device_config_t isarom_dual_config[] = { }, { .name = "bios_size2", - .description = "BIOS Size (ROM #2):", + .description = "BIOS size (ROM #2)", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, @@ -352,7 +352,7 @@ static const device_config_t isarom_dual_config[] = { static const device_config_t isarom_quad_config[] = { { .name = "bios_fn", - .description = "BIOS File (ROM #1)", + .description = "BIOS file (ROM #1)", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -363,7 +363,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_addr", - .description = "BIOS Address (ROM #1)", + .description = "BIOS address (ROM #1)", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 0x00000, @@ -374,7 +374,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_size", - .description = "BIOS Size (ROM #1):", + .description = "BIOS size (ROM #1)", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, @@ -396,7 +396,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_fn2", - .description = "BIOS File (ROM #2)", + .description = "BIOS file (ROM #2)", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -407,7 +407,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_addr2", - .description = "BIOS Address (ROM #2)", + .description = "BIOS address (ROM #2)", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 0x00000, @@ -418,7 +418,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_size2", - .description = "BIOS Size (ROM #2):", + .description = "BIOS size (ROM #2)", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, @@ -440,7 +440,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_fn3", - .description = "BIOS File (ROM #3)", + .description = "BIOS file (ROM #3)", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -451,7 +451,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_addr3", - .description = "BIOS Address (ROM #3)", + .description = "BIOS address (ROM #3)", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 0x00000, @@ -462,7 +462,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_size3", - .description = "BIOS Size (ROM #3):", + .description = "BIOS size (ROM #3)", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, @@ -484,7 +484,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_fn4", - .description = "BIOS File (ROM #4)", + .description = "BIOS file (ROM #4)", .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, @@ -495,7 +495,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_addr4", - .description = "BIOS Address (ROM #4)", + .description = "BIOS address (ROM #4)", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 0x00000, @@ -506,7 +506,7 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "bios_size4", - .description = "BIOS Size (ROM #4):", + .description = "BIOS size (ROM #4)", .type = CONFIG_INT, .default_string = NULL, .default_int = 8192, diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index 8820addde..08334e751 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -109,7 +109,7 @@ static const device_config_t keycard_config[] = { }; const device_t novell_keycard_device = { - .name = "Novell Netware 2.x Key Card", + .name = "Novell NetWare 2.x Key Card", .internal_name = "mssystems", .flags = DEVICE_ISA, .local = 0, From 23f697782efda70e59e48d3661fbaf27cda95fc8 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Tue, 10 Jun 2025 13:59:15 +0300 Subject: [PATCH 1121/1190] Fixes for broken translation Fixes for broken translation --- src/floppy/fdc_monster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c index b91d4db66..04536520f 100644 --- a/src/floppy/fdc_monster.c +++ b/src/floppy/fdc_monster.c @@ -183,7 +183,7 @@ static const device_config_t monster_fdc_config[] = { #if 0 { .name = "bios_size", - .description = "BIOS Size:", + .description = "BIOS size", .type = CONFIG_HEX20, .default_string = NULL, .default_int = 32, From fdfb338ae9d36d3e99112acf4880814867e27932 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:00:02 +0300 Subject: [PATCH 1122/1190] Fixes for broken translation Fixes for broken translation --- src/video/vid_ps55da2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 567d60347..2cc993b8c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -3441,7 +3441,7 @@ static const device_config_t da2_configuration[] = { // clang-format off { .name = "charset", - .description = "Charset", + .description = "Character set", .type = CONFIG_SELECTION, .default_int = DA2_DCONFIG_CHARSET_JPAN, .selection = { From b746a23768ae376b2a93fd89a5e503c9335d447d Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:00:59 +0300 Subject: [PATCH 1123/1190] Update the Russian translation Update the Russian translation --- src/qt/languages/ru-RU.po | 135 +++++++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 9 deletions(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 19975c2c9..719e5afc0 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -598,7 +598,10 @@ msgid "ISA RTC:" msgstr "ISA RTC:" msgid "ISA Memory Expansion" -msgstr "Карта расширения памяти ISA" +msgstr "Карты расширения памяти ISA" + +msgid "ISA ROM Cards" +msgstr "Карты ПЗУ ISA" msgid "Card 1:" msgstr "Карта 1:" @@ -1237,7 +1240,7 @@ msgid "Pen" msgstr "Ручка" msgid "Host CD/DVD Drive (%1:)" -msgstr "CD/DVD-привод хоста (%1:)" +msgstr "CD/DVD Привод хоста (%1:)" msgid "&Connected" msgstr "&Кабель подключен" @@ -1249,7 +1252,7 @@ msgid "Create..." msgstr "Создать..." msgid "Host CD/DVD Drive (%1)" -msgstr "CD/DVD-привод хоста (%1)" +msgstr "CD/DVD Привод хоста (%1)" msgid "Unknown Bus" msgstr "Неизвестная шина" @@ -1413,12 +1416,54 @@ msgstr "Системный MIDI" msgid "MIDI Input Device" msgstr "Устройство ввода MIDI" +msgid "BIOS file" +msgstr "Файл BIOS" + +msgid "BIOS file (ROM #1)" +msgstr "Файл BIOS (ПЗУ #1)" + +msgid "BIOS file (ROM #2)" +msgstr "Файл BIOS (ПЗУ #2)" + +msgid "BIOS file (ROM #3)" +msgstr "Файл BIOS (ПЗУ #3)" + +msgid "BIOS file (ROM #4)" +msgstr "Файл BIOS (ПЗУ #4)" + msgid "BIOS Address" msgstr "Адрес BIOS" +msgid "BIOS address (ROM #1)" +msgstr "Адрес BIOS (ПЗУ #1)" + +msgid "BIOS address (ROM #2)" +msgstr "Адрес BIOS (ПЗУ #2)" + +msgid "BIOS address (ROM #3)" +msgstr "Адрес BIOS (ПЗУ #3)" + +msgid "BIOS address (ROM #4)" +msgstr "Адрес BIOS (ПЗУ #4)" + msgid "Enable BIOS extension ROM Writes" msgstr "Разрешить запись в ПЗУ расширения BIOS" +msgid "Enable BIOS extension ROM Writes (ROM #1)" +msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #1)" + +msgid "Enable BIOS extension ROM Writes (ROM #2)" +msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #2)" + +msgid "Enable BIOS extension ROM Writes (ROM #3)" +msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #3)" + +msgid "Enable BIOS extension ROM Writes (ROM #4)" +msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #4)" + +msgid "Linear framebuffer base" +msgstr "Линейная база кадрового буфера" + msgid "Address" msgstr "Адрес" @@ -1428,6 +1473,21 @@ msgstr "IRQ" msgid "BIOS Revision" msgstr "Версия BIOS" +msgid "BIOS Version" +msgstr "Версия BIOS" + +msgid "BIOS Versions" +msgstr "Версии BIOS" + +msgid "BIOS Language" +msgstr "Язык BIOS" + +msgid "IBM 5161 Expansion Unit" +msgstr "Блок расширения IBM 5161" + +msgid "IBM Cassette Basic" +msgstr "Кассетный бейсик IBM" + msgid "Translate 26 -> 17" msgstr "Переводить 26 -> 17" @@ -1443,6 +1503,18 @@ msgstr "Инвертировать цвета" msgid "BIOS size" msgstr "Размер BIOS" +msgid "BIOS size (ROM #1)" +msgstr "Размер BIOS (ПЗУ #1)" + +msgid "BIOS size (ROM #2)" +msgstr "Размер BIOS (ПЗУ #2)" + +msgid "BIOS size (ROM #3)" +msgstr "Размер BIOS (ПЗУ #3)" + +msgid "BIOS size (ROM #4)" +msgstr "Размер BIOS (ПЗУ #4)" + msgid "Map C0000-C7FFF as UMB" msgstr "Отображение C0000-C7FFF в качестве UMB" @@ -1518,6 +1590,9 @@ msgstr "Уровень реверберации" msgid "Interpolation Method" msgstr "Метод интерполяции" +msgid "Dynamic Sample Loading" +msgstr "Динамическая загрузка образца" + msgid "Reverb Output Gain" msgstr "Усиление выходного сигнала ревербератора" @@ -1606,7 +1681,7 @@ msgid "Enable Game port" msgstr "Включить игровой порт" msgid "Surround module" -msgstr "Модуль объемного звучания" +msgstr "Модуль объёмного звучания" msgid "CODEC" msgstr "Кодек" @@ -1617,6 +1692,9 @@ msgstr "Поднимать прерывание кодека при настро msgid "SB Address" msgstr "Адрес SB" +msgid "Use EEPROM setting" +msgstr "Использовать настройку EEPROM" + msgid "WSS IRQ" msgstr "IRQ WSS" @@ -1701,6 +1779,9 @@ msgstr "Тип RAMDAC" msgid "Blend" msgstr "Смесь" +msgid "Font" +msgstr "Шрифт" + msgid "Bilinear filtering" msgstr "Билинейная фильтрация" @@ -1746,6 +1827,33 @@ msgstr "Скорость передачи данных" msgid "EMS mode" msgstr "Режим EMS" +msgid "EMS Address" +msgstr "Адрес EMS" + +msgid "EMS 1 Address" +msgstr "Адрес EMS 1" + +msgid "EMS 2 Address" +msgstr "Адрес EMS 2" + +msgid "EMS Memory Size" +msgstr "Размер памяти EMS" + +msgid "EMS 1 Memory Size" +msgstr "Размер памяти EMS 1" + +msgid "EMS 2 Memory Size" +msgstr "Размер памяти EMS 2" + +msgid "Enable EMS" +msgstr "Включить EMS" + +msgid "Enable EMS 1" +msgstr "Включить EMS 1" + +msgid "Enable EMS 2" +msgstr "Включить EMS 2" + msgid "Address for > 2 MB" msgstr "Адрес для > 2 МБ" @@ -1765,10 +1873,10 @@ msgid "BIOS setting + Hotkeys (off during POST)" msgstr "Настройка BIOS + горячие клавиши (отключается во время POST)" msgid "64 kB starting from F0000" -msgstr "64 кБ, начиная с F0000" +msgstr "64 КБ, начиная с F0000" msgid "128 kB starting from E0000 (address MSB inverted, last 64KB first)" -msgstr "128 кБ, начиная с E0000 (адрес MSB инвертирован, сначала последние 64 КБ)" +msgstr "128 КБ, начиная с E0000 (адрес MSB инвертирован, сначала последние 64 КБ)" msgid "Sine" msgstr "Синусоидальная" @@ -1792,7 +1900,7 @@ msgid "45 Hz (JMP2 not populated)" msgstr "45 Гц (без джампера на JMP2)" msgid "Two" -msgstr "Два" +msgstr "Две" msgid "Three" msgstr "Три" @@ -1935,6 +2043,9 @@ msgstr "Янтарный" msgid "Gray" msgstr "Серый" +msgid "Grayscale" +msgstr "Монохромный" + msgid "Color" msgstr "Цветной" @@ -1950,6 +2061,12 @@ msgstr "Другие языки" msgid "Bochs latest" msgstr "Bochs последний" +msgid "Apply overscan deltas" +msgstr "Применить дельты вылетов развёртки" + +msgid "Mono Interlaced" +msgstr "Монохромный с чересстрочной развёрткой" + msgid "Mono Non-Interlaced" msgstr "Монохромный без чересстрочной развёртки" @@ -2095,7 +2212,7 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P." msgid "Inhibit multimedia keys" -msgstr "Перехватывать мультимедиа-клавиши" +msgstr "Перехватывать мультимедийные клавиши" msgid "Ask for confirmation before saving settings" msgstr "Запрашивать подтверждение перед сохранением настроек" @@ -2182,7 +2299,7 @@ msgid "Send Control+Alt+Escape" msgstr "Отправить Control+Alt+Escape" msgid "Toggle fullscreen" -msgstr "Переключить на полноэкранный режим" +msgstr "Переключить полноэкранный режим" msgid "Screenshot" msgstr "Скриншот" From fa0925057a26dd6b665b710b3dd8f6ecbd0b5d28 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:17:44 +0300 Subject: [PATCH 1124/1190] Update src/qt/languages/ru-RU.po Co-authored-by: Alexander Babikov <lemondrops358@gmail.com> --- src/qt/languages/ru-RU.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 719e5afc0..bb8a9caf5 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1591,7 +1591,7 @@ msgid "Interpolation Method" msgstr "Метод интерполяции" msgid "Dynamic Sample Loading" -msgstr "Динамическая загрузка образца" +msgstr "Динамическая загрузка сэмплов" msgid "Reverb Output Gain" msgstr "Усиление выходного сигнала ревербератора" From d3f13cf82b1610356c549425820567f06f788e22 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Tue, 10 Jun 2025 18:14:44 +0200 Subject: [PATCH 1125/1190] Added the Ast! Advantage 40xxd. --- src/include/86box/machine.h | 1 + src/include/86box/sio.h | 2 ++ src/include/86box/video.h | 1 + src/machine/m_at_386dx_486.c | 27 ++++++++++++++++++++++++ src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ src/sio/sio_um8663f.c | 28 +++++++++++++++++++++++++ src/video/vid_cl54xx.c | 22 +++++++++++++++++++- 7 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 7aec5db4f..e59ca494a 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -564,6 +564,7 @@ extern int machine_at_dtk461_init(const machine_t *); extern int machine_at_sis401_init(const machine_t *); extern int machine_at_isa486_init(const machine_t *); extern int machine_at_av4_init(const machine_t *); +extern int machine_at_advantage40xxd_init(const machine_t *); extern int machine_at_valuepoint433_init(const machine_t *); extern int machine_at_vli486sv2g_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 358cd8c9a..613b294d8 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -125,6 +125,8 @@ extern const device_t sio_detect_device; #endif /* USE_SIO_DETECT */ /* UMC */ +extern const device_t um82c863f_device; +extern const device_t um82c863f_ide_device; extern const device_t um8663af_device; extern const device_t um8663af_ide_device; extern const device_t um8663af_sec_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 6ab375370..74658708c 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -359,6 +359,7 @@ extern const device_t gd5420_isa_device; extern const device_t gd5420_onboard_device; extern const device_t gd5422_isa_device; extern const device_t gd5424_vlb_device; +extern const device_t gd5424_onboard_device; extern const device_t gd5426_isa_device; extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device; extern const device_t gd5426_vlb_device; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0becae2b8..b2a335e61 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1009,6 +1009,33 @@ machine_at_ami471_init(const machine_t *model) return ret; } +int +machine_at_advantage40xxd_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/advantage40xxd/AST101.09A", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sis_85c471_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&keyboard_ps2_phoenix_device); + + device_add(&ide_vlb_device); + device_add(&um82c863f_ide_device); + + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_vli486sv2g_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 28d4a9a6a..371cb7d47 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6485,6 +6485,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has Phoenix KBC firmware. */ + { + .name = "[SiS 471] AST Advantage! 40xxd", + .internal_name = "advantage40xxd", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_advantage40xxd_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 2 + }, + .bus_flags = MACHINE_PS2_VLB, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 4096, + .max = 36864, + .step = 4096 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5424_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware. */ { .name = "[Symphony SL42C460] DTK PKM-0031Y", diff --git a/src/sio/sio_um8663f.c b/src/sio/sio_um8663f.c index 54f12dda6..03fa4f9aa 100644 --- a/src/sio/sio_um8663f.c +++ b/src/sio/sio_um8663f.c @@ -281,6 +281,34 @@ um8663f_init(UNUSED(const device_t *info)) return dev; } +const device_t um82c863f_device = { + .name = "UMC UM82C863F Super I/O", + .internal_name = "um82c863f", + .flags = 0, + .local = 0xc100, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um82c863f_ide_device = { + .name = "UMC UM82C863F Super I/O (With IDE)", + .internal_name = "um82c863f_ide", + .flags = 0, + .local = 0xc101, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t um8663af_device = { .name = "UMC UM8663AF Super I/O", .internal_name = "um8663af", diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 2377e792b..bad42156b 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4254,10 +4254,16 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5422: - case CIRRUS_ID_CLGD5424: romfn = BIOS_GD5422_PATH; break; + case CIRRUS_ID_CLGD5424: + if (info->local & 0x200) + romfn = /*NULL*/ "roms/machines/advantage40xxd/AST101.09A"; + else + romfn = BIOS_GD5422_PATH; + break; + case CIRRUS_ID_CLGD5426: if (info->local & 0x200) romfn = NULL; @@ -5023,6 +5029,20 @@ const device_t gd5424_vlb_device = { .config = gd542x_config, }; +const device_t gd5424_onboard_device = { + .name = "Cirrus Logic GD5424 (VLB) (On-Board)", + .internal_name = "cl_gd5424_onboard", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5424 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + .available = NULL, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config, +}; + const device_t gd5426_isa_device = { .name = "Cirrus Logic GD5426 (ISA)", .internal_name = "cl_gd5426_isa", From 738b084148edfcfc283ad787101a2a3a2756944a Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Tue, 10 Jun 2025 18:20:35 +0200 Subject: [PATCH 1126/1190] Some small fixes to the Plasma (June 10th, 2025) Including a small cleanup as well. And fixes to the attributes. --- src/video/vid_cga_compaq_plasma.c | 162 ++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 55 deletions(-) diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index feb9a12c8..db4218a89 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -174,7 +174,7 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA; This leads me to believe bit 2 is not relevant to the mode. */ - if ((val & 0x03) == 0x03) + if ((val & 0x07) == 0x03) mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000); else mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000); @@ -182,7 +182,6 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x23c6: self->port_23c6 = val; - compaq_plasma_recalcattrs(self); break; case 0x27c6: @@ -221,10 +220,6 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x13c6: ret = self->port_13c6; -#if 0 - if ((self->cga.cgamode & 0x28) == 0x00) - ret |= 0x04; -#endif break; case 0x17c6: @@ -264,11 +259,15 @@ compaq_plasma_poll(void *priv) int cursorline; int blink = 0; int underline = 0; + int cursorvisible = 0; + int cursorinvisible = 0; int c; int x; uint32_t ink = 0; uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; uint32_t bg = black; + uint32_t black_half = black; + uint32_t amber_half = amber; uint32_t cols[2]; uint8_t dat; uint8_t pattern; @@ -304,8 +303,19 @@ compaq_plasma_poll(void *priv) if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cursorline = 0; - else - cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); + else { + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) > 0x07) + cursorvisible = (self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) + 1; + else + cursorvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1); + + if ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) > 0x07) + cursorinvisible = (self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) + 2; + else + cursorinvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1); + + cursorline = (cursorvisible <= sc) && (cursorinvisible >= sc); + } /* for each text column */ for (x = 0; x < 80; x++) { @@ -319,12 +329,10 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } - uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = ((attr & 0x07) == 0x01); - underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); + underline = ((self->port_23c6 >> 5) == 1) && (attr & 0x1) && !(attr & 0x6); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -349,11 +357,11 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && hi_bit) + if ((self->port_23c6 >> 5) == 3) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { + if (underline) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; @@ -365,17 +373,39 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if (hi_bit) { - if ((self->port_23c6 >> 5) == 1) { + if ((self->port_23c6 >> 5) == 4) { + uint8_t b = (cols[1] & 0xff) >> 1; + uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; + uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; + cols[1] = b | (g << 8) | (r << 16); + b = (cols[0] & 0xff) >> 1; + g = ((cols[0] >> 8) & 0xff) >> 1; + r = ((cols[0] >> 16) & 0xff) >> 1; + cols[0] = b | (g << 8) | (r << 16); + if (drawcursor) { + black_half = black; + amber_half = amber; + uint8_t bB = (black & 0xff) >> 1; + uint8_t gB = ((black >> 8) & 0xff) >> 1; + uint8_t rB = ((black >> 16) & 0xff) >> 1; + black_half = bB | (gB << 8) | (rB << 16); + uint8_t bA = (amber & 0xff) >> 1; + uint8_t gA = ((amber >> 8) & 0xff) >> 1; + uint8_t rA = ((amber >> 16) & 0xff) >> 1; + amber_half = bA | (gA << 8) | (rA << 16); for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); - } else if ((self->port_23c6 >> 5) == 4) { - for (c = 0; c < 8; c++) { - uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f; - uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f; - uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f; - buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16); - } + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + } else if ((self->port_23c6 >> 5) == 2) { + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; } } ma++; @@ -389,9 +419,20 @@ compaq_plasma_poll(void *priv) if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cursorline = 0; - else - cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); + else { + if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) > 0x07) + cursorvisible = (self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) + 1; + else + cursorvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1); + if ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) > 0x07) + cursorinvisible = (self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) + 2; + else + cursorinvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1); + + cursorline = (cursorvisible <= sc) && (cursorinvisible >= sc); + } + for (x = 0; x < 40; x++) { /* video output enabled */ if (self->cga.cgamode & 0x08) { @@ -407,8 +448,7 @@ compaq_plasma_poll(void *priv) /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = ((attr & 0x07) == 0x01); - underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); + underline = ((self->port_23c6 >> 5) == 1) && (attr & 0x1) && !(attr & 0x6); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -450,18 +490,41 @@ compaq_plasma_poll(void *priv) } if (hi_bit) { - if ((self->port_23c6 >> 5) == 1) - for (c = 0; c < 8; c++) { - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black); + if ((self->port_23c6 >> 5) == 4) { + uint8_t b = (cols[1] & 0xff) >> 1; + uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; + uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; + cols[1] = b | (g << 8) | (r << 16); + b = (cols[0] & 0xff) >> 1; + g = ((cols[0] >> 8) & 0xff) >> 1; + r = ((cols[0] >> 16) & 0xff) >> 1; + cols[0] = b | (g << 8) | (r << 16); + if (drawcursor) { + black_half = black; + amber_half = amber; + uint8_t bB = (black & 0xff) >> 1; + uint8_t gB = ((black >> 8) & 0xff) >> 1; + uint8_t rB = ((black >> 16) & 0xff) >> 1; + black_half = bB | (gB << 8) | (rB << 16); + uint8_t bA = (amber & 0xff) >> 1; + uint8_t gA = ((amber >> 8) & 0xff) >> 1; + uint8_t rA = ((amber >> 16) & 0xff) >> 1; + amber_half = bA | (gA << 8) | (rA << 16); + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - else if ((self->port_23c6 >> 5) == 4) - for (c = 0; c < 8; c++) { - uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f; - uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f; - uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f; - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); + } else if ((self->port_23c6 >> 5) == 2) { + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; } + } } ma++; } @@ -638,30 +701,18 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x11; n <= 0xFF; n++) { if ((n & 7) == 0) continue; - if ((self->port_23c6 >> 5) == 1) { /* Inverse */ - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } else { /* Normal */ - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - } + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; } /* Set up the 01-0E range, controlled by bits 0 and 1 of the * passed value. When blinking is enabled this also affects 81-8E. */ for (n = 0x01; n <= 0x0E; n++) { if (n == 7) continue; - if ((self->port_23c6 >> 5) == 1) { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n + 128][0] = amber; - blinkcols[n + 128][1] = black; - } else { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n + 128][0] = black; - blinkcols[n + 128][1] = amber; - } + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; } /* Colours 07 and 0F are always amber on black. If blinking is * enabled so are 87 and 8F. */ @@ -720,6 +771,7 @@ compaq_plasma_init(UNUSED(const device_t *info)) io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); overscan_x = overscan_y = 16; + compaq_plasma_recalcattrs(self); self->cga.rgb_type = device_get_config_int("rgb_type"); cga_palette = (self->cga.rgb_type << 1); From a8df05354b1e7d9770851d520a3b0a63e0619b98 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Tue, 10 Jun 2025 18:28:16 +0200 Subject: [PATCH 1127/1190] Small fix again. --- src/video/vid_cga_compaq_plasma.c | 73 +++++++++++++++---------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index db4218a89..57aae2bf5 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -432,7 +432,7 @@ compaq_plasma_poll(void *priv) cursorline = (cursorvisible <= sc) && (cursorinvisible >= sc); } - + for (x = 0; x < 40; x++) { /* video output enabled */ if (self->cga.cgamode & 0x08) { @@ -444,7 +444,6 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } - uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ @@ -473,7 +472,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && hi_bit) + if ((self->port_23c6 >> 5) == 3) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -489,41 +488,39 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if (hi_bit) { - if ((self->port_23c6 >> 5) == 4) { - uint8_t b = (cols[1] & 0xff) >> 1; - uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; - uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; - cols[1] = b | (g << 8) | (r << 16); - b = (cols[0] & 0xff) >> 1; - g = ((cols[0] >> 8) & 0xff) >> 1; - r = ((cols[0] >> 16) & 0xff) >> 1; - cols[0] = b | (g << 8) | (r << 16); - if (drawcursor) { - black_half = black; - amber_half = amber; - uint8_t bB = (black & 0xff) >> 1; - uint8_t gB = ((black >> 8) & 0xff) >> 1; - uint8_t rB = ((black >> 16) & 0xff) >> 1; - black_half = bB | (gB << 8) | (rB << 16); - uint8_t bA = (amber & 0xff) >> 1; - uint8_t gA = ((amber >> 8) & 0xff) >> 1; - uint8_t rA = ((amber >> 16) & 0xff) >> 1; - amber_half = bA | (gA << 8) | (rA << 16); - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; - } - } else if ((self->port_23c6 >> 5) == 2) { - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; - } + if ((self->port_23c6 >> 5) == 4) { + uint8_t b = (cols[1] & 0xff) >> 1; + uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; + uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; + cols[1] = b | (g << 8) | (r << 16); + b = (cols[0] & 0xff) >> 1; + g = ((cols[0] >> 8) & 0xff) >> 1; + r = ((cols[0] >> 16) & 0xff) >> 1; + cols[0] = b | (g << 8) | (r << 16); + if (drawcursor) { + black_half = black; + amber_half = amber; + uint8_t bB = (black & 0xff) >> 1; + uint8_t gB = ((black >> 8) & 0xff) >> 1; + uint8_t rB = ((black >> 16) & 0xff) >> 1; + black_half = bB | (gB << 8) | (rB << 16); + uint8_t bA = (amber & 0xff) >> 1; + uint8_t gA = ((amber >> 8) & 0xff) >> 1; + uint8_t rA = ((amber >> 16) & 0xff) >> 1; + amber_half = bA | (gA << 8) | (rA << 16); + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + } else if ((self->port_23c6 >> 5) == 2) { + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; } } ma++; From dfb601190106e723f3061f2ce990af427ba6f6d6 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Tue, 10 Jun 2025 19:02:40 +0200 Subject: [PATCH 1128/1190] Restore the attribute check (bit 3 of attr) --- src/video/vid_cga_compaq_plasma.c | 150 ++++++++++++++++-------------- 1 file changed, 80 insertions(+), 70 deletions(-) diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index 57aae2bf5..5985faae6 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -329,10 +329,13 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } + + uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = ((self->port_23c6 >> 5) == 1) && (attr & 0x1) && !(attr & 0x6); + underline = ((attr & 0x07) == 0x01); + underline = underline || (((self->port_23c6 >> 5) == 1) && hi_bit); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -357,7 +360,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if ((self->port_23c6 >> 5) == 3) + if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -373,39 +376,41 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if ((self->port_23c6 >> 5) == 4) { - uint8_t b = (cols[1] & 0xff) >> 1; - uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; - uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; - cols[1] = b | (g << 8) | (r << 16); - b = (cols[0] & 0xff) >> 1; - g = ((cols[0] >> 8) & 0xff) >> 1; - r = ((cols[0] >> 16) & 0xff) >> 1; - cols[0] = b | (g << 8) | (r << 16); - if (drawcursor) { - black_half = black; - amber_half = amber; - uint8_t bB = (black & 0xff) >> 1; - uint8_t gB = ((black >> 8) & 0xff) >> 1; - uint8_t rB = ((black >> 16) & 0xff) >> 1; - black_half = bB | (gB << 8) | (rB << 16); - uint8_t bA = (amber & 0xff) >> 1; - uint8_t gA = ((amber >> 8) & 0xff) >> 1; - uint8_t rA = ((amber >> 16) & 0xff) >> 1; - amber_half = bA | (gA << 8) | (rA << 16); - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; - } - } else if ((self->port_23c6 >> 5) == 2) { - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; + if (hi_bit) { + if ((self->port_23c6 >> 5) == 4) { + uint8_t b = (cols[1] & 0xff) >> 1; + uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; + uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; + cols[1] = b | (g << 8) | (r << 16); + b = (cols[0] & 0xff) >> 1; + g = ((cols[0] >> 8) & 0xff) >> 1; + r = ((cols[0] >> 16) & 0xff) >> 1; + cols[0] = b | (g << 8) | (r << 16); + if (drawcursor) { + black_half = black; + amber_half = amber; + uint8_t bB = (black & 0xff) >> 1; + uint8_t gB = ((black >> 8) & 0xff) >> 1; + uint8_t rB = ((black >> 16) & 0xff) >> 1; + black_half = bB | (gB << 8) | (rB << 16); + uint8_t bA = (amber & 0xff) >> 1; + uint8_t gA = ((amber >> 8) & 0xff) >> 1; + uint8_t rA = ((amber >> 16) & 0xff) >> 1; + amber_half = bA | (gA << 8) | (rA << 16); + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + } else if ((self->port_23c6 >> 5) == 2) { + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; + } } } ma++; @@ -444,10 +449,13 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } + + uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = ((self->port_23c6 >> 5) == 1) && (attr & 0x1) && !(attr & 0x6); + underline = ((attr & 0x07) == 0x01); + underline = underline || (((self->port_23c6 >> 5) == 1) && hi_bit); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -472,7 +480,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if ((self->port_23c6 >> 5) == 3) + if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -488,39 +496,41 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if ((self->port_23c6 >> 5) == 4) { - uint8_t b = (cols[1] & 0xff) >> 1; - uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; - uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; - cols[1] = b | (g << 8) | (r << 16); - b = (cols[0] & 0xff) >> 1; - g = ((cols[0] >> 8) & 0xff) >> 1; - r = ((cols[0] >> 16) & 0xff) >> 1; - cols[0] = b | (g << 8) | (r << 16); - if (drawcursor) { - black_half = black; - amber_half = amber; - uint8_t bB = (black & 0xff) >> 1; - uint8_t gB = ((black >> 8) & 0xff) >> 1; - uint8_t rB = ((black >> 16) & 0xff) >> 1; - black_half = bB | (gB << 8) | (rB << 16); - uint8_t bA = (amber & 0xff) >> 1; - uint8_t gA = ((amber >> 8) & 0xff) >> 1; - uint8_t rA = ((amber >> 16) & 0xff) >> 1; - amber_half = bA | (gA << 8) | (rA << 16); - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; - } - } else if ((self->port_23c6 >> 5) == 2) { - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; + if (hi_bit) { + if ((self->port_23c6 >> 5) == 4) { + uint8_t b = (cols[1] & 0xff) >> 1; + uint8_t g = ((cols[1] >> 8) & 0xff) >> 1; + uint8_t r = ((cols[1] >> 16) & 0xff) >> 1; + cols[1] = b | (g << 8) | (r << 16); + b = (cols[0] & 0xff) >> 1; + g = ((cols[0] >> 8) & 0xff) >> 1; + r = ((cols[0] >> 16) & 0xff) >> 1; + cols[0] = b | (g << 8) | (r << 16); + if (drawcursor) { + black_half = black; + amber_half = amber; + uint8_t bB = (black & 0xff) >> 1; + uint8_t gB = ((black >> 8) & 0xff) >> 1; + uint8_t rB = ((black >> 16) & 0xff) >> 1; + black_half = bB | (gB << 8) | (rB << 16); + uint8_t bA = (amber & 0xff) >> 1; + uint8_t gA = ((amber >> 8) & 0xff) >> 1; + uint8_t rA = ((amber >> 16) & 0xff) >> 1; + amber_half = bA | (gA << 8) | (rA << 16); + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + } else if ((self->port_23c6 >> 5) == 2) { + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1]; + } } } ma++; From dd7f3d0aae4ef9bce533031ffebe8b34e566d696 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Tue, 10 Jun 2025 22:53:45 +0100 Subject: [PATCH 1129/1190] ma -> memaddr ma_latch -> memaddr_latch maback -> memaddr_backup ca -> cursoraddr sc -> scanline oldsc -> scanline_old --- src/include/86box/m_pcjr.h | 6 +- src/include/86box/m_tandy.h | 6 +- src/include/86box/vid_8514a.h | 8 +- src/include/86box/vid_cga.h | 6 +- src/include/86box/vid_ega.h | 16 +- src/include/86box/vid_ega_render_remap.h | 4 +- src/include/86box/vid_hercules.h | 6 +- src/include/86box/vid_mda.h | 6 +- src/include/86box/vid_pgc.h | 4 +- src/include/86box/vid_svga.h | 10 +- src/include/86box/vid_svga_render.h | 6 +- src/include/86box/vid_svga_render_remap.h | 4 +- src/include/86box/vid_xga.h | 8 +- src/machine/m_amstrad.c | 210 +++++----- src/video/vid_8514a.c | 114 ++--- src/video/vid_ati18800.c | 4 +- src/video/vid_ati28800.c | 10 +- src/video/vid_ati_mach64.c | 4 +- src/video/vid_ati_mach8.c | 52 +-- src/video/vid_bochs_vbe.c | 10 +- src/video/vid_cga.c | 86 ++-- src/video/vid_cga_colorplus.c | 58 +-- src/video/vid_cga_compaq.c | 70 ++-- src/video/vid_cga_compaq_plasma.c | 44 +- src/video/vid_cga_ncr.c | 84 ++-- src/video/vid_cga_olivetti.c | 80 ++-- src/video/vid_cga_toshiba_t1000.c | 52 +-- src/video/vid_cga_toshiba_t3100e.c | 56 +-- src/video/vid_chips_69000.c | 4 +- src/video/vid_cl54xx.c | 6 +- src/video/vid_ega.c | 72 ++-- src/video/vid_ega_render.c | 20 +- src/video/vid_et3000.c | 4 +- src/video/vid_et4000.c | 10 +- src/video/vid_et4000w32.c | 4 +- src/video/vid_f82c425.c | 30 +- src/video/vid_genius.c | 34 +- src/video/vid_hercules.c | 68 +-- src/video/vid_hercules_incolor.c | 84 ++-- src/video/vid_hercules_plus.c | 80 ++-- src/video/vid_ht216.c | 6 +- src/video/vid_ibm_rgb528_ramdac.c | 88 ++-- src/video/vid_jega.c | 22 +- src/video/vid_mda.c | 54 +-- src/video/vid_mga.c | 44 +- src/video/vid_oak_oti.c | 6 +- src/video/vid_paradise.c | 2 +- src/video/vid_pcjr.c | 98 ++--- src/video/vid_pgc.c | 32 +- src/video/vid_ps55da2.c | 144 +++---- src/video/vid_rtg310x.c | 4 +- src/video/vid_s3.c | 12 +- src/video/vid_s3_virge.c | 12 +- src/video/vid_sigma.c | 106 ++--- src/video/vid_svga.c | 60 +-- src/video/vid_svga_render.c | 490 +++++++++++----------- src/video/vid_tandy.c | 98 ++--- src/video/vid_tgui9440.c | 12 +- src/video/vid_tvga.c | 10 +- src/video/vid_vga.c | 2 +- src/video/vid_voodoo_banshee.c | 4 +- src/video/vid_wy700.c | 28 +- src/video/vid_xga.c | 82 ++-- 63 files changed, 1428 insertions(+), 1428 deletions(-) diff --git a/src/include/86box/m_pcjr.h b/src/include/86box/m_pcjr.h index 8ba0c4414..3ffcc3b3e 100644 --- a/src/include/86box/m_pcjr.h +++ b/src/include/86box/m_pcjr.h @@ -36,7 +36,7 @@ typedef struct pcjr_s uint8_t *b8000; int linepos; int displine; - int sc; + int scanline; int vc; int dispon; int cursorvisible; // Is the cursor visible on the current scanline? @@ -45,8 +45,8 @@ typedef struct pcjr_s int vsynctime; int fullchange; int vadj; - uint16_t ma; - uint16_t maback; + uint16_t memaddr; + uint16_t memaddr_backup; uint64_t dispontime; uint64_t dispofftime; pc_timer_t timer; diff --git a/src/include/86box/m_tandy.h b/src/include/86box/m_tandy.h index 3bafafd46..392c9b8a5 100644 --- a/src/include/86box/m_tandy.h +++ b/src/include/86box/m_tandy.h @@ -38,7 +38,7 @@ typedef struct t1kvid_t { int linepos; int displine; - int sc; + int scanline; int vc; int dispon; int cursorvisible; @@ -47,8 +47,8 @@ typedef struct t1kvid_t { int fullchange; int vsynctime; int vadj; - uint16_t ma; - uint16_t maback; + uint16_t memaddr; + uint16_t memaddr_backup; uint64_t dispontime; uint64_t dispofftime; diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 92960f912..9d19d916c 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -80,7 +80,7 @@ typedef struct ibm8514_t { uint32_t vram_mask; uint32_t pallook[512]; uint32_t bios_addr; - uint32_t ma_latch; + uint32_t memaddr_latch; PALETTE vgapal; uint8_t hwcursor_oddeven; @@ -220,8 +220,8 @@ typedef struct ibm8514_t { int lastline_draw; int displine; int fullchange; - uint32_t ma; - uint32_t maback; + uint32_t memaddr; + uint32_t memaddr_backup; uint8_t *vram; uint8_t *changedvram; @@ -236,7 +236,7 @@ typedef struct ibm8514_t { int hdisp; int hdisp2; int hdisped; - int sc; + int scanline; int vsyncstart; int vsyncwidth; int vtotal; diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index add92c708..04616431e 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -87,7 +87,7 @@ typedef struct cga_t { int fontbase; int linepos; int displine; - int sc; + int scanline; int vc; int cgadispon; int cursorvisible; // Determines if the cursor is visible FOR THE CURRENT SCANLINE. @@ -95,8 +95,8 @@ typedef struct cga_t { int cgablink; int vsynctime; int vadj; - uint16_t ma; - uint16_t maback; + uint16_t memaddr; + uint16_t memaddr_backup; int oddeven; uint64_t dispontime; diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 19461ba2b..6c88d50e6 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -73,7 +73,7 @@ typedef struct ega_t { int oddeven_chain; int vc; int real_vc; - int sc; + int scanline; int dispon; int hdisp_on; int cursoron; @@ -119,10 +119,10 @@ typedef struct ega_t { uint32_t charseta; uint32_t charsetb; - uint32_t ma_latch; - uint32_t ma; - uint32_t maback; - uint32_t ca; + uint32_t memaddr_latch; + uint32_t memaddr; + uint32_t memaddr_backup; + uint32_t cursoraddr; uint32_t vram_limit; uint32_t overscan_color; uint32_t cca; @@ -189,10 +189,10 @@ extern void ega_set_type(void *priv, uint32_t local); extern int firstline_draw; extern int lastline_draw; extern int displine; -extern int sc; +extern int scanline; -extern uint32_t ma; -extern uint32_t ca; +extern uint32_t memaddr; +extern uint32_t cursoraddr; extern int cursorvisible; extern int cursoron; extern int cgablink; diff --git a/src/include/86box/vid_ega_render_remap.h b/src/include/86box/vid_ega_render_remap.h index b01bb2b0e..1b0f7676c 100644 --- a/src/include/86box/vid_ega_render_remap.h +++ b/src/include/86box/vid_ega_render_remap.h @@ -33,9 +33,9 @@ } \ \ if (nr & VAR_ROW0_MA13) \ - out_addr = (out_addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); \ + out_addr = (out_addr & ~0x8000) | ((ega->scanline & 1) ? 0x8000 : 0); \ if (nr & VAR_ROW1_MA14) \ - out_addr = (out_addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); \ + out_addr = (out_addr & ~0x10000) | ((ega->scanline & 2) ? 0x10000 : 0); \ \ return out_addr; \ } diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index 46b0e16a7..c2d2770a9 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -43,9 +43,9 @@ typedef struct { int linepos; int displine; int vc; - int sc; - uint16_t ma; - uint16_t maback; + int scanline; + uint16_t memaddr; + uint16_t memaddr_backup; int cursorvisible; int cursoron; int dispon; diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index 15a1cabde..44123ce52 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -25,9 +25,9 @@ typedef struct mda_t { int linepos; int displine; int vc; - int sc; - uint16_t ma; - uint16_t maback; + int scanline; + uint16_t memaddr; + uint16_t memaddr_backup; int cursorvisible; int cursoron; int dispon; diff --git a/src/include/86box/vid_pgc.h b/src/include/86box/vid_pgc.h index d7906f2bc..dd6a45b98 100644 --- a/src/include/86box/vid_pgc.h +++ b/src/include/86box/vid_pgc.h @@ -120,8 +120,8 @@ typedef struct pgc { int cgablink; int vsynctime; int vadj; - uint16_t ma; - uint16_t maback; + uint16_t memaddr; + uint16_t memaddr_backup; int oddeven; uint64_t dispontime; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index aec33d95c..ad9170ad3 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -100,7 +100,7 @@ typedef struct svga_t { int dispon; int hdisp_on; int vc; - int sc; + int scanline; int linepos; int vslines; int linecountff; @@ -152,15 +152,15 @@ typedef struct svga_t { uint32_t charseta; uint32_t charsetb; uint32_t adv_flags; - uint32_t ma_latch; + uint32_t memaddr_latch; uint32_t ca_adj; - uint32_t ma; - uint32_t maback; + uint32_t memaddr; + uint32_t memaddr_backup; uint32_t write_bank; uint32_t read_bank; uint32_t extra_banks[2]; uint32_t banked_mask; - uint32_t ca; + uint32_t cursoraddr; uint32_t overscan_color; uint32_t *map8; uint32_t pallook[512]; diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index a96610d4a..097bb4509 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -23,10 +23,10 @@ extern int firstline_draw; extern int lastline_draw; extern int displine; -extern int sc; +extern int scanline; -extern uint32_t ma; -extern uint32_t ca; +extern uint32_t memaddr; +extern uint32_t cursoraddr; extern int cursorvisible; extern int cursoron; extern int cgablink; diff --git a/src/include/86box/vid_svga_render_remap.h b/src/include/86box/vid_svga_render_remap.h index ff9151c3c..d6c9fa5a6 100644 --- a/src/include/86box/vid_svga_render_remap.h +++ b/src/include/86box/vid_svga_render_remap.h @@ -47,9 +47,9 @@ } \ \ if (nr & VAR_ROW0_MA13) \ - out_addr = (out_addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); \ + out_addr = (out_addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0); \ if (nr & VAR_ROW1_MA14) \ - out_addr = (out_addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); \ + out_addr = (out_addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0); \ \ return out_addr; \ } diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index b2001dba9..e72c7af40 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -127,7 +127,7 @@ typedef struct xga_t { int dispon; int h_disp_on; int vc; - int sc; + int scanline; int linepos; int oddeven; int firstline; @@ -160,12 +160,12 @@ typedef struct xga_t { uint32_t hwc_color0; uint32_t hwc_color1; uint32_t disp_start_addr; - uint32_t ma_latch; + uint32_t memaddr_latch; uint32_t vram_size; uint32_t vram_mask; uint32_t rom_addr; - uint32_t ma; - uint32_t maback; + uint32_t memaddr; + uint32_t memaddr_backup; uint32_t read_bank; uint32_t write_bank; uint32_t px_map_base; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 43800a8bc..0c39c2176 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -113,7 +113,7 @@ typedef struct amsvid_t { int fontbase; /* 1512/200 */ int linepos; int displine; - int sc; + int scanline; int vc; int cgadispon; int cursorvisible; @@ -122,8 +122,8 @@ typedef struct amsvid_t { int vsynctime; int fullchange; int vadj; - uint16_t ma; - uint16_t maback; + uint16_t memaddr; + uint16_t memaddr_backup; int dispon; int blink; uint64_t dispontime; /* 1512/1640 */ @@ -339,7 +339,7 @@ static void vid_poll_1512(void *priv) { amsvid_t *vid = (amsvid_t *) priv; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -353,13 +353,13 @@ vid_poll_1512(void *priv) uint16_t dat4; int cols[4]; int col; - int oldsc; + int scanline_old; if (!vid->linepos) { timer_advance_u64(&vid->timer, vid->dispofftime); vid->stat |= 1; vid->linepos = 1; - oldsc = vid->sc; + scanline_old = vid->scanline; if (vid->dispon) { if (vid->displine < vid->firstline) { vid->firstline = vid->displine; @@ -385,9 +385,9 @@ vid_poll_1512(void *priv) } if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) { for (x = 0; x < 80; x++) { - chr = vid->vram[(vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); + chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; + attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; + drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron); if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -399,20 +399,20 @@ vid_poll_1512(void *priv) } if (drawcursor) { for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } } else { for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } - vid->ma++; + vid->memaddr++; } } else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) { for (x = 0; x < 40; x++) { - chr = vid->vram[(vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); + chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; + attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; + drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron); if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; @@ -422,14 +422,14 @@ vid_poll_1512(void *priv) cols[1] = (attr & 15) + 16; cols[0] = (attr >> 4) + 16; } - vid->ma++; + vid->memaddr++; if (drawcursor) { for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } } else { for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } } @@ -450,8 +450,8 @@ vid_poll_1512(void *priv) cols[3] = col | 6; } for (x = 0; x < 40; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; + dat = (vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1]; + vid->memaddr++; for (c = 0; c < 8; c++) { buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; dat <<= 2; @@ -459,13 +459,13 @@ vid_poll_1512(void *priv) } } else { for (x = 0; x < 40; x++) { - ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000); - dat = (vid->vram[ca] << 8) | vid->vram[ca + 1]; - dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001]; - dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001]; - dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001]; + cursoraddr = ((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000); + dat = (vid->vram[cursoraddr] << 8) | vid->vram[cursoraddr + 1]; + dat2 = (vid->vram[cursoraddr + 0x4000] << 8) | vid->vram[cursoraddr + 0x4001]; + dat3 = (vid->vram[cursoraddr + 0x8000] << 8) | vid->vram[cursoraddr + 0x8001]; + dat4 = (vid->vram[cursoraddr + 0xc000] << 8) | vid->vram[cursoraddr + 0xc001]; - vid->ma++; + vid->memaddr++; for (c = 0; c < 16; c++) { buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; dat <<= 1; @@ -494,7 +494,7 @@ vid_poll_1512(void *priv) video_process_8(x, vid->displine << 1); video_process_8(x, (vid->displine << 1) + 1); - vid->sc = oldsc; + vid->scanline = scanline_old; if (vid->vsynctime) vid->stat |= 8; vid->displine++; @@ -512,22 +512,22 @@ vid_poll_1512(void *priv) if (!vid->vsynctime) vid->stat &= ~8; } - if (vid->sc == (vid->crtc[11] & 31)) { + if (vid->scanline == (vid->crtc[11] & 31)) { vid->cursorvisible = 0; } if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; + vid->scanline++; + vid->scanline &= 31; + vid->memaddr= vid->memaddr_backup; vid->vadj--; if (!vid->vadj) { vid->dispon = 1; - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; + vid->memaddr= vid->memaddr_backup = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->scanline = 0; } - } else if (vid->sc == vid->crtc[9]) { - vid->maback = vid->ma; - vid->sc = 0; + } else if (vid->scanline == vid->crtc[9]) { + vid->memaddr_backup = vid->memaddr; + vid->scanline = 0; vid->vc++; vid->vc &= 127; @@ -602,11 +602,11 @@ vid_poll_1512(void *priv) vid->blink++; } } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; + vid->scanline++; + vid->scanline &= 31; + vid->memaddr= vid->memaddr_backup; } - if (vid->sc == (vid->crtc[10] & 31)) + if (vid->scanline == (vid->crtc[10] & 31)) vid->cursorvisible = 1; } } @@ -1210,11 +1210,11 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv) static void lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr, - uint8_t attr, int drawcursor, int blink, int sc, + uint8_t attr, int drawcursor, int blink, int scanline, int mode160, uint8_t control) { int c; - uint8_t bits = fontdat[chr + vid->cga.fontbase][sc]; + uint8_t bits = fontdat[chr + vid->cga.fontbase][scanline]; uint8_t bright = 0; uint16_t mask; @@ -1245,10 +1245,10 @@ lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr, static void lcd_draw_char_40(amsvid_t *vid, uint32_t *buffer, uint8_t chr, - uint8_t attr, int drawcursor, int blink, int sc, + uint8_t attr, int drawcursor, int blink, int scanline, uint8_t control) { - uint8_t bits = fontdat[chr + vid->cga.fontbase][sc]; + uint8_t bits = fontdat[chr + vid->cga.fontbase][scanline]; uint8_t mask = 0x80; if (attr & 8) /* bright */ @@ -1269,38 +1269,38 @@ static void lcdm_poll(amsvid_t *vid) { mda_t *mda = &vid->mda; - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; int drawcursor; int x; int oldvc; uint8_t chr; uint8_t attr; - int oldsc; + int scanline_old; int blink; if (!mda->linepos) { timer_advance_u64(&vid->timer, mda->dispofftime); mda->stat |= 1; mda->linepos = 1; - oldsc = mda->sc; + scanline_old = mda->scanline; if ((mda->crtc[8] & 3) == 3) - mda->sc = (mda->sc << 1) & 7; + mda->scanline = (mda->scanline << 1) & 7; if (mda->dispon) { if (mda->displine < mda->firstline) mda->firstline = mda->displine; mda->lastline = mda->displine; for (x = 0; x < mda->crtc[1]; x++) { - chr = mda->vram[(mda->ma << 1) & 0xfff]; - attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->cursorvisible && mda->cursoron); + chr = mda->vram[(mda->memaddr<< 1) & 0xfff]; + attr = mda->vram[((mda->memaddr<< 1) + 1) & 0xfff]; + drawcursor = ((mda->memaddr== cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl); - mda->ma++; + lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->scanline, 0, mda->ctrl); + mda->memaddr++; } } - mda->sc = oldsc; - if (mda->vc == mda->crtc[7] && !mda->sc) + mda->scanline = scanline_old; + if (mda->vc == mda->crtc[7] && !mda->scanline) mda->stat |= 8; mda->displine++; if (mda->displine >= 500) @@ -1315,22 +1315,22 @@ lcdm_poll(amsvid_t *vid) if (!mda->vsynctime) mda->stat &= ~8; } - if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[11] & 31) >> 1))) { mda->cursorvisible = 0; } if (mda->vadj) { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; + mda->scanline++; + mda->scanline &= 31; + mda->memaddr= mda->memaddr_backup; mda->vadj--; if (!mda->vadj) { mda->dispon = 1; - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - mda->sc = 0; + mda->memaddr= mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->scanline = 0; } - } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { - mda->maback = mda->ma; - mda->sc = 0; + } else if (mda->scanline == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->scanline == (mda->crtc[9] >> 1))) { + mda->memaddr_backup = mda->memaddr; + mda->scanline = 0; oldvc = mda->vc; mda->vc++; mda->vc &= 127; @@ -1342,7 +1342,7 @@ lcdm_poll(amsvid_t *vid) if (!mda->vadj) mda->dispon = 1; if (!mda->vadj) - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->memaddr= mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0; else @@ -1378,11 +1378,11 @@ lcdm_poll(amsvid_t *vid) mda->blink++; } } else { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; + mda->scanline++; + mda->scanline &= 31; + mda->memaddr= mda->memaddr_backup; } - if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) + if (mda->scanline == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[10] & 31) >> 1))) mda->cursorvisible = 1; } } @@ -1399,19 +1399,19 @@ lcdc_poll(amsvid_t *vid) uint8_t chr; uint8_t attr; uint16_t dat; - int oldsc; - uint16_t ca; + int scanline_old; + uint16_t cursoraddr; int blink; - ca = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + cursoraddr = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; if (!cga->linepos) { timer_advance_u64(&vid->timer, cga->dispofftime); cga->cgastat |= 1; cga->linepos = 1; - oldsc = cga->sc; + scanline_old = cga->scanline; if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3) - cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; + cga->scanline = ((cga->scanline << 1) + cga->oddeven) & 7; if (cga->cgadispon) { if (cga->displine < cga->firstline) { cga->firstline = cga->displine; @@ -1423,26 +1423,26 @@ lcdc_poll(amsvid_t *vid) for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { chr = cga->charbuffer[x << 1]; attr = cga->charbuffer[(x << 1) + 1]; - drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); + drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron); blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); - lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); - lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); - cga->ma++; + lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode & 0x40, cga->cgamode); + lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode & 0x40, cga->cgamode); + cga->memaddr++; } } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { - chr = cga->vram[(cga->ma << 1) & 0x3fff]; - attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; - drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); + chr = cga->vram[(cga->memaddr << 1) & 0x3fff]; + attr = cga->vram[((cga->memaddr << 1) + 1) & 0x3fff]; + drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron); blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); - lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); - lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); - cga->ma++; + lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode); + lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode); + cga->memaddr++; } } else { /* Graphics mode */ for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - cga->ma++; + dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) | cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1]; + cga->memaddr++; for (uint8_t c = 0; c < 16; c++) { buffer32->line[cga->displine << 1][(x << 4) + c] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c] = (dat & 0x8000) ? blue : green; dat <<= 1; @@ -1464,8 +1464,8 @@ lcdc_poll(amsvid_t *vid) else x = (cga->crtc[CGA_CRTC_HDISP] << 4); - cga->sc = oldsc; - if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->sc) + cga->scanline = scanline_old; + if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->scanline) cga->cgastat |= 8; cga->displine++; if (cga->displine >= 360) @@ -1478,24 +1478,24 @@ lcdc_poll(amsvid_t *vid) if (!cga->vsynctime) cga->cgastat &= ~8; } - if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { + if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { cga->cursorvisible = 0; } - if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) - cga->maback = cga->ma; + if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) + cga->memaddr_backup = cga->memaddr; if (cga->vadj) { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; + cga->scanline++; + cga->scanline &= 31; + cga->memaddr = cga->memaddr_backup; cga->vadj--; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - cga->sc = 0; + cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + cga->scanline = 0; } - } else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { - cga->maback = cga->ma; - cga->sc = 0; + } else if (cga->scanline == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { + cga->memaddr_backup = cga->memaddr; + cga->scanline = 0; oldvc = cga->vc; cga->vc++; cga->vc &= 127; @@ -1509,7 +1509,7 @@ lcdc_poll(amsvid_t *vid) if (!cga->vadj) cga->cgadispon = 1; if (!cga->vadj) - cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; if ((cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cga->cursoron = 0; else @@ -1573,17 +1573,17 @@ lcdc_poll(amsvid_t *vid) cga->oddeven ^= 1; } } else { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; + cga->scanline++; + cga->scanline &= 31; + cga->memaddr = cga->memaddr_backup; } if (cga->cgadispon) cga->cgastat &= ~1; - if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) + if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) cga->cursorvisible = 1; if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++) - cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; + cga->charbuffer[x] = cga->vram[((cga->memaddr << 1) + x) & 0x3fff]; } } } diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 02f22ed54..dcac57fe1 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -3383,7 +3383,7 @@ ibm8514_render_8bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3391,22 +3391,22 @@ ibm8514_render_8bpp(svga_t *svga) dev->lastline_draw = dev->displine; for (int x = 0; x <= dev->h_disp; x += 8) { - dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]); p[0] = dev->pallook[dat & dev->dac_mask & 0xff]; p[1] = dev->pallook[(dat >> 8) & dev->dac_mask & 0xff]; p[2] = dev->pallook[(dat >> 16) & dev->dac_mask & 0xff]; p[3] = dev->pallook[(dat >> 24) & dev->dac_mask & 0xff]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 4) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 4) & dev->vram_mask]); p[4] = dev->pallook[dat & dev->dac_mask & 0xff]; p[5] = dev->pallook[(dat >> 8) & dev->dac_mask & 0xff]; p[6] = dev->pallook[(dat >> 16) & dev->dac_mask & 0xff]; p[7] = dev->pallook[(dat >> 24) & dev->dac_mask & 0xff]; - dev->ma += 8; + dev->memaddr += 8; p += 8; } - dev->ma &= dev->vram_mask; + dev->memaddr &= dev->vram_mask; } } @@ -3421,7 +3421,7 @@ ibm8514_render_15bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3429,24 +3429,24 @@ ibm8514_render_15bpp(svga_t *svga) dev->lastline_draw = dev->displine; for (x = 0; x <= dev->h_disp; x += 8) { - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1)) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1)) & dev->vram_mask]); p[x] = video_15to32[dat & 0xffff]; p[x + 1] = video_15to32[dat >> 16]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 4) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 4) & dev->vram_mask]); p[x + 2] = video_15to32[dat & 0xffff]; p[x + 3] = video_15to32[dat >> 16]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 8) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 8) & dev->vram_mask]); p[x + 4] = video_15to32[dat & 0xffff]; p[x + 5] = video_15to32[dat >> 16]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 12) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 12) & dev->vram_mask]); p[x + 6] = video_15to32[dat & 0xffff]; p[x + 7] = video_15to32[dat >> 16]; } - dev->ma += (x << 1); - dev->ma &= dev->vram_mask; + dev->memaddr += (x << 1); + dev->memaddr &= dev->vram_mask; } } @@ -3461,7 +3461,7 @@ ibm8514_render_16bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3469,24 +3469,24 @@ ibm8514_render_16bpp(svga_t *svga) dev->lastline_draw = dev->displine; for (x = 0; x <= dev->h_disp; x += 8) { - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1)) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1)) & dev->vram_mask]); p[x] = video_16to32[dat & 0xffff]; p[x + 1] = video_16to32[dat >> 16]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 4) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 4) & dev->vram_mask]); p[x + 2] = video_16to32[dat & 0xffff]; p[x + 3] = video_16to32[dat >> 16]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 8) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 8) & dev->vram_mask]); p[x + 4] = video_16to32[dat & 0xffff]; p[x + 5] = video_16to32[dat >> 16]; - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 12) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 12) & dev->vram_mask]); p[x + 6] = video_16to32[dat & 0xffff]; p[x + 7] = video_16to32[dat >> 16]; } - dev->ma += (x << 1); - dev->ma &= dev->vram_mask; + dev->memaddr += (x << 1); + dev->memaddr &= dev->vram_mask; } } @@ -3500,7 +3500,7 @@ ibm8514_render_24bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3508,21 +3508,21 @@ ibm8514_render_24bpp(svga_t *svga) dev->lastline_draw = dev->displine; for (int x = 0; x <= dev->h_disp; x += 4) { - dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]); p[x] = dat & 0xffffff; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]); p[x + 1] = dat & 0xffffff; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]); p[x + 2] = dat & 0xffffff; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]); p[x + 3] = dat & 0xffffff; - dev->ma += 12; + dev->memaddr += 12; } - dev->ma &= dev->vram_mask; + dev->memaddr &= dev->vram_mask; } } @@ -3536,7 +3536,7 @@ ibm8514_render_BGR(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3544,21 +3544,21 @@ ibm8514_render_BGR(svga_t *svga) dev->lastline_draw = dev->displine; for (int x = 0; x <= dev->h_disp; x += 4) { - dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]); p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]); p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]); p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]); p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dev->ma += 12; + dev->memaddr += 12; } - dev->ma &= dev->vram_mask; + dev->memaddr &= dev->vram_mask; } } @@ -3573,7 +3573,7 @@ ibm8514_render_ABGR8888(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3581,11 +3581,11 @@ ibm8514_render_ABGR8888(svga_t *svga) dev->lastline_draw = dev->displine; for (x = 0; x <= dev->h_disp; x++) { - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]); *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); } - dev->ma += (x * 4); - dev->ma &= dev->vram_mask; + dev->memaddr += (x * 4); + dev->memaddr &= dev->vram_mask; } } @@ -3600,7 +3600,7 @@ ibm8514_render_32bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || dev->changedvram[(dev->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -3608,11 +3608,11 @@ ibm8514_render_32bpp(svga_t *svga) dev->lastline_draw = dev->displine; for (x = 0; x <= dev->h_disp; x++) { - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]); p[x] = dat & 0xffffff; } - dev->ma += (x * 4); - dev->ma &= dev->vram_mask; + dev->memaddr += (x * 4); + dev->memaddr &= dev->vram_mask; } } @@ -3681,7 +3681,7 @@ ibm8514_poll(void *priv) if (dev->dispon) { dev->hdisp_on = 1; - dev->ma &= dev->vram_mask; + dev->memaddr &= dev->vram_mask; if (dev->firstline == 2000) { dev->firstline = dev->displine; @@ -3689,7 +3689,7 @@ ibm8514_poll(void *priv) } if (dev->hwcursor_on) - dev->changedvram[dev->ma >> 12] = dev->changedvram[(dev->ma >> 12) + 1] = dev->interlace ? 3 : 2; + dev->changedvram[dev->memaddr >> 12] = dev->changedvram[(dev->memaddr >> 12) + 1] = dev->interlace ? 3 : 2; svga->render8514(svga); @@ -3726,18 +3726,18 @@ ibm8514_poll(void *priv) dev->linepos = 0; if (dev->dispon) { - if (dev->sc == dev->rowcount) { - dev->sc = 0; - dev->maback += (dev->rowoffset << 3); + if (dev->scanline == dev->rowcount) { + dev->scanline = 0; + dev->memaddr_backup += (dev->rowoffset << 3); if (dev->interlace) - dev->maback += (dev->rowoffset << 3); + dev->memaddr_backup += (dev->rowoffset << 3); - dev->maback &= dev->vram_mask; - dev->ma = dev->maback; + dev->memaddr_backup &= dev->vram_mask; + dev->memaddr = dev->memaddr_backup; } else { - dev->sc++; - dev->sc &= 0x1f; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 0x1f; + dev->memaddr = dev->memaddr_backup; } } @@ -3783,16 +3783,16 @@ ibm8514_poll(void *priv) svga->vslines = 0; if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = (dev->rowoffset << 1); + dev->memaddr = dev->memaddr_backup = (dev->rowoffset << 1); else - dev->ma = dev->maback = 0; + dev->memaddr = dev->memaddr_backup = 0; - dev->ma = (dev->ma << 2); - dev->maback = (dev->maback << 2); + dev->memaddr = (dev->memaddr << 2); + dev->memaddr_backup = (dev->memaddr_backup << 2); } if (dev->vc == dev->v_total) { dev->vc = 0; - dev->sc = (svga->crtc[0x8] & 0x1f); + dev->scanline = (svga->crtc[0x8] & 0x1f); dev->dispon = 1; dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 9a9be6ff6..9c87746c6 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -109,7 +109,7 @@ ati18800_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -223,7 +223,7 @@ ati18800_recalctimings(svga_t *svga) else { svga->render = svga_render_8bpp_highres; if (!svga->packed_4bpp) { - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; svga->rowoffset <<= 1; } } diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 156e95425..284abe78c 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -206,7 +206,7 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -416,10 +416,10 @@ ati28800_recalctimings(svga_t *svga) ((ati28800->regs[0xb9] & 2) << 1); if (ati28800->regs[0xa3] & 0x10) - svga->ma_latch |= 0x10000; + svga->memaddr_latch |= 0x10000; if (ati28800->regs[0xb0] & 0x40) - svga->ma_latch |= 0x20000; + svga->memaddr_latch |= 0x20000; if (ati28800->regs[0xb8] & 0x40) svga->clock *= 2; @@ -483,7 +483,7 @@ ati28800_recalctimings(svga_t *svga) else { svga->render = svga_render_8bpp_highres; if (!svga->packed_4bpp) { - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; svga->rowoffset <<= 1; } } @@ -496,7 +496,7 @@ ati28800_recalctimings(svga_t *svga) svga->hdisp >>= 1; svga->dots_per_clock >>= 1; svga->rowoffset <<= 1; - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; } break; default: diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 026634cf2..cb7abc13c 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -456,7 +456,7 @@ mach64_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); @@ -524,7 +524,7 @@ mach64_recalctimings(svga_t *svga) svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; svga->rowoffset = (mach64->crtc_off_pitch >> 22); svga->clock = (cpuclock * (double) (1ULL << 32)) / ics2595_getclock(svga->clock_gen); - svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; + svga->memaddr_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; svga->linedbl = svga->rowcount = 0; svga->split = 0xffffff; svga->vblankstart = svga->dispend; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index f7b5e0915..32a1c2b9e 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2461,7 +2461,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); @@ -2604,7 +2604,7 @@ ati_render_24bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -2613,38 +2613,38 @@ ati_render_24bpp(svga_t *svga) if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/ for (int x = 0; x <= dev->h_disp; x += 4) { - dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]); p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]); p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]); p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]); p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - dev->ma += 12; + dev->memaddr += 12; } } else { /*RGB, Red-(23:16), Green-(15:8), Blue-(7:0)*/ for (int x = 0; x <= dev->h_disp; x += 4) { - dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]); p[x] = dat & 0xffffff; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]); p[x + 1] = dat & 0xffffff; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]); p[x + 2] = dat & 0xffffff; - dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]); p[x + 3] = dat & 0xffffff; - dev->ma += 12; + dev->memaddr += 12; } } - dev->ma &= dev->vram_mask; + dev->memaddr &= dev->vram_mask; } } @@ -2660,7 +2660,7 @@ ati_render_32bpp(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) { + if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || dev->changedvram[(dev->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -2669,17 +2669,17 @@ ati_render_32bpp(svga_t *svga) if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/ for (x = 0; x <= dev->h_disp; x++) { - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]); *p++ = ((dat & 0x00ff0000) >> 16) | (dat & 0x0000ff00) | ((dat & 0x000000ff) << 16); } } else { /*RGB, Red-(31:24), Green-(23:16), Blue-(15:8)*/ for (x = 0; x <= dev->h_disp; x++) { - dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]); *p++ = ((dat & 0xffffff00) >> 8); } } - dev->ma += (x * 4); - dev->ma &= dev->vram_mask; + dev->memaddr += (x * 4); + dev->memaddr &= dev->vram_mask; } } @@ -2847,17 +2847,17 @@ mach_recalctimings(svga_t *svga) if (ATI_MACH32) { if (mach->regs[0xad] & 0x04) - svga->ma_latch |= 0x40000; + svga->memaddr_latch |= 0x40000; if (mach->regs[0xad] & 0x08) - svga->ma_latch |= 0x80000; + svga->memaddr_latch |= 0x80000; } if (mach->regs[0xa3] & 0x10) - svga->ma_latch |= 0x10000; + svga->memaddr_latch |= 0x10000; if (mach->regs[0xb0] & 0x40) - svga->ma_latch |= 0x20000; + svga->memaddr_latch |= 0x20000; if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; @@ -2886,7 +2886,7 @@ mach_recalctimings(svga_t *svga) mach_log("ON=%d, override=%d, gelo=%04x, gehi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, svga->hdisp); if (dev->on) { - dev->ma_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ + dev->memaddr_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ dev->interlace = !!(dev->disp_cntl & 0x10); dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; @@ -3085,7 +3085,7 @@ mach_recalctimings(svga_t *svga) else { svga->render = svga_render_8bpp_highres; if (!svga->packed_4bpp) { - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; svga->rowoffset <<= 1; } } @@ -3972,7 +3972,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x92ee: - mach_log("Write port 92ee, malatch=%08x.\n", svga->ma_latch); + mach_log("Write port 92ee, malatch=%08x.\n", svga->memaddr_latch); break; case 0x96ee: @@ -4227,7 +4227,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; default: - mach_log("Unknown or reserved write to %04x, val=%04x, len=%d, latch=%08x.\n", port, val, len, svga->ma_latch); + mach_log("Unknown or reserved write to %04x, val=%04x, len=%d, latch=%08x.\n", port, val, len, svga->memaddr_latch); break; } } diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c index a87890c75..fd5772b19 100644 --- a/src/video/vid_bochs_vbe.c +++ b/src/video/vid_bochs_vbe.c @@ -336,13 +336,13 @@ bochs_vbe_recalctimings(svga_t* svga) if (svga->bpp == 4) { svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; - svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); svga->fullchange = 3; } else { svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); - svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); svga->fullchange = 3; } @@ -470,11 +470,11 @@ bochs_vbe_outw(const uint16_t addr, const uint16_t val, void *priv) svga_t *svga = &dev->svga; if (svga->bpp == 4) { svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; - svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); } else { svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); - svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); } @@ -575,7 +575,7 @@ bochs_vbe_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 38dac61c7..5566537db 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -253,7 +253,7 @@ cga_recalctimings(cga_t *cga) static void cga_render(cga_t *cga, int line) { - uint16_t ca = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -289,7 +289,7 @@ cga_render(cga_t *cga, int line) attr = cga->charbuffer[(x << 1) + 1]; } else chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); + drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron); cols[1] = (attr & 15) + 16; if (cga->cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; @@ -300,24 +300,24 @@ cga_render(cga_t *cga, int line) if (drawcursor) { for (c = 0; c < 8; c++) { buffer32->line[line][(x << 3) + c + 8] - = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } } else { for (c = 0; c < 8; c++) { buffer32->line[line][(x << 3) + c + 8] - = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } - cga->ma++; + cga->memaddr++; } } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { - chr = cga->vram[(cga->ma << 1) & 0x3fff]; - attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; + chr = cga->vram[(cga->memaddr << 1) & 0x3fff]; + attr = cga->vram[((cga->memaddr << 1) + 1) & 0x3fff]; } else chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron); + drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron); cols[1] = (attr & 15) + 16; if (cga->cgamode & CGA_MODE_FLAG_BLINK) { cols[0] = ((attr >> 4) & 7) + 16; @@ -325,18 +325,18 @@ cga_render(cga_t *cga, int line) cols[1] = cols[0]; } else cols[0] = (attr >> 4) + 16; - cga->ma++; + cga->memaddr++; if (drawcursor) { for (c = 0; c < 8; c++) { buffer32->line[line][(x << 4) + (c << 1) + 8] = buffer32->line[line][(x << 4) + (c << 1) + 9] - = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } } else { for (c = 0; c < 8; c++) { buffer32->line[line][(x << 4) + (c << 1) + 8] = buffer32->line[line][(x << 4) + (c << 1) + 9] - = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } } @@ -358,11 +358,11 @@ cga_render(cga_t *cga, int line) } for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | - cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; + dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) | + cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1]; else dat = 0; - cga->ma++; + cga->memaddr++; for (c = 0; c < 8; c++) { buffer32->line[line][(x << 4) + (c << 1) + 8] = buffer32->line[line][(x << 4) + (c << 1) + 9] @@ -375,11 +375,11 @@ cga_render(cga_t *cga, int line) cols[1] = (cga->cgacol & 15) + 16; for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) { if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | - cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; + dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) | + cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1]; else dat = 0; - cga->ma++; + cga->memaddr++; for (c = 0; c < 16; c++) { buffer32->line[line][(x << 4) + c + 8] = cols[dat >> 15]; dat <<= 1; @@ -519,7 +519,7 @@ cga_poll(void *priv) { cga_t *cga = (cga_t *) priv; int x; - int oldsc; + int scanline_old; int oldvc; int xs_temp; int ys_temp; @@ -529,9 +529,9 @@ cga_poll(void *priv) timer_advance_u64(&cga->timer, cga->dispofftime); cga->cgastat |= 1; cga->linepos = 1; - oldsc = cga->sc; + scanline_old = cga->scanline; if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3) - cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; + cga->scanline = ((cga->scanline << 1) + cga->oddeven) & 7; if (cga->cgadispon) { if (cga->displine < cga->firstline) { cga->firstline = cga->displine; @@ -547,9 +547,9 @@ cga_poll(void *priv) cga_render(cga, cga->displine); break; case DOUBLE_SIMPLE: - old_ma = cga->ma; + old_ma = cga->memaddr; cga_render(cga, cga->displine << 1); - cga->ma = old_ma; + cga->memaddr = old_ma; cga_render(cga, (cga->displine << 1) + 1); break; } @@ -578,8 +578,8 @@ cga_poll(void *priv) break; } - cga->sc = oldsc; - if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->sc) + cga->scanline = scanline_old; + if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->scanline) cga->cgastat |= 8; cga->displine++; if (cga->displine >= 360) @@ -592,25 +592,25 @@ cga_poll(void *priv) if (!cga->vsynctime) cga->cgastat &= ~8; } - if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && - cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { + if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && + cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { cga->cursorvisible = 0; } - if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) - cga->maback = cga->ma; + if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) + cga->memaddr_backup = cga->memaddr; if (cga->vadj) { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; + cga->scanline++; + cga->scanline &= 31; + cga->memaddr = cga->memaddr_backup; cga->vadj--; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - cga->sc = 0; + cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + cga->scanline = 0; } - } else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { - cga->maback = cga->ma; - cga->sc = 0; + } else if (cga->scanline == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { + cga->memaddr_backup = cga->memaddr; + cga->scanline = 0; oldvc = cga->vc; cga->vc++; cga->vc &= 127; @@ -623,7 +623,7 @@ cga_poll(void *priv) cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!cga->vadj) { cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; } switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) { @@ -717,18 +717,18 @@ cga_poll(void *priv) cga->oddeven ^= 1; } } else { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; + cga->scanline++; + cga->scanline &= 31; + cga->memaddr = cga->memaddr_backup; } if (cga->cgadispon) cga->cgastat &= ~1; - if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && - cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) + if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && + cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) cga->cursorvisible = 1; if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++) - cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; + cga->charbuffer[x] = cga->vram[((cga->memaddr << 1) + x) & 0x3fff]; } } } diff --git a/src/video/vid_cga_colorplus.c b/src/video/vid_cga_colorplus.c index efa8ab3a7..af8fd6d99 100644 --- a/src/video/vid_cga_colorplus.c +++ b/src/video/vid_cga_colorplus.c @@ -130,7 +130,7 @@ colorplus_poll(void *priv) uint16_t dat1; int cols[4]; int col; - int oldsc; + int scanline_old; static const int cols16[16] = { 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x11, 0x13, 0x15, 0x17, @@ -149,9 +149,9 @@ colorplus_poll(void *priv) timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime); colorplus->cga.cgastat |= 1; colorplus->cga.linepos = 1; - oldsc = colorplus->cga.sc; + scanline_old = colorplus->cga.scanline; if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) - colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7; + colorplus->cga.scanline = ((colorplus->cga.scanline << 1) + colorplus->cga.oddeven) & 7; if (colorplus->cga.cgadispon) { if (colorplus->cga.displine < colorplus->cga.firstline) { colorplus->cga.firstline = colorplus->cga.displine; @@ -164,9 +164,9 @@ colorplus_poll(void *priv) } if (colorplus->control & COLORPLUS_320x200_MODE) { for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; x++) { - dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - colorplus->cga.ma++; + dat0 = (plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1]; + dat1 = (plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1]; + colorplus->cga.memaddr++; for (c = 0; c < 8; c++) { buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)]; dat0 <<= 2; @@ -190,9 +190,9 @@ colorplus_poll(void *priv) cols[3] = col | 6; } for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; x++) { - dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - colorplus->cga.ma++; + dat0 = (plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1]; + dat1 = (plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1]; + colorplus->cga.memaddr++; for (c = 0; c < 16; c++) { buffer32->line[colorplus->cga.displine][(x << 4) + c + 8] = cols[(dat0 >> 15) | ((dat1 >> 15) << 1)]; dat0 <<= 1; @@ -213,8 +213,8 @@ colorplus_poll(void *priv) else video_process_8(x, colorplus->cga.displine); - colorplus->cga.sc = oldsc; - if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC] && !colorplus->cga.sc) + colorplus->cga.scanline = scanline_old; + if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC] && !colorplus->cga.scanline) colorplus->cga.cgastat |= 8; colorplus->cga.displine++; if (colorplus->cga.displine >= 360) @@ -227,25 +227,25 @@ colorplus_poll(void *priv) if (!colorplus->cga.vsynctime) colorplus->cga.cgastat &= ~8; } - if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) - || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { + if (colorplus->cga.scanline == (colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) + || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.scanline == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { colorplus->cga.cursorvisible = 0; } - if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) - colorplus->cga.maback = colorplus->cga.ma; + if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.scanline == (colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) + colorplus->cga.memaddr_backup = colorplus->cga.memaddr; if (colorplus->cga.vadj) { - colorplus->cga.sc++; - colorplus->cga.sc &= 31; - colorplus->cga.ma = colorplus->cga.maback; + colorplus->cga.scanline++; + colorplus->cga.scanline &= 31; + colorplus->cga.memaddr = colorplus->cga.memaddr_backup; colorplus->cga.vadj--; if (!colorplus->cga.vadj) { colorplus->cga.cgadispon = 1; - colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - colorplus->cga.sc = 0; + colorplus->cga.memaddr = colorplus->cga.memaddr_backup = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + colorplus->cga.scanline = 0; } - } else if (colorplus->cga.sc == colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { - colorplus->cga.maback = colorplus->cga.ma; - colorplus->cga.sc = 0; + } else if (colorplus->cga.scanline == colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) { + colorplus->cga.memaddr_backup = colorplus->cga.memaddr; + colorplus->cga.scanline = 0; oldvc = colorplus->cga.vc; colorplus->cga.vc++; colorplus->cga.vc &= 127; @@ -259,7 +259,7 @@ colorplus_poll(void *priv) if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1; if (!colorplus->cga.vadj) - colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + colorplus->cga.memaddr = colorplus->cga.memaddr_backup = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; if ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) colorplus->cga.cursoron = 0; else @@ -312,17 +312,17 @@ colorplus_poll(void *priv) colorplus->cga.oddeven ^= 1; } } else { - colorplus->cga.sc++; - colorplus->cga.sc &= 31; - colorplus->cga.ma = colorplus->cga.maback; + colorplus->cga.scanline++; + colorplus->cga.scanline &= 31; + colorplus->cga.memaddr = colorplus->cga.memaddr_backup; } if (colorplus->cga.cgadispon) colorplus->cga.cgastat &= ~1; - if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) + if (colorplus->cga.scanline == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.scanline == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) colorplus->cga.cursorvisible = 1; if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (colorplus->cga.crtc[CGA_CRTC_HDISP] << 1); x++) - colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.ma << 1) + x) & 0x3fff]; + colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.memaddr << 1) + x) & 0x3fff]; } } } diff --git a/src/video/vid_cga_compaq.c b/src/video/vid_cga_compaq.c index c36af38b1..1e21d63c1 100644 --- a/src/video/vid_cga_compaq.c +++ b/src/video/vid_cga_compaq.c @@ -82,7 +82,7 @@ static void compaq_cga_poll(void *priv) { cga_t *dev = (cga_t *) priv; - uint16_t ca = (dev->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (dev->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (dev->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (dev->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -93,7 +93,7 @@ compaq_cga_poll(void *priv) uint8_t attr; uint8_t border; uint8_t cols[4]; - int oldsc; + int scanline_old; int underline = 0; int blink = 0; @@ -112,9 +112,9 @@ compaq_cga_poll(void *priv) timer_advance_u64(&dev->timer, dev->dispofftime); dev->cgastat |= 1; dev->linepos = 1; - oldsc = dev->sc; + scanline_old = dev->scanline; if ((dev->crtc[CGA_CRTC_INTERLACE] & 3) == 3) - dev->sc = ((dev->sc << 1) + dev->oddeven) & 7; + dev->scanline = ((dev->scanline << 1) + dev->oddeven) & 7; if (dev->cgadispon) { if (dev->displine < dev->firstline) { dev->firstline = dev->displine; @@ -137,7 +137,7 @@ compaq_cga_poll(void *priv) for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) { chr = dev->charbuffer[x << 1]; attr = dev->charbuffer[(x << 1) + 1]; - drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); + drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron); if (vflags) { underline = 0; @@ -148,7 +148,7 @@ compaq_cga_poll(void *priv) cols[0] = mdaattr[attr][blink][0]; cols[1] = mdaattr[attr][blink][1]; - if ((dev->sc == 12) && ((attr & 7) == 1)) + if ((dev->scanline == 12) && ((attr & 7) == 1)) underline = 1; } else if (dev->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; @@ -172,19 +172,19 @@ compaq_cga_poll(void *priv) } else if (drawcursor) { for (c = 0; c < 8; c++) buffer32->line[dev->displine][(x << 3) + c + 8] = - cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) buffer32->line[dev->displine][(x << 3) + c + 8] = - cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0]; } - dev->ma++; + dev->memaddr++; } } else { for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) { - chr = dev->vram[(dev->ma << 1) & 0x3fff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; - drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); + chr = dev->vram[(dev->memaddr << 1) & 0x3fff]; + attr = dev->vram[((dev->memaddr << 1) + 1) & 0x3fff]; + drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron); if (vflags) { underline = 0; @@ -194,7 +194,7 @@ compaq_cga_poll(void *priv) if (vflags && (dev->cgamode & 0x80)) { cols[0] = mdaattr[attr][blink][0]; cols[1] = mdaattr[attr][blink][1]; - if (dev->sc == 12 && (attr & 7) == 1) + if (dev->scanline == 12 && (attr & 7) == 1) underline = 1; } else if (dev->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; @@ -211,7 +211,7 @@ compaq_cga_poll(void *priv) cols[1] = (attr & 15) + 16; cols[0] = (attr >> 4) + 16; } - dev->ma++; + dev->memaddr++; if (vflags && underline) { for (c = 0; c < 8; c++) @@ -221,12 +221,12 @@ compaq_cga_poll(void *priv) for (c = 0; c < 8; c++) buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] = buffer32->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] = buffer32->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdatm[chr + dev->fontbase][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0]; } } } @@ -257,8 +257,8 @@ compaq_cga_poll(void *priv) } else video_process_8(x, dev->displine); - dev->sc = oldsc; - if (dev->vc == dev->crtc[CGA_CRTC_VSYNC] && !dev->sc) + dev->scanline = scanline_old; + if (dev->vc == dev->crtc[CGA_CRTC_VSYNC] && !dev->scanline) dev->cgastat |= 8; dev->displine++; if (dev->displine >= 500) @@ -272,24 +272,24 @@ compaq_cga_poll(void *priv) dev->cgastat &= ~8; } - if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { dev->cursorvisible = 0; } - if ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1)) - dev->maback = dev->ma; + if ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1)) + dev->memaddr_backup = dev->memaddr; if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; dev->vadj--; if (!dev->vadj) { dev->cgadispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->scanline = 0; } - } else if (dev->sc == dev->crtc[9]) { - dev->maback = dev->ma; - dev->sc = 0; + } else if (dev->scanline == dev->crtc[9]) { + dev->memaddr_backup = dev->memaddr; + dev->scanline = 0; oldvc = dev->vc; dev->vc++; dev->vc &= 127; @@ -305,7 +305,7 @@ compaq_cga_poll(void *priv) dev->cgadispon = 1; if (!dev->vadj) - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; if ((dev->crtc[10] & 0x60) == 0x20) dev->cursoron = 0; @@ -382,20 +382,20 @@ compaq_cga_poll(void *priv) dev->oddeven ^= 1; } } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; } if (dev->cgadispon) dev->cgastat &= ~1; - if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1))) dev->cursorvisible = 1; if (dev->cgadispon && (dev->cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (dev->crtc[CGA_CRTC_HDISP] << 1); x++) - dev->charbuffer[x] = dev->vram[((dev->ma << 1) + x) & 0x3fff]; + dev->charbuffer[x] = dev->vram[((dev->memaddr << 1) + x) & 0x3fff]; } } } diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index feb9a12c8..e316c6269 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -256,9 +256,9 @@ compaq_plasma_poll(void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; uint8_t chr; uint8_t attr; - uint8_t sc; - uint16_t ma = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; - uint16_t ca = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; + uint8_t scanline; + uint16_t memaddr = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t cursoraddr = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; uint16_t addr; int drawcursor; int cursorline; @@ -298,14 +298,14 @@ compaq_plasma_poll(void *priv) /* 80-col */ if (self->cga.cgamode & 0x01) { - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; - ma += (self->cga.displine >> 4) * 80; + scanline = self->cga.displine & 0x0f; + addr = ((memaddr & ~1) + (self->cga.displine >> 4) * 80) << 1; + memaddr += (self->cga.displine >> 4) * 80; if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cursorline = 0; else - cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); + cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= scanline) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= scanline); /* for each text column */ for (x = 0; x < 80; x++) { @@ -321,7 +321,7 @@ compaq_plasma_poll(void *priv) } uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ underline = ((attr & 0x07) == 0x01); underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); @@ -348,12 +348,12 @@ compaq_plasma_poll(void *priv) } /* character address */ - uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + uint16_t chr_addr = ((chr * 16) + scanline) & 0x0fff; if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { + if (underline && (scanline == 7)) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; @@ -378,19 +378,19 @@ compaq_plasma_poll(void *priv) } } } - ma++; + memaddr++; } } /* 40-col */ else if (!(self->cga.cgamode & 0x02)) { - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; - ma += (self->cga.displine >> 4) * 40; + scanline = self->cga.displine & 0x0f; + addr = ((memaddr & ~1) + (self->cga.displine >> 4) * 40) << 1; + memaddr += (self->cga.displine >> 4) * 40; if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) cursorline = 0; else - cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= sc); + cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= scanline) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1) >= scanline); for (x = 0; x < 40; x++) { /* video output enabled */ @@ -405,7 +405,7 @@ compaq_plasma_poll(void *priv) } uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ underline = ((attr & 0x07) == 0x01); underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); @@ -432,12 +432,12 @@ compaq_plasma_poll(void *priv) } /* character address */ - uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + uint16_t chr_addr = ((chr * 16) + scanline) & 0x0fff; if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { + if (underline && (scanline == 7)) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; @@ -463,15 +463,15 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); } } - ma++; + memaddr++; } } else { if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { /* 640x400 mode */ if (self->port_23c6 & 0x01) /* 640*400 */ { - addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((memaddr & ~1) << 1); } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((memaddr & ~1) << 1); } for (uint8_t x = 0; x < 80; x++) { dat = self->cga.vram[addr & 0x7fff]; @@ -486,7 +486,7 @@ compaq_plasma_poll(void *priv) } } } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((memaddr & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { dat = self->cga.vram[addr & 0x7fff]; addr++; diff --git a/src/video/vid_cga_ncr.c b/src/video/vid_cga_ncr.c index 2eb94220a..eb4474a40 100644 --- a/src/video/vid_cga_ncr.c +++ b/src/video/vid_cga_ncr.c @@ -148,7 +148,7 @@ nga_poll(void *priv) { nga_t *nga = (nga_t *) priv; /* set cursor position in memory */ - uint16_t ca = (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -161,7 +161,7 @@ nga_poll(void *priv) uint16_t dat2; int cols[4]; int col; - int oldsc; + int scanline_old; /* graphic mode and not high-res modes */ if ((nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) && !(nga->cga.cgamode & 0x40)) { @@ -174,10 +174,10 @@ nga_poll(void *priv) timer_advance_u64(&nga->cga.timer, nga->cga.dispofftime); nga->cga.cgastat |= 1; nga->cga.linepos = 1; - oldsc = nga->cga.sc; + scanline_old = nga->cga.scanline; /* if interlaced */ if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) - nga->cga.sc = ((nga->cga.sc << 1) + nga->cga.oddeven) & 7; + nga->cga.scanline = ((nga->cga.scanline << 1) + nga->cga.oddeven) & 7; if (nga->cga.cgadispon) { if (nga->cga.displine < nga->cga.firstline) { nga->cga.firstline = nga->cga.displine; @@ -197,7 +197,7 @@ nga_poll(void *priv) } else chr = attr = 0; /* check if cursor has to be drawn */ - drawcursor = ((nga->cga.ma == ca) && nga->cga.cursorvisible && nga->cga.cursoron); + drawcursor = ((nga->cga.memaddr == cursoraddr) && nga->cga.cursorvisible && nga->cga.cursoron); /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ @@ -214,13 +214,13 @@ nga_poll(void *priv) } if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } - nga->cga.ma++; + nga->cga.memaddr++; } } /* 40-col */ @@ -228,12 +228,12 @@ nga_poll(void *priv) /* for each text column */ for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) { if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { - chr = nga->cga.vram[((nga->cga.ma << 1) & 0x3fff) + nga->base]; - attr = nga->cga.vram[(((nga->cga.ma << 1) + 1) & 0x3fff) + nga->base]; + chr = nga->cga.vram[((nga->cga.memaddr << 1) & 0x3fff) + nga->base]; + attr = nga->cga.vram[(((nga->cga.memaddr << 1) + 1) & 0x3fff) + nga->base]; } else { chr = attr = 0; } - drawcursor = ((nga->cga.ma == ca) && nga->cga.cursorvisible && nga->cga.cursoron); + drawcursor = ((nga->cga.memaddr == cursoraddr) && nga->cga.cursorvisible && nga->cga.cursoron); /* set foreground */ cols[1] = (attr & 15) + 16; /* blink active */ @@ -250,13 +250,13 @@ nga_poll(void *priv) if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } - nga->cga.ma++; + nga->cga.memaddr++; } } else { /* high res modes */ @@ -270,7 +270,7 @@ nga_poll(void *priv) * 0bc000-0bdf3f even scans (1,5,...) * 0be000-0bff3f odd scans (3,7,...) */ - dat2 = ((nga->cga.sc & 1) * 0x2000) | (nga->lineff * 0x4000); + dat2 = ((nga->cga.scanline & 1) * 0x2000) | (nga->lineff * 0x4000); cols[0] = 0; cols[1] = 15 + 16; /* 640x400x4 mode */ @@ -297,10 +297,10 @@ nga_poll(void *priv) * 0a8000-0abf3f even scans (2,6,...) * 0ac000-0aff3f odd scans (3,7,...) */ - dat2 = (nga->cga.sc & 1) * 0x4000; + dat2 = (nga->cga.scanline & 1) * 0x4000; } } else { - dat2 = (nga->cga.sc & 1) * 0x2000; + dat2 = (nga->cga.scanline & 1) * 0x2000; cols[0] = 0; cols[1] = (nga->cga.cgacol & 15) + 16; } @@ -312,7 +312,7 @@ nga_poll(void *priv) /* 640x400x2 */ if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) { /* read two bytes at a time */ - dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2 + 1]; + dat = (nga->cga.vram[((nga->cga.memaddr << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.memaddr << 1) & 0x1fff) + dat2 + 1]; /* each pixel is represented by one bit, so draw 16 pixels at a time */ /* crtc[1] is 40 column, so 40x16=640 pixels */ for (c = 0; c < 16; c++) { @@ -322,13 +322,13 @@ nga_poll(void *priv) /* 640x400x4 */ } else { /* lines 2,3,6,7,etc. */ - if (nga->cga.sc & 2) + if (nga->cga.scanline & 2) /* read two bytes at a time */ - dat = (nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1]; + dat = (nga->vram_64k[((nga->cga.memaddr << 1) & 0x7fff) + dat2] << 8) | nga->vram_64k[((nga->cga.memaddr << 1) & 0x7fff) + dat2 + 1]; /* lines 0,1,4,5,etc. */ else /* read two bytes at a time */ - dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1]; + dat = (nga->cga.vram[((nga->cga.memaddr << 1) & 0x7fff) + dat2] << 8) | nga->cga.vram[((nga->cga.memaddr << 1) & 0x7fff) + dat2 + 1]; /* each pixel is represented by two bits, so draw 8 pixels at a time */ /* crtc[1] is 80 column, so 80x8=640 pixels */ for (c = 0; c < 8; c++) { @@ -339,7 +339,7 @@ nga_poll(void *priv) } else { dat = 0; } - nga->cga.ma++; + nga->cga.memaddr++; } } } else { @@ -364,9 +364,9 @@ nga_poll(void *priv) video_process_8(x, nga->cga.displine); - nga->cga.sc = oldsc; + nga->cga.scanline = scanline_old; /* vertical sync */ - if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VSYNC] && !nga->cga.sc) + if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VSYNC] && !nga->cga.scanline) nga->cga.cgastat |= 8; nga->cga.displine++; if (nga->cga.displine >= 720) @@ -381,7 +381,7 @@ nga_poll(void *priv) /* text mode or 640x400x2 */ if (nga->lineff && !((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && (nga->cga.cgamode & 0x40))) { - nga->cga.ma = nga->cga.maback; + nga->cga.memaddr = nga->cga.memaddr_backup; /* 640x400x4 */ } else { if (nga->cga.vsynctime) { @@ -390,29 +390,29 @@ nga_poll(void *priv) nga->cga.cgastat &= ~8; } /* cursor stop scanline */ - if (nga->cga.sc == (nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { + if (nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == ((nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { nga->cga.cursorvisible = 0; } /* interlaced and max scanline per char reached */ - if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) - nga->cga.maback = nga->cga.ma; + if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) + nga->cga.memaddr_backup = nga->cga.memaddr; if (nga->cga.vadj) { - nga->cga.sc++; - nga->cga.sc &= 31; - nga->cga.ma = nga->cga.maback; + nga->cga.scanline++; + nga->cga.scanline &= 31; + nga->cga.memaddr = nga->cga.memaddr_backup; nga->cga.vadj--; if (!nga->cga.vadj) { nga->cga.cgadispon = 1; /* change start of displayed page (crtc 12-13) */ - nga->cga.ma = nga->cga.maback = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; - nga->cga.sc = 0; + nga->cga.memaddr = nga->cga.memaddr_backup = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + nga->cga.scanline = 0; } /* nga specific */ /* end of character line reached */ - } else if (nga->cga.sc == nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { - nga->cga.maback = nga->cga.ma; - nga->cga.sc = 0; + } else if (nga->cga.scanline == nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { + nga->cga.memaddr_backup = nga->cga.memaddr; + nga->cga.scanline = 0; oldvc = nga->cga.vc; nga->cga.vc++; nga->cga.vc &= 127; @@ -429,7 +429,7 @@ nga_poll(void *priv) if (!nga->cga.vadj) { nga->cga.cgadispon = 1; /* change start of displayed page (crtc 12-13) */ - nga->cga.ma = nga->cga.maback = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + nga->cga.memaddr = nga->cga.memaddr_backup = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; } /* cursor start */ switch (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) { @@ -514,23 +514,23 @@ nga_poll(void *priv) nga->cga.oddeven ^= 1; } } else { - nga->cga.sc++; - nga->cga.sc &= 31; - nga->cga.ma = nga->cga.maback; + nga->cga.scanline++; + nga->cga.scanline &= 31; + nga->cga.memaddr = nga->cga.memaddr_backup; } if (nga->cga.cgadispon) nga->cga.cgastat &= ~1; /* enable cursor if its scanline was reached */ - if (nga->cga.sc == (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) + if (nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == ((nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) nga->cga.cursorvisible = 1; } /* 80-columns */ if (nga->cga.cgadispon && (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { /* for each character per line */ for (x = 0; x < (nga->cga.crtc[CGA_CRTC_HDISP] << 1); x++) - nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.ma << 1) + x) & 0x3fff) + nga->base]; + nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.memaddr << 1) + x) & 0x3fff) + nga->base]; } } } diff --git a/src/video/vid_cga_olivetti.c b/src/video/vid_cga_olivetti.c index 71073d464..8be40ee2e 100644 --- a/src/video/vid_cga_olivetti.c +++ b/src/video/vid_cga_olivetti.c @@ -201,7 +201,7 @@ void ogc_poll(void *priv) { ogc_t *ogc = (ogc_t *) priv; - uint16_t ca = (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -213,7 +213,7 @@ ogc_poll(void *priv) uint16_t dat; uint16_t dat2; int cols[4]; - int oldsc; + int scanline_old; int blink = 0; int underline = 0; @@ -230,9 +230,9 @@ ogc_poll(void *priv) timer_advance_u64(&ogc->cga.timer, ogc->cga.dispofftime); ogc->cga.cgastat |= 1; ogc->cga.linepos = 1; - oldsc = ogc->cga.sc; + scanline_old = ogc->cga.scanline; if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3) - ogc->cga.sc = ((ogc->cga.sc << 1) + ogc->cga.oddeven) & 7; + ogc->cga.scanline = ((ogc->cga.scanline << 1) + ogc->cga.oddeven) & 7; if (ogc->cga.cgadispon) { if (ogc->cga.displine < ogc->cga.firstline) { ogc->cga.firstline = ogc->cga.displine; @@ -252,7 +252,7 @@ ogc_poll(void *priv) } else chr = attr = 0; /* check if cursor has to be drawn */ - drawcursor = ((ogc->cga.ma == ca) && ogc->cga.cursorvisible && ogc->cga.cursoron); + drawcursor = ((ogc->cga.memaddr == cursoraddr) && ogc->cga.cursorvisible && ogc->cga.cursoron); /* check if character underline mode should be set */ underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); if (underline) { @@ -277,31 +277,31 @@ ogc_poll(void *priv) blink = (attr & 0x80) * 8 + 7 + 16; } /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (ogc->cga.sc == 7)) { + if (underline && (ogc->cga.scanline == 7)) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } - ogc->cga.ma++; + ogc->cga.memaddr++; } } /* 40-col */ else if (!(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) { for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) { if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { - chr = ogc->cga.vram[((ogc->cga.ma << 1) & 0x3fff) + ogc->base]; - attr = ogc->cga.vram[(((ogc->cga.ma << 1) + 1) & 0x3fff) + ogc->base]; + chr = ogc->cga.vram[((ogc->cga.memaddr << 1) & 0x3fff) + ogc->base]; + attr = ogc->cga.vram[(((ogc->cga.memaddr << 1) + 1) & 0x3fff) + ogc->base]; } else { chr = attr = 0; } - drawcursor = ((ogc->cga.ma == ca) && ogc->cga.cursorvisible && ogc->cga.cursoron); + drawcursor = ((ogc->cga.memaddr == cursoraddr) && ogc->cga.cursorvisible && ogc->cga.cursoron); /* check if character underline mode should be set */ underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); if (underline) { @@ -326,28 +326,28 @@ ogc_poll(void *priv) } /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (ogc->cga.sc == 7)) { + if (underline && (ogc->cga.scanline == 7)) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } - ogc->cga.ma++; + ogc->cga.memaddr++; } } else { /* 640x400 mode */ if (ogc->ctrl_3de & 1) { - dat2 = ((ogc->cga.sc & 1) * 0x4000) | (ogc->lineff * 0x2000); + dat2 = ((ogc->cga.scanline & 1) * 0x4000) | (ogc->lineff * 0x2000); cols[0] = 0; cols[1] = 15 + 16; } else { - dat2 = (ogc->cga.sc & 1) * 0x2000; + dat2 = (ogc->cga.scanline & 1) * 0x2000; cols[0] = 0; cols[1] = (ogc->cga.cgacol & 15) + 16; } @@ -355,11 +355,11 @@ ogc_poll(void *priv) for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) { /* video out */ if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { - dat = (ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2 + 1]; + dat = (ogc->cga.vram[((ogc->cga.memaddr << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.memaddr << 1) & 0x1fff) + dat2 + 1]; } else { dat = 0; } - ogc->cga.ma++; + ogc->cga.memaddr++; for (c = 0; c < 16; c++) { buffer32->line[ogc->cga.displine][(x << 4) + c + 8] = cols[dat >> 15]; @@ -384,8 +384,8 @@ ogc_poll(void *priv) video_process_8(x, ogc->cga.displine); - ogc->cga.sc = oldsc; - if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC] && !ogc->cga.sc) + ogc->cga.scanline = scanline_old; + if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC] && !ogc->cga.scanline) ogc->cga.cgastat |= 8; ogc->cga.displine++; if (ogc->cga.displine >= 720) @@ -398,32 +398,32 @@ ogc_poll(void *priv) /* ogc specific */ ogc->lineff ^= 1; if (ogc->lineff) { - ogc->cga.ma = ogc->cga.maback; + ogc->cga.memaddr = ogc->cga.memaddr_backup; } else { if (ogc->cga.vsynctime) { ogc->cga.vsynctime--; if (!ogc->cga.vsynctime) ogc->cga.cgastat &= ~8; } - if (ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { + if (ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == ((ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) { ogc->cga.cursorvisible = 0; } - if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) - ogc->cga.maback = ogc->cga.ma; + if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1)) + ogc->cga.memaddr_backup = ogc->cga.memaddr; if (ogc->cga.vadj) { - ogc->cga.sc++; - ogc->cga.sc &= 31; - ogc->cga.ma = ogc->cga.maback; + ogc->cga.scanline++; + ogc->cga.scanline &= 31; + ogc->cga.memaddr = ogc->cga.memaddr_backup; ogc->cga.vadj--; if (!ogc->cga.vadj) { ogc->cga.cgadispon = 1; - ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - ogc->cga.sc = 0; + ogc->cga.memaddr = ogc->cga.memaddr_backup = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + ogc->cga.scanline = 0; } // may cause problems with composite - } else if (ogc->cga.sc == ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { - ogc->cga.maback = ogc->cga.ma; - ogc->cga.sc = 0; + } else if (ogc->cga.scanline == ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { + ogc->cga.memaddr_backup = ogc->cga.memaddr; + ogc->cga.scanline = 0; oldvc = ogc->cga.vc; ogc->cga.vc++; ogc->cga.vc &= 127; @@ -436,7 +436,7 @@ ogc_poll(void *priv) ogc->cga.vadj = ogc->cga.crtc[CGA_CRTC_VTOTAL_ADJUST]; if (!ogc->cga.vadj) { ogc->cga.cgadispon = 1; - ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + ogc->cga.memaddr = ogc->cga.memaddr_backup = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; } switch (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) { case 0x20: @@ -516,21 +516,21 @@ ogc_poll(void *priv) ogc->cga.oddeven ^= 1; } } else { - ogc->cga.sc++; - ogc->cga.sc &= 31; - ogc->cga.ma = ogc->cga.maback; + ogc->cga.scanline++; + ogc->cga.scanline &= 31; + ogc->cga.memaddr = ogc->cga.memaddr_backup; } if (ogc->cga.cgadispon) ogc->cga.cgastat &= ~1; - if (ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) + if (ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == ((ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1))) ogc->cga.cursorvisible = 1; } /* 80-columns */ if (ogc->cga.cgadispon && (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) { for (x = 0; x < (ogc->cga.crtc[CGA_CRTC_HDISP] << 1); x++) - ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.ma << 1) + x) & 0x3fff) + ogc->base]; + ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.memaddr << 1) + x) & 0x3fff) + ogc->base]; } } } diff --git a/src/video/vid_cga_toshiba_t1000.c b/src/video/vid_cga_toshiba_t1000.c index 8811309a0..2fd382272 100644 --- a/src/video/vid_cga_toshiba_t1000.c +++ b/src/video/vid_cga_toshiba_t1000.c @@ -245,23 +245,23 @@ t1000_text_row80(t1000_t *t1000) int bold; int blink; uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + uint8_t scanline; + uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2; - ma += (t1000->displine >> 3) * 80; + scanline = (t1000->displine) & 7; + addr = ((memaddr & ~1) + (t1000->displine >> 3) * 80) * 2; + memaddr += (t1000->displine >> 3) * 80; if ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= sc) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc); + cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= scanline) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= scanline); } for (uint8_t x = 0; x < 80; x++) { chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16)); blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); @@ -284,13 +284,13 @@ t1000_text_row80(t1000_t *t1000) } if (drawcursor) { for (uint8_t c = 0; c < 8; c++) { - (buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); + (buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); } } else { for (uint8_t c = 0; c < 8; c++) - (buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + (buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0]; } - ++ma; + ++memaddr; } } @@ -306,23 +306,23 @@ t1000_text_row40(t1000_t *t1000) int bold; int blink; uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + uint8_t scanline; + uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2; - ma += (t1000->displine >> 3) * 40; + scanline = (t1000->displine) & 7; + addr = ((memaddr & ~1) + (t1000->displine >> 3) * 40) * 2; + memaddr += (t1000->displine >> 3) * 40; if ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= sc) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc); + cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= scanline) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= scanline); } for (uint8_t x = 0; x < 40; x++) { chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16)); blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); @@ -345,14 +345,14 @@ t1000_text_row40(t1000_t *t1000) } if (drawcursor) { for (uint8_t c = 0; c < 8; c++) { - (buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); + (buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); } } else { for (uint8_t c = 0; c < 8; c++) { - (buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + (buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0]; } } - ++ma; + ++memaddr; } } @@ -366,9 +366,9 @@ t1000_cgaline6(t1000_t *t1000) uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey; uint32_t bg = grey; - uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1); + addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((memaddr & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { dat = t1000->vram[addr & 0x3FFF]; @@ -395,8 +395,8 @@ t1000_cgaline4(t1000_t *t1000) uint32_t ink1; uint16_t addr; - uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1); + uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((memaddr & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { dat = t1000->vram[addr & 0x3FFF]; diff --git a/src/video/vid_cga_toshiba_t3100e.c b/src/video/vid_cga_toshiba_t3100e.c index 0346fccd4..56883ba4b 100644 --- a/src/video/vid_cga_toshiba_t3100e.c +++ b/src/video/vid_cga_toshiba_t3100e.c @@ -254,23 +254,23 @@ t3100e_text_row80(t3100e_t *t3100e) int bold; int blink; uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; + uint8_t scanline; + uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t cursoraddr = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; - ma += (t3100e->displine >> 4) * 80; + scanline = (t3100e->displine) & 15; + addr = ((memaddr & ~1) + (t3100e->displine >> 4) * 80) * 2; + memaddr += (t3100e->displine >> 4) * 80; if ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= sc); + cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= scanline) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= scanline); } for (uint8_t x = 0; x < 80; x++) { chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16)); blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); @@ -292,13 +292,13 @@ t3100e_text_row80(t3100e_t *t3100e) } if (drawcursor) { for (uint8_t c = 0; c < 8; c++) { - (buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + (buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } } else { for (uint8_t c = 0; c < 8; c++) - (buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + (buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0]; } - ++ma; + ++memaddr; } } @@ -315,23 +315,23 @@ t3100e_text_row40(t3100e_t *t3100e) int bold; int blink; uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; + uint8_t scanline; + uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t cursoraddr = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff; - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; - ma += (t3100e->displine >> 4) * 40; + scanline = (t3100e->displine) & 15; + addr = ((memaddr & ~1) + (t3100e->displine >> 4) * 40) * 2; + memaddr += (t3100e->displine >> 4) * 40; if ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= sc); + cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= scanline) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= scanline); } for (uint8_t x = 0; x < 40; x++) { chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16)); blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); @@ -353,14 +353,14 @@ t3100e_text_row40(t3100e_t *t3100e) } if (drawcursor) { for (c = 0; c < 8; c++) { - (buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + (buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } } else { for (c = 0; c < 8; c++) { - (buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + (buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0]; } } - ++ma; + ++memaddr; } } @@ -374,13 +374,13 @@ t3100e_cgaline6(t3100e_t *t3100e) uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; uint32_t bg = black; - uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; + uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 640*400 */ { - addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1); } else { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1); } for (uint8_t x = 0; x < 80; x++) { dat = t3100e->vram[addr & 0x7FFF]; @@ -407,13 +407,13 @@ t3100e_cgaline4(t3100e_t *t3100e) uint32_t ink1 = 0; uint16_t addr; - uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_END] << 8)) & 0x7fff; + uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_END] << 8)) & 0x7fff; if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 320*400 undocumented */ { - addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1); } else /* 320*200 */ { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1); } for (uint8_t x = 0; x < 80; x++) { dat = t3100e->vram[addr & 0x7FFF]; diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 170a601fd..70b2b9e16 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -1098,7 +1098,7 @@ chips_69000_recalctimings(svga_t *svga) svga->hblank_end_val = ((svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00)) | (svga->crtc[0x3c] & 0b11000000); svga->hblank_end_mask = 0xff; - svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16; + svga->memaddr_latch |= (svga->crtc[0x40] & 0xF) << 16; svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8; svga->interlace = !!(svga->crtc[0x70] & 0x80); @@ -2044,7 +2044,7 @@ chips_69000_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 2377e792b..e1c02f5a9 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -575,7 +575,7 @@ gd54xx_overlay_draw(svga_t *svga, int displine) uint8_t *src = &svga->vram[(svga->overlay_latch.addr << shift) & svga->vram_mask]; int bpp = svga->bpp; int bytesperpix = (bpp + 7) / 8; - uint8_t *src2 = &svga->vram[(svga->ma - (svga->hdisp * bytesperpix)) & svga->vram_display_mask]; + uint8_t *src2 = &svga->vram[(svga->memaddr - (svga->hdisp * bytesperpix)) & svga->vram_display_mask]; int occl; int ckval; @@ -1255,7 +1255,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; @@ -1875,7 +1875,7 @@ gd54xx_recalctimings(svga_t *svga) } else if (svga->gdcreg[5] & 0x40) svga->render = svga_render_8bpp_lowres; - svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); + svga->memaddr_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); svga->bpp = 8; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 6000a2f30..3b4e8cce0 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -313,7 +313,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if ((idx < 0xe) || (idx > 0x10)) { if ((idx == 0xc) || (idx == 0xd)) { ega->fullchange = 3; - ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + + ega->memaddr_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + ((ega->crtc[8] & 0x60) >> 5); } else { ega->fullchange = changeframecount; @@ -649,7 +649,7 @@ ega_recalctimings(ega_t *ega) ega->interlace = 0; - ega->ma_latch = (ega->crtc[0xc] << 8) | ega->crtc[0xd]; + ega->memaddr_latch = (ega->crtc[0xc] << 8) | ega->crtc[0xd]; ega->render = ega_render_blank; if (!ega->scrblank && ega->attr_palette_enable) { @@ -748,7 +748,7 @@ ega_dot_poll(void *priv) const int dwshift = doublewidth ? 1 : 0; const int dotwidth = 1 << dwshift; const int charwidth = dotwidth * (seq9dot ? 9 : 8); - const int cursoron = (ega->sc == (ega->crtc[10] & 31)); + const int cursoron = (ega->scanline == (ega->crtc[10] & 31)); const int cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; uint32_t addr; int drawcursor; @@ -792,7 +792,7 @@ ega_dot_poll(void *priv) else charaddr = ega->charseta + (chr * 0x80); - dat = ega->vram[charaddr + (ega->sc << 2)]; + dat = ega->vram[charaddr + (ega->scanline << 2)]; dat <<= 1; if ((chr & ~0x1F) == 0xC0 && attrlinechars) dat |= (dat >> 1) & 1; @@ -843,13 +843,13 @@ ega_poll(void *priv) if (ega->dispon) { ega->hdisp_on = 1; - ega->ma &= ega->vrammask; + ega->memaddr &= ega->vrammask; if (ega->firstline == 2000) { ega->firstline = ega->displine; video_wait_for_buffer(); } - old_ma = ega->ma; + old_ma = ega->memaddr; ega->displine *= ega->vres + 1; ega->y_add *= ega->vres + 1; for (int y = 0; y <= ega->vres; y++) { @@ -863,7 +863,7 @@ ega_poll(void *priv) ega->x_add = (overscan_x >> 1) - ega->scrollcache; if (y != ega->vres) { - ega->ma = old_ma; + ega->memaddr = old_ma; ega->displine++; } } @@ -900,31 +900,31 @@ ega_poll(void *priv) ega->hdisp_on = 0; ega->linepos = 0; - if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount)) + if ((ega->scanline == (ega->crtc[11] & 31)) || (ega->scanline == ega->rowcount)) ega->cursorvisible = 0; if (ega->dispon) { /* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll */ if (ega->linedbl && !ega->linecountff) { ega->linecountff = 1; - ega->ma = ega->maback; - ega->cca = ega->maback; + ega->memaddr = ega->memaddr_backup; + ega->cca = ega->memaddr_backup; } - if (ega->sc == (ega->crtc[9] & 31)) { + if (ega->scanline == (ega->crtc[9] & 31)) { ega->linecountff = 0; - ega->sc = 0; + ega->scanline = 0; - ega->maback += (ega->rowoffset << 3); + ega->memaddr_backup += (ega->rowoffset << 3); if (ega->interlace) - ega->maback += (ega->rowoffset << 3); - ega->maback &= ega->vrammask; - ega->ma = ega->maback; - ega->cca = ega->maback; + ega->memaddr_backup += (ega->rowoffset << 3); + ega->memaddr_backup &= ega->vrammask; + ega->memaddr = ega->memaddr_backup; + ega->cca = ega->memaddr_backup; } else { ega->linecountff = 0; - ega->sc++; - ega->sc &= 31; - ega->ma = ega->maback; - ega->cca = ega->maback; + ega->scanline++; + ega->scanline &= 31; + ega->memaddr = ega->memaddr_backup; + ega->cca = ega->memaddr_backup; } } ega->real_vc++; @@ -941,13 +941,13 @@ ega_poll(void *priv) if (ega->vc == ega->split) { // TODO: Implement the hardware bug where the first scanline is drawn twice when the split happens if (ega->interlace && ega->oddeven) - ega->ma = ega->maback = ega->rowoffset << 1; + ega->memaddr = ega->memaddr_backup = ega->rowoffset << 1; else - ega->ma = ega->maback = 0; - ega->ma <<= 2; - ega->cca = ega->ma; - ega->maback <<= 2; - ega->sc = 0; + ega->memaddr = ega->memaddr_backup = 0; + ega->memaddr <<= 2; + ega->cca = ega->memaddr; + ega->memaddr_backup <<= 2; + ega->scanline = 0; } if (ega->vc == ega->dispend) { ega->dispon = 0; @@ -1007,19 +1007,19 @@ ega_poll(void *priv) ega->vslines = 0; if (ega->interlace && ega->oddeven) - ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1); + ega->memaddr = ega->memaddr_backup = ega->memaddr_latch + (ega->rowoffset << 1); else - ega->ma = ega->maback = ega->ma_latch; - ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; + ega->memaddr = ega->memaddr_backup = ega->memaddr_latch; + ega->cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; - ega->ma <<= 2; - ega->maback <<= 2; - ega->ca <<= 2; - ega->cca = ega->ma; + ega->memaddr <<= 2; + ega->memaddr_backup <<= 2; + ega->cursoraddr <<= 2; + ega->cca = ega->memaddr; } if (ega->vc == ega->vtotal) { ega->vc = 0; - ega->sc = (ega->crtc[0x8] & 0x1f); + ega->scanline = (ega->crtc[0x8] & 0x1f); ega->dispon = 1; ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; @@ -1036,7 +1036,7 @@ ega_poll(void *priv) ega->linecountff = 0; } - if (ega->sc == (ega->crtc[10] & 31)) + if (ega->scanline == (ega->crtc[10] & 31)) ega->cursorvisible = 1; } } diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index b383e96b0..1f307a12c 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -141,9 +141,9 @@ ega_render_text(ega_t *ega) } for (int x = 0; x < (ega->hdisp + ega->scrollcache); x += charwidth) { - uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; + uint32_t addr = ega->remap_func(ega, ega->memaddr) & ega->vrammask; - int drawcursor = ((ega->ma == ega->ca) && ega->cursorvisible && ega->cursoron); + int drawcursor = ((ega->memaddr == ega->cursoraddr) && ega->cursorvisible && ega->cursoron); uint32_t chr; uint32_t attr; @@ -175,7 +175,7 @@ ega_render_text(ega_t *ega) } } - uint32_t dat = ega->vram[charaddr + (ega->sc << 2)]; + uint32_t dat = ega->vram[charaddr + (ega->scanline << 2)]; dat <<= 1; if (((chr & ~0x1f) == 0xc0) && attrlinechars) dat |= (dat >> 1) & 1; @@ -184,7 +184,7 @@ ega_render_text(ega_t *ega) 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)) + if ((ega->scanline == ega->crtc[0x14]) && ((attr & 7) == 1)) p[xx] = ega->mdacols[attr][blink][1]; else p[xx] = ega->mdacols[attr][blink][bit]; @@ -195,10 +195,10 @@ ega_render_text(ega_t *ega) p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; } - ega->ma += 4; + ega->memaddr += 4; p += charwidth; } - ega->ma &= 0x3ffff; + ega->memaddr &= 0x3ffff; } } @@ -236,7 +236,7 @@ ega_render_graphics(ega_t *ega) } for (int x = 0; x <= (ega->hdisp + ega->scrollcache); x += charwidth) { - uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; + uint32_t addr = ega->remap_func(ega, ega->memaddr) & ega->vrammask; uint8_t edat[4]; if (seqoddeven) { @@ -247,12 +247,12 @@ ega_render_graphics(ega_t *ega) edat[3] = ega->vram[(addr | 3) ^ secondcclk]; secondcclk = (secondcclk + 1) & 1; if (secondcclk == 0) - ega->ma += 4; + ega->memaddr += 4; } else { *(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]); - ega->ma += 4; + ega->memaddr += 4; } - ega->ma &= 0x3ffff; + ega->memaddr &= 0x3ffff; if (cga2bpp) { // Remap CGA 2bpp-chunky data into fully planar data diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index 193fed3c7..a82f93385 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -424,7 +424,7 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) static void et3000_recalctimings(svga_t *svga) { - svga->ma_latch |= (svga->crtc[0x23] & 2) << 15; + svga->memaddr_latch |= (svga->crtc[0x23] & 2) << 15; if (svga->crtc[0x25] & 1) svga->vblankstart |= 0x400; if (svga->crtc[0x25] & 2) @@ -439,7 +439,7 @@ et3000_recalctimings(svga_t *svga) svga->interlace = !!(svga->crtc[0x25] & 0x80); if (svga->attrregs[0x16] & 0x10) { - svga->ma_latch <<= (1 << 0); + svga->memaddr_latch <<= (1 << 0); svga->rowoffset <<= (1 << 0); switch (svga->gdcreg[5] & 0x60) { case 0x00: diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 1929d1d16..a99cb8872 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -378,7 +378,7 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -642,7 +642,7 @@ et4000_recalctimings(svga_t *svga) { const et4000_t *dev = (et4000_t *) svga->priv; - svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; + svga->memaddr_latch |= (svga->crtc[0x33] & 3) << 16; svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; @@ -701,7 +701,7 @@ et4000_recalctimings(svga_t *svga) if (dev->type == ET4000_TYPE_KOREAN || dev->type == ET4000_TYPE_TRIGEM || dev->type == ET4000_TYPE_KASAN) { if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { if (dev->port_32cb_val & 0x80) { - svga->ma_latch -= 2; + svga->memaddr_latch -= 2; svga->ca_adj = -2; } if ((dev->port_32cb_val & 0xB4) == ((svga->crtc[0x37] & 3) == 2 ? 0xB4 : 0xB0)) { @@ -719,7 +719,7 @@ et4000_recalctimings(svga_t *svga) } if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40) && svga->lowres) { - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; svga->rowoffset <<= 1; svga->render = svga_render_8bpp_highres; } @@ -734,7 +734,7 @@ et4000_kasan_recalctimings(svga_t *svga) if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) { svga->hdisp += svga->dots_per_clock; - svga->ma_latch -= 4; + svga->memaddr_latch -= 4; svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; if ((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 246decb9c..533bd1f28 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -238,7 +238,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -430,7 +430,7 @@ et4000w32p_recalctimings(svga_t *svga) { et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv; - svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; + svga->memaddr_latch |= (svga->crtc[0x33] & 0x7) << 16; svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index a8fd2227b..078e0f3df 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -361,26 +361,26 @@ f82c425_text_row(f82c425_t *f82c425) int cursorline; int blink; uint16_t addr; - uint8_t sc; - uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; + uint8_t scanline; + uint16_t memaddr = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t cursoraddr = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; uint8_t sl = f82c425->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1; int columns = f82c425->cga.crtc[CGA_CRTC_HDISP]; - sc = (f82c425->displine) & 7; - addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2; - ma += (f82c425->displine >> 3) * columns; + scanline = (f82c425->displine) & 7; + addr = ((memaddr & ~1) + (f82c425->displine >> 3) * columns) * 2; + memaddr += (f82c425->displine >> 3) * columns; if ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= sc) && ((f82c425->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc); + cursorline = ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= scanline) && ((f82c425->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= scanline); } for (int x = 0; x < columns; x++) { chr = f82c425->vram[(addr + 2 * x) & 0x3FFF]; attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && (f82c425->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (f82c425->cga.cgablink & 0x10)); + drawcursor = ((memaddr == cursoraddr) && cursorline && (f82c425->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (f82c425->cga.cgablink & 0x10)); blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor); @@ -398,16 +398,16 @@ f82c425_text_row(f82c425_t *f82c425) if (f82c425->cga.cgamode & 0x01) { /* High resolution (80 cols) */ for (c = 0; c < sl; c++) { - (buffer32->line[f82c425->displine])[(x << 3) + c] = colors[(fontdat[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + (buffer32->line[f82c425->displine])[(x << 3) + c] = colors[(fontdat[chr][scanline] & (1 << (c ^ 7))) ? 1 : 0]; } } else { /* Low resolution (40 columns, stretch pixels horizontally) */ for (c = 0; c < sl; c++) { - (buffer32->line[f82c425->displine])[(x << 4) + c * 2] = (buffer32->line[f82c425->displine])[(x << 4) + c * 2 + 1] = colors[(fontdat[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + (buffer32->line[f82c425->displine])[(x << 4) + c * 2] = (buffer32->line[f82c425->displine])[(x << 4) + c * 2 + 1] = colors[(fontdat[chr][scanline] & (1 << (c ^ 7))) ? 1 : 0]; } } - ++ma; + ++memaddr; } } @@ -418,9 +418,9 @@ f82c425_cgaline6(f82c425_t *f82c425) uint8_t dat; uint16_t addr; - uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + uint16_t memaddr = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1); + addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((memaddr & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { dat = f82c425->vram[addr & 0x3FFF]; @@ -442,8 +442,8 @@ f82c425_cgaline4(f82c425_t *f82c425) uint8_t pattern; uint16_t addr; - uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1); + uint16_t memaddr = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((memaddr & ~1) << 1); for (uint8_t x = 0; x < 80; x++) { dat = f82c425->vram[addr & 0x3FFF]; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index c7a91aac6..366fa25e1 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -387,7 +387,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) int cw = 9; /* Each character is 9 pixels wide */ uint8_t chr; uint8_t attr; - uint8_t sc; + uint8_t scanline; uint8_t ctrl; const uint8_t *crtc; uint8_t bitmap[2]; @@ -398,8 +398,8 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) int drawcursor; int cursorline; uint16_t addr; - uint16_t ma = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff; - uint16_t ca = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff; + uint16_t memaddr = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff; + uint16_t cursoraddr = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff; const uint8_t *framebuf = genius->vram + 0x10000; uint32_t col; uint32_t dl = genius->displine; @@ -416,14 +416,14 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) #if 0 if (genius->genius_charh & 0x10) { row = ((dl >> 1) / charh); - sc = ((dl >> 1) % charh); + scanline = ((dl >> 1) % charh); } else { row = (dl / charh); - sc = (dl % charh); + scanline = (dl % charh); } #else row = (dl / charh); - sc = (dl % charh); + scanline = (dl % charh); #endif } else { if ((genius->displine < 512) || (genius->displine >= 912)) @@ -439,23 +439,23 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) charh = crtc[9] + 1; row = ((dl >> 1) / charh); - sc = ((dl >> 1) % charh); + scanline = ((dl >> 1) % charh); } - ma = (crtc[13] | (crtc[12] << 8)) & 0x3fff; - ca = (crtc[15] | (crtc[14] << 8)) & 0x3fff; + memaddr = (crtc[13] | (crtc[12] << 8)) & 0x3fff; + cursoraddr = (crtc[15] | (crtc[14] << 8)) & 0x3fff; - addr = ((ma & ~1) + row * w) * 2; + addr = ((memaddr & ~1) + row * w) * 2; if (!mda) dl += 512; - ma += (row * w); + memaddr += (row * w); if ((crtc[10] & 0x60) == 0x20) cursorline = 0; else - cursorline = ((crtc[10] & 0x1F) <= sc) && ((crtc[11] & 0x1F) >= sc); + cursorline = ((crtc[10] & 0x1F) <= scanline) && ((crtc[11] & 0x1F) >= scanline); for (int x = 0; x < w; x++) { #if 0 @@ -467,7 +467,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) chr = framebuf[(addr + 2 * x) & 0x3FFF]; attr = framebuf[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && genius->enabled && (ctrl & 8)); + drawcursor = ((memaddr == cursoraddr) && cursorline && genius->enabled && (ctrl & 8)); switch (crtc[10] & 0x60) { case 0x00: @@ -487,7 +487,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) attr &= 0x7F; /* MDA underline */ - if (mda && (sc == charh) && ((attr & 7) == 1)) { + if (mda && (scanline == charh) && ((attr & 7) == 1)) { col = mdaattr[attr][blink][1]; if (genius->genius_control & 0x20) @@ -504,9 +504,9 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) } } else { /* Draw 8 pixels of character */ if (mda) - bitmap[0] = fontdat8x12[chr][sc]; + bitmap[0] = fontdat8x12[chr][scanline]; else - bitmap[0] = fontdat[chr][sc]; + bitmap[0] = fontdat[chr][scanline]; for (c = 0; c < 8; c++) { col = mdaattr[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; @@ -563,7 +563,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) } } } - ++ma; + ++memaddr; } } } diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 48037b3f4..4b8d796a3 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -168,9 +168,9 @@ hercules_in(uint16_t addr, void *priv) case 0x03b5: case 0x03b7: if (dev->crtcreg == 0x0c) - ret = (dev->ma >> 8) & 0x3f; + ret = (dev->memaddr >> 8) & 0x3f; else if (dev->crtcreg == 0x0d) - ret = dev->ma & 0xff; + ret = dev->memaddr & 0xff; else ret = dev->crtc[dev->crtcreg]; break; @@ -281,10 +281,10 @@ hercules_poll(void *priv) hercules_t *dev = (hercules_t *) priv; uint8_t chr; uint8_t attr; - uint16_t ca; + uint16_t cursoraddr; uint16_t dat; uint16_t pa; - int oldsc; + int scanline_old; int blink; int x; int xx; @@ -296,16 +296,16 @@ hercules_poll(void *priv) uint32_t *p; VIDEO_MONITOR_PROLOGUE() - ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + cursoraddr = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; if (!dev->linepos) { timer_advance_u64(&dev->timer, dev->dispofftime); dev->stat |= 1; dev->linepos = 1; - oldsc = dev->sc; + scanline_old = dev->scanline; if ((dev->crtc[8] & 3) == 3) - dev->sc = (dev->sc << 1) & 7; + dev->scanline = (dev->scanline << 1) & 7; if (dev->dispon) { if (dev->displine < dev->firstline) { @@ -317,16 +317,16 @@ hercules_poll(void *priv) hercules_render_overscan_left(dev); if (dev->ctrl & 0x02) { - ca = (dev->sc & 3) * 0x2000; + cursoraddr = (dev->scanline & 3) * 0x2000; if (dev->ctrl & 0x80) - ca += 0x8000; + cursoraddr += 0x8000; for (x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) - dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; + dat = (dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr] << 8) | dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 1]; else dat = 0; - dev->ma++; + dev->memaddr++; for (c = 0; c < 16; c++) buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0; for (c = 0; c < 16; c += 8) @@ -341,25 +341,25 @@ hercules_poll(void *priv) attr = dev->charbuffer[(x << 1) + 1]; } else chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); + drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron); blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (dev->sc == 12 && ((attr & 7) == 1)) { + if (dev->scanline == 12 && ((attr & 7) == 1)) { for (c = 0; c < 9; c++) buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1]; } else { for (c = 0; c < 8; c++) - buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->scanline] & (1 << (c ^ 7))) ? 1 : 0]; if ((chr & ~0x1f) == 0xc0) - buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; + buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->scanline] & 1]; else buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0]; } if (dev->ctrl2 & 0x01) - dev->ma = (dev->ma + 1) & 0x3fff; + dev->memaddr = (dev->memaddr + 1) & 0x3fff; else - dev->ma = (dev->ma + 1) & 0x7ff; + dev->memaddr = (dev->memaddr + 1) & 0x7ff; if (drawcursor) { for (c = 0; c < 9; c++) @@ -377,9 +377,9 @@ hercules_poll(void *priv) video_process_8(x + 16, dev->displine + 14); } - dev->sc = oldsc; + dev->scanline = scanline_old; - if (dev->vc == dev->crtc[7] && !dev->sc) + if (dev->vc == dev->crtc[7] && !dev->scanline) dev->stat |= 8; dev->displine++; if (dev->displine >= 500) @@ -397,23 +397,23 @@ hercules_poll(void *priv) dev->stat &= ~8; } - if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { dev->cursorvisible = 0; } if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; dev->vadj--; if (!dev->vadj) { dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->scanline = 0; } - } else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { - dev->maback = dev->ma; - dev->sc = 0; + } else if (((dev->crtc[8] & 3) != 3 && dev->scanline == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))) { + dev->memaddr_backup = dev->memaddr; + dev->scanline = 0; oldvc = dev->vc; dev->vc++; dev->vc &= 127; @@ -426,7 +426,7 @@ hercules_poll(void *priv) dev->vadj = dev->crtc[5]; if (!dev->vadj) { dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; } switch (dev->crtc[10] & 0x60) { case 0x20: @@ -511,17 +511,17 @@ hercules_poll(void *priv) dev->blink++; } } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; } - if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1))) dev->cursorvisible = 1; if (dev->dispon && !(dev->ctrl & 0x02)) { for (x = 0; x < (dev->crtc[1] << 1); x++) { pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000; - dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa]; + dev->charbuffer[x] = dev->vram[(((dev->memaddr << 1) + x) & 0x3fff) + pa]; } } } diff --git a/src/video/vid_hercules_incolor.c b/src/video/vid_hercules_incolor.c index 1d5e9d2aa..6e202d338 100644 --- a/src/video/vid_hercules_incolor.c +++ b/src/video/vid_hercules_incolor.c @@ -165,8 +165,8 @@ typedef struct { int firstline, lastline; int linepos, displine; - int vc, sc; - uint16_t ma, maback; + int vc, scanline; + uint16_t memaddr, memaddr_backup; int cursorvisible, cursoron; int dispon, blink; int vsynctime; @@ -483,11 +483,11 @@ draw_char_rom(incolor_t *dev, int x, uint8_t chr, uint8_t attr) elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = &(fontdatm[chr][dev->sc]); + fnt = &(fontdatm[chr][dev->scanline]); if (blk) { val = 0x000; /* Blinking, draw all background */ - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { val = 0x1ff; /* Underscore, draw all foreground */ } else { val = fnt[0] << 1; @@ -559,12 +559,12 @@ draw_char_ram4(incolor_t *dev, int x, uint8_t chr, uint8_t attr) } else { elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; + fnt = dev->vram + 0x4000 + 16 * chr + dev->scanline; if (blk) { /* Blinking, draw all background */ val[0] = val[1] = val[2] = val[3] = 0x000; - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { /* Underscore, draw all foreground */ val[0] = val[1] = val[2] = val[3] = 0x1ff; } else { @@ -685,12 +685,12 @@ draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr) } else { elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->scanline; if (blk) { /* Blinking, draw all background */ val[0] = val[1] = val[2] = val[3] = 0x000; - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { /* Underscore, draw all foreground */ val[0] = val[1] = val[2] = val[3] = 0x1ff; } else { @@ -716,9 +716,9 @@ draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr) /* Generate pixel colour */ cfg = 0; pmask = 1; - if (dev->sc == oll) { + if (dev->scanline == oll) { cfg = olc ^ ibg; /* Strikethrough */ - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { cfg = ulc ^ ibg; /* Underline */ } else { for (uint8_t plane = 0; plane < 4; plane++, pmask = pmask << 1) { @@ -746,7 +746,7 @@ draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr) } static void -text_line(incolor_t *dev, uint16_t ca) +text_line(incolor_t *dev, uint16_t cursoraddr) { int drawcursor; uint8_t chr; @@ -755,12 +755,12 @@ text_line(incolor_t *dev, uint16_t ca) for (uint8_t x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) { - chr = dev->vram[(dev->ma << 1) & 0x3fff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + chr = dev->vram[(dev->memaddr << 1) & 0x3fff]; + attr = dev->vram[((dev->memaddr << 1) + 1) & 0x3fff]; } else chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); + drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron); switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) { case 0: @@ -779,7 +779,7 @@ text_line(incolor_t *dev, uint16_t ca) default: break; } - ++dev->ma; + ++dev->memaddr; if (drawcursor) { int cw = INCOLOR_CW; @@ -808,29 +808,29 @@ static void graphics_line(incolor_t *dev) { uint8_t mask; - uint16_t ca; + uint16_t cursoraddr; int plane; int col; uint8_t ink; uint16_t val[4]; /* Graphics mode. */ - ca = (dev->sc & 3) * 0x2000; + cursoraddr = (dev->scanline & 3) * 0x2000; if ((dev->ctrl & INCOLOR_CTRL_PAGE1) && (dev->ctrl2 & INCOLOR_CTRL2_PAGE1)) - ca += 0x8000; + cursoraddr += 0x8000; for (uint8_t x = 0; x < dev->crtc[1]; x++) { mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ for (plane = 0; plane < 4; plane++, mask = mask >> 1) { if (dev->ctrl & 8) { if (mask & 1) - val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + val[plane] = (dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane] << 8) | dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane + 1]; else val[plane] = 0; } else val[plane] = 0; } - dev->ma++; + dev->memaddr++; for (uint8_t c = 0; c < 16; c++) { ink = 0; @@ -855,19 +855,19 @@ static void incolor_poll(void *priv) { incolor_t *dev = (incolor_t *) priv; - uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; int x; int oldvc; - int oldsc; + int scanline_old; int cw = INCOLOR_CW; if (!dev->linepos) { timer_advance_u64(&dev->timer, dev->dispofftime); dev->stat |= 1; dev->linepos = 1; - oldsc = dev->sc; + scanline_old = dev->scanline; if ((dev->crtc[8] & 3) == 3) - dev->sc = (dev->sc << 1) & 7; + dev->scanline = (dev->scanline << 1) & 7; if (dev->dispon) { if (dev->displine < dev->firstline) { @@ -878,10 +878,10 @@ incolor_poll(void *priv) if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) graphics_line(dev); else - text_line(dev, ca); + text_line(dev, cursoraddr); } - dev->sc = oldsc; - if (dev->vc == dev->crtc[7] && !dev->sc) + dev->scanline = scanline_old; + if (dev->vc == dev->crtc[7] && !dev->scanline) dev->stat |= 8; dev->displine++; if (dev->displine >= 500) @@ -897,24 +897,24 @@ incolor_poll(void *priv) dev->stat &= ~8; } - if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { dev->cursorvisible = 0; } if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; dev->vadj--; if (!dev->vadj) { dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->scanline = 0; } - } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { - dev->maback = dev->ma; - dev->sc = 0; - oldvc = dev->vc; + } else if (dev->scanline == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))) { + dev->memaddr_backup = dev->memaddr; + dev->scanline = 0; + oldvc = dev->vc; dev->vc++; dev->vc &= 127; if (dev->vc == dev->crtc[6]) @@ -925,7 +925,7 @@ incolor_poll(void *priv) if (!dev->vadj) dev->dispon = 1; if (!dev->vadj) - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; if ((dev->crtc[10] & 0x60) == 0x20) dev->cursoron = 0; else @@ -971,12 +971,12 @@ incolor_poll(void *priv) dev->blink++; } } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; } - if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1))) dev->cursorvisible = 1; } } diff --git a/src/video/vid_hercules_plus.c b/src/video/vid_hercules_plus.c index 4c3f7867c..4a2790dc0 100644 --- a/src/video/vid_hercules_plus.c +++ b/src/video/vid_hercules_plus.c @@ -75,8 +75,8 @@ typedef struct { int firstline, lastline; int linepos, displine; - int vc, sc; - uint16_t ma, maback; + int vc, scanline; + uint16_t memaddr, memaddr_backup; int cursorvisible, cursoron; int dispon, blink; int vsynctime; @@ -260,11 +260,11 @@ draw_char_rom(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) else elg = ((chr >= 0xc0) && (chr <= 0xdf)); - fnt = &(fontdatm[chr][dev->sc]); + fnt = &(fontdatm[chr][dev->scanline]); if (blk) { val = 0x000; /* Blinking, draw all background */ - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { val = 0x1ff; /* Underscore, draw all foreground */ } else { val = fnt[0] << 1; @@ -319,11 +319,11 @@ draw_char_ram4(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) else elg = ((chr >= 0xc0) && (chr <= 0xdf)); - fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; + fnt = dev->vram + 0x4000 + 16 * chr + dev->scanline; if (blk) { val = 0x000; /* Blinking, draw all background */ - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { val = 0x1ff; /* Underscore, draw all foreground */ } else { val = fnt[0] << 1; @@ -384,11 +384,11 @@ draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) else elg = ((chr >= 0xc0) && (chr <= 0xdf)); - fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->scanline; if (blk) { val = 0x000; /* Blinking, draw all background */ - } else if (dev->sc == ull) { + } else if (dev->scanline == ull) { val = 0x1ff; /* Underscore, draw all foreground */ } else { val = fnt[0] << 1; @@ -404,7 +404,7 @@ draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) } static void -text_line(herculesplus_t *dev, uint16_t ca) +text_line(herculesplus_t *dev, uint16_t cursoraddr) { int drawcursor; uint8_t chr; @@ -413,12 +413,12 @@ text_line(herculesplus_t *dev, uint16_t ca) for (uint8_t x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) { - chr = dev->vram[(dev->ma << 1) & 0x3fff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + chr = dev->vram[(dev->memaddr << 1) & 0x3fff]; + attr = dev->vram[((dev->memaddr << 1) + 1) & 0x3fff]; } else chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron); + drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron); switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) { case 0: @@ -437,7 +437,7 @@ text_line(herculesplus_t *dev, uint16_t ca) default: break; } - ++dev->ma; + ++dev->memaddr; if (drawcursor) { int cw = HERCULESPLUS_CW; @@ -452,24 +452,24 @@ text_line(herculesplus_t *dev, uint16_t ca) static void graphics_line(herculesplus_t *dev) { - uint16_t ca; + uint16_t cursoraddr; int c; int plane = 0; uint16_t val; /* Graphics mode. */ - ca = (dev->sc & 3) * 0x2000; + cursoraddr = (dev->scanline & 3) * 0x2000; if ((dev->ctrl & HERCULESPLUS_CTRL_PAGE1) && (dev->ctrl2 & HERCULESPLUS_CTRL2_PAGE1)) - ca += 0x8000; + cursoraddr += 0x8000; for (uint8_t x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) - val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) - | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + val = (dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane] << 8) + | dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane + 1]; else val = 0; - dev->ma++; + dev->memaddr++; for (c = 0; c < 16; c++) { buffer32->line[dev->displine][(x << 4) + c] = (val & 0x8000) ? 7 : 0; @@ -485,10 +485,10 @@ static void herculesplus_poll(void *priv) { herculesplus_t *dev = (herculesplus_t *) priv; - uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; int x; int oldvc; - int oldsc; + int scanline_old; int cw = HERCULESPLUS_CW; VIDEO_MONITOR_PROLOGUE(); @@ -496,9 +496,9 @@ herculesplus_poll(void *priv) timer_advance_u64(&dev->timer, dev->dispofftime); dev->stat |= 1; dev->linepos = 1; - oldsc = dev->sc; + scanline_old = dev->scanline; if ((dev->crtc[8] & 3) == 3) - dev->sc = (dev->sc << 1) & 7; + dev->scanline = (dev->scanline << 1) & 7; if (dev->dispon) { if (dev->displine < dev->firstline) { dev->firstline = dev->displine; @@ -508,7 +508,7 @@ herculesplus_poll(void *priv) if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) graphics_line(dev); else - text_line(dev, ca); + text_line(dev, cursoraddr); if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) x = dev->crtc[1] << 4; @@ -517,8 +517,8 @@ herculesplus_poll(void *priv) video_process_8(x, dev->displine); } - dev->sc = oldsc; - if (dev->vc == dev->crtc[7] && !dev->sc) + dev->scanline = scanline_old; + if (dev->vc == dev->crtc[7] && !dev->scanline) dev->stat |= 8; dev->displine++; if (dev->displine >= 500) @@ -534,22 +534,22 @@ herculesplus_poll(void *priv) dev->stat &= ~8; } - if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { dev->cursorvisible = 0; } if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; dev->vadj--; if (!dev->vadj) { dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->scanline = 0; } - } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { - dev->maback = dev->ma; - dev->sc = 0; + } else if (dev->scanline == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))) { + dev->memaddr_backup = dev->memaddr; + dev->scanline = 0; oldvc = dev->vc; dev->vc++; dev->vc &= 127; @@ -561,7 +561,7 @@ herculesplus_poll(void *priv) if (!dev->vadj) dev->dispon = 1; if (!dev->vadj) - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; if ((dev->crtc[10] & 0x60) == 0x20) dev->cursoron = 0; else @@ -606,12 +606,12 @@ herculesplus_poll(void *priv) dev->blink++; } } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; + dev->scanline++; + dev->scanline &= 31; + dev->memaddr = dev->memaddr_backup; } - if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1))) dev->cursorvisible = 1; } diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index b650cb53b..3089ae26d 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -448,7 +448,7 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -660,10 +660,10 @@ ht216_recalctimings(svga_t *svga) break; } - svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); + svga->memaddr_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); if (ht216->ht_regs[0xf6] & 0x80) - svga->ma_latch = ((ht216->ht_regs[0xf6] & 0x30) << 12); + svga->memaddr_latch = ((ht216->ht_regs[0xf6] & 0x30) << 12); svga->interlace = ht216->ht_regs[0xe0] & 0x01; diff --git a/src/video/vid_ibm_rgb528_ramdac.c b/src/video/vid_ibm_rgb528_ramdac.c index dcdbbb25b..cd7d5c1b6 100644 --- a/src/video/vid_ibm_rgb528_ramdac.c +++ b/src/video/vid_ibm_rgb528_ramdac.c @@ -104,7 +104,7 @@ ibm_rgb528_render_4bpp(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -114,8 +114,8 @@ ibm_rgb528_render_4bpp(svga_t *svga) for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { if (vram_size == 3) { if (!(x & 31)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); - dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); + dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]); if (swap_word) { dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); @@ -127,7 +127,7 @@ ibm_rgb528_render_4bpp(svga_t *svga) dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf; } else if (vram_size == 1) { if (!(x & 15)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); if (swap_word) dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); } @@ -137,7 +137,7 @@ ibm_rgb528_render_4bpp(svga_t *svga) dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf; } else { if (!(x & 7)) - dat32 = *(uint32_t *) (&svga->vram[svga->ma]); + dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]); if (swap_nib) dat = (dat32 >> ((x & 7) << 2)) & 0xf; else @@ -156,11 +156,11 @@ ibm_rgb528_render_4bpp(svga_t *svga) p[x] = dat_out.pixel & 0xffffff; if ((vram_size == 3) && ((x & 31) == 31)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask; if ((vram_size == 1) && ((x & 15) == 15)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask; else if ((!vram_size) && ((x & 7) == 7)) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask; } } } @@ -182,7 +182,7 @@ ibm_rgb528_render_8bpp(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -192,8 +192,8 @@ ibm_rgb528_render_8bpp(svga_t *svga) for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { if (vram_size == 3) { if (!(x & 15)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); - dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); + dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]); if (swap_word) { dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); @@ -202,14 +202,14 @@ ibm_rgb528_render_8bpp(svga_t *svga) dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff; } else if (vram_size == 1) { if (!(x & 7)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); if (swap_word) dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); } dat = (dat64 >> ((x & 7) << 3)) & 0xff; } else { if (!(x & 3)) - dat32 = *(uint32_t *) (&svga->vram[svga->ma]); + dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]); dat = (dat32 >> ((x & 3) << 3)) & 0xff; } if (b8_dcol == 0x00) { @@ -225,11 +225,11 @@ ibm_rgb528_render_8bpp(svga_t *svga) p[x] = dat_out.pixel & 0xffffff; if ((vram_size == 3) && ((x & 15) == 15)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask; else if ((vram_size == 1) && ((x & 7) == 7)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask; else if ((!vram_size) && ((x & 3) == 3)) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask; } } } @@ -262,7 +262,7 @@ ibm_rgb528_render_15_16bpp(svga_t *svga) if (b555_565 && (b16_dcol != 0x01)) partition &= 0xc0; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -272,8 +272,8 @@ ibm_rgb528_render_15_16bpp(svga_t *svga) for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { if (vram_size == 2) { if (!(x & 7)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); - dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); + dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]); if (swap_word) { dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL); @@ -282,14 +282,14 @@ ibm_rgb528_render_15_16bpp(svga_t *svga) dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff; } else if (vram_size == 1) { if (!(x & 3)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); if (swap_word) dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); } dat = (dat64 >> ((x & 3) << 4)) & 0xffff; } else { if (!(x & 1)) - dat32 = *(uint32_t *) (&svga->vram[svga->ma]); + dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]); dat = (dat32 >> ((x & 1) << 4)) & 0xffff; } dat_ex = (ibm_rgb528_pixel16_t *) &dat; @@ -350,11 +350,11 @@ ibm_rgb528_render_15_16bpp(svga_t *svga) p[x] = dat_out.pixel & 0xffffff; if ((vram_size == 3) && ((x & 7) == 7)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask; else if ((vram_size == 1) && ((x & 3) == 3)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask; else if (!vram_size && ((x & 1) == 1)) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask; } } } @@ -378,7 +378,7 @@ ibm_rgb528_render_24bpp(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -389,12 +389,12 @@ ibm_rgb528_render_24bpp(svga_t *svga) dat_ex = (ibm_rgb528_pixel32_t *) &dat; if (vram_size == 3) { if ((x & 15) == 0) { - dat64[0] = *(uint64_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - dat64[1] = *(uint64_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); - dat64[2] = *(uint64_t *) (&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); - dat64[3] = *(uint64_t *) (&svga->vram[(svga->ma + 24) & svga->vram_display_mask]); - dat64[4] = *(uint64_t *) (&svga->vram[(svga->ma + 32) & svga->vram_display_mask]); - dat64[5] = *(uint64_t *) (&svga->vram[(svga->ma + 40) & svga->vram_display_mask]); + dat64[0] = *(uint64_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); + dat64[1] = *(uint64_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *) (&svga->vram[(svga->memaddr + 16) & svga->vram_display_mask]); + dat64[3] = *(uint64_t *) (&svga->vram[(svga->memaddr + 24) & svga->vram_display_mask]); + dat64[4] = *(uint64_t *) (&svga->vram[(svga->memaddr + 32) & svga->vram_display_mask]); + dat64[5] = *(uint64_t *) (&svga->vram[(svga->memaddr + 40) & svga->vram_display_mask]); if (swap_word) { dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); @@ -407,9 +407,9 @@ ibm_rgb528_render_24bpp(svga_t *svga) dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[(x & 15) * 3]); } else if (vram_size == 1) { if ((x & 7) == 0) { - dat64[0] = *(uint64_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - dat64[1] = *(uint64_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); - dat64[2] = *(uint64_t *) (&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + dat64[0] = *(uint64_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); + dat64[1] = *(uint64_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *) (&svga->vram[(svga->memaddr + 16) & svga->vram_display_mask]); if (swap_word) { dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); @@ -441,9 +441,9 @@ ibm_rgb528_render_24bpp(svga_t *svga) p[x] = dat_ex->pixel & 0xffffff; if ((vram_size == 3) && ((x & 15) == 15)) - svga->ma = (svga->ma + 48) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 48) & svga->vram_display_mask; else if ((vram_size == 1) && ((x & 7) == 7)) - svga->ma = (svga->ma + 24) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 24) & svga->vram_display_mask; } } } @@ -468,7 +468,7 @@ ibm_rgb528_render_32bpp(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) { p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -478,8 +478,8 @@ ibm_rgb528_render_32bpp(svga_t *svga) for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { if (vram_size == 3) { if (!(x & 3)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); - dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); + dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]); if (swap_word) { dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); @@ -488,13 +488,13 @@ ibm_rgb528_render_32bpp(svga_t *svga) dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff; } else if (vram_size == 1) { if (!(x & 1)) { - dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]); if (swap_word) dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); } dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff; } else - dat = *(uint32_t *) (&svga->vram[svga->ma]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr]); dat_ex = (ibm_rgb528_pixel32_t *) &dat; if (swaprb) { temp = dat_ex->r; @@ -520,11 +520,11 @@ ibm_rgb528_render_32bpp(svga_t *svga) p[x] = dat_ex->pixel & 0xffffff; if ((vram_size == 3) && ((x & 3) == 3)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask; else if ((vram_size == 1) && ((x & 1) == 1)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask; else if (!vram_size) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; + svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask; } } } diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 053ef0030..257acfff0 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -116,7 +116,7 @@ typedef struct jega_t { int cursorvisible; int cursoron; int cursorblink_disable; - int ca; + int cursoraddr; int font_index; int sbcsbank_inv; int attr3_sbcsbank; @@ -222,14 +222,14 @@ jega_render_text(void *priv) &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 * sc = jega->is_vga ? &jega->vga.svga.scanline : + &jega->ega.scanline; 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; + uint32_t *memaddr = jega->is_vga ? &jega->vga.svga.memaddr : + &jega->ega.memaddr; uint8_t mask = jega->is_vga ? jega->vga.svga.dac_mask : 0xff; if (*firstline_draw == 2000) @@ -260,12 +260,12 @@ jega_render_text(void *priv) if (jega->is_vga) { if (!jega->vga.svga.force_old_addr) - addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.ma) & + addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.memaddr) & jega->vga.svga.vram_display_mask; } else - addr = jega->ega.remap_func(&jega->ega, *ma) & jega->ega.vrammask; + addr = jega->ega.remap_func(&jega->ega, *memaddr) & jega->ega.vrammask; - int drawcursor = ((*ma == jega->ca) && cursoron); + int drawcursor = ((*memaddr == jega->cursoraddr) && cursoron); uint32_t chr; uint32_t attr; @@ -399,9 +399,9 @@ jega_render_text(void *priv) p += charwidth; } } - *ma += 4; + *memaddr += 4; } - *ma &= 0x3ffff; + *memaddr &= 0x3ffff; } } @@ -523,7 +523,7 @@ jega_out(uint16_t addr, uint8_t val, void *priv) break; case RCCLH: case RCCLL: - jega->ca = jega->regs[RCCLH] << 10 | jega->regs[RCCLL] << 2; + jega->cursoraddr = jega->regs[RCCLH] << 10 | jega->regs[RCCLL] << 2; break; case RCMOD: jega->cursoron = (val & 0x80); diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 12f8a93ac..4928441e6 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -131,14 +131,14 @@ void mda_poll(void *priv) { mda_t *mda = (mda_t *) priv; - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; int drawcursor; int x; int c; int oldvc; uint8_t chr; uint8_t attr; - int oldsc; + int scanline_old; int blink; VIDEO_MONITOR_PROLOGUE() @@ -146,9 +146,9 @@ mda_poll(void *priv) timer_advance_u64(&mda->timer, mda->dispofftime); mda->stat |= 1; mda->linepos = 1; - oldsc = mda->sc; + scanline_old = mda->scanline; if ((mda->crtc[8] & 3) == 3) - mda->sc = (mda->sc << 1) & 7; + mda->scanline = (mda->scanline << 1) & 7; if (mda->dispon) { if (mda->displine < mda->firstline) { mda->firstline = mda->displine; @@ -156,22 +156,22 @@ mda_poll(void *priv) } mda->lastline = mda->displine; for (x = 0; x < mda->crtc[1]; x++) { - chr = mda->vram[(mda->ma << 1) & 0xfff]; - attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->cursorvisible && mda->cursoron); + chr = mda->vram[(mda->memaddr << 1) & 0xfff]; + attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; + drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (mda->sc == 12 && ((attr & 7) == 1)) { + if (mda->scanline == 12 && ((attr & 7) == 1)) { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; } else { for (c = 0; c < 8; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr + mda->fontbase][mda->sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0]; if ((chr & ~0x1f) == 0xc0) - buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr + mda->fontbase][mda->sc] & 1]; + buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; else buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0]; } - mda->ma++; + mda->memaddr++; if (drawcursor) { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1]; @@ -180,8 +180,8 @@ mda_poll(void *priv) video_process_8(mda->crtc[1] * 9, mda->displine); } - mda->sc = oldsc; - if (mda->vc == mda->crtc[7] && !mda->sc) { + mda->scanline = scanline_old; + if (mda->vc == mda->crtc[7] && !mda->scanline) { mda->stat |= 8; } mda->displine++; @@ -198,22 +198,22 @@ mda_poll(void *priv) mda->stat &= ~8; } } - if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[11] & 31) >> 1))) { mda->cursorvisible = 0; } if (mda->vadj) { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; + mda->scanline++; + mda->scanline &= 31; + mda->memaddr = mda->memaddr_backup; mda->vadj--; if (!mda->vadj) { mda->dispon = 1; - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - mda->sc = 0; + mda->memaddr = mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->scanline = 0; } - } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { - mda->maback = mda->ma; - mda->sc = 0; + } else if (mda->scanline == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->scanline == (mda->crtc[9] >> 1))) { + mda->memaddr_backup = mda->memaddr; + mda->scanline = 0; oldvc = mda->vc; mda->vc++; mda->vc &= 127; @@ -225,7 +225,7 @@ mda_poll(void *priv) if (!mda->vadj) mda->dispon = 1; if (!mda->vadj) - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->memaddr = mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0; else @@ -261,11 +261,11 @@ mda_poll(void *priv) mda->blink++; } } else { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; + mda->scanline++; + mda->scanline &= 31; + mda->memaddr = mda->memaddr_backup; } - if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[10] & 31) >> 1))) { mda->cursorvisible = 1; } } diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 00570bd9f..294e6ce75 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -736,7 +736,7 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) if ((svga->crtcreg & 0x3f) < 0xE || (svga->crtcreg & 0x3f) > 0x10) { if (((svga->crtcreg & 0x3f) == 0xc) || ((svga->crtcreg & 0x3f) == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -768,24 +768,24 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) if (!(mystique->type >= MGA_2164W)) svga->rowoffset <<= 1; - svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | + svga->memaddr_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd]; if ((mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8))) { svga->rowoffset <<= 1; - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; } if (!(mystique->type >= MGA_2164W)) - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; - if (svga->ma_latch != mystique->ma_latch_old) { + if (svga->memaddr_latch != mystique->ma_latch_old) { if (svga->interlace && svga->oddeven) - svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + - (svga->ma_latch << 2) + (svga->rowoffset << 1); + svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) + + (svga->memaddr_latch << 2) + (svga->rowoffset << 1); else - svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + - (svga->ma_latch << 2); - mystique->ma_latch_old = svga->ma_latch; + svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) + + (svga->memaddr_latch << 2); + mystique->ma_latch_old = svga->memaddr_latch; } } @@ -895,9 +895,9 @@ mystique_vblank_start(svga_t *svga) mystique_t *mystique = (mystique_t *) svga->priv; if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { - svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd]; + svga->memaddr_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd]; if (mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8)) - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; } } @@ -984,29 +984,29 @@ mystique_recalctimings(svga_t *svga) svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS); if (mystique->type >= MGA_1064SG) - svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd]; + svga->memaddr_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd]; if ((mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8))) { svga->rowoffset <<= 1; if (mystique->type >= MGA_1064SG) - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; } if (mystique->type >= MGA_1064SG) { /*Mystique and later, unlike most SVGA cards, allows display start to take effect mid-screen*/ if (!(mystique->type >= MGA_2164W)) - svga->ma_latch <<= 1; - /* Only change maback so the new display start will take effect on the next + svga->memaddr_latch <<= 1; + /* Only change memaddr_backup so the new display start will take effect on the next horizontal retrace. */ - if (svga->ma_latch != mystique->ma_latch_old) { + if (svga->memaddr_latch != mystique->ma_latch_old) { if (svga->interlace && svga->oddeven) - svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + - (svga->ma_latch << 2) + (svga->rowoffset << 1); + svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) + + (svga->memaddr_latch << 2) + (svga->rowoffset << 1); else - svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + - (svga->ma_latch << 2); - mystique->ma_latch_old = svga->ma_latch; + svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) + + (svga->memaddr_latch << 2); + mystique->ma_latch_old = svga->memaddr_latch; } if (!(mystique->type >= MGA_2164W)) diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index ce44ef890..70bac6425 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -124,7 +124,7 @@ oti_out(uint16_t addr, uint8_t val, void *priv) if ((idx < 0x0e) || (idx > 0x10)) { if (idx == 0x0c || idx == 0x0d) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -393,9 +393,9 @@ oti_recalctimings(svga_t *svga) if (oti->chip_id > 0) { if (oti->regs[0x14] & 0x08) - svga->ma_latch |= 0x10000; + svga->memaddr_latch |= 0x10000; if (oti->regs[0x16] & 0x08) - svga->ma_latch |= 0x20000; + svga->memaddr_latch |= 0x20000; if (oti->regs[0x14] & 0x01) svga->vtotal += 0x400; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index da8bb9aa6..a9b0c65a5 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -245,7 +245,7 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index 9d1e3453e..c02275f09 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -299,7 +299,7 @@ static void vid_poll(void *priv) { pcjr_t *pcjr = (pcjr_t *) priv; - uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; int drawcursor; int x; int xs_temp; @@ -309,7 +309,7 @@ vid_poll(void *priv) uint8_t attr; uint16_t dat; int cols[4]; - int oldsc; + int scanline_old; int l = (pcjr->displine << 1) + 16; int ho_s = vid_get_h_overscan_size(pcjr); int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2); @@ -318,9 +318,9 @@ vid_poll(void *priv) timer_advance_u64(&pcjr->timer, pcjr->dispofftime); pcjr->stat &= ~1; pcjr->linepos = 1; - oldsc = pcjr->sc; + scanline_old = pcjr->scanline; if ((pcjr->crtc[8] & 3) == 3) - pcjr->sc = (pcjr->sc << 1) & 7; + pcjr->scanline = (pcjr->scanline << 1) & 7; if (pcjr->dispon) { uint16_t offset = 0; uint16_t mask = 0x1fff; @@ -346,10 +346,10 @@ vid_poll(void *priv) mask = 0x3fff; break; case 1: /*Low resolution graphics*/ - offset = (pcjr->sc & 1) * 0x2000; + offset = (pcjr->scanline & 1) * 0x2000; break; case 3: /*High resolution graphics*/ - offset = (pcjr->sc & 3) * 0x2000; + offset = (pcjr->scanline & 3) * 0x2000; break; default: break; @@ -358,9 +358,9 @@ vid_poll(void *priv) case 0x13: /*320x200x16*/ for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 3) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; + pcjr->memaddr++; buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; @@ -378,9 +378,9 @@ vid_poll(void *priv) case 0x12: /*160x200x16*/ for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 4) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; + pcjr->memaddr++; buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = @@ -406,9 +406,9 @@ vid_poll(void *priv) case 0x03: /*640x200x4*/ for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 3) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - pcjr->ma++; + dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1] << 8) | + pcjr->vram[((pcjr->memaddr << 1) & mask) + offset]; + pcjr->memaddr++; for (uint8_t c = 0; c < 8; c++) { chr = (dat >> 7) & 1; chr |= ((dat >> 14) & 2); @@ -421,9 +421,9 @@ vid_poll(void *priv) case 0x01: /*80 column text*/ for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 3) + ho_d; - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->cursorvisible && pcjr->cursoron); + chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset]; + attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; + drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron); if (pcjr->array[3] & 4) { cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; @@ -433,7 +433,7 @@ vid_poll(void *priv) cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; } - if (pcjr->sc & 8) + if (pcjr->scanline & 8) for (uint8_t c = 0; c < 8; c++) buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = cols[0]; @@ -441,21 +441,21 @@ vid_poll(void *priv) for (uint8_t c = 0; c < 8; c++) buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = - cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; if (drawcursor) for (uint8_t c = 0; c < 8; c++) { buffer32->line[l][ef_x + c] ^= 15; buffer32->line[l + 1][ef_x + c] ^= 15; } - pcjr->ma++; + pcjr->memaddr++; } break; case 0x00: /*40 column text*/ for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 4) + ho_d; - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->cursorvisible && pcjr->cursoron); + chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset]; + attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; + drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron); if (pcjr->array[3] & 4) { cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; @@ -465,8 +465,8 @@ vid_poll(void *priv) cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; } - pcjr->ma++; - if (pcjr->sc & 8) + pcjr->memaddr++; + if (pcjr->scanline & 8) for (uint8_t c = 0; c < 8; c++) buffer32->line[l][ef_x + (c << 1)] = buffer32->line[l][ef_x + (c << 1) + 1] = @@ -478,7 +478,7 @@ vid_poll(void *priv) buffer32->line[l][ef_x + (c << 1) + 1] = buffer32->line[l + 1][ef_x + (c << 1)] = buffer32->line[l + 1][ef_x + (c << 1) + 1] = - cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; if (drawcursor) for (uint8_t c = 0; c < 16; c++) { buffer32->line[l][ef_x + c] ^= 15; @@ -493,9 +493,9 @@ vid_poll(void *priv) cols[3] = pcjr->array[3 + 16] + 16; for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 4) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; + pcjr->memaddr++; for (uint8_t c = 0; c < 8; c++) { buffer32->line[l][ef_x + (c << 1)] = buffer32->line[l][ef_x + (c << 1) + 1] = @@ -510,9 +510,9 @@ vid_poll(void *priv) cols[1] = pcjr->array[1 + 16] + 16; for (x = 0; x < pcjr->crtc[1]; x++) { int ef_x = (x << 4) + ho_d; - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; + pcjr->memaddr++; for (uint8_t c = 0; c < 16; c++) { buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = cols[dat >> 15]; @@ -555,8 +555,8 @@ vid_poll(void *priv) video_process_8(x, l); video_process_8(x, l + 1); } - pcjr->sc = oldsc; - if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { + pcjr->scanline = scanline_old; + if (pcjr->vc == pcjr->crtc[7] && !pcjr->scanline) { pcjr->stat |= 8; } pcjr->displine++; @@ -573,22 +573,22 @@ vid_poll(void *priv) pcjr->stat &= ~8; } } - if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { + if (pcjr->scanline == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == ((pcjr->crtc[11] & 31) >> 1))) { pcjr->cursorvisible = 0; } if (pcjr->vadj) { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; + pcjr->scanline++; + pcjr->scanline &= 31; + pcjr->memaddr = pcjr->memaddr_backup; pcjr->vadj--; if (!pcjr->vadj) { pcjr->dispon = 1; - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - pcjr->sc = 0; + pcjr->memaddr = pcjr->memaddr_backup = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; + pcjr->scanline = 0; } - } else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) { - pcjr->maback = pcjr->ma; - pcjr->sc = 0; + } else if (pcjr->scanline == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == (pcjr->crtc[9] >> 1))) { + pcjr->memaddr_backup = pcjr->memaddr; + pcjr->scanline = 0; oldvc = pcjr->vc; pcjr->vc++; pcjr->vc &= 127; @@ -600,7 +600,7 @@ vid_poll(void *priv) if (!pcjr->vadj) pcjr->dispon = 1; if (!pcjr->vadj) - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; + pcjr->memaddr = pcjr->memaddr_backup = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; if ((pcjr->crtc[10] & 0x60) == 0x20) pcjr->cursoron = 0; else @@ -664,11 +664,11 @@ vid_poll(void *priv) pcjr->blink++; } } else { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; + pcjr->scanline++; + pcjr->scanline &= 31; + pcjr->memaddr = pcjr->memaddr_backup; } - if (pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1))) + if (pcjr->scanline == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == ((pcjr->crtc[10] & 31) >> 1))) pcjr->cursorvisible = 1; } } diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 5cb35dc4e..63126955c 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2342,23 +2342,23 @@ pgc_cga_text(pgc_t *dev, int w) int drawcursor = 0; uint32_t cols[2]; int pitch = (dev->mapram[0x3e9] + 1) * 2; - uint16_t sc = (dev->displine & 0x0f) % pitch; - uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; - uint16_t ca = (dev->mapram[0x3ef] | (dev->mapram[0x3ee] << 8)) & 0x3fff; + uint16_t scanline = (dev->displine & 0x0f) % pitch; + uint16_t memaddr = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; + uint16_t cursoraddr = (dev->mapram[0x3ef] | (dev->mapram[0x3ee] << 8)) & 0x3fff; const uint8_t *addr; uint32_t val; int cw = (w == 80) ? 8 : 16; - addr = &dev->cga_vram[((ma + ((dev->displine / pitch) * w)) * 2) & 0x3ffe]; - ma += (dev->displine / pitch) * w; + addr = &dev->cga_vram[((memaddr + ((dev->displine / pitch) * w)) * 2) & 0x3ffe]; + memaddr += (dev->displine / pitch) * w; for (int x = 0; x < w; x++) { chr = *addr++; attr = *addr++; /* Cursor enabled? */ - if (ma == ca && (dev->cgablink & 8) && (dev->mapram[0x3ea] & 0x60) != 0x20) { - drawcursor = ((dev->mapram[0x3ea] & 0x1f) <= (sc >> 1)) && ((dev->mapram[0x3eb] & 0x1f) >= (sc >> 1)); + if (memaddr == cursoraddr && (dev->cgablink & 8) && (dev->mapram[0x3ea] & 0x60) != 0x20) { + drawcursor = ((dev->mapram[0x3ea] & 0x1f) <= (scanline >> 1)) && ((dev->mapram[0x3eb] & 0x1f) >= (scanline >> 1)); } else drawcursor = 0; @@ -2374,9 +2374,9 @@ pgc_cga_text(pgc_t *dev, int w) for (int c = 0; c < cw; c++) { if (drawcursor) - val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; + val = cols[(fontdatm[chr + dev->fontbase][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; else - val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + val = cols[(fontdatm[chr + dev->fontbase][scanline] & (1 << (c ^ 7))) ? 1 : 0]; if (cw == 8) /* 80x25 CGA text screen. */ buffer32->line[dev->displine][(x * cw) + c] = val; else { /* 40x25 CGA text screen. */ @@ -2385,7 +2385,7 @@ pgc_cga_text(pgc_t *dev, int w) } } - ma++; + memaddr++; } } @@ -2395,7 +2395,7 @@ pgc_cga_gfx40(pgc_t *dev) { uint32_t cols[4]; int col; - uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; + uint16_t memaddr = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; const uint8_t *addr; uint16_t dat; @@ -2422,9 +2422,9 @@ pgc_cga_gfx40(pgc_t *dev) } for (uint8_t x = 0; x < 40; x++) { - addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; + addr = &dev->cga_vram[(memaddr + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; dat = (addr[0] << 8) | addr[1]; - dev->ma++; + dev->memaddr++; for (uint8_t c = 0; c < 8; c++) { buffer32->line[dev->displine][(x << 4) + (c << 1)] = buffer32->line[dev->displine][(x << 4) + (c << 1) + 1] = cols[dat >> 14]; dat <<= 2; @@ -2437,7 +2437,7 @@ void pgc_cga_gfx80(pgc_t *dev) { uint32_t cols[2]; - uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; + uint16_t memaddr = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; const uint8_t *addr; uint16_t dat; @@ -2445,9 +2445,9 @@ pgc_cga_gfx80(pgc_t *dev) cols[1] = (dev->mapram[0x3d9] & 15) + 16; for (uint8_t x = 0; x < 40; x++) { - addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; + addr = &dev->cga_vram[(memaddr + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; dat = (addr[0] << 8) | addr[1]; - dev->ma++; + dev->memaddr++; for (uint8_t c = 0; c < 16; c++) { buffer32->line[dev->displine][(x << 4) + c] = cols[dat >> 15]; dat <<= 1; diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 4b9c8064a..f6a530702 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -349,7 +349,7 @@ typedef struct da2_t { int lowres; int rowcount; double clock; - uint32_t ma_latch, ca_adj; + uint32_t memaddr_latch, ca_adj; uint64_t dispontime, dispofftime; pc_timer_t timer; @@ -358,9 +358,9 @@ typedef struct da2_t { int dispon; int hdisp_on; - uint32_t ma, maback, ca; + uint32_t memaddr, memaddr_backup, cursoraddr; int vc; - int sc; + int scanline; int linepos, vslines, linecountff; int cursorvisible, cursoron, blink, blinkconf; int scrollcache; @@ -1960,10 +1960,10 @@ da2_render_text(da2_t *da2) 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); + // da2_log("\nda2ma: %x, da2sc: %x\n", da2->memaddr, da2->scanline); 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]; + chr = da2->cram[(da2->memaddr) & DA2_MASK_CRAM]; + attr = da2->cram[(da2->memaddr + 1) & DA2_MASK_CRAM]; // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); if (colormode) /* IO 3E8h, Index 1Dh */ { /* --Parse attribute byte in color mode-- */ @@ -2003,11 +2003,11 @@ da2_render_text(da2_t *da2) /* Stay drawing If the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->cram[(da2->ma + 2) & DA2_MASK_CRAM]; + chr_dbcs = da2->cram[(da2->memaddr + 2) & DA2_MASK_CRAM]; chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; @@ -2020,10 +2020,10 @@ da2_render_text(da2_t *da2) fontbase = DA2_GAIJIRAM_SBEX; else fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->scanline * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ - // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->scanline * 2 + 1]; /* w13xh29 font */ + // if(chr!=0x20) da2_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", da2->memaddr, da2->scanline, chr, font); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2033,7 +2033,7 @@ da2_render_text(da2_t *da2) } /* right half of DBCS */ else { - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2042,7 +2042,7 @@ 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 == da2->crtc[LC_UNDERLINE_LOCATION] && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ + if (da2->scanline == 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) */ } @@ -2050,13 +2050,13 @@ da2_render_text(da2_t *da2) if (attr & 0x10) { 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 */ + if (da2->scanline == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */ for (uint32_t n = 0; n < 13; n++) 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->cursorvisible && da2->cursoron); - if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { + drawcursor = ((da2->memaddr == da2->cursoraddr) && da2->cursorvisible && da2->cursoron); + if (drawcursor && da2->scanline >= da2->crtc[LC_CURSOR_ROW_START] && da2->scanline <= da2->crtc[LC_CURSOR_ROW_END]) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); 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); @@ -2071,10 +2071,10 @@ da2_render_text(da2_t *da2) else p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; } - da2->ma += 2; + da2->memaddr += 2; p += 13; } - // da2->ma &= DA2_MASK_CRAM; + // da2->memaddr &= DA2_MASK_CRAM; // da2->writelines++; } } @@ -2096,12 +2096,12 @@ da2_render_textm3(da2_t *da2) int fg, bg; uint32_t chr_dbcs; int chr_wide = 0; - // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + // da2_log("\nda2ma: %x, da2sc: %x\n", da2->memaddr, da2->scanline); for (x = 0; x < da2->hdisp; x += 13) { - chr = da2_vram_r(DA2_VM03_BASECHR + da2->ma, da2); - attr = da2_vram_r(DA2_VM03_BASECHR + da2->ma + 1, da2); - extattr = da2_vram_r(DA2_VM03_BASEEXATTR + da2->ma + 1, da2); - // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); + chr = da2_vram_r(DA2_VM03_BASECHR + da2->memaddr, da2); + attr = da2_vram_r(DA2_VM03_BASECHR + da2->memaddr + 1, da2); + extattr = da2_vram_r(DA2_VM03_BASEEXATTR + da2->memaddr + 1, da2); + // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->memaddr << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; // fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; @@ -2118,11 +2118,11 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2_vram_r(DA2_VM03_BASECHR + da2->ma + 2, da2); + chr_dbcs = da2_vram_r(DA2_VM03_BASECHR + da2->memaddr + 2, da2); chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; @@ -2135,10 +2135,10 @@ da2_render_textm3(da2_t *da2) fontbase = DA2_GAIJIRAM_SBEX; else fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase+ chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ + uint16_t font = da2->mmio.ram[fontbase+ chr * 0x40 + da2->scanline * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ - // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->scanline * 2 + 1]; /* w13xh29 font */ + // if(chr!=0x20) da2_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", da2->memaddr, da2->scanline, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; @@ -2147,7 +2147,7 @@ da2_render_textm3(da2_t *da2) } /* right half of DBCS */ else { - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2155,8 +2155,8 @@ da2_render_textm3(da2_t *da2) } chr_wide = 0; } - drawcursor = ((da2->ma == da2->ca) && da2->cursorvisible && da2->cursoron); - if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { + drawcursor = ((da2->memaddr == da2->cursoraddr) && da2->cursorvisible && da2->cursoron); + if (drawcursor && da2->scanline >= da2->crtc[LC_CURSOR_ROW_START] && da2->scanline <= da2->crtc[LC_CURSOR_ROW_END]) { // int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); // int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ // fg = (colormode) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; @@ -2168,10 +2168,10 @@ da2_render_textm3(da2_t *da2) for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[fg]]; } - da2->ma += 2; + da2->memaddr += 2; p += 13; } - // da2->ma &= DA2_MASK_CRAM; + // da2->memaddr &= DA2_MASK_CRAM; // da2->writelines++; } } @@ -2179,8 +2179,8 @@ da2_render_textm3(da2_t *da2) static void da2_render_color_4bpp(da2_t *da2) { - int changed_offset = da2->ma >> 9; - // da2_log("ma %x cf %x\n", da2->ma, changed_offset); + int changed_offset = da2->memaddr >> 9; + // da2_log("memaddr %x cf %x\n", da2->memaddr, changed_offset); da2->plane_mask &= 0x0f; /*safety */ if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { @@ -2191,7 +2191,7 @@ da2_render_color_4bpp(da2_t *da2) if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - // da2_log("d %X\n", da2->ma); + // da2_log("d %X\n", da2->memaddr); for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ { @@ -2199,9 +2199,9 @@ da2_render_color_4bpp(da2_t *da2) uint8_t dat; /* get 8 pixels from vram */ - da2->ma &= da2->vram_display_mask; - *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]); - da2->ma += 1; + da2->memaddr &= da2->vram_display_mask; + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->memaddr << 3]); + da2->memaddr += 1; dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; @@ -2228,8 +2228,8 @@ da2_render_color_4bpp(da2_t *da2) static void da2_render_color_8bpp(da2_t *da2) { - int changed_offset = da2->ma >> 9; - // da2_log("ma %x cf %x\n", da2->ma, changed_offset); + int changed_offset = da2->memaddr >> 9; + // da2_log("memaddr %x cf %x\n", da2->memaddr, changed_offset); if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { int x; @@ -2239,7 +2239,7 @@ da2_render_color_8bpp(da2_t *da2) if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - // da2_log("d %X\n", da2->ma); + // da2_log("d %X\n", da2->memaddr); for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ { @@ -2247,10 +2247,10 @@ da2_render_color_8bpp(da2_t *da2) uint8_t dat; /* get 8 pixels from vram */ - da2->ma &= da2->vram_display_mask; - *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]); - *(uint32_t *) (&edat[4]) = *(uint32_t *) (&da2->vram[(da2->ma << 3) + 4]); - da2->ma += 1; + da2->memaddr &= da2->vram_display_mask; + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->memaddr << 3]); + *(uint32_t *) (&edat[4]) = *(uint32_t *) (&da2->vram[(da2->memaddr << 3) + 4]); + da2->memaddr += 1; dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); p[0] = da2->pallook[dat]; @@ -2343,9 +2343,9 @@ da2_recalctimings(da2_t *da2) if (da2->rowoffset == 0) da2->rowoffset = 64 * 2; /* To avoid causing a DBZ error */ if (da2->split == 0) /* To avoid a glitch in MODE 1 of OS/2 J1.3 DOSBox. */ - da2->ma_latch = 0; + da2->memaddr_latch = 0; else - da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; + da2->memaddr_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; da2->ca_adj = 0; da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; @@ -3022,7 +3022,7 @@ da2_poll(void *priv) if (da2->dispon) { da2->hdisp_on = 1; - da2->ma &= da2->vram_display_mask; + da2->memaddr &= da2->vram_display_mask; if (da2->firstline == 2000) { da2->firstline = da2->displine; video_wait_for_buffer(); @@ -3035,7 +3035,7 @@ da2_poll(void *priv) da2->lastline = da2->displine; } - // da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + // da2_log("%03i %06X %06X\n", da2->displine, da2->memaddr,da2->vram_display_mask); da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { // da2_log("Vsync off at line %i\n",displine); @@ -3045,9 +3045,9 @@ da2_poll(void *priv) if (da2->displine > 1200) da2->displine = 0; // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - // displine, vc, ma); + // displine, vc, memaddr); } else { - // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + // da2_log("VC %i memaddr %05X\n", da2->vc, da2->memaddr); timer_advance_u64(&da2->timer, da2->dispontime); if (da2->dispon) @@ -3055,20 +3055,20 @@ da2_poll(void *priv) da2->hdisp_on = 0; da2->linepos = 0; - if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) + if (da2->scanline == (da2->crtc[LC_CURSOR_ROW_END] & 31)) da2->cursorvisible = 0; if (da2->dispon) { - if (da2->sc == da2->rowcount) { + if (da2->scanline == da2->rowcount) { da2->linecountff = 0; - da2->sc = 0; + da2->scanline = 0; - da2->maback += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */ - da2->maback &= da2->vram_display_mask; - da2->ma = da2->maback; + da2->memaddr_backup += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */ + da2->memaddr_backup &= da2->vram_display_mask; + da2->memaddr = da2->memaddr_backup; } else { - da2->sc++; - da2->sc &= 31; - da2->ma = da2->maback; + da2->scanline++; + da2->scanline &= 31; + da2->memaddr = da2->memaddr_backup; } } @@ -3076,9 +3076,9 @@ da2_poll(void *priv) da2->vc &= 2047; if (da2->vc == da2->split) { - // da2->ma = da2->maback = da2->hblank_sub; - da2->ma = da2->maback = 0; - da2->sc = 0; + // da2->memaddr = da2->memaddr_backup = da2->hblank_sub; + da2->memaddr = da2->memaddr_backup = 0; + da2->scanline = 0; // da2->displine = 0; } @@ -3128,23 +3128,23 @@ da2_poll(void *priv) changeframecount = 2; da2->vslines = 0; - da2->ma - = da2->maback = da2->ma_latch << 1; - da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; - da2->ca <<= 1; + da2->memaddr + = da2->memaddr_backup = da2->memaddr_latch << 1; + da2->cursoraddr = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; + da2->cursoraddr <<= 1; - // da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF); + // da2_log("Addr %08X vson %03X vsoff %01X\n",da2->memaddr,da2->vsyncstart,da2->crtc[0x11]&0xF); } if (da2->vc == da2->vtotal) { // da2_log("VC vtotal\n"); // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); da2->vc = 0; - da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->scanline = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; da2->displine = 0; da2->scrollcache = da2->attrc[LV_PANNING] & 7; } - if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) + if (da2->scanline == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->cursorvisible = 1; } } @@ -3231,7 +3231,7 @@ da2_reset(void *priv) da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->ma_latch = 0; + da2->memaddr_latch = 0; da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index ae9475d96..813d30bf3 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -180,7 +180,7 @@ rtg_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -211,7 +211,7 @@ rtg_recalctimings(svga_t *svga) { const rtg_t *dev = (rtg_t *) svga->priv; - svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); + svga->memaddr_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); svga->interlace = (svga->crtc[0x19] & 1); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 99521f061..d0495dca0 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3179,9 +3179,9 @@ s3_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); if ((((svga->crtc[0x67] & 0xc) != 0xc) && (s3->chip >= S3_TRIO64V)) || (s3->chip < S3_TRIO64V)) - svga->ma_latch |= (s3->ma_ext << 16); + svga->memaddr_latch |= (s3->ma_ext << 16); } else { svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); @@ -3503,7 +3503,7 @@ s3_recalctimings(svga_t *svga) } svga->hdisp = svga->hdisp_old; - svga->ma_latch |= (s3->ma_ext << 16); + svga->memaddr_latch |= (s3->ma_ext << 16); svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); @@ -4379,7 +4379,7 @@ s3_trio64v_recalctimings(svga_t *svga) if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { - svga->ma_latch |= (s3->ma_ext << 16); + svga->memaddr_latch |= (s3->ma_ext << 16); if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) @@ -4427,9 +4427,9 @@ s3_trio64v_recalctimings(svga_t *svga) } else /*Streams mode*/ { if (s3->streams.buffer_ctrl & 1) - svga->ma_latch = s3->streams.pri_fb1 >> 2; + svga->memaddr_latch = s3->streams.pri_fb1 >> 2; else - svga->ma_latch = s3->streams.pri_fb0 >> 2; + svga->memaddr_latch = s3->streams.pri_fb0 >> 2; svga->hdisp = s3->streams.pri_w + 1; if (s3->streams.pri_h < svga->dispend) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 1b61c02d5..9422f69bf 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -688,10 +688,10 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); if ((svga->crtc[0x67] & 0xc) != 0xc) - svga->ma_latch |= (virge->ma_ext << 16); + svga->memaddr_latch |= (virge->ma_ext << 16); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -890,7 +890,7 @@ s3_virge_recalctimings(svga_t *svga) } if ((svga->crtc[0x67] & 0xc) != 0xc) { /*VGA mode*/ - svga->ma_latch |= (virge->ma_ext << 16); + svga->memaddr_latch |= (virge->ma_ext << 16); if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) @@ -935,9 +935,9 @@ s3_virge_recalctimings(svga_t *svga) } else { /*Streams mode*/ if (virge->chip < S3_VIRGEGX2) { if (virge->streams.buffer_ctrl & 1) - svga->ma_latch = virge->streams.pri_fb1 >> 2; + svga->memaddr_latch = virge->streams.pri_fb1 >> 2; else - svga->ma_latch = virge->streams.pri_fb0 >> 2; + svga->memaddr_latch = virge->streams.pri_fb0 >> 2; svga->hdisp = virge->streams.pri_w + 1; if (virge->streams.pri_h < svga->dispend) @@ -946,7 +946,7 @@ s3_virge_recalctimings(svga_t *svga) svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; } else { - svga->ma_latch |= (virge->ma_ext << 16); + svga->memaddr_latch |= (virge->ma_ext << 16); if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 9a5d184f9..6be21ce69 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -151,12 +151,12 @@ typedef struct sigma_t { uint8_t sigmamode; /* Mode control register [0x2D8] */ - uint16_t ma, maback; + uint16_t memaddr, memaddr_backup; int crtcreg; /* CRTC: Real selected register */ int linepos, displine; - int sc, vc; + int scanline, vc; int cgadispon; int cursorvisible, cursoron, cgablink; int vsynctime, vadj; @@ -414,23 +414,23 @@ sigma_text80(sigma_t *sigma) { uint8_t chr; uint8_t attr; - uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8)); - uint16_t ma = ((sigma->ma & 0x3FFF) << 1); + uint16_t cursoraddr = (sigma->crtc[15] | (sigma->crtc[14] << 8)); + uint16_t memaddr = ((sigma->memaddr & 0x3FFF) << 1); int drawcursor; uint32_t cols[4]; - const uint8_t *vram = sigma->vram + (ma << 1); + const uint8_t *vram = sigma->vram + (memaddr << 1); - ca = ca << 1; + cursoraddr = cursoraddr << 1; if (sigma->sigma_ctl & CTL_CURSOR) - ++ca; - ca &= 0x3fff; + ++cursoraddr; + cursoraddr &= 0x3fff; /* The Sigma 400 seems to use screen widths stated in words (40 for 80-column, 20 for 40-column) */ for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { chr = vram[x << 1]; attr = vram[(x << 1) + 1]; - drawcursor = ((ma == ca) && sigma->cursorvisible && sigma->cursoron); + drawcursor = ((memaddr == cursoraddr) && sigma->cursorvisible && sigma->cursoron); if (!(sigma->sigmamode & MODE_NOBLINK)) { cols[1] = (attr & 15) | 16; @@ -445,22 +445,22 @@ sigma_text80(sigma_t *sigma) if (drawcursor) { for (uint8_t c = 0; c < 8; c++) { if (sigma->sigmamode & MODE_FONT16) - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; else - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; } } else { for (uint8_t c = 0; c < 8; c++) { if (sigma->sigmamode & MODE_FONT16) - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0]; else - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } - ++ma; + ++memaddr; } - sigma->ma += sigma->crtc[1]; + sigma->memaddr += sigma->crtc[1]; } /* Render a line in 40-column text mode */ @@ -469,23 +469,23 @@ sigma_text40(sigma_t *sigma) { uint8_t chr; uint8_t attr; - uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8)); - uint16_t ma = ((sigma->ma & 0x3FFF) << 1); + uint16_t cursoraddr = (sigma->crtc[15] | (sigma->crtc[14] << 8)); + uint16_t memaddr = ((sigma->memaddr & 0x3FFF) << 1); int drawcursor; uint32_t cols[4]; - const uint8_t *vram = sigma->vram + ((ma << 1) & 0x3FFF); + const uint8_t *vram = sigma->vram + ((memaddr << 1) & 0x3FFF); - ca = ca << 1; + cursoraddr = cursoraddr << 1; if (sigma->sigma_ctl & CTL_CURSOR) - ++ca; - ca &= 0x3fff; + ++cursoraddr; + cursoraddr &= 0x3fff; /* The Sigma 400 seems to use screen widths stated in words (40 for 80-column, 20 for 40-column) */ for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { chr = vram[x << 1]; attr = vram[(x << 1) + 1]; - drawcursor = ((ma == ca) && sigma->cursorvisible && sigma->cursoron); + drawcursor = ((memaddr == cursoraddr) && sigma->cursorvisible && sigma->cursoron); if (!(sigma->sigmamode & MODE_NOBLINK)) { cols[1] = (attr & 15) | 16; @@ -499,24 +499,24 @@ sigma_text40(sigma_t *sigma) if (drawcursor) { for (uint8_t c = 0; c < 8; c++) { - buffer32->line[sigma->displine][(x << 4) + 2 * c + 8] = buffer32->line[sigma->displine][(x << 4) + 2 * c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; + buffer32->line[sigma->displine][(x << 4) + 2 * c + 8] = buffer32->line[sigma->displine][(x << 4) + 2 * c + 9] = cols[(fontdatm[chr][sigma->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; } } else { for (uint8_t c = 0; c < 8; c++) { - buffer32->line[sigma->displine][(x << 4) + 2 * c + 8] = buffer32->line[sigma->displine][(x << 4) + 2 * c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[sigma->displine][(x << 4) + 2 * c + 8] = buffer32->line[sigma->displine][(x << 4) + 2 * c + 9] = cols[(fontdatm[chr][sigma->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0]; } } - ma++; + memaddr++; } - sigma->ma += sigma->crtc[1]; + sigma->memaddr += sigma->crtc[1]; } /* Draw a line in the 640x400 graphics mode */ static void sigma_gfx400(sigma_t *sigma) { - const uint8_t *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + (sigma->sc & 3) * 0x2000]; + const uint8_t *vram = &sigma->vram[((sigma->memaddr << 1) & 0x1FFF) + (sigma->scanline & 3) * 0x2000]; uint8_t plane[4]; uint8_t col; @@ -532,7 +532,7 @@ sigma_gfx400(sigma_t *sigma) buffer32->line[sigma->displine][(x << 3) + c + 8] = col; } if (x & 1) - ++sigma->ma; + ++sigma->memaddr; } } @@ -544,7 +544,7 @@ sigma_gfx400(sigma_t *sigma) static void sigma_gfx200(sigma_t *sigma) { - const uint8_t *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + (sigma->sc & 2) * 0x1000]; + const uint8_t *vram = &sigma->vram[((sigma->memaddr << 1) & 0x1FFF) + (sigma->scanline & 2) * 0x1000]; uint8_t plane[4]; uint8_t col; @@ -561,7 +561,7 @@ sigma_gfx200(sigma_t *sigma) } if (x & 1) - ++sigma->ma; + ++sigma->memaddr; } } @@ -569,7 +569,7 @@ sigma_gfx200(sigma_t *sigma) static void sigma_gfx4col(sigma_t *sigma) { - const uint8_t *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + (sigma->sc & 2) * 0x1000]; + const uint8_t *vram = &sigma->vram[((sigma->memaddr << 1) & 0x1FFF) + (sigma->scanline & 2) * 0x1000]; uint8_t plane[4]; uint8_t mask; uint8_t col; @@ -592,7 +592,7 @@ sigma_gfx4col(sigma_t *sigma) } if (x & 1) - ++sigma->ma; + ++sigma->memaddr; } } @@ -604,15 +604,15 @@ sigma_poll(void *priv) int c; int oldvc; uint32_t cols[4]; - int oldsc; + int scanline_old; if (!sigma->linepos) { timer_advance_u64(&sigma->timer, sigma->dispofftime); sigma->sigmastat |= STATUS_RETR_H; sigma->linepos = 1; - oldsc = sigma->sc; + scanline_old = sigma->scanline; if ((sigma->crtc[8] & 3) == 3) - sigma->sc = ((sigma->sc << 1) + sigma->oddeven) & 7; + sigma->scanline = ((sigma->scanline << 1) + sigma->oddeven) & 7; if (sigma->cgadispon) { if (sigma->displine < sigma->firstline) { sigma->firstline = sigma->displine; @@ -660,8 +660,8 @@ sigma_poll(void *priv) video_process_8(x, sigma->displine); - sigma->sc = oldsc; - if (sigma->vc == sigma->crtc[7] && !sigma->sc) + sigma->scanline = scanline_old; + if (sigma->vc == sigma->crtc[7] && !sigma->scanline) sigma->sigmastat |= STATUS_RETR_V; sigma->displine++; if (sigma->displine >= 560) @@ -674,24 +674,24 @@ sigma_poll(void *priv) if (!sigma->vsynctime) sigma->sigmastat &= ~STATUS_RETR_V; } - if (sigma->sc == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1))) { + if (sigma->scanline == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->scanline == ((sigma->crtc[11] & 31) >> 1))) { sigma->cursorvisible = 0; } - if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1)) - sigma->maback = sigma->ma; + if ((sigma->crtc[8] & 3) == 3 && sigma->scanline == (sigma->crtc[9] >> 1)) + sigma->memaddr_backup = sigma->memaddr; if (sigma->vadj) { - sigma->sc++; - sigma->sc &= 31; - sigma->ma = sigma->maback; + sigma->scanline++; + sigma->scanline &= 31; + sigma->memaddr = sigma->memaddr_backup; sigma->vadj--; if (!sigma->vadj) { sigma->cgadispon = 1; - sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; - sigma->sc = 0; + sigma->memaddr = sigma->memaddr_backup = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; + sigma->scanline = 0; } - } else if (sigma->sc == sigma->crtc[9]) { - sigma->maback = sigma->ma; - sigma->sc = 0; + } else if (sigma->scanline == sigma->crtc[9]) { + sigma->memaddr_backup = sigma->memaddr; + sigma->scanline = 0; oldvc = sigma->vc; sigma->vc++; sigma->vc &= 127; @@ -705,7 +705,7 @@ sigma_poll(void *priv) if (!sigma->vadj) sigma->cgadispon = 1; if (!sigma->vadj) - sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; + sigma->memaddr = sigma->memaddr_backup = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; if ((sigma->crtc[10] & 0x60) == 0x20) sigma->cursoron = 0; else @@ -768,13 +768,13 @@ sigma_poll(void *priv) sigma->oddeven ^= 1; } } else { - sigma->sc++; - sigma->sc &= 31; - sigma->ma = sigma->maback; + sigma->scanline++; + sigma->scanline &= 31; + sigma->memaddr = sigma->memaddr_backup; } if (sigma->cgadispon) sigma->sigmastat &= ~STATUS_RETR_H; - if (sigma->sc == (sigma->crtc[10] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[10] & 31) >> 1))) + if (sigma->scanline == (sigma->crtc[10] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->scanline == ((sigma->crtc[10] & 31) >> 1))) sigma->cursorvisible = 1; } } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 6290832df..449a7bd43 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -754,7 +754,7 @@ svga_recalctimings(svga_t *svga) svga->interlace = 0; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); svga->ca_adj = 0; svga->rowcount = svga->crtc[9] & 0x1f; @@ -1283,17 +1283,17 @@ svga_poll(void *priv) if (svga->dispon) { svga->hdisp_on = 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; if (svga->firstline == 2000) { svga->firstline = svga->displine; video_wait_for_buffer_monitor(svga->monitor_index); } if (svga->hwcursor_on || svga->dac_hwcursor_on || svga->overlay_on) - svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = svga->interlace ? 3 : 2; + svga->changedvram[svga->memaddr >> 12] = svga->changedvram[(svga->memaddr >> 12) + 1] = svga->interlace ? 3 : 2; if (svga->vertical_linedbl) { - old_ma = svga->ma; + old_ma = svga->memaddr; svga->displine <<= 1; svga->y_add <<= 1; @@ -1302,7 +1302,7 @@ svga_poll(void *priv) svga->displine++; - svga->ma = old_ma; + svga->memaddr = old_ma; svga_do_render(svga); @@ -1331,29 +1331,29 @@ svga_poll(void *priv) svga->hdisp_on = 0; svga->linepos = 0; - if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount)) + if ((svga->scanline == (svga->crtc[11] & 31)) || (svga->scanline == svga->rowcount)) svga->cursorvisible = 0; if (svga->dispon) { /* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll - - S3 Trio64V2/DX: sc == rowcount, wrapping 5-bit counter. */ + - S3 Trio64V2/DX: scanline == rowcount, wrapping 5-bit counter. */ if (svga->linedbl && !svga->linecountff) { svga->linecountff = 1; - svga->ma = svga->maback; - } else if (svga->sc == svga->rowcount) { + svga->memaddr = svga->memaddr_backup; + } else if (svga->scanline == svga->rowcount) { svga->linecountff = 0; - svga->sc = 0; + svga->scanline = 0; - svga->maback += (svga->adv_flags & FLAG_NO_SHIFT3) ? svga->rowoffset : (svga->rowoffset << 3); + svga->memaddr_backup += (svga->adv_flags & FLAG_NO_SHIFT3) ? svga->rowoffset : (svga->rowoffset << 3); if (svga->interlace) - svga->maback += (svga->adv_flags & FLAG_NO_SHIFT3) ? svga->rowoffset : (svga->rowoffset << 3); + svga->memaddr_backup += (svga->adv_flags & FLAG_NO_SHIFT3) ? svga->rowoffset : (svga->rowoffset << 3); - svga->maback &= svga->vram_display_mask; - svga->ma = svga->maback; + svga->memaddr_backup &= svga->vram_display_mask; + svga->memaddr = svga->memaddr_backup; } else { svga->linecountff = 0; - svga->sc++; - svga->sc &= 0x1f; - svga->ma = svga->maback; + svga->scanline++; + svga->scanline &= 0x1f; + svga->memaddr = svga->memaddr_backup; } } @@ -1373,14 +1373,14 @@ svga_poll(void *priv) if (ret) { if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->rowoffset << 1) + svga->hblank_sub; + svga->memaddr = svga->memaddr_backup = (svga->rowoffset << 1) + svga->hblank_sub; else - svga->ma = svga->maback = svga->hblank_sub; + svga->memaddr = svga->memaddr_backup = svga->hblank_sub; - svga->ma = (svga->ma << 2); - svga->maback = (svga->maback << 2); + svga->memaddr = (svga->memaddr << 2); + svga->memaddr_backup = (svga->memaddr_backup << 2); - svga->sc = 0; + svga->scanline = 0; if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; svga->x_add = svga->left_overscan; @@ -1449,16 +1449,16 @@ svga_poll(void *priv) svga->vslines = 0; if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + svga->hblank_sub; + svga->memaddr = svga->memaddr_backup = svga->memaddr_latch + (svga->rowoffset << 1) + svga->hblank_sub; else - svga->ma = svga->maback = svga->ma_latch + svga->hblank_sub; + svga->memaddr = svga->memaddr_backup = svga->memaddr_latch + svga->hblank_sub; - svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj; + svga->cursoraddr = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj; if (!(svga->adv_flags & FLAG_NO_SHIFT3)) { - svga->ma = (svga->ma << 2); - svga->maback = (svga->maback << 2); + svga->memaddr = (svga->memaddr << 2); + svga->memaddr_backup = (svga->memaddr_backup << 2); } - svga->ca = (svga->ca << 2); + svga->cursoraddr = (svga->cursoraddr << 2); if (svga->vsync_callback) svga->vsync_callback(svga); @@ -1468,7 +1468,7 @@ svga_poll(void *priv) #endif if (svga->vc == svga->vtotal) { svga->vc = 0; - svga->sc = (svga->crtc[0x8] & 0x1f); + svga->scanline = (svga->crtc[0x8] & 0x1f); svga->dispon = 1; svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; @@ -1502,7 +1502,7 @@ svga_poll(void *priv) svga->overlay_on = 0; svga->overlay_latch = svga->overlay; } - if (svga->sc == (svga->crtc[10] & 31)) + if (svga->scanline == (svga->crtc[10] & 31)) svga->cursorvisible = 1; } } diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 348506e56..bdb496686 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -156,13 +156,13 @@ svga_render_text_40(svga_t *svga) for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { if (!svga->force_old_addr) - addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; + addr = svga->remap_func(svga, svga->memaddr) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron); + drawcursor = ((svga->memaddr == svga->cursoraddr) && svga->cursorvisible && svga->cursoron); if (svga->force_old_addr) { - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + chr = svga->vram[(svga->memaddr << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->memaddr << 1) + 1) & svga->vram_display_mask]; } else { chr = svga->vram[addr]; attr = svga->vram[addr + 1]; @@ -187,7 +187,7 @@ svga_render_text_40(svga_t *svga) } } - dat = svga->vram[charaddr + (svga->sc << 2)]; + dat = svga->vram[charaddr + (svga->scanline << 2)]; if (svga->seqregs[1] & 1) { for (xx = 0; xx < 16; xx += 2) p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; @@ -199,10 +199,10 @@ svga_render_text_40(svga_t *svga) else p[16] = p[17] = (dat & 1) ? fg : bg; } - svga->ma += 4; + svga->memaddr += 4; p += xinc; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } @@ -239,13 +239,13 @@ svga_render_text_80(svga_t *svga) for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { if (!svga->force_old_addr) - addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; + addr = svga->remap_func(svga, svga->memaddr) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron); + drawcursor = ((svga->memaddr == svga->cursoraddr) && svga->cursorvisible && svga->cursoron); if (svga->force_old_addr) { - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + chr = svga->vram[(svga->memaddr << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->memaddr << 1) + 1) & svga->vram_display_mask]; } else { chr = svga->vram[addr]; attr = svga->vram[addr + 1]; @@ -269,7 +269,7 @@ svga_render_text_80(svga_t *svga) } } - dat = svga->vram[charaddr + (svga->sc << 2)]; + dat = svga->vram[charaddr + (svga->scanline << 2)]; if (svga->seqregs[1] & 1) { for (xx = 0; xx < 8; xx++) p[xx] = (dat & (0x80 >> xx)) ? fg : bg; @@ -281,10 +281,10 @@ svga_render_text_80(svga_t *svga) else p[8] = (dat & 1) ? fg : bg; } - svga->ma += 4; + svga->memaddr += 4; p += xinc; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } @@ -317,8 +317,8 @@ svga_render_text_80_ksc5601(svga_t *svga) xinc = (svga->seqregs[1] & 1) ? 8 : 9; for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { - uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron); + uint32_t addr = svga->remap_func(svga, svga->memaddr) & svga->vram_display_mask; + drawcursor = ((svga->memaddr == svga->cursoraddr) && svga->cursorvisible && svga->cursoron); chr = svga->vram[addr]; nextchr = svga->vram[addr + 8]; attr = svga->vram[addr + 1]; @@ -338,7 +338,7 @@ svga_render_text_80_ksc5601(svga_t *svga) if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { if ((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->scanline]; else if (nextchr & 0x80) { if (svga->ksc5601_swap_mode == 1 && (nextchr > 0xa0 && nextchr < 0xff)) { if (chr >= 0x80 && chr < 0x99) @@ -346,7 +346,7 @@ svga_render_text_80_ksc5601(svga_t *svga) else if (chr >= 0xB0 && chr < 0xC9) chr -= 0x30; } - dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; + dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->scanline]; } else dat = 0xff; } else { @@ -356,9 +356,9 @@ svga_render_text_80_ksc5601(svga_t *svga) charaddr = svga->charseta + (chr * 128); if ((svga->ksc5601_english_font_type >> 8) == 1) - dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)].chr[((chr & 1) << 4) | svga->sc]; + dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)].chr[((chr & 1) << 4) | svga->scanline]; else - dat = svga->vram[charaddr + (svga->sc << 2)]; + dat = svga->vram[charaddr + (svga->scanline << 2)]; } if (svga->seqregs[1] & 1) { @@ -372,11 +372,11 @@ svga_render_text_80_ksc5601(svga_t *svga) else p[8] = (dat & 1) ? fg : bg; } - svga->ma += 4; + svga->memaddr += 4; p += xinc; if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->memaddr << 1) + 1) & svga->vram_display_mask]; if (drawcursor) { bg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; @@ -392,9 +392,9 @@ svga_render_text_80_ksc5601(svga_t *svga) } if ((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->scanline + 16]; else if (nextchr & 0x80) - dat = fontdatksc5601[((chr & 0x7f) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; + dat = fontdatksc5601[((chr & 0x7f) << 7) | (nextchr & 0x7F)].chr[svga->scanline + 16]; else dat = 0xff; @@ -410,12 +410,12 @@ svga_render_text_80_ksc5601(svga_t *svga) p[8] = (dat & 1) ? fg : bg; } - svga->ma += 4; + svga->memaddr += 4; p += xinc; x += xinc; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } @@ -433,7 +433,7 @@ svga_render_2bpp_s3_lowres(svga_t *svga) return; if (svga->force_old_addr) { - changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + changed_offset = ((svga->memaddr << 1) + (svga->scanline & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -443,32 +443,32 @@ svga_render_2bpp_s3_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { - addr = svga->ma; + addr = svga->memaddr; if (!(svga->crtc[0x17] & 0x40)) { addr = (addr << 1) & svga->vram_mask; addr &= ~7; - if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + if ((svga->crtc[0x17] & 0x20) && (svga->memaddr & 0x20000)) addr |= 4; - if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + if (!(svga->crtc[0x17] & 0x20) && (svga->memaddr & 0x8000)) addr |= 4; } if (!(svga->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + addr = (addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0); if (!(svga->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + addr = (addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0); dat[0] = svga->vram[addr]; dat[1] = svga->vram[addr | 0x1]; if (svga->seqregs[1] & 4) - svga->ma += 2; + svga->memaddr += 2; else - svga->ma += 4; - svga->ma &= svga->vram_mask; + svga->memaddr += 4; + svga->memaddr &= svga->vram_mask; p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3] & svga->dac_mask]; @@ -481,7 +481,7 @@ svga_render_2bpp_s3_lowres(svga_t *svga) } } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -491,16 +491,16 @@ svga_render_2bpp_s3_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat[0] = svga->vram[addr]; dat[1] = svga->vram[addr | 0x1]; if (svga->seqregs[1] & 4) - svga->ma += 2; + svga->memaddr += 2; else - svga->ma += 4; + svga->memaddr += 4; - svga->ma &= svga->vram_mask; + svga->memaddr &= svga->vram_mask; p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; @@ -531,7 +531,7 @@ svga_render_2bpp_s3_highres(svga_t *svga) return; if (svga->force_old_addr) { - changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + changed_offset = ((svga->memaddr << 1) + (svga->scanline & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -541,32 +541,32 @@ svga_render_2bpp_s3_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->ma; + addr = svga->memaddr; if (!(svga->crtc[0x17] & 0x40)) { addr = (addr << 1) & svga->vram_mask; addr &= ~7; - if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + if ((svga->crtc[0x17] & 0x20) && (svga->memaddr & 0x20000)) addr |= 4; - if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + if (!(svga->crtc[0x17] & 0x20) && (svga->memaddr & 0x8000)) addr |= 4; } if (!(svga->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + addr = (addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0); if (!(svga->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + addr = (addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0); dat[0] = svga->vram[addr]; dat[1] = svga->vram[addr | 0x1]; if (svga->seqregs[1] & 4) - svga->ma += 2; + svga->memaddr += 2; else - svga->ma += 4; - svga->ma &= svga->vram_mask; + svga->memaddr += 4; + svga->memaddr &= svga->vram_mask; p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3] & svga->dac_mask]; @@ -579,7 +579,7 @@ svga_render_2bpp_s3_highres(svga_t *svga) } } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -589,16 +589,16 @@ svga_render_2bpp_s3_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat[0] = svga->vram[addr]; dat[1] = svga->vram[addr | 0x1]; if (svga->seqregs[1] & 4) - svga->ma += 2; + svga->memaddr += 2; else - svga->ma += 4; + svga->memaddr += 4; - svga->ma &= svga->vram_mask; + svga->memaddr &= svga->vram_mask; p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; @@ -628,7 +628,7 @@ svga_render_2bpp_headland_highres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -638,7 +638,7 @@ svga_render_2bpp_headland_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); oddeven = 0; if (svga->seqregs[1] & 4) { @@ -649,8 +649,8 @@ svga_render_2bpp_headland_highres(svga_t *svga) } else { *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]); } - svga->ma += 4; - svga->ma &= svga->vram_mask; + svga->memaddr += 4; + svga->memaddr &= svga->vram_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask] & svga->dac_mask]; @@ -736,9 +736,9 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) return; if (svga->force_old_addr) - changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + changed_offset = (svga->memaddr + (svga->scanline & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; else - changed_offset = svga->remap_func(svga, svga->ma) >> 12; + changed_offset = svga->remap_func(svga, svga->memaddr) >> 12; if (!(svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)) return; @@ -755,19 +755,19 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) if (load_counter == 0) { /* Find our address */ if (svga->force_old_addr) { - addr = ((svga->ma & ~0x3) << incbypow2); + addr = ((svga->memaddr & ~0x3) << incbypow2); if (incbypow2 == 2) { - if (svga->ma & (4 << 15)) + if (svga->memaddr & (4 << 15)) addr |= 0x8; - if (svga->ma & (4 << 14)) + if (svga->memaddr & (4 << 14)) addr |= 0x4; } else if (incbypow2 == 1) { if ((svga->crtc[0x17] & 0x20)) { - if (svga->ma & (4 << 15)) + if (svga->memaddr & (4 << 15)) addr |= 0x4; } else { - if (svga->ma & (4 << 13)) + if (svga->memaddr & (4 << 13)) addr |= 0x4; } } else { @@ -775,13 +775,13 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) } if (!(svga->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + addr = (addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0); if (!(svga->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + addr = (addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0); } else if (svga->remap_required) - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); else - addr = svga->ma; + addr = svga->memaddr; addr &= svga->vram_display_mask; @@ -819,9 +819,9 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) incr_counter += 1; if (incr_counter >= incevery) { incr_counter = 0; - svga->ma += 4; + svga->memaddr += 4; /* DISCREPANCY TODO FIXME 2/4bpp used vram_mask, 8bpp used vram_display_mask --GM */ - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } uint32_t current_shift = shift_values; @@ -926,7 +926,7 @@ svga_render_8bpp_clone_highres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -934,25 +934,25 @@ svga_render_8bpp_clone_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); p[4] = svga->map8[dat & svga->dac_mask & 0xff]; p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 8; + svga->memaddr += 8; p += 8; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -963,35 +963,35 @@ svga_render_8bpp_clone_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); p[4] = svga->map8[dat & svga->dac_mask & 0xff]; p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 8; + svga->memaddr += 8; p += 8; } } else { for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 4) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 4; + svga->memaddr += 4; p += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1011,7 +1011,7 @@ svga_render_8bpp_lowres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1019,20 +1019,20 @@ svga_render_8bpp_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[0] = p[1] = svga->map8[dat & 0xff]; p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; - svga->ma += 4; + svga->memaddr += 4; p += 8; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1043,29 +1043,29 @@ svga_render_8bpp_lowres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[0] = p[1] = svga->map8[dat & svga->dac_mask & 0xff]; p[2] = p[3] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[4] = p[5] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[6] = p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 4; + svga->memaddr += 4; p += 8; } } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); p[0] = p[1] = svga->map8[dat & svga->dac_mask & 0xff]; p[2] = p[3] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[4] = p[5] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[6] = p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 4; + svga->memaddr += 4; p += 8; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1083,7 +1083,7 @@ svga_render_8bpp_highres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1091,25 +1091,25 @@ svga_render_8bpp_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); p[4] = svga->map8[dat & svga->dac_mask & 0xff]; p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 8; + svga->memaddr += 8; p += 8; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1120,35 +1120,35 @@ svga_render_8bpp_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); p[4] = svga->map8[dat & svga->dac_mask & 0xff]; p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 8; + svga->memaddr += 8; p += 8; } } else { for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 4) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; - svga->ma += 4; + svga->memaddr += 4; p += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1163,7 +1163,7 @@ svga_render_8bpp_tseng_lowres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1171,7 +1171,7 @@ svga_render_8bpp_tseng_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); p[0] = p[1] = svga->map8[dat & svga->dac_mask & 0xff]; @@ -1188,10 +1188,10 @@ svga_render_8bpp_tseng_lowres(svga_t *svga) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); p[6] = p[7] = svga->map8[dat & svga->dac_mask & 0xff]; - svga->ma += 4; + svga->memaddr += 4; p += 8; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } @@ -1204,7 +1204,7 @@ svga_render_8bpp_tseng_highres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1212,7 +1212,7 @@ svga_render_8bpp_tseng_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (int x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); p[0] = svga->map8[dat & svga->dac_mask & 0xff]; @@ -1229,7 +1229,7 @@ svga_render_8bpp_tseng_highres(svga_t *svga) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); p[3] = svga->map8[dat & svga->dac_mask & 0xff]; - dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); p[4] = svga->map8[dat & svga->dac_mask & 0xff]; @@ -1246,10 +1246,10 @@ svga_render_8bpp_tseng_highres(svga_t *svga) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); p[7] = svga->map8[dat & svga->dac_mask & 0xff]; - svga->ma += 8; + svga->memaddr += 8; p += 8; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } @@ -1266,7 +1266,7 @@ svga_render_15bpp_lowres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1274,21 +1274,21 @@ svga_render_15bpp_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); p[x << 1] = p[(x << 1) + 1] = svga->conv_16to32(svga, dat & 0xffff, 15); p[(x << 1) + 2] = p[(x << 1) + 3] = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); p[(x << 1) + 4] = p[(x << 1) + 5] = svga->conv_16to32(svga, dat & 0xffff, 15); p[(x << 1) + 6] = p[(x << 1) + 7] = svga->conv_16to32(svga, dat >> 16, 15); } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr += x << 1; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1299,28 +1299,28 @@ svga_render_15bpp_lowres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); } - svga->ma += x << 1; + svga->memaddr += x << 1; } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); - svga->ma += 4; + svga->memaddr += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1338,7 +1338,7 @@ svga_render_15bpp_highres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1346,27 +1346,27 @@ svga_render_15bpp_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); p[x] = svga->conv_16to32(svga, dat & 0xffff, 15); p[x + 1] = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); p[x + 2] = svga->conv_16to32(svga, dat & 0xffff, 15); p[x + 3] = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 8) & svga->vram_display_mask]); p[x + 4] = svga->conv_16to32(svga, dat & 0xffff, 15); p[x + 5] = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 12) & svga->vram_display_mask]); p[x + 6] = svga->conv_16to32(svga, dat & 0xffff, 15); p[x + 7] = svga->conv_16to32(svga, dat >> 16, 15); } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr += x << 1; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1377,34 +1377,34 @@ svga_render_15bpp_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 8) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 12) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); } - svga->ma += x << 1; + svga->memaddr += x << 1; } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); *p++ = svga->conv_16to32(svga, dat >> 16, 15); - svga->ma += 4; + svga->memaddr += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1419,7 +1419,7 @@ svga_render_15bpp_mix_lowres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1427,20 +1427,20 @@ svga_render_15bpp_mix_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); p[x << 1] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr += x << 1; + svga->memaddr &= svga->vram_display_mask; } } @@ -1454,7 +1454,7 @@ svga_render_15bpp_mix_highres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1462,28 +1462,28 @@ svga_render_15bpp_mix_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 8) & svga->vram_display_mask]); p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 12) & svga->vram_display_mask]); p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr += x << 1; + svga->memaddr &= svga->vram_display_mask; } } @@ -1500,7 +1500,7 @@ svga_render_16bpp_lowres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1508,19 +1508,19 @@ svga_render_16bpp_lowres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); p[x << 1] = p[(x << 1) + 1] = svga->conv_16to32(svga, dat & 0xffff, 16); p[(x << 1) + 2] = p[(x << 1) + 3] = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); p[(x << 1) + 4] = p[(x << 1) + 5] = svga->conv_16to32(svga, dat & 0xffff, 16); p[(x << 1) + 6] = p[(x << 1) + 7] = svga->conv_16to32(svga, dat >> 16, 16); } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr += x << 1; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1531,28 +1531,28 @@ svga_render_16bpp_lowres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); } - svga->ma += x << 1; + svga->memaddr += x << 1; } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); } - svga->ma += 4; + svga->memaddr += 4; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1570,7 +1570,7 @@ svga_render_16bpp_highres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1578,27 +1578,27 @@ svga_render_16bpp_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - uint32_t dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + uint32_t dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); p[x] = svga->conv_16to32(svga, dat & 0xffff, 16); p[x + 1] = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); p[x + 2] = svga->conv_16to32(svga, dat & 0xffff, 16); p[x + 3] = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 8) & svga->vram_display_mask]); p[x + 4] = svga->conv_16to32(svga, dat & 0xffff, 16); p[x + 5] = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 12) & svga->vram_display_mask]); p[x + 6] = svga->conv_16to32(svga, dat & 0xffff, 16); p[x + 7] = svga->conv_16to32(svga, dat >> 16, 16); } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + svga->memaddr += x << 1; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1609,35 +1609,35 @@ svga_render_16bpp_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1)) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 4) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 8) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 1) + 12) & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); } - svga->ma += x << 1; + svga->memaddr += x << 1; } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); *p++ = svga->conv_16to32(svga, dat >> 16, 16); - svga->ma += 4; + svga->memaddr += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1661,20 +1661,20 @@ svga_render_24bpp_lowres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { if (svga->firstline_draw == 2000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); - svga->ma += 3; - svga->ma &= svga->vram_display_mask; + fg = svga->vram[svga->memaddr] | (svga->vram[svga->memaddr + 1] << 8) | (svga->vram[svga->memaddr + 2] << 16); + svga->memaddr += 3; + svga->memaddr &= svga->vram_display_mask; svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = lookup_lut(fg); } } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1685,24 +1685,24 @@ svga_render_24bpp_lowres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat0 = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - dat1 = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - dat2 = *(uint32_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat0 = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); + dat1 = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); + dat2 = *(uint32_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]); p[0] = p[1] = lookup_lut(dat0 & 0xffffff); p[2] = p[3] = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8)); p[4] = p[5] = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); p[6] = p[7] = lookup_lut(dat2 >> 8); - svga->ma += 12; + svga->memaddr += 12; } } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat0 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 4); + addr = svga->remap_func(svga, svga->memaddr + 4); dat1 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 8); + addr = svga->remap_func(svga, svga->memaddr + 8); dat2 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); p[0] = p[1] = lookup_lut(dat0 & 0xffffff); @@ -1710,10 +1710,10 @@ svga_render_24bpp_lowres(svga_t *svga) p[4] = p[5] = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); p[6] = p[7] = lookup_lut(dat2 >> 8); - svga->ma += 12; + svga->memaddr += 12; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1734,7 +1734,7 @@ svga_render_24bpp_highres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1742,24 +1742,24 @@ svga_render_24bpp_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); p[x] = lookup_lut(dat & 0xffffff); - dat = *(uint32_t *) (&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 3) & svga->vram_display_mask]); p[x + 1] = lookup_lut(dat & 0xffffff); - dat = *(uint32_t *) (&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 6) & svga->vram_display_mask]); p[x + 2] = lookup_lut(dat & 0xffffff); - dat = *(uint32_t *) (&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + 9) & svga->vram_display_mask]); p[x + 3] = lookup_lut(dat & 0xffffff); - svga->ma += 12; + svga->memaddr += 12; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1770,24 +1770,24 @@ svga_render_24bpp_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - dat0 = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - dat1 = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - dat2 = *(uint32_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat0 = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]); + dat1 = *(uint32_t *) (&svga->vram[(svga->memaddr + 4) & svga->vram_display_mask]); + dat2 = *(uint32_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]); *p++ = lookup_lut(dat0 & 0xffffff); *p++ = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8)); *p++ = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); *p++ = lookup_lut(dat2 >> 8); - svga->ma += 12; + svga->memaddr += 12; } } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat0 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 4); + addr = svga->remap_func(svga, svga->memaddr + 4); dat1 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 8); + addr = svga->remap_func(svga, svga->memaddr + 8); dat2 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = lookup_lut(dat0 & 0xffffff); @@ -1795,10 +1795,10 @@ svga_render_24bpp_highres(svga_t *svga) *p++ = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); *p++ = lookup_lut(dat2 >> 8); - svga->ma += 12; + svga->memaddr += 12; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1816,20 +1816,20 @@ svga_render_32bpp_lowres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) { if (svga->firstline_draw == 2000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); - svga->ma += 4; - svga->ma &= svga->vram_display_mask; + dat = svga->vram[svga->memaddr] | (svga->vram[svga->memaddr + 1] << 8) | (svga->vram[svga->memaddr + 2] << 16); + svga->memaddr += 4; + svga->memaddr &= svga->vram_display_mask; svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = lookup_lut(dat); } } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1840,20 +1840,20 @@ svga_render_32bpp_lowres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 2)) & svga->vram_display_mask]); *p++ = lookup_lut(dat & 0xffffff); *p++ = lookup_lut(dat & 0xffffff); } - svga->ma += (x * 4); + svga->memaddr += (x * 4); } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = lookup_lut(dat & 0xffffff); *p++ = lookup_lut(dat & 0xffffff); - svga->ma += 4; + svga->memaddr += 4; } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1872,7 +1872,7 @@ svga_render_32bpp_highres(svga_t *svga) return; if (svga->force_old_addr) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; if (svga->firstline_draw == 2000) @@ -1880,14 +1880,14 @@ svga_render_32bpp_highres(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 2)) & svga->vram_display_mask]); p[x] = lookup_lut(dat & 0xffffff); } - svga->ma += 4; - svga->ma &= svga->vram_display_mask; + svga->memaddr += 4; + svga->memaddr &= svga->vram_display_mask; } } else { - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1898,20 +1898,20 @@ svga_render_32bpp_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 2)) & svga->vram_display_mask]); *p++ = lookup_lut(dat & 0xffffff); } - svga->ma += (x * 4); + svga->memaddr += (x * 4); } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = lookup_lut(dat & 0xffffff); - svga->ma += 4; + svga->memaddr += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } } @@ -1928,7 +1928,7 @@ svga_render_ABGR8888_highres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1939,20 +1939,20 @@ svga_render_ABGR8888_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 2)) & svga->vram_display_mask]); *p++ = lookup_lut(((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16)); } - svga->ma += x * 4; + svga->memaddr += x * 4; } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = lookup_lut(((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16)); - svga->ma += 4; + svga->memaddr += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } @@ -1968,7 +1968,7 @@ svga_render_RGBA8888_highres(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->memaddr); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -1979,19 +1979,19 @@ svga_render_RGBA8888_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->memaddr + (x << 2)) & svga->vram_display_mask]); *p++ = lookup_lut(dat >> 8); } - svga->ma += (x * 4); + svga->memaddr += (x * 4); } else { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - addr = svga->remap_func(svga, svga->ma); + addr = svga->remap_func(svga, svga->memaddr); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); *p++ = lookup_lut(dat >> 8); - svga->ma += 4; + svga->memaddr += 4; } } - svga->ma &= svga->vram_display_mask; + svga->memaddr &= svga->vram_display_mask; } } diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index 13d46a239..78e7d55c3 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -337,7 +337,7 @@ vid_poll(void *priv) { tandy_t *dev = (tandy_t *) priv; t1kvid_t *vid = dev->vid; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -349,15 +349,15 @@ vid_poll(void *priv) uint16_t dat; int cols[4]; int col; - int oldsc; + int scanline_old; if (!vid->linepos) { timer_advance_u64(&vid->timer, vid->dispofftime); vid->stat |= 1; vid->linepos = 1; - oldsc = vid->sc; + scanline_old = vid->scanline; if ((vid->crtc[8] & 3) == 3) - vid->sc = (vid->sc << 1) & 7; + vid->scanline = (vid->scanline << 1) & 7; if (vid->dispon) { if (vid->displine < vid->firstline) { vid->firstline = vid->displine; @@ -391,8 +391,8 @@ vid_poll(void *priv) } if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/ for (x = 0; x < vid->crtc[1] * 2; x++) { - dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | vid->vram[((vid->ma << 1) + 1) & 0xffff]; - vid->ma++; + dat = (vid->vram[(vid->memaddr << 1) & 0xffff] << 8) | vid->vram[((vid->memaddr << 1) + 1) & 0xffff]; + vid->memaddr++; buffer32->line[vid->displine << 1][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16; buffer32->line[vid->displine << 1][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16; buffer32->line[vid->displine << 1][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16; @@ -400,8 +400,8 @@ vid_poll(void *priv) } } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; + dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000)] << 8) | vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000) + 1]; + vid->memaddr++; buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; @@ -410,11 +410,11 @@ vid_poll(void *priv) } else if (vid->array[3] & 0x10) { /*160x200x16*/ for (x = 0; x < vid->crtc[1]; x++) { if (dev->is_sl2) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1]; } else { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000)] << 8) | vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000) + 1]; } - vid->ma++; + vid->memaddr++; buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; @@ -422,8 +422,8 @@ vid_poll(void *priv) } } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; + dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000)] << 8) | vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000) + 1]; + vid->memaddr++; for (c = 0; c < 8; c++) { chr = (dat >> 6) & 2; chr |= ((dat >> 15) & 1); @@ -433,9 +433,9 @@ vid_poll(void *priv) } } else if (vid->mode & 1) { for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[(vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); + chr = vid->vram[(vid->memaddr << 1) & 0x3fff]; + attr = vid->vram[((vid->memaddr << 1) + 1) & 0x3fff]; + drawcursor = ((vid->memaddr == cursoraddr) && vid->cursorvisible && vid->cursoron); if (vid->mode & 0x20) { cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; @@ -445,16 +445,16 @@ vid_poll(void *priv) cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; } - if (vid->sc & 8) { + if (vid->scanline & 8) { for (c = 0; c < 8; c++) { buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; } } else { for (c = 0; c < 8; c++) { - if (vid->sc == 8) { + if (vid->scanline == 8) { buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; } else { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } } @@ -464,13 +464,13 @@ vid_poll(void *priv) buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15; } } - vid->ma++; + vid->memaddr++; } } else if (!(vid->mode & 2)) { for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[(vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->cursorvisible && vid->cursoron); + chr = vid->vram[(vid->memaddr << 1) & 0x3fff]; + attr = vid->vram[((vid->memaddr << 1) + 1) & 0x3fff]; + drawcursor = ((vid->memaddr == cursoraddr) && vid->cursorvisible && vid->cursoron); if (vid->mode & 0x20) { cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; @@ -480,16 +480,16 @@ vid_poll(void *priv) cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; } - vid->ma++; - if (vid->sc & 8) { + vid->memaddr++; + if (vid->scanline & 8) { for (c = 0; c < 8; c++) buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; } else { for (c = 0; c < 8; c++) { - if (vid->sc == 8) { + if (vid->scanline == 8) { buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; } else { - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } } @@ -521,8 +521,8 @@ vid_poll(void *priv) cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16; cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16; for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; + dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1]; + vid->memaddr++; for (c = 0; c < 8; c++) { buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; dat <<= 2; @@ -532,8 +532,8 @@ vid_poll(void *priv) cols[0] = 0; cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; + dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1]; + vid->memaddr++; for (c = 0; c < 16; c++) { buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; dat <<= 1; @@ -572,8 +572,8 @@ vid_poll(void *priv) video_process_8(x, vid->displine << 1); video_process_8(x, (vid->displine << 1) + 1); } - vid->sc = oldsc; - if (vid->vc == vid->crtc[7] && !vid->sc) + vid->scanline = scanline_old; + if (vid->vc == vid->crtc[7] && !vid->scanline) vid->stat |= 8; vid->displine++; if (vid->displine >= 360) @@ -588,25 +588,25 @@ vid_poll(void *priv) if (!vid->vsynctime) vid->stat &= ~8; } - if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { + if (vid->scanline == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->scanline == ((vid->crtc[11] & 31) >> 1))) { vid->cursorvisible = 0; } if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; + vid->scanline++; + vid->scanline &= 31; + vid->memaddr = vid->memaddr_backup; vid->vadj--; if (!vid->vadj) { vid->dispon = 1; if (dev->is_sl2 && (vid->array[5] & 1)) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + vid->memaddr = vid->memaddr_backup = vid->crtc[13] | (vid->crtc[12] << 8); else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; + vid->memaddr = vid->memaddr_backup = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->scanline = 0; } - } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { - vid->maback = vid->ma; - vid->sc = 0; + } else if (vid->scanline == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->scanline == (vid->crtc[9] >> 1))) { + vid->memaddr_backup = vid->memaddr; + vid->scanline = 0; oldvc = vid->vc; vid->vc++; if (dev->is_sl2) @@ -622,9 +622,9 @@ vid_poll(void *priv) vid->dispon = 1; if (!vid->vadj) { if (dev->is_sl2 && (vid->array[5] & 1)) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + vid->memaddr = vid->memaddr_backup = vid->crtc[13] | (vid->crtc[12] << 8); else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->memaddr = vid->memaddr_backup = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; } if ((vid->crtc[10] & 0x60) == 0x20) vid->cursoron = 0; @@ -704,11 +704,11 @@ vid_poll(void *priv) vid->blink++; } } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; + vid->scanline++; + vid->scanline &= 31; + vid->memaddr = vid->memaddr_backup; } - if (vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1))) + if (vid->scanline == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->scanline == ((vid->crtc[10] & 31) >> 1))) vid->cursorvisible = 1; } } diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 6fbdb7c3f..5cc3a8a78 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -543,7 +543,7 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); @@ -726,13 +726,13 @@ tgui_recalctimings(svga_t *svga) #endif if ((svga->crtc[0x1e] & 0xA0) == 0xA0) - svga->ma_latch |= 0x10000; + svga->memaddr_latch |= 0x10000; if (svga->crtc[0x27] & 0x01) - svga->ma_latch |= 0x20000; + svga->memaddr_latch |= 0x20000; if (svga->crtc[0x27] & 0x02) - svga->ma_latch |= 0x40000; + svga->memaddr_latch |= 0x40000; if (svga->crtc[0x27] & 0x04) - svga->ma_latch |= 0x80000; + svga->memaddr_latch |= 0x80000; if (svga->crtc[0x27] & 0x08) svga->split |= 0x400; @@ -759,7 +759,7 @@ tgui_recalctimings(svga_t *svga) svga->vdisp += 2; if (tgui->oldctrl2 & 0x10) - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; svga->lowres = !(svga->crtc[0x2a] & 0x40); diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index 9dd7e424d..51ab132ca 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -168,7 +168,7 @@ tvga_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -293,15 +293,15 @@ tvga_recalctimings(svga_t *svga) svga->hdisp = (svga->crtc[1] + 1) * 8; if ((svga->crtc[0x1e] & 0xA0) == 0xA0) - svga->ma_latch |= 0x10000; + svga->memaddr_latch |= 0x10000; if ((svga->crtc[0x27] & 0x01) == 0x01) - svga->ma_latch |= 0x20000; + svga->memaddr_latch |= 0x20000; if ((svga->crtc[0x27] & 0x02) == 0x02) - svga->ma_latch |= 0x40000; + svga->memaddr_latch |= 0x40000; if (tvga->oldctrl2 & 0x10) { svga->rowoffset <<= 1; - svga->ma_latch <<= 1; + svga->memaddr_latch <<= 1; } if (svga->gdcreg[0xf] & 0x08) { diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 8289fd4cb..4cde5ba01 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -63,7 +63,7 @@ vga_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 1381a95f7..4bcf8a479 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -385,7 +385,7 @@ banshee_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x11 || (svga->crtcreg == 0x11 && old != val)) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -663,7 +663,7 @@ banshee_recalctimings(svga_t *svga) svga->rowoffset = ((banshee->vidDesktopOverlayStride & 0x3fff) * 128) >> 3; else svga->rowoffset = (banshee->vidDesktopOverlayStride & 0x3fff) >> 3; - svga->ma_latch = banshee->vidDesktopStartAddr >> 2; + svga->memaddr_latch = banshee->vidDesktopStartAddr >> 2; banshee->desktop_stride_tiled = (banshee->vidDesktopOverlayStride & 0x3fff) * 128 * 32; #if 0 banshee_log("Extended shift out %i rowoffset=%i %02x\n", VIDPROCCFG_DESKTOP_PIX_FORMAT, svga->rowoffset, svga->crtc[1]); diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index a52bad4ee..6bd8d54ac 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -535,9 +535,9 @@ wy700_textline(wy700_t *wy700) int cursorline; int mda = 0; uint16_t addr; - uint8_t sc; - uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; - uint16_t ca = (wy700->cga_crtc[15] | (wy700->cga_crtc[14] << 8)) & 0x3fff; + uint8_t scanline; + uint16_t memaddr = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; + uint16_t cursoraddr = (wy700->cga_crtc[15] | (wy700->cga_crtc[14] << 8)) & 0x3fff; /* The fake CRTC character height register selects whether MDA or CGA * attributes are used */ @@ -548,33 +548,33 @@ wy700_textline(wy700_t *wy700) if (wy700->font) { fontbase += 256 * 32; } - addr = ((ma & ~1) + (wy700->displine >> 5) * w) * 2; - sc = (wy700->displine >> 1) & 15; + addr = ((memaddr & ~1) + (wy700->displine >> 5) * w) * 2; + scanline = (wy700->displine >> 1) & 15; - ma += ((wy700->displine >> 5) * w); + memaddr += ((wy700->displine >> 5) * w); if ((wy700->real_crtc[10] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((wy700->real_crtc[10] & 0x1F) <= sc) && ((wy700->real_crtc[11] & 0x1F) >= sc); + cursorline = ((wy700->real_crtc[10] & 0x1F) <= scanline) && ((wy700->real_crtc[11] & 0x1F) >= scanline); } for (int x = 0; x < w; x++) { chr = wy700->vram[(addr + 2 * x) & 0x3FFF]; attr = wy700->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && wy700->enabled && (wy700->cga_ctrl & 8) && (wy700->blink & 16)); + drawcursor = ((memaddr == cursoraddr) && cursorline && wy700->enabled && (wy700->cga_ctrl & 8) && (wy700->blink & 16)); blink = ((wy700->blink & 16) && (wy700->cga_ctrl & 0x20) && (attr & 0x80) && !drawcursor); if (wy700->cga_ctrl & 0x20) attr &= 0x7F; /* MDA underline */ - if (sc == 14 && mda && ((attr & 7) == 1)) { + if (scanline == 14 && mda && ((attr & 7) == 1)) { for (c = 0; c < cw; c++) buffer32->line[wy700->displine][(x * cw) + c] = mdacols[attr][blink][1]; } else /* Draw 16 pixels of character */ { - bitmap[0] = fontbase[chr * 32 + 2 * sc]; - bitmap[1] = fontbase[chr * 32 + 2 * sc + 1]; + bitmap[0] = fontbase[chr * 32 + 2 * scanline]; + bitmap[1] = fontbase[chr * 32 + 2 * scanline + 1]; for (c = 0; c < 16; c++) { int col; if (c < 8) @@ -594,7 +594,7 @@ wy700_textline(wy700_t *wy700) for (c = 0; c < cw; c++) buffer32->line[wy700->displine][(x * cw) + c] ^= (mda ? mdacols : cgacols)[attr][0][1]; } - ++ma; + ++memaddr; } } } @@ -608,8 +608,8 @@ wy700_cgaline(wy700_t *wy700) uint8_t ink = 0; uint16_t addr; - uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; - addr = ((wy700->displine >> 2) & 1) * 0x2000 + (wy700->displine >> 3) * 80 + ((ma & ~1) << 1); + uint16_t memaddr = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; + addr = ((wy700->displine >> 2) & 1) * 0x2000 + (wy700->displine >> 3) * 80 + ((memaddr & ~1) << 1); /* The fixed mode setting here programs the real CRTC with a screen * width to 20, so draw in 20 fixed chunks of 4 bytes each */ diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 4c08b7b71..8f4dc0d0e 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -107,7 +107,7 @@ svga_xga_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -290,7 +290,7 @@ xga_recalctimings(svga_t *svga) xga->v_blankstart >>= 1; } - xga->ma_latch = xga->disp_start_addr; + xga->memaddr_latch = xga->disp_start_addr; xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x, dispcntl2=%02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80, xga->disp_cntl_2 & 0xc0); @@ -2626,7 +2626,7 @@ xga_render_4bpp(svga_t *svga) if ((xga->displine + svga->y_add) < 0) return; - if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + if (xga->changedvram[xga->memaddr >> 12] || xga->changedvram[(xga->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) @@ -2635,22 +2635,22 @@ xga_render_4bpp(svga_t *svga) xga->lastline_draw = xga->displine; for (int x = 0; x <= xga->h_disp; x += 8) { - dat = *(uint32_t *) (&xga->vram[xga->ma & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[xga->memaddr & xga->vram_mask]); p[0] = xga->pallook[dat & 0x0f]; p[1] = xga->pallook[(dat >> 8) & 0x0f]; p[2] = xga->pallook[(dat >> 16) & 0x0f]; p[3] = xga->pallook[(dat >> 24) & 0x0f]; - dat = *(uint32_t *) (&xga->vram[(xga->ma + 2) & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + 2) & xga->vram_mask]); p[4] = xga->pallook[dat & 0x0f]; p[5] = xga->pallook[(dat >> 8) & 0x0f]; p[6] = xga->pallook[(dat >> 16) & 0x0f]; p[7] = xga->pallook[(dat >> 24) & 0x0f]; - xga->ma += 8; + xga->memaddr += 8; p += 8; } - xga->ma &= xga->vram_mask; + xga->memaddr &= xga->vram_mask; } } @@ -2664,7 +2664,7 @@ xga_render_8bpp(svga_t *svga) if ((xga->displine + svga->y_add) < 0) return; - if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + if (xga->changedvram[xga->memaddr >> 12] || xga->changedvram[(xga->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) @@ -2672,22 +2672,22 @@ xga_render_8bpp(svga_t *svga) xga->lastline_draw = xga->displine; for (int x = 0; x <= xga->h_disp; x += 8) { - dat = *(uint32_t *) (&xga->vram[xga->ma & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[xga->memaddr & xga->vram_mask]); p[0] = xga->pallook[dat & 0xff]; p[1] = xga->pallook[(dat >> 8) & 0xff]; p[2] = xga->pallook[(dat >> 16) & 0xff]; p[3] = xga->pallook[(dat >> 24) & 0xff]; - dat = *(uint32_t *) (&xga->vram[(xga->ma + 4) & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + 4) & xga->vram_mask]); p[4] = xga->pallook[dat & 0xff]; p[5] = xga->pallook[(dat >> 8) & 0xff]; p[6] = xga->pallook[(dat >> 16) & 0xff]; p[7] = xga->pallook[(dat >> 24) & 0xff]; - xga->ma += 8; + xga->memaddr += 8; p += 8; } - xga->ma &= xga->vram_mask; + xga->memaddr &= xga->vram_mask; } } @@ -2702,7 +2702,7 @@ xga_render_16bpp(svga_t *svga) if ((xga->displine + svga->y_add) < 0) return; - if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + if (xga->changedvram[xga->memaddr >> 12] || xga->changedvram[(xga->memaddr >> 12) + 1] || svga->fullchange) { p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) @@ -2710,24 +2710,24 @@ xga_render_16bpp(svga_t *svga) xga->lastline_draw = xga->displine; for (x = 0; x <= xga->h_disp; x += 8) { - dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1)) & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + (x << 1)) & xga->vram_mask]); p[x] = video_16to32[dat & 0xffff]; p[x + 1] = video_16to32[dat >> 16]; - dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1) + 4) & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + (x << 1) + 4) & xga->vram_mask]); p[x + 2] = video_16to32[dat & 0xffff]; p[x + 3] = video_16to32[dat >> 16]; - dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1) + 8) & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + (x << 1) + 8) & xga->vram_mask]); p[x + 4] = video_16to32[dat & 0xffff]; p[x + 5] = video_16to32[dat >> 16]; - dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1) + 12) & xga->vram_mask]); + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + (x << 1) + 12) & xga->vram_mask]); p[x + 6] = video_16to32[dat & 0xffff]; p[x + 7] = video_16to32[dat >> 16]; } - xga->ma += x << 1; - xga->ma &= xga->vram_mask; + xga->memaddr += x << 1; + xga->memaddr &= xga->vram_mask; } } @@ -3109,7 +3109,7 @@ xga_poll(void *priv) if (xga->dispon) { xga->h_disp_on = 1; - xga->ma &= xga->vram_mask; + xga->memaddr &= xga->vram_mask; if (xga->firstline == 2000) { xga->firstline = xga->displine; @@ -3117,7 +3117,7 @@ xga_poll(void *priv) } if (xga->hwcursor_on) - xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; + xga->changedvram[xga->memaddr >> 12] = xga->changedvram[(xga->memaddr >> 12) + 1] = xga->interlace ? 3 : 2; svga->render_xga(svga); @@ -3153,20 +3153,20 @@ xga_poll(void *priv) xga->linepos = 0; if (xga->dispon) { - if (xga->sc == xga->rowcount) { - xga->sc = 0; + if (xga->scanline == xga->rowcount) { + xga->scanline = 0; - xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); - xga->maback += (xga->rowoffset << 3); + xga_log("MA=%08x, MALATCH=%x.\n", xga->memaddr, xga->memaddr_latch); + xga->memaddr_backup += (xga->rowoffset << 3); if (xga->interlace) - xga->maback += (xga->rowoffset << 3); + xga->memaddr_backup += (xga->rowoffset << 3); - xga->maback &= xga->vram_mask; - xga->ma = xga->maback; + xga->memaddr_backup &= xga->vram_mask; + xga->memaddr = xga->memaddr_backup; } else { - xga->sc++; - xga->sc &= 0x1f; - xga->ma = xga->maback; + xga->scanline++; + xga->scanline &= 0x1f; + xga->memaddr = xga->memaddr_backup; } } @@ -3175,14 +3175,14 @@ xga_poll(void *priv) if (xga->vc == xga->split) { if (xga->interlace && xga->oddeven) - xga->ma = xga->maback = (xga->rowoffset << 1); + xga->memaddr = xga->memaddr_backup = (xga->rowoffset << 1); else - xga->ma = xga->maback = 0; + xga->memaddr = xga->memaddr_backup = 0; - xga->ma = (xga->ma << 2); - xga->maback = (xga->maback << 2); + xga->memaddr = (xga->memaddr << 2); + xga->memaddr_backup = (xga->memaddr_backup << 2); - xga->sc = 0; + xga->scanline = 0; } if (xga->vc == xga->dispend) { xga->dispon = 0; @@ -3220,16 +3220,16 @@ xga_poll(void *priv) svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; if (xga->interlace && xga->oddeven) - xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); + xga->memaddr = xga->memaddr_backup = xga->memaddr_latch + (xga->rowoffset << 1); else - xga->ma = xga->maback = xga->ma_latch; + xga->memaddr = xga->memaddr_backup = xga->memaddr_latch; - xga->ma = (xga->ma << 2); - xga->maback = (xga->maback << 2); + xga->memaddr = (xga->memaddr << 2); + xga->memaddr_backup = (xga->memaddr_backup << 2); } if (xga->vc == xga->v_total) { xga->vc = 0; - xga->sc = 0; + xga->scanline = 0; xga->dispon = 1; xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; From f9544682a5cb3a5b1c3eee74947f23da1683c44e Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Tue, 10 Jun 2025 22:55:30 +0100 Subject: [PATCH 1130/1190] fix plasma compile --- src/video/vid_cga_compaq_plasma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index 8f058be01..d01be1392 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -314,7 +314,7 @@ compaq_plasma_poll(void *priv) else cursorinvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1); - cursorline = (cursorvisible <= scanline) && (cursorinvisible >= sc); + cursorline = (cursorvisible <= scanline) && (cursorinvisible >= scanline); } /* for each text column */ From 50144585f3d9834086c71dcb15f234c1b126177f Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Tue, 10 Jun 2025 22:56:00 +0100 Subject: [PATCH 1131/1190] now really fix the compile --- src/video/vid_cga_compaq_plasma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index d01be1392..b281cf93f 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -435,7 +435,7 @@ compaq_plasma_poll(void *priv) else cursorinvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1); - cursorline = (cursorvisible <= scanline) && (cursorinvisible >= sc); + cursorline = (cursorvisible <= scanline) && (cursorinvisible >= scanline); } for (x = 0; x < 40; x++) { From b718e821b018101401f729bf64bf39b8482816b7 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Wed, 11 Jun 2025 00:55:30 +0100 Subject: [PATCH 1132/1190] Fix t3100 cgaline4 --- src/video/vid_cga_toshiba_t3100e.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_cga_toshiba_t3100e.c b/src/video/vid_cga_toshiba_t3100e.c index 56883ba4b..12ebcffa2 100644 --- a/src/video/vid_cga_toshiba_t3100e.c +++ b/src/video/vid_cga_toshiba_t3100e.c @@ -407,7 +407,7 @@ t3100e_cgaline4(t3100e_t *t3100e) uint32_t ink1 = 0; uint16_t addr; - uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_END] << 8)) & 0x7fff; + uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff; if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 320*400 undocumented */ { addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1); From dd6f7746a9344614b0022a5798ef90887aba667d Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Wed, 11 Jun 2025 15:36:22 +0100 Subject: [PATCH 1133/1190] Some missing t3100e changes --- src/video/vid_cga_toshiba_t3100e.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_cga_toshiba_t3100e.c b/src/video/vid_cga_toshiba_t3100e.c index 12ebcffa2..9f7c2f526 100644 --- a/src/video/vid_cga_toshiba_t3100e.c +++ b/src/video/vid_cga_toshiba_t3100e.c @@ -497,12 +497,12 @@ t3100e_poll(void *priv) } /* Graphics */ - if (t3100e->cga.cgamode & 0x02) { + if (t3100e->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) { if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) t3100e_cgaline6(t3100e); else t3100e_cgaline4(t3100e); - } else if (t3100e->cga.cgamode & 0x01) /* High-res text */ + } else if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES) /* High-res text */ { t3100e_text_row80(t3100e); } else { @@ -550,7 +550,7 @@ t3100e_poll(void *priv) video_res_x = T3100E_XSIZE; video_res_y = T3100E_YSIZE; - if (t3100e->cga.cgamode & 0x02) { + if (t3100e->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) { if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) video_bpp = 1; else From 317a5b7ade3637f99c19331fb0d5900721f3bf0f Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Wed, 11 Jun 2025 17:37:15 +0100 Subject: [PATCH 1134/1190] stat -> status; improve MDA register decoding; add MDA CRTC, register and mode enums --- src/include/86box/m_pcjr.h | 2 +- src/include/86box/m_tandy.h | 2 +- src/include/86box/vid_ega.h | 2 +- src/include/86box/vid_hercules.h | 2 +- src/include/86box/vid_mda.h | 72 +++++++++++++-- src/machine/m_amstrad.c | 68 +++++++------- src/video/vid_8514a.c | 2 +- src/video/vid_ati_mach8.c | 2 +- src/video/vid_cga_toshiba_t3100e.c | 4 +- src/video/vid_ega.c | 16 ++-- src/video/vid_hercules.c | 12 +-- src/video/vid_hercules_incolor.c | 12 +-- src/video/vid_hercules_plus.c | 12 +-- src/video/vid_mda.c | 137 ++++++++++++++++------------- src/video/vid_pcjr.c | 12 +-- src/video/vid_tandy.c | 10 +-- 16 files changed, 220 insertions(+), 147 deletions(-) diff --git a/src/include/86box/m_pcjr.h b/src/include/86box/m_pcjr.h index 3ffcc3b3e..7a137fb03 100644 --- a/src/include/86box/m_pcjr.h +++ b/src/include/86box/m_pcjr.h @@ -30,7 +30,7 @@ typedef struct pcjr_s uint8_t array[32]; int array_ff; int memctrl; - uint8_t stat; + uint8_t status; int addr_mode; uint8_t *vram; uint8_t *b8000; diff --git a/src/include/86box/m_tandy.h b/src/include/86box/m_tandy.h index 392c9b8a5..2d0100c1a 100644 --- a/src/include/86box/m_tandy.h +++ b/src/include/86box/m_tandy.h @@ -27,7 +27,7 @@ typedef struct t1kvid_t { int memctrl; uint8_t mode; uint8_t col; - uint8_t stat; + uint8_t status; uint8_t *vram; uint8_t *b8000; diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 6c88d50e6..7cd29aa08 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -39,7 +39,7 @@ typedef struct ega_t { uint8_t lb; uint8_t lc; uint8_t ld; - uint8_t stat; + uint8_t status; uint8_t colourcompare; uint8_t colournocare; uint8_t scrblank; diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index c2d2770a9..3d9324124 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -31,7 +31,7 @@ typedef struct { uint8_t ctrl; uint8_t ctrl2; - uint8_t stat; + uint8_t status; uint64_t dispontime; uint64_t dispofftime; diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index 44123ce52..4cd7e2c54 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -1,18 +1,78 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * 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 IBM Monochrome Display and Printer card. + * + * Authors: Sarah Walker, starfrost + * + * Copyright 2007-2024 Sarah Walker + * Copyright 2025 Connor Hyde / starfrost, <mario64crashed@gmail.com> + */ #ifndef VIDEO_MDA_H #define VIDEO_MDA_H +// Defines +#define MDA_CRTC_NUM_REGISTERS 32 + +// Enums & structures + +typedef enum mda_registers_e +{ + MDA_REGISTER_START = 0x3B0, + + MDA_REGISTER_CRTC_INDEX = 0x3B4, + MDA_REGISTER_CRTC_DATA = 0x3B5, + MDA_REGISTER_MODE_CONTROL = 0x3B8, + MDA_REGISTER_CRT_STATUS = 0x3BA, + MDA_REGISTER_PARALLEL_DATA = 0x3BC, + MDA_REGISTER_PRINTER_STATUS = 0x3BD, + MDA_REGISTER_PRINTER_CONTROL = 0x3BE, + + MDA_REGISTER_END = 0x3BF, +} mda_registers; + +// Motorola MC6845 CRTC registers (without light pen for some reason) +typedef enum mda_crtc_registers_e +{ + MDA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync) + MDA_CRTC_HDISP = 0x1, // Horizontal display + MDA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc + MDA_CRTC_HSYNC_WIDTH = 0x3, // Width of horizontal sync + MDA_CRTC_VTOTAL = 0x4, // Vertical total (total number of scanlines incl. vsync) + MDA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value + MDA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline) + MDA_CRTC_VSYNC = 0x7, // Vertical sync scanline number + MDA_CRTC_INTERLACE = 0x8, // Interlacing mode + MDA_CRTC_MAX_SCANLINE_ADDR = 0x9, // Maximum scanline address + MDA_CRTC_CURSOR_START = 0xA, // Cursor start scanline + MDA_CRTC_CURSOR_END = 0xB, // Cursor end scanline + MDA_CRTC_START_ADDR_HIGH = 0xC, // Screen start address high 8 bits + MDA_CRTC_START_ADDR_LOW = 0xD, // Screen start address low 8 bits + MDA_CRTC_CURSOR_ADDR_HIGH = 0xE, // Cursor address high 8 bits + MDA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor address low 8 bits +} mda_crtc_registers; + +typedef enum mda_mode_flags_e +{ + MDA_MODE_HIGHRES = 1 << 0, + MDA_MODE_VIDEO_ENABLE = 1 << 3, + MDA_MODE_BLINK = 1 << 5, +} mda_mode_flags; + typedef struct mda_t { mem_mapping_t mapping; - uint8_t crtc[32]; + uint8_t crtc[MDA_CRTC_NUM_REGISTERS]; int crtcreg; - uint8_t ctrl; - uint8_t stat; + uint8_t mode; + uint8_t status; uint64_t dispontime; uint64_t dispofftime; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 0c39c2176..584b7b3ac 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -105,7 +105,7 @@ typedef struct amsvid_t { int cga_enabled; /* 1640 */ uint8_t cgacol; uint8_t cgamode; - uint8_t stat; + uint8_t status; uint8_t plane_write; /* 1512/200 */ uint8_t plane_read; /* 1512/200 */ uint8_t border; /* 1512/200 */ @@ -290,7 +290,7 @@ vid_in_1512(uint16_t addr, void *priv) break; case 0x03da: - ret = vid->stat; + ret = vid->status; break; default: @@ -357,7 +357,7 @@ vid_poll_1512(void *priv) if (!vid->linepos) { timer_advance_u64(&vid->timer, vid->dispofftime); - vid->stat |= 1; + vid->status |= 1; vid->linepos = 1; scanline_old = vid->scanline; if (vid->dispon) { @@ -496,7 +496,7 @@ vid_poll_1512(void *priv) vid->scanline = scanline_old; if (vid->vsynctime) - vid->stat |= 8; + vid->status |= 8; vid->displine++; if (vid->displine >= 360) vid->displine = 0; @@ -505,12 +505,12 @@ vid_poll_1512(void *priv) if ((vid->lastline - vid->firstline) == 199) vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ if (vid->dispon) - vid->stat &= ~1; + vid->status &= ~1; vid->linepos = 0; if (vid->vsynctime) { vid->vsynctime--; if (!vid->vsynctime) - vid->stat &= ~8; + vid->status &= ~8; } if (vid->scanline == (vid->crtc[11] & 31)) { vid->cursorvisible = 0; @@ -1044,7 +1044,7 @@ vid_in_200(uint16_t addr, void *priv) switch (addr) { case 0x03b8: - return (mda->ctrl); + return (mda->mode); case 0x03d8: return (cga->cgamode); @@ -1106,9 +1106,9 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv) } return; case 0x3b8: - old = mda->ctrl; - mda->ctrl = val; - if ((mda->ctrl ^ old) & 3) + old = mda->mode; + mda->mode = val; + if ((mda->mode ^ old) & 3) mda_recalctimings(mda); vid->crtc_index &= 0x1F; vid->crtc_index |= 0x80; @@ -1269,7 +1269,7 @@ static void lcdm_poll(amsvid_t *vid) { mda_t *mda = &vid->mda; - uint16_t cursoraddr = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int oldvc; @@ -1280,42 +1280,42 @@ lcdm_poll(amsvid_t *vid) if (!mda->linepos) { timer_advance_u64(&vid->timer, mda->dispofftime); - mda->stat |= 1; + mda->status |= 1; mda->linepos = 1; scanline_old = mda->scanline; - if ((mda->crtc[8] & 3) == 3) + if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; if (mda->dispon) { if (mda->displine < mda->firstline) mda->firstline = mda->displine; mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[1]; x++) { + for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { chr = mda->vram[(mda->memaddr<< 1) & 0xfff]; attr = mda->vram[((mda->memaddr<< 1) + 1) & 0xfff]; drawcursor = ((mda->memaddr== cursoraddr) && mda->cursorvisible && mda->cursoron); - blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); - lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->scanline, 0, mda->ctrl); + lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->scanline, 0, mda->mode); mda->memaddr++; } } mda->scanline = scanline_old; - if (mda->vc == mda->crtc[7] && !mda->scanline) - mda->stat |= 8; + if (mda->vc == mda->crtc[MDA_CRTC_VSYNC] && !mda->scanline) + mda->status |= 8; mda->displine++; if (mda->displine >= 500) mda->displine = 0; } else { timer_advance_u64(&vid->timer, mda->dispontime); if (mda->dispon) - mda->stat &= ~1; + mda->status &= ~1; mda->linepos = 0; if (mda->vsynctime) { mda->vsynctime--; if (!mda->vsynctime) - mda->stat &= ~8; + mda->status &= ~8; } - if (mda->scanline == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[11] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) { mda->cursorvisible = 0; } if (mda->vadj) { @@ -1325,35 +1325,35 @@ lcdm_poll(amsvid_t *vid) mda->vadj--; if (!mda->vadj) { mda->dispon = 1; - mda->memaddr= mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->memaddr= mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; mda->scanline = 0; } - } else if (mda->scanline == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->scanline == (mda->crtc[9] >> 1))) { + } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { mda->memaddr_backup = mda->memaddr; mda->scanline = 0; oldvc = mda->vc; mda->vc++; mda->vc &= 127; - if (mda->vc == mda->crtc[6]) + if (mda->vc == mda->crtc[MDA_CRTC_VDISP]) mda->dispon = 0; - if (oldvc == mda->crtc[4]) { + if (oldvc == mda->crtc[MDA_CRTC_VTOTAL]) { mda->vc = 0; - mda->vadj = mda->crtc[5]; + mda->vadj = mda->crtc[MDA_CRTC_VTOTAL_ADJUST]; if (!mda->vadj) mda->dispon = 1; if (!mda->vadj) - mda->memaddr= mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - if ((mda->crtc[10] & 0x60) == 0x20) + mda->memaddr= mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + if ((mda->crtc[MDA_CRTC_CURSOR_START] & 0x60) == 0x20) mda->cursoron = 0; else mda->cursoron = mda->blink & 16; } - if (mda->vc == mda->crtc[7]) { + if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) { mda->dispon = 0; mda->displine = 0; mda->vsynctime = 16; - if (mda->crtc[7]) { - x = mda->crtc[1] * 8; + if (mda->crtc[MDA_CRTC_VSYNC]) { + x = mda->crtc[MDA_CRTC_HDISP] * 8; mda->lastline++; if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { xsize = x; @@ -1369,8 +1369,8 @@ lcdm_poll(amsvid_t *vid) } video_blit_memtoscreen(0, mda->firstline, xsize, ysize); frames++; - video_res_x = mda->crtc[1]; - video_res_y = mda->crtc[6]; + video_res_x = mda->crtc[MDA_CRTC_HDISP]; + video_res_y = mda->crtc[MDA_CRTC_VDISP]; video_bpp = 0; } mda->firstline = 1000; @@ -1382,7 +1382,7 @@ lcdm_poll(amsvid_t *vid) mda->scanline &= 31; mda->memaddr= mda->memaddr_backup; } - if (mda->scanline == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[10] & 31) >> 1))) + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) mda->cursorvisible = 1; } } diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index dcac57fe1..97202340d 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -459,7 +459,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x42e8: - ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + ibm8514_log("VBLANK status=%02x, val=%02x.\n", dev->subsys_stat, val); if (len == 2) { dev->subsys_cntl = val; dev->subsys_stat &= ~val; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 32a1c2b9e..9dd736cd7 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -3297,7 +3297,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x42e8: case 0x42e9: - mach_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + mach_log("VBLANK status=%02x, val=%02x.\n", dev->subsys_stat, val); if (len == 2) dev->subsys_cntl = val; else { diff --git a/src/video/vid_cga_toshiba_t3100e.c b/src/video/vid_cga_toshiba_t3100e.c index 9f7c2f526..e3eb673c8 100644 --- a/src/video/vid_cga_toshiba_t3100e.c +++ b/src/video/vid_cga_toshiba_t3100e.c @@ -169,8 +169,8 @@ t3100e_out(uint16_t addr, uint8_t val, void *priv) t3100e_recalctimings(t3100e); return; - case 0x3D8: /* CGA control register */ - case 0x3D9: /* CGA colour register */ + case CGA_REGISTER_MODE_CONTROL: /* CGA control register */ + case CGA_REGISTER_COLOR_SELECT: /* CGA colour register */ cga_out(addr, val, &t3100e->cga); return; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 3b4e8cce0..d937b2458 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -505,7 +505,7 @@ ega_in(uint16_t addr, void *priv) case 0x3da: ega->attrff = 0; if (type == EGA_TYPE_COMPAQ) { - ret = ega->stat & 0xcf; + ret = ega->status & 0xcf; switch ((ega->attrregs[0x12] >> 4) & 0x03) { case 0x00: /* 00 = Pri. Red (5), Pri. Blue (4) */ @@ -526,8 +526,8 @@ ega_in(uint16_t addr, void *priv) break; } } else { - ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ - ret = ega->stat; + ega->status ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ + ret = ega->status; } break; case 0x7c6: @@ -837,7 +837,7 @@ ega_poll(void *priv) if (!ega->linepos) { timer_advance_u64(&ega->timer, ega->dispofftime); - ega->stat |= 1; + ega->status |= 1; ega->linepos = 1; if (ega->dispon) { @@ -877,8 +877,8 @@ ega_poll(void *priv) ega->displine++; if (ega->interlace) ega->displine++; - if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) - ega->stat &= ~8; + if ((ega->status & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) + ega->status &= ~8; ega->vslines++; if (ega->chipset) { if (ega->hdisp >= 800) { @@ -896,7 +896,7 @@ ega_poll(void *priv) timer_advance_u64(&ega->timer, ega->dispontime); if (ega->dispon) - ega->stat &= ~1; + ega->status &= ~1; ega->hdisp_on = 0; ega->linepos = 0; @@ -968,7 +968,7 @@ ega_poll(void *priv) } if (ega->vc == ega->vsyncstart) { ega->dispon = 0; - ega->stat |= 8; + ega->status |= 8; #if 0 picint(1 << 2); #endif diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 4b8d796a3..5e0ac1bc9 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -178,8 +178,8 @@ hercules_in(uint16_t addr, void *priv) case 0x03ba: ret = 0x70; /* Hercules ident */ ret |= (dev->lp_ff ? 2 : 0); - ret |= (dev->stat & 0x01); - if (dev->stat & 0x08) + ret |= (dev->status & 0x01); + if (dev->status & 0x08) ret |= 0x80; if ((ret & 0x81) == 0x80) ret |= 0x08; @@ -300,7 +300,7 @@ hercules_poll(void *priv) if (!dev->linepos) { timer_advance_u64(&dev->timer, dev->dispofftime); - dev->stat |= 1; + dev->status |= 1; dev->linepos = 1; scanline_old = dev->scanline; @@ -380,7 +380,7 @@ hercules_poll(void *priv) dev->scanline = scanline_old; if (dev->vc == dev->crtc[7] && !dev->scanline) - dev->stat |= 8; + dev->status |= 8; dev->displine++; if (dev->displine >= 500) dev->displine = 0; @@ -388,13 +388,13 @@ hercules_poll(void *priv) timer_advance_u64(&dev->timer, dev->dispontime); if (dev->dispon) - dev->stat &= ~1; + dev->status &= ~1; dev->linepos = 0; if (dev->vsynctime) { dev->vsynctime--; if (!dev->vsynctime) - dev->stat &= ~8; + dev->status &= ~8; } if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { diff --git a/src/video/vid_hercules_incolor.c b/src/video/vid_hercules_incolor.c index 6e202d338..c4751e8fa 100644 --- a/src/video/vid_hercules_incolor.c +++ b/src/video/vid_hercules_incolor.c @@ -157,7 +157,7 @@ typedef struct { uint8_t crtc[32]; int crtcreg; - uint8_t ctrl, ctrl2, stat; + uint8_t ctrl, ctrl2, status; uint64_t dispontime, dispofftime; pc_timer_t timer; @@ -285,7 +285,7 @@ incolor_in(uint16_t port, void *priv) case 0x3ba: /* 0x50: InColor card identity */ - ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50; + ret = (dev->status & 0xf) | ((dev->status & 8) << 4) | 0x50; break; default: @@ -863,7 +863,7 @@ incolor_poll(void *priv) if (!dev->linepos) { timer_advance_u64(&dev->timer, dev->dispofftime); - dev->stat |= 1; + dev->status |= 1; dev->linepos = 1; scanline_old = dev->scanline; if ((dev->crtc[8] & 3) == 3) @@ -882,19 +882,19 @@ incolor_poll(void *priv) } dev->scanline = scanline_old; if (dev->vc == dev->crtc[7] && !dev->scanline) - dev->stat |= 8; + dev->status |= 8; dev->displine++; if (dev->displine >= 500) dev->displine = 0; } else { timer_advance_u64(&dev->timer, dev->dispontime); if (dev->dispon) - dev->stat &= ~1; + dev->status &= ~1; dev->linepos = 0; if (dev->vsynctime) { dev->vsynctime--; if (!dev->vsynctime) - dev->stat &= ~8; + dev->status &= ~8; } if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { diff --git a/src/video/vid_hercules_plus.c b/src/video/vid_hercules_plus.c index 4a2790dc0..0c6125d0b 100644 --- a/src/video/vid_hercules_plus.c +++ b/src/video/vid_hercules_plus.c @@ -67,7 +67,7 @@ typedef struct { uint8_t crtc[32]; int crtcreg; - uint8_t ctrl, ctrl2, stat; + uint8_t ctrl, ctrl2, status; uint64_t dispontime, dispofftime; pc_timer_t timer; @@ -194,7 +194,7 @@ herculesplus_in(uint16_t port, void *priv) case 0x3ba: /* 0x10: Hercules Plus card identity */ - ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; + ret = (dev->status & 0xf) | ((dev->status & 8) << 4) | 0x10; break; default: @@ -494,7 +494,7 @@ herculesplus_poll(void *priv) VIDEO_MONITOR_PROLOGUE(); if (!dev->linepos) { timer_advance_u64(&dev->timer, dev->dispofftime); - dev->stat |= 1; + dev->status |= 1; dev->linepos = 1; scanline_old = dev->scanline; if ((dev->crtc[8] & 3) == 3) @@ -519,19 +519,19 @@ herculesplus_poll(void *priv) } dev->scanline = scanline_old; if (dev->vc == dev->crtc[7] && !dev->scanline) - dev->stat |= 8; + dev->status |= 8; dev->displine++; if (dev->displine >= 500) dev->displine = 0; } else { timer_advance_u64(&dev->timer, dev->dispontime); if (dev->dispon) - dev->stat &= ~1; + dev->status &= ~1; dev->linepos = 0; if (dev->vsynctime) { dev->vsynctime--; if (!dev->vsynctime) - dev->stat &= ~8; + dev->status &= ~8; } if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) { diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 4928441e6..c8a739fbe 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -12,9 +12,11 @@ * * Authors: Sarah Walker, <https://pcem-emulator.co.uk/> * Miran Grca, <mgrca8@gmail.com> + * Connor Hyde, <mario64crashed@gmail.com> * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2025 Miran Grca. + * Copyright 2025 starfrost / Connor Hyde */ #include <stdio.h> #include <stdint.h> @@ -44,32 +46,35 @@ mda_out(uint16_t addr, uint8_t val, void *priv) { mda_t *mda = (mda_t *) priv; - switch (addr) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - mda->crtcreg = val & 31; - return; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - mda->crtc[mda->crtcreg] = val; - if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - mda->crtc[10] = 0xb; - mda->crtc[11] = 0xc; - } - mda_recalctimings(mda); - return; - case 0x3b8: - mda->ctrl = val; - return; + if (addr < MDA_REGISTER_START + || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case + return; + switch (addr) + { + case MDA_REGISTER_MODE_CONTROL: + mda->mode = val; + return; default: break; } + + // addr & 1 == 1 = MDA_REGISTER_CRTC_DATA + // otherwise MDA_REGISTER_CRTC_INDEX + if (addr & 1) + { + mda->crtc[mda->crtcreg] = val; + if (mda->crtc[MDA_CRTC_CURSOR_START] == 6 + && mda->crtc[MDA_CRTC_CURSOR_END] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ + { + mda->crtc[MDA_CRTC_CURSOR_START] = 0xb; + mda->crtc[MDA_CRTC_CURSOR_END] = 0xc; + } + mda_recalctimings(mda); + } + else + mda->crtcreg = val & 31; + } uint8_t @@ -77,24 +82,26 @@ mda_in(uint16_t addr, void *priv) { const mda_t *mda = (mda_t *) priv; - switch (addr) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - return mda->crtcreg; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - return mda->crtc[mda->crtcreg]; - case 0x3ba: - return mda->stat | 0xF0; + switch (addr) + { + case MDA_REGISTER_CRT_STATUS: + return mda->status | 0xF0; default: + if (addr < MDA_REGISTER_START + || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case + return 0xFF; + + // MDA_REGISTER_CRTC_DATA + if (addr & 1) + return mda->crtc[mda->crtcreg]; + else + return mda->crtcreg; + break; } - return 0xff; + + return 0xFF; } void @@ -118,8 +125,8 @@ mda_recalctimings(mda_t *mda) double _dispontime; double _dispofftime; double disptime; - disptime = mda->crtc[0] + 1; - _dispontime = mda->crtc[1]; + disptime = mda->crtc[MDA_CRTC_HTOTAL] + 1; + _dispontime = mda->crtc[MDA_CRTC_HDISP]; _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; @@ -131,7 +138,7 @@ void mda_poll(void *priv) { mda_t *mda = (mda_t *) priv; - uint16_t cursoraddr = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; int c; @@ -144,10 +151,10 @@ mda_poll(void *priv) VIDEO_MONITOR_PROLOGUE() if (!mda->linepos) { timer_advance_u64(&mda->timer, mda->dispofftime); - mda->stat |= 1; + mda->status |= 1; mda->linepos = 1; scanline_old = mda->scanline; - if ((mda->crtc[8] & 3) == 3) + if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; if (mda->dispon) { if (mda->displine < mda->firstline) { @@ -155,11 +162,11 @@ mda_poll(void *priv) video_wait_for_buffer(); } mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[1]; x++) { + for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); - blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); if (mda->scanline == 12 && ((attr & 7) == 1)) { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; @@ -178,11 +185,11 @@ mda_poll(void *priv) } } - video_process_8(mda->crtc[1] * 9, mda->displine); + video_process_8(mda->crtc[MDA_CRTC_HDISP] * 9, mda->displine); } mda->scanline = scanline_old; - if (mda->vc == mda->crtc[7] && !mda->scanline) { - mda->stat |= 8; + if (mda->vc == mda->crtc[MDA_CRTC_VSYNC] && !mda->scanline) { + mda->status |= 8; } mda->displine++; if (mda->displine >= 500) @@ -190,15 +197,17 @@ mda_poll(void *priv) } else { timer_advance_u64(&mda->timer, mda->dispontime); if (mda->dispon) - mda->stat &= ~1; + mda->status &= ~1; mda->linepos = 0; if (mda->vsynctime) { mda->vsynctime--; if (!mda->vsynctime) { - mda->stat &= ~8; + mda->status &= ~8; } } - if (mda->scanline == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[11] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) { mda->cursorvisible = 0; } if (mda->vadj) { @@ -208,35 +217,37 @@ mda_poll(void *priv) mda->vadj--; if (!mda->vadj) { mda->dispon = 1; - mda->memaddr = mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; mda->scanline = 0; } - } else if (mda->scanline == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->scanline == (mda->crtc[9] >> 1))) { + } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { mda->memaddr_backup = mda->memaddr; mda->scanline = 0; oldvc = mda->vc; mda->vc++; mda->vc &= 127; - if (mda->vc == mda->crtc[6]) + if (mda->vc == mda->crtc[MDA_CRTC_VDISP]) mda->dispon = 0; - if (oldvc == mda->crtc[4]) { + if (oldvc == mda->crtc[MDA_CRTC_VTOTAL]) { mda->vc = 0; - mda->vadj = mda->crtc[5]; + mda->vadj = mda->crtc[MDA_CRTC_VTOTAL_ADJUST]; if (!mda->vadj) mda->dispon = 1; if (!mda->vadj) - mda->memaddr = mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - if ((mda->crtc[10] & 0x60) == 0x20) + mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; + if ((mda->crtc[MDA_CRTC_CURSOR_START] & 0x60) == 0x20) mda->cursoron = 0; else mda->cursoron = mda->blink & 16; } - if (mda->vc == mda->crtc[7]) { + if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) { mda->dispon = 0; mda->displine = 0; mda->vsynctime = 16; - if (mda->crtc[7]) { - x = mda->crtc[1] * 9; + if (mda->crtc[MDA_CRTC_VSYNC]) { + x = mda->crtc[MDA_CRTC_HDISP] * 9; mda->lastline++; if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { xsize = x; @@ -252,8 +263,8 @@ mda_poll(void *priv) } video_blit_memtoscreen(0, mda->firstline, xsize, ysize); frames++; - video_res_x = mda->crtc[1]; - video_res_y = mda->crtc[6]; + video_res_x = mda->crtc[MDA_CRTC_HDISP]; + video_res_y = mda->crtc[MDA_CRTC_VDISP]; video_bpp = 0; } mda->firstline = 1000; @@ -265,7 +276,9 @@ mda_poll(void *priv) mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; } - if (mda->scanline == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[10] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) { mda->cursorvisible = 1; } } diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index c02275f09..17a43fb40 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -183,8 +183,8 @@ vid_in(uint16_t addr, void *priv) case 0x3da: pcjr->array_ff = 0; - pcjr->stat ^= 0x10; - ret = pcjr->stat; + pcjr->status ^= 0x10; + ret = pcjr->status; break; default: @@ -316,7 +316,7 @@ vid_poll(void *priv) if (!pcjr->linepos) { timer_advance_u64(&pcjr->timer, pcjr->dispofftime); - pcjr->stat &= ~1; + pcjr->status &= ~1; pcjr->linepos = 1; scanline_old = pcjr->scanline; if ((pcjr->crtc[8] & 3) == 3) @@ -557,7 +557,7 @@ vid_poll(void *priv) } pcjr->scanline = scanline_old; if (pcjr->vc == pcjr->crtc[7] && !pcjr->scanline) { - pcjr->stat |= 8; + pcjr->status |= 8; } pcjr->displine++; if (pcjr->displine >= 360) @@ -565,12 +565,12 @@ vid_poll(void *priv) } else { timer_advance_u64(&pcjr->timer, pcjr->dispontime); if (pcjr->dispon) - pcjr->stat |= 1; + pcjr->status |= 1; pcjr->linepos = 0; if (pcjr->vsynctime) { pcjr->vsynctime--; if (!pcjr->vsynctime) { - pcjr->stat &= ~8; + pcjr->status &= ~8; } } if (pcjr->scanline == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == ((pcjr->crtc[11] & 31) >> 1))) { diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index 78e7d55c3..312527a35 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -268,7 +268,7 @@ tandy_vid_in(uint16_t addr, void *priv) break; case 0x03da: - ret = vid->stat; + ret = vid->status; break; case 0x3db: @@ -353,7 +353,7 @@ vid_poll(void *priv) if (!vid->linepos) { timer_advance_u64(&vid->timer, vid->dispofftime); - vid->stat |= 1; + vid->status |= 1; vid->linepos = 1; scanline_old = vid->scanline; if ((vid->crtc[8] & 3) == 3) @@ -574,19 +574,19 @@ vid_poll(void *priv) } vid->scanline = scanline_old; if (vid->vc == vid->crtc[7] && !vid->scanline) - vid->stat |= 8; + vid->status |= 8; vid->displine++; if (vid->displine >= 360) vid->displine = 0; } else { timer_advance_u64(&vid->timer, vid->dispontime); if (vid->dispon) - vid->stat &= ~1; + vid->status &= ~1; vid->linepos = 0; if (vid->vsynctime) { vid->vsynctime--; if (!vid->vsynctime) - vid->stat &= ~8; + vid->status &= ~8; } if (vid->scanline == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->scanline == ((vid->crtc[11] & 31) >> 1))) { vid->cursorvisible = 0; From 5d8b3412e94b3336836bdb50cc081b1745db43bf Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Wed, 11 Jun 2025 20:36:56 +0100 Subject: [PATCH 1135/1190] mdacols -> mda_attr_to_color_table; cgacols -> cga_attr_to_color_table --- src/include/86box/vid_ega.h | 2 +- src/include/86box/vid_hercules.h | 10 ++-- src/include/86box/vid_mda.h | 5 +- src/machine/m_amstrad.c | 4 +- src/video/vid_cga.c | 58 ++++++++++----------- src/video/vid_ega.c | 30 +++++------ src/video/vid_ega_render.c | 6 +-- src/video/vid_mda.c | 53 +++++++++---------- src/video/vid_wy700.c | 88 ++++++++++++++++---------------- 9 files changed, 131 insertions(+), 125 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 7cd29aa08..beef6f98d 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -115,7 +115,7 @@ typedef struct ega_t { int chipset; int mono_display; - int mdacols[256][2][2]; + int mda_attr_to_color_table[256][2][2]; uint32_t charseta; uint32_t charsetb; diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index 3d9324124..1d62bee67 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -13,10 +13,12 @@ * Authors: Sarah Walker, <https://pcem-emulator.co.uk/> * Miran Grca, <mgrca8@gmail.com> * Jasmine Iwanek, <jriwanek@gmail.com> - * + * Connor Hyde / starfrost, <mario64crashed@gmail.com + * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. * Copyright 2021 Jasmine Iwanek. + * Copyright 2025 starfrost */ #ifndef VIDEO_HERCULES_H @@ -53,10 +55,10 @@ typedef struct { int vsynctime; int vadj; - int lp_ff; - int fullchange; + int lp_ff; + int fullchange; - int cols[256][2][2]; + int cols[256][2][2]; uint8_t *vram; int monitor_index; diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index 4cd7e2c54..e8ccd8602 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -60,8 +60,9 @@ typedef enum mda_crtc_registers_e typedef enum mda_mode_flags_e { - MDA_MODE_HIGHRES = 1 << 0, - MDA_MODE_VIDEO_ENABLE = 1 << 3, + MDA_MODE_HIGHRES = 1 << 0, // MUST be enabled for sane operation + MDA_MODE_BLACKANDWHITE = 1 << 1, // UNUSED in most cases. Not present on Hercules + MDA_MODE_VIDEO_ENABLE = 1 << 3, MDA_MODE_BLINK = 1 << 5, } mda_mode_flags; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 584b7b3ac..d42807b4d 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -412,7 +412,9 @@ vid_poll_1512(void *priv) for (x = 0; x < 40; x++) { chr = vid->vram[(vid->memaddr<< 1) & 0x3fff]; attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff]; - drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron); + drawcursor = ((vid->memaddr == cursoraddr) + && vid->cursorvisible && vid->cursoron); + if (vid->cgamode & CGA_MODE_FLAG_BLINK) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 5566537db..72389d219 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -16,7 +16,7 @@ * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. - * Copyright 2023 W. M. Martine + * Copyright 2023 W. M. Martinez */ #include <stdio.h> #include <stdint.h> @@ -256,7 +256,7 @@ cga_render(cga_t *cga, int line) uint16_t cursoraddr = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; - int c; + int column; uint8_t chr; uint8_t attr; uint16_t dat; @@ -266,20 +266,20 @@ cga_render(cga_t *cga, int line) int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); if (((cga->cgamode & highres_graphics_flag) == highres_graphics_flag)) { - for (c = 0; c < 8; ++c) { - buffer32->line[line][c] = 0; + for (column = 0; column < 8; ++column) { + buffer32->line[line][column] = 0; if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) - buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = 0; + buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = 0; else - buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = 0; + buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = 0; } } else { - for (c = 0; c < 8; ++c) { - buffer32->line[line][c] = (cga->cgacol & 15) + 16; + for (column = 0; column < 8; ++column) { + buffer32->line[line][column] = (cga->cgacol & 15) + 16; if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) - buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = (cga->cgacol & 15) + 16; + buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = (cga->cgacol & 15) + 16; else - buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = (cga->cgacol & 15) + 16; + buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = (cga->cgacol & 15) + 16; } } if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { @@ -298,14 +298,14 @@ cga_render(cga_t *cga, int line) } else cols[0] = (attr >> 4) + 16; if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[line][(x << 3) + c + 8] - = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + for (column = 0; column < 8; column++) { + buffer32->line[line][(x << 3) + column + 8] + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15; } } else { - for (c = 0; c < 8; c++) { - buffer32->line[line][(x << 3) + c + 8] - = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; + for (column = 0; column < 8; column++) { + buffer32->line[line][(x << 3) + column + 8] + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0]; } } cga->memaddr++; @@ -327,16 +327,16 @@ cga_render(cga_t *cga, int line) cols[0] = (attr >> 4) + 16; cga->memaddr++; if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[line][(x << 4) + (c << 1) + 8] - = buffer32->line[line][(x << 4) + (c << 1) + 9] - = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + for (column = 0; column < 8; column++) { + buffer32->line[line][(x << 4) + (column << 1) + 8] + = buffer32->line[line][(x << 4) + (column << 1) + 9] + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15; } } else { - for (c = 0; c < 8; c++) { - buffer32->line[line][(x << 4) + (c << 1) + 8] - = buffer32->line[line][(x << 4) + (c << 1) + 9] - = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0]; + for (column = 0; column < 8; column++) { + buffer32->line[line][(x << 4) + (column << 1) + 8] + = buffer32->line[line][(x << 4) + (column << 1) + 9] + = cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0]; } } } @@ -363,9 +363,9 @@ cga_render(cga_t *cga, int line) else dat = 0; cga->memaddr++; - for (c = 0; c < 8; c++) { - buffer32->line[line][(x << 4) + (c << 1) + 8] - = buffer32->line[line][(x << 4) + (c << 1) + 9] + for (column = 0; column < 8; column++) { + buffer32->line[line][(x << 4) + (column << 1) + 8] + = buffer32->line[line][(x << 4) + (column << 1) + 9] = cols[dat >> 14]; dat <<= 2; } @@ -380,8 +380,8 @@ cga_render(cga_t *cga, int line) else dat = 0; cga->memaddr++; - for (c = 0; c < 16; c++) { - buffer32->line[line][(x << 4) + c + 8] = cols[dat >> 15]; + for (column = 0; column < 16; column++) { + buffer32->line[line][(x << 4) + column + 8] = cols[dat >> 15]; dat <<= 1; } } diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index d937b2458..1cfea782c 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1512,24 +1512,24 @@ 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; + ega->mda_attr_to_color_table[c][0][0] = ega->mda_attr_to_color_table[c][1][0] = ega->mda_attr_to_color_table[c][1][1] = 16; if (c & 8) - ega->mdacols[c][0][1] = 15 + 16; + ega->mda_attr_to_color_table[c][0][1] = 15 + 16; else - ega->mdacols[c][0][1] = 7 + 16; + ega->mda_attr_to_color_table[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; + ega->mda_attr_to_color_table[0x70][0][1] = 16; + ega->mda_attr_to_color_table[0x70][0][0] = ega->mda_attr_to_color_table[0x70][1][0] = ega->mda_attr_to_color_table[0x70][1][1] = 16 + 15; + ega->mda_attr_to_color_table[0xF0][0][1] = 16; + ega->mda_attr_to_color_table[0xF0][0][0] = ega->mda_attr_to_color_table[0xF0][1][0] = ega->mda_attr_to_color_table[0xF0][1][1] = 16 + 15; + ega->mda_attr_to_color_table[0x78][0][1] = 16 + 7; + ega->mda_attr_to_color_table[0x78][0][0] = ega->mda_attr_to_color_table[0x78][1][0] = ega->mda_attr_to_color_table[0x78][1][1] = 16 + 15; + ega->mda_attr_to_color_table[0xF8][0][1] = 16 + 7; + ega->mda_attr_to_color_table[0xF8][0][0] = ega->mda_attr_to_color_table[0xF8][1][0] = ega->mda_attr_to_color_table[0xF8][1][1] = 16 + 15; + ega->mda_attr_to_color_table[0x00][0][1] = ega->mda_attr_to_color_table[0x00][1][1] = 16; + ega->mda_attr_to_color_table[0x08][0][1] = ega->mda_attr_to_color_table[0x08][1][1] = 16; + ega->mda_attr_to_color_table[0x80][0][1] = ega->mda_attr_to_color_table[0x80][1][1] = 16; + ega->mda_attr_to_color_table[0x88][0][1] = ega->mda_attr_to_color_table[0x88][1][1] = 16; egaswitches = monitor_type & 0xf; diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 1f307a12c..c1c44dfdb 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -185,11 +185,11 @@ ega_render_text(ega_t *ega) int bit = (dat & (0x100 >> (xx >> dwshift))) ? 1 : 0; int blink = (!drawcursor && (attr & 0x80) && attrblink && blinked); if ((ega->scanline == ega->crtc[0x14]) && ((attr & 7) == 1)) - p[xx] = ega->mdacols[attr][blink][1]; + p[xx] = ega->mda_attr_to_color_table[attr][blink][1]; else - p[xx] = ega->mdacols[attr][blink][bit]; + p[xx] = ega->mda_attr_to_color_table[attr][blink][bit]; if (drawcursor) - p[xx] ^= ega->mdacols[attr][0][1]; + p[xx] ^= ega->mda_attr_to_color_table[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_mda.c b/src/video/vid_mda.c index c8a739fbe..f3d881769 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -35,7 +35,7 @@ #include <86box/vid_mda.h> #include <86box/plat_unused.h> -static int mdacols[256][2][2]; +static int mda_attr_to_color_table[256][2][2]; static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; @@ -86,7 +86,6 @@ mda_in(uint16_t addr, void *priv) { case MDA_REGISTER_CRT_STATUS: return mda->status | 0xF0; - default: if (addr < MDA_REGISTER_START || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case @@ -169,19 +168,19 @@ mda_poll(void *priv) blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); if (mda->scanline == 12 && ((attr & 7) == 1)) { for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; } else { for (c = 0; c < 8; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][(fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0]; if ((chr & ~0x1f) == 0xc0) - buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; else - buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0]; + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; } mda->memaddr++; if (drawcursor) { for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1]; + buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1]; } } @@ -218,14 +217,14 @@ mda_poll(void *priv) if (!mda->vadj) { mda->dispon = 1; mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - mda->scanline = 0; + mda->scanline = 0; } } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { mda->memaddr_backup = mda->memaddr; - mda->scanline = 0; - oldvc = mda->vc; + mda->scanline = 0; + oldvc = mda->vc; mda->vc++; mda->vc &= 127; if (mda->vc == mda->crtc[MDA_CRTC_VDISP]) @@ -242,6 +241,7 @@ mda_poll(void *priv) else mda->cursoron = mda->blink & 16; } + if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) { mda->dispon = 0; mda->displine = 0; @@ -276,6 +276,7 @@ mda_poll(void *priv) mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; } + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) { @@ -289,24 +290,24 @@ void mda_init(mda_t *mda) { for (uint16_t c = 0; c < 256; c++) { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; + mda_attr_to_color_table[c][0][0] = mda_attr_to_color_table[c][1][0] = mda_attr_to_color_table[c][1][1] = 16; if (c & 8) - mdacols[c][0][1] = 15 + 16; + mda_attr_to_color_table[c][0][1] = 15 + 16; else - mdacols[c][0][1] = 7 + 16; + mda_attr_to_color_table[c][0][1] = 7 + 16; } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + mda_attr_to_color_table[0x70][0][1] = 16; + mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = 16 + 15; + mda_attr_to_color_table[0xF0][0][1] = 16; + mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = 16 + 15; + mda_attr_to_color_table[0x78][0][1] = 16 + 7; + mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = 16 + 15; + mda_attr_to_color_table[0xF8][0][1] = 16 + 7; + mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = 16 + 15; + mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16; + mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; + mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; + mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16; overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; @@ -366,7 +367,7 @@ mda_standalone_init(UNUSED(const device_t *info)) void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) { - mdacols[chr][blink][fg] = 16 + cga_ink; + mda_attr_to_color_table[chr][blink][fg] = 16 + cga_ink; } void diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 6bd8d54ac..c00541113 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -212,9 +212,9 @@ typedef struct wy700_t { } wy700_t; /* Mapping of attributes to colours, in CGA emulation... */ -static int cgacols[256][2][2]; +static int cga_attr_to_color_table[256][2][2]; /* ... and MDA emulation. */ -static int mdacols[256][2][2]; +static int mda_attr_to_color_table[256][2][2]; void wy700_recalctimings(wy700_t *wy700); void wy700_write(uint32_t addr, uint8_t val, void *priv); @@ -570,7 +570,7 @@ wy700_textline(wy700_t *wy700) /* MDA underline */ if (scanline == 14 && mda && ((attr & 7) == 1)) { for (c = 0; c < cw; c++) - buffer32->line[wy700->displine][(x * cw) + c] = mdacols[attr][blink][1]; + buffer32->line[wy700->displine][(x * cw) + c] = mda_attr_to_color_table[attr][blink][1]; } else /* Draw 16 pixels of character */ { bitmap[0] = fontbase[chr * 32 + 2 * scanline]; @@ -578,11 +578,11 @@ wy700_textline(wy700_t *wy700) for (c = 0; c < 16; c++) { int col; if (c < 8) - col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; + col = (mda ? mda_attr_to_color_table : cga_attr_to_color_table)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; else - col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; + col = (mda ? mda_attr_to_color_table : cga_attr_to_color_table)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - col = mdacols[0][0][0]; + col = mda_attr_to_color_table[0][0][0]; if (w == 40) { buffer32->line[wy700->displine][(x * cw) + 2 * c] = col; buffer32->line[wy700->displine][(x * cw) + 2 * c + 1] = col; @@ -592,7 +592,7 @@ wy700_textline(wy700_t *wy700) if (drawcursor) { for (c = 0; c < cw; c++) - buffer32->line[wy700->displine][(x * cw) + c] ^= (mda ? mdacols : cgacols)[attr][0][1]; + buffer32->line[wy700->displine][(x * cw) + c] ^= (mda ? mda_attr_to_color_table : cga_attr_to_color_table)[attr][0][1]; } ++memaddr; } @@ -902,74 +902,74 @@ wy700_init(UNUSED(const device_t *info)) /* Set up the emulated attributes. * CGA is done in four groups: 00-0F, 10-7F, 80-8F, 90-FF */ for (c = 0; c < 0x10; c++) { - cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16; + cga_attr_to_color_table[c][0][0] = cga_attr_to_color_table[c][1][0] = cga_attr_to_color_table[c][1][1] = 16; if (c & 8) - cgacols[c][0][1] = 15 + 16; + cga_attr_to_color_table[c][0][1] = 15 + 16; else - cgacols[c][0][1] = 7 + 16; + cga_attr_to_color_table[c][0][1] = 7 + 16; } for (c = 0x10; c < 0x80; c++) { - cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16 + 7; + cga_attr_to_color_table[c][0][0] = cga_attr_to_color_table[c][1][0] = cga_attr_to_color_table[c][1][1] = 16 + 7; if (c & 8) - cgacols[c][0][1] = 15 + 16; + cga_attr_to_color_table[c][0][1] = 15 + 16; else - cgacols[c][0][1] = 0 + 16; + cga_attr_to_color_table[c][0][1] = 0 + 16; if ((c & 0x0F) == 8) - cgacols[c][0][1] = 8 + 16; + cga_attr_to_color_table[c][0][1] = 8 + 16; } /* With special cases for 00, 11, 22, ... 77 */ - cgacols[0x00][0][1] = cgacols[0x00][1][1] = 16; + cga_attr_to_color_table[0x00][0][1] = cga_attr_to_color_table[0x00][1][1] = 16; for (c = 0x11; c <= 0x77; c += 0x11) { - cgacols[c][0][1] = cgacols[c][1][1] = 16 + 7; + cga_attr_to_color_table[c][0][1] = cga_attr_to_color_table[c][1][1] = 16 + 7; } for (c = 0x80; c < 0x90; c++) { - cgacols[c][0][0] = 16 + 8; + cga_attr_to_color_table[c][0][0] = 16 + 8; if (c & 8) - cgacols[c][0][1] = 15 + 16; + cga_attr_to_color_table[c][0][1] = 15 + 16; else - cgacols[c][0][1] = 7 + 16; - cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c - 0x80][0][0]; + cga_attr_to_color_table[c][0][1] = 7 + 16; + cga_attr_to_color_table[c][1][0] = cga_attr_to_color_table[c][1][1] = cga_attr_to_color_table[c - 0x80][0][0]; } for (c = 0x90; c < 0x100; c++) { - cgacols[c][0][0] = 16 + 15; + cga_attr_to_color_table[c][0][0] = 16 + 15; if (c & 8) - cgacols[c][0][1] = 8 + 16; + cga_attr_to_color_table[c][0][1] = 8 + 16; else - cgacols[c][0][1] = 7 + 16; + cga_attr_to_color_table[c][0][1] = 7 + 16; if ((c & 0x0F) == 0) - cgacols[c][0][1] = 16; - cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c - 0x80][0][0]; + cga_attr_to_color_table[c][0][1] = 16; + cga_attr_to_color_table[c][1][0] = cga_attr_to_color_table[c][1][1] = cga_attr_to_color_table[c - 0x80][0][0]; } /* Also special cases for 99, AA, ..., FF */ for (c = 0x99; c <= 0xFF; c += 0x11) { - cgacols[c][0][1] = 16 + 15; + cga_attr_to_color_table[c][0][1] = 16 + 15; } /* Special cases for 08, 80 and 88 */ - cgacols[0x08][0][1] = 16 + 8; - cgacols[0x80][0][1] = 16; - cgacols[0x88][0][1] = 16 + 8; + cga_attr_to_color_table[0x08][0][1] = 16 + 8; + cga_attr_to_color_table[0x80][0][1] = 16; + cga_attr_to_color_table[0x88][0][1] = 16 + 8; /* MDA attributes */ for (c = 0; c < 256; c++) { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; + mda_attr_to_color_table[c][0][0] = mda_attr_to_color_table[c][1][0] = mda_attr_to_color_table[c][1][1] = 16; if (c & 8) - mdacols[c][0][1] = 15 + 16; + mda_attr_to_color_table[c][0][1] = 15 + 16; else - mdacols[c][0][1] = 7 + 16; + mda_attr_to_color_table[c][0][1] = 7 + 16; } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + mda_attr_to_color_table[0x70][0][1] = 16; + mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = 16 + 15; + mda_attr_to_color_table[0xF0][0][1] = 16; + mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = 16 + 15; + mda_attr_to_color_table[0x78][0][1] = 16 + 7; + mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = 16 + 15; + mda_attr_to_color_table[0xF8][0][1] = 16 + 7; + mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = 16 + 15; + mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16; + mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; + mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; + mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16; /* Start off in 80x25 text mode */ wy700->cga_stat = 0xF4; From 51882035af8edd23d846955bec716bf59342b9ab Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Thu, 12 Jun 2025 23:39:12 +0200 Subject: [PATCH 1136/1190] Siemens-related fixes. --- src/machine/m_at_socket5.c | 29 ++++++++++++++--------------- src/machine/m_at_socket7_3v.c | 28 +++++++++++++--------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 3ed2bd2c7..b2d3c46f3 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -96,21 +96,21 @@ machine_at_d842_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init(model); + machine_at_common_init(model); device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Onboard */ - pci_register_slot(0x03, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Onboard */ - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */ - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */ + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Onboard */ + pci_register_slot(0x03, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Onboard */ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */ device_add(&keyboard_ps2_pci_device); device_add(&i430nx_device); device_add(&sio_zb_device); device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); + device_add(&intel_flash_bxt_device); return ret; } @@ -127,18 +127,17 @@ static const device_config_t d842_config[] = { .spinner = { 0 }, /*W1*/ .bios = { { .name = "Version 1.03 Revision 1.03.842 (11/24/1994)", .internal_name = "d842", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842.bin", "" } }, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842.BIN", "" } }, { .name = "Version 4.04 Revision 1.05.842 (03/15/1996)", .internal_name = "d842_mar96", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_mar96.bin", "" } }, { .name = "Version 4.04 Revision 1.06.842 (04/03/1998)", .internal_name = "d842_apr98", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_apr98.bin", "" } }, - { .name = "Version 4.04 Revision 1.07.842 (06/02/1998)", .internal_name = "d842_jun98", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98.bin", "" } }, - { .name = "Version 1.03 Revision 1.09.842 (07/08/1996)", .internal_name = "d842_jul96", .bios_type = BIOS_NORMAL, + { .name = "Version 4.04 Revision 1.07.842 (06/02/1998)", .internal_name = "d842_jun98", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98.BIN", "" } }, + { .name = "Version 1.03 Revision 1.09.842 (07/08/1996)", .internal_name = "d842_jul96", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jul96.bin", "" } }, - { .name = "Version 1.03 Revision 1.10.842 (06/04/1998)", .internal_name = "d842_jun98_1", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98_1.bin", "" } }, - + { .name = "Version 1.03 Revision 1.10.842 (06/04/1998)", .internal_name = "d842_jun98_1", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98_1.bin", "" } }, }, }, { .name = "", .description = "", .type = CONFIG_END } @@ -155,7 +154,7 @@ const device_t d842_device = { .init = NULL, .close = NULL, .reset = NULL, - .available = NULL, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = &d842_config[0] diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 7dd1f9bf0..7d29a6f3a 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -628,25 +628,24 @@ machine_at_d943_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 2, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 2, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 3, 2, 4); device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); device_add(&fdc37c665_device); device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_EDO, 0x7, 256); - - - if (gfxcard[0] == VID_INTERNAL) + spd_register(SPD_TYPE_EDO, 0x7, 256); + + if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); if (sound_card_current[0] == SOUND_INTERNAL) @@ -670,11 +669,10 @@ static const device_config_t d943_config[] = { .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct96.bin", "" } }, { .name = "Version 4.05 Revision 1.03.943 (12/12/1996)", .internal_name = "d943_dec96", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_dec96.bin", "" } }, - { .name = "Version 4.05 Revision 1.05.943 (09/04/1997)", .internal_name = "d943_sept97", .bios_type = BIOS_NORMAL, + { .name = "Version 4.05 Revision 1.05.943 (09/04/1997)", .internal_name = "d943_sept97", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_sept97.bin", "" } }, { .name = "Version 4.05 Revision 1.06.943 (10/29/1997)", .internal_name = "d943_oct97", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct97.bin", "" } }, - }, }, { .name = "", .description = "", .type = CONFIG_END } @@ -691,7 +689,7 @@ const device_t d943_device = { .init = NULL, .close = NULL, .reset = NULL, - .available = NULL, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = &d943_config[0] From 8482937f9ff19a5334ca53c0571d409f28b762b5 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Fri, 13 Jun 2025 19:42:59 +0200 Subject: [PATCH 1137/1190] Added the Packard Bell Legend 300SX. --- src/chipset/CMakeLists.txt | 1 + src/chipset/acc2036.c | 346 +++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 1 + src/include/86box/machine.h | 2 + src/include/86box/sio.h | 2 + src/include/86box/video.h | 1 + src/machine/m_at_286_386sx.c | 68 +++++++ src/machine/m_at_386dx_486.c | 1 + src/machine/machine_table.c | 42 +++++ src/sio/sio_um8663f.c | 31 +++- src/video/vid_oak_oti.c | 136 ++++++++------ 11 files changed, 574 insertions(+), 57 deletions(-) create mode 100644 src/chipset/acc2036.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 7817ac052..89998ff39 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(chipset OBJECT 82c100.c + acc2036.c acc2168.c cs8220.c cs8230.c diff --git a/src/chipset/acc2036.c b/src/chipset/acc2036.c new file mode 100644 index 000000000..225c22813 --- /dev/null +++ b/src/chipset/acc2036.c @@ -0,0 +1,346 @@ +/* + * 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. + * + * Implementation of the ACC 2036 chipset. + * + * Authors: Miran Grca, <mgrca8@gmail.com> + * + * Copyright 2025 Miran Grca. + */ +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/port_92.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/chipset.h> + +typedef struct { + uint32_t virt; + uint32_t phys; + + mem_mapping_t mapping; +} ram_page_t; + +typedef struct { + uint8_t reg; + uint8_t regs[32]; + + ram_page_t ram_mid_pages[24]; + ram_page_t ems_pages[4]; +} acc2036_t; + +static uint8_t +acc2036_mem_read(uint32_t addr, void *priv) +{ + ram_page_t *dev = (ram_page_t *) priv; + uint8_t ret = 0xff; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + ret = ram[addr]; + + return ret; +} + +static uint16_t +acc2036_mem_readw(uint32_t addr, void *priv) +{ + ram_page_t *dev = (ram_page_t *) priv; + uint16_t ret = 0xffff; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + ret = *(uint16_t *) &(ram[addr]); + + return ret; +} + +static void +acc2036_mem_write(uint32_t addr, uint8_t val, void *priv) +{ + ram_page_t *dev = (ram_page_t *) priv; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + ram[addr] = val; +} + +static void +acc2036_mem_writew(uint32_t addr, uint16_t val, void *priv) +{ + ram_page_t *dev = (ram_page_t *) priv; + + addr = (addr - dev->virt) + dev->phys; + + if (addr < (mem_size << 10)) + *(uint16_t *) &(ram[addr]) = val; +} + +static void +acc2036_recalc(acc2036_t *dev) +{ + uint32_t ems_bases[4] = { 0x000c0000, 0x000c8000, 0x000d0000, 0x000e0000 }; + + int start_i = (ems_bases[dev->regs[0x0c] & 0x03] - 0x000a0000) >> 14; + int end_i = start_i + 3; + + for (int i = 0; i < 24; i++) { + ram_page_t *rp = &dev->ram_mid_pages[i]; + mem_mapping_disable(&rp->mapping); + } + + for (int i = 0; i < 4; i++) { + ram_page_t *ep = &dev->ems_pages[i]; + mem_mapping_disable(&ep->mapping); + } + + for (int i = 0; i < 24; i++) { + ram_page_t *rp = &dev->ram_mid_pages[i]; + + if ((dev->regs[0x03] & 0x08) && (i >= start_i) && (i <= end_i)) { + /* EMS */ + ram_page_t *ep = &dev->ems_pages[i - start_i]; + + mem_mapping_disable(&rp->mapping); + mem_mapping_set_addr(&ep->mapping, ep->virt, 0x000040000); + mem_mapping_set_exec(&ep->mapping, ram + ep->phys); + mem_set_mem_state_both(ep->virt, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else { + int master_write; + int master_read; + int bit; + int ew_flag; + int er_flag; + int flags; + uint8_t val; + + mem_mapping_set_addr(&rp->mapping, rp->virt, 0x000040000); + mem_mapping_set_exec(&rp->mapping, ram + rp->phys); + + if ((i >= 8) && (i <= 15)) { + /* 0C0000-0DFFFF */ + master_write = dev->regs[0x02] & 0x08; + master_read = dev->regs[0x02] & 0x04; + bit = ((i - 8) >> 1); + val = dev->regs[0x0d] & (1 << bit); + if (i >= 12) { + ew_flag = (dev->regs[0x07] & 0x80) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + er_flag = (dev->regs[0x07] & 0x80) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + } else { + ew_flag = (dev->regs[0x07] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + er_flag = (dev->regs[0x07] & 0x40) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + } + flags = (val && master_write) ? MEM_WRITE_INTERNAL : ew_flag; + flags |= (val && master_read) ? MEM_READ_INTERNAL : er_flag; + mem_set_mem_state_both(rp->virt, 0x00004000, flags); + } else if (i > 15) { + /* 0E0000-0FFFFF */ + master_write = dev->regs[0x02] & 0x02; + master_read = dev->regs[0x02] & 0x01; + bit = (((i - 8) >> 2) + 2); + val = dev->regs[0x0c] & (1 << bit); + if (i >= 20) { + ew_flag = MEM_WRITE_EXTANY; + er_flag = MEM_READ_EXTANY; + } else { + ew_flag = (dev->regs[0x0c] & 0x10) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + er_flag = (dev->regs[0x0c] & 0x10) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + } + flags = (val && master_write) ? MEM_WRITE_INTERNAL : ew_flag; + flags |= (val && master_read) ? MEM_READ_INTERNAL : er_flag; + mem_set_mem_state_both(rp->virt, 0x00004000, flags); + } + } + } + + if (dev->regs[0x00] & 0x40) + mem_set_mem_state_both(0x00fe0000, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else + mem_set_mem_state_both(0x00fe0000, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + for (int i = 0x01; i <= 0x06; i++) { + uint32_t base = 0x00fe0000 - (i * 0x00010000); + + if (dev->regs[i] & 0x40) + mem_set_mem_state_both(base, 0x00008000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else + mem_set_mem_state_both(base, 0x00008000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + if (dev->regs[i] & 0x80) + mem_set_mem_state_both(base + 0x00008000, 0x00008000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else + mem_set_mem_state_both(base + 0x00008000, 0x00008000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + + mem_remap_top(0); + if (dev->regs[0x03] & 0x10) { + if (dev->regs[0x02] & 0x0c) + mem_remap_top(128); + else if (dev->regs[0x02] & 0x03) + mem_remap_top(256); + else + mem_remap_top(384); + } + + flushmmucache_nopc(); +} + +static uint8_t +acc2036_in(uint16_t port, void *priv) { + acc2036_t *dev = (acc2036_t *) priv; + uint8_t reg = dev->reg - 0x20; + uint8_t ret = 0xff; + + if (port & 0x0001) switch (dev->reg) { + default: + break; + case 0x20 ... 0x2e: + case 0x31 ... 0x3f: + ret = dev->regs[reg]; + break; + } else + ret = dev->reg; + + return ret; +} + +static void +acc2036_out(uint16_t port, uint8_t val, void *priv) { + acc2036_t *dev = (acc2036_t *) priv; + uint8_t reg = dev->reg - 0x20; + + if (port & 0x0001) switch (dev->reg) { + default: + break; + case 0x20 ... 0x23: + dev->regs[reg] = val; + acc2036_recalc(dev); + break; + case 0x24 ... 0x2b: + dev->regs[reg] = val; + dev->ems_pages[(reg - 0x04) >> 1].phys = ((dev->regs[reg & 0xfe] & 0x1f) << 19) | + ((dev->regs[reg | 0x01] & 0x1f) << 14); + acc2036_recalc(dev); + break; + case 0x2c: case 0x2d: + dev->regs[reg] = val; + acc2036_recalc(dev); + break; + case 0x2e: + dev->regs[reg] = val | 0x10; + break; + case 0x31: + dev->regs[reg] = val; + mem_a20_alt = (val & 0x01); + mem_a20_recalc(); + flushmmucache(); + if (val & 0x02) { + softresetx86(); /* Pulse reset! */ + cpu_set_edx(); + flushmmucache(); + } + break; + case 0x32 ... 0x3f: + dev->regs[reg] = val; + break; + } else + dev->reg = val; +} + +static void +acc2036_close(void *priv) +{ + acc2036_t *dev = (acc2036_t *) priv; + + free(dev); +} + +static void * +acc2036_init(UNUSED(const device_t *info)) +{ + acc2036_t *dev = (acc2036_t *) calloc(1, sizeof(acc2036_t)); + + for (int i = 0; i < 24; i++) { + ram_page_t *rp = &dev->ram_mid_pages[i]; + + rp->virt = 0x000a0000 + (i << 14); + rp->phys = 0x000a0000 + (i << 14); + mem_mapping_add(&rp->mapping, rp->virt, 0x00004000, + acc2036_mem_read, acc2036_mem_readw, NULL, + acc2036_mem_write, acc2036_mem_writew, NULL, + ram + rp->phys, MEM_MAPPING_INTERNAL, rp); + } + + for (int i = 0; i < 4; i++) { + ram_page_t *ep = &dev->ems_pages[i]; + + ep->virt = 0x000d0000 + (i << 14); + ep->phys = 0x00000000 + (i << 14); + mem_mapping_add(&ep->mapping, ep->virt, 0x00004000, + acc2036_mem_read, acc2036_mem_readw, NULL, + acc2036_mem_write, acc2036_mem_writew, NULL, + ram + ep->phys, MEM_MAPPING_INTERNAL, ep); + mem_mapping_disable(&ep->mapping); + } + + mem_mapping_disable(&ram_mid_mapping); + + dev->regs[0x00] = 0x02; + dev->regs[0x0e] = 0x10; + dev->regs[0x11] = 0x01; + dev->regs[0x13] = 0x40; + dev->regs[0x15] = 0x40; + dev->regs[0x17] = 0x40; + dev->regs[0x19] = 0x40; + dev->regs[0x1b] = 0x40; + dev->regs[0x1c] = 0x22; + dev->regs[0x1d] = 0xc4; + dev->regs[0x1f] = 0x30; + acc2036_recalc(dev); + + mem_a20_alt = 0x01; + mem_a20_recalc(); + flushmmucache(); + + io_sethandler(0x00f2, 0x0002, + acc2036_in, NULL, NULL, acc2036_out, NULL, NULL, dev); + + device_add(&port_92_device); + + return dev; +} + +const device_t acc2036_device = { + .name = "ACC 2036", + .internal_name = "acc2036", + .flags = 0, + .local = 0, + .init = acc2036_init, + .close = acc2036_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 1b5684414..0d750c4cf 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -18,6 +18,7 @@ #define EMU_CHIPSET_H /* ACC */ +extern const device_t acc2036_device; extern const device_t acc2168_device; /* ALi */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index e59ca494a..3b62d28d6 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -197,6 +197,7 @@ enum { MACHINE_CHIPSET_GC100A, MACHINE_CHIPSET_GC103, MACHINE_CHIPSET_HT18, + MACHINE_CHIPSET_ACC_2036, MACHINE_CHIPSET_ACC_2168, MACHINE_CHIPSET_ALI_M1217, MACHINE_CHIPSET_ALI_M6117, @@ -456,6 +457,7 @@ extern int machine_at_px286_init(const machine_t *); extern int machine_at_quadt286_init(const machine_t *); extern int machine_at_mr286_init(const machine_t *); +extern int machine_at_pbl300sx_init(const machine_t *); extern int machine_at_neat_init(const machine_t *); extern int machine_at_neat_ami_init(const machine_t *); extern int machine_at_ataripc4_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 613b294d8..0b07d7a13 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -125,6 +125,8 @@ extern const device_t sio_detect_device; #endif /* USE_SIO_DETECT */ /* UMC */ +extern const device_t um82c862f_device; +extern const device_t um82c862f_ide_device; extern const device_t um82c863f_device; extern const device_t um82c863f_ide_device; extern const device_t um8663af_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 74658708c..77e192291 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -469,6 +469,7 @@ extern const device_t if386jega_device; /* Oak OTI-0x7 */ extern const device_t oti037c_device; +extern const device_t oti037_pbl300sx_device; extern const device_t oti067_device; extern const device_t oti067_acer386_device; extern const device_t oti067_ama932j_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index a295f305a..65fbd4fd9 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -169,6 +169,74 @@ machine_at_quadt386sx_init(const machine_t *model) return ret; } +static const device_config_t pbl300sx_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "pbl300sx", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1991", .internal_name = "pbl300sx_1991", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pbl300sx/V1.10_1113_910723.bin", "" } }, + { .name = "1992", .internal_name = "pbl300sx", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pbl300sx/pb_l300sx_1992.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t pbl300sx_device = { + .name = "Packard Bell Legend 300SX", + .internal_name = "pbl300sx_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pbl300sx_config +}; + +int +machine_at_pbl300sx_init(const machine_t *model) +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&acc2036_device); + + device_add(&keyboard_ps2_phoenix_device); + + device_add(&ide_isa_device); + device_add(&um82c862f_ide_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + return ret; +} + int machine_at_neat_init(const machine_t *model) { diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index b2a335e61..6dd5b1cae 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -822,6 +822,7 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } + static const device_config_t pb450_config[] = { // clang-format off { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 371cb7d47..5c96efc02 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -71,6 +71,7 @@ extern const device_t d842_device; extern const device_t d943_device; extern const device_t dells333sl_device; extern const device_t hot433a_device; +extern const device_t pbl300sx_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -107,6 +108,7 @@ const machine_filter_t machine_chipsets[] = { { "Headland GC100A", MACHINE_CHIPSET_GC100A }, { "Headland GC103", MACHINE_CHIPSET_GC103 }, { "Headland HT18", MACHINE_CHIPSET_HT18 }, + { "ACC 2036", MACHINE_CHIPSET_ACC_2036 }, { "ACC 2168", MACHINE_CHIPSET_ACC_2168 }, { "ALi M1217", MACHINE_CHIPSET_ALI_M1217 }, { "ALi M6117", MACHINE_CHIPSET_ALI_M6117 }, @@ -4301,6 +4303,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Most likely has Phonenix KBC firmware. */ + { + .name = "[ACC 2036] Packard Bell Legend 300SX", + .internal_name = "pbl300sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ACC_2036, + .init = machine_at_pbl300sx_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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &pbl300sx_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &oti037_pbl300sx_device, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[ALi M1217] Acrosser AR-B1374", diff --git a/src/sio/sio_um8663f.c b/src/sio/sio_um8663f.c index 03fa4f9aa..6075fe3e7 100644 --- a/src/sio/sio_um8663f.c +++ b/src/sio/sio_um8663f.c @@ -274,13 +274,42 @@ um8663f_init(UNUSED(const device_t *info)) dev->max_reg = info->local >> 8; - io_sethandler(0x0108, 0x0002, um8663f_read, NULL, NULL, um8663f_write, NULL, NULL, dev); + if (dev->max_reg != 0x00) + io_sethandler(0x0108, 0x0002, um8663f_read, NULL, NULL, um8663f_write, NULL, NULL, dev); um8663f_reset(dev); return dev; } +const device_t um82c862f_device = { + .name = "UMC UM82C862F Super I/O", + .internal_name = "um82c862f", + .flags = 0, + .local = 0x0000, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um82c862f_ide_device = { + .name = "UMC UM82C862F Super I/O (With IDE)", + .internal_name = "um82c862f_ide", + .flags = 0, + .local = 0x0001, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t um82c863f_device = { .name = "UMC UM82C863F Super I/O", .internal_name = "um82c863f", diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 70bac6425..3233f9d00 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -30,6 +30,7 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/plat_unused.h> +#include "cpu.h" #define BIOS_037C_PATH "roms/video/oti/bios.bin" #define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN" @@ -38,13 +39,13 @@ #define BIOS_077_PATH "roms/video/oti/oti077.vbi" #define BIOS_077_ACER100T_PATH "roms/machines/acer100t/oti077_acer100t.BIN" - enum { - OTI_037C = 0, - OTI_067 = 2, - OTI_067_AMA932J = 3, - OTI_067_M300 = 4, - OTI_077 = 5, + OTI_037C = 0, + OTI_037_PBL300SX = 1, + OTI_067 = 2, + OTI_067_AMA932J = 3, + OTI_067_M300 = 4, + OTI_077 = 5, OTI_077_ACER100T = 6 }; @@ -76,14 +77,15 @@ oti_out(uint16_t addr, uint8_t val, void *priv) uint8_t idx; uint8_t enable; - if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3)) + if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3c3)) return; - if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + if (((((addr & 0xfff0) == 0x3d0) || ((addr & 0xfff0) == 0x3b0)) && (addr < 0x3de)) && + !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { - case 0x3C3: + case 0x3c3: if (!oti->chip_id) { oti->enable_register = val & 1; return; @@ -95,20 +97,20 @@ oti_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) + if ((oti->chip_id == OTI_077) || (oti->chip_id == OTI_077_ACER100T)) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); else svga_out(addr, val, svga); return; - case 0x3D4: + case 0x3d4: if (oti->chip_id) svga->crtcreg = val & 0x3f; else svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */ return; - case 0x3D5: + case 0x3d5: if (oti->chip_id && (svga->crtcreg & 0x20)) return; idx = svga->crtcreg; @@ -124,7 +126,8 @@ oti_out(uint16_t addr, uint8_t val, void *priv) if ((idx < 0x0e) || (idx > 0x10)) { if (idx == 0x0c || idx == 0x0d) { svga->fullchange = 3; - svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + + ((svga->crtc[8] & 0x60) >> 5); } else { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -133,14 +136,14 @@ oti_out(uint16_t addr, uint8_t val, void *priv) } break; - case 0x3DE: + case 0x3de: if (oti->chip_id) oti->index = val & 0x1f; else oti->index = val; return; - case 0x3DF: + case 0x3df: idx = oti->index; if (!oti->chip_id) idx &= 0x1f; @@ -223,14 +226,14 @@ oti_in(uint16_t addr, void *priv) addr ^= 0x60; switch (addr) { - case 0x3C2: + case 0x3c2: if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) temp = 0; else temp = 0x10; break; - case 0x3C3: + case 0x3c3: if (oti->chip_id) temp = svga_in(addr, svga); else @@ -248,11 +251,11 @@ oti_in(uint16_t addr, void *priv) case 0x3CF: return svga->gdcreg[svga->gdcaddr & 0xf]; - case 0x3D4: + case 0x3d4: temp = svga->crtcreg; break; - case 0x3D5: + case 0x3d5: if (oti->chip_id) { if (svga->crtcreg & 0x20) temp = 0xff; @@ -262,17 +265,19 @@ oti_in(uint16_t addr, void *priv) temp = svga->crtc[svga->crtcreg & 0x1f]; break; - case 0x3DA: + case 0x3da: if (oti->chip_id) { temp = svga_in(addr, svga); break; } svga->attrff = 0; - /*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again - and expects the diagnostic bits to equal the current border colour. As I understand - it, the 0x3da active enable status does not include the border time, so this may be - an area where OTI-037C is not entirely VGA compatible.*/ + /* + The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again + and expects the diagnostic bits to equal the current border colour. As I understand + it, the 0x3da active enable status does not include the border time, so this may be + an area where OTI-037C is not entirely VGA compatible. + */ svga->cgastat &= ~0x30; /* copy color diagnostic info from the overscan color register */ switch (svga->attrregs[0x12] & 0x30) { @@ -307,13 +312,13 @@ oti_in(uint16_t addr, void *priv) temp = svga->cgastat; break; - case 0x3DE: + case 0x3de: temp = oti->index; if (oti->chip_id) temp |= (oti->chip_id << 5); break; - case 0x3DF: + case 0x3df: idx = oti->index; if (!oti->chip_id) idx &= 0x1f; @@ -441,6 +446,13 @@ oti_init(const device_t *info) #endif break; + case OTI_037_PBL300SX: + romfn = NULL; + oti->chip_id = 0; + oti->vram_size = 256; + oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */ + break; + case OTI_067_AMA932J: romfn = BIOS_067_AMA932J_PATH; oti->chip_id = 2; @@ -478,26 +490,25 @@ oti_init(const device_t *info) break; } - if (romfn != NULL) { + if (romfn != NULL) rom_init(&oti->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } oti->vram_mask = (oti->vram_size << 10) - 1; - if (oti->chip_id == OTI_077_ACER100T){ - /* josephillips: Required to show all BIOS - information on Acer 100T only + if (oti->chip_id == OTI_077_ACER100T) { + /* + josephillips: Required to show all BIOS + information on Acer 100T only */ - video_inform(0x1,&timing_oti); - }else{ + video_inform(0x1, &timing_oti); + } else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); - } svga_init(info, &oti->svga, oti, oti->vram_size << 10, oti_recalctimings, oti_in, oti_out, NULL, NULL); - if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) + if ((oti->chip_id == OTI_077) || (oti->chip_id == OTI_077_ACER100T)) oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ io_sethandler(0x03c0, 32, @@ -662,6 +673,20 @@ const device_t oti037c_device = { .config = NULL }; +const device_t oti037_pbl300sx_device = { + .name = "Oak OTI-037 (Packard Bell Legend 300SX)", + .internal_name = "oti037_pbl300sx", + .flags = DEVICE_ISA, + .local = 1, + .init = oti_init, + .close = oti_close, + .reset = NULL, + .available = NULL, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = NULL +}; + const device_t oti067_device = { .name = "Oak OTI-067", .internal_name = "oti067", @@ -676,20 +701,6 @@ const device_t oti067_device = { .config = oti067_config }; -const device_t oti067_m300_device = { - .name = "Oak OTI-067 (Olivetti M300-08/15)", - .internal_name = "oti067_m300", - .flags = DEVICE_ISA, - .local = 4, - .init = oti_init, - .close = oti_close, - .reset = NULL, - .available = oti067_m300_available, - .speed_changed = oti_speed_changed, - .force_redraw = oti_force_redraw, - .config = oti067_config -}; - const device_t oti067_ama932j_device = { .name = "Oak OTI-067 (AMA-932J)", .internal_name = "oti067_ama932j", @@ -704,21 +715,20 @@ const device_t oti067_ama932j_device = { .config = oti067_ama932j_config }; -const device_t oti077_acer100t_device = { - .name = "Oak OTI-077 (Acer 100T)", - .internal_name = "oti077_acer100t", +const device_t oti067_m300_device = { + .name = "Oak OTI-067 (Olivetti M300-08/15)", + .internal_name = "oti067_m300", .flags = DEVICE_ISA, - .local = 6, + .local = 4, .init = oti_init, .close = oti_close, .reset = NULL, - .available = oti077_acer100t_available, + .available = oti067_m300_available, .speed_changed = oti_speed_changed, .force_redraw = oti_force_redraw, - .config = oti077_acer100t_config + .config = oti067_config }; - const device_t oti077_device = { .name = "Oak OTI-077", .internal_name = "oti077", @@ -732,3 +742,17 @@ const device_t oti077_device = { .force_redraw = oti_force_redraw, .config = oti077_config }; + +const device_t oti077_acer100t_device = { + .name = "Oak OTI-077 (Acer 100T)", + .internal_name = "oti077_acer100t", + .flags = DEVICE_ISA, + .local = 6, + .init = oti_init, + .close = oti_close, + .reset = NULL, + .available = oti077_acer100t_available, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti077_acer100t_config +}; From 8a4e8696b9696fbc3666f6fbf111878d12b35990 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Fri, 13 Jun 2025 19:52:06 +0200 Subject: [PATCH 1138/1190] =?UTF-8?q?Added=20the=20PC=E2=80=99s=20Limited?= =?UTF-8?q?=20(Dell)=2028608L/AT122.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/86box/machine.h | 1 + src/machine/m_at_286_386sx.c | 16 ++++++++++++++ src/machine/machine_table.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 3b62d28d6..3dec461d0 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -477,6 +477,7 @@ extern int machine_at_kmxc02_init(const machine_t *); extern int machine_at_deskmaster286_init(const machine_t *); extern int machine_at_dells200_init(const machine_t *); +extern int machine_at_at122_init(const machine_t *); extern int machine_at_tuliptc7_init(const machine_t *); extern int machine_at_pc8_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 65fbd4fd9..7da687c16 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -360,6 +360,22 @@ machine_at_dells200_init(const machine_t *model) return ret; } +int +machine_at_at122_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/at122/FINAL.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ctat_common_init(model); + + return ret; +} + int machine_at_tuliptc7_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5c96efc02..e90c1e3f1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3419,6 +3419,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC + firmware. */ + { + .name = "[C&T PC/AT] PC's Limited (Dell) 28608L/AT122", + .internal_name = "at122", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_CT_AT, + .init = machine_at_at122_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 12000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .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 + }, /* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC firmware. */ { From 5e9d48ec1b69f345034daa304ec3e21b9b68fbc5 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sat, 14 Jun 2025 16:33:25 +0200 Subject: [PATCH 1139/1190] Added the CAF Technology C747 and assorted OPTi fixes, including the implementation of OPTi 498 for the Mylex 486. --- src/chipset/CMakeLists.txt | 1 + src/chipset/opti283.c | 41 +++- src/chipset/opti495.c | 47 ++++- src/chipset/opti498.c | 360 +++++++++++++++++++++++++++++++++++ src/chipset/opti499.c | 46 ++++- src/chipset/opti895.c | 24 +++ src/include/86box/chipset.h | 4 +- src/include/86box/machine.h | 5 +- src/machine/m_at_386dx_486.c | 35 +++- src/machine/machine_table.c | 60 +++++- 10 files changed, 594 insertions(+), 29 deletions(-) create mode 100644 src/chipset/opti498.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 89998ff39..d61b5c53d 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -49,6 +49,7 @@ add_library(chipset OBJECT opti291.c opti391.c opti495.c + opti498.c opti499.c opti602.c opti822.c diff --git a/src/chipset/opti283.c b/src/chipset/opti283.c index 395ad4212..81780cf10 100644 --- a/src/chipset/opti283.c +++ b/src/chipset/opti283.c @@ -16,6 +16,7 @@ * Copyright 2021 Tiseno100. * Copyright 2021 Miran Grca. */ +#include <math.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> @@ -158,7 +159,20 @@ opti283_shadow_recalc(opti283_t *dev) rom = dev->regs[0x11] & (1 << ((i >> 2) + 4)); opti283_log("OPTI 283: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4))); - if (sh_enable && rom) { + if (sh_copy) { + if (base >= 0x000e0000) + shadowbios_write |= 1; + if (base >= 0x000d0000) + dev->shadow_high |= 1; + + if (base >= 0xe0000) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_INTERNAL\n", base, base + 0x3fff); + } else { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); + } + } else if (sh_enable && rom) { if (base >= 0x000e0000) shadowbios |= 1; if (base >= 0x000d0000) @@ -171,13 +185,8 @@ opti283_shadow_recalc(opti283_t *dev) if (base >= 0x000e0000) shadowbios_write |= 1; - if (sh_copy) { - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); - } else { - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_EXTERNAL\n", base, base + 0x3fff); - } + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); } } else { if (base >= 0xe0000) { @@ -239,9 +248,21 @@ opti283_write(uint16_t addr, uint8_t val, void *priv) dev->regs[dev->index] = (dev->regs[dev->index] & 0x80) | (val & 0x7f); break; - case 0x14: + case 0x14: { + double bus_clk; + switch (val & 0x01) { + default: + case 0x00: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x01: + bus_clk = cpu_busspeed / 4.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); reset_on_hlt = !!(val & 0x40); fallthrough; + } case 0x11: case 0x12: case 0x13: @@ -310,6 +331,8 @@ opti283_init(UNUSED(const device_t *info)) opti283_shadow_recalc(dev); + cpu_set_isa_speed((int) round(cpu_busspeed / 6.0)); + device_add(&port_92_device); return dev; diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index aa4e4b4c5..8521dbd17 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -8,14 +8,13 @@ * * Implementation of the OPTi 82C493/82C495 chipset. * - * - * * Authors: Tiseno100, * Miran Grca, <mgrca8@gmail.com> * * Copyright 2008-2020 Tiseno100. * Copyright 2016-2020 Miran Grca. */ +#include <math.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> @@ -28,6 +27,7 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_fallthrough.h> #include <86box/port_92.h> #include <86box/chipset.h> @@ -166,6 +166,27 @@ opti495_write(uint16_t addr, uint8_t val, void *priv) case 0x26: opti495_recalc(dev); break; + + case 0x25: { + double bus_clk; + switch (val & 0x03) { + default: + case 0x00: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x01: + bus_clk = cpu_busspeed / 4.0; + break; + case 0x02: + bus_clk = cpu_busspeed / 3.0; + break; + case 0x03: + bus_clk = (cpu_busspeed * 2.0) / 5.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + break; + } } } @@ -259,6 +280,8 @@ opti495_init(const device_t *info) io_sethandler(0x00e1, 0x0002, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev); + cpu_set_isa_speed((int) round(cpu_busspeed / 6.0)); + return dev; } @@ -276,11 +299,25 @@ const device_t opti493_device = { .config = NULL }; -const device_t opti495_device = { +const device_t opti495slc_device = { .name = "OPTi 82C495", - .internal_name = "opti495", + .internal_name = "opti495slc", .flags = 0, - .local = OPTI495XLC, + .local = OPTI495SLC, + .init = opti495_init, + .close = opti495_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t opti495sx_device = { + .name = "OPTi 82C495SX", + .internal_name = "opti495sx", + .flags = 0, + .local = OPTI495SX, .init = opti495_init, .close = opti495_close, .reset = NULL, diff --git a/src/chipset/opti498.c b/src/chipset/opti498.c new file mode 100644 index 000000000..2d3dc6709 --- /dev/null +++ b/src/chipset/opti498.c @@ -0,0 +1,360 @@ +/* + * 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. + * + * Implementation of the OPTi 82C498 chipset. + * + * Authors: Miran Grca, <mgrca8@gmail.com> + * + * Copyright 2025 Miran Grca. + */ +#include <math.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + +#ifdef ENABLE_OPTI498_LOG +int opti498_do_log = ENABLE_OPTI498_LOG; + +static void +opti498_log(const char *fmt, ...) +{ + va_list ap; + + if (opti498_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define opti498_log(fmt, ...) +#endif + +typedef struct mem_remapping_t { + uint32_t phys; + uint32_t virt; +} mem_remapping_t; + +typedef struct opti498_t { + uint8_t index; + /* 0x30 for 496/497, 0x70 for 498. */ + uint8_t reg_base; + uint8_t shadow_high; + uint8_t regs[256]; + mem_remapping_t mem_remappings[2]; + mem_mapping_t mem_mappings[2]; +} opti498_t; + +static uint8_t +opti498_read_remapped_ram(uint32_t addr, void *priv) +{ + const mem_remapping_t *dev = (mem_remapping_t *) priv; + + return mem_read_ram((addr - dev->virt) + dev->phys, priv); +} + +static uint16_t +opti498_read_remapped_ramw(uint32_t addr, void *priv) +{ + const mem_remapping_t *dev = (mem_remapping_t *) priv; + + return mem_read_ramw((addr - dev->virt) + dev->phys, priv); +} + +static uint32_t +opti498_read_remapped_raml(uint32_t addr, void *priv) +{ + const mem_remapping_t *dev = (mem_remapping_t *) priv; + + return mem_read_raml((addr - dev->virt) + dev->phys, priv); +} + +static void +opti498_write_remapped_ram(uint32_t addr, uint8_t val, void *priv) +{ + const mem_remapping_t *dev = (mem_remapping_t *) priv; + + mem_write_ram((addr - dev->virt) + dev->phys, val, priv); +} + +static void +opti498_write_remapped_ramw(uint32_t addr, uint16_t val, void *priv) +{ + const mem_remapping_t *dev = (mem_remapping_t *) priv; + + mem_write_ramw((addr - dev->virt) + dev->phys, val, priv); +} + +static void +opti498_write_remapped_raml(uint32_t addr, uint32_t val, void *priv) +{ + const mem_remapping_t *dev = (mem_remapping_t *) priv; + + mem_write_raml((addr - dev->virt) + dev->phys, val, priv); +} + +static void +opti498_shadow_recalc(opti498_t *dev) +{ + uint32_t base; + uint32_t rbase; + uint8_t sh_enable; + uint8_t sh_mode; + uint8_t rom; + uint8_t sh_copy; + + shadowbios = shadowbios_write = 0; + dev->shadow_high = 0; + + opti498_log("OPTI 498: %02X %02X %02X %02X\n", dev->regs[0x02], dev->regs[0x03], dev->regs[0x04], dev->regs[0x05]); + + if (dev->regs[0x02] & 0x80) { + if (dev->regs[0x04] & 0x02) { + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + opti498_log("OPTI 498: F0000-FFFFF READ_EXTANY, WRITE_EXTANY\n"); + } else { + shadowbios_write = 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + opti498_log("OPTI 498: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n"); + } + } else { + shadowbios = 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + opti498_log("OPTI 498: F0000-FFFFF READ_INTERNAL, WRITE_DISABLED\n"); + } + + sh_copy = dev->regs[0x02] & 0x08; + for (uint8_t i = 0; i < 12; i++) { + base = 0xc0000 + (i << 14); + if (i >= 4) + sh_enable = dev->regs[0x03] & (1 << (i - 4)); + else + sh_enable = dev->regs[0x04] & (1 << (i + 4)); + sh_mode = dev->regs[0x02] & (1 << (i >> 2)); + rom = dev->regs[0x02] & (1 << ((i >> 2) + 4)); + opti498_log("OPTI 498: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4))); + + if (sh_copy) { + if (base >= 0x000e0000) + shadowbios_write |= 1; + if (base >= 0x000d0000) + dev->shadow_high |= 1; + + if (base >= 0xe0000) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + opti498_log("OPTI 498: %08X-%08X READ_EXTANY, WRITE_INTERNAL\n", base, base + 0x3fff); + } else { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + opti498_log("OPTI 498: %08X-%08X READ_EXTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); + } + } else if (sh_enable && rom) { + if (base >= 0x000e0000) + shadowbios |= 1; + if (base >= 0x000d0000) + dev->shadow_high |= 1; + + if (sh_mode) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + opti498_log("OPTI 498: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff); + } else { + if (base >= 0x000e0000) + shadowbios_write |= 1; + + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + opti498_log("OPTI 498: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); + } + } else { + if (base >= 0xe0000) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED); + opti498_log("OPTI 498: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff); + } else { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); + opti498_log("OPTI 498: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff); + } + } + } + + rbase = ((uint32_t) (dev->regs[0x05] & 0x3f)) << 20; + + if (rbase > 0) { + dev->mem_remappings[0].virt = rbase; + mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000); + + if (!dev->shadow_high) { + rbase += 0x00020000; + dev->mem_remappings[1].virt = rbase; + mem_mapping_set_addr(&dev->mem_mappings[1], rbase, 0x00020000); + } else + mem_mapping_disable(&dev->mem_mappings[1]); + } else { + mem_mapping_disable(&dev->mem_mappings[0]); + mem_mapping_disable(&dev->mem_mappings[1]); + } + + flushmmucache_nopc(); +} + +static void +opti498_write(uint16_t addr, uint8_t val, void *priv) +{ + opti498_t *dev = (opti498_t *) priv; + uint8_t reg = dev->index - dev->reg_base; + + switch (addr) { + default: + break; + + case 0x22: + dev->index = val; + break; + + case 0x24: + opti498_log("OPTi 498: dev->regs[%02x] = %02x\n", dev->index, val); + + if ((reg >= 0x00) && (reg <= 0x0b)) switch (reg) { + default: + break; + + case 0x00: + dev->regs[reg] = (dev->regs[reg] & 0xc0) | (val & 0x3f); + break; + + case 0x01: + case 0x07 ... 0x0b: + dev->regs[reg] = val; + break; + + case 0x02: + case 0x03: + case 0x04: + case 0x05: + dev->regs[reg] = val; + opti498_shadow_recalc(dev); + break; + + case 0x06: { + double bus_clk; + dev->regs[reg] = val; + switch (val & 0x03) { + default: + case 0x00: + bus_clk = cpu_busspeed / 8.0; + break; + case 0x01: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x02: + bus_clk = cpu_busspeed / 5.0; + break; + case 0x03: + bus_clk = cpu_busspeed / 4.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + reset_on_hlt = !!(val & 0x40); + break; + } + } + + dev->index = 0xff; + break; + } +} + +static uint8_t +opti498_read(uint16_t addr, void *priv) +{ + opti498_t *dev = (opti498_t *) priv; + uint8_t reg = dev->index - dev->reg_base; + uint8_t ret = 0xff; + + if (addr == 0x24) { + if ((reg >= 0x00) && (reg <= 0x0b)) + ret = dev->regs[reg]; + + dev->index = 0xff; + } + + return ret; +} + +static void +opti498_close(void *priv) +{ + opti498_t *dev = (opti498_t *) priv; + + free(dev); +} + +static void * +opti498_init(UNUSED(const device_t *info)) +{ + opti498_t *dev = (opti498_t *) calloc(1, sizeof(opti498_t)); + + dev->reg_base = info->local & 0xff; + + io_sethandler(0x0022, 0x0001, opti498_read, NULL, NULL, opti498_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti498_read, NULL, NULL, opti498_write, NULL, NULL, dev); + + dev->regs[0x00] = 0x1f; + dev->regs[0x01] = 0x8f; + dev->regs[0x02] = 0xf0; + dev->regs[0x07] = 0x70; + dev->regs[0x09] = 0x70; + + dev->mem_remappings[0].phys = 0x000a0000; + dev->mem_remappings[1].phys = 0x000d0000; + + mem_mapping_add(&dev->mem_mappings[0], 0, 0x00020000, + opti498_read_remapped_ram, opti498_read_remapped_ramw, opti498_read_remapped_raml, + opti498_write_remapped_ram, opti498_write_remapped_ramw, opti498_write_remapped_raml, + &ram[dev->mem_remappings[0].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[0]); + mem_mapping_disable(&dev->mem_mappings[0]); + + mem_mapping_add(&dev->mem_mappings[1], 0, 0x00020000, + opti498_read_remapped_ram, opti498_read_remapped_ramw, opti498_read_remapped_raml, + opti498_write_remapped_ram, opti498_write_remapped_ramw, opti498_write_remapped_raml, + &ram[dev->mem_remappings[1].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[1]); + mem_mapping_disable(&dev->mem_mappings[1]); + + opti498_shadow_recalc(dev); + + cpu_set_isa_speed((int) round(cpu_busspeed / 8.0)); + + device_add(&port_92_device); + + return dev; +} + +const device_t opti498_device = { + .name = "OPTi 82C498", + .internal_name = "opti498", + .flags = 0, + .local = 0x70, + .init = opti498_init, + .close = opti498_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index d54e8184e..383b8e3e2 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -16,6 +16,7 @@ * Copyright 2008-2020 Tiseno100. * Copyright 2016-2020 Miran Grca. */ +#include <math.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> @@ -148,9 +149,28 @@ opti499_write(uint16_t addr, uint8_t val, void *priv) default: break; - case 0x20: + case 0x20: { + double coeff = (val & 0x10) ? 1.0 : 2.0; + double bus_clk; + switch (dev->regs[0x25] & 0x03) { + default: + case 0x00: + bus_clk = (cpu_busspeed * coeff) / 6.0; + break; + case 0x01: + bus_clk = (cpu_busspeed * coeff) / 5.0; + break; + case 0x02: + bus_clk = (cpu_busspeed * coeff) / 4.0; + break; + case 0x03: + bus_clk = (cpu_busspeed * coeff) / 3.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); reset_on_hlt = !(val & 0x02); break; + } case 0x21: cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); @@ -163,6 +183,28 @@ opti499_write(uint16_t addr, uint8_t val, void *priv) case 0x2d: opti499_recalc(dev); break; + + case 0x25: { + double coeff = (dev->regs[0x20] & 0x10) ? 1.0 : 2.0; + double bus_clk; + switch (val & 0x03) { + default: + case 0x00: + bus_clk = (cpu_busspeed * coeff) / 8.0; + break; + case 0x01: + bus_clk = (cpu_busspeed * coeff) / 6.0; + break; + case 0x02: + bus_clk = (cpu_busspeed * coeff) / 5.0; + break; + case 0x03: + bus_clk = (cpu_busspeed * coeff) / 4.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + break; + } } } @@ -229,6 +271,8 @@ opti499_reset(void *priv) cpu_update_waitstates(); opti499_recalc(dev); + + cpu_set_isa_speed((int) round((cpu_busspeed * 2.0) / 6.0)); } static void diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index cb55ef2a7..16b324963 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -16,6 +16,7 @@ * Copyright 2008-2020 Tiseno100. * Copyright 2016-2020 Miran Grca. */ +#include <math.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> @@ -182,6 +183,27 @@ opti895_write(uint16_t addr, uint8_t val, void *priv) smram_state_change(dev->smram, 0, !!(val & 0x80)); break; + case 0x25: { + double bus_clk; + switch (val & 0x03) { + default: + case 0x00: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x01: + bus_clk = cpu_busspeed / 5.0; + break; + case 0x02: + bus_clk = cpu_busspeed / 4.0; + break; + case 0x03: + bus_clk = cpu_busspeed / 3.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + break; + } + case 0xe0: if (!(val & 0x01)) dev->forced_green = 0; @@ -294,6 +316,8 @@ opti895_init(const device_t *info) smram_enable(dev->smram, 0x00030000, 0x000b0000, 0x00010000, 0, 1); + cpu_set_isa_speed((int) round(cpu_busspeed / 6.0)); + return dev; } diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 0d750c4cf..7ee8182ea 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -124,7 +124,9 @@ extern const device_t opti381_device; extern const device_t opti391_device; extern const device_t opti481_device; extern const device_t opti493_device; -extern const device_t opti495_device; +extern const device_t opti495slc_device; +extern const device_t opti495sx_device; +extern const device_t opti498_device; extern const device_t opti499_device; extern const device_t opti601_device; extern const device_t opti602_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 3dec461d0..6fba13dc5 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -241,7 +241,9 @@ enum { MACHINE_CHIPSET_OPTI_391, MACHINE_CHIPSET_OPTI_481, MACHINE_CHIPSET_OPTI_493, - MACHINE_CHIPSET_OPTI_495, + MACHINE_CHIPSET_OPTI_495SLC, + MACHINE_CHIPSET_OPTI_495SX, + MACHINE_CHIPSET_OPTI_498, MACHINE_CHIPSET_OPTI_499, MACHINE_CHIPSET_OPTI_895_802G, MACHINE_CHIPSET_OPTI_547_597, @@ -547,6 +549,7 @@ extern int machine_at_winbios1429_init(const machine_t *); extern int machine_at_opti495_init(const machine_t *); extern int machine_at_opti495_ami_init(const machine_t *); extern int machine_at_opti495_mr_init(const machine_t *); +extern int machine_at_c747_init(const machine_t *); extern int machine_at_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 6dd5b1cae..6de17101c 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -682,7 +682,7 @@ machine_at_opti495_init(const machine_t *model) machine_at_common_init(model); - device_add(&opti495_device); + device_add(&opti495slc_device); device_add(&keyboard_at_device); @@ -697,7 +697,7 @@ machine_at_opti495_ami_common_init(const machine_t *model) { machine_at_common_init(model); - device_add(&opti495_device); + device_add(&opti495sx_device); device_add(&keyboard_at_ami_device); @@ -737,6 +737,34 @@ machine_at_opti495_mr_init(const machine_t *model) return ret; } +int +machine_at_c747_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/c747/486-C747 Tandon.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + /* The EFAR chipset is a rebrand of the OPTi 495SX. */ + device_add(&opti495sx_device); + + /* + No idea what KBC it actually has but this produces the + desired behavior: command A9 does absolutely nothing. + */ + device_add(&keyboard_at_siemens_device); + + device_add(&ide_isa_device); + device_add(&um82c862f_ide_device); + + return ret; +} + int machine_at_exp4349_init(const machine_t *model) { @@ -975,7 +1003,8 @@ machine_at_mvi486_init(const machine_t *model) machine_at_common_init(model); - device_add(&opti495_device); + device_add(&opti498_device); + device_add(&keyboard_at_device); device_add(&pc87311_ide_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e90c1e3f1..39b5e05db 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -152,7 +152,9 @@ const machine_filter_t machine_chipsets[] = { { "OPTi 391", MACHINE_CHIPSET_OPTI_391 }, { "OPTi 481", MACHINE_CHIPSET_OPTI_481 }, { "OPTi 493", MACHINE_CHIPSET_OPTI_493 }, - { "OPTi 495", MACHINE_CHIPSET_OPTI_495 }, + { "OPTi 495SLC", MACHINE_CHIPSET_OPTI_495SLC }, + { "OPTi 495SX", MACHINE_CHIPSET_OPTI_495SX }, + { "OPTi 498", MACHINE_CHIPSET_OPTI_498 }, { "OPTi 499", MACHINE_CHIPSET_OPTI_499 }, { "OPTi 895/802G", MACHINE_CHIPSET_OPTI_895_802G }, { "OPTi 547/597", MACHINE_CHIPSET_OPTI_547_597 }, @@ -5800,10 +5802,10 @@ const machine_t machines[] = { but the BIOS sends commands C9 without a parameter and D5, both of which are Phoenix MultiKey commands. */ { - .name = "[OPTi 495] U-Board OPTi 495SLC", + .name = "[OPTi 495SLC] U-Board OPTi 495SLC", .internal_name = "award495", .type = MACHINE_TYPE_386DX, - .chipset = MACHINE_CHIPSET_OPTI_495, + .chipset = MACHINE_CHIPSET_OPTI_495SLC, .init = machine_at_opti495_init, .p1_handler = NULL, .gpio_handler = NULL, @@ -6042,12 +6044,52 @@ const machine_t machines[] = { }, /* 386DX/486 machines */ + /* Has AMIKey F KBC firmware. The EFAR chipst is a rebrand of OPTi 495SX. */ + { + .name = "[OPTi 495SX] CAF Technology C747", + .internal_name = "c747", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_OPTI_495SX, + .init = machine_at_c747_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_SOCKET1, + .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_APM | MACHINE_IDE, + .ram = { + .min = 1024, + .max = 32768, + .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 AMIKey F KBC firmware. */ { - .name = "[OPTi 495] DataExpert SX495", + .name = "[OPTi 495SX] DataExpert SX495", .internal_name = "ami495", .type = MACHINE_TYPE_386DX_486, - .chipset = MACHINE_CHIPSET_OPTI_495, + .chipset = MACHINE_CHIPSET_OPTI_495SX, .init = machine_at_opti495_ami_init, .p1_handler = NULL, .gpio_handler = NULL, @@ -6084,10 +6126,10 @@ const machine_t machines[] = { }, /* Has AMIKey F KBC firmware (it's just the MR BIOS for the above machine). */ { - .name = "[OPTi 495] DataExpert SX495 (MR BIOS)", + .name = "[OPTi 495SX] DataExpert SX495 (MR BIOS)", .internal_name = "mr495", .type = MACHINE_TYPE_386DX_486, - .chipset = MACHINE_CHIPSET_OPTI_495, + .chipset = MACHINE_CHIPSET_OPTI_495SX, .init = machine_at_opti495_mr_init, .p1_handler = NULL, .gpio_handler = NULL, @@ -6409,10 +6451,10 @@ const machine_t machines[] = { /* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix copyright. */ { - .name = "[OPTi 495] Mylex MVI486", + .name = "[OPTi 498] Mylex MVI486", .internal_name = "mvi486", .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_OPTI_495, + .chipset = MACHINE_CHIPSET_OPTI_498, .init = machine_at_mvi486_init, .p1_handler = NULL, .gpio_handler = NULL, From b394480a0605cb4be703f9b32ade7bc5c709cc68 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sat, 14 Jun 2025 21:06:57 +0200 Subject: [PATCH 1140/1190] Assorted machines and JEGA/JVGA fixes. --- src/machine/m_at_286_386sx.c | 2 -- src/machine/m_at_386dx_486.c | 4 ---- src/video/vid_ega.c | 8 +++++--- src/video/vid_jega.c | 30 +++++++++++++++++++++++++++--- src/video/vid_svga.c | 8 +++++--- 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 7da687c16..eb5394ba4 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -227,8 +227,6 @@ machine_at_pbl300sx_init(const machine_t *model) device_add(&acc2036_device); device_add(&keyboard_ps2_phoenix_device); - - device_add(&ide_isa_device); device_add(&um82c862f_ide_device); if (gfxcard[0] == VID_INTERNAL) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 6de17101c..0c0582c3c 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -758,8 +758,6 @@ machine_at_c747_init(const machine_t *model) desired behavior: command A9 does absolutely nothing. */ device_add(&keyboard_at_siemens_device); - - device_add(&ide_isa_device); device_add(&um82c862f_ide_device); return ret; @@ -1057,8 +1055,6 @@ machine_at_advantage40xxd_init(const machine_t *model) device_add(machine_get_vid_device(machine)); device_add(&keyboard_ps2_phoenix_device); - - device_add(&ide_vlb_device); device_add(&um82c863f_ide_device); device_add(&intel_flash_bxt_device); diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 1cfea782c..21671f4b3 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -158,9 +158,11 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if (ega->alt_addr == 1) base_addr = 0x02a0; #endif - io_removehandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - if (!(val & 1)) - io_sethandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + if (ega->priv_parent == NULL) { + io_removehandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + if (!(val & 1)) + io_sethandler(base_addr, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + } ega_recalctimings(ega); if ((type == EGA_TYPE_COMPAQ) && !(val & 0x02)) mem_mapping_disable(&ega->mapping); diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 257acfff0..f49c92e64 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -151,6 +151,8 @@ 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); } +static uint8_t jega_in(uint16_t addr, void *priv); + static uint16_t SJIS_to_SEQ(uint16_t sjis) { @@ -422,7 +424,10 @@ jega_out(uint16_t addr, uint8_t val, void *priv) if (!jega->attrff) { jega->attraddr = val & 31; if ((val & 0x20) != jega->attr_palette_enable) { - jega->ega.fullchange = 3; + if (jega->is_vga) + jega->vga.svga.fullchange = 3; + else + jega->ega.fullchange = 3; jega->attr_palette_enable = val & 0x20; jega_recalctimings(jega); } @@ -449,6 +454,13 @@ jega_out(uint16_t addr, uint8_t val, void *priv) } jega->attrff ^= 1; break; + case 0x3c2: + if (jega->regs[RMOD1] & 0x0c) { + io_removehandler(0x03a0, 0x0020, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); + if (!(val & 1)) + io_sethandler(0x03a0, 0x0020, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); + } + break; case 0x3b4: case 0x3d4: /* Index 0x00-0x1F (write only), 0xB8-0xDF (write and read) */ @@ -742,9 +754,19 @@ jega_commoninit(const device_t *info, void *priv, int vga) jega->is_vga = vga; if (vga) { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); - vga_init(info, &jega->vga, 1); + svga_init(info, &jega->vga.svga, &jega->vga, 1 << 18, /*256kb*/ + NULL, + jega_in, jega_out, + NULL, + NULL); + + jega->vga.svga.bpp = 8; + jega->vga.svga.miscout = 1; + + jega->vga.svga.vga_enabled = 0; jega->vga.svga.priv_parent = jega; jega->pallook = jega->vga.svga.pallook; + io_sethandler(0x03c0, 0x0020, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); } else { for (int c = 0; c < 256; c++) { pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); @@ -758,9 +780,11 @@ jega_commoninit(const device_t *info, void *priv, int vga) 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(0x03c0, 0x001c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); } /* I/O 3DD and 3DE are used by Oki if386 */ - io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); + // io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); jega->regs[RMOD1] = 0x48; } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 449a7bd43..f9d7bc4a0 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -280,9 +280,11 @@ svga_out(uint16_t addr, uint8_t val, void *priv) case 0x3c2: svga->miscout = val; svga->vidclock = val & 4; - io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->priv); - if (!(val & 1)) - io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->priv); + if (svga->priv_parent == NULL) { + io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->priv); + if (!(val & 1)) + io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->priv); + } svga_recalctimings(svga); break; case 0x3c3: From 30ae882263a409d6b127669bf02ed0363d602ec2 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Sun, 15 Jun 2025 02:55:32 +0200 Subject: [PATCH 1141/1190] Added the Tulip PC Compact 2, the Tulip DGA font ROM, and assorted font ROM-related improvements. --- src/device/keyboard_xt.c | 47 ++++++++++++++++++++++++++++---- src/include/86box/keyboard.h | 1 + src/include/86box/machine.h | 1 + src/include/86box/video.h | 1 + src/machine/m_xt.c | 29 ++++++++++++++++++++ src/machine/machine_table.c | 39 ++++++++++++++++++++++++++ src/video/vid_cga.c | 28 +++++++++++++++++++ src/video/vid_hercules.c | 26 ++++++++++-------- src/video/vid_hercules_incolor.c | 44 +++++++++++++++++++++++++++++- src/video/vid_hercules_plus.c | 36 ++++++++++++++++++++++++ src/video/vid_mda.c | 5 +++- 11 files changed, 238 insertions(+), 19 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 7e419b39d..5190de839 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -69,6 +69,7 @@ enum { KBD_TYPE_ZENITH, KBD_TYPE_PRAVETZ, KBD_TYPE_HYUNDAI, + KBD_TYPE_FE2010, KBD_TYPE_XTCLONE }; @@ -80,6 +81,7 @@ typedef struct xtkbd_t { uint8_t pa; uint8_t pb; uint8_t pd; + uint8_t cfg; uint8_t clock; uint8_t key_waiting; uint8_t type; @@ -832,12 +834,26 @@ kbd_write(uint16_t port, uint8_t val, void *priv) kbd_log("XTkbd: Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); #endif break; -#ifdef ENABLE_KEYBOARD_XT_LOG + case 0x62: /* Switch Register (aka Port C) */ +#ifdef ENABLE_KEYBOARD_XT_LOG if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) kbd_log("XTkbd: Cassette IN is %i\n", !!(val & 0x10)); - break; #endif + if (kbd->type == KBD_TYPE_FE2010) { + kbd_log("XTkbd: Switch register in is %02X\n", val); + if (!(kbd->cfg & 0x08)) + kbd->pd = (kbd->pd & 0x30) | (val & 0xcf); + } + break; + + case 0x63: + if (kbd->type == KBD_TYPE_FE2010) { + kbd_log("XTkbd: Configuration register in is %02X\n", val); + if (!(kbd->cfg & 0x08)) + kbd->cfg = val; + } + break; case 0xc0 ... 0xcf: /* Pravetz Flags */ kbd_log("XTkbd: Port %02X out: %02X\n", port, val); @@ -912,7 +928,12 @@ kbd_read(uint16_t port, void *priv) break; case 0x62: /* Switch Register (aka Port C) */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + if (kbd->type == KBD_TYPE_FE2010) { + if (kbd->pb & 0x04) /* PB2 */ + ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00); + else + ret = kbd->pd >> 4; + } else if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) { if (kbd->pb & 0x04) /* PB2 */ switch (mem_size + isa_mem_size) { @@ -1037,7 +1058,7 @@ kbd_init(const device_t *info) (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_VTECH)) { + (kbd->type == KBD_TYPE_VTECH) || (kbd->type == KBD_TYPE_FE2010)) { /* DIP switch readout: bit set = OFF, clear = ON. */ if (kbd->type == KBD_TYPE_OLIVETTI) /* Olivetti M19 @@ -1057,7 +1078,7 @@ kbd_init(const device_t *info) /* Switches 3, 4 - memory size. */ if ((kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_HYUNDAI) || (kbd->type == KBD_TYPE_COMPAQ) || - (kbd->type == KBD_TYPE_TOSHIBA)) { + (kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_FE2010)) { switch (mem_size) { case 256: kbd->pd |= 0x00; @@ -1356,7 +1377,7 @@ const device_t keyboard_xt_zenith_device = { const device_t keyboard_xt_hyundai_device = { .name = "Hyundai XT Keyboard", - .internal_name = "keyboard_x_hyundai", + .internal_name = "keyboard_xt_hyundai", .flags = 0, .local = KBD_TYPE_HYUNDAI, .init = kbd_init, @@ -1368,6 +1389,20 @@ const device_t keyboard_xt_hyundai_device = { .config = NULL }; +const device_t keyboard_xt_fe2010_device = { + .name = "Faraday FE2010 XT Keyboard", + .internal_name = "keyboard_xt_fe2010", + .flags = 0, + .local = KBD_TYPE_FE2010, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t keyboard_xtclone_device = { .name = "XT (Clone) Keyboard", .internal_name = "keyboard_xtclone", diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index b9bac0821..62938fae4 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -228,6 +228,7 @@ extern const device_t keyboard_xt_lxt3_device; extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_xt_hyundai_device; +extern const device_t keyboard_xt_fe2010_device; extern const device_t keyboard_xtclone_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 6fba13dc5..90b596ae8 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -980,6 +980,7 @@ extern int machine_xt_kaypropc_init(const machine_t *); extern int machine_xt_sansx16_init(const machine_t *); extern int machine_xt_bw230_init(const machine_t *); extern int machine_xt_pb8810_init(const machine_t *); +extern int machine_xt_tuliptc8_init(const machine_t *); extern int machine_xt_v20xt_init(const machine_t *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 77e192291..c23c341a0 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -75,6 +75,7 @@ enum { #define FONT_IBM_MDA_437_NORDIC_PATH "roms/video/mda/4733197.bin" #define FONT_KAM_PATH "roms/video/mda/kam.bin" #define FONT_KAMCL16_PATH "roms/video/mda/kamcl16.bin" +#define FONT_TULIP_DGA_PATH "roms/video/mda/tulip-dga-bios.bin" typedef struct video_timings_t { int type; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index d71d16c15..c94549463 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -39,6 +39,7 @@ #include <86box/keyboard.h> #include <86box/rom.h> #include <86box/machine.h> +#include <86box/nvr.h> #include <86box/chipset.h> #include <86box/port_6x.h> #include <86box/video.h> @@ -668,6 +669,34 @@ machine_xt_amixt_init(const machine_t *model) return ret; } +int +machine_xt_tuliptc8_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tuliptc8/tulip-bios_xt_compact_2.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_xt_fe2010_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + machine_common_init(model); + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + nmi_init(); + standalone_gameport_type = &gameport_device; + + device_add(&amstrad_megapc_nvr_device); + + return ret; +} + // TODO // Onboard EGA Graphics (NSI Logic EVC315-S on early boards STMicroelectronics EGA on later revisions) // RTC diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 39b5e05db..3f324f4d6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2030,6 +2030,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[V20] Tulip PC Compact 2", + .internal_name = "tuliptc8", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_tuliptc8_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK(CPU_8088), + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 63, + .kbc_device = &keyboard_xtclone_device, + .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 + }, /* 8086 Machines */ { diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 72389d219..79b9360f5 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -777,6 +777,18 @@ cga_standalone_init(UNUSED(const device_t *info)) } } + switch(device_get_config_int("font")) { + case 0: + loadfont(FONT_IBM_MDA_437_PATH, 0); + break; + case 1: + loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0); + break; + case 4: + loadfont(FONT_TULIP_DGA_PATH, 0); + break; + } + return cga; } @@ -880,6 +892,22 @@ const device_config_t cga_config[] = { }, .bios = { { 0 } } }, + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "US (CP 437)", .value = 0 }, + { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, + { .description = "Tulip DGA", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "snow_enabled", .description = "Snow emulation", diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 5e0ac1bc9..229ddcca8 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -555,6 +555,9 @@ hercules_init(UNUSED(const device_t *info)) case 3: loadfont(FONT_KAMCL16_PATH, 0); break; + case 4: + loadfont(FONT_TULIP_DGA_PATH, 0); + break; } timer_add(&dev->timer, hercules_poll, dev, 1); @@ -649,17 +652,6 @@ static const device_config_t hercules_config[] = { }, .bios = { { 0 } } }, - { - .name = "blend", - .description = "Blend", - .type = CONFIG_BINARY, - .default_string = NULL, - .default_int = 1, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } }, - .bios = { { 0 } } - }, { .name = "font", .description = "Font", @@ -673,10 +665,22 @@ static const device_config_t hercules_config[] = { { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, + { .description = "Tulip DGA", .value = 4 }, { .description = "" } }, .bios = { { 0 } } }, + { + .name = "blend", + .description = "Blend", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; diff --git a/src/video/vid_hercules_incolor.c b/src/video/vid_hercules_incolor.c index c4751e8fa..eceb440f9 100644 --- a/src/video/vid_hercules_incolor.c +++ b/src/video/vid_hercules_incolor.c @@ -992,6 +992,24 @@ incolor_init(UNUSED(const device_t *info)) dev->vram = (uint8_t *) malloc(0x40000); /* 4 planes of 64k */ + switch(device_get_config_int("font")) { + case 0: + loadfont(FONT_IBM_MDA_437_PATH, 0); + break; + case 1: + loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0); + break; + case 2: + loadfont(FONT_KAM_PATH, 0); + break; + case 3: + loadfont(FONT_KAMCL16_PATH, 0); + break; + case 4: + loadfont(FONT_TULIP_DGA_PATH, 0); + break; + } + timer_add(&dev->timer, incolor_poll, dev, 1); mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, @@ -1044,6 +1062,30 @@ speed_changed(void *priv) recalc_timings(dev); } +static const device_config_t incolor_config[] = { + // clang-format off + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "US (CP 437)", .value = 0 }, + { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, + { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, + { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, + { .description = "Tulip DGA", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t incolor_device = { .name = "Hercules InColor", .internal_name = "incolor", @@ -1055,5 +1097,5 @@ const device_t incolor_device = { .available = NULL, .speed_changed = speed_changed, .force_redraw = NULL, - .config = NULL + .config = incolor_config }; diff --git a/src/video/vid_hercules_plus.c b/src/video/vid_hercules_plus.c index 0c6125d0b..7e1aec943 100644 --- a/src/video/vid_hercules_plus.c +++ b/src/video/vid_hercules_plus.c @@ -629,6 +629,24 @@ herculesplus_init(UNUSED(const device_t *info)) dev->vram = (uint8_t *) malloc(0x10000); /* 64k VRAM */ dev->monitor_index = monitor_index_global; + switch(device_get_config_int("font")) { + case 0: + loadfont(FONT_IBM_MDA_437_PATH, 0); + break; + case 1: + loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0); + break; + case 2: + loadfont(FONT_KAM_PATH, 0); + break; + case 3: + loadfont(FONT_KAMCL16_PATH, 0); + break; + case 4: + loadfont(FONT_TULIP_DGA_PATH, 0); + break; + } + timer_add(&dev->timer, herculesplus_poll, dev, 1); mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, @@ -715,6 +733,24 @@ static const device_config_t herculesplus_config[] = { }, .bios = { { 0 } } }, + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "US (CP 437)", .value = 0 }, + { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, + { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, + { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, + { .description = "Tulip DGA", .value = 4 }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "blend", .description = "Blend", diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index f3d881769..f7c114daa 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -337,13 +337,15 @@ mda_standalone_init(UNUSED(const device_t *info)) case 1: loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0); break; - case 2: loadfont(FONT_KAM_PATH, 0); break; case 3: loadfont(FONT_KAMCL16_PATH, 0); break; + case 4: + loadfont(FONT_TULIP_DGA_PATH, 0); + break; } mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, @@ -419,6 +421,7 @@ static const device_config_t mda_config[] = { { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, + { .description = "Tulip DGA", .value = 4 }, { .description = "" } }, .bios = { { 0 } } From a92f7367f2416cbd5b3f086438d72704a0d6ea43 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Sun, 15 Jun 2025 21:32:08 +0200 Subject: [PATCH 1142/1190] Fix mach8/32 win2000 blit regression (June 15th, 2025) If the height is 1, then make sure Cur_X is used for the destination X start, otherwise, Dest_X_Start is the destination X start for the blit. This fixes some blit errors on Win2000's mach8/32 drivers. --- src/include/86box/vid_ati_mach8.h | 1 + src/video/vid_ati_mach8.c | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index d5e80d0c8..e999c7087 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -137,6 +137,7 @@ typedef struct mach_t { int16_t dx_end; int16_t dy; int16_t dy_end; + int16_t dx_first_row_start; int16_t dx_start; int16_t dy_start; int16_t cy; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 9dd736cd7..4133b730e 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -817,6 +817,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.dy |= ~0x5ff; /*Destination Width*/ + mach->accel.dx_first_row_start = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + mach->accel.dx_first_row_start |= ~0x5ff; + mach->accel.dx_start = mach->accel.dest_x_start; if (mach->accel.dest_x_start >= 0x600) mach->accel.dx_start |= ~0x5ff; @@ -831,16 +835,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } else if (mach->accel.dx_end < mach->accel.dx_start) { mach->accel.width = (mach->accel.dx_start - mach->accel.dx_end); mach->accel.stepx = -1; - if (dev->accel.dx > 0) - dev->accel.dx--; - mach_log("BitBLT: Dst Negative X, dxstart = %d, end = %d, width = %d, dx = %d, dpconfig = %04x.\n", - mach->accel.dest_x_start, mach->accel.dest_x_end, mach->accel.width, dev->accel.dx, - mach->accel.dp_config); } else { mach->accel.stepx = 1; mach->accel.width = 0; - mach_log("BitBLT: Dst Indeterminate X, dpconfig = %04x, destxend = %d, destxstart = %d.\n", - mach->accel.dp_config, mach->accel.dest_x_end, mach->accel.dest_x_start); } dev->accel.sx = 0; @@ -869,6 +866,24 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config == 0x4011) mach->accel.height++; + if (mach->accel.height == 1) { + if (mach->accel.dx_end > mach->accel.dx_first_row_start) { + mach->accel.width = (mach->accel.dx_end - mach->accel.dx_first_row_start); + mach->accel.stepx = 1; + } else if (mach->accel.dx_end < mach->accel.dx_first_row_start) { + mach->accel.width = (mach->accel.dx_first_row_start - mach->accel.dx_end); + mach->accel.stepx = -1; + } else { + mach->accel.stepx = 1; + mach->accel.width = 0; + } + } + + if (mach->accel.stepx == -1) { + if (dev->accel.dx > 0) + dev->accel.dx--; + } + dev->accel.sy = 0; dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); @@ -6475,6 +6490,7 @@ ati8514_io_set(svga_t *svga) io_sethandler(0xeeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xf2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xf6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xfeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); } From 50ce93f3f7682d3db35004921f51592e84ac59c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= <oubattler@gmail.com> Date: Mon, 16 Jun 2025 19:09:39 +0200 Subject: [PATCH 1143/1190] (S)VGA: Also override overscan and horizontal timings and calculation when override is enabled. --- 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 449a7bd43..cf3a22c5c 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -915,7 +915,7 @@ svga_recalctimings(svga_t *svga) if (vblankend <= svga->vblankstart) vblankend += 0x00000080; - if (svga->hoverride) { + if (svga->hoverride || svga->override) { if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; From 231cf519488409ed80ef89c5a86bcd9ecb9ca5c5 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Mon, 16 Jun 2025 19:46:48 +0200 Subject: [PATCH 1144/1190] Some cleanup and work on the Mach64 side (June 16th, 2025) 1. Make sure the horizontal sync part is actually loaded. 2. The Mach64 *T parts have an integrated RAMDAC as opposed to the non-*T parts which have a separate RAMDAC (like the ATI68860), so modify accordingly, this also fixes intermittent black cursors in Win95 OSR2.5 using updated Mach64 drivers in the VT2. 3. Make sure the type of the Mach64 is properly assigned as such (in info->local). --- src/video/vid_ati68860_ramdac.c | 73 ++++++---- src/video/vid_ati_mach64.c | 236 +++++++++++++++++++++++++++----- 2 files changed, 244 insertions(+), 65 deletions(-) diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 17b2a6d22..e3e486d57 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -261,38 +261,57 @@ void ati68860_hwcursor_draw(svga_t *svga, int displine) { const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; + int comb; int offset; - uint8_t dat; + int x_pos; + int y_pos; + int shift = 0; + uint16_t dat; uint32_t col0 = ramdac->pallook[0]; uint32_t col1 = ramdac->pallook[1]; + uint32_t *p; - offset = svga->dac_hwcursor_latch.xoff; - for (uint32_t x = 0; x < 64 - svga->dac_hwcursor_latch.xoff; x += 4) { - dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)]; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; - dat >>= 2; - offset += 4; + offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + if (svga->packed_4bpp) + shift = 1; + + for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += (8 >> shift)) { + if (shift) { + dat = svga->vram[(svga->dac_hwcursor_latch.addr) & svga->vram_mask] & 0x0f; + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 4); + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 2) & svga->vram_mask] << 8); + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 3) & svga->vram_mask] << 12); + } else { + dat = svga->vram[svga->dac_hwcursor_latch.addr & svga->vram_mask]; + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 8); + } + for (int xx = 0; xx < (8 >> shift); xx++) { + comb = (dat >> (xx << 1)) & 0x03; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + if (offset >= svga->dac_hwcursor_latch.x) { + switch (comb) { + case 0: + p[x_pos] = col0; + break; + case 1: + p[x_pos] = col1; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + } + offset++; + } + svga->dac_hwcursor_latch.addr += 2; } - - svga->dac_hwcursor_latch.addr += 16; } static void diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index cb7abc13c..74086dab1 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -524,14 +524,18 @@ mach64_recalctimings(svga_t *svga) svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; svga->rowoffset = (mach64->crtc_off_pitch >> 22); svga->clock = (cpuclock * (double) (1ULL << 32)) / ics2595_getclock(svga->clock_gen); - svga->memaddr_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; + svga->memaddr_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; svga->linedbl = svga->rowcount = 0; svga->split = 0xffffff; svga->vblankstart = svga->dispend; svga->rowcount = mach64->crtc_gen_cntl & 1; svga->rowoffset <<= 1; + if (mach64->type == MACH64_GX) ati68860_ramdac_set_render(svga->ramdac, svga); + + svga->packed_4bpp = !!(((mach64->crtc_gen_cntl >> 8) & 7) == BPP_4); + switch ((mach64->crtc_gen_cntl >> 8) & 7) { case BPP_4: if (mach64->type != MACH64_GX) @@ -572,8 +576,9 @@ mach64_recalctimings(svga_t *svga) } svga->vram_display_mask = mach64->vram_mask; - } else + } else { svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; + } } void @@ -2310,6 +2315,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *priv) { mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; uint8_t ret = 0xff; if (!(addr & 0x400)) { @@ -2524,8 +2530,22 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0xc3: if (mach64->type == MACH64_GX) ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); - else - ret = ati68860_ramdac_in(addr & 3, mach64->svga.ramdac, &mach64->svga); + else { + switch (addr & 3) { + case 0: + ret = svga_in(0x3c8, svga); + break; + case 1: + ret = svga_in(0x3c9, svga); + break; + case 2: + ret = svga_in(0x3c6, svga); + break; + case 3: + ret = svga_in(0x3c7, svga); + break; + } + } break; case 0xc4: case 0xc5: @@ -2962,7 +2982,7 @@ mach64_ext_readl(uint32_t addr, void *priv) uint32_t ret; if (!(addr & 0x400)) { - mach64_log("nmach64_ext_readl: addr=%04x\n", addr); + mach64_log("mach64_ext_readl: addr=%04x\n", addr); ret = 0xffffffff; } else switch (addr & 0x3ff) { @@ -3101,6 +3121,7 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) } else if (addr & 0x300) { mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE); } else { + mach64_log("mach64_ext_writeb: addr=%04x val=%02x\n", addr & 0x3ff, val); switch (addr & 0x3ff) { case 0x00: case 0x01: @@ -3189,39 +3210,48 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) case 0x62: case 0x63: WRITE8(addr, mach64->cur_clr0, val); - if (mach64->type == MACH64_VT2) - ati68860_ramdac_set_pallook(mach64->svga.ramdac, 0, makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff)); break; case 0x64: case 0x65: case 0x66: case 0x67: WRITE8(addr, mach64->cur_clr1, val); - if (mach64->type == MACH64_VT2) - ati68860_ramdac_set_pallook(mach64->svga.ramdac, 1, makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff)); break; case 0x68: case 0x69: case 0x6a: case 0x6b: WRITE8(addr, mach64->cur_offset, val); - svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) * 8; + if (mach64->type == MACH64_GX) + svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) << 3; + else + svga->hwcursor.addr = (mach64->cur_offset & 0xfffff) << 3; break; case 0x6c: case 0x6d: case 0x6e: case 0x6f: WRITE8(addr, mach64->cur_horz_vert_posn, val); - svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; - svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; + if (mach64->type == MACH64_GX) { + svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; + svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; + } else { + svga->hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; + svga->hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; + } break; case 0x70: case 0x71: case 0x72: case 0x73: WRITE8(addr, mach64->cur_horz_vert_off, val); - svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; - svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; + if (mach64->type == MACH64_GX) { + svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; + svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; + } else { + svga->hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; + svga->hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; + } break; case 0x80: @@ -3283,8 +3313,22 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) case 0xc3: if (mach64->type == MACH64_GX) ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); - else - ati68860_ramdac_out(addr & 3, val, svga->ramdac, svga); + else { + switch (addr & 3) { + case 0: + svga_out(0x3c8, val, svga); + break; + case 1: + svga_out(0x3c9, val, svga); + break; + case 2: + svga_out(0x3c6, val, svga); + break; + case 3: + svga_out(0x3c7, val, svga); + break; + } + } break; case 0xc4: case 0xc5: @@ -3294,7 +3338,8 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) mach64_log("Ext RAMDAC TYPE write=%x, bit set=%03x.\n", addr & 0x3ff, mach64->dac_cntl & 0x100); if ((addr & 3) >= 1) { svga_set_ramdac_type(svga, !!(mach64->dac_cntl & 0x100)); - ati68860_set_ramdac_type(svga->ramdac, !!(mach64->dac_cntl & 0x100)); + if (mach64->type == MACH64_GX) + ati68860_set_ramdac_type(svga->ramdac, !!(mach64->dac_cntl & 0x100)); } i2c_gpio_set(mach64->i2c, !(mach64->dac_cntl & 0x20000000) || (mach64->dac_cntl & 0x04000000), !(mach64->dac_cntl & 0x10000000) || (mach64->dac_cntl & 0x02000000)); break; @@ -3306,7 +3351,10 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) WRITE8(addr, mach64->gen_test_cntl, val); ati_eeprom_write(&mach64->eeprom, mach64->gen_test_cntl & 0x10, mach64->gen_test_cntl & 2, mach64->gen_test_cntl & 1); mach64->gen_test_cntl = (mach64->gen_test_cntl & ~8) | (ati_eeprom_read(&mach64->eeprom) ? 8 : 0); - svga->dac_hwcursor.ena = mach64->gen_test_cntl & 0x80; + if (mach64->type == MACH64_GX) + svga->dac_hwcursor.ena = !!(mach64->gen_test_cntl & 0x80); + else + svga->hwcursor.ena = !!(mach64->gen_test_cntl & 0x80); break; case 0xdc: @@ -3371,6 +3419,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *priv) { mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; uint8_t ret = 0xff; switch (port) { @@ -3384,6 +3433,12 @@ mach64_ext_inb(uint16_t port, void *priv) case 0x7eef: ret = mach64_ext_readb(0x400 | 0x00 | (port & 3), priv); break; + case 0x06ec: + case 0x06ed: + case 0x06ee: + case 0x06ef: + ret = mach64_ext_readb(0x400 | 0x04 | (port & 3), priv); + break; case 0x0aec: case 0x0aed: case 0x0aee: @@ -3519,8 +3574,22 @@ mach64_ext_inb(uint16_t port, void *priv) case 0x5eef: if (mach64->type == MACH64_GX) ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); - else - ret = ati68860_ramdac_in(port & 3, mach64->svga.ramdac, &mach64->svga); + else { + switch (port & 3) { + case 0: + ret = svga_in(0x3c8, svga); + break; + case 1: + ret = svga_in(0x3c9, svga); + break; + case 2: + ret = svga_in(0x3c6, svga); + break; + case 3: + ret = svga_in(0x3c7, svga); + break; + } + } break; case 0x62ec: @@ -3617,6 +3686,12 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x7eef: mach64_ext_writeb(0x400 | 0x00 | (port & 3), val, priv); break; + case 0x06ec: + case 0x06ed: + case 0x06ee: + case 0x06ef: + mach64_ext_writeb(0x400 | 0x04 | (port & 3), val, priv); + break; case 0x0aec: case 0x0aed: case 0x0aee: @@ -3745,8 +3820,22 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x5eef: if (mach64->type == MACH64_GX) ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); - else - ati68860_ramdac_out(port & 3, val, svga->ramdac, svga); + else { + switch (port & 3) { + case 0: + svga_out(0x3c8, val, svga); + break; + case 1: + svga_out(0x3c9, val, svga); + break; + case 2: + svga_out(0x3c6, val, svga); + break; + case 3: + svga_out(0x3c7, val, svga); + break; + } + } break; case 0x62ec: @@ -3905,6 +3994,63 @@ mach64_readl(uint32_t addr, void *priv) return ret; } +void +mach64_int_hwcursor_draw(svga_t *svga, int displine) +{ + const mach64_t *mach64 = (mach64_t *) svga->priv; + int comb; + int offset; + int x_pos; + int y_pos; + int shift = 0; + uint16_t dat; + uint32_t col0 = makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff); + uint32_t col1 = makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff); + uint32_t *p; + + offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + if (svga->packed_4bpp) + shift = 1; + + for (int x = 0; x < svga->hwcursor_latch.cur_xsize; x += (8 >> shift)) { + if (shift) { + dat = svga->vram[(svga->hwcursor_latch.addr) & svga->vram_mask] & 0x0f; + dat |= (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 4); + dat |= (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_mask] << 8); + dat |= (svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_mask] << 12); + } else { + dat = svga->vram[svga->hwcursor_latch.addr & svga->vram_mask]; + dat |= (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 8); + } + for (int xx = 0; xx < (8 >> shift); xx++) { + comb = (dat >> (xx << 1)) & 0x03; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + if (offset >= svga->hwcursor_latch.x) { + switch (comb) { + case 0: + p[x_pos] = col0; + break; + case 1: + p[x_pos] = col1; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + } + offset++; + } + svga->hwcursor_latch.addr += 2; + } +} + #define CLAMP(x) \ do { \ if ((x) & ~0xff) \ @@ -4550,15 +4696,22 @@ 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_mask = (mach64->vram_size << 20) - 1; - svga_init(info, svga, mach64, mach64->vram_size << 20, - mach64_recalctimings, - mach64_in, mach64_out, - NULL, - mach64_overlay_draw); - svga->dac_hwcursor.cur_ysize = 64; + if (mach64->type > MACH64_GX) + svga_init(info, svga, mach64, mach64->vram_size << 20, + mach64_recalctimings, + mach64_in, mach64_out, + mach64_int_hwcursor_draw, + mach64_overlay_draw); + else + svga_init(info, svga, mach64, mach64->vram_size << 20, + mach64_recalctimings, + mach64_in, mach64_out, + NULL, + 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->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); @@ -4576,9 +4729,6 @@ mach64_common_init(const device_t *info) mach64->pci_regs[0x32] = 0x0c; mach64->pci_regs[0x33] = 0x00; - svga->ramdac = device_add(&ati68860_ramdac_device); - svga->dac_hwcursor_draw = ati68860_hwcursor_draw; - svga->clock_gen = device_add(&ics2595_device); mach64->dst_cntl = 3; @@ -4598,6 +4748,13 @@ static void * mach64gx_init(const device_t *info) { mach64_t *mach64 = mach64_common_init(info); + svga_t *svga = &mach64->svga; + + svga->ramdac = device_add(&ati68860_ramdac_device); + svga->dac_hwcursor_draw = ati68860_hwcursor_draw; + + svga->dac_hwcursor.cur_ysize = 64; + svga->dac_hwcursor.cur_xsize = 64; if (info->flags & DEVICE_ISA16) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_isa); @@ -4606,12 +4763,11 @@ mach64gx_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); - mach64->type = MACH64_GX; mach64->pci = !!(info->flags & DEVICE_PCI); mach64->pci_id = 'X' | ('G' << 8); mach64->config_chip_id = 0x000000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ - mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI-68860, 256Kx16 DRAM*/ + mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI 68860, 256Kx16 DRAM*/ if (info->flags & DEVICE_PCI) { mach64->config_stat0 |= 7; /*PCI, 256Kx16 DRAM*/ ati_eeprom_load(&mach64->eeprom, "mach64_pci.nvr", 1); @@ -4635,9 +4791,13 @@ mach64vt2_init(const device_t *info) mach64_t *mach64 = mach64_common_init(info); svga_t *svga = &mach64->svga; + svga->dac_hwcursor_draw = NULL; + + svga->hwcursor.cur_ysize = 64; + svga->hwcursor.cur_xsize = 64; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); - mach64->type = MACH64_VT2; mach64->pci = 1; mach64->pci_id = 0x5654; mach64->config_chip_id = 0x40005654; @@ -4757,7 +4917,7 @@ const device_t mach64gx_isa_device = { .name = "ATI Mach64GX ISA", .internal_name = "mach64gx_isa", .flags = DEVICE_ISA16, - .local = 0, + .local = MACH64_GX, .init = mach64gx_init, .close = mach64_close, .reset = NULL, @@ -4771,7 +4931,7 @@ const device_t mach64gx_vlb_device = { .name = "ATI Mach64GX VLB", .internal_name = "mach64gx_vlb", .flags = DEVICE_VLB, - .local = 0, + .local = MACH64_GX, .init = mach64gx_init, .close = mach64_close, .reset = NULL, @@ -4785,7 +4945,7 @@ const device_t mach64gx_pci_device = { .name = "ATI Mach64GX PCI", .internal_name = "mach64gx_pci", .flags = DEVICE_PCI, - .local = 0, + .local = MACH64_GX, .init = mach64gx_init, .close = mach64_close, .reset = NULL, @@ -4799,7 +4959,7 @@ const device_t mach64vt2_device = { .name = "ATI Mach64VT2", .internal_name = "mach64vt2", .flags = DEVICE_PCI, - .local = 0, + .local = MACH64_VT2, .init = mach64vt2_init, .close = mach64_close, .reset = NULL, From 0ba20993dee59db81fab46ccedb30a33a45edb55 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Mon, 16 Jun 2025 21:14:31 +0200 Subject: [PATCH 1145/1190] Voodoo 3D change of the day (June 16th, 2025) When 3D is enabled on the behalf of the Voodoo, make sure the override is reflected in recalctimings as well so that it can use the old calculation way of the overscan. Fixes more blackness in some areas of some games (and possibly more). --- src/video/vid_voodoo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index e45f112ed..57ddbf64d 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -530,6 +530,7 @@ voodoo_writel(uint32_t addr, uint32_t val, void *priv) voodoo_recalc(voodoo); voodoo->front_offset = voodoo->params.front_offset; } + svga_recalctimings(voodoo->svga); } break; case SST_fbiInit1: From a0da500c381c85940c894e25f105f334e3a01987 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 20:45:11 +0100 Subject: [PATCH 1146/1190] Add MDA colour support. Kind of crappy implementatio --- src/include/86box/vid_mda.h | 2 +- src/video/vid_mda.c | 88 +++++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index e8ccd8602..d7d51fe44 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -61,7 +61,7 @@ typedef enum mda_crtc_registers_e typedef enum mda_mode_flags_e { MDA_MODE_HIGHRES = 1 << 0, // MUST be enabled for sane operation - MDA_MODE_BLACKANDWHITE = 1 << 1, // UNUSED in most cases. Not present on Hercules + MDA_MODE_BW = 1 << 1, // UNUSED in most cases. Not present on Hercules MDA_MODE_VIDEO_ENABLE = 1 << 3, MDA_MODE_BLINK = 1 << 5, } mda_mode_flags; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index f3d881769..7c4251285 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * MDA emulation. + * IBM Monochrome Display and Printer Adapter emulation. * * * @@ -18,6 +18,7 @@ * Copyright 2016-2025 Miran Grca. * Copyright 2025 starfrost / Connor Hyde */ +#include <stdbool.h> #include <stdio.h> #include <stdint.h> #include <string.h> @@ -35,6 +36,17 @@ #include <86box/vid_mda.h> #include <86box/plat_unused.h> +// Enumerates MDA monitor types +enum mda_monitor_type_e +{ + MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type. + MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor + MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor + MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor + MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support +} mda_monitor_type; + +// [attr][blink][fg] static int mda_attr_to_color_table[256][2][2]; static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; @@ -155,32 +167,66 @@ mda_poll(void *priv) scanline_old = mda->scanline; if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; - if (mda->dispon) { - if (mda->displine < mda->firstline) { + if (mda->dispon) + { + if (mda->displine < mda->firstline) + { mda->firstline = mda->displine; video_wait_for_buffer(); } mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { + + for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) + { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); - if (mda->scanline == 12 && ((attr & 7) == 1)) { + + int32_t color_bg = 0, color_fg = 0; + + // If we are using an RGBI monitor allow colour + //if (cga_palette == MDA_MONITOR_TYPE_RGBI) + //{ + if (!(mda->mode & MDA_MODE_BW)) + { + color_bg = (attr >> 4) & 0x0F; + color_fg = (attr & 0x0F); + } + + //} + + if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_bg; } else { for (c = 0; c < 8; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][(fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0]; + { + //bg=0, fg=1 + bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0; + + uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; + + if (!(mda->mode & MDA_MODE_BW)) + { + if (!is_fg) + font_char = 16 + color_bg; + else + font_char = 16 + color_fg; + } + + buffer32->line[mda->displine][(x * 9) + c] = font_char; + + } if ((chr & ~0x1f) == 0xc0) buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } mda->memaddr++; if (drawcursor) { for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1]; + buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; } } @@ -289,6 +335,7 @@ mda_poll(void *priv) void mda_init(mda_t *mda) { + for (uint16_t c = 0; c < 256; c++) { mda_attr_to_color_table[c][0][0] = mda_attr_to_color_table[c][1][0] = mda_attr_to_color_table[c][1][1] = 16; if (c & 8) @@ -308,6 +355,7 @@ mda_init(mda_t *mda) mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16; + overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; @@ -387,6 +435,7 @@ mda_speed_changed(void *priv) mda_recalctimings(mda); } + static const device_config_t mda_config[] = { // clang-format off { @@ -397,12 +446,14 @@ static const device_config_t mda_config[] = { .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "Default", .value = 0 }, - { .description = "Green", .value = 1 }, - { .description = "Amber", .value = 2 }, - { .description = "Gray", .value = 3 }, - { .description = "" } + .selection = + { + { .description = "Default", .value = MDA_MONITOR_TYPE_DEFAULT }, + { .description = "Green", .value = MDA_MONITOR_TYPE_GREEN }, + { .description = "Amber", .value = MDA_MONITOR_TYPE_AMBER }, + { .description = "Gray", .value = MDA_MONITOR_TYPE_GRAY }, + { .description = "Generic RGBI color monitor", .value = MDA_MONITOR_TYPE_RGBI }, + { .description = "" } }, .bios = { { 0 } } }, @@ -414,12 +465,13 @@ static const device_config_t mda_config[] = { .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "US (CP 437)", .value = 0 }, + .selection = + { + { .description = "US (CP 437)", .value = 0 }, { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, - { .description = "" } + { .description = "" } }, .bios = { { 0 } } }, From a64fafcf614f0625706d3dc594a0fa7d778ff9c2 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 20:48:38 +0100 Subject: [PATCH 1147/1190] Only enable colour support if we are using an RGBI monitor --- src/include/86box/vid_mda.h | 49 +++++++++++++++++++------------------ src/video/vid_mda.c | 9 ++++--- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index d7d51fe44..105159b0f 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -69,34 +69,35 @@ typedef enum mda_mode_flags_e typedef struct mda_t { mem_mapping_t mapping; - uint8_t crtc[MDA_CRTC_NUM_REGISTERS]; - int crtcreg; + uint8_t crtc[MDA_CRTC_NUM_REGISTERS]; + int32_t crtcreg; - uint8_t mode; - uint8_t status; + uint8_t mode; + uint8_t status; - uint64_t dispontime; - uint64_t dispofftime; - pc_timer_t timer; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; - int firstline; - int lastline; + int32_t firstline; + int32_t lastline; - int fontbase; - int linepos; - int displine; - int vc; - int scanline; - uint16_t memaddr; - uint16_t memaddr_backup; - int cursorvisible; - int cursoron; - int dispon; - int blink; - int vsynctime; - int vadj; - int monitor_index; - int prev_monitor_index; + int32_t fontbase; + int32_t linepos; + int32_t displine; + int32_t vc; + int32_t scanline; + uint16_t memaddr; + uint16_t memaddr_backup; + int32_t cursorvisible; + int32_t cursoron; + int32_t dispon; + int32_t blink; + int32_t vsynctime; + int32_t vadj; + int32_t monitor_index; + int32_t prev_monitor_index; + int32_t monitor_type; // Used for MDA Colour support (REV0 u64) uint8_t *vram; } mda_t; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 7c4251285..a0bd61010 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -186,15 +186,15 @@ mda_poll(void *priv) int32_t color_bg = 0, color_fg = 0; // If we are using an RGBI monitor allow colour - //if (cga_palette == MDA_MONITOR_TYPE_RGBI) - //{ + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI) + { if (!(mda->mode & MDA_MODE_BW)) { color_bg = (attr >> 4) & 0x0F; color_fg = (attr & 0x0F); } - //} + } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) @@ -360,7 +360,8 @@ mda_init(mda_t *mda) overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; - cga_palette = device_get_config_int("rgb_type") << 1; + mda->monitor_type = device_get_config_int("rgb_type"); + cga_palette = mda->monitor_type << 1; if (cga_palette > 6) { cga_palette = 0; } From 23414bafcbedad45efe3815551b90c77dad83693 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 20:53:27 +0100 Subject: [PATCH 1148/1190] Fix non-RGBI monitors --- src/video/vid_mda.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index a0bd61010..d900df69e 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -198,7 +198,7 @@ mda_poll(void *priv) if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_bg; + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_fg; } else { for (c = 0; c < 8; c++) { @@ -207,7 +207,8 @@ mda_poll(void *priv) uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; - if (!(mda->mode & MDA_MODE_BW)) + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) font_char = 16 + color_bg; From 0e7be429ca859b03c9418ebe21d8d0612b2203dc Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 21:00:36 +0100 Subject: [PATCH 1149/1190] more accuracy --- src/video/vid_mda.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index d900df69e..35026318b 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -217,10 +217,16 @@ mda_poll(void *priv) } buffer32->line[mda->displine][(x * 9) + c] = font_char; - } if ((chr & ~0x1f) == 0xc0) - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; + { + bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; + + if (is_fg) + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; + else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_bg; + } else buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } From d63d1342de39e03ea122f65077ef04bb32fac96a Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 21:12:22 +0100 Subject: [PATCH 1150/1190] Don't set colour in blink mode --- src/video/vid_mda.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 35026318b..d8f349ae9 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -192,8 +192,14 @@ mda_poll(void *priv) { color_bg = (attr >> 4) & 0x0F; color_fg = (attr & 0x0F); - } - + + // turn off bright bg colours in blink mode + if ((mda->mode & MDA_MODE_BLINK) + && (color_bg & 0x8)) + { + color_bg & ~(0x8); + } + } } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline @@ -222,10 +228,10 @@ mda_poll(void *priv) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; - if (is_fg) - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; - else + if (!is_fg) buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_bg; + else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; } else buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; From 89b8652792982f0bbddc44c9cc6b87148dfb9479 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 21:52:18 +0100 Subject: [PATCH 1151/1190] Fix the underlines --- src/include/86box/video.h | 4 ++++ src/video/vid_mda.c | 34 +++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 6ab375370..db7d5bfa0 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -187,6 +187,10 @@ extern bitmap_t *buffer32; #define efscrnsz_y (monitors[monitor_index_global].mon_efscrnsz_y) #define unscaled_size_x (monitors[monitor_index_global].mon_unscaled_size_x) #define unscaled_size_y (monitors[monitor_index_global].mon_unscaled_size_y) + +#define CGAPAL_CGA_START 16 // Where the 16-color cga text/composite starts + + extern PALETTE cgapal; extern PALETTE cgapal_mono[6]; #if 0 diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index d8f349ae9..fe382101f 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -196,16 +196,22 @@ mda_poll(void *priv) // turn off bright bg colours in blink mode if ((mda->mode & MDA_MODE_BLINK) && (color_bg & 0x8)) - { color_bg & ~(0x8); - } } } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_fg; - } else { + { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + buffer32->line[mda->displine][(x * 9) + c] = CGAPAL_CGA_START + color_fg; + } + else + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; + } + } else { // main text for (c = 0; c < 8; c++) { //bg=0, fg=1 @@ -217,13 +223,14 @@ mda_poll(void *priv) && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) - font_char = 16 + color_bg; + font_char = CGAPAL_CGA_START + color_bg; else - font_char = 16 + color_fg; + font_char = CGAPAL_CGA_START + color_fg; } buffer32->line[mda->displine][(x * 9) + c] = font_char; } + if ((chr & ~0x1f) == 0xc0) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; @@ -237,6 +244,7 @@ mda_poll(void *priv) buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } mda->memaddr++; + if (drawcursor) { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; @@ -357,13 +365,13 @@ mda_init(mda_t *mda) mda_attr_to_color_table[c][0][1] = 7 + 16; } mda_attr_to_color_table[0x70][0][1] = 16; - mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = 16 + 15; + mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15; mda_attr_to_color_table[0xF0][0][1] = 16; - mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = 16 + 15; - mda_attr_to_color_table[0x78][0][1] = 16 + 7; - mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = 16 + 15; - mda_attr_to_color_table[0xF8][0][1] = 16 + 7; - mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = 16 + 15; + mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = CGAPAL_CGA_START + 15; + mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = CGAPAL_CGA_START + 15; + mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = CGAPAL_CGA_START + 15; mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16; mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; @@ -429,7 +437,7 @@ mda_standalone_init(UNUSED(const device_t *info)) void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) { - mda_attr_to_color_table[chr][blink][fg] = 16 + cga_ink; + mda_attr_to_color_table[chr][blink][fg] = CGAPAL_CGA_START + cga_ink; } void From 00ceaa3a39be0b9a9ae002a4ba645e144bf88a59 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 21:56:01 +0100 Subject: [PATCH 1152/1190] Slightly better syntatical sugar --- src/video/vid_mda.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index fe382101f..2f02be80a 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -183,24 +183,24 @@ mda_poll(void *priv) drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); + // Colours that will be used int32_t color_bg = 0, color_fg = 0; // If we are using an RGBI monitor allow colour - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI) + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { - if (!(mda->mode & MDA_MODE_BW)) - { - color_bg = (attr >> 4) & 0x0F; - color_fg = (attr & 0x0F); + color_bg = (attr >> 4) & 0x0F; + color_fg = (attr & 0x0F); - // turn off bright bg colours in blink mode - if ((mda->mode & MDA_MODE_BLINK) - && (color_bg & 0x8)) - color_bg & ~(0x8); - } + // turn off bright bg colours in blink mode + if ((mda->mode & MDA_MODE_BLINK) + && (color_bg & 0x8)) + color_bg & ~(0x8); } - if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline + if (mda->scanline == 12 && ((attr & 7) == 1)) + { // underline for (c = 0; c < 9; c++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI @@ -243,9 +243,11 @@ mda_poll(void *priv) else buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } + mda->memaddr++; - if (drawcursor) { + if (drawcursor) + { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; } From 091c0aa32e97ad0edbcb595663333382fc499574 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 22:08:07 +0100 Subject: [PATCH 1153/1190] c -> attr --- src/video/vid_mda.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 2f02be80a..c4fb4be74 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -359,12 +359,13 @@ void mda_init(mda_t *mda) { - for (uint16_t c = 0; c < 256; c++) { - mda_attr_to_color_table[c][0][0] = mda_attr_to_color_table[c][1][0] = mda_attr_to_color_table[c][1][1] = 16; - if (c & 8) - mda_attr_to_color_table[c][0][1] = 15 + 16; + for (uint16_t attr = 0; attr < 256; attr++) + { + mda_attr_to_color_table[attr][0][0] = mda_attr_to_color_table[attr][1][0] = mda_attr_to_color_table[attr][1][1] = 16; + if (attr & 8) + mda_attr_to_color_table[attr][0][1] = 15 + 16; else - mda_attr_to_color_table[c][0][1] = 7 + 16; + mda_attr_to_color_table[attr][0][1] = 7 + 16; } mda_attr_to_color_table[0x70][0][1] = 16; mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15; From 7b044e808463498f58d18059d72a3484ab5b6ad8 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:21:40 +0100 Subject: [PATCH 1154/1190] much cleaned up code with fixed 9th column support, gray/black background special treatment --- src/video/vid_mda.c | 68 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index c4fb4be74..ed99a169b 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -152,7 +152,7 @@ mda_poll(void *priv) uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; - int c; + int column; int oldvc; uint8_t chr; uint8_t attr; @@ -197,25 +197,38 @@ mda_poll(void *priv) if ((mda->mode & MDA_MODE_BLINK) && (color_bg & 0x8)) color_bg & ~(0x8); + + // black-on-non black or white colours forced to white + // grey-on-colours forced to bright white + + bool special_treatment = (color_bg != 0 && color_bg != 7); + + if (color_fg == 7 + && special_treatment) + color_fg = 15; + + if (color_fg == 0 + && special_treatment) + color_fg = 7; } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline - for (c = 0; c < 9; c++) + for (column = 0; column < 9; column++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI && !(mda->mode & MDA_MODE_BW)) { - buffer32->line[mda->displine][(x * 9) + c] = CGAPAL_CGA_START + color_fg; + buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; } else - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; + buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } - } else { // main text - for (c = 0; c < 8; c++) + } else { // character + for (column = 0; column < 8; column++) { //bg=0, fg=1 - bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0; + bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0; uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; @@ -228,28 +241,53 @@ mda_poll(void *priv) font_char = CGAPAL_CGA_START + color_fg; } - buffer32->line[mda->displine][(x * 9) + c] = font_char; + buffer32->line[mda->displine][(x * 9) + column] = font_char; } if ((chr & ~0x1f) == 0xc0) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; + uint32_t final_result = mda_attr_to_color_table[attr][blink][is_fg]; + + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + if (!is_fg) + final_result = CGAPAL_CGA_START + color_bg; + else + final_result = CGAPAL_CGA_START + color_fg; + } + + buffer32->line[mda->displine][(x * 9) + 8] = final_result; - if (!is_fg) - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_bg; - else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; } else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; + { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg; + + } + else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; + } } mda->memaddr++; if (drawcursor) { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; + for (column = 0; column < 9; column++) + { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg; + } + else + buffer32->line[mda->displine][(x * 9) + column] ^= mda_attr_to_color_table[attr][0][1]; + } } } From a925076a7a1a0724073fdc7f94e3580393d95206 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:23:47 +0100 Subject: [PATCH 1155/1190] implement gray being black on fg and bg being gray --- src/video/vid_mda.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index ed99a169b..6c4070d8c 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -210,6 +210,11 @@ mda_poll(void *priv) if (color_fg == 0 && special_treatment) color_fg = 7; + + // gray is black + if (color_fg == 7 + && color_bg == 7) + color_fg = 0; } if (mda->scanline == 12 && ((attr & 7) == 1)) From a530f9365b69559eee40f3ef2f541bd4283abbcc Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:25:27 +0100 Subject: [PATCH 1156/1190] missed one --- src/video/vid_mda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 6c4070d8c..bfdc50352 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -213,7 +213,7 @@ mda_poll(void *priv) // gray is black if (color_fg == 7 - && color_bg == 7) + && (color_bg == 7 || color_bg == 0)) color_fg = 0; } From 0109f0b81109f19fc451772329f3d63f3bbabb8c Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:33:43 +0100 Subject: [PATCH 1157/1190] make gray actually gray --- src/video/vid_mda.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index bfdc50352..65e57a8e0 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -203,17 +203,17 @@ mda_poll(void *priv) bool special_treatment = (color_bg != 0 && color_bg != 7); - if (color_fg == 7 + if (color_fg == 8 && special_treatment) color_fg = 15; if (color_fg == 0 && special_treatment) - color_fg = 7; + color_fg = 8; // gray is black - if (color_fg == 7 - && (color_bg == 7 || color_bg == 0)) + if (color_fg == 8 + && (color_bg == 8 || color_bg == 0)) color_fg = 0; } @@ -225,7 +225,7 @@ mda_poll(void *priv) && !(mda->mode & MDA_MODE_BW)) { buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; - } + 1 } else buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } From 3c29c00a94f9c567e3834bb602b1320c8b8fe6ff Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:38:05 +0100 Subject: [PATCH 1158/1190] mda_poll: make drawcursor a bool; localise the scope of various variables; de-same-line-braceify for readability --- src/video/vid_mda.c | 58 ++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 65e57a8e0..6e5298201 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -150,23 +150,24 @@ mda_poll(void *priv) { mda_t *mda = (mda_t *) priv; uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; - int drawcursor; - int x; - int column; - int oldvc; + bool drawcursor; + int32_t oldvc; uint8_t chr; uint8_t attr; - int scanline_old; - int blink; + int32_t scanline_old; + int32_t blink; VIDEO_MONITOR_PROLOGUE() - if (!mda->linepos) { + + if (!mda->linepos) + { timer_advance_u64(&mda->timer, mda->dispofftime); mda->status |= 1; mda->linepos = 1; scanline_old = mda->scanline; if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; + if (mda->dispon) { if (mda->displine < mda->firstline) @@ -176,7 +177,7 @@ mda_poll(void *priv) } mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) + for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; @@ -217,20 +218,23 @@ mda_poll(void *priv) color_fg = 0; } - if (mda->scanline == 12 && ((attr & 7) == 1)) + if (mda->scanline == 12 + && ((attr & 7) == 1)) { // underline - for (column = 0; column < 9; column++) + for (uint32_t column = 0; column < 9; column++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI && !(mda->mode & MDA_MODE_BW)) { buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; - 1 } + } else buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } - } else { // character - for (column = 0; column < 8; column++) + } + else + { // character + for (uint32_t column = 0; column < 8; column++) { //bg=0, fg=1 bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0; @@ -249,6 +253,7 @@ mda_poll(void *priv) buffer32->line[mda->displine][(x * 9) + column] = font_char; } + // these characters (C0-DF) have their background extended to their 9th column if ((chr & ~0x1f) == 0xc0) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; @@ -283,7 +288,7 @@ mda_poll(void *priv) if (drawcursor) { - for (column = 0; column < 9; column++) + for (uint32_t column = 0; column < 9; column++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI && !(mda->mode & MDA_MODE_BW)) @@ -310,30 +315,39 @@ mda_poll(void *priv) if (mda->dispon) mda->status &= ~1; mda->linepos = 0; - if (mda->vsynctime) { + + if (mda->vsynctime) + { mda->vsynctime--; - if (!mda->vsynctime) { + if (!mda->vsynctime) + { mda->status &= ~8; } } if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) { + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) + { mda->cursorvisible = 0; } - if (mda->vadj) { + + if (mda->vadj) + { mda->scanline++; mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; mda->vadj--; - if (!mda->vadj) { + if (!mda->vadj) + { mda->dispon = 1; mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; mda->scanline = 0; } - } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] + } + else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { + && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) + { mda->memaddr_backup = mda->memaddr; mda->scanline = 0; oldvc = mda->vc; @@ -359,7 +373,7 @@ mda_poll(void *priv) mda->displine = 0; mda->vsynctime = 16; if (mda->crtc[MDA_CRTC_VSYNC]) { - x = mda->crtc[MDA_CRTC_HDISP] * 9; + uint32_t x = mda->crtc[MDA_CRTC_HDISP] * 9; mda->lastline++; if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { xsize = x; From b732ece04d8bea1ffcaa2d238d80c7b6f2757a13 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:41:01 +0100 Subject: [PATCH 1159/1190] Conform to the style guide --- src/video/vid_mda.c | 235 ++++++++++++++++++-------------------------- 1 file changed, 98 insertions(+), 137 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 6e5298201..36e486b2d 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -37,13 +37,12 @@ #include <86box/plat_unused.h> // Enumerates MDA monitor types -enum mda_monitor_type_e -{ - MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type. - MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor - MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor - MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor - MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support +enum mda_monitor_type_e { + MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type. + MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor + MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor + MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor + MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support } mda_monitor_type; // [attr][blink][fg] @@ -58,12 +57,11 @@ mda_out(uint16_t addr, uint8_t val, void *priv) { mda_t *mda = (mda_t *) priv; - if (addr < MDA_REGISTER_START - || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case + if (addr < MDA_REGISTER_START + || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case return; - switch (addr) - { + switch (addr) { case MDA_REGISTER_MODE_CONTROL: mda->mode = val; return; @@ -73,20 +71,17 @@ mda_out(uint16_t addr, uint8_t val, void *priv) // addr & 1 == 1 = MDA_REGISTER_CRTC_DATA // otherwise MDA_REGISTER_CRTC_INDEX - if (addr & 1) - { + if (addr & 1) { mda->crtc[mda->crtcreg] = val; - if (mda->crtc[MDA_CRTC_CURSOR_START] == 6 + if (mda->crtc[MDA_CRTC_CURSOR_START] == 6 && mda->crtc[MDA_CRTC_CURSOR_END] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ { mda->crtc[MDA_CRTC_CURSOR_START] = 0xb; - mda->crtc[MDA_CRTC_CURSOR_END] = 0xc; + mda->crtc[MDA_CRTC_CURSOR_END] = 0xc; } mda_recalctimings(mda); - } - else + } else mda->crtcreg = val & 31; - } uint8_t @@ -94,19 +89,18 @@ mda_in(uint16_t addr, void *priv) { const mda_t *mda = (mda_t *) priv; - switch (addr) - { + switch (addr) { case MDA_REGISTER_CRT_STATUS: return mda->status | 0xF0; default: - if (addr < MDA_REGISTER_START - || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case + if (addr < MDA_REGISTER_START + || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case return 0xFF; // MDA_REGISTER_CRTC_DATA if (addr & 1) return mda->crtc[mda->crtcreg]; - else + else return mda->crtcreg; break; @@ -148,8 +142,8 @@ mda_recalctimings(mda_t *mda) void mda_poll(void *priv) { - mda_t *mda = (mda_t *) priv; - uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + mda_t *mda = (mda_t *) priv; + uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; bool drawcursor; int32_t oldvc; uint8_t chr; @@ -159,44 +153,39 @@ mda_poll(void *priv) VIDEO_MONITOR_PROLOGUE() - if (!mda->linepos) - { + if (!mda->linepos) { timer_advance_u64(&mda->timer, mda->dispofftime); mda->status |= 1; mda->linepos = 1; - scanline_old = mda->scanline; + scanline_old = mda->scanline; if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; - if (mda->dispon) - { - if (mda->displine < mda->firstline) - { + if (mda->dispon) { + if (mda->displine < mda->firstline) { mda->firstline = mda->displine; video_wait_for_buffer(); } mda->lastline = mda->displine; - for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) - { + for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); // Colours that will be used - int32_t color_bg = 0, color_fg = 0; - + int32_t color_bg = 0, color_fg = 0; + // If we are using an RGBI monitor allow colour if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + && !(mda->mode & MDA_MODE_BW)) { color_bg = (attr >> 4) & 0x0F; - color_fg = (attr & 0x0F); + color_fg = (attr & 0x0F); // turn off bright bg colours in blink mode if ((mda->mode & MDA_MODE_BLINK) - && (color_bg & 0x8)) + && (color_bg & 0x8)) color_bg & ~(0x8); // black-on-non black or white colours forced to white @@ -204,98 +193,80 @@ mda_poll(void *priv) bool special_treatment = (color_bg != 0 && color_bg != 7); - if (color_fg == 8 - && special_treatment) + if (color_fg == 8 + && special_treatment) color_fg = 15; - + if (color_fg == 0 - && special_treatment) + && special_treatment) color_fg = 8; - // gray is black + // gray is black if (color_fg == 8 - && (color_bg == 8 || color_bg == 0)) + && (color_bg == 8 || color_bg == 0)) color_fg = 0; } - if (mda->scanline == 12 - && ((attr & 7) == 1)) - { // underline - for (uint32_t column = 0; column < 9; column++) - { - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + if (mda->scanline == 12 + && ((attr & 7) == 1)) { // underline + for (uint32_t column = 0; column < 9; column++) { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; - } - else + } else buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } - } - else - { // character - for (uint32_t column = 0; column < 8; column++) - { - //bg=0, fg=1 + } else { // character + for (uint32_t column = 0; column < 8; column++) { + // bg=0, fg=1 bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0; uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) - font_char = CGAPAL_CGA_START + color_bg; - else - font_char = CGAPAL_CGA_START + color_fg; + font_char = CGAPAL_CGA_START + color_bg; + else + font_char = CGAPAL_CGA_START + color_fg; } - + buffer32->line[mda->displine][(x * 9) + column] = font_char; } - + // these characters (C0-DF) have their background extended to their 9th column - if ((chr & ~0x1f) == 0xc0) - { - bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; + if ((chr & ~0x1f) == 0xc0) { + bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; uint32_t final_result = mda_attr_to_color_table[attr][blink][is_fg]; - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) - final_result = CGAPAL_CGA_START + color_bg; + final_result = CGAPAL_CGA_START + color_bg; else - final_result = CGAPAL_CGA_START + color_fg; + final_result = CGAPAL_CGA_START + color_fg; } - buffer32->line[mda->displine][(x * 9) + 8] = final_result; + buffer32->line[mda->displine][(x * 9) + 8] = final_result; - } - else - { - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { - buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg; + } else { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { + buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg; - } - else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; + } else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; } } - + mda->memaddr++; - if (drawcursor) - { - for (uint32_t column = 0; column < 9; column++) - { - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { - buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg; - } - else + if (drawcursor) { + for (uint32_t column = 0; column < 9; column++) { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { + buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg; + } else buffer32->line[mda->displine][(x * 9) + column] ^= mda_attr_to_color_table[attr][0][1]; } } @@ -316,41 +287,34 @@ mda_poll(void *priv) mda->status &= ~1; mda->linepos = 0; - if (mda->vsynctime) - { + if (mda->vsynctime) { mda->vsynctime--; - if (!mda->vsynctime) - { + if (!mda->vsynctime) { mda->status &= ~8; } } - if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) - || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) - { - mda->cursorvisible = 0; + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) { + mda->cursorvisible = 0; } - if (mda->vadj) - { + if (mda->vadj) { mda->scanline++; mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; mda->vadj--; - if (!mda->vadj) - { - mda->dispon = 1; + if (!mda->vadj) { + mda->dispon = 1; mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - mda->scanline = 0; + mda->scanline = 0; } - } - else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] - || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) - { + } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { mda->memaddr_backup = mda->memaddr; - mda->scanline = 0; - oldvc = mda->vc; + mda->scanline = 0; + oldvc = mda->vc; mda->vc++; mda->vc &= 127; if (mda->vc == mda->crtc[MDA_CRTC_VDISP]) @@ -403,9 +367,9 @@ mda_poll(void *priv) mda->memaddr = mda->memaddr_backup; } - if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) - || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) { mda->cursorvisible = 1; } } @@ -415,9 +379,8 @@ mda_poll(void *priv) void mda_init(mda_t *mda) { - - for (uint16_t attr = 0; attr < 256; attr++) - { + + for (uint16_t attr = 0; attr < 256; attr++) { mda_attr_to_color_table[attr][0][0] = mda_attr_to_color_table[attr][1][0] = mda_attr_to_color_table[attr][1][1] = 16; if (attr & 8) mda_attr_to_color_table[attr][0][1] = 15 + 16; @@ -426,23 +389,22 @@ mda_init(mda_t *mda) } mda_attr_to_color_table[0x70][0][1] = 16; mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15; - mda_attr_to_color_table[0xF0][0][1] = 16; + mda_attr_to_color_table[0xF0][0][1] = 16; mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = CGAPAL_CGA_START + 15; - mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7; mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = CGAPAL_CGA_START + 15; - mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7; mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = CGAPAL_CGA_START + 15; mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16; mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16; - overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; mda->monitor_type = device_get_config_int("rgb_type"); - cga_palette = mda->monitor_type << 1; + cga_palette = mda->monitor_type << 1; if (cga_palette > 6) { cga_palette = 0; } @@ -460,7 +422,7 @@ mda_standalone_init(UNUSED(const device_t *info)) mda->vram = malloc(0x1000); - switch(device_get_config_int("font")) { + switch (device_get_config_int("font")) { case 0: loadfont(FONT_IBM_MDA_437_PATH, 0); break; @@ -517,9 +479,8 @@ mda_speed_changed(void *priv) mda_recalctimings(mda); } - static const device_config_t mda_config[] = { - // clang-format off + // clang-format off { .name = "rgb_type", .description = "Display type", @@ -558,7 +519,7 @@ static const device_config_t mda_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t mda_device = { From 07b418d470440bc96d62197c5059d7c484998719 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Mon, 16 Jun 2025 23:47:15 +0100 Subject: [PATCH 1160/1190] add the mda_colors enum and use it instead of magic numbers in the colour fixup code --- src/include/86box/vid_mda.h | 20 ++++++++++++++++++++ src/video/vid_mda.c | 12 ++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index 105159b0f..13aa70594 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -66,6 +66,26 @@ typedef enum mda_mode_flags_e MDA_MODE_BLINK = 1 << 5, } mda_mode_flags; +typedef enum mda_colors_e +{ + MDA_COLOR_BLACK = 0, + MDA_COLOR_BLUE = 1, + MDA_COLOR_GREEN = 2, + MDA_COLOR_CYAN = 3, + MDA_COLOR_RED = 4, + MDA_COLOR_MAGENTA = 5, + MDA_COLOR_BROWN = 6, + MDA_COLOR_WHITE = 7, + MDA_COLOR_GREY = 8, + MDA_COLOR_BRIGHT_BLUE = 9, + MDA_COLOR_BRIGHT_GREEN = 10, + MDA_COLOR_BRIGHT_CYAN = 11, + MDA_COLOR_BRIGHT_RED = 12, + MDA_COLOR_BRIGHT_MAGENTA = 13, + MDA_COLOR_BRIGHT_YELLOW = 14, + MDA_COLOR_BRIGHT_WHITE = 15, +} mda_colors; + typedef struct mda_t { mem_mapping_t mapping; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 36e486b2d..b0cbd203e 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -193,18 +193,18 @@ mda_poll(void *priv) bool special_treatment = (color_bg != 0 && color_bg != 7); - if (color_fg == 8 + if (color_fg == MDA_COLOR_GREY && special_treatment) - color_fg = 15; + color_fg = MDA_COLOR_BRIGHT_WHITE; if (color_fg == 0 && special_treatment) - color_fg = 8; + color_fg = MDA_COLOR_GREY; // gray is black - if (color_fg == 8 - && (color_bg == 8 || color_bg == 0)) - color_fg = 0; + if (color_fg == MDA_COLOR_GREY + && (color_bg == MDA_COLOR_GREY || color_bg == MDA_COLOR_BLACK)) + color_fg = MDA_COLOR_BLACK; } if (mda->scanline == 12 From c826294a965768725e54b5c5aacdfebb8abf1826 Mon Sep 17 00:00:00 2001 From: starfrost013 <mario64crashed@gmail.com> Date: Tue, 17 Jun 2025 01:07:26 +0100 Subject: [PATCH 1161/1190] Move components of video cards (external ramdacs and clock generators that could be paired with many cards) to their own folders. Reorganise video cmakelists --- src/video/CMakeLists.txt | 110 +++++++++++++----- .../vid_clockgen_av9194.c} | 0 .../vid_clockgen_icd2061.c} | 0 .../vid_clockgen_ics2494.c} | 0 .../vid_clockgen_ics2595.c} | 0 .../vid_ramdac_ati68860.c} | 0 .../vid_ramdac_ati68875.c} | 0 .../vid_ramdac_att20c49x.c} | 0 .../vid_ramdac_att2xc498.c} | 0 .../vid_ramdac_bt481.c} | 0 .../vid_ramdac_bt48x.c} | 0 .../vid_ramdac_ibm_rgb528.c} | 0 .../vid_ramdac_sc1148x.c} | 0 .../vid_ramdac_sc1502x.c} | 0 .../vid_ramdac_sdac.c} | 0 .../vid_ramdac_stg1702.c} | 0 .../vid_ramdac_tkd8001.c} | 0 .../vid_ramdac_tvp3026.c} | 0 18 files changed, 80 insertions(+), 30 deletions(-) rename src/video/{vid_av9194.c => clockgen/vid_clockgen_av9194.c} (100%) rename src/video/{vid_icd2061.c => clockgen/vid_clockgen_icd2061.c} (100%) rename src/video/{vid_ics2494.c => clockgen/vid_clockgen_ics2494.c} (100%) rename src/video/{vid_ics2595.c => clockgen/vid_clockgen_ics2595.c} (100%) rename src/video/{vid_ati68860_ramdac.c => ramdac/vid_ramdac_ati68860.c} (100%) rename src/video/{vid_ati68875_ramdac.c => ramdac/vid_ramdac_ati68875.c} (100%) rename src/video/{vid_att20c49x_ramdac.c => ramdac/vid_ramdac_att20c49x.c} (100%) rename src/video/{vid_att2xc498_ramdac.c => ramdac/vid_ramdac_att2xc498.c} (100%) rename src/video/{vid_bt481_ramdac.c => ramdac/vid_ramdac_bt481.c} (100%) rename src/video/{vid_bt48x_ramdac.c => ramdac/vid_ramdac_bt48x.c} (100%) rename src/video/{vid_ibm_rgb528_ramdac.c => ramdac/vid_ramdac_ibm_rgb528.c} (100%) rename src/video/{vid_sc1148x_ramdac.c => ramdac/vid_ramdac_sc1148x.c} (100%) rename src/video/{vid_sc1502x_ramdac.c => ramdac/vid_ramdac_sc1502x.c} (100%) rename src/video/{vid_sdac_ramdac.c => ramdac/vid_ramdac_sdac.c} (100%) rename src/video/{vid_stg_ramdac.c => ramdac/vid_ramdac_stg1702.c} (100%) rename src/video/{vid_tkd8001_ramdac.c => ramdac/vid_ramdac_tkd8001.c} (100%) rename src/video/{vid_tvp3026_ramdac.c => ramdac/vid_ramdac_tvp3026.c} (100%) diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 09c49dabe..4cac8b76d 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -15,10 +15,39 @@ # add_library(vid OBJECT + + # Video Core agpgart.c video.c vid_table.c - # CGA + + # RAMDAC (Should this be its own library?) + ramdac/vid_ramdac_ati68860.c + ramdac/vid_ramdac_ati68875.c + ramdac/vid_ramdac_att20c49x.c + ramdac/vid_ramdac_att2xc498.c + ramdac/vid_ramdac_bt48x.c + ramdac/vid_ramdac_bt481.c + ramdac/vid_ramdac_ibm_rgb528.c + ramdac/vid_ramdac_sc1148x.c + ramdac/vid_ramdac_sc1502x.c + ramdac/vid_ramdac_sdac.c + ramdac/vid_ramdac_stg1702.c + ramdac/vid_ramdac_tkd8001.c + ramdac/vid_ramdac_tvp3026.c + + # Clock generator chips + clockgen/vid_clockgen_av9194.c + clockgen/vid_clockgen_icd2061.c + clockgen/vid_clockgen_ics2494.c + clockgen/vid_clockgen_ics2595.c + + # DDC / monitor identification stuff + vid_ddc.c + + # CARDS start here + + # CGA / Super CGA vid_cga.c vid_cga_comp.c vid_cga_compaq.c @@ -32,64 +61,84 @@ add_library(vid OBJECT # PCJr/Tandy vid_pcjr.c vid_tandy.c - vid_mda.c + + # Hercules vid_hercules.c vid_hercules_plus.c vid_hercules_incolor.c + + # Other early CGA-era cards vid_genius.c + vid_sigma.c + + # PGC / IM1024 / WY700 high-resolution vid_pgc.c vid_im1024.c - vid_sigma.c vid_wy700.c + + # EGA vid_ega.c vid_ega_render.c - vid_svga.c - vid_8514a.c - vid_svga_render.c - vid_ddc.c + vid_jega.c + + # (Real IBM) VGA vid_vga.c + + # Super VGA core + vid_svga.c + vid_svga_render.c + + # 8514/A, XGA and derivatives + vid_8514a.c + vid_xga.c + vid_ps55da2.c + + # ATI Technologies vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach8.c vid_ati_mach64.c - vid_ati68875_ramdac.c - vid_ati68860_ramdac.c - vid_bt481_ramdac.c - vid_bt48x_ramdac.c + + # Chips & Technologies vid_chips_69000.c - vid_av9194.c - vid_icd2061.c - vid_ics2494.c - vid_ics2595.c + + # Cirrus Logic vid_cl54xx.c + + # Tseng Labs vid_et3000.c vid_et4000.c - vid_sc1148x_ramdac.c - vid_sc1502x_ramdac.c vid_et4000w32.c - vid_stg_ramdac.c + + # Headland vid_ht216.c vid_oak_oti.c + + # Paradise vid_paradise.c vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c - vid_tvga.c vid_tgui9440.c - vid_tkd8001_ramdac.c - vid_att20c49x_ramdac.c - vid_s3.c vid_s3_virge.c - vid_ibm_rgb528_ramdac.c - vid_sdac_ramdac.c + + # Trident + vid_tvga.c + vid_tgui9440.c + + # S3 Graphics + vid_s3.c + vid_s3_virge.c + + # Matrox vid_mga.c - vid_tvp3026_ramdac.c - vid_att2xc498_ramdac.c - vid_xga.c - vid_bochs_vbe.c - vid_ps55da2.c - vid_jega.c + + # NVidia (pending) nv/nv_rivatimer.c + + # Generic + vid_bochs_vbe.c + ) if(G100) @@ -100,6 +149,7 @@ if(XL24) target_compile_definitions(vid PRIVATE USE_XL24) endif() +# 3Dfx Voodoo add_library(voodoo OBJECT vid_voodoo.c vid_voodoo_banshee.c diff --git a/src/video/vid_av9194.c b/src/video/clockgen/vid_clockgen_av9194.c similarity index 100% rename from src/video/vid_av9194.c rename to src/video/clockgen/vid_clockgen_av9194.c diff --git a/src/video/vid_icd2061.c b/src/video/clockgen/vid_clockgen_icd2061.c similarity index 100% rename from src/video/vid_icd2061.c rename to src/video/clockgen/vid_clockgen_icd2061.c diff --git a/src/video/vid_ics2494.c b/src/video/clockgen/vid_clockgen_ics2494.c similarity index 100% rename from src/video/vid_ics2494.c rename to src/video/clockgen/vid_clockgen_ics2494.c diff --git a/src/video/vid_ics2595.c b/src/video/clockgen/vid_clockgen_ics2595.c similarity index 100% rename from src/video/vid_ics2595.c rename to src/video/clockgen/vid_clockgen_ics2595.c diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/ramdac/vid_ramdac_ati68860.c similarity index 100% rename from src/video/vid_ati68860_ramdac.c rename to src/video/ramdac/vid_ramdac_ati68860.c diff --git a/src/video/vid_ati68875_ramdac.c b/src/video/ramdac/vid_ramdac_ati68875.c similarity index 100% rename from src/video/vid_ati68875_ramdac.c rename to src/video/ramdac/vid_ramdac_ati68875.c diff --git a/src/video/vid_att20c49x_ramdac.c b/src/video/ramdac/vid_ramdac_att20c49x.c similarity index 100% rename from src/video/vid_att20c49x_ramdac.c rename to src/video/ramdac/vid_ramdac_att20c49x.c diff --git a/src/video/vid_att2xc498_ramdac.c b/src/video/ramdac/vid_ramdac_att2xc498.c similarity index 100% rename from src/video/vid_att2xc498_ramdac.c rename to src/video/ramdac/vid_ramdac_att2xc498.c diff --git a/src/video/vid_bt481_ramdac.c b/src/video/ramdac/vid_ramdac_bt481.c similarity index 100% rename from src/video/vid_bt481_ramdac.c rename to src/video/ramdac/vid_ramdac_bt481.c diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/ramdac/vid_ramdac_bt48x.c similarity index 100% rename from src/video/vid_bt48x_ramdac.c rename to src/video/ramdac/vid_ramdac_bt48x.c diff --git a/src/video/vid_ibm_rgb528_ramdac.c b/src/video/ramdac/vid_ramdac_ibm_rgb528.c similarity index 100% rename from src/video/vid_ibm_rgb528_ramdac.c rename to src/video/ramdac/vid_ramdac_ibm_rgb528.c diff --git a/src/video/vid_sc1148x_ramdac.c b/src/video/ramdac/vid_ramdac_sc1148x.c similarity index 100% rename from src/video/vid_sc1148x_ramdac.c rename to src/video/ramdac/vid_ramdac_sc1148x.c diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/ramdac/vid_ramdac_sc1502x.c similarity index 100% rename from src/video/vid_sc1502x_ramdac.c rename to src/video/ramdac/vid_ramdac_sc1502x.c diff --git a/src/video/vid_sdac_ramdac.c b/src/video/ramdac/vid_ramdac_sdac.c similarity index 100% rename from src/video/vid_sdac_ramdac.c rename to src/video/ramdac/vid_ramdac_sdac.c diff --git a/src/video/vid_stg_ramdac.c b/src/video/ramdac/vid_ramdac_stg1702.c similarity index 100% rename from src/video/vid_stg_ramdac.c rename to src/video/ramdac/vid_ramdac_stg1702.c diff --git a/src/video/vid_tkd8001_ramdac.c b/src/video/ramdac/vid_ramdac_tkd8001.c similarity index 100% rename from src/video/vid_tkd8001_ramdac.c rename to src/video/ramdac/vid_ramdac_tkd8001.c diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/ramdac/vid_ramdac_tvp3026.c similarity index 100% rename from src/video/vid_tvp3026_ramdac.c rename to src/video/ramdac/vid_ramdac_tvp3026.c From 8e32c973395afc59306aaddc0fdaa62b420fd857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= <oubattler@gmail.com> Date: Wed, 18 Jun 2025 10:45:56 +0200 Subject: [PATCH 1162/1190] (S)VGA: Do some compensation when calculating the overscan, fixes #5688. --- src/video/vid_svga.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index cf3a22c5c..b0d9765da 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -956,14 +956,18 @@ svga_recalctimings(svga_t *svga) svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); svga->left_overscan = svga->x_add = (svga->htotal - adj_dot - 1) * svga->dots_per_clock; - svga->monitor->mon_overscan_x = svga->x_add + (svga->hblankstart * svga->dots_per_clock) - hd; + svga->monitor->mon_overscan_x = svga->x_add + (svga->hblankstart * svga->dots_per_clock) - hd + svga->dots_per_clock; + /* Compensate for the HDISP code above. */ + if (svga->crtc[1] & 1) + svga->monitor->mon_overscan_x++; if ((svga->hdisp >= 2048) || (svga->left_overscan < 0)) { svga->left_overscan = svga->x_add = 0; svga->monitor->mon_overscan_x = 0; } - svga->y_add = svga->vtotal - vblankend + 1; + /* - 1 because + 1 but also - 2 to compensate for the + 2 added to vtotal above. */ + svga->y_add = svga->vtotal - vblankend - 1; svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend); if ((svga->dispend >= 2048) || (svga->y_add < 0)) { From dd305a174cc70f7b21c0d6e2f07c03422635f2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= <oubattler@gmail.com> Date: Wed, 18 Jun 2025 11:06:25 +0200 Subject: [PATCH 1163/1190] Tandy: Fix last scanline in doube-scanned 40-column text mode, fixes #5689. --- src/video/vid_tandy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index 312527a35..0609ca378 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -483,7 +483,7 @@ vid_poll(void *priv) vid->memaddr++; if (vid->scanline & 8) { for (c = 0; c < 8; c++) - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; } else { for (c = 0; c < 8; c++) { if (vid->scanline == 8) { @@ -824,4 +824,4 @@ const device_t tandy_1000sl_video_device = { .speed_changed = tandy_vid_speed_changed, .force_redraw = NULL, .config = NULL -}; \ No newline at end of file +}; From 83832b5a3719b5f243d0f5b7add74633f85e1741 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Thu, 19 Jun 2025 01:55:03 +0200 Subject: [PATCH 1164/1190] MDA: A small bug fix. --- src/video/vid_mda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index f48fefec1..5330e2ab3 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -186,7 +186,7 @@ mda_poll(void *priv) // turn off bright bg colours in blink mode if ((mda->mode & MDA_MODE_BLINK) && (color_bg & 0x8)) - color_bg & ~(0x8); + color_bg &= ~(0x8); // black-on-non black or white colours forced to white // grey-on-colours forced to bright white From 212401bed6745bc8041bbbd6e043334d1cf1a8d1 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 22 Jun 2025 21:29:46 -0500 Subject: [PATCH 1165/1190] Ensure the S3 ViRGE type is correctly assigned including when using an onboard ViRGE --- src/video/vid_s3_virge.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 9422f69bf..774b0d4b7 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -211,6 +211,7 @@ typedef struct virge_t { uint8_t pci_regs[256]; uint8_t pci_slot; + uint8_t type; int chip; int bilinear_enabled; @@ -5140,9 +5141,11 @@ s3_virge_init(const device_t *info) virge_t *virge = (virge_t *) calloc(1, sizeof(virge_t)); reset_state = calloc(1, sizeof(virge_t)); + virge->type = (info->local & 0xff); + virge->bilinear_enabled = device_get_config_int("bilinear"); virge->dithering_enabled = device_get_config_int("dithering"); - if (info->local >= S3_VIRGE_GX2) + if (virge->type >= S3_VIRGE_GX2) virge->memory_size = 4; else virge->memory_size = device_get_config_int("memory"); @@ -5150,7 +5153,7 @@ s3_virge_init(const device_t *info) virge->onboard = !!(info->local & 0x100); if (!virge->onboard) - switch (info->local) { + switch (virge->type) { case S3_VIRGE_325: bios_fn = ROM_VIRGE_325; break; @@ -5197,7 +5200,7 @@ s3_virge_init(const device_t *info) virge->svga.hwcursor.cur_ysize = 64; if (bios_fn != NULL) { - if (info->local == S3_VIRGE_GX2) + if (virge->type == S3_VIRGE_GX2) rom_init(&virge->bios_rom, bios_fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); else rom_init(&virge->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -5251,7 +5254,7 @@ s3_virge_init(const device_t *info) virge->virge_id = 0xe1; virge->is_agp = !!(info->flags & DEVICE_AGP); - switch (info->local) { + switch (virge->type) { case S3_VIRGE_325: case S3_DIAMOND_STEALTH3D_2000: case S3_MIROCRYSTAL_3D: @@ -5356,7 +5359,7 @@ s3_virge_init(const device_t *info) default: break; } - if (info->local == S3_VIRGE_GX) + if (virge->type == S3_VIRGE_GX) virge->svga.crtc[0x36] |= (1 << 2); } From ef342b4031a8cfe41f82998e7916f275974fab89 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Tue, 24 Jun 2025 04:25:19 +0200 Subject: [PATCH 1166/1190] Added the no brown option for PCjr. --- src/86box.c | 2 ++ src/include/86box/m_pcjr.h | 6 ++++-- src/machine/m_pcjr.c | 8 +++++--- src/video/vid_pcjr.c | 7 +++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/86box.c b/src/86box.c index 92e2f0c24..3994d72f2 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1606,6 +1606,8 @@ pc_close(UNUSED(thread_t *ptr)) plat_mouse_capture(0); + warning("CS:EIP = %04X:%08X\n", CS, cpu_state.pc); + /* Close all the memory mappings. */ mem_close(); diff --git a/src/include/86box/m_pcjr.h b/src/include/86box/m_pcjr.h index 7a137fb03..c6cb33588 100644 --- a/src/include/86box/m_pcjr.h +++ b/src/include/86box/m_pcjr.h @@ -17,8 +17,10 @@ #pragma once -#define PCJR_RGB 0 -#define PCJR_COMPOSITE 1 +#define PCJR_RGB 0 +#define PCJR_COMPOSITE 1 +#define PCJR_RGB_NO_BROWN 4 +#define PCJR_RGB_IBM_5153 5 typedef struct pcjr_s { diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index e76889d93..30a5e609a 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -782,9 +782,11 @@ static const device_config_t pcjr_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "RGB", .value = PCJR_RGB }, - { .description = "Composite", .value = PCJR_COMPOSITE }, - { .description = "" } + { .description = "RGB", .value = PCJR_RGB }, + { .description = "Composite", .value = PCJR_COMPOSITE }, + { .description = "RGB (no brown)", .value = PCJR_RGB_NO_BROWN }, + { .description = "RGB (IBM 5153)", .value = PCJR_RGB_IBM_5153 }, + { .description = "" } } }, { diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index 17a43fb40..2b3eb730a 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -686,7 +686,7 @@ pcjr_vid_init(pcjr_t *pcjr) pcjr->memctrl &= ~0x24; display_type = device_get_config_int("display_type"); - pcjr->composite = (display_type != PCJR_RGB); + pcjr->composite = (display_type == PCJR_COMPOSITE); pcjr->apply_hd = device_get_config_int("apply_hd"); overscan_x = 256; overscan_y = 32; @@ -698,6 +698,9 @@ pcjr_vid_init(pcjr_t *pcjr) vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); timer_add(&pcjr->timer, vid_poll, pcjr, 1); - cga_palette = 0; + if (pcjr->composite) + cga_palette = 0; + else + cga_palette = (display_type << 1); cgapal_rebuild(); } From 6a8eaf507c67c2af7000235c5c0ed2d0e4f36730 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Tue, 24 Jun 2025 05:13:05 +0200 Subject: [PATCH 1167/1190] Fixed all the warnings and reverted a change to 86box.c that was not supposed to be committed. --- src/86box.c | 10 ++++++---- src/qt/qt_platform.cpp | 4 ++-- src/qt/qt_vmmanager_main.cpp | 1 - src/qt/qt_vmmanager_system.cpp | 14 ++++++++------ 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/86box.c b/src/86box.c index e5b0f46cc..8c07daa15 100644 --- a/src/86box.c +++ b/src/86box.c @@ -639,7 +639,7 @@ pc_show_usage(char *s) ui_msgbox(MBX_ANSI | ((s == NULL) ? MBX_INFO : MBX_WARNING), p); #else if (s == NULL) - pclog(p); + pclog("%s", p); else ui_msgbox(MBX_ANSI | MBX_WARNING, p); #endif @@ -742,7 +742,11 @@ usage: /* Using this variable for vm manager path Temporary solution!*/ if ((c+1) == argc) goto usage; - strcpy(vmm_path, argv[++c]); + char *vp = argv[++c]; + if ((strlen(vp) + 1) >= sizeof(vmm_path)) + memcpy(vmm_path, vp, sizeof(vmm_path)); + else + memcpy(vmm_path, vp, strlen(vp) + 1); //#endif } else if (!strcasecmp(argv[c], "--fullscreen") || !strcasecmp(argv[c], "-F")) { start_in_fullscreen = 1; @@ -1613,8 +1617,6 @@ pc_close(UNUSED(thread_t *ptr)) plat_mouse_capture(0); - warning("CS:EIP = %04X:%08X\n", CS, cpu_state.pc); - /* Close all the memory mappings. */ mem_close(); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index a8c25bc2d..8c2586482 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -776,8 +776,8 @@ plat_set_thread_name(void *thread, const char *name) if (pSetThreadDescription) { size_t len = strlen(name) + 1; - wchar_t wname[len + 1]; - mbstowcs(wname, name, len); + wchar_t wname[2048]; + mbstowcs(wname, name, (len >= 1024) ? 1024 : len); pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname); } #else diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index c49340647..8c83b549f 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -236,7 +236,6 @@ VMManagerMain::shutdownForceButtonPressed() const void VMManagerMain::refresh() { - bool running = selected_sysconfig->process->state() == QProcess::ProcessState::Running; const auto current_index = ui->listView->currentIndex(); emit selectionChanged(current_index, selected_sysconfig->process->state()); diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 68b83c3a8..08853feab 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -747,18 +747,20 @@ VMManagerSystem::setupVars() { QStringList serialFinal; QStringList lptFinal; int portIndex = 0; - for(const auto &serialNum: serial_enabled) { - if (serial_enabled[portIndex]) { + while (true) { + if (serial_enabled[portIndex]) serialFinal.append(QString("COM%1").arg(portIndex + 1)); - } ++portIndex; + if (portIndex == SERIAL_MAX) + break; } portIndex = 0; - for (const auto &lptNum: lpt_enabled) { - if (lpt_enabled[portIndex]) { + while (true) { + if (lpt_enabled[portIndex]) lptFinal.append(QString("LPT%1").arg(portIndex + 1)); - } ++portIndex; + if (portIndex == PARALLEL_MAX) + break; } display_table[Display::Name::Serial] = serialFinal.empty() ? tr("None") : serialFinal.join(", "); display_table[Display::Name::Parallel] = lptFinal.empty() ? tr("None") : lptFinal.join(", "); From 8a9e06ff110ad76ca55f2b0e675b71a724d9a40e Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Tue, 24 Jun 2025 12:37:51 +0300 Subject: [PATCH 1168/1190] Update the Russian translation Update the Russian translation --- src/qt/languages/ru-RU.po | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index bb8a9caf5..b721d6f29 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -147,6 +147,12 @@ msgstr "RGB &цветной" msgid "&RGB Grayscale" msgstr "&RGB монохромный" +msgid "RGB (no brown)" +msgstr "RGB (без коричневого)" + +msgid "Generic RGBI color monitor" +msgstr "Стандартный цветной монитор RGBI" + msgid "&Amber monitor" msgstr "&Янтарный оттенок" @@ -1789,7 +1795,7 @@ msgid "Dithering" msgstr "Дизеринг" msgid "Enable NMI for CGA emulation" -msgstr "Включение NMI для эмуляции CGA" +msgstr "Включить NMI для эмуляции CGA" msgid "Voodoo type" msgstr "Тип Voodoo" From 58aa26127345d00944fe9ba2091898881d85a271 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Tue, 24 Jun 2025 01:23:32 -0400 Subject: [PATCH 1169/1190] LPT ECP/EPP support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Miran Grča <oubattler@gmail.com> --- src/device/CMakeLists.txt | 2 +- src/device/hasp.c | 22 +- src/device/lpt.c | 837 ++++++++++++++++++++++++++++++++++++++ src/include/86box/lpt.h | 59 ++- src/lpt.c | 264 ------------ src/network/net_plip.c | 21 +- src/printer/prt_escp.c | 62 ++- src/printer/prt_ps.c | 71 +++- src/printer/prt_text.c | 53 ++- src/sio/sio_ali5123.c | 12 +- src/sio/sio_pc87306.c | 79 ++-- src/sound/snd_lpt_dac.c | 50 ++- src/sound/snd_lpt_dss.c | 21 +- 13 files changed, 1161 insertions(+), 392 deletions(-) create mode 100644 src/device/lpt.c delete mode 100644 src/lpt.c diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 29fc0b9b4..999b83aeb 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -41,7 +41,7 @@ add_library(dev OBJECT keyboard.c keyboard_at.c keyboard_xt.c - ../lpt.c + lpt.c mouse.c mouse_bus.c mouse_microtouch_touchscreen.c diff --git a/src/device/hasp.c b/src/device/hasp.c index 3834af4cd..53228c2a0 100644 --- a/src/device/hasp.c +++ b/src/device/hasp.c @@ -27,6 +27,7 @@ #include <stdarg.h> #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/timer.h> #include <86box/lpt.h> #include <86box/device.h> @@ -334,13 +335,16 @@ hasp_close(void *priv) } const lpt_device_t lpt_hasp_savquest_device = { - .name = "Protection Dongle for Savage Quest", - .internal_name = "dongle_savquest", - .init = hasp_init_savquest, - .close = hasp_close, - .write_data = hasp_write_data, - .write_ctrl = NULL, - .read_data = NULL, - .read_status = hasp_read_status, - .read_ctrl = NULL + .name = "Protection Dongle for Savage Quest", + .internal_name = "dongle_savquest", + .init = hasp_init_savquest, + .close = hasp_close, + .write_data = hasp_write_data, + .write_ctrl = NULL, + .autofeed = NULL, + .strobe = NULL, + .read_status = hasp_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/device/lpt.c b/src/device/lpt.c new file mode 100644 index 000000000..179dc9a2d --- /dev/null +++ b/src/device/lpt.c @@ -0,0 +1,837 @@ +/* Copyright holders: Sarah Walker + see COPYING for more details +*/ +#include <stdarg.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <wchar.h> +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/fifo.h> +#include <86box/timer.h> +#include <86box/dma.h> +#include <86box/lpt.h> +#include <86box/pic.h> +#include <86box/sound.h> +#include <86box/prt_devs.h> +#include <86box/thread.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/network.h> + +lpt_port_t lpt_ports[PARALLEL_MAX]; + +const lpt_device_t lpt_none_device = { + .name = "None", + .internal_name = "none", + .init = NULL, + .close = NULL, + .write_data = NULL, + .write_ctrl = NULL, + .read_status = NULL, + .read_ctrl = NULL +}; + +static const struct { + const char *internal_name; + const lpt_device_t *device; +} lpt_devices[] = { + // clang-format off + {"none", &lpt_none_device }, + {"dss", &dss_device }, + {"lpt_dac", &lpt_dac_device }, + {"lpt_dac_stereo", &lpt_dac_stereo_device }, + {"text_prt", &lpt_prt_text_device }, + {"dot_matrix", &lpt_prt_escp_device }, + {"postscript", &lpt_prt_ps_device }, + {"pcl", &lpt_prt_pcl_device }, + {"plip", &lpt_plip_device }, + {"dongle_savquest", &lpt_hasp_savquest_device }, + {"", NULL } + // clang-format on +}; + +#ifdef ENABLE_LPT_LOG +int lpt_do_log = ENABLE_LPT_LOG; + +static void +lpt_log(const char *fmt, ...) +{ + va_list ap; + + if (lpt_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define lpt_log(fmt, ...) +#endif + +const char * +lpt_device_get_name(const int id) +{ + if (strlen(lpt_devices[id].internal_name) == 0) + return NULL; + if (lpt_devices[id].device == NULL) + return "None"; + return lpt_devices[id].device->name; +} + +const char * +lpt_device_get_internal_name(const int id) +{ + if (strlen(lpt_devices[id].internal_name) == 0) + return NULL; + return lpt_devices[id].internal_name; +} + +int +lpt_device_get_from_internal_name(const char *s) +{ + int c = 0; + + while (strlen(lpt_devices[c].internal_name) != 0) { + if (strcmp(lpt_devices[c].internal_name, s) == 0) + return c; + c++; + } + + return 0; +} + +void +lpt_devices_init(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; + + if (lpt_ports[i].dt && lpt_ports[i].dt->init) + lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); + } +} + +void +lpt_devices_close(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_port_t *dev = &lpt_ports[i]; + + if (lpt_ports[i].dt && lpt_ports[i].dt->close) + dev->dt->close(dev->priv); + + dev->dt = NULL; + } +} + +static uint8_t +lpt_get_ctrl_raw(const lpt_port_t *dev) +{ + uint8_t ret; + + if (dev->dt && dev->dt->read_ctrl && dev->priv) + ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; + else + ret = 0xc0 | dev->ctrl | dev->enable_irq; + + return ret & 0xdf; +} + +static uint8_t +lpt_is_epp(const lpt_port_t *dev) +{ + return (dev->epp || ((dev->ecp) && ((dev->ecr & 0xe0) == 0x80))); +} + +static uint8_t +lpt_get_ctrl(const lpt_port_t *dev) +{ + uint8_t ret = lpt_get_ctrl_raw(dev); + + if (!dev->ecp && !dev->epp) + ret |= 0x20; + + return ret; +} + +static void +lpt_write_fifo(lpt_port_t *dev, const uint8_t val, const uint8_t tag) +{ + if (!fifo_get_full(dev->fifo)) { + fifo_write_evt_tagged(tag, val, dev->fifo); + + if (!timer_is_enabled(&dev->fifo_out_timer)) + timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } +} + +static void +lpt_ecp_update_irq(lpt_port_t *dev) +{ + if (!(dev->ecr & 0x04) && ((dev->fifo_stat | dev->dma_stat) & 0x04)) + picintlevel(1 << dev->irq, &dev->irq_state); + else + picintclevel(1 << dev->irq, &dev->irq_state); +} + +static void +lpt_autofeed(lpt_port_t *dev, const uint8_t val) +{ + if (dev->dt && dev->dt->autofeed && dev->priv) + dev->dt->autofeed(val, dev->priv); + + dev->autofeed = val; +} + +static void +lpt_strobe(lpt_port_t *dev, const uint8_t val) +{ + if (dev->dt && dev->dt->strobe && dev->priv) + dev->dt->strobe(dev->strobe, val, dev->priv); + + dev->strobe = val; +} + +static void +lpt_fifo_out_callback(void *priv) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + switch (dev->state) { + default: + break; + + case LPT_STATE_READ_DMA: + ; + int ret = 0xff; + + if (dev->dma == 0xff) + ret = DMA_NODATA; + else + ret = dma_channel_read(dev->dma); + + lpt_log("DMA %02X: %08X\n", dev->dma, ret); + + if (ret != DMA_NODATA) { + fifo_write_evt_tagged(0x01, (uint8_t) (ret & 0xff), dev->fifo); + + if (ret & DMA_OVER) + /* Internal flag to indicate we have finished the DMA reads. */ + dev->dma_stat = 0x08; + } + + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + + if (dev->dma_stat || fifo_get_full(dev->fifo)) + dev->state = LPT_STATE_WRITE_FIFO; + break; + + case LPT_STATE_WRITE_FIFO: + if (!fifo_get_empty(dev->fifo)) { + uint8_t tag = 0x00; + const uint8_t val = fifo_read_evt_tagged(&tag, dev->fifo); + + lpt_log("FIFO: %02X, TAG = %02X\n", val, tag); + + /* We do not currently support sending commands. */ + if (tag == 0x01) { + if (dev->dt && dev->dt->write_data && dev->priv) + dev->dt->write_data(val, dev->priv); + + lpt_strobe(dev, 1); + lpt_strobe(dev, 0); + } + } + + if (dev->ecr & 0x08) { + if (fifo_get_empty(dev->fifo)) { + if (dev->dma_stat) { + /* Now actually set the external flag. */ + dev->dma_stat = 0x04; + dev->state = LPT_STATE_IDLE; + lpt_ecp_update_irq(dev); + lpt_autofeed(dev, 0); + } else { + dev->state = LPT_STATE_READ_DMA; + + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } + } else + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } else if (!fifo_get_empty(dev->fifo)) + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + else + lpt_autofeed(dev, 0); + break; + } +} + +void +lpt_write(const uint16_t port, const uint8_t val, void *priv) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + uint16_t mask = 0x0407; + + lpt_log("[W] %04X = %02X\n", port, val); + + /* This is needed so the parallel port at 3BC works. */ + if (dev->addr & 0x0004) + mask = 0x0403; + + switch (port & mask) { + case 0x0000: + if (dev->ecp) { + if ((dev->ecr & 0xe0) == 0x60) + /* AFIFO */ + lpt_write_fifo(dev, val, 0x00); + else if (!(dev->ecr & 0xc0) && (!(dev->ecr & 0x20) || !(lpt_get_ctrl_raw(dev) & 0x20)) && + dev->dt && dev->dt->write_data && dev->priv) + /* DATAR */ + dev->dt->write_data(val, dev->priv); + dev->dat = val; + } else { + /* DTR */ + if ((!dev->ext || !(lpt_get_ctrl_raw(dev) & 0x20)) && dev->dt && + dev->dt->write_data && dev->priv) + dev->dt->write_data(val, dev->priv); + dev->dat = val; + } + break; + + case 0x0001: + break; + + case 0x0002: + if (dev->dt && dev->dt->write_ctrl && dev->priv) { + if (dev->ecp) + dev->dt->write_ctrl((val & 0xfc) | dev->autofeed | dev->strobe, dev->priv); + else + dev->dt->write_ctrl(val, dev->priv); + } + dev->ctrl = val; + dev->enable_irq = val & 0x10; + if (!(val & 0x10) && (dev->irq != 0xff)) + picintc(1 << dev->irq); + dev->irq_state = 0; + break; + + case 0x0003: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_write_data && dev->priv) + dev->dt->epp_write_data(1, val, dev->priv); + } + break; + + case 0x0004 ... 0x0007: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_write_data && dev->priv) + dev->dt->epp_write_data(0, val, dev->priv); + } + break; + + case 0x0400: case 0x0404: + switch (dev->ecr >> 5) { + default: + break; + case 2: + lpt_write_fifo(dev, val, 0x01); + break; + case 3: + if (!(lpt_get_ctrl_raw(dev) & 0x20)) + lpt_write_fifo(dev, val, 0x01); + break; + case 6: + /* TFIFO */ + if (!fifo_get_full(dev->fifo)) + fifo_write_evt(val, dev->fifo); + break; + } + break; + + case 0x0402: case 0x0406: + if (!(val & 0x0c)) + lpt_autofeed(dev, 0x00); + else + lpt_autofeed(dev, 0x02); + + if ((dev->ecr & 0x04) && !(val & 0x04)) { + dev->dma_stat = 0x00; + fifo_reset(dev->fifo); + if (val & 0x08) { + dev->state = LPT_STATE_READ_DMA; + dev->fifo_stat = 0x00; + if (!timer_is_enabled(&dev->fifo_out_timer)) + timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } else { + dev->state = LPT_STATE_WRITE_FIFO; + if (lpt_get_ctrl_raw(dev) & 0x20) + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00; + else + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04; + } + } else if ((val & 0x04) && !(dev->ecr & 0x04)) { + if (timer_is_enabled(&dev->fifo_out_timer)) + timer_disable(&dev->fifo_out_timer); + + dev->state = LPT_STATE_IDLE; + } + dev->ecr = val; + lpt_ecp_update_irq(dev); + break; + + default: + break; + } +} + +static void +lpt_fifo_d_ready_evt(void *priv) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + if (!(dev->ecr & 0x08)) { + if (lpt_get_ctrl_raw(dev) & 0x20) + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00; + else + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04; + } + + lpt_ecp_update_irq(dev); +} + +void +lpt_write_to_fifo(void *priv, const uint8_t val) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + if (dev->ecp) { + if (((dev->ecr & 0xe0) == 0x20) && (lpt_get_ctrl_raw(dev) & 0x20)) + dev->dat = val; + else if (((dev->ecr & 0xe0) == 0x60) && (lpt_get_ctrl_raw(dev) & 0x20) && + !fifo_get_full(dev->fifo)) + fifo_write_evt_tagged(0x01, val, dev->fifo); + + if (((dev->ecr & 0x0c) == 0x08) && (dev->dma != 0xff)) { + const int ret = dma_channel_write(dev->dma, val); + + if (ret & DMA_OVER) + dev->dma_stat |= 0x04; + } + } else { + if (dev->ext && (lpt_get_ctrl_raw(dev) & 0x20)) + dev->dat = val; + } +} + +void +lpt_write_to_dat(void *priv, const uint8_t val) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + dev->dat = val; +} + +static uint8_t +lpt_read_fifo(const lpt_port_t *dev) +{ + uint8_t ret = 0xff; + + if (!fifo_get_empty(dev->fifo)) + ret = fifo_read(dev->fifo); + + return ret; +} + +uint8_t +lpt_read_status(const int port) +{ + lpt_port_t *dev = &lpt_ports[port]; + uint8_t low_bits = 0x07; + uint8_t ret; + + if (dev->ext) { + low_bits = 0x03 | (dev->irq_state ? 0x00 : 0x04); + if (dev->irq != 0xff) + picintclevel(1 << dev->irq, &dev->irq_state); + dev->irq_state = 0; + } + if (dev->epp || dev->ecp) { + low_bits = lpt_is_epp(dev) ? 0x02 : 0x03; + if (lpt_get_ctrl_raw(dev) & 0x10) + low_bits |= (dev->irq_state ? 0x00 : 0x04); + else + low_bits |= 0x04; + } + + if (dev->dt && dev->dt->read_status && dev->priv) + ret = (dev->dt->read_status(dev->priv) & 0xf8) | low_bits; + else + ret = 0xd8 | low_bits; + + return ret; +} + +uint8_t +lpt_read(const uint16_t port, void *priv) +{ + const lpt_port_t *dev = (lpt_port_t *) priv; + uint16_t mask = 0x0407; + uint8_t ret = 0xff; + + /* This is needed so the parallel port at 3BC works. */ + if (dev->addr & 0x0004) + mask = 0x0403; + + switch (port & mask) { + case 0x0000: + if (dev->ecp) { + if (!(dev->ecr & 0xc0)) + ret = dev->dat; + } else { + /* DTR */ + ret = dev->dat; + } + break; + + case 0x0001: + ret = lpt_read_status(dev->id); + break; + + case 0x0002: + ret = lpt_get_ctrl(dev); + if (dev->ecp) + ret = (ret & 0xfc) | (dev->ctrl & 0x03); + break; + + case 0x0003: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_request_read && dev->priv) + dev->dt->epp_request_read(1, dev->priv); + ret = dev->dat; + } + break; + + case 0x0004 ... 0x0007: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_request_read && dev->priv) + dev->dt->epp_request_read(0, dev->priv); + ret = dev->dat; + } + break; + + case 0x0400: case 0x0404: + switch (dev->ecr >> 5) { + default: + break; + case 3: + if (lpt_get_ctrl_raw(dev) & 0x20) + ret = lpt_read_fifo(dev); + break; + case 6: + /* TFIFO */ + if (!fifo_get_empty(dev->fifo)) + ret = fifo_read_evt(dev->fifo); + break; + case 7: + /* CNFGA */ + ret = 0x14; + break; + } + break; + + case 0x0401: case 0x0405: + if ((dev->ecr & 0xe0) == 0xe0) { + /* CNFGB */ + ret = 0x08; + ret |= (dev->irq_state ? 0x40 : 0x00); + ret |= ((dev->irq == 0x05) ? 0x30 : 0x00); + if ((dev->dma >= 1) && (dev->dma <= 3)) + ret |= dev->dma; + } + break; + + case 0x0402: case 0x0406: + ret = dev->ecr | dev->fifo_stat | (dev->dma_stat & 0x04); + ret |= (fifo_get_full(dev->fifo) ? 0x02 : 0x00); + ret |= (fifo_get_empty(dev->fifo) ? 0x01 : 0x00); + break; + + default: + break; + } + + lpt_log("[R] %04X = %02X\n", port, ret); + + return ret; +} + +uint8_t +lpt_read_port(const int port, const uint16_t reg) +{ + lpt_port_t *dev = &(lpt_ports[port]); + + return lpt_read(reg, dev); +} + +void +lpt_irq(void *priv, const int raise) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + if (dev->enable_irq) { + if (dev->irq != 0xff) { + if (dev->ext) { + if (raise) + picintlevel(1 << dev->irq, &dev->irq_state); + else + picintclevel(1 << dev->irq, &dev->irq_state); + } else { + if (raise) + picint(1 << dev->irq); + else + picintc(1 << dev->irq); + } + } + + if (!dev->ext || (dev->irq == 0xff)) + dev->irq_state = raise; + } else { + if (dev->irq != 0xff) { + if (dev->ext) + picintclevel(1 << dev->irq, &dev->irq_state); + else + picintc(1 << dev->irq); + } + + dev->irq_state = 0; + } +} + +void +lpt_set_ext(const int port, const uint8_t ext) +{ + if (lpt_ports[port].enabled) + lpt_ports[port].ext = ext; +} + +void +lpt_set_ecp(const int port, const uint8_t ecp) +{ + if (lpt_ports[port].enabled) { + const uint16_t addr = lpt_ports[port].addr; + lpt_port_setup(port, 0xfff); + lpt_ports[port].ecp = ecp; + lpt_port_setup(port, addr); + } +} + +void +lpt_set_epp(const int port, const uint8_t epp) +{ + if (lpt_ports[port].enabled) { + const uint16_t addr = lpt_ports[port].addr; + lpt_port_setup(port, 0xfff); + lpt_ports[port].epp = epp; + lpt_port_setup(port, addr); + } +} + +void +lpt_set_lv2(const int port, const uint8_t lv2) +{ + if (lpt_ports[port].enabled) { + const uint16_t addr = lpt_ports[port].addr; + lpt_port_setup(port, 0xfff); + lpt_ports[port].lv2 = lv2; + lpt_port_setup(port, addr); + } +} + +void +lpt_close(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + if (lpt_ports[i].enabled) { + fifo_close(lpt_ports[i].fifo); + lpt_ports[i].fifo = NULL; + + timer_disable(&lpt_ports[i].fifo_out_timer); + } + } +} + +void +lpt_port_zero(lpt_port_t *dev) +{ + lpt_port_t temp = { 0 }; + + temp.irq = dev->irq; + temp.id = dev->id; + temp.device = dev->device; + temp.dt = dev->dt; + temp.priv = dev->priv; + temp.enabled = dev->enabled; + temp.fifo = dev->fifo; + temp.fifo_out_timer = dev->fifo_out_timer; + + if (dev->enabled) + lpt_port_remove(dev->id); + + memset(dev, 0x00, sizeof(lpt_port_t)); + + dev->addr = 0xffff; + dev->irq = temp.irq; + dev->id = temp.id; + dev->device = temp.device; + dev->dt = temp.dt; + dev->priv = temp.priv; + dev->enabled = temp.enabled; + dev->fifo = temp.fifo; + dev->fifo_out_timer = temp.fifo_out_timer; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + dev->ext = 1; +} + +void +lpt_reset(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + if (lpt_ports[i].enabled) + if (timer_is_enabled(&lpt_ports[i].fifo_out_timer)) + timer_disable(&lpt_ports[i].fifo_out_timer); + + lpt_port_zero(&(lpt_ports[i])); + + if (lpt_ports[i].enabled) { + if (lpt_ports[i].irq_state) { + if (lpt_ports[i].irq == 0xff) + lpt_ports[i].irq_state = 0x00; + else { + picintclevel(lpt_ports[i].irq, &lpt_ports[i].irq_state); + picintc(lpt_ports[i].irq); + } + } + + lpt_ports[i].enable_irq = 0x00; + lpt_ports[i].ext = !!(machine_has_bus(machine, MACHINE_BUS_MCA)); + lpt_ports[i].epp = 0; + lpt_ports[i].ecp = 0; + lpt_ports[i].ecr = 0x15; + lpt_ports[i].dat = 0xff; + lpt_ports[i].fifo_stat = 0x00; + lpt_ports[i].dma_stat = 0x00; + } + } +} + +void +lpt_init(void) +{ + const uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR }; + const uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ }; + + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].id = i; + lpt_ports[i].dt = NULL; + lpt_ports[i].priv = NULL; + lpt_ports[i].fifo = NULL; + memset(&lpt_ports[i].fifo_out_timer, 0x00, sizeof(pc_timer_t)); + + lpt_port_zero(&(lpt_ports[i])); + + lpt_ports[i].addr = 0xffff; + lpt_ports[i].irq = 0xff; + lpt_ports[i].dma = 0xff; + lpt_ports[i].enable_irq = 0x00; + lpt_ports[i].ext = 0; + lpt_ports[i].epp = 0; + lpt_ports[i].ecp = 0; + lpt_ports[i].ecr = 0x15; + + if (lpt_ports[i].enabled) { + lpt_port_setup(i, default_ports[i]); + lpt_port_irq(i, default_irqs[i]); + + lpt_ports[i].fifo = fifo16_init(); + + fifo_set_trigger_len(lpt_ports[i].fifo, 8); + + fifo_set_d_ready_evt(lpt_ports[i].fifo, lpt_fifo_d_ready_evt); + fifo_set_priv(lpt_ports[i].fifo, &lpt_ports[i]); + + timer_add(&lpt_ports[i].fifo_out_timer, lpt_fifo_out_callback, &lpt_ports[i], 0); + } + } +} + +void +lpt_port_setup(const int i, const uint16_t port) +{ + if (lpt_ports[i].enabled) { + if (lpt_ports[i].addr != 0xffff) { + io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + } + if (port != 0xffff) { + lpt_log("Set handler: %04X-%04X\n", port, port + 0x0003); + io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (lpt_ports[i].epp) + io_sethandler(lpt_ports[i].addr + 0x0003, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (lpt_ports[i].ecp || lpt_ports[i].lv2) { + io_sethandler(port + 0x0400, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (lpt_ports[i].epp) + io_sethandler(lpt_ports[i].addr + 0x0403, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + } + } + lpt_ports[i].addr = port; + } else + lpt_ports[i].addr = 0xffff; +} + +void +lpt_port_irq(const int i, const uint8_t irq) +{ + if (lpt_ports[i].enabled) + lpt_ports[i].irq = irq; + else + lpt_ports[i].irq = 0xff; + + lpt_log("Port %i IRQ = %02X\n", i, irq); +} + +void +lpt_port_dma(const int i, const uint8_t dma) +{ + if (lpt_ports[i].enabled) + lpt_ports[i].dma = dma; + else + lpt_ports[i].dma = 0xff; + + lpt_log("Port %i DMA = %02X\n", i, dma); +} + +void +lpt_port_remove(const int i) +{ + if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) { + io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + + lpt_ports[i].addr = 0xffff; + } +} + +void +lpt1_remove_ams(void) +{ + if (lpt_ports[0].enabled) + io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]); +} diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index 674d6340f..c13d70291 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -25,14 +25,24 @@ typedef struct lpt_device_t { void (*close)(void *priv); void (*write_data)(uint8_t val, void *priv); void (*write_ctrl)(uint8_t val, void *priv); - uint8_t (*read_data)(void *priv); + void (*autofeed)(uint8_t val,void *priv); + void (*strobe)(uint8_t old, uint8_t val,void *priv); uint8_t (*read_status)(void *priv); uint8_t (*read_ctrl)(void *priv); + void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv); + void (*epp_request_read)(uint8_t is_addr, void *priv); } lpt_device_t; +extern void lpt_set_ext(int port, uint8_t ext); +extern void lpt_set_ecp(int port, uint8_t ecp); +extern void lpt_set_epp(int port, uint8_t epp); +extern void lpt_set_lv2(int port, uint8_t lv2); +extern void lpt_reset(void); +extern void lpt_close(void); extern void lpt_init(void); extern void lpt_port_setup(int i, uint16_t port); extern void lpt_port_irq(int i, uint8_t irq); +extern void lpt_port_dma(int i, uint8_t dma); extern void lpt_port_remove(int i); extern void lpt1_remove_ams(void); @@ -68,31 +78,62 @@ void lpt_devices_close(void); typedef struct lpt_port_t { uint8_t enabled; uint8_t irq; + uint8_t irq_state; + uint8_t dma; uint8_t dat; uint8_t ctrl; + uint8_t ext; + uint8_t epp; + uint8_t ecp; + uint8_t ecr; + uint8_t in_dat; + uint8_t fifo_stat; + uint8_t dma_stat; + uint8_t state; + uint8_t autofeed; + uint8_t strobe; + uint8_t lv2; + uint8_t pad[7]; uint16_t addr; - uint16_t pad0; + uint16_t id; + uint16_t pad0[2]; int device; int enable_irq; lpt_device_t *dt; +#ifdef FIFO_H + fifo16_t *fifo; +#else + void *fifo; +#endif void *priv; + + pc_timer_t fifo_out_timer; } lpt_port_t; +typedef enum { + LPT_STATE_IDLE = 0, + LPT_STATE_READ_DMA, + LPT_STATE_WRITE_FIFO +} lpt_state_t; + extern lpt_port_t lpt_ports[PARALLEL_MAX]; -extern void lpt_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t lpt_read(uint16_t port, void *priv); +extern void lpt_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t lpt_read_port(int port, uint16_t reg); +extern void lpt_write_to_fifo(void *priv, uint8_t val); -extern uint8_t lpt_read_status(int port); -extern void lpt_irq(void *priv, int raise); +extern uint8_t lpt_read(uint16_t port, void *priv); + +extern uint8_t lpt_read_port(int port, uint16_t reg); + +extern uint8_t lpt_read_status(int port); +extern void lpt_irq(void *priv, int raise); + +extern int lpt_device_get_from_internal_name(const char *s); extern const char *lpt_device_get_name(int id); extern const char *lpt_device_get_internal_name(int id); -extern int lpt_device_get_from_internal_name(char *s); - extern const lpt_device_t lpt_dac_device; extern const lpt_device_t lpt_dac_stereo_device; diff --git a/src/lpt.c b/src/lpt.c deleted file mode 100644 index 072f4a34c..000000000 --- a/src/lpt.c +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <wchar.h> -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/lpt.h> -#include <86box/pic.h> -#include <86box/sound.h> -#include <86box/prt_devs.h> -#include <86box/thread.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/network.h> - -lpt_port_t lpt_ports[PARALLEL_MAX]; - -const lpt_device_t lpt_none_device = { - .name = "None", - .internal_name = "none", - .init = NULL, - .close = NULL, - .write_data = NULL, - .write_ctrl = NULL, - .read_data = NULL, - .read_status = NULL, - .read_ctrl = NULL -}; - -static const struct { - const char *internal_name; - const lpt_device_t *device; -} lpt_devices[] = { - // clang-format off - {"none", &lpt_none_device }, - {"dss", &dss_device }, - {"lpt_dac", &lpt_dac_device }, - {"lpt_dac_stereo", &lpt_dac_stereo_device }, - {"text_prt", &lpt_prt_text_device }, - {"dot_matrix", &lpt_prt_escp_device }, - {"postscript", &lpt_prt_ps_device }, -#ifdef USE_PCL - {"pcl", &lpt_prt_pcl_device }, -#endif - {"plip", &lpt_plip_device }, - {"dongle_savquest", &lpt_hasp_savquest_device }, - {"", NULL } - // clang-format on -}; - -const char * -lpt_device_get_name(int id) -{ - if (strlen(lpt_devices[id].internal_name) == 0) - return NULL; - if (!lpt_devices[id].device) - return "None"; - return lpt_devices[id].device->name; -} - -const char * -lpt_device_get_internal_name(int id) -{ - if (strlen(lpt_devices[id].internal_name) == 0) - return NULL; - return lpt_devices[id].internal_name; -} - -int -lpt_device_get_from_internal_name(char *s) -{ - int c = 0; - - while (strlen(lpt_devices[c].internal_name) != 0) { - if (strcmp(lpt_devices[c].internal_name, s) == 0) - return c; - c++; - } - - return 0; -} - -void -lpt_devices_init(void) -{ - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; - - if (lpt_ports[i].dt && lpt_ports[i].dt->init) - lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); - } -} - -void -lpt_devices_close(void) -{ - lpt_port_t *dev; - - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - dev = &lpt_ports[i]; - - if (lpt_ports[i].dt && lpt_ports[i].dt->close) - dev->dt->close(dev->priv); - - dev->dt = NULL; - } -} - -void -lpt_write(uint16_t port, uint8_t val, void *priv) -{ - lpt_port_t *dev = (lpt_port_t *) priv; - - switch (port & 3) { - case 0: - if (dev->dt && dev->dt->write_data && dev->priv) - dev->dt->write_data(val, dev->priv); - dev->dat = val; - break; - - case 1: - break; - - case 2: - if (dev->dt && dev->dt->write_ctrl && dev->priv) - dev->dt->write_ctrl(val, dev->priv); - dev->ctrl = val; - dev->enable_irq = val & 0x10; - break; - - default: - break; - } -} - -uint8_t -lpt_read(uint16_t port, void *priv) -{ - uint8_t ret = 0xff; - lpt_port_t *dev = (lpt_port_t *) priv; - - switch (port & 3) { - case 0: - if (dev->dt && dev->dt->read_data && dev->priv) - ret = dev->dt->read_data(dev->priv); - else - ret = dev->dat; - break; - - case 1: - if (dev->dt && dev->dt->read_status && dev->priv) - ret = dev->dt->read_status(dev->priv) | 0x07; - else - ret = 0xdf; - break; - - case 2: - if (dev->dt && dev->dt->read_ctrl && dev->priv) - ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; - else - ret = 0xe0 | dev->ctrl | dev->enable_irq; - break; - - default: - break; - } - - return ret; -} - -uint8_t -lpt_read_port(int port, uint16_t reg) -{ - lpt_port_t *dev = &(lpt_ports[port]); - uint8_t ret = lpt_read(reg, dev); - - return ret; -} - -uint8_t -lpt_read_status(int port) -{ - lpt_port_t *dev = &(lpt_ports[port]); - uint8_t ret = 0xff; - - if (dev->dt && dev->dt->read_status && dev->priv) - ret = dev->dt->read_status(dev->priv) | 0x07; - else - ret = 0xdf; - - return ret; -} - -void -lpt_irq(void *priv, int raise) -{ - const lpt_port_t *dev = (lpt_port_t *) priv; - - if (dev->enable_irq && (dev->irq != 0xff)) { - if (raise) - picint(1 << dev->irq); - else - picintc(1 << dev->irq); - } -} - -void -lpt_init(void) -{ - uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR }; - uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ }; - - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].addr = 0xffff; - lpt_ports[i].irq = 0xff; - lpt_ports[i].enable_irq = 0x10; - - if (lpt_ports[i].enabled) { - lpt_port_setup(i, default_ports[i]); - lpt_port_irq(i, default_irqs[i]); - } - } -} - -void -lpt_port_setup(int i, uint16_t port) -{ - if (lpt_ports[i].enabled) { - if ((lpt_ports[i].addr != 0xffff) && (lpt_ports[i].addr != 0x0000)) - io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - if ((port != 0xffff) && (port != 0x0000)) - io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - lpt_ports[i].addr = port; - } else - lpt_ports[i].addr = 0xffff; -} - -void -lpt_port_irq(int i, uint8_t irq) -{ - if (lpt_ports[i].enabled) - lpt_ports[i].irq = irq; - else - lpt_ports[i].irq = 0xff; -} - -void -lpt_port_remove(int i) -{ - if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) { - io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - lpt_ports[i].addr = 0xffff; - } -} - -void -lpt1_remove_ams(void) -{ - if (lpt_ports[0].enabled) - io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]); -} diff --git a/src/network/net_plip.c b/src/network/net_plip.c index 8c46213c6..ac8ab2850 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -488,15 +488,18 @@ plip_close(void *priv) } const lpt_device_t lpt_plip_device = { - .name = "Parallel Line Internet Protocol", - .internal_name = "plip", - .init = plip_lpt_init, - .close = plip_close, - .write_data = plip_write_data, - .write_ctrl = plip_write_ctrl, - .read_data = NULL, - .read_status = plip_read_status, - .read_ctrl = NULL + .name = "Parallel Line Internet Protocol", + .internal_name = "plip", + .init = plip_lpt_init, + .close = plip_close, + .write_data = plip_write_data, + .write_ctrl = plip_write_ctrl, + .autofeed = NULL, + .strobe = NULL, + .read_status = plip_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; const device_t plip_device = { diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index f238341c5..41c81e696 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1881,6 +1881,39 @@ write_data(uint8_t val, void *priv) dev->data = val; } +static void +autofeed(uint8_t val, void *priv) +{ + escp_t *dev = (escp_t *) priv; + + if (dev == NULL) + return; + + dev->autofeed = ((val & 0x02) > 0); +} + +static void +strobe(uint8_t old, uint8_t val, void *priv) +{ + escp_t *dev = (escp_t *) priv; + + if (dev == NULL) + return; + + /* Data is strobed to the parallel printer on the falling edge of the + strobe bit. */ + if (!(val & 0x01) && (old & 0x01)) { + /* Process incoming character. */ + handle_char(dev, dev->data); + + /* ACK it, will be read on next READ STATUS. */ + dev->ack = 1; + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + } +} + static void write_ctrl(uint8_t val, void *priv) { @@ -1919,14 +1952,6 @@ write_ctrl(uint8_t val, void *priv) dev->autofeed = ((val & 0x02) > 0); } -static uint8_t -read_data(void *priv) -{ - const escp_t *dev = (escp_t *) priv; - - return dev->data; -} - static uint8_t read_ctrl(void *priv) { @@ -2058,13 +2083,16 @@ escp_close(void *priv) } const lpt_device_t lpt_prt_escp_device = { - .name = "Generic ESC/P Dot-Matrix Printer", - .internal_name = "dot_matrix", - .init = escp_init, - .close = escp_close, - .write_data = write_data, - .write_ctrl = write_ctrl, - .read_data = read_data, - .read_status = read_status, - .read_ctrl = read_ctrl + .name = "Generic ESC/P Dot-Matrix", + .internal_name = "dot_matrix", + .init = escp_init, + .close = escp_close, + .write_data = write_data, + .write_ctrl = write_ctrl, + .autofeed = autofeed, + .strobe = strobe, + .read_status = read_status, + .read_ctrl = read_ctrl, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 1298018ee..904ff34ad 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -319,6 +319,35 @@ process_data(ps_t *dev) dev->buffer[dev->buffer_pos] = 0; } +static void +ps_autofeed(uint8_t val, void *priv) +{ + ps_t *dev = (ps_t *) priv; + + if (dev == NULL) + return; + + dev->autofeed = val & 0x02 ? true : false; +} + +static void +ps_strobe(uint8_t old, uint8_t val, void *priv) +{ + ps_t *dev = (ps_t *) priv; + + if (dev == NULL) + return; + + if (!(val & 0x01) && (old & 0x01)) { + process_data(dev); + + dev->ack = true; + + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + } +} + static void ps_write_ctrl(uint8_t val, void *priv) { @@ -479,27 +508,33 @@ ps_close(void *priv) } const lpt_device_t lpt_prt_ps_device = { - .name = "Generic PostScript Printer", - .internal_name = "postscript", - .init = ps_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .read_data = NULL, - .read_status = ps_read_status, - .read_ctrl = NULL + .name = "Generic PostScript Printer", + .internal_name = "postscript", + .init = ps_init, + .close = ps_close, + .write_data = ps_write_data, + .write_ctrl = ps_write_ctrl, + .autofeed = ps_autofeed, + .strobe = ps_strobe, + .read_status = ps_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; #ifdef USE_PCL const lpt_device_t lpt_prt_pcl_device = { - .name = "Generic PCL5e Printer", - .internal_name = "pcl", - .init = pcl_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .read_data = NULL, - .read_status = ps_read_status, - .read_ctrl = NULL + .name = "Generic PCL5e Printer", + .internal_name = "pcl", + .init = pcl_init, + .close = ps_close, + .write_data = ps_write_data, + .write_ctrl = ps_write_ctrl, + .autofeed = ps_autofeed, + .strobe = ps_strobe, + .read_status = ps_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; #endif diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index e04ef9680..7604d023e 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -367,6 +367,38 @@ write_data(uint8_t val, void *priv) dev->data = val; } +static void +autofeed(uint8_t val, void *priv) +{ + prnt_t *dev = (prnt_t *) priv; + + if (dev == NULL) + return; + + /* set autofeed value */ + dev->autofeed = val & 0x02 ? 1 : 0; +} + +static void +strobe(uint8_t old, uint8_t val, void *priv) +{ + prnt_t *dev = (prnt_t *) priv; + + if (dev == NULL) + return; + + if (!(val & 0x01) && (old & 0x01)) { /* STROBE */ + /* Process incoming character. */ + handle_char(dev); + + /* ACK it, will be read on next READ STATUS. */ + dev->ack = 1; + + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + } +} + static void write_ctrl(uint8_t val, void *priv) { @@ -465,13 +497,16 @@ prnt_close(void *priv) } const lpt_device_t lpt_prt_text_device = { - .name = "Generic Text Printer", - .internal_name = "text_prt", - .init = prnt_init, - .close = prnt_close, - .write_data = write_data, - .write_ctrl = write_ctrl, - .read_data = NULL, - .read_status = read_status, - .read_ctrl = NULL + .name = "Generic Text Printer", + .internal_name = "text_prt", + .init = prnt_init, + .close = prnt_close, + .write_data = write_data, + .write_ctrl = write_ctrl, + .autofeed = autofeed, + .strobe = strobe, + .read_status = read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c index 398d00839..436e425d2 100644 --- a/src/sio/sio_ali5123.c +++ b/src/sio/sio_ali5123.c @@ -85,11 +85,18 @@ ali5123_lpt_handler(ali5123_t *dev) uint8_t global_enable = !(dev->regs[0x22] & (1 << 3)); uint8_t local_enable = !!dev->ld_regs[3][0x30]; uint8_t lpt_irq = dev->ld_regs[3][0x70]; + uint8_t lpt_dma = dev->ld_regs[3][0x74]; if (lpt_irq > 15) lpt_irq = 0xff; + if (lpt_dma == 4) + lpt_dma = 0xff; + lpt1_remove(); + lpt_set_epp(0, !!(dev->ld_regs[3][0xf0] & 0x01)); + lpt_set_ecp(0, !!(dev->ld_regs[3][0xf0] & 0x02)); + lpt_set_ext(0, !(dev->ld_regs[3][0xf0] & 0x04) || !!(dev->ld_regs[3][0xf1] & 0x80)); if (global_enable && local_enable) { ld_port = make_port(dev, 3) & 0xFFFC; if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) @@ -247,7 +254,7 @@ ali5123_write(uint16_t port, uint8_t val, void *priv) dev->regs[dev->cur_reg] = val; } else { valxor = val ^ dev->ld_regs[cur_ld][dev->cur_reg]; - if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4)) + if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4) && (cur_ld != 3)) return; /* Block writes to some logical devices. */ if (cur_ld > 0x0c) @@ -357,6 +364,9 @@ ali5123_write(uint16_t port, uint8_t val, void *priv) case 0x60: case 0x61: case 0x70: + case 0x74: + case 0xf0: + case 0xf1: if ((dev->cur_reg == 0x30) && (val & 0x01)) dev->regs[0x22] &= ~0x08; if (valxor) diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index 41d69b0cc..e42c48ab4 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -121,6 +121,10 @@ lpt1_handler(pc87306_t *dev) uint16_t lptba; uint16_t lpt_port = LPT1_ADDR; uint8_t lpt_irq = LPT2_IRQ; + uint8_t lpt_dma = ((dev->regs[0x18] & 0x06) >> 1); + + if (lpt_dma == 0x00) + lpt_dma = 0xff; temp = dev->regs[0x01] & 3; lptba = ((uint16_t) dev->regs[0x19]) << 2; @@ -157,6 +161,13 @@ lpt1_handler(pc87306_t *dev) lpt1_setup(lpt_port); lpt1_irq(lpt_irq); + + lpt_port_dma(0, lpt_dma); + + lpt_set_ext(0, !!(dev->regs[0x02] & 0x80)); + + lpt_set_epp(0, !!(dev->regs[0x04] & 0x01)); + lpt_set_ecp(0, !!(dev->regs[0x04] & 0x04)); } static void @@ -169,7 +180,7 @@ serial_handler(pc87306_t *dev, int uart) uint8_t pnp_shift; uint8_t irq; - temp = (dev->regs[1] >> (2 << uart)) & 3; + temp = (dev->regs[0x01] >> (2 << uart)) & 3; fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */ pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */ @@ -188,7 +199,7 @@ serial_handler(pc87306_t *dev, int uart) serial_setup(dev->uart[uart], COM2_ADDR, irq); break; case 2: - switch ((dev->regs[1] >> 6) & 3) { + switch ((dev->regs[0x01] >> 6) & 3) { case 0: serial_setup(dev->uart[uart], COM3_ADDR, irq); break; @@ -207,7 +218,7 @@ serial_handler(pc87306_t *dev, int uart) } break; case 3: - switch ((dev->regs[1] >> 6) & 3) { + switch ((dev->regs[0x01] >> 6) & 3) { case 0: serial_setup(dev->uart[uart], COM4_ADDR, irq); break; @@ -264,41 +275,41 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0x00: - if (valxor & 1) { + if (valxor & 0x01) { lpt1_remove(); - if ((val & 1) && !(dev->regs[2] & 1)) + if ((val & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } - if (valxor & 2) { - serial_remove(dev->uart[0]); - if ((val & 2) && !(dev->regs[2] & 1)) + if (valxor & 0x02) { + serial_remove(dev->uart[0x00]); + if ((val & 2) && !(dev->regs[0x02] & 1)) serial_handler(dev, 0); } - if (valxor & 4) { - serial_remove(dev->uart[1]); - if ((val & 4) && !(dev->regs[2] & 1)) + if (valxor & 0x04) { + serial_remove(dev->uart[0x01]); + if ((val & 4) && !(dev->regs[0x02] & 1)) serial_handler(dev, 1); } if (valxor & 0x28) { fdc_remove(dev->fdc); - if ((val & 8) && !(dev->regs[2] & 1)) + if ((val & 8) && !(dev->regs[0x02] & 1)) fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } break; case 0x01: - if (valxor & 3) { + if (valxor & 0x03) { lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } if (valxor & 0xcc) { - serial_remove(dev->uart[0]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + serial_remove(dev->uart[0x00]); + if ((dev->regs[0x00] & 2) && !(dev->regs[0x02] & 1)) serial_handler(dev, 0); } if (valxor & 0xf0) { - serial_remove(dev->uart[1]); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + serial_remove(dev->uart[0x01]); + if ((dev->regs[0x00] & 4) && !(dev->regs[0x02] & 1)) serial_handler(dev, 1); } break; @@ -327,6 +338,11 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) } break; case 0x04: + if (valxor & (0x05)) { + lpt1_remove(); + if ((dev->regs[0x00] & 0x01) && !(dev->regs[0x02] & 0x01)) + lpt1_handler(dev); + } if (valxor & 0x80) nvr_lock_set(0x00, 256, !!(val & 0x80), dev->nvr); break; @@ -352,10 +368,17 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) if (valxor & 0x30) pc87306_gpio_handler(dev); break; + case 0x18: + if (valxor & (0x06)) { + lpt1_remove(); + if ((dev->regs[0x00] & 0x01) && !(dev->regs[0x02] & 0x01)) + lpt1_handler(dev); + } + break; case 0x19: if (valxor) { lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } break; @@ -364,18 +387,18 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) lpt1_remove(); if (!(val & 0x40)) dev->regs[0x19] = 0xEF; - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } break; case 0x1c: if (valxor) { - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + serial_remove(dev->uart[0x00]); + serial_remove(dev->uart[0x01]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 2) && !(dev->regs[0x02] & 1)) serial_handler(dev, 0); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 4) && !(dev->regs[0x02] & 1)) serial_handler(dev, 1); } break; @@ -432,8 +455,8 @@ pc87306_reset_common(void *priv) */ lpt1_remove(); lpt1_handler(dev); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + serial_remove(dev->uart[0x00]); + serial_remove(dev->uart[0x01]); serial_handler(dev, 0); serial_handler(dev, 1); fdc_reset(dev->fdc); @@ -471,8 +494,8 @@ pc87306_init(UNUSED(const device_t *info)) dev->fdc = device_add(&fdc_at_nsc_device); - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[0x00] = device_add_inst(&ns16550_device, 1); + dev->uart[0x01] = device_add_inst(&ns16550_device, 2); dev->nvr = device_add(&at_mb_nvr_device); diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index 0462818a0..13a430c91 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -50,6 +50,14 @@ dac_write_data(uint8_t val, void *priv) dac_update(lpt_dac); } +static void +dac_strobe(uint8_t old, uint8_t val, void *priv) +{ + lpt_dac_t *lpt_dac = (lpt_dac_t *) priv; + + lpt_dac->channel = val; +} + static void dac_write_ctrl(uint8_t val, void *priv) { @@ -109,25 +117,31 @@ dac_close(void *priv) } const lpt_device_t lpt_dac_device = { - .name = "LPT DAC / Covox Speech Thing", - .internal_name = "lpt_dac", - .init = dac_init, - .close = dac_close, - .write_data = dac_write_data, - .write_ctrl = dac_write_ctrl, - .read_data = NULL, - .read_status = dac_read_status, - .read_ctrl = NULL + .name = "LPT DAC / Covox Speech Thing", + .internal_name = "lpt_dac", + .init = dac_init, + .close = dac_close, + .write_data = dac_write_data, + .write_ctrl = dac_write_ctrl, + .autofeed = NULL, + .strobe = dac_strobe, + .read_status = dac_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; const lpt_device_t lpt_dac_stereo_device = { - .name = "Stereo LPT DAC", - .internal_name = "lpt_dac_stereo", - .init = dac_stereo_init, - .close = dac_close, - .write_data = dac_write_data, - .write_ctrl = dac_write_ctrl, - .read_data = NULL, - .read_status = dac_read_status, - .read_ctrl = NULL + .name = "Stereo LPT DAC", + .internal_name = "lpt_dac_stereo", + .init = dac_stereo_init, + .close = dac_close, + .write_data = dac_write_data, + .write_ctrl = dac_write_ctrl, + .autofeed = NULL, + .strobe = dac_strobe, + .read_status = dac_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 875230518..b609e3add 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -133,13 +133,16 @@ dss_close(void *priv) } const lpt_device_t dss_device = { - .name = "Disney Sound Source", - .internal_name = "dss", - .init = dss_init, - .close = dss_close, - .write_data = dss_write_data, - .write_ctrl = dss_write_ctrl, - .read_data = NULL, - .read_status = dss_read_status, - .read_ctrl = NULL + .name = "Disney Sound Source", + .internal_name = "dss", + .init = dss_init, + .close = dss_close, + .write_data = dss_write_data, + .autofeed = NULL, + .strobe = NULL, + .write_ctrl = dss_write_ctrl, + .read_status = dss_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; From 33cee0cc46a504b561f93bbf6716715417b46242 Mon Sep 17 00:00:00 2001 From: "Joakim L. Gilje" <jgilje@jgilje.net> Date: Tue, 24 Jun 2025 18:46:45 +0200 Subject: [PATCH 1170/1190] fix for conflicting types of Display --- src/qt/qt_vmmanager_details.cpp | 2 ++ src/qt/qt_vmmanager_detailsection.cpp | 1 + src/qt/qt_vmmanager_detailsection.hpp | 2 +- src/qt/qt_vmmanager_system.cpp | 2 ++ src/qt/qt_vmmanager_system.hpp | 7 +++++-- 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index 23fe5377e..a834e35f8 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -26,6 +26,8 @@ extern bool windows_is_light_theme(); #endif +using namespace VMManager; + VMManagerDetails::VMManagerDetails(QWidget *parent) : QWidget(parent), ui(new Ui::VMManagerDetails) { ui->setupUi(this); diff --git a/src/qt/qt_vmmanager_detailsection.cpp b/src/qt/qt_vmmanager_detailsection.cpp index bd080e00c..ce42ae281 100644 --- a/src/qt/qt_vmmanager_detailsection.cpp +++ b/src/qt/qt_vmmanager_detailsection.cpp @@ -21,6 +21,7 @@ #include <QPushButton> const QString VMManagerDetailSection::sectionSeparator = ";"; +using namespace VMManager; VMManagerDetailSection:: VMManagerDetailSection(const QString &sectionName) diff --git a/src/qt/qt_vmmanager_detailsection.hpp b/src/qt/qt_vmmanager_detailsection.hpp index 2eb63685a..7619a476c 100644 --- a/src/qt/qt_vmmanager_detailsection.hpp +++ b/src/qt/qt_vmmanager_detailsection.hpp @@ -60,7 +60,7 @@ public: ~VMManagerDetailSection() override; - void addSection(const QString &name, const QString &value, Display::Name displayField = Display::Name::Unknown); + void addSection(const QString &name, const QString &value, VMManager::Display::Name displayField = VMManager::Display::Name::Unknown); void clear(); CollapseButton *collapseButton; diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 08853feab..7ab7e43ca 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -51,6 +51,8 @@ extern "C" { #include <86box/mouse.h> } +using namespace VMManager; + VMManagerSystem::VMManagerSystem(const QString &sysconfig_file) { // The 86Box configuration file diff --git a/src/qt/qt_vmmanager_system.hpp b/src/qt/qt_vmmanager_system.hpp index ab2069617..6ac0a7635 100644 --- a/src/qt/qt_vmmanager_system.hpp +++ b/src/qt/qt_vmmanager_system.hpp @@ -34,6 +34,8 @@ inline uint qHash(const T &t, uint seed) { \ return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \ } +namespace VMManager { +Q_NAMESPACE namespace Display { Q_NAMESPACE enum class Name { @@ -58,11 +60,12 @@ enum class Name { Q_ENUM_NS(Name) QHASH_FOR_CLASS_ENUM(Name) } +} class VMManagerSystem : public QWidget { Q_OBJECT - typedef QHash<Display::Name, QString> display_table_t; + typedef QHash<VMManager::Display::Name, QString> display_table_t; typedef QHash <QString, QHash <QString, QString>> config_hash_t; public: @@ -127,7 +130,7 @@ public: bool window_obscured; - QString getDisplayValue(Display::Name key); + QString getDisplayValue(VMManager::Display::Name key); QFileInfoList getScreenshots(); inline bool operator==(const VMManagerSystem &rhs) const From 9040aa1b7084a24e75b63018812f88ae60dc3162 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek <jasmine@iwanek.co.uk> Date: Tue, 24 Jun 2025 14:34:39 -0400 Subject: [PATCH 1171/1190] Missed bit in lpt.c --- src/device/lpt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/device/lpt.c b/src/device/lpt.c index 179dc9a2d..11afc04f9 100644 --- a/src/device/lpt.c +++ b/src/device/lpt.c @@ -46,7 +46,9 @@ static const struct { {"text_prt", &lpt_prt_text_device }, {"dot_matrix", &lpt_prt_escp_device }, {"postscript", &lpt_prt_ps_device }, +#ifdef USE_PCL {"pcl", &lpt_prt_pcl_device }, +#endif {"plip", &lpt_plip_device }, {"dongle_savquest", &lpt_hasp_savquest_device }, {"", NULL } From de1a3da5a7fe7f8beed0b1808419ae97caf5629c Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Tue, 24 Jun 2025 23:30:45 +0200 Subject: [PATCH 1172/1190] Add Alaris Cobalt LPX machine code. --- src/machine/m_at_386dx_486.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0c0582c3c..333bcfd92 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2869,6 +2869,35 @@ machine_at_ga486l_init(const machine_t *model) return ret; } +int +machine_at_cobalt_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/cobalt/Cobalt_2.3.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti499_device); + device_add(&ide_opti611_vlb_device); + device_add(&ide_isa_sec_device); + device_add(&fdc37c665_device); + + device_add(&keyboard_ps2_ami_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_cougar_init(const machine_t *model) { From 066e7cc5eea6dbf9bb7fc58623b562b7a0759978 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Tue, 24 Jun 2025 23:31:23 +0200 Subject: [PATCH 1173/1190] Add Alaris Cobalt LPX machine table entry. --- src/machine/machine_table.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3f324f4d6..2b7da7494 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7179,6 +7179,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[OPTi 499] Alaris Cobalt LPX", + .internal_name = "cobalt", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_OPTI_499, + .init = machine_at_cobalt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3 | CPU_PKG_486BL, + .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_VLB, + .flags = MACHINE_APM | MACHINE_VIDEO | MACHINE_IDE_DUAL, + .ram = { + .min = 1024, + .max = 65536, + .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 = &gd5428_vlb_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey-2 'H' KBC firmware. */ { .name = "[OPTi 499] Alaris COUGAR 486BL", From ca1390f3bb25e4bf67671fbc2efa98beaac4ca07 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Tue, 24 Jun 2025 23:32:05 +0200 Subject: [PATCH 1174/1190] Add Alaris Cobalt LPX machine definition. --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 90b596ae8..39fb1a933 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -517,6 +517,7 @@ extern int machine_at_dataexpert386wb_init(const machine_t *); extern int machine_at_isa486c_init(const machine_t *); extern int machine_at_genoa486_init(const machine_t *); extern int machine_at_ga486l_init(const machine_t *); +extern int machine_at_cobalt_init(const machine_t *); extern int machine_at_cougar_init(const machine_t *); extern int machine_at_acc386_init(const machine_t *); From 6e695512f7a21a90464d9921326320e10c419abc Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Tue, 24 Jun 2025 23:49:29 +0200 Subject: [PATCH 1175/1190] Block usage of Pentium OverDrive on the Alaris Cobalt LPX. It won't post with it. --- 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 2b7da7494..e779eb753 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7191,7 +7191,7 @@ const machine_t machines[] = { .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET3 | CPU_PKG_486BL, - .block = CPU_BLOCK_NONE, + .block = CPU_BLOCK(CPU_P24T), .min_bus = 0, .max_bus = 0, .min_voltage = 0, From 2e4eed0ac02c836104fe9fba50fa539b4e6ed538 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 04:45:40 +0200 Subject: [PATCH 1176/1190] Assorted ACC 2036 and OAK OTi-037 fixes, fixes #5697. --- src/chipset/acc2036.c | 2 +- src/device/kbc_at.c | 4 +--- src/video/vid_oak_oti.c | 16 +++++++++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/chipset/acc2036.c b/src/chipset/acc2036.c index 225c22813..3984f82e0 100644 --- a/src/chipset/acc2036.c +++ b/src/chipset/acc2036.c @@ -158,7 +158,7 @@ acc2036_recalc(acc2036_t *dev) /* 0E0000-0FFFFF */ master_write = dev->regs[0x02] & 0x02; master_read = dev->regs[0x02] & 0x01; - bit = (((i - 8) >> 2) + 2); + bit = ((i - 8) >> 2); val = dev->regs[0x0c] & (1 << bit); if (i >= 20) { ew_flag = MEM_WRITE_EXTANY; diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 1338b9555..d19b08f84 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1817,8 +1817,6 @@ read_p1(atkbc_t *dev) Compaq: Reserved; NCR: DMA mode. */ - kbc_at_log("ATkbc: read P1\n"); - fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -2108,7 +2106,7 @@ kbc_at_process_cmd(void *priv) break; case 0xc0: /* read P1 */ - kbc_at_log("ATkbc: read P2\n"); + kbc_at_log("ATkbc: read P1\n"); kbc_delay_to_ob(dev, read_p1(dev), 0, 0x00); break; diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 3233f9d00..3ea935b06 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -55,6 +55,7 @@ typedef struct { rom_t bios_rom; int index; + int en_map; uint8_t regs[32]; uint8_t chip_id; @@ -88,6 +89,12 @@ oti_out(uint16_t addr, uint8_t val, void *priv) case 0x3c3: if (!oti->chip_id) { oti->enable_register = val & 1; + if ((val & 0x01) && oti->en_map) + mem_mapping_enable(&svga->mapping); + else if (!(val & 0x01)) { + oti->en_map = svga->mapping.enable; + mem_mapping_disable(&svga->mapping); + } return; } svga_out(addr, val, svga); @@ -245,11 +252,14 @@ oti_in(uint16_t addr, void *priv) case 0x3c8: case 0x3c9: if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); + temp = sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + else + temp = svga_in(addr, svga); + break; case 0x3CF: - return svga->gdcreg[svga->gdcaddr & 0xf]; + temp = svga->gdcreg[svga->gdcaddr & 0xf]; + break; case 0x3d4: temp = svga->crtcreg; From cbdfa32e6513872f8e2b1de8aa3ac54f19390c1a Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 05:42:50 +0200 Subject: [PATCH 1177/1190] Reset the FIFO and update its lengths on test mode set/reset, fixes #5702. --- src/floppy/fdc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 186d4c894..523ae6948 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -191,7 +191,7 @@ fdc_ctrl_reset(void *priv) fdc->step = 0; fdc->power_down = 0; - if (!fdc->lock) { + if (!fdc->lock && !fdc->fifointest) { fdc->fifo = 0; fdc->tfifo = 1; @@ -808,6 +808,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->tfifo = 1; fdc->fifointest = 0; } + fifo_reset(fdc->fifo_p); + fifo_set_len(fdc->fifo_p, fdc->tfifo + 1); + fifo_set_trigger_len(fdc->fifo_p, fdc->tfifo + 1); } return; case 4: /* DSR */ From 6d7ab90fd3caff47545c339a3f67098d15adcced Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 05:56:55 +0200 Subject: [PATCH 1178/1190] Alaris Cobalt machine fixes. --- src/machine/m_at_386dx_486.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 333bcfd92..09efd51bf 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -2880,21 +2880,18 @@ machine_at_cobalt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init(model); device_add(&opti499_device); - device_add(&ide_opti611_vlb_device); - device_add(&ide_isa_sec_device); - device_add(&fdc37c665_device); + device_add(&ide_opti611_vlb_device); + device_add(&ide_isa_sec_device); + device_add(&fdc37c665_device); device_add(&keyboard_ps2_ami_device); - if (gfxcard[0] == VID_INTERNAL) + if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); - if (fdc_current[0] == FDC_INTERNAL) - device_add(&fdc_at_device); - return ret; } From 609a7e45498009de791772e969dc95f2d7e683e1 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 19:31:14 +0200 Subject: [PATCH 1179/1190] Only enable the change introduced in build 6807 for VLB Mach64GX, fixes #5701. --- src/video/vid_ati_mach64.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 74086dab1..8e6b52517 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -94,6 +94,7 @@ typedef struct mach64_t { int type; int pci; + int vlb; uint8_t pci_slot; uint8_t irq_state; @@ -3857,7 +3858,7 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x6aee: case 0x6aef: WRITE8(port, mach64->config_cntl, val); - if (!mach64->pci) + if (mach64->vlb) mach64->linear_base = (mach64->config_cntl & 0x3ff0) << 18; mach64_updatemapping(mach64); @@ -4764,6 +4765,7 @@ mach64gx_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); mach64->pci = !!(info->flags & DEVICE_PCI); + mach64->vlb = !!(info->flags & DEVICE_VLB); mach64->pci_id = 'X' | ('G' << 8); mach64->config_chip_id = 0x000000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ From 495ee9b9318cf13058f7ebf66ec78f492264ef82 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 19:35:59 +0200 Subject: [PATCH 1180/1190] MMU: Move the lookup tables to the heap in 64-bit builds and free them on exit in 32-bit builds, prevents memory leaks. --- src/86box.c | 4 ++++ src/include/86box/mem.h | 16 ++++++++++++++++ src/mem/mem.c | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/86box.c b/src/86box.c index 8c07daa15..1c11d9bee 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1656,6 +1656,10 @@ pc_close(UNUSED(thread_t *ptr)) scsi_disk_close(); gdbstub_close(); + +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + mem_free(); +#endif } #ifdef __APPLE__ diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 62cb493a5..53001b8db 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -265,12 +265,16 @@ extern uint32_t biosmask; extern uint32_t biosaddr; extern int readlookup[256]; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) extern uintptr_t *readlookup2; +#endif extern uintptr_t old_rl2; extern uint8_t uncached; extern int readlnext; extern int writelookup[256]; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) extern uintptr_t *writelookup2; +#endif extern int writelnext; extern uint32_t ram_mapped_addr[64]; extern uint8_t page_ff[4096]; @@ -288,7 +292,16 @@ extern mem_mapping_t bios_high_mapping; extern uint32_t mem_logical_addr; extern page_t *pages; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) extern page_t **page_lookup; +#endif + +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) +/* The lookup tables. */ +extern page_t *page_lookup[1048576]; +extern uintptr_t readlookup2[1048576]; +extern uintptr_t writelookup2[1048576]; +#endif extern uint32_t get_phys_virt; extern uint32_t get_phys_phys; @@ -457,6 +470,9 @@ extern void mem_a20_init(void); extern void mem_a20_recalc(void); extern void mem_init(void); +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) +extern void mem_free(void); +#endif extern void mem_close(void); extern void mem_zero(void); extern void mem_reset(void); diff --git a/src/mem/mem.c b/src/mem/mem.c index d365ecffb..fa749002c 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -67,7 +67,9 @@ mem_mapping_t bios_mapping; mem_mapping_t bios_high_mapping; page_t *pages; /* RAM page table */ +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) page_t **page_lookup; /* pagetable lookup */ +#endif uint32_t pages_sz; /* #pages in table */ uint8_t *ram; /* the virtual RAM */ @@ -85,12 +87,23 @@ uint8_t *pccache2; int readlnext; int readlookup[256]; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) uintptr_t *readlookup2; +#endif uintptr_t old_rl2; uint8_t uncached = 0; int writelnext; int writelookup[256]; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) uintptr_t *writelookup2; +#endif + +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) +/* The lookup tables. */ +page_t *page_lookup[1048576] = { 0 }; +uintptr_t readlookup2[1048576] = { 0 }; +uintptr_t writelookup2[1048576] = { 0 }; +#endif uint32_t mem_logical_addr; @@ -2987,12 +3000,25 @@ mem_init(void) ram2 = NULL; pages = NULL; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) /* Allocate the lookup tables. */ page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *)); readlookup2 = malloc((1 << 20) * sizeof(uintptr_t)); writelookup2 = malloc((1 << 20) * sizeof(uintptr_t)); +#endif } +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) +void +mem_free(void) +{ + free(page_lookup); + free(readlookup2); + free(writelookup2); +} +#endif + + static void umc_page_recalc(uint32_t c, uint32_t phys, int set) { From a18c46e9190eea1b17329cb987934ef1c27f3c43 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 19:45:08 +0200 Subject: [PATCH 1181/1190] Sort the graphics cards table in the following order: ISA - ISA16 - MCA - VLB - PCI - AGP. --- src/video/vid_table.c | 122 ++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 33a7f30ca..b97defe8c 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -52,10 +52,10 @@ video_cards[] = { // clang-format off { .device = &device_none, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &device_internal, .flags = VIDEO_FLAG_TYPE_NONE }, + /* ISA */ { .device = &atiega800p_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &mach8_vga_isa_device, .flags = VIDEO_FLAG_TYPE_8514 }, { .device = &mach32_isa_device, .flags = VIDEO_FLAG_TYPE_8514 }, - { .device = &mach64gx_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &ati28800k_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &ati18800_vga88_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &ati28800_device, .flags = VIDEO_FLAG_TYPE_NONE }, @@ -71,15 +71,6 @@ video_cards[] = { { .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 }, - { .device = &gd5422_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5426_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5426_diamond_speedstar_pro_a1_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5428_boca_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5428_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5429_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5434_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5434_diamond_speedstar_64_a3_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &compaq_cga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &compaq_cga_2_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &cpqega_device, .flags = VIDEO_FLAG_TYPE_NONE }, @@ -88,7 +79,6 @@ video_cards[] = { { .device = &hercules_device, .flags = VIDEO_FLAG_TYPE_MDA }, { .device = &herculesplus_device, .flags = VIDEO_FLAG_TYPE_MDA }, { .device = &incolor_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &inmos_isa_device, .flags = VIDEO_FLAG_TYPE_XGA }, { .device = &im1024_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &iskra_ega_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000_kasan_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, @@ -106,16 +96,8 @@ video_cards[] = { { .device = &colorplus_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &pgc_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &cga_pravetz_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &radius_svga_multiview_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &realtek_rtg3105_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &realtek_rtg3106_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_diamond_stealth_vram_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_orchid_86c911_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_ami_86c924_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_metheus_86c928_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_phoenix_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_spea_mirage_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_winner1000_805_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &sigma_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &tvga8900b_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &tvga8900d_device, .flags = VIDEO_FLAG_TYPE_NONE }, @@ -127,16 +109,76 @@ video_cards[] = { { .device = &et3000_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000_tc6058af_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32i_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &vga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &v7_vga_1024i_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &wy700_device, .flags = VIDEO_FLAG_TYPE_NONE }, + /* ISA16 */ + { .device = &mach64gx_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5420_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5422_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5426_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5426_diamond_speedstar_pro_a1_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_boca_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5429_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_diamond_speedstar_64_a3_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &inmos_isa_device, .flags = VIDEO_FLAG_TYPE_XGA }, + { .device = &radius_svga_multiview_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_vram_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_orchid_86c911_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_ami_86c924_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_metheus_86c928_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mirage_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_winner1000_805_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32i_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, + /* MCA */ { .device = &mach32_mca_device, .flags = VIDEO_FLAG_TYPE_8514 }, { .device = &gd5426_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5428_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &radius_svga_multiview_mca_device, .flags = VIDEO_FLAG_TYPE_NONE }, + /* VLB */ + { .device = &mach32_vlb_device, .flags = VIDEO_FLAG_TYPE_8514 }, + { .device = &mach64gx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32i_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_videomagic_revb_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_revc_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_cardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &et4000w32p_noncardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5424_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5426_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5428_diamond_speedstar_pro_b1_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5429_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5430_diamond_speedstar_pro_se_a8_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5430_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &gd5434_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_metheus_86c928_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_8s_805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_10sd_805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_86c805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mirage_86c805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_964_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_20sv_964_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_mirocrystal_20sd_864_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_bahamas64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_vision864_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth_se_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio32_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_9fx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_phoenix_trio64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_spea_mirage_p64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_diamond_stealth64_968_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &s3_stb_powergraph_64_video_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ht216_32_standalone_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9400cxi_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &tgui9440_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + /* PCI */ { .device = &mach32_pci_device, .flags = VIDEO_FLAG_TYPE_8514 }, { .device = &mach64gx_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &mach64vt2_device, .flags = VIDEO_FLAG_TYPE_NONE }, @@ -200,43 +242,7 @@ video_cards[] = { { .device = &voodoo_3_1000_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &voodoo_3_2000_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &voodoo_3_3000_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &mach32_vlb_device, .flags = VIDEO_FLAG_TYPE_8514 }, - { .device = &mach64gx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32i_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32p_videomagic_revb_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32p_revc_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32p_cardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32p_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &et4000w32p_noncardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5424_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5426_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5428_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5428_diamond_speedstar_pro_b1_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5429_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5430_diamond_speedstar_pro_se_a8_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5430_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5434_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_metheus_86c928_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_mirocrystal_8s_805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_mirocrystal_10sd_805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_phoenix_86c805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_spea_mirage_86c805_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_diamond_stealth64_964_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_mirocrystal_20sv_964_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_mirocrystal_20sd_864_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_bahamas64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_phoenix_vision864_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_diamond_stealth_se_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_phoenix_trio32_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_diamond_stealth64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_9fx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_phoenix_trio64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_spea_mirage_p64_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_diamond_stealth64_968_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &s3_stb_powergraph_64_video_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &ht216_32_standalone_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &tgui9400cxi_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &tgui9440_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE }, + /* AGP */ { .device = &s3_virge_357_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &s3_diamond_stealth_4000_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &s3_trio3d2x_agp_device, .flags = VIDEO_FLAG_TYPE_NONE }, From 1916a60d6cff1f2a5badd5661e14e96c7a99669f Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 19:49:26 +0200 Subject: [PATCH 1182/1190] svga_render_overscan_right(): Fix the calculation for the right overscan, fixes #5699. --- src/video/vid_svga_render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index bdb496686..5cfcc8889 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -118,7 +118,7 @@ svga_render_overscan_right(svga_t *svga) return; uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp]; - right = (overscan_x >> 1); + right = overscan_x - svga->left_overscan; for (int i = 0; i < right; i++) *line_ptr++ = svga->overscan_color; } From cd6a3ee48f0e6654b4be23ebb0d0aabc683230ce Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Wed, 25 Jun 2025 20:24:30 +0200 Subject: [PATCH 1183/1190] Applied the same sorting to hard disk controllers, network adapters, SCSI controllers, and sound cards as well. --- src/disk/hdc.c | 31 ++++++++++++++++------------ src/network/network.c | 31 +++++++++++++++++----------- src/scsi/scsi.c | 28 +++++++++++++++---------- src/sound/sound.c | 48 ++++++++++++++++++++++++------------------- 4 files changed, 81 insertions(+), 57 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 582c33428..ecd609476 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -56,35 +56,40 @@ static const struct { // clang-format off { &device_none }, { &device_internal }, - { &st506_xt_xebec_device }, - { &st506_xt_wdxt_gen_device }, + /* ISA */ + { &xtide_acculogic_device }, { &st506_xt_dtc5150x_device }, + { &st506_xt_xebec_device }, + { &xtide_device }, { &st506_xt_st11_m_device }, - { &st506_xt_wd1002a_wx1_device }, - { &st506_xt_wd1004a_wx1_device }, - { &st506_at_wd1003_device }, { &st506_xt_st11_r_device }, + { &st506_xt_victor_v86p_device }, { &st506_xt_wd1002a_27x_device }, + { &st506_xt_wd1002a_wx1_device }, { &st506_xt_wd1004_27x_device }, { &st506_xt_wd1004a_27x_device }, - { &st506_xt_victor_v86p_device }, - { &esdi_at_wd1007vse1_device }, + { &st506_xt_wd1004a_wx1_device }, + { &xta_wdxt150_device }, + { &st506_xt_wdxt_gen_device }, + /* ISA16 */ { &ide_isa_device }, { &ide_isa_2ch_device }, { &xtide_at_device }, { &xtide_at_2ch_device }, { &xtide_at_ps2_device }, { &xtide_at_ps2_2ch_device }, - { &xta_wdxt150_device }, - { &xtide_acculogic_device }, - { &xtide_device }, + { &st506_at_wd1003_device }, + { &esdi_at_wd1007vse1_device }, + /* MCA */ { &esdi_ps2_device }, { &esdi_integrated_device }, - { &ide_pci_device }, - { &ide_pci_2ch_device }, + { &mcide_device }, + /* VLB */ { &ide_vlb_device }, { &ide_vlb_2ch_device }, - { &mcide_device }, + /* PCI */ + { &ide_pci_device }, + { &ide_pci_2ch_device }, { NULL } // clang-format on }; diff --git a/src/network/network.c b/src/network/network.c index 239178a5d..c1ee82b65 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -85,36 +85,43 @@ static const NETWORK_CARD net_cards[] = { // clang-format off { &device_none }, { &device_internal }, + /* ISA */ { &threec501_device }, { &threec503_device }, - { &pcnet_am79c960_device }, - { &pcnet_am79c961_device }, - { &de220p_device }, { &ne1000_compat_device }, - { &ne2000_compat_device }, { &ne2000_compat_8bit_device }, { &ne1000_device }, - { &ne2000_device }, - { &pcnet_am79c960_eb_device }, - { &rtl8019as_pnp_device }, { &wd8003e_device }, { &wd8003eb_device }, { &wd8013ebt_device }, + /* COM */ + { &modem_device }, + /* LPT */ { &plip_device }, + /* ISA16 */ + { &pcnet_am79c960_device }, + { &pcnet_am79c961_device }, + { &de220p_device }, + { &ne2000_compat_device }, + { &ne2000_device }, + { &pcnet_am79c960_eb_device }, + { &rtl8019as_pnp_device }, + /* MCA */ { &ethernext_mc_device }, { &wd8003eta_device }, { &wd8003ea_device }, { &wd8013epa_device }, + /* VLB */ + { &pcnet_am79c960_vlb_device }, + /* PCI */ { &pcnet_am79c973_device }, { &pcnet_am79c970a_device }, + { &dec_tulip_21140_device }, + { &dec_tulip_21040_device }, { &dec_tulip_device }, + { &dec_tulip_21140_vpc_device }, { &rtl8029as_device }, { &rtl8139c_plus_device }, - { &dec_tulip_21140_device }, - { &dec_tulip_21140_vpc_device }, - { &dec_tulip_21040_device }, - { &pcnet_am79c960_vlb_device }, - { &modem_device }, { NULL } // clang-format on }; diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index bbce63651..0b0ca7211 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -54,6 +54,14 @@ typedef const struct { static SCSI_CARD scsi_cards[] = { // clang-format off { &device_none, }, + /* ISA/Sidecar */ + { &scsi_ls2000_device, }, + /* ISA */ + { &scsi_lcs6821n_device, }, + { &scsi_rt1000b_device, }, + { &scsi_t128_device, }, + { &scsi_t130b_device, }, + /* ISA16 */ { &aha154xa_device, }, { &aha154xb_device, }, { &aha154xc_device, }, @@ -63,18 +71,19 @@ static SCSI_CARD scsi_cards[] = { { &buslogic_542bh_device, }, { &buslogic_545s_device, }, { &buslogic_545c_device, }, - { &scsi_ls2000_device, }, - { &scsi_lcs6821n_device, }, - { &scsi_rt1000b_device, }, - { &scsi_rt1000mc_device, }, - { &scsi_t128_device, }, - { &scsi_t228_device, }, - { &scsi_t130b_device, }, + /* MCA */ { &aha1640_device, }, { &buslogic_640a_device, }, - { &ncr53c90a_mca_device, }, { &spock_device, }, { &tribble_device, }, + { &ncr53c90a_mca_device, }, + { &scsi_rt1000mc_device, }, + { &scsi_t228_device, }, + /* VLB */ + { &buslogic_445s_device, }, + { &buslogic_445c_device, }, + /* PCI */ + { &am53c974_pci_device, }, { &buslogic_958d_pci_device, }, { &ncr53c810_pci_device, }, { &ncr53c815_pci_device, }, @@ -82,10 +91,7 @@ static SCSI_CARD scsi_cards[] = { { &ncr53c825a_pci_device, }, { &ncr53c860_pci_device, }, { &ncr53c875_pci_device, }, - { &am53c974_pci_device, }, { &dc390_pci_device, }, - { &buslogic_445s_device, }, - { &buslogic_445c_device, }, { NULL, }, // clang-format on }; diff --git a/src/sound/sound.c b/src/sound/sound.c index 7bf27a136..615df88bc 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -100,31 +100,45 @@ static const SOUND_CARD sound_cards[] = { // clang-format off { &device_none }, { &device_internal }, - { &acermagic_s20_device }, - { &mirosound_pcm10_device }, - { &adlib_device }, + /* ISA */ { &adgold_device }, - { &azt2316a_device }, - { &azt1605_device }, { &cms_device }, - { &cs4235_device }, - { &cs4236b_device }, { &ess_688_device }, { &ess_ess0100_pnp_device }, { &ess_1688_device }, { &ess_ess0102_pnp_device }, { &ess_ess0968_pnp_device }, - { &gus_device }, - { &gus_max_device }, + { &ssi2001_device }, + { &mmb_device }, + { &pasplus_device }, { &sb_1_device }, { &sb_15_device }, { &sb_2_device }, { &sb_pro_v1_device }, { &sb_pro_v2_device }, + { &entertainer_device }, + { &pssj_isa_device }, + { &tndy_device }, +#ifdef USE_LIBSERIALPORT /*The following devices required LIBSERIALPORT*/ + { &opl2board_device }, +#endif + /* ISA/Sidecar */ + { &adlib_device }, + /* ISA16 */ + { &acermagic_s20_device }, + { &azt2316a_device }, + { &azt1605_device }, + { &sb_goldfinch_device }, + { &cs4235_device }, + { &cs4236b_device }, + { &gus_device }, + { &gus_max_device }, + { &mirosound_pcm10_device }, + { &pas16_device }, + { &pas16d_device }, { &sb_16_device }, { &sb_16_pnp_device }, { &sb_16_pnp_ide_device }, - { &sb_goldfinch_device }, { &sb_32_pnp_device }, { &sb_awe32_device }, { &sb_awe32_pnp_device }, @@ -136,15 +150,8 @@ static const SOUND_CARD sound_cards[] = { { &sb_vibra16cl_device }, { &sb_vibra16s_device }, { &sb_vibra16xv_device }, - { &ssi2001_device }, - { &entertainer_device }, - { &mmb_device }, - { &pasplus_device }, - { &pas16_device }, - { &pas16d_device }, - { &pssj_isa_device }, - { &tndy_device }, { &wss_device }, + /* MCA */ { &adlib_mca_device }, { &ess_chipchat_16_mca_device }, { &ncr_business_audio_device }, @@ -153,17 +160,16 @@ static const SOUND_CARD sound_cards[] = { { &sb_16_reply_mca_device }, { &ess_soundpiper_16_mca_device }, { &ess_soundpiper_32_mca_device }, + /* PCI */ { &cmi8338_device }, { &cmi8738_device }, { &es1370_device }, { &es1371_device }, { &es1373_device }, { &ct5880_device }, + /* AC97 */ { &ad1881_device }, { &cs4297a_device }, -#ifdef USE_LIBSERIALPORT /*The following devices required LIBSERIALPORT*/ - { &opl2board_device }, -#endif { NULL } // clang-format on }; From 368834cbd7af6ea834b7975ad9d7ecb28c159fda Mon Sep 17 00:00:00 2001 From: Lili Kurek <lili@lili.lgbt> Date: Wed, 25 Jun 2025 21:05:16 +0000 Subject: [PATCH 1184/1190] Fix and update pl-PL.po --- src/qt/languages/pl-PL.po | 240 +++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 7433c1d65..c8a7cb886 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -13,7 +13,7 @@ msgid "&Keyboard requires capture" msgstr "&Klawaitura wymaga przechwytu myszy" msgid "&Right CTRL is left ALT" -msgstr "&Prawy CTRL to lewy Alt" +msgstr "&Prawy CTRL to lewy ALT" msgid "&Hard Reset..." msgstr "&Twardy reset..." @@ -49,7 +49,7 @@ msgid "Re&nderer" msgstr "Re&nderer" msgid "&Qt (Software)" -msgstr "&Qt (Software)" +msgstr "&Qt (programowy)" msgid "Qt (&OpenGL)" msgstr "Qt (&OpenGL)" @@ -61,13 +61,13 @@ msgid "&VNC" msgstr "&VNC" msgid "Specify dimensions..." -msgstr "Określ rozmiary..." +msgstr "Określ wymiary..." msgid "F&orce 4:3 display ratio" msgstr "&Wymuś proporcje wyświetlania 4:3" msgid "&Window scale factor" -msgstr "&Czynnik skalowania okna" +msgstr "Współ&czynnik skalowania okna" msgid "&0.5x" msgstr "&0.5x" @@ -103,10 +103,10 @@ msgid "Filter method" msgstr "Metoda filtrowania" msgid "&Nearest" -msgstr "&Nearest" +msgstr "&Najbliższa" msgid "&Linear" -msgstr "&Linear" +msgstr "&Liniowa" msgid "Hi&DPI scaling" msgstr "Skalowanie Hi&DPI" @@ -145,7 +145,7 @@ msgid "RGB &Color" msgstr "RGB - &Kolorowy" msgid "&RGB Grayscale" -msgstr "&RGB - Skala szarości" +msgstr "&RGB - Skala odcieni szarości" msgid "&Amber monitor" msgstr "&Bursztynowy monitor" @@ -157,7 +157,7 @@ msgid "&White monitor" msgstr "&Biały monitor" msgid "Grayscale &conversion type" -msgstr "Typ konwersji &w skali szarości" +msgstr "Typ konwersji &w skali odcieni szarości" msgid "BT&601 (NTSC/PAL)" msgstr "BT&601 (NTSC/PAL)" @@ -166,13 +166,13 @@ msgid "BT&709 (HDTV)" msgstr "BT&709 (HDTV)" msgid "&Average" -msgstr "&Średni" +msgstr "&Średnia" msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" msgstr "Overscan dla CGA/PCjr/Tandy/E&GA/(S)VGA" msgid "Change contrast for &monochrome display" -msgstr "Zmień kontrast dla &monochromatycznego ekranu" +msgstr "Zmień kontrast ekranu &monochromatycznego" msgid "&Media" msgstr "&Nośnik" @@ -196,7 +196,7 @@ msgid "&Preferences..." msgstr "&Preferencje..." msgid "Enable &Discord integration" -msgstr "Włącz integrację z &Discord" +msgstr "Włącz integrację z &Discordem" msgid "Sound &gain..." msgstr "Wzmocnienie &dźwięku..." @@ -214,7 +214,7 @@ msgid "&Documentation..." msgstr "&Dokumentacja..." msgid "&About 86Box..." -msgstr "&O 86Box..." +msgstr "&O 86Boxie..." msgid "&New image..." msgstr "&Nowy obraz..." @@ -247,7 +247,7 @@ msgid "E&xport to 86F..." msgstr "E&ksportuj do 86F..." msgid "&Mute" -msgstr "&Ścisz" +msgstr "&Wycisz" msgid "E&mpty" msgstr "P&usty" @@ -256,13 +256,13 @@ msgid "Reload previous image" msgstr "Przeładuj poprzedni obraz" msgid "&Folder..." -msgstr "&Teczka..." +msgstr "&Folder..." msgid "Target &framerate" msgstr "Docelowa &liczba klatek na sekundę" msgid "&Sync with video" -msgstr "&Zsynchronizuj z wideo" +msgstr "&Zsynchronizuj z obrazem" msgid "&25 fps" msgstr "&25 fps" @@ -355,7 +355,7 @@ msgid "Speed:" msgstr "Szybkość:" msgid "Frequency:" -msgstr "Częstotliwość:" +msgstr "Taktowanie:" msgid "FPU:" msgstr "Jednostka FPU:" @@ -391,7 +391,7 @@ msgid "Video #2:" msgstr "Wideo 2:" msgid "Voodoo 1 or 2 Graphics" -msgstr "Grafika Voodoo 1 czy 2" +msgstr "Grafika Voodoo 1 lub 2" msgid "IBM 8514/A Graphics" msgstr "Grafika IBM 8514/A" @@ -505,10 +505,10 @@ msgid "FD Controller:" msgstr "Kontroler dyskietek:" msgid "Tertiary IDE Controller" -msgstr "Trzeciorzędowy kontroler IDE" +msgstr "Trzeciorzędny kontroler IDE" msgid "Quaternary IDE Controller" -msgstr "Czwartorzędowy kontroler IDE" +msgstr "Czwartorzędny kontroler IDE" msgid "SCSI" msgstr "SCSI" @@ -577,7 +577,7 @@ msgid "Floppy drives:" msgstr "Napędy dyskietek:" msgid "Turbo timings" -msgstr "Rozrządy Turbo" +msgstr "Timing Turbo" msgid "Check BPB" msgstr "Sprawdzaj BPB" @@ -628,7 +628,7 @@ msgid "Fatal error" msgstr "Fatalny błąd" msgid " - PAUSED" -msgstr " - PAUSED" +msgstr " - PAUZA" msgid "Speed" msgstr "Szybkość" @@ -664,19 +664,19 @@ msgid "Basic sector images" msgstr "Podstawowe obrazy sektorów" msgid "Surface images" -msgstr "Obrazy powierzchniowe" +msgstr "Obrazy powierzchni" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "Maszyna \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/machines. Przełączanie na dostępną maszynę." +msgstr "Maszyna \"%hs\" nie jest dostępna, ponieważ brakuje ROM-ów w katalogu roms/machines. Przełączanie na dostępną maszynę." msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Karta wideo \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Przełączanie na dostępną kartę wideo." +msgstr "Karta wideo \"%hs\" nie jest dostępna, ponieważ brakuje ROM-ów w katalogu roms/video. Przełączanie na dostępną kartę graficzną." msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." -msgstr "Karta wideo 2 \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Wyłączenie drugiej karty graficznej." +msgstr "Karta wideo 2 \"%hs\" nie jest dostępna, ponieważ brakuje ROM-ów w katalogu roms/video. Wyłączenie drugiej karty graficznej." msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device." -msgstr "Urządzenie \"%hs\" nie jest dostępne, ponieważ brakuje obrazów ROM. Ignorowanie urządzenia." +msgstr "Urządzenie \"%hs\" nie jest dostępne, ponieważ brakuje ROM-ów. Ignorowanie urządzenia." msgid "Machine" msgstr "Maszyna" @@ -697,7 +697,7 @@ msgid "Ports (COM & LPT)" msgstr "Porty (COM & LPT)" msgid "Storage controllers" -msgstr "Kontrolery pamięci" +msgstr "Kontrolery danych" msgid "Hard disks" msgstr "Dyski twarde" @@ -712,13 +712,13 @@ msgid "Other peripherals" msgstr "Inne urządzenia peryferyjne" msgid "Click to capture mouse" -msgstr "Kliknij w celu przechwycenia myszy" +msgstr "Kliknij, by przechwycić mysz" msgid "Press %1 to release mouse" -msgstr "Naciśnij klawisze %1 w celu uwolnienia myszy" +msgstr "Naciśnij %1 w celu uwolnienia myszy" msgid "Press %1 or middle button to release mouse" -msgstr "Naciśnij klawisze %1 lub środkowy przycisk w celu uwolnienia myszy" +msgstr "Naciśnij %1 lub środkowy przycisk w celu uwolnienia myszy" msgid "Bus" msgstr "Magistrala" @@ -742,7 +742,7 @@ msgid "Default" msgstr "Domyślny" msgid "%1 Wait state(s)" -msgstr "%1 Stany oczekiwania" +msgstr "%1 stany oczekiwania" msgid "Type" msgstr "Rodzaj" @@ -796,16 +796,16 @@ msgid "Advanced sector images" msgstr "Zaawansowane obrazy sektorów" msgid "Flux images" -msgstr "Flux images" +msgstr "Obrazy Flux" msgid "Are you sure you want to hard reset the emulated machine?" -msgstr "Jesteś pewien że chcesz wykonać twardy reset emulowanej maszyny?" +msgstr "Czy na pewno chcesz wykonać twardy reset emulowanej maszyny?" msgid "Are you sure you want to exit 86Box?" -msgstr "Jesteś pewien że chcesz zakończyć 86Box?" +msgstr "Czy na pewno chcesz zakończyć 86Box?" msgid "Unable to initialize Ghostscript" -msgstr "Nie można zainicjować Ghostscript" +msgstr "Nie można zainicjować Ghostscriptu" msgid "Unable to initialize GhostPCL" msgstr "Nie można zainicjować GhostPCL" @@ -817,7 +817,7 @@ msgid "MO images" msgstr "Obrazy MO" msgid "Welcome to 86Box!" -msgstr "Witamy w 86Box!" +msgstr "Witamy w 86Boxie!" msgid "Internal device" msgstr "Urządzenie wewnętrzne" @@ -826,7 +826,7 @@ msgid "Exit" msgstr "Zakończ" msgid "No ROMs found" -msgstr "Nie znaleziono obrazów ROM" +msgstr "Nie znaleziono ROM-ów" msgid "Do you want to save the settings?" msgstr "Czy chcesz zapisać ustawienia?" @@ -844,7 +844,7 @@ msgid "86Box v" msgstr "86Box v" msgid "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." -msgstr "Emulator starych komputerów\n\nAutorzy: 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, i inni.\n\nZ wcześniejszym wkładem od Sarah Walker, leilei, JohnElliott, greatpsycho i innych.\n\nPrzetłumaczony przez: Fanta-Shokata\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać więcej informacji." +msgstr "Emulator starych komputerów\n\nAutorzy: 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, i inni.\n\nZ wcześniejszym wkładem od Sarah Walker, leilei, JohnElliott, greatpsycho i innych.\n\nPrzetłumaczony przez: Fanta-Shokata, Lili1228\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać więcej informacji." msgid "Hardware not available" msgstr "Sprzęt niedostępny" @@ -886,10 +886,10 @@ msgid "GLSL shaders" msgstr "Shadery GLSL" msgid "You are loading an unsupported configuration" -msgstr "Ładujesz nieobsługiwaną konfigurację" +msgstr "Wczytujesz nieobsługiwaną konfigurację" 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 "Wybór rodzaju procesora oparty na wybranej maszynie jest wyłączony dla tej emulowanej maszyny.\n\nPozwala to na wybór procesora który jest niekompatybilny z wybraną maszyną. Jednak możesz napotkać niezgodności z BIOS-em maszyny lub innym oprogramowaniem.\n\nAktywacja tego ustawienia nie jest wspierana i każde zgłoszenie błędu może zostać zamknięte jako nieważne." +msgstr "Filtrowanie rodzaju procesora na podstawie wybranej maszyny jest wyłączone dla tej emulowanej maszyny.\n\nPozwala to na wybór procesora, który jest niekompatybilny z wybraną maszyną, jednak możesz napotkać niezgodności z BIOS-em maszyny lub innym oprogramowaniem.\n\nAktywacja tego ustawienia nie jest wspierana i każde zgłoszenie błędu może zostać zamknięte jako nieprawidłowe." msgid "Continue" msgstr "Kontynuuj" @@ -901,10 +901,10 @@ msgid "Cassette images" msgstr "Obrazy kaset" msgid "Cartridge %1: %2" -msgstr "Kartrydż %1: %2" +msgstr "Kartridż %1: %2" msgid "Cartridge images" -msgstr "Obrazy kartrydżu" +msgstr "Obrazy kartridżów" msgid "Resume execution" msgstr "Wznów wykonywanie" @@ -994,7 +994,7 @@ msgid "Don't overwrite" msgstr "Nie nadpisuj" msgid "Raw image" -msgstr "Obraz surowy" +msgstr "Surowy obraz" msgid "HDI image" msgstr "Obraz HDI" @@ -1003,19 +1003,19 @@ msgid "HDX image" msgstr "Obraz HDX" msgid "Fixed-size VHD" -msgstr "VHD o stałym rozmiarze" +msgstr "VHD stałego rozmiaru" msgid "Dynamic-size VHD" -msgstr "VHD o dynamicznym rozmiarze" +msgstr "VHD dynamicznego rozmiaru" msgid "Differencing VHD" msgstr "VHD różnicujący" msgid "(N/A)" -msgstr "(Bez)" +msgstr "(N/D)" msgid "Raw image (.img)" -msgstr "Obraz surowy (.img)" +msgstr "Surowy obraz (.img)" msgid "HDI image (.hdi)" msgstr "Obraz HDI (.hdi)" @@ -1030,7 +1030,7 @@ msgid "Dynamic-size VHD (.vhd)" msgstr "VHD o dynamicznym rozmiarze (.vhd)" msgid "Differencing VHD (.vhd)" -msgstr "VHD różnicujący (.vhd)" +msgstr "VHD różnicowy (.vhd)" msgid "Large blocks (2 MB)" msgstr "Duże bloki (2 MB)" @@ -1045,7 +1045,7 @@ msgid "Select the parent VHD" msgstr "Wybierz nadrzędny plik VHD" msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" -msgstr "Może to oznaczać, że obraz nadrzędny został zmodyfikowany po utworzeniu obrazu różnicującego.\n\nMoże się to również zdarzyć, jeśli pliki obrazów zostały przeniesione lub skopiowane, lub wystąpił błąd w programie, który utworzył ten dysk\n\nCzy chcesz naprawić sygnatury czasowe?" +msgstr "Może to oznaczać, że obraz nadrzędny został zmodyfikowany po utworzeniu obrazu różnicowego.\n\nMoże się to również zdarzyć, jeśli pliki obrazów zostały przeniesione lub skopiowane, lub wystąpił błąd w programie, który utworzył ten dysk.\n\nCzy chcesz naprawić sygnatury czasowe?" msgid "Parent and child disk timestamps do not match" msgstr "Sygnatury czasowe dysku nadrzędnego i podrzędnego nie zgadzają się" @@ -1162,10 +1162,10 @@ msgid "The network configuration will be switched to the null driver" msgstr "Konfiguracja sieci zostanie przełączona na sterownik null" msgid "Mouse sensitivity:" -msgstr "Wrażliwość myszy:" +msgstr "Czułość myszy:" msgid "Select media images from program working directory" -msgstr "Wybór obrazów multimedialnych z katalogu roboczego programu" +msgstr "Wybór obrazów nośników z katalogu roboczego programu" msgid "PIT mode:" msgstr "Tryb PIT:" @@ -1186,7 +1186,7 @@ msgid "WinBox is no longer supported" msgstr "WinBox nie jest już wspierany" msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." -msgstr "Rozwój menedżera WinBox został zatrzymany w 2022 roku z powodu braku opiekunów. Ponieważ kierujemy nasze wysiłki na uczynienie 86Box jeszcze lepszym, podjęliśmy decyzję o zaprzestaniu wspierania WinBox jako menedżera.\n\nŻadne dalsze aktualizacje nie będą dostarczane za pośrednictwem WinBox i możesz napotkać nieprawidłowe zachowanie, jeśli będziesz go nadal używać z nowszymi wersjami 86Box. Wszelkie zgłoszenia błędów związane z działaniem WinBox zostaną zamknięte jako nieważne.\n\nLista innych menedżerów, z których można korzystać, znajduje się na stronie 86box.net." +msgstr "Menedżer WinBox przestał być rozwijany w 2022 roku z powodu braku opiekunów. Ponieważ kierujemy nasze wysiłki na uczynienie 86Box jeszcze lepszym, podjęliśmy decyzję o zaprzestaniu wspierania WinBox jako menedżera.\n\nŻadne dalsze aktualizacje nie będą dostarczane za pośrednictwem WinBoxa i możesz napotkać nieprawidłowe zachowanie, jeśli będziesz go nadal używać z nowszymi wersjami 86Box. Wszelkie zgłoszenia błędów związane z działaniem WinBox zostaną zamknięte jako nieważne.\n\nLista innych menedżerów, z których można korzystać, znajduje się na stronie 86box.net." msgid "Generate" msgstr "Generuj" @@ -1273,7 +1273,7 @@ msgid "VSync" msgstr "VSync" msgid "Synchronize with video" -msgstr "Zsynchronizuj z wideo" +msgstr "Synchronizuj z obrazem" msgid "Shaders" msgstr "Shadery" @@ -1297,10 +1297,10 @@ msgid "Error initializing OpenGL" msgstr "Błąd inicjalizacji OpenGL" msgid "\nFalling back to software rendering." -msgstr "\nPowrót do renderowania oprogramowania." +msgstr "\nPowrót do renderowania programowego." msgid "<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>" -msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itp.) otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>" +msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itd.), otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>" msgid "This machine might have been moved or copied." msgstr "To urządzenie mogło zostać przeniesione lub skopiowane." @@ -1354,25 +1354,25 @@ msgid "Novell NetWare 2.x Key Card" msgstr "Karta klucza Novell NetWare 2.x" msgid "Serial port passthrough 1" -msgstr "Przełączanie portu szeregowego 1" +msgstr "Przelotka portu szeregowego 1" msgid "Serial port passthrough 2" -msgstr "Przełączanie portu szeregowego 2" +msgstr "Przelotka portu szeregowego 2" msgid "Serial port passthrough 3" -msgstr "Przełączanie portu szeregowego 3" +msgstr "Przelotka portu szeregowego 3" msgid "Serial port passthrough 4" -msgstr "Przełączanie portu szeregowego 4" +msgstr "Przelotka portu szeregowego 4" msgid "Renderer options..." msgstr "Opcje renderowania..." msgid "Logitech/Microsoft Bus Mouse" -msgstr "Mysz magistralna Logitech/Microsoft" +msgstr "Mysz magistralowa Logitech/Microsoft" msgid "Microsoft Bus Mouse (InPort)" -msgstr "Mysz magistralna Microsoft (InPort)" +msgstr "Mysz magistralowa Microsoft (InPort)" msgid "Mouse Systems Serial Mouse" msgstr "Mysz szeregowa Mouse Systems" @@ -1387,7 +1387,7 @@ msgid "PS/2 Mouse" msgstr "Mysz PS/2" msgid "3M MicroTouch (Serial)" -msgstr "3M MicroTouch (szeregowa)" +msgstr "3M MicroTouch (szeregowy)" msgid "[COM] Standard Hayes-compliant Modem" msgstr "[COM] Standardowy modem zgodny z Hayes" @@ -1396,7 +1396,7 @@ msgid "Roland MT-32 Emulation" msgstr "Emulacja Roland MT-32" msgid "Roland MT-32 (New) Emulation" -msgstr "Emulacja Roland MT-32 (nowego)" +msgstr "(Nowa) emulacja Roland MT-32" msgid "Roland CM-32L Emulation" msgstr "Emulacja Roland CM-32L" @@ -1405,7 +1405,7 @@ msgid "Roland CM-32LN Emulation" msgstr "Emulacja Roland CM-32LN" msgid "OPL4-ML Daughterboard" -msgstr "Płyta córka OPL4-ML" +msgstr "Płyta-córka OPL4-ML" msgid "System MIDI" msgstr "System MIDI" @@ -1612,7 +1612,7 @@ msgid "CODEC" msgstr "CODEC" msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)" -msgstr "Podniesienie przerwania CODEC przy konfiguracji CODEC (wymagane przez niektóre sterowniki)" +msgstr "Podnieś przerwanie CODEC podczas konfiguracji CODEC-a (wymagane przez niektóre sterowniki)" msgid "SB Address" msgstr "Adres SB" @@ -1630,7 +1630,7 @@ msgid "Receive MIDI input (MPU-401)" msgstr "Odbiór wejścia MIDI (MPU-401)" msgid "SB low DMA" -msgstr "SB low DMA" +msgstr "Niskie DMA SB" msgid "6CH variant (6-channel)" msgstr "Wariant 6CH (6-kanałowy)" @@ -1645,7 +1645,7 @@ msgid "High DMA" msgstr "Wysokie DMA" msgid "Control PC speaker" -msgstr "Głośnik komputera sterującego" +msgstr "Kontroluj PC speaker" msgid "Memory size" msgstr "Rozmiar pamięci" @@ -1663,10 +1663,10 @@ msgid "GUS type" msgstr "Typ GUS" msgid "Enable 0x04 \"Exit 86Box\" command" -msgstr "Włącz polecenie 0x04 \"Wyjdź z 86Box\"" +msgstr "Włącz polecenie 0x04 \"Wyjdź z 86Boxa\"" msgid "Display type" -msgstr "Typ wyświetlacza" +msgstr "Typ ekranu" msgid "Composite type" msgstr "Typ kompozytowy" @@ -1777,7 +1777,7 @@ msgid "Triangle" msgstr "Trójkątny" msgid "Linear" -msgstr "Liniowa" +msgstr "Liniowy" msgid "4th Order" msgstr "4. rzędu" @@ -1798,13 +1798,13 @@ msgid "Three" msgstr "Trzy" msgid "Wheel" -msgstr "Koło" +msgstr "Rolka" msgid "Five + Wheel" -msgstr "" +msgstr "Pięć + rolka" msgid "Five + 2 Wheels" -msgstr "" +msgstr "Pięć + dwie rolki" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 szeregowa / SMT3(R)V" @@ -1876,7 +1876,7 @@ msgid "New" msgstr "Nowość" msgid "Color (generic)" -msgstr "Kolor (generyczny)" +msgstr "Kolorowy (generyczny)" msgid "Green Monochrome" msgstr "Zielony monochromatyczny" @@ -1888,10 +1888,10 @@ msgid "Gray Monochrome" msgstr "Szary monochromatyczny" msgid "Color (no brown)" -msgstr "Kolor (bez brązowego)" +msgstr "Kolorowy (bez brązowego)" msgid "Color (IBM 5153)" -msgstr "Kolor (IBM 5153)" +msgstr "Kolorowy (IBM 5153)" msgid "Simple doubling" msgstr "Proste podwojenie" @@ -1921,7 +1921,7 @@ msgid "Color 80x25 (5153/CGA)" msgstr "Kolor 80x25 (5153/CGA)" msgid "Enhanced Color - Normal Mode (5154/ECD)" -msgstr "Rozszerzone kolory - tryb normalny (5154/ECD)" +msgstr "Rozszerzony kolor - tryb zwykły (5154/ECD)" msgid "Enhanced Color - Enhanced Mode (5154/ECD)" msgstr "Rozszerzony kolor - tryb rozszerzony (5154/ECD)" @@ -1936,10 +1936,10 @@ msgid "Gray" msgstr "Szary" msgid "Color" -msgstr "Kolor" +msgstr "Kolorowy" msgid "U.S. English" -msgstr "Amerykański angielski" +msgstr "Angielski (USA)" msgid "Scandinavian" msgstr "Skandynawski" @@ -1948,13 +1948,13 @@ msgid "Other languages" msgstr "Inne języki" msgid "Bochs latest" -msgstr "Bochs najnowsze" +msgstr "Najnowszy Bochs" msgid "Mono Non-Interlaced" -msgstr "Mono bez przeplotu" +msgstr "Monochromatyczny bez przeplotu" msgid "Color Interlaced" -msgstr "Kolor z przeplotem" +msgstr "Kolorowy z przeplotem" msgid "Color Non-Interlaced" msgstr "Kolor bez przeplotu" @@ -1963,7 +1963,7 @@ msgid "3Dfx Voodoo Graphics" msgstr "Grafika 3Dfx Voodoo" msgid "Obsidian SB50 + Amethyst (2 TMUs)" -msgstr "Obsydian SB50 + Ametyst (2 jednostki TMU)" +msgstr "Obsydian SB50 + Amethyst (2 jednostki TMU)" msgid "8-bit" msgstr "8-bitowy" @@ -1987,7 +1987,7 @@ msgid "High-Speed" msgstr "Wysoka prędkość" msgid "Stereo LPT DAC" -msgstr "Stereofoniczny przetwornik cyfrowo-analogowy LPT" +msgstr "Stereo LPT DAC" msgid "Generic Text Printer" msgstr "Generyczna drukarka tekstowa" @@ -2002,7 +2002,7 @@ msgid "Generic PCL5e Printer" msgstr "Generyczna drukarka PCL5e" msgid "Parallel Line Internet Protocol" -msgstr "Protokół internetowy linii równoległej" +msgstr "Parallel Line Internet Protocol" msgid "Protection Dongle for Savage Quest" msgstr "Klucz ochronny dla Savage Quest" @@ -2017,7 +2017,7 @@ msgid "Host Serial Device" msgstr "Urządzenie szeregowe hosta" msgid "Name of pipe" -msgstr "Nazwa rury" +msgstr "Nazwa potoku" msgid "Data bits" msgstr "Bity danych" @@ -2026,19 +2026,19 @@ msgid "Stop bits" msgstr "Bity stopu" msgid "Baud Rate of Passthrough" -msgstr "Szybkość transmisji Passthrough" +msgstr "Szybkość transmisji przelotowej" msgid "Named Pipe (Server)" -msgstr "Nazwana rura (serwer)" +msgstr "Nazwany potok (serwer)" msgid "Host Serial Passthrough" -msgstr "Przejście przez port szeregowy hosta" +msgstr "Przelot przez port szeregowy hosta" msgid "E&ject %1" msgstr "W&yjmij %1" msgid "&Unmute" -msgstr "&Wycisz" +msgstr "O&dcisz" msgid "Softfloat FPU" msgstr "FPU Softfloat" @@ -2047,28 +2047,28 @@ msgid "High performance impact" msgstr "Wysoki wpływ na wydajność" msgid "[Generic] RAM Disk (max. speed)" -msgstr "[Generic] Dysk RAM (maks. prędkość)" +msgstr "[generyczny] Dysk RAM (maks. prędkość)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[generyczny] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[generyczny] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[generyczny] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[generyczny] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[generyczny] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[generyczny] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[generyczny] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "Klon IBM 8514/A (ISA)" @@ -2083,67 +2083,67 @@ msgid "Generic PC/AT Memory Expansion" msgstr "Generyczne rozszerzenie pamięci PC/AT" msgid "Unable to find Dot-Matrix fonts" -msgstr "Nie można znaleźć czcionek igłowych" +msgstr "Nie można znaleźć fontów igłowych" msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." -msgstr "Czcionki TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generyczniej drukarki igłowej ESC/P." +msgstr "Fonty TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generycznej drukarki igłowej ESC/P." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Przejmij klawisze multimedialne" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Pytaj o potwierdzenie przed zapisaniem ustawień" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Pytaj o potwierdzenie przed twardym resetem" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Pytaj o potwierdzenie przed wyjściem" msgid "Options" -msgstr "" +msgstr "Opcje" msgid "Model" -msgstr "" +msgstr "Model" msgid "Model:" -msgstr "" +msgstr "Model:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Nie udało się zainicjować renderera Vulkan." msgid "GLSL Error" -msgstr "" +msgstr "Błąd GLSL" msgid "Could not load shader: %1" -msgstr "" +msgstr "Nie udało się wczytać shadera: %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "Wymagana jest wersja OpenGL 3.0 lub wyższa. Aktualna wersja GLSL to %1." msgid "Could not load texture: %1" -msgstr "" +msgstr "Nie udało się wczytać tekstury: %1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "Nie udało się skompilować shadera:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "Program niezalinkowany:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "Menedżer shaderów" msgid "Shader Configuration" -msgstr "" +msgstr "Konfiguracja shadera" msgid "Add" -msgstr "" +msgstr "Dodaj" msgid "Move up" -msgstr "" +msgstr "Przesuń w górę" msgid "Move down" -msgstr "" +msgstr "Przesuń w dół" msgid "Could not load file %1" -msgstr "" +msgstr "Nie można wczytać pliku %1" From 537ab6ae6fd84ffeecca0f31af8e0f33767e646b Mon Sep 17 00:00:00 2001 From: Lili Kurek <lili@lili.lgbt> Date: Wed, 25 Jun 2025 21:40:49 +0000 Subject: [PATCH 1185/1190] Incorporate some of the changes suggested by @asiekierka --- src/qt/languages/pl-PL.po | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index c8a7cb886..b161370ed 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -172,7 +172,7 @@ msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" msgstr "Overscan dla CGA/PCjr/Tandy/E&GA/(S)VGA" msgid "Change contrast for &monochrome display" -msgstr "Zmień kontrast ekranu &monochromatycznego" +msgstr "Zmień kontrast dla ekranu &monochromatycznego" msgid "&Media" msgstr "&Nośnik" @@ -697,7 +697,7 @@ msgid "Ports (COM & LPT)" msgstr "Porty (COM & LPT)" msgid "Storage controllers" -msgstr "Kontrolery danych" +msgstr "Kontrolery pamięci masowej" msgid "Hard disks" msgstr "Dyski twarde" @@ -742,7 +742,7 @@ msgid "Default" msgstr "Domyślny" msgid "%1 Wait state(s)" -msgstr "%1 stany oczekiwania" +msgstr "%1 stan(y/ów) oczekiwania" msgid "Type" msgstr "Rodzaj" @@ -796,7 +796,7 @@ msgid "Advanced sector images" msgstr "Zaawansowane obrazy sektorów" msgid "Flux images" -msgstr "Obrazy Flux" +msgstr "Obrazy flux" msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Czy na pewno chcesz wykonać twardy reset emulowanej maszyny?" @@ -1003,16 +1003,16 @@ msgid "HDX image" msgstr "Obraz HDX" msgid "Fixed-size VHD" -msgstr "VHD stałego rozmiaru" +msgstr "VHD o stałym rozmiarze" msgid "Dynamic-size VHD" -msgstr "VHD dynamicznego rozmiaru" +msgstr "VHD o dynamicznym rozmiarze" msgid "Differencing VHD" msgstr "VHD różnicujący" msgid "(N/A)" -msgstr "(N/D)" +msgstr "(nd.)" msgid "Raw image (.img)" msgstr "Surowy obraz (.img)" @@ -1630,7 +1630,7 @@ msgid "Receive MIDI input (MPU-401)" msgstr "Odbiór wejścia MIDI (MPU-401)" msgid "SB low DMA" -msgstr "Niskie DMA SB" +msgstr "Low DMA SB" msgid "6CH variant (6-channel)" msgstr "Wariant 6CH (6-kanałowy)" @@ -2119,7 +2119,7 @@ msgid "Could not load shader: %1" msgstr "Nie udało się wczytać shadera: %1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "Wymagana jest wersja OpenGL 3.0 lub wyższa. Aktualna wersja GLSL to %1." +msgstr "Wymagana jest wersja OpenGL 3.0 lub wyższa. Aktualna wersja GLSL to %1.%2" msgid "Could not load texture: %1" msgstr "Nie udało się wczytać tekstury: %1" From 07af9f12d75cfe724d650583be935f756fb94332 Mon Sep 17 00:00:00 2001 From: TC1995 <mariogplayer90@gmail.com> Date: Thu, 26 Jun 2025 13:11:42 +0200 Subject: [PATCH 1186/1190] Video: more changes and fixes of the day (June 26th, 2025) 1. Convert the ramdac types into an enumerator. 2. Make sure the 8514/A compatible ramdacs are, if in VGA mode, using VGA compatible ports and/or, in 8514/A mode, the 8514/A ports when needed, fixes color issues in 1280x1024 resolutions on NT 3.1 and various stuff using the Mach32. 3. Add pitch initialization on reset, fixes 8514/A display drivers on various stuff on Mach8/Mach32 cards. --- src/include/86box/vid_ati_mach8.h | 8 ++++- src/include/86box/vid_svga.h | 9 +++--- src/video/ramdac/vid_ramdac_ati68860.c | 20 ++++++------- src/video/ramdac/vid_ramdac_ati68875.c | 24 +++++++++++---- src/video/vid_ati_mach64.c | 13 ++++---- src/video/vid_ati_mach8.c | 41 ++++++++++++++------------ src/video/vid_svga.c | 11 ++++--- 7 files changed, 74 insertions(+), 52 deletions(-) diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index e999c7087..ad5281ac3 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -18,6 +18,12 @@ #ifndef VIDEO_ATI_MACH8_H #define VIDEO_ATI_MACH8_H +typedef enum { + ATI_68875 = 0, + ATI_68860, + RAMDAC_MAX +} mach_ramdac_type; + typedef struct mach_t { ati_eeprom_t eeprom; svga_t svga; @@ -39,7 +45,7 @@ typedef struct mach_t { uint8_t irq_state; int index; - int ramdac_type; + mach_ramdac_type ramdac_type; int old_mode; uint16_t config1; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index ad9170ad3..cc67e70bc 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -136,6 +136,7 @@ typedef struct svga_t { int packed_4bpp; int ps_bit_bug; int ati_4color; + int vblankend; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM @@ -404,15 +405,15 @@ uint32_t svga_lookup_lut_ram(svga_t* svga, uint32_t val); /* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */ -extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga); -extern uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga); +extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, int is_8514, void *priv, svga_t *svga); +extern uint8_t ati68860_ramdac_in(uint16_t addr, int is_8514, void *priv, svga_t *svga); extern void ati68860_set_ramdac_type(void *priv, int type); extern void ati68860_ramdac_set_render(void *priv, svga_t *svga); extern void ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col); extern void ati68860_hwcursor_draw(svga_t *svga, int displine); -extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga); -extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga); +extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, int is_8514, void *priv, svga_t *svga); +extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, int is_8514, void *priv, svga_t *svga); extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga); extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); diff --git a/src/video/ramdac/vid_ramdac_ati68860.c b/src/video/ramdac/vid_ramdac_ati68860.c index e3e486d57..4411f2ee2 100644 --- a/src/video/ramdac/vid_ramdac_ati68860.c +++ b/src/video/ramdac/vid_ramdac_ati68860.c @@ -67,22 +67,22 @@ typedef struct ati68860_ramdac_t { } ati68860_ramdac_t; void -ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) +ati68860_ramdac_out(uint16_t addr, uint8_t val, int is_8514, void *priv, svga_t *svga) { ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; switch (addr) { case 0: - svga_out(0x3c8, val, svga); + svga_out(is_8514 ? 0x2ec : 0x3c8, val, svga); break; case 1: - svga_out(0x3c9, val, svga); + svga_out(is_8514 ? 0x2ed : 0x3c9, val, svga); break; case 2: - svga_out(0x3c6, val, svga); + svga_out(is_8514 ? 0x2ea : 0x3c6, val, svga); break; case 3: - svga_out(0x3c7, val, svga); + svga_out(is_8514 ? 0x2eb : 0x3c7, val, svga); break; default: ramdac->regs[addr & 0xf] = val; @@ -172,23 +172,23 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) } uint8_t -ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga) +ati68860_ramdac_in(uint16_t addr, int is_8514, void *priv, svga_t *svga) { const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; uint8_t temp = 0; switch (addr) { case 0: - temp = svga_in(0x3c8, svga); + temp = svga_in(is_8514 ? 0x2ec : 0x3c8, svga); break; case 1: - temp = svga_in(0x3c9, svga); + temp = svga_in(is_8514 ? 0x2ed : 0x3c9, svga); break; case 2: - temp = svga_in(0x3c6, svga); + temp = svga_in(is_8514 ? 0x2ea : 0x3c6, svga); break; case 3: - temp = svga_in(0x3c7, svga); + temp = svga_in(is_8514 ? 0x2eb : 0x3c7, svga); break; case 4: case 8: diff --git a/src/video/ramdac/vid_ramdac_ati68875.c b/src/video/ramdac/vid_ramdac_ati68875.c index 5d573a282..4de0ed3d9 100644 --- a/src/video/ramdac/vid_ramdac_ati68875.c +++ b/src/video/ramdac/vid_ramdac_ati68875.c @@ -38,7 +38,7 @@ typedef struct ati68875_ramdac_t { } ati68875_ramdac_t; void -ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga) +ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, int is_8514, void *priv, svga_t *svga) { ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv; uint8_t rs = (addr & 0x03); @@ -48,10 +48,16 @@ ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, sv switch (rs) { case 0x00: /* Palette Write Index Register (RS value = 0000) */ + svga_out(is_8514 ? 0x2ec : 0x3c8, val, svga); + break; case 0x01: /* Palette Data Register (RS value = 0001) */ + svga_out(is_8514 ? 0x2ed : 0x3c9, val, svga); + break; case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - case 0x03: - svga_out(addr, val, svga); + svga_out(is_8514 ? 0x2ea : 0x3c6, val, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + svga_out(is_8514 ? 0x2eb : 0x3c7, val, svga); break; case 0x08: /* General Control Register (RS value = 1000) */ ramdac->gen_cntl = val; @@ -83,7 +89,7 @@ ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, sv } uint8_t -ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) +ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, int is_8514, void *priv, svga_t *svga) { const ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv; uint8_t rs = (addr & 0x03); @@ -94,10 +100,16 @@ ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) switch (rs) { case 0x00: /* Palette Write Index Register (RS value = 0000) */ + temp = svga_in(is_8514 ? 0x2ec : 0x3c8, svga); + break; case 0x01: /* Palette Data Register (RS value = 0001) */ + temp = svga_in(is_8514 ? 0x2ed : 0x3c9, svga); + break; case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - case 0x03: - temp = svga_in(addr, svga); + temp = svga_in(is_8514 ? 0x2ea : 0x3c6, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + temp = svga_in(is_8514 ? 0x2eb : 0x3c7, svga); break; case 0x08: /* General Control Register (RS value = 1000) */ temp = ramdac->gen_cntl; diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 8e6b52517..2b89bddf4 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -425,7 +425,7 @@ mach64_out(uint16_t addr, uint8_t val, void *priv) case 0x3C8: case 0x3C9: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, 0, svga->ramdac, svga); else svga_out(addr, val, svga); return; @@ -492,7 +492,7 @@ mach64_in(uint16_t addr, void *priv) case 0x3C8: case 0x3C9: if (mach64->type == MACH64_GX) - return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), svga->ramdac, svga); + return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), 0, svga->ramdac, svga); return svga_in(addr, svga); case 0x3D4: @@ -2530,7 +2530,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0xc2: case 0xc3: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); + ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), 0, mach64->svga.ramdac, &mach64->svga); else { switch (addr & 3) { case 0: @@ -3313,7 +3313,7 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) case 0xc2: case 0xc3: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, 0, svga->ramdac, svga); else { switch (addr & 3) { case 0: @@ -3574,7 +3574,7 @@ mach64_ext_inb(uint16_t port, void *priv) case 0x5eee: case 0x5eef: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); + ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), 0, mach64->svga.ramdac, &mach64->svga); else { switch (port & 3) { case 0: @@ -3820,7 +3820,7 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x5eee: case 0x5eef: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); + ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, 0, svga->ramdac, svga); else { switch (port & 3) { case 0: @@ -4801,6 +4801,7 @@ mach64vt2_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); mach64->pci = 1; + mach64->vlb = 0; mach64->pci_id = 0x5654; mach64->config_chip_id = 0x40005654; mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/ diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 4133b730e..46d3d98c1 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2422,11 +2422,11 @@ mach_out(uint16_t addr, uint8_t val, void *priv) rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); mach_log("8514/A Extended mode=%02x.\n", mach->regs[0xb0] & 0x20); - if (ATI_MACH32 && !dev->on) { - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + if (ATI_MACH32) { + if (mach->pci_bus && (mach->ramdac_type == ATI_68860)) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, 1, svga->ramdac, svga); else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + ati68875_ramdac_out(addr, rs2, rs3, val, 1, svga->ramdac, svga); } else svga_out(addr, val, svga); return; @@ -2438,11 +2438,11 @@ mach_out(uint16_t addr, uint8_t val, void *priv) rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); mach_log("VGA Extended mode=%02x.\n", mach->regs[0xb0] & 0x20); - if (ATI_MACH32 && !dev->on) { - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + if (ATI_MACH32) { + if (mach->pci_bus && (mach->ramdac_type == ATI_68860)) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, 0, svga->ramdac, svga); else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + ati68875_ramdac_out(addr, rs2, rs3, val, 0, svga->ramdac, svga); } else svga_out(addr, val, svga); return; @@ -2563,11 +2563,11 @@ mach_in(uint16_t addr, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); - if (ATI_MACH32 && !dev->on) { - if (mach->pci_bus && !mach->ramdac_type) - temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); + if (ATI_MACH32) { + if (mach->pci_bus && (mach->ramdac_type == ATI_68860)) + temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), 1, svga->ramdac, svga); else - temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + temp = ati68875_ramdac_in(addr, rs2, rs3, 1, svga->ramdac, svga); } else temp = svga_in(addr, svga); break; @@ -3007,6 +3007,7 @@ mach_recalctimings(svga_t *svga) 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); + mach_log("EXTGECONFIG bits 11-15=%04x.\n", mach->accel.ext_ge_config & 0x8800); if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) { 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, @@ -4759,7 +4760,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) } } else { switch (mach->accel.cmd_type) { - case 1: case 2: case 5: if ((dev->subsys_cntl & INT_GE_BSY) && @@ -4770,6 +4770,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) (dev->accel.dy <= clip_b)) temp |= INT_GE_BSY; break; + case 1: case 3: case 4: if ((dev->subsys_cntl & INT_GE_BSY) && @@ -7068,7 +7069,7 @@ mach8_init(const device_t *info) dev->type = info->flags; dev->local = info->local & 0xff; mach->has_bios = !(info->local & 0xff00); - mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : 1; + mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : ATI_68875; dev->vram_amount = device_get_config_int("memory"); dev->vram_512k_8514 = dev->vram_amount == 512; @@ -7119,7 +7120,7 @@ mach8_init(const device_t *info) dev->vram_mask = dev->vram_size - 1; dev->hwcursor.cur_ysize = 64; mach->config1 = 0x20; - if (mach->pci_bus && !mach->ramdac_type) + if (mach->pci_bus && (mach->ramdac_type == ATI_68860)) svga->ramdac = device_add(&ati68860_ramdac_device); else svga->ramdac = device_add(&ati68875_ramdac_device); @@ -7142,7 +7143,7 @@ mach8_init(const device_t *info) } else if (mach->pci_bus) { video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_pci); mach->config1 |= 0x0e; - if (mach->ramdac_type) + if (mach->ramdac_type == ATI_68860) mach->config1 |= 0x0400; else mach->config1 |= 0x0a00; @@ -7180,6 +7181,7 @@ mach8_init(const device_t *info) dev->on = 0; dev->pitch = 1024; + dev->ext_pitch = 1024; dev->ext_crt_pitch = 0x80; dev->accel_bpp = 8; svga->force_old_addr = 1; @@ -7242,6 +7244,7 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) /*Init as 1024x768 87hz interlaced first, per 8514/A.*/ dev->on = 0; dev->pitch = 1024; + dev->ext_pitch = 1024; dev->ext_crt_pitch = 0x80; dev->accel_bpp = 8; dev->rowoffset = 0x80; @@ -7390,12 +7393,12 @@ static const device_config_t mach32_pci_config[] = { .description = "RAMDAC type", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 0, + .default_int = ATI_68860, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "ATI 68860", .value = 0 }, - { .description = "ATI 68875", .value = 1 }, + { .description = "ATI 68860", .value = ATI_68860 }, + { .description = "ATI 68875", .value = ATI_68875 }, { .description = "" } }, .bios = { { 0 } } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 2899f3bf7..afeb7a9d6 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -693,7 +693,6 @@ svga_recalctimings(svga_t *svga) double _dispontime_xga = 0.0; double _dispofftime_xga = 0.0; double disptime_xga = 0.0; - int vblankend; #ifdef ENABLE_SVGA_LOG int vsyncend; int hdispend; @@ -913,9 +912,9 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); - vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); - if (vblankend <= svga->vblankstart) - vblankend += 0x00000080; + svga->vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); + if (svga->vblankend <= svga->vblankstart) + svga->vblankend += 0x00000080; if (svga->hoverride || svga->override) { if (svga->hdisp >= 2048) @@ -969,7 +968,7 @@ svga_recalctimings(svga_t *svga) } /* - 1 because + 1 but also - 2 to compensate for the + 2 added to vtotal above. */ - svga->y_add = svga->vtotal - vblankend - 1; + svga->y_add = svga->vtotal - svga->vblankend - 1; svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend); if ((svga->dispend >= 2048) || (svga->y_add < 0)) { @@ -1050,7 +1049,7 @@ svga_recalctimings(svga_t *svga) "\n" "\n", svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend, - svga->vblankstart, vblankend, + svga->vblankstart, svga->vblankend, svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend, svga->hblankstart, svga->hblankend); From 7141e15fa8039061f4afce130f362b7d42cfe5f0 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:20:19 +0200 Subject: [PATCH 1187/1190] Olivetti M290 fixes Change minimum RAM to 1 MB and add the name of the AT&T variant, which seems to have the exact same BIOS --- 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 e779eb753..24b950ad7 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3141,7 +3141,7 @@ const machine_t machines[] = { }, /* Has Olivetti KBC firmware. */ { - .name = "[ISA] Olivetti M290", + .name = "[ISA] Olivetti M290/AT&T 6286 WGS", .internal_name = "m290", .type = MACHINE_TYPE_286, .chipset = MACHINE_CHIPSET_PROPRIETARY, @@ -3163,7 +3163,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_AT, .flags = MACHINE_FLAGS_NONE, .ram = { - .min = 640, + .min = 1024, .max = 16384, .step = 128 }, From f6caa6ff8d41220659a4b0c7765e53f3b2db5501 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Thu, 26 Jun 2025 19:27:58 +0200 Subject: [PATCH 1188/1190] Tandy graphics: repeat character line 7 in line 8, fixes #5710. --- src/video/vid_tandy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index 0609ca378..0ff9ad3df 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -447,7 +447,7 @@ vid_poll(void *priv) } if (vid->scanline & 8) { for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; } } else { for (c = 0; c < 8; c++) { @@ -483,7 +483,7 @@ vid_poll(void *priv) vid->memaddr++; if (vid->scanline & 8) { for (c = 0; c < 8; c++) - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; } else { for (c = 0; c < 8; c++) { if (vid->scanline == 8) { From 3d42dbcb0efea299e76b4ba4c1a55ebd17617914 Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Thu, 26 Jun 2025 19:35:14 +0200 Subject: [PATCH 1189/1190] Tandy: Improve the fix. --- src/video/vid_tandy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index 0ff9ad3df..0504fd096 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -447,7 +447,7 @@ vid_poll(void *priv) } if (vid->scanline & 8) { for (c = 0; c < 8; c++) { - buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = ((chr & 0xf0) == 0xb0) ? cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0] : cols[0]; } } else { for (c = 0; c < 8; c++) { @@ -483,7 +483,7 @@ vid_poll(void *priv) vid->memaddr++; if (vid->scanline & 8) { for (c = 0; c < 8; c++) - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = ((chr & 0xf0) == 0xb0) ? cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0] : cols[0]; } else { for (c = 0; c < 8; c++) { if (vid->scanline == 8) { From 37dfa93c47f24e3082ec4aab4ccbd597870a31cd Mon Sep 17 00:00:00 2001 From: OBattler <oubattler@gmail.com> Date: Thu, 26 Jun 2025 23:45:40 +0200 Subject: [PATCH 1190/1190] Manager: Extend the serial_enabled list to 8 entries, fixes the manager. --- src/qt/qt_vmmanager_system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 7ab7e43ca..0a7382094 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -719,7 +719,7 @@ VMManagerSystem::setupVars() { // Serial // By default serial 1 and 2 are enabled unless otherwise specified static auto serial_match = QRegularExpression("serial\\d_enabled", QRegularExpression::CaseInsensitiveOption); - QList<bool> serial_enabled = {true, true, false, false}; + QList<bool> serial_enabled = {true, true, false, false, false, false, false, false}; // Parallel // By default lpt 1 is enabled unless otherwise specified static auto lpt_match = QRegularExpression("lpt\\d_enabled", QRegularExpression::CaseInsensitiveOption);

      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 JRwic_^na9pG)e#f literal 0 HcmV?d00001 diff --git a/src/qt/assets/systemicons/ibm_ps2_m80.png b/src/qt/assets/systemicons/ibm_ps2_m80.png new file mode 100644 index 0000000000000000000000000000000000000000..9df02adffc37ad3ab68e9eab35a115ae1ace0887 GIT binary patch literal 265107 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