Merge branch '86Box:master' into master

This commit is contained in:
starfrost
2025-03-16 23:30:57 +00:00
committed by GitHub
16 changed files with 975 additions and 636 deletions

View File

@@ -264,18 +264,20 @@ 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();
/* 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 {
CHECK_READ_CS(MIN(ol, 4));
}
if (!cpu_state.abrt) {
@@ -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 (is386 && !x86_was_reset && ins_fetch_fault)
x86gen();
} else if (new_ne) {
flags_rebuild();
new_ne = 0;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));

View File

@@ -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 },

View File

@@ -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"

View File

@@ -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;

View File

@@ -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
@@ -454,9 +455,6 @@ MainWindow::MainWindow(QWidget *parent)
endblit();
}
#endif
case 6:
newVidApi = RendererStack::Renderer::OpenGL3PCem;
break;
}
ui->stackedWidget->switchRenderer(newVidApi);
if (!show_second_monitors)
@@ -468,7 +466,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 */
@@ -1754,7 +1752,7 @@ MainWindow::on_actionAbout_86Box_triggered()
versioninfo.append(QString(" [%1, %2]").arg(QSysInfo::buildCpuArchitecture(), tr(DYNAREC_STR)));
msgBox.setText(QString("<b>%3%1%2</b>").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);
@@ -2028,8 +2026,8 @@ MainWindow::on_actionRenderer_options_triggered()
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(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<RendererStack::Renderer>(vid_api));
if (renderers[i]) {
renderers[i]->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
}
}
}

View File

@@ -353,6 +353,9 @@
<property name="text">
<string>Exit</string>
</property>
<property name="menuRole">
<enum>QAction::QuitRole</enum>
</property>
</action>
<action name="actionSettings">
<property name="icon">
@@ -815,6 +818,9 @@
<property name="text">
<string>Renderer options...</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
<action name="actionVulkan">
<property name="checkable">

View File

@@ -288,7 +288,8 @@ RendererStack::leaveEvent(QEvent *event)
void
RendererStack::switchRenderer(Renderer renderer)
{
startblit();
//startblit();
switchInProgress = true;
if (current) {
rendererWindow->finalize();
removeWidget(current.get());
@@ -339,26 +340,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();
@@ -369,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, [=]() {
@@ -401,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, [=]() {
@@ -431,9 +412,9 @@ 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();
switchInProgress = false;
emit rendererChanged();
}
}
@@ -443,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<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set()) {
video_blit_complete_monitor(m_monitor_index);

View File

@@ -61,7 +61,6 @@ public:
OpenGLES,
OpenGL3,
Vulkan,
OpenGL3PCem = 6,
None = -1
};
void switchRenderer(Renderer renderer);
@@ -114,6 +113,7 @@ private:
std::unique_ptr<QWidget> current;
std::atomic_bool rendererTakesScreenshots;
std::atomic_bool switchInProgress{false};
};
#endif // QT_RENDERERCONTAINER_HPP

View File

@@ -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,

File diff suppressed because it is too large Load Diff