Merge branch 'master' into Dungeonseeker-patch-1

This commit is contained in:
Jasmine Iwanek
2023-04-28 14:54:08 -04:00
committed by GitHub
26 changed files with 337 additions and 274 deletions

View File

@@ -29,6 +29,7 @@ It is also recommended to use a manager application with 86Box for easier handli
* [86Box Manager Lite](https://github.com/insanemal/86box_manager_py) by [Insanemal](https://github.com/insanemal)
* [WinBox for 86Box](https://github.com/86Box/WinBox-for-86Box) by Laci bá' (Windows only)
* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by 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.
@@ -50,16 +51,6 @@ Licensing
The emulator can also optionally make use of [munt](https://github.com/munt/munt), [FluidSynth](https://www.fluidsynth.org/), [Ghostscript](https://www.ghostscript.com/) and [Discord Game SDK](https://discord.com/developers/docs/game-sdk/sdk-starter-guide), which are distributed under their respective licenses.
Contribution requirements
-------------------------
Formal codification of the project's emulated hardware contribution requirements, which all have to be met to accept an addition:
* A ROM must be available;
* Documentation must be available or it must be feasible to reverse engineer with a reasonable amount of time and effort;
* It must be feasible to implement with a reasonable amount of time and effort;
* It has to fall inside the project's scope.
Where unsure or for more details about the project's emulated hardware contribution requirements, contact a Contributor or higher.
Donations
---------
We do not charge you for the emulator but donations are still welcome:

View File

@@ -151,11 +151,13 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x41:
/* TODO: Bit 7 selects keyboard controller type:
0 = AT, 1 = PS/2 */
pic_kbd_latch(1);
pic_mouse_latch(!!(val & 0x40));
dev->pci_conf[addr] = val & 0xbf;
// pic_kbd_latch(!!(val & 0x80));
if (dev->type == 1)
pic_mouse_latch(!!(val & 0x40) || !(dev->pci_conf[0x78] & 0x02));
else
pic_mouse_latch(!!(val & 0x40));
dev->pci_conf[addr] = val;
break;
case 0x42: /* ISA Bus Speed */
@@ -431,6 +433,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
if (dev->type == 1) {
ali1543_log("PCI78 = %02X\n", val);
dev->pci_conf[addr] = val & 0x33;
pic_mouse_latch(!!(dev->pci_conf[0x41] & 0x40) || !(val & 0x02));
}
break;
@@ -1520,6 +1523,8 @@ ali1543_reset(void *priv)
ali1533_write(0, 0x74, 0x00, dev);
ali1533_write(0, 0x75, 0x00, dev);
ali1533_write(0, 0x76, 0x00, dev);
if (dev->type == 1)
ali1533_write(0, 0x78, 0x00, dev);
unmask_a20_in_smm = 1;
}

View File

@@ -200,9 +200,11 @@ sio_write(int func, int addr, uint8_t val, void *priv)
dev->regs[addr] = val;
break;
case 0x4c:
dev->regs[addr] = (val & 0x7f);
break;
case 0x4d:
dev->regs[addr] = (val & 0x7f);
pic_mouse_latch(!!(val & 0x10));
// pic_mouse_latch(!!(val & 0x10));
break;
case 0x4f:
dev->regs[addr] = val;
@@ -394,7 +396,7 @@ sio_reset_hard(void *priv)
dev->regs[0x4b] = 0x0f;
dev->regs[0x4c] = 0x56;
dev->regs[0x4d] = 0x40;
pic_mouse_latch(0x00);
// pic_mouse_latch(0x00);
dev->regs[0x4e] = 0x07;
dev->regs[0x4f] = 0x4f;
dev->regs[0x57] = 0x04;
@@ -544,7 +546,19 @@ sio_init(const device_t *info)
// device_add(&i8254_sec_device);
pic_kbd_latch(0x01);
// pic_kbd_latch(0x01);
/* The situation is as follow: SIO.AB has the IRQ 1 latch but SIO.IB and SIO.ZB do not,
and I suspect that because of that, the IRQ 12 latch on SIO.IB and SIO.ZB, while
evidently planned and documented in the datashet, was basically non-functional, and
motherboard manufacturers had to install their own latches to use PS/2 keyboards
and/or mice. One such example is the AMI Excalibur PCI Pentium, which never enables
the SIO.ZB's IRQ 12 latch but clearly expects one since otherwise, the PS/2 mouse
behaves erractically in the WinBIOS CMOS Setup. */
if (machine_has_bus(machine, MACHINE_BUS_PS2)) {
pic_kbd_latch(0x01);
pic_mouse_latch(0x01);
}
return dev;
}

View File

@@ -1053,13 +1053,13 @@ enter_smm(int in_hlt)
memset(saved_state, 0x00, SMM_SAVE_STATE_MAP_SIZE * sizeof(uint32_t));
if (is_cxsmm) /* Cx6x86 */
if (is_cxsmm) /* Cx6x86 */
smram_save_state_cyrix(saved_state, in_hlt);
else if (is_pentium || is_am486) /* Am486 / 5x86 / Intel P5 (Pentium) */
smram_save_state_p5(saved_state, in_hlt);
else if (is_k5 || is_k6) /* AMD K5 and K6 */
else if (is_k5 || is_k6) /* AMD K5 and K6 */
smram_save_state_amd_k(saved_state, in_hlt);
else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */
else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */
smram_save_state_p6(saved_state, in_hlt);
cr0 &= ~0x8000000d;
@@ -1224,13 +1224,13 @@ leave_smm(void)
}
x386_common_log("New SMBASE: %08X (%08X)\n", saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET], saved_state[66]);
if (is_cxsmm) /* Cx6x86 */
if (is_cxsmm) /* Cx6x86 */
smram_restore_state_cyrix(saved_state);
else if (is_pentium || is_am486) /* Am486 / 5x86 / Intel P5 (Pentium) */
smram_restore_state_p5(saved_state);
else if (is_k5 || is_k6) /* AMD K5 and K6 */
else if (is_k5 || is_k6) /* AMD K5 and K6 */
smram_restore_state_amd_k(saved_state);
else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */
else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */
smram_restore_state_p6(saved_state);
in_smm = 0;
@@ -1427,25 +1427,29 @@ x86illegal(void)
}
int
checkio(uint32_t port)
checkio(uint32_t port, int mask)
{
uint16_t t;
uint8_t d;
uint32_t t;
cpl_override = 1;
t = readmemw(tr.base, 0x66);
cpl_override = 0;
if (cpu_state.abrt)
if (UNLIKELY(cpu_state.abrt)) {
cpl_override = 0;
return 0;
}
if ((t + (port >> 3UL)) > tr.limit)
return 1;
cpl_override = 1;
d = readmembl(tr.base + t + (port >> 3));
t += (port >> 3UL);
mask <<= (port & 7);
if (UNLIKELY(mask & 0xff00)) {
if (LIKELY(t < tr.limit))
mask &= readmemwl(tr.base + t);
} else {
if (LIKELY(t <= tr.limit))
mask &= readmembl(tr.base + t);
}
cpl_override = 0;
return d & (1 << (port & 7));
return mask;
}
#ifdef OLD_DIVEXCP

View File

@@ -97,11 +97,11 @@
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
do_mmutranslate((s) + (a), b, 4, 1)
int checkio(uint32_t port);
int checkio(uint32_t port, int mask);
#define check_io_perm(port) \
#define check_io_perm(port, size) \
if (msw & 1 && ((CPL > IOPL) || (cpu_state.eflags & VM_FLAG))) { \
int tempi = checkio(port); \
int tempi = checkio(port, (1 << size) - 1); \
if (cpu_state.abrt) \
return 1; \
if (tempi) { \

View File

@@ -642,7 +642,7 @@ extern void cpu_CPUID(void);
extern void cpu_RDMSR(void);
extern void cpu_WRMSR(void);
extern int checkio(uint32_t port);
extern int checkio(uint32_t port, int mask);
extern void codegen_block_end(void);
extern void codegen_reset(void);
extern void cpu_set_edx(void);

View File

@@ -2,7 +2,7 @@ static int
opIN_AL_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t) getbytef();
check_io_perm(port);
check_io_perm(port, 1);
AL = inb(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 1, 0, 0, 0, 0);
@@ -14,8 +14,7 @@ static int
opIN_AX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t) getbytef();
check_io_perm(port);
check_io_perm(port + 1);
check_io_perm(port, 2);
AX = inw(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 1, 0, 0, 0, 0);
@@ -27,10 +26,7 @@ static int
opIN_EAX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t) getbytef();
check_io_perm(port);
check_io_perm(port + 1);
check_io_perm(port + 2);
check_io_perm(port + 3);
check_io_perm(port, 4);
EAX = inl(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 0, 1, 0, 0, 0);
@@ -43,7 +39,7 @@ static int
opOUT_AL_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t) getbytef();
check_io_perm(port);
check_io_perm(port, 1);
outb(port, AL);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0, 0, 1, 0, 0);
@@ -57,8 +53,7 @@ static int
opOUT_AX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t) getbytef();
check_io_perm(port);
check_io_perm(port + 1);
check_io_perm(port, 2);
outw(port, AX);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0, 0, 1, 0, 0);
@@ -70,10 +65,7 @@ static int
opOUT_EAX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t) getbytef();
check_io_perm(port);
check_io_perm(port + 1);
check_io_perm(port + 2);
check_io_perm(port + 3);
check_io_perm(port, 4);
outl(port, EAX);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0, 0, 0, 1, 0);
@@ -85,7 +77,7 @@ opOUT_EAX_imm(uint32_t fetchdat)
static int
opIN_AL_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX, 1);
AL = inb(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 1, 0, 0, 0, 0);
@@ -96,8 +88,7 @@ opIN_AL_DX(uint32_t fetchdat)
static int
opIN_AX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX, 2);
AX = inw(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 1, 0, 0, 0, 0);
@@ -108,10 +99,7 @@ opIN_AX_DX(uint32_t fetchdat)
static int
opIN_EAX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
check_io_perm(DX, 4);
EAX = inl(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 0, 1, 0, 0, 0);
@@ -123,7 +111,7 @@ opIN_EAX_DX(uint32_t fetchdat)
static int
opOUT_AL_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX, 1);
outb(DX, AL);
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 1, -1, 0, 0, 1, 0, 0);
@@ -134,8 +122,7 @@ opOUT_AL_DX(uint32_t fetchdat)
static int
opOUT_AX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX, 2);
outw(DX, AX);
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 1, -1, 0, 0, 1, 0, 0);
@@ -146,10 +133,7 @@ opOUT_AX_DX(uint32_t fetchdat)
static int
opOUT_EAX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
check_io_perm(DX, 4);
outl(DX, EAX);
PREFETCH_RUN(11, 1, -1, 0, 0, 0, 1, 0);
if (nmi && nmi_enable && nmi_mask)

View File

@@ -9,7 +9,7 @@
uint8_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX, 1); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \
high_page = 0; \
do_mmut_wb(es, DEST_REG, &addr64); \
@@ -48,8 +48,7 @@
uint16_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX, 2); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
high_page = 0; \
do_mmut_ww(es, DEST_REG, addr64a); \
@@ -88,10 +87,7 @@
uint32_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX + 2); \
check_io_perm(DX + 3); \
check_io_perm(DX, 4); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
high_page = 0; \
do_mmut_wl(es, DEST_REG, addr64a); \
@@ -132,7 +128,7 @@
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX); \
check_io_perm(DX, 1); \
outb(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG--; \
@@ -163,8 +159,7 @@
temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX, 2); \
outw(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 2; \
@@ -195,10 +190,7 @@
temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX + 2); \
check_io_perm(DX + 3); \
check_io_perm(DX, 4); \
outl(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 4; \

View File

@@ -7,7 +7,7 @@
uint8_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX, 1); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \
high_page = 0; \
do_mmut_wb(es, DEST_REG, &addr64); \
@@ -40,8 +40,7 @@
uint16_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX, 2); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
high_page = 0; \
do_mmut_ww(es, DEST_REG, addr64a); \
@@ -74,10 +73,7 @@
uint32_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX + 2); \
check_io_perm(DX + 3); \
check_io_perm(DX, 4); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
high_page = 0; \
do_mmut_wl(es, DEST_REG, addr64a); \
@@ -112,7 +108,7 @@
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX); \
check_io_perm(DX, 1); \
outb(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG--; \
@@ -137,8 +133,7 @@
temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX, 2); \
outw(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 2; \
@@ -163,10 +158,7 @@
temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX); \
check_io_perm(DX + 1); \
check_io_perm(DX + 2); \
check_io_perm(DX + 3); \
check_io_perm(DX, 4); \
outl(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 4; \

View File

@@ -804,7 +804,7 @@ opINSB_a16(uint32_t fetchdat)
addr64 = 0x00000000;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX, 1);
CHECK_WRITE(&cpu_state.seg_es, DI, DI);
high_page = 0;
do_mmut_wb(es, DI, &addr64);
@@ -830,7 +830,7 @@ opINSB_a32(uint32_t fetchdat)
addr64 = 0x00000000;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX, 1);
high_page = 0;
CHECK_WRITE(&cpu_state.seg_es, EDI, EDI);
do_mmut_wb(es, EDI, &addr64);
@@ -857,8 +857,7 @@ opINSW_a16(uint32_t fetchdat)
addr64a[0] = addr64a[1] = 0x00000000;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX, 2);
CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL);
high_page = 0;
do_mmut_ww(es, DI, addr64a);
@@ -885,8 +884,7 @@ opINSW_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(&cpu_state.seg_es);
high_page = 0;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX, 2);
CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL);
do_mmut_ww(es, EDI, addr64a);
if (cpu_state.abrt)
@@ -912,10 +910,7 @@ opINSL_a16(uint32_t fetchdat)
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
check_io_perm(DX, 4);
CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL);
high_page = 0;
do_mmut_wl(es, DI, addr64a);
@@ -941,10 +936,7 @@ opINSL_a32(uint32_t fetchdat)
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
check_io_perm(DX, 4);
CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL);
high_page = 0;
do_mmut_wl(es, DI, addr64a);
@@ -973,7 +965,7 @@ opOUTSB_a16(uint32_t fetchdat)
temp = readmemb(cpu_state.ea_seg->base, SI);
if (cpu_state.abrt)
return 1;
check_io_perm(DX);
check_io_perm(DX, 1);
if (cpu_state.flags & D_FLAG)
SI--;
else
@@ -993,7 +985,7 @@ opOUTSB_a32(uint32_t fetchdat)
temp = readmemb(cpu_state.ea_seg->base, ESI);
if (cpu_state.abrt)
return 1;
check_io_perm(DX);
check_io_perm(DX, 1);
if (cpu_state.flags & D_FLAG)
ESI--;
else
@@ -1014,8 +1006,7 @@ opOUTSW_a16(uint32_t fetchdat)
temp = readmemw(cpu_state.ea_seg->base, SI);
if (cpu_state.abrt)
return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX, 2);
if (cpu_state.flags & D_FLAG)
SI -= 2;
else
@@ -1035,8 +1026,7 @@ opOUTSW_a32(uint32_t fetchdat)
temp = readmemw(cpu_state.ea_seg->base, ESI);
if (cpu_state.abrt)
return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX, 2);
if (cpu_state.flags & D_FLAG)
ESI -= 2;
else
@@ -1057,10 +1047,7 @@ opOUTSL_a16(uint32_t fetchdat)
temp = readmeml(cpu_state.ea_seg->base, SI);
if (cpu_state.abrt)
return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
check_io_perm(DX, 4);
if (cpu_state.flags & D_FLAG)
SI -= 4;
else
@@ -1080,10 +1067,7 @@ opOUTSL_a32(uint32_t fetchdat)
temp = readmeml(cpu_state.ea_seg->base, ESI);
if (cpu_state.abrt)
return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
check_io_perm(DX, 4);
if (cpu_state.flags & D_FLAG)
ESI -= 4;
else

View File

@@ -64,25 +64,22 @@
#define MODE_MASK 0x6c
#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */
#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */
#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */
#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */
#define KBC_TYPE_PS2_1 0x01 /* PS2 on PS/2, type 1 */
#define KBC_TYPE_PS2_2 0x02 /* PS2 on PS/2, type 2 */
#define KBC_TYPE_GREEN 0x03 /* PS2 green controller */
#define KBC_TYPE_MASK 0x03
#define KBC_VEN_GENERIC 0x00
#define KBC_VEN_AMI 0x04
#define KBC_VEN_IBM_MCA 0x08
#define KBC_VEN_QUADTEL 0x0c
#define KBC_VEN_TOSHIBA 0x10
#define KBC_VEN_IBM_PS1 0x14
#define KBC_VEN_ACER 0x18
#define KBC_VEN_INTEL_AMI 0x1c
#define KBC_VEN_OLIVETTI 0x20
#define KBC_VEN_IBM_PS1 0x04
#define KBC_VEN_TOSHIBA 0x08
#define KBC_VEN_OLIVETTI 0x0c
#define KBC_VEN_AMI 0x10
#define KBC_VEN_TRIGEM_AMI 0x14
#define KBC_VEN_QUADTEL 0x18
#define KBC_VEN_PHOENIX 0x1c
#define KBC_VEN_ACER 0x20
#define KBC_VEN_NCR 0x24
#define KBC_VEN_PHOENIX 0x28
#define KBC_VEN_ALI 0x2c
#define KBC_VEN_TG 0x30
#define KBC_VEN_TG_GREEN 0x34
#define KBC_VEN_ALI 0x28
#define KBC_VEN_MASK 0x3c
#define FLAG_CLOCK 0x01
@@ -210,6 +207,7 @@ kbc_at_queue_add(atkbc_t *dev, uint8_t val)
static int
kbc_translate(atkbc_t *dev, uint8_t val)
{
/* TODO: Does the IBM AT keyboard controller firmware apply translation in XT mode or not? */
int xt_mode = (dev->mem[0x20] & 0x20) && !(dev->misc_flags & FLAG_PS2);
int translate = (dev->mem[0x20] & 0x40) || xt_mode || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2);
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
@@ -308,8 +306,8 @@ add_to_kbc_queue_front(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_
if (temp == -1)
return;
if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) ||
(kbc_ven == KBC_VEN_TG_GREEN) || (dev->misc_flags & FLAG_PS2))
if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TRIGEM_AMI) ||
(dev->misc_flags & FLAG_PS2))
stat_hi |= ((dev->p1 & 0x80) ? 0x10 : 0x00);
else
stat_hi |= 0x10;
@@ -675,7 +673,7 @@ write_p2(atkbc_t *dev, uint8_t val)
coreboot machines. */
pc_reset_hard();
} else {
softresetx86(); /*Pulse reset!*/
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
if (kbc_ven == KBC_VEN_ALI)
@@ -797,14 +795,80 @@ write64_generic(void *priv, uint8_t val)
add_to_kbc_queue_front(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";
Comapq: 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_INTEL_AMI)
if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN))
fixed_bits |= 0x40;
if (kbc_ven == KBC_VEN_IBM_PS1) {
current_drive = fdc_get_current_drive();
/* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */
add_to_kbc_queue_front(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00),
0, 0x00);
} else if (kbc_ven == KBC_VEN_NCR) {
@@ -818,9 +882,10 @@ write64_generic(void *priv, uint8_t val)
* bit 1: high/auto speed
* bit 0: dma mode
*/
/* (B0 or F0) | 0x04 | (display on bit 6) | (fpu on bit 3) */
add_to_kbc_queue_front(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf,
0, 0x00);
} else if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN)) {
} else if (kbc_ven == KBC_VEN_TRIGEM_AMI) {
/* Bit 3, 2:
1, 1: TriGem logo;
1, 0: Garbled logo;
@@ -828,14 +893,35 @@ write64_generic(void *priv, uint8_t val)
0, 0: Generic AMI logo. */
if (dev->misc_flags & FLAG_PCI)
fixed_bits |= 8;
/* (B0 or F0) | (0x04 or 0x0c) */
add_to_kbc_queue_front(dev, dev->p1 | fixed_bits, 0, 0x00);
} else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI))
} 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) */
add_to_kbc_queue_front(dev, ((dev->p1 | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00);
else
/* (B0 or F0) | (0x04 or 0x44) */
add_to_kbc_queue_front(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");
@@ -903,10 +989,13 @@ write60_ami(void *priv, uint8_t val)
dev->ami_flags = val;
dev->misc_flags &= ~FLAG_PS2;
if (val & 0x01) {
kbc_at_log("ATkbc: AMI: Emulate PS/2 keyboard\n");
dev->misc_flags |= FLAG_PS2;
kbc_at_do_poll = kbc_at_poll_ps2;
} else
} else {
kbc_at_log("ATkbc: AMI: Emulate AT keyboard\n");
kbc_at_do_poll = kbc_at_poll_at;
}
return 0;
}
@@ -935,7 +1024,7 @@ write64_ami(void *priv, uint8_t val)
kbc_at_queue_add(dev, 0x28);
kbc_at_queue_add(dev, 0x00);
dev->state = STATE_KBC_OUT;
break;
return 0;
case 0xa1: /* get controller version */
kbc_at_log("ATkbc: AMI - get controller version\n");
@@ -1029,6 +1118,7 @@ write64_ami(void *priv, uint8_t val)
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
/* TODO: The ICS SB486PV sends command B4 but expects to read *TWO* bytes. */
case 0xb4: case 0xb5:
/* set KBC lines P22-P23 (P2 bits 2-3) low */
kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n");
@@ -1112,37 +1202,6 @@ write64_ami(void *priv, uint8_t val)
return write64_generic(dev, val);
}
static uint8_t
write64_ibm_mca(void *priv, uint8_t val)
{
atkbc_t *dev = (atkbc_t *) priv;
switch (val) {
case 0xc1: /*Copy bits 0 to 3 of P1 to status bits 4 to 7*/
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 & 0xfc) | 0x84) & 0x0f) << 4);
return 0;
case 0xc2: /*Copy bits 4 to 7 of P1 to status bits 4 to 7*/
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 & 0xfc) | 0x84) & 0xf0);
return 0;
case 0xaf:
kbc_at_log("ATkbc: bad KBC command AF\n");
return 1;
case 0xf0 ... 0xff:
kbc_at_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c);
pulse_output(dev, (val & 0x03) | 0x0c);
return 0;
}
return write64_generic(dev, val);
}
static uint8_t
write60_quadtel(void *priv, uint8_t val)
{
@@ -1260,15 +1319,17 @@ write64_toshiba(void *priv, uint8_t val)
dev->state = STATE_KBC_PARAM;
return 0;
/* TODO: Toshiba KBC mode switching. */
case 0xb7: /* T3100e: Emulate PS/2 keyboard */
case 0xb8: /* T3100e: Emulate AT keyboard */
dev->flags &= ~KBC_TYPE_MASK;
dev->misc_flags &= ~FLAG_PS2;
if (val == 0xb7) {
kbc_at_log("ATkbc: T3100e: Emulate PS/2 keyboard\n");
dev->flags |= KBC_TYPE_PS2_NOREF;
dev->misc_flags |= FLAG_PS2;
kbc_at_do_poll = kbc_at_poll_ps2;
} else {
kbc_at_log("ATkbc: T3100e: Emulate AT keyboard\n");
dev->flags |= KBC_TYPE_ISA;
kbc_at_do_poll = kbc_at_poll_at;
}
return 0;
@@ -1333,7 +1394,7 @@ kbc_at_process_cmd(void *priv)
case 0xaa: /* self-test */
kbc_at_log("ATkbc: self-test\n");
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
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. */
@@ -1531,7 +1592,7 @@ kbc_at_process_cmd(void *priv)
if (dev->ib == 0xbb)
break;
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if (dev->misc_flags & FLAG_PS2) {
set_enable_aux(dev, 1);
if ((dev->ports[1] != NULL) && (dev->ports[1]->priv != NULL)) {
dev->ports[1]->wantcmd = 1;
@@ -1614,7 +1675,7 @@ kbc_at_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_NOREF)
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)
cycles -= ISA_CYCLES(8);
switch (port) {
@@ -1667,10 +1728,10 @@ kbc_at_reset(void *priv)
dev->sc_or = 0;
dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00;
dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 0x01 : 0x00;
dev->misc_flags = 0x00;
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) {
dev->misc_flags |= FLAG_PS2;
kbc_at_do_poll = kbc_at_poll_ps2;
} else
@@ -1679,7 +1740,7 @@ kbc_at_reset(void *priv)
dev->misc_flags |= FLAG_CACHE;
dev->p2 = 0xcd;
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) {
write_p2(dev, 0x4b);
} else {
/* The real thing writes CF and then AND's it with BF. */
@@ -1694,7 +1755,7 @@ static void
kbc_at_close(void *priv)
{
atkbc_t *dev = (atkbc_t *) priv;
int i, max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 2 : 1;
int i, max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1;
kbc_at_reset(dev);
@@ -1752,12 +1813,6 @@ kbc_at_init(const device_t *info)
dev->write64_ven = write64_olivetti;
break;
case KBC_VEN_INTEL_AMI:
kbc_ami_revision = '5';
dev->write60_ven = write60_ami;
dev->write64_ven = write64_ami;
break;
case KBC_VEN_ALI:
kbc_ami_revision = 'F';
kbc_award_revision = 0x43;
@@ -1765,15 +1820,16 @@ kbc_at_init(const device_t *info)
dev->write64_ven = write64_ami;
break;
case KBC_VEN_TG:
case KBC_VEN_TG_GREEN:
case KBC_VEN_TRIGEM_AMI:
kbc_ami_revision = 'Z';
dev->write60_ven = write60_ami;
dev->write64_ven = write64_ami;
break;
case KBC_VEN_AMI:
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN)
kbc_ami_revision = '5';
else if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) {
if (cpu_64bitbus)
kbc_ami_revision = 'R';
else if (is486)
@@ -1794,10 +1850,6 @@ kbc_at_init(const device_t *info)
dev->write64_ven = write64_ami;
break;
case KBC_VEN_IBM_MCA:
dev->write64_ven = write64_ibm_mca;
break;
case KBC_VEN_QUADTEL:
dev->write60_ven = write60_quadtel;
dev->write64_ven = write64_quadtel;
@@ -1809,7 +1861,7 @@ kbc_at_init(const device_t *info)
break;
}
max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 2 : 1;
max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1;
for (i = 0; i < max_ports; i++) {
kbc_at_ports[i] = (kbc_at_port_t *) malloc(sizeof(kbc_at_port_t));
@@ -1858,7 +1910,7 @@ const device_t keyboard_at_tg_ami_device = {
.name = "PC/AT Keyboard (TriGem AMI)",
.internal_name = "keyboard_at_tg_ami",
.flags = DEVICE_KBC,
.local = KBC_TYPE_ISA | KBC_VEN_TG,
.local = KBC_TYPE_ISA | KBC_VEN_TRIGEM_AMI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -1914,7 +1966,7 @@ const device_t keyboard_ps2_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC,
.local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -1928,7 +1980,7 @@ const device_t keyboard_ps2_ps1_device = {
.name = "PS/2 Keyboard (IBM PS/1)",
.internal_name = "keyboard_ps2_ps1",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1,
.local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -1942,7 +1994,7 @@ const device_t keyboard_ps2_ps1_pci_device = {
.name = "PS/2 Keyboard (IBM PS/1)",
.internal_name = "keyboard_ps2_ps1_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1,
.local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -1970,7 +2022,7 @@ const device_t keyboard_ps2_ami_device = {
.name = "PS/2 Keyboard (AMI)",
.internal_name = "keyboard_ps2_ami",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI,
.local = KBC_TYPE_PS2_1 | KBC_VEN_AMI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -1984,21 +2036,7 @@ const device_t keyboard_ps2_tg_ami_device = {
.name = "PS/2 Keyboard (TriGem AMI)",
.internal_name = "keyboard_ps2_tg_ami",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG,
.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_mca_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_mca",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA,
.local = KBC_TYPE_PS2_1 | KBC_VEN_TRIGEM_AMI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2012,7 +2050,7 @@ const device_t keyboard_ps2_mca_2_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_mca_2",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA,
.local = KBC_TYPE_PS2_2 | KBC_VEN_GENERIC,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2026,7 +2064,7 @@ const device_t keyboard_ps2_quadtel_device = {
.name = "PS/2 Keyboard (Quadtel/MegaPC)",
.internal_name = "keyboard_ps2_quadtel",
.flags = DEVICE_KBC,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL,
.local = KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2040,7 +2078,7 @@ const device_t keyboard_ps2_pci_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC,
.local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2054,7 +2092,7 @@ const device_t keyboard_ps2_ami_pci_device = {
.name = "PS/2 Keyboard (AMI)",
.internal_name = "keyboard_ps2_ami_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI,
.local = KBC_TYPE_PS2_1 | KBC_VEN_AMI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2068,7 +2106,7 @@ const device_t keyboard_ps2_ali_pci_device = {
.name = "PS/2 Keyboard (ALi M5123/M1543C)",
.internal_name = "keyboard_ps2_ali_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_ALI,
.local = KBC_TYPE_PS2_1 | KBC_VEN_ALI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2082,7 +2120,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = {
.name = "PS/2 Keyboard (AMI)",
.internal_name = "keyboard_ps2_intel_ami_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI,
.local = KBC_TYPE_GREEN | KBC_VEN_AMI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2096,7 +2134,7 @@ const device_t keyboard_ps2_tg_ami_pci_device = {
.name = "PS/2 Keyboard (TriGem AMI)",
.internal_name = "keyboard_ps2_tg_ami_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG,
.local = KBC_TYPE_PS2_1 | KBC_VEN_TRIGEM_AMI,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
@@ -2110,7 +2148,7 @@ const device_t keyboard_ps2_acer_pci_device = {
.name = "PS/2 Keyboard (Acer 90M002A)",
.internal_name = "keyboard_ps2_acer_pci",
.flags = DEVICE_KBC | DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_ACER,
.local = KBC_TYPE_PS2_1 | KBC_VEN_ACER,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,

View File

@@ -119,7 +119,7 @@ kbc_at_dev_poll(void *priv)
case DEV_STATE_MAIN_2:
/* Output from scan queue if needed and then return to main loop #1. */
if (*dev->scan && (dev->port->out_new == -1) && (dev->queue_start != dev->queue_end)) {
kbc_at_dev_log("%s %1: %02X (DATA) on channel 1\n", dev->name, dev->inst, dev->queue[dev->queue_start]);
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];
dev->queue_start = (dev->queue_start + 1) & 0xf;
}
@@ -173,9 +173,9 @@ kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa)
if (do_fa)
kbc_at_dev_queue_add(dev, 0xfa, 0);
dev->execute_bat(dev);
dev->state = DEV_STATE_MAIN_OUT;
dev->execute_bat(dev);
}
atkbc_dev_t *

View File

@@ -788,10 +788,9 @@ keyboard_at_write(void *priv)
dev->state = DEV_STATE_MAIN_WANT_IN;
}
dev->command = val;
switch (dev->command) {
switch (val) {
case 0xed: /* set/reset LEDs */
dev->command = val;
keyboard_at_log("%s: set/reset LEDs\n", dev->name);
dev->flags |= FLAG_CTRLDAT;
kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
@@ -811,6 +810,7 @@ keyboard_at_write(void *priv)
case 0xf0: /* get/set scan code set */
if (dev->type & FLAG_PS2) {
dev->command = val;
keyboard_at_log("%s: scan code set\n", dev->name);
dev->flags |= FLAG_CTRLDAT;
kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
@@ -833,6 +833,7 @@ keyboard_at_write(void *priv)
break;
case 0xf3: /* set command mode */
dev->command = val;
keyboard_at_log("%s: set typematic rate/delay\n", dev->name);
dev->flags |= FLAG_CTRLDAT;
kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */

View File

@@ -102,6 +102,8 @@ static int mouse_nbut;
static int (*mouse_dev_poll)(int x, int y, int z, int b, void *priv);
static void (*mouse_poll_ex)(void) = NULL;
static double sample_rate = 200.0;
#ifdef ENABLE_MOUSE_LOG
int mouse_do_log = ENABLE_MOUSE_LOG;
@@ -153,7 +155,7 @@ static void
mouse_timer_poll(void *priv)
{
/* Poll at 255 Hz, maximum supported by PS/2 mic. */
timer_on_auto(&mouse_timer, 1000000.0 / 255.0);
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
if (gdbstub_step == GDBSTUB_EXEC)
@@ -161,6 +163,15 @@ mouse_timer_poll(void *priv)
mouse_process();
}
void
mouse_set_sample_rate(double new_rate)
{
timer_stop(&mouse_timer);
sample_rate = new_rate;
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
}
void
mouse_reset(void)
{
@@ -179,15 +190,16 @@ mouse_reset(void)
if (mouse_type == 0)
return;
timer_add(&mouse_timer, mouse_timer_poll, NULL, 0);
/* Poll at 100 Hz, the default of a PS/2 mouse. */
sample_rate = 100.0;
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
mouse_curr = mouse_devices[mouse_type].device;
if (mouse_curr != NULL)
mouse_priv = device_add(mouse_curr);
timer_add(&mouse_timer, mouse_timer_poll, NULL, 0);
/* Poll at 255 Hz, maximum supported by PS/2 mic. */
timer_on_auto(&mouse_timer, 1000000.0 / 255.0);
}
/* Callback from the hardware driver. */

View File

@@ -133,8 +133,11 @@ static void
ps2_set_defaults(atkbc_dev_t *dev)
{
dev->mode = MODE_STREAM;
dev->rate = 1;
dev->rate = 100;
mouse_set_sample_rate(100.0);
dev->resolution = 2;
dev->flags &= 0x88;
mouse_scan = 0;
}
static void
@@ -144,8 +147,6 @@ ps2_bat(void *priv)
ps2_set_defaults(dev);
mouse_scan = 1;
kbc_at_dev_queue_add(dev, 0xaa, 0);
kbc_at_dev_queue_add(dev, 0x00, 0);
}
@@ -178,6 +179,7 @@ ps2_write(void *priv)
case 0xf3: /* set sample rate */
dev->rate = val;
mouse_set_sample_rate((double) val);
kbc_at_dev_queue_add(dev, 0xfa, 0); /* Command response */
mouse_ps2_log("%s: Set sample rate [%02X]\n", dev->name, val);
break;
@@ -228,6 +230,7 @@ ps2_write(void *priv)
case 0xea: /* set stream */
mouse_ps2_log("%s: Set stream\n", dev->name);
dev->flags &= ~FLAG_CTRLDAT;
dev->mode = MODE_STREAM;
mouse_scan = 1;
kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
break;
@@ -239,6 +242,14 @@ ps2_write(void *priv)
ps2_report_coordinates(dev, 0);
break;
case 0xf0: /* set remote */
mouse_ps2_log("%s: Set remote\n", dev->name);
dev->flags &= ~FLAG_CTRLDAT;
dev->mode = MODE_REMOTE;
mouse_scan = 1;
kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
break;
case 0xf2: /* read ID */
mouse_ps2_log("%s: Read ID\n", dev->name);
kbc_at_dev_queue_add(dev, 0xfa, 0);

View File

@@ -55,6 +55,14 @@
#define BCD16(x) ((((x) / 1000) << 12) | (((x) / 100) << 8) | BCD8(x))
#define BCD32(x) ((((x) / 10000000) << 28) | (((x) / 1000000) << 24) | (((x) / 100000) << 20) | (((x) / 10000) << 16) | BCD16(x))
#if defined(__GNUC__) || defined(__clang__)
# define UNLIKELY(x) __builtin_expect((x), 0)
# define LIKELY(x) __builtin_expect((x), 1)
#else
# define UNLIKELY(x) (x)
# define LIKELY(x) (x)
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -225,7 +225,6 @@ extern const device_t keyboard_ps2_ami_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_mca_device;
extern const device_t keyboard_ps2_mca_2_device;
extern const device_t keyboard_ps2_quadtel_device;
extern const device_t keyboard_ps2_pci_device;

View File

@@ -80,6 +80,8 @@ extern void mouse_poll(void);
extern void mouse_bus_set_irq(void *priv, int irq);
extern void mouse_set_sample_rate(double new_rate);
extern char *mouse_get_name(int mouse);
extern char *mouse_get_internal_name(int mouse);
extern int mouse_get_from_internal_name(char *s);

View File

@@ -998,7 +998,7 @@ ps2_mca_board_model_55sx_init(int has_sec_nvram, int slots)
}
mca_init(slots);
device_add(&keyboard_ps2_mca_device);
device_add(&keyboard_ps2_device);
if (has_sec_nvram == 1)
device_add(&ps2_nvr_55ls_device);
@@ -1162,7 +1162,7 @@ ps2_mca_board_model_70_type34_init(int is_type4, int slots)
ps2.split_addr = mem_size * 1024;
mca_init(slots);
device_add(&keyboard_ps2_mca_device);
device_add(&keyboard_ps2_device);
ps2.planar_read = model_70_type3_read;
ps2.planar_write = model_70_type3_write;
@@ -1255,7 +1255,7 @@ ps2_mca_board_model_80_type2_init(int is486)
ps2.split_addr = mem_size * 1024;
mca_init(8);
device_add(&keyboard_ps2_mca_device);
device_add(&keyboard_ps2_device);
ps2.planar_read = model_80_read;
ps2.planar_write = model_80_write;

View File

@@ -2898,7 +2898,7 @@ mem_remap_top(int kb)
if (addr >= 0x000c0000)
addr += 0x00010000;
}
if (start_addr != 0)
if (start_addr == 0)
start_addr = addr;
pages[c].mem = set ? &ram[addr] : page_ff;
pages[c].write_b = set ? mem_write_ramb_page : NULL;

View File

@@ -202,7 +202,7 @@ find_best_interrupt(pic_t *dev)
intr = dev->interrupt = (ret == -1) ? 0x17 : ret;
if (dev->at && (ret != 1)) {
if (dev->at && (ret != -1)) {
if (dev == &pic2)
intr += 8;
@@ -644,7 +644,7 @@ picint_common(uint16_t num, int level, int set)
pic2.lines |= (num >> 8);
/* Latch IRQ 12 if the mouse latch is enabled. */
if (mouse_latch && (num & 0x1000))
if ((num & 0x1000) && mouse_latch)
pic2.lines |= 0x10;
pic2.irr |= (num >> 8);

View File

@@ -69,11 +69,18 @@ port_92_readw(uint16_t port, void *priv)
return ret;
}
/*
This does the exact same thing as keyboard controller reset.
TODO: ALi M1543(c) behavior.
*/
static void
port_92_pulse(void *priv)
{
resetx86();
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
cpu_alt_reset = 1;
}
static void
@@ -166,6 +173,15 @@ port_92_remove(void *priv)
port_92_readb, NULL, NULL, port_92_writeb, NULL, NULL, dev);
}
static void
port_92_reset(void *priv)
{
cpu_alt_reset = 0;
mem_a20_alt = 0x00;
mem_a20_recalc();
}
static void
port_92_close(void *priv)
{
@@ -252,7 +268,7 @@ const device_t port_92_pci_device = {
.local = PORT_92_PCI,
.init = port_92_init,
.close = port_92_close,
.reset = NULL,
.reset = port_92_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,

View File

@@ -305,7 +305,7 @@ msgid "&Default"
msgstr "&За замовчуванням"
msgid "Language:"
msgstr "Язык:"
msgstr "Мова:"
msgid "Icon set:"
msgstr "Набір іконок:"
@@ -446,7 +446,7 @@ msgid "PCap device:"
msgstr "Пристрій PCap:"
msgid "Network adapter:"
msgstr "Мережева карта:"
msgstr "Мережевий адаптер:"
msgid "COM1 Device:"
msgstr "Пристрій COM1:"

View File

@@ -24,11 +24,16 @@ D3D9Renderer::D3D9Renderer(QWidget *parent, int monitor_index)
windowHandle = (HWND) winId();
surfaceInUse = true;
finalized = true;
RendererCommon::parentWidget = parent;
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->m_monitor_index = monitor_index;
d3d9surface = nullptr;
d3d9dev = nullptr;
d3d9 = nullptr;
}
D3D9Renderer::~D3D9Renderer()
@@ -67,6 +72,7 @@ D3D9Renderer::hideEvent(QHideEvent *event)
void
D3D9Renderer::showEvent(QShowEvent *event)
{
if (d3d9) finalize();
params = {};
if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9))) {
@@ -80,7 +86,7 @@ D3D9Renderer::showEvent(QShowEvent *event)
params.BackBufferCount = 1;
params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
params.hDeviceWindow = windowHandle;
params.hDeviceWindow = (HWND) winId();
HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING, &params, nullptr, &d3d9dev);
if (FAILED(result))
@@ -118,10 +124,10 @@ D3D9Renderer::paintEvent(QPaintEvent *event)
srcRect.bottom = source.bottom();
srcRect.left = source.left();
srcRect.right = source.right();
dstRect.top = destination.top();
dstRect.bottom = destination.bottom();
dstRect.left = destination.left();
dstRect.right = destination.right();
dstRect.top = destination.top() * devicePixelRatioF();
dstRect.bottom = destination.bottom() * devicePixelRatioF();
dstRect.left = destination.left() * devicePixelRatioF();
dstRect.right = destination.right() * devicePixelRatioF();
d3d9dev->BeginScene();
d3d9dev->Clear(0, nullptr, D3DCLEAR_TARGET, 0xFF000000, 0, 0);
while (surfaceInUse) { }

View File

@@ -174,6 +174,7 @@ ali5123_reset(ali5123_t *dev)
serial_setup(dev->uart[1], 0x03e8, dev->ld_regs[5][0x70]);
/* Logical device 7: Keyboard */
dev->ld_regs[7][0x30] = 1;
dev->ld_regs[7][0x70] = 1;
/* TODO: Register F0 bit 6: 0 = PS/2, 1 = AT */
@@ -253,6 +254,9 @@ ali5123_write(uint16_t port, uint8_t val, void *priv)
case 0x06:
case 0x08 ... 0x0a:
return;
case 0x07:
if (dev->cur_reg == 0xf0)
val &= 0xbf;
}
dev->ld_regs[cur_ld][dev->cur_reg] = val;
}

View File

@@ -250,7 +250,7 @@ END
#define STR_CANCEL "Відміна"
#define STR_GLOBAL "Зберегти ці параметри як &глобальні за замовчуванням"
#define STR_DEFAULT "&За замовчуванням"
#define STR_LANGUAGE "Язык:"
#define STR_LANGUAGE "Мова:"
#define STR_ICONSET "Набір іконок:"
#define STR_GAIN "Посилення"
@@ -306,11 +306,11 @@ END
#define STR_NET_TYPE "Тип мережі:"
#define STR_PCAP "Пристрій PCap:"
#define STR_NET "Мережева карта:"
#define STR_NET1 "Network card 1:"
#define STR_NET2 "Network card 2:"
#define STR_NET3 "Network card 3:"
#define STR_NET4 "Network card 4:"
#define STR_NET "Мережевий адаптер:"
#define STR_NET1 "Мережева карта 1:"
#define STR_NET2 "Мережева карта 2:"
#define STR_NET3 "Мережева карта 3:"
#define STR_NET4 "Мережева карта 4:"
#define STR_COM1 "Пристрій COM1:"
#define STR_COM2 "Пристрій COM2:"
@@ -404,11 +404,11 @@ BEGIN
IDS_2055 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0"
IDS_2056 "86Box не зміг знайти жодного відповідного для використання файлу з ПЗУ.\n\nБудь ласка <a href=""https://github.com/86Box/roms/releases/latest"">завантажте</a> набір ПЗУ і витягніть його в каталог ""roms""."
IDS_2057 "(порожньо)"
IDS_2058 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Всі файли (*.*)\0*.*\0"
IDS_2058 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Усі файли (*.*)\0*.*\0"
IDS_2059 "Турбо"
IDS_2060 "Увімк"
IDS_2061 "Вимк"
IDS_2062 "Всі образи (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Прості посекторні образи (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Образ поверхні (*.86F)\0*.86F\0"
IDS_2062 "Усі образи (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Прості посекторні образи (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Образ поверхні (*.86F)\0*.86F\0"
IDS_2063 "Системна плата ""%hs"" недоступна через відсутність файлу її ПЗУ в каталозі roms/machines. Переключення на доступну системну плату."
END
@@ -464,14 +464,14 @@ BEGIN
IDS_2107 "%u"
IDS_2108 "%u МБ (CHS: %i, %i, %i)"
IDS_2109 "Дисковод %i (%s): %ls"
IDS_2110 "Всі образи (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Розширені образи секторів (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Основні образи секторів (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образи Flux (*.FDI)\0*.FDI\0Образи Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Всі файли (*.*)\0*.*\0"
IDS_2110 "Усі образи (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Розширені образи секторів (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Основні образи секторів (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образи Flux (*.FDI)\0*.FDI\0Образи Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Усі файли (*.*)\0*.*\0"
IDS_2111 "Неможливо ініціалізувати FreeType"
IDS_2112 "Неможливо ініціалізувати SDL, потрібно SDL2.dll"
IDS_2113 "Ви впевнені, що хочете виконати холодне перезавантаження емульованої машини?"
IDS_2114 "Ви впевнені, що хочете вийти з 86Box?"
IDS_2115 "Неможливо ініціалізувати Ghostscript"
IDS_2116 "Магнітооптичний %i (%ls): %ls"
IDS_2117 "Образи магнітооптичних дисків (*.IM?;*.MDI)\0*.IM?;*.MDI\0Все файлы (*.*)\0*.*\0"
IDS_2117 "Образи магнітооптичних дисків (*.IM?;*.MDI)\0*.IM?;*.MDI\0Усі файлі (*.*)\0*.*\0"
IDS_2118 "Ласкаво просимо в 86Box!"
IDS_2119 "Вбудований контролер"
IDS_2120 "Вихід"
@@ -503,7 +503,7 @@ BEGIN
#else
#define LIB_NAME_GS "libgs"
#endif
IDS_2133 LIB_NAME_GS " потрібно для автоматичного перетворення файлів PostScript в PDF.\n\nВсі документи, відправлені на загальний принтер PostScript, будуть збережені у вигляді файлів PostScript (.ps)."
IDS_2133 LIB_NAME_GS " потрібно для автоматичного перетворення файлів PostScript в PDF.\n\nсі документи, відправлені на загальний принтер PostScript, будуть збережені у вигляді файлів PostScript (.ps)."
#ifdef _WIN32
#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll"
#else
@@ -527,7 +527,7 @@ BEGIN
IDS_2149 "Касета: %s"
IDS_2150 "Образи касет (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Усі файли (*.*)\0*. *\0"
IDS_2151 "Картридж %i: %ls"
IDS_2152 "Образи картриджів (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Всі файли (*.*)\0*.*\0"
IDS_2152 "Образи картриджів (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Усі файли (*.*)\0*.*\0"
IDS_2153 "Помилка ініціалізації рендерера"
IDS_2154 "Неможливо ініціалізувати рендерер OpenGL (3.0). Будь ласка, використовуйте інший рендерер."
IDS_2155 "Відновити виконання"
@@ -541,7 +541,7 @@ BEGIN
IDS_2163 "No Dynarec"
IDS_2164 "Old Dynarec"
IDS_2165 "New Dynarec"
IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card."
IDS_2166 "Відеокарта #2 ""%hs"" недоступна через відсутність файлу її ПЗУ в каталозі roms/video. Відключення другої відеокарти."
END
STRINGTABLE DISCARDABLE
@@ -556,7 +556,7 @@ BEGIN
IDS_4103 "Вибрати існуючий жорсткий диск"
IDS_4104 "Розмір образів дисків HDI не може перевищувати 4 ГБ."
IDS_4105 "Розмір образів дисків не може перевищувати 127 ГБ."
IDS_4106 "Образи жорстких дисків (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Всі файли (*.*)\0*.*\0 "
IDS_4106 "Образи жорстких дисків (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Усі файли (*.*)\0*.*\0 "
IDS_4107 "Неможливо прочитати файл"
IDS_4108 "Неможливо записати файл"
IDS_4109 "Образи HDI або HDX з розміром сектора, відмінним від 512, не підтримуються."
@@ -580,7 +580,7 @@ BEGIN
IDS_4127 "Диференційований образ VHD (.vhd)"
IDS_4128 "Великі блоки (2 МБ)"
IDS_4129 "Маленькі блоки (512 КБ)"
IDS_4130 "Файли VHD (*.VHD)\0*.VHD\0Всі файли (*.*)\0*.*\0"
IDS_4130 "Файли VHD (*.VHD)\0*.VHD\0Усі файли (*.*)\0*.*\0"
IDS_4131 "Виберіть батьківський VHD"
IDS_4132 "Це може означати, що батьківський образ був змінений після того, як було створено диференційований образ.\n\nЦе також може статися, якщо файли зображення були переміщені або скопійовані, або через помилку в програмі, що створила цей диск.\n \nВи хочете виправити тимчасові позначки?"
IDS_4133 "Тимчасові мітки батьківського та дочірнього дисків не співпадають"